网络子系统大杂烩三

之前分析的是网桥对输入帧的处理。

若系统未配置成网桥,则在__netif_receive_skb帧处理函数中

会继续执行后续代码,将帧提交给上层协议处理。

上层协议的处理函数在系统初始化的时候已经注册到packet_base函数指针数组中了

例如

802.2帧 对应的是llc_packet_type,其处理函数为llc_rcv

系统在初始化的时候通过/net/llc/llc_core.c 中的llc_init注册。

802.3帧对应的是ipx_8023_packet_type,其处理函数为ipx_rcv

系统在初始化的时候通过/net/ipx/af_ipx.c中的ipx_init函数注册到系统

ethernet帧直接根据skb->protocola中存放的协议号来寻找,例如

ETH_P_IP对应的是ip_packet_type,其处理函数是ip_rcv。

系统在初始化的时候通过/net/ipv4/af_inet.c中函数inet_init注册进系统


所以入口队列帧的处理需要根据eth_type_trans的结果来检测。

若是ethernet真则直接根据skb->protocol指明的L3层协议,交由其处理函数处理。

若是802.2则交由llc_rcv

若是802.3则交由ipx_rcv

其中若是ethernet帧,且其L3曾协议指定的是IP,则交由ip_rcv函数处理。


数据包到L3层之后在L3进行处理,L3通过skb->dst->input函数对包进行处理

转发则在input函数中通过ip_forward进行转发,若是本地则通过ip_local_deliver进行后续处理

input函数在很多地方都有可能被初始化

例如

在__mkroute_input函数中被初始化为

    rth->dst.input = ip_forward;
    rth->dst.output = ip_output;

同样被初始化的还有ip_output函数

在ip_route_input_slow函数中

    rth->rt_spec_dst= spec_dst;
    rth->dst.input= ip_local_deliver;


若被初始化为ip_forward则工作在路由层

若被初始化为ip_local_deliver则会继续向上层传送包。


发送的情况比较复杂 若是路由层则通过ip_forward->ip_output ... ...->hard_start_xmit发送

若是从L4层传下来的包则是通过skb->dst.output进行发送,这里outpur方法就是ip_mc_output函数

output方法的初始化比较复杂。

L4层通过函数ip_queue_xmit发送数据包,发送之前首先初始化好L3的output方法,然后调用output方法

发送到下一层。

具体函数调用异常复杂 大致如下:

ip_queue_xmit函数首先初始化output方法:
ip_queue_xmit->ip_route_output_flow->__ip_route_output_key->ip_route_output_slow

->ip_mkroute_output->__mkroute_outpu rth

然后在__mkroute_outpu rth中会将dst.output方法初始化

dst.output = ip_mc_output;

然后在ip_queue_xmit函数中调用ip_local_out函数发送到下一层

ip_queue_xmit->ip_local_out->dst_output

在函数dst_output函数中通过skb_dst(skb)->output(skb);调用之前初始化好的output方法,即Ip_mc_output函数

在ip_mc_output函数会一步一步最后调用hard_start_xmit发送数据包

你可能感兴趣的:(网络子系统大杂烩三)