目录(?)[+]
Socket Buffers 由以下两部分组成:
1) Packet data: 它是在网络上传输的数据,其存储位置对应的PDU (Protocol Data Unit)
2) Management data: 当包在kernel中进行处理时,kernel需要另外一些数据,如pointer, timers等,它们是协议实体间交换信息的ICI(Interface Control Information)
Socket Buffer构成如下图所示:
在Kernel处理过程中,网络数据以Socket Buffer的形式存在。
当app通过socket发送数据时,socket将创建一个对应的socket buffer,并把需要发送的数据(payload)放于其中。当它通过各个协议层时,每一层的包头将被插入到payload的前面,在创建socket buffer时,为包头预留了足够空间。按此方案,payload被copy两次:
1) 从用户空间copy到kernel空间
2) 发送数据到network adapter
在协议层间传递时,其数据变化如下图所示:
Socket Buffer数据结构如下所示:
对Socket Buffers的操作分为以下三类:
1) 创建、释放和复制sokcet buffers
2) 操作sk_buff结构中的参数和指针,主要是改变包数据空间的操作
3) 管理socket buffer队列
其相关函数如下所示:
alloc_skb() include/linux/skbuff.h
dev_alloc_skb() net/core/skbuff.c
skb_copy() net/core/skbuff.c
skb_copy_expand() net/core/skbuff.c
skb_clone() net/core/skbuff.c
kfree_skb() net/core/skbuff.c
dev_kfree_skb() include/linux/skbuff.h
kfree_skbmem() net/core/skbuff.c
include/linux/skbuff.h
skb_get()
skb_unshare()
skb_put()
skb_push()
skb_pull()
skb_tailroom()
skb_headroom()
skb_realloc_headroom()
skb_reserve()
skb_trim()
skb_cow()
如果Socket Buffer不是正在被处理,则它被sk_buff_head管理,它通过双向链表进行管理,如下图所示:
include/linux/skbuff.h
skb_queue_head_init()
skb_queue_empty()
skb_queue_len()
include/linux/skbuff.h
skb_queue_head()
skb_queue_tail()
skb_dequeue()
skb_dequeue_tail()
skb_queue_purge()
skb_insert()
skb_append()
skb_unlink()
skb_peek()
skb_peek_tail()
在Linux系统中的网络架构,基于软件的协议(software-based protocol)与网络适配器(network adapters)间的接口通过network devices来实现。一个network-device接口需要满足以下要求:
1) 是network adapter的技术抽象
2) 提供统一的接口供协议实体访问
【网络设备】不同于【字符设备】和【块设备】,其主要区别如下:
1) 网络设备在/dev下不存在对应的设备名,即不可通过read和write进行读写操作
2) 网络设备基于包进行处理,且必须经过复杂协议的处理(如TCP和UDP)
net_device定义如下:
net_device是每个网络设备的基础,它不仅包含network adapter硬件信息(如:interrupt, ports, driver functions等),也包含高层网络协议的配置数据(如:IP address, subnet mask等).
在/sys/class/net下列出来所有网络设备的名字,如我的为:
shell@android:/sys/class/net # ll
lrwxrwxrwx root root 2013-07-05 17:08 ip6tnl0
lrwxrwxrwx root root 2013-07-05 17:08 lo (loopback设备)
lrwxrwxrwx root root 2013-07-05 17:08 sit0
lrwxrwxrwx root root 2000-01-01 08:00 wlan0 (Wifi设备)
从上面的协议实例看net_device。
位于文件:kernel/net/core/dev.c
int register_netdev(struct net_device *dev)
void unregister_netdev(struct net_device *dev)
网络设备(net_device)与一个已经存在的network adapter一一对应。
位于文件:kernel/net/core/dev.c
int dev_open(struct net_device *dev)
int dev_close(struct net_device *dev)
位于文件:kernel/net/core/dev.c
struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
void (*setup)(struct net_device *),
unsigned int txqs, unsigned int rxqs)
void free_netdev(struct net_device *dev)
int dev_alloc_name(struct net_device *dev, const char *name)
struct net_device *dev_get_by_index(struct net *net, int ifindex)
struct net_device *dev_get_by_name(struct net *net, const char *name)
void dev_load(struct net *net, const char *name)
int call_netdevice_notifiers(unsigned long val, struct net_device *dev)
网络状态有如下值:
NETDEV_UP: 激活一个网络设备 (dev_open)
NETDEV_DOWN: 禁止一个网络设备 (dev_close)
NETDEV_CHANGE: 通知网络设备状态变化
NETDEV_REGISTER: 网络设备已经被注册,但是没有打开实例
NETDEV_UNREGISTER: 网络设备已经被删除
NETDEV_CHANGEMTU: 网络设备MTU被修改
NETDEV_CHANGEADDR: 网络设备硬件地址被修改
NETDEV_CHANGENAME:网络设备名字被修改
int dev_queue_xmit(struct sk_buff *skb) // kernel/net/core/dev.c
它由高层的协议实例调用,以通过一个net_device(skb->dev)发送一个socket buffer.
在net_device被激活之前,我们必须找到一个匹配的network adapter。网络驱动(network driver)的初始化函数(init/probe)负责找到一个匹配的network adapter并且使用对应的信息初始化net_device。在驱动的probe函数中,主要完成以下任务:(参考:kernel/drivers/net/pci-skeleton.c)
1) 创建net_device
2) 填充相关的硬件信息
3) 调用register_netdev进行注册
4) 设置net_device->netdev_ops (netdev_ops由驱动实现)
1) 打开: ifconfig wlan0 up->ioctl->dev_open->net_device.netdev_ops.ndo_open
2) 关闭: ifconfig wlan0 down->ioctl->dev_close->net_device.netdev_ops.ndo_stop
在驱动中实现与ndo_start_xmit对应的函数
其流程如下图所示:
在网络驱动的中断处理函数中,首先调用dev_alloc_skb创建socket buffer,然后把接收到的数据copy到其中,最后调用netif_rx把socket buffer放入队列中,供协议层处理。
int netif_rx(struct sk_buff *skb) // kernel/net/core/dev.c
1) 逻辑链路控制(LLC)层由Linux内核实现,网络适配器通过net_device连接到操作系统内核。
2) 数据链路层(Data-Link Layer)由LLC和MAC组成。LLC隐藏了所有不同传输介质的差异,从而以上层协议提供统一的接口;而MAC层则反应了不同传输技术(传输协议,如802.3与802.11不同)的差异。
逻辑链路控制 LLC (Logical Link Control)子层
媒体接入控制 MAC (Medium Access Control)子层
与接入到传输媒体有关的内容都放在 MAC子层,而LLC 子层则与传输媒体无关,不管采用何种协议的局域网对 LLC 子层来说都是透明的。