您的位置:首页 > 运维架构 > Linux

Linux中ipv6代码阅读(1)

2008-12-25 16:19 162 查看
一. 网卡接受数据的过程
这部分是说明数据报文在在链路层的处理,以及如何将报文送交给对应的网络层协议来处理。这些功能基本都是在驱动中实现的。
1. 从网络中接收数据报文的时候,涉及到两个终端。一个是硬中断,一个是软中断。
(1).硬中断的中断处理函数是在驱动中注册,一般在device open()函数或者 device init()函数中注册,使用request_irq()来注册硬中断处理函数。当网卡接收到数据的时候,就会调用这个终端处理函数来处理。比如8139too.c函数就用 retval = request_irq (dev->irq, rtl8139_interrupt, SA_SHIRQ, dev->name, dev)来注册硬中断处理函数。
(2)软中断是通过NET_RX_SOFTIRQ信号来触发的,处理函数是net_rx_action。注册函数是open_softirq(NET_RX_SOFTIRQ, net_rx_action, NULL)。触发这个中断信号(raise irq)一般是在硬中断处理流程中,当硬中断处理基本结束的时候,通过调用__raise_softirq_irqoff(NET_RX_SOFTIRQ)来触发这个中断。


2.接收软中断(net_rx_action)主要还是通过调用驱动中的poll的方法进行接收。在poll方法中,会提取接收包,根据它所在的设备和协议类型传递给各自的包处理器。以rtl8139_poll为例,它会调用rtl8139_rx()来把尽可能多的数据在一次中断处理中处理完,而不是一个软中断只处理一个数据包,这样可以提高效率。每个数据包都会通过netif_receive_skb()函数,根据报文的协议类型,调用上层的包处理器。如果网卡本身驱动没有poll函数,将是调用bakclog_dev的process_backlog函数。

3.包处理器用dev_add_pack()注册,如果注册的设备号是零则表明它接收所有设备的包, 如果注册的包类型是(ETH_P_ALL),则表示它接收所有类型的包。

netif_receive_skb()函数会根据接受数据的协议类型,在ptype_all和ptype_base列表中去查找对应的处理协议,再将数据包传递给对应的协议处理函数。

4. 对于ipv4,就是在af_inet.c中的inet_init()函数中,初始化了ip_packet_type.func = ip_rcv,因此,ip_rcv()将接收ipv4的报文。在inet_init()中调用dev_add_pack(&ip_packet_type)去在ptype_all和ptype_base中注册协议处理函数。ipv4的IP头类型值是ETH_P_IP:0x0800。
对于ipv6,则在af_inet6.c中的inet6_init()函数中完成初始化, inet6_init()调用ipv6_packet_init()来注册协议处理报文。Ipv6的IP头类型值是 ETH_P_IPV6 0x86DD。其注册的接收处理程序是ipv6_rcv()。

5. 扣除tc模块,linux内核网络部分的收发结构图。



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: