网络子系统在链路层的收发过程剖析(一)【转】

简介:

转自:http://linux.chinaunix.net/techdoc/net/2007/01/30/949381.shtml

R.wen (
rwen2012@126.com
)

1),Skb_buff


/* To allow 64K frame to be packed as single skb without frag_list */
#define MAX_SKB_FRAGS (65536/PAGE_SIZE + 2)

typedef struct skb_frag_struct skb_frag_t;

struct skb_frag_struct {
       struct page *page;
       __u16 page_offset;
       __u16 size;
};

/* This data is invariant across clones and lives at
* the end of the header data, ie. at skb->end.
*/
struct skb_shared_info {
       atomic_t  dataref;
       unsigned short       nr_frags;
       unsigned short       gso_size;
       /* Warning: this field is not always filled in (UFO)! */
       unsigned short       gso_segs;
       unsigned short  gso_type;
       unsigned int    ip6_frag_id;
       struct sk_buff *frag_list;
       skb_frag_t      frags[MAX_SKB_FRAGS];
};


Skb比较复杂的部分在于skb_shared_info部分,alloc_skb()在为数据分配空间的时候,会在这个数据的末尾加上一个skb_shared_info结构,这个结构就是用于scatter/gather IO的实现的。它主要用于提高性能,避免数据的多次拷贝。例如,当用户用sendmsg分送一个数组结构的数据时,这些数据在物理可能是不连续的(大多数情况),在不支持scatter/gather IO的网卡上,它只能通过重新拷贝,将它重装成连续的skb(skb_linearize),才可以进行DMA操作。而在支持S/G IO上,它就省去了这次拷贝。






2),网卡(PCI设备的注册)
       系统启动的时候,pci会扫描所有的PCI设备然后根据注册驱动的id_table,找到相匹配的驱动,实现关联。当找到匹配的驱动时,它会执行相关驱动程序中的probe函数,而网卡的net_device就是在这个函数里面初始化的并注册到内核的。


3),网卡链路状态检测
       当网卡链路状态变化时(如断开或连上),网卡会通知驱动程序或者由驱动程序去查询网卡的相关寄存器位(例如在timeout时去查询这些位),然后由netif_carrier_on/off去通知内核这个变化。

void netif_carrier_on(struct net_device *dev)
{   // test_and_clear_bit - Clear a bit and return its old value
       if (test_and_clear_bit(__LINK_STATE_NOCARRIER, &dev->state))
              linkwatch_fire_event(dev);
       if (netif_running(dev))
              __netdev_watchdog_up(dev);
}

static inline netif_carrier_off(struct net_device *dev)
{
//test_and_set_bit - Set a bit and return its old value
    if (!test_and_set_bit(_ _LINK_STATE_NOCARRIER, &dev->state))
        linkwatch_fire_event(dev);
}

这样,netif_carrier_on会调用linkwatch_fire_event,它会创建一个lw_event结构:

       struct lw_event {
       struct list_head list;
       struct net_device *dev;
};
并将这个结构初始化后(event->dev = dev;)加入到事件队列中:
              spin_lock_irqsave(&lweventlist_lock, flags);
              list_add_tail(&event->list, &lweventlist);
              spin_unlock_irqrestore(&lweventlist_lock, flags);

然后它调用schedule_work(&linkwatch_work)由内核线程去处理这些事件。它最终由linkwatch_run_queue(void)去完成这些处理工作:

list_for_each_safe(n, next, &head) {
              struct lw_event *event = list_entry(n, struct lw_event, list);
              struct net_device *dev = event->dev;
       …
              if (dev->flags & IFF_UP) {
                     if (netif_carrier_ok(dev)) {
                            dev_activate(dev);
                     } else
                            dev_deactivate(dev);
                     netdev_state_change(dev);
              }
}

可以看到,它的最主要工作之一就是netdev_state_change(dev):
void netdev_state_change(struct net_device *dev)
{
       if (dev->flags & IFF_UP) {
              raw_notifier_call_chain(&netdev_chain,
                            NETDEV_CHANGE, dev);
              rtmsg_ifinfo(RTM_NEWLINK, dev, 0);
       }
}

这个函数通知注册到netdev_chain链表的所有子系统,这个网卡的链路状态有了变化。就是说,如果某个子系统对网卡的链路状态变化感兴趣,它就可以注册到进这个链表,在变化产生时,内核便会通知这些子系统。

注意:a. 它只会在网卡状态为UP时,才会发出通知,因为,如果状态为DOWN,网卡链路的状态改变也没什么意义。
         b. 每个见网卡的这些状态变化的事件lw_event是不会队列的,即每个网卡只有一个事件的实例在队列中。还有由上面看到的lw_event结构,它只是包含发生状态变化的网卡设备,而没有包含它是链上或是断开的状状参数。

                                                 07.01.29










本文转自张昺华-sky博客园博客,原文链接:http://www.cnblogs.com/sky-heaven/p/5383695.html,如需转载请自行联系原作者

相关文章
|
机器学习/深度学习 存储 数据可视化
【PyTorch基础教程23】可视化网络和训练过程
为了更好确定复杂网络模型中,每一层的输入结构,输出结构以及参数等信息,在Keras中可以调用一个叫做model.summary()的API能够显示我们的模型参数,输入大小,输出大小,模型的整体参数等。
1357 0
【PyTorch基础教程23】可视化网络和训练过程
|
5月前
|
算法 网络虚拟化
计算机网络——链路层(下)
计算机网络——链路层(下)
|
8月前
|
网络协议 数据挖掘 网络架构
【计算机网络】网络层和链路层网路协议分析
【计算机网络】网络层和链路层网路协议分析
|
8月前
|
机器学习/深度学习 传感器 物联网
毫米波V2I网络的链路层仿真研究(Matlab代码实现)
毫米波V2I网络的链路层仿真研究(Matlab代码实现)
|
10月前
|
网络架构
《计算机网络》阅读摘要——链路层交换机
《计算机网络》阅读摘要——链路层交换机
85 0
|
10月前
|
网络架构
《计算机网络》阅读摘要——链路层寻址
《计算机网络》阅读摘要——链路层寻址
79 0
|
12月前
|
算法 Cloud Native Linux
《云原生网络数据面可观测性最佳实践》—— 一、容器网络内核原理——3.tc子系统(上)
《云原生网络数据面可观测性最佳实践》—— 一、容器网络内核原理——3.tc子系统(上)
|
12月前
|
Cloud Native Linux 网络性能优化
《云原生网络数据面可观测性最佳实践》—— 一、容器网络内核原理——3.tc子系统(下)
《云原生网络数据面可观测性最佳实践》—— 一、容器网络内核原理——3.tc子系统(下)
|
Kubernetes 网络协议 Linux
CentOS7下打通调试PC到K8s Pod之间网络的实践过程
CentOS7下打通调试PC到K8s Pod之间网络的实践过程
252 0
CentOS7下打通调试PC到K8s Pod之间网络的实践过程
|
物联网 数据管理 数据安全/隐私保护
AliOS Things 网络篇之 Wi-Fi 基础知识与连接过程|学习笔记
快速学习 AliOS Things 网络篇之 Wi-Fi 基础知识与连接过程。
458 0
AliOS Things 网络篇之 Wi-Fi 基础知识与连接过程|学习笔记