linux 协议栈分析 ip数据包处理

前提

 

http://lxr.linux.no/#linux+v2.6.35.7/net/ipv4/protocol.c

 

inet_protos 是一个协议处理接口的数组,包含了可以处理的ip协议如udp,tcp等

 

inet_add_protocol  inet_del_protocol 是提供注册删除协议的两个接口

 

http://lxr.linux.no/#linux+v2.6.35.7/net/ipv4/af_inet.c


在 inet_init 注册各种协议处理接口

 

接收部分

 

http://lxr.linux.no/#linux+v2.6.35.7/net/ipv4/ip_input.c

 

属于本地数据包的处理流程

ip_local_deliver() --> ip_local_deliver_finish()

这是3,4层协议的处理接口,在这里根据ip包的协议类型找到对应的协议处理接口如tcp,udp等等

 

int protocol = ip_hdr(skb)->protocol; //获取ip负载的协议

hash = protocol & (MAX_INET_PROTOS - 1); //换算hash值

ipprot = rcu_dereference(inet_protos[hash]); //查找对应的协议处理接口
if (ipprot != NULL) {
...... //如果接口不为空则处理该协议
}

inet_protos是一个协议注册的数组,里面包含了协议的处理接口,具体协议枚举类型查看

 

http://lxr.linux.no/#linux+v2.6.35.7/include/linux/in.h

 

 

发送部分

 

Linux内核中有3种基本的IP包生成器, 它们分别为

ip_build_xmit()

ip_queue_xmit()
ip_build_and_send_pkt()

 

ip_build_and_send_pkt()是一简单的IP包头封装接口,它接照输入包的路由添加一个IP包头后直接输出,不进行分片处理, 用于tcp_v4_send_synack()中.ip_send_reply()是基于ip_build_xmit()的一个函数,用于tcp_v4_send_ack()和tcp_v4_send_reset()中.

 

ip_build_xmit()使用用户定义的回调函数直接读取用户数据片段生成IP包输出.如果需要分片,ip_build_xmit()按照最后一个片段到第一个片段的顺序来生成IP包,这是因为第一个IP包片段的数据区可能包含对整个IP包数据区的校验码,在回调函数中用户可能会计算输出数据的校验码,采用从后向前的输出顺序可使校验码自然地写到第一个片段中.

 

ip_queue_xmit()完成面向连接套接字输出包的路由和IP包头封装. 当套接字处于连接状态时,所有从套接字发出的包都具有确定的路由, 无需为每一个输出包查询它的目的入口,可将套接字直接绑定到路由入口上, 这由套接字的目的缓冲指针(dst_cache)来完成.ip_queue_xmit()首先为输入包建立IP包头, 经过本地包过滤器后,再将IP包分片输出(ip_fragment), 如果需要的话.

 

IP包生成器的输出经过本地包过滤器后输入包的路由入口, 对于点播地址来说,输入到IP输出器中(ip_output); 对于广播或同播地址来说, 输入到IP同播输出器(ip_mc_output).


在IP输出器中, 再经过路由后过滤器,进入路由的"邻居"入口(dst->neighbour->output)或硬件帧头缓冲入口(dst->hh->hh_output).
邻居是指与主机自已在网络 接口设备 层次上直达的相邻主机.邻居负责解析输出包的硬件投送地址, 将包投递给相邻的目的主机或网关主机.
当邻居成功解析包的硬件投送地址时, 将在包的目的入口上创建硬件帧头缓冲结构(dst->hh),使得后继包可以直接使用组装好的帧头, 直接将包传递给包调度器(dev_queue_xmit).包调度器按照包的优先级进行重排, 最后将包提交给设备驱动 程序 发送(dev->hard_start_xmit).

 

你可能感兴趣的:(linux,tcp,Build,DST,output,linux内核)