第12章 网络 (2)

目录

12.5 网络命名空间

12.6 套接字缓冲区

12.6.1 使用 sk_buff 管理数据

12.6.2 管理套接字缓冲区数据


本专栏文章将有70篇左右,欢迎+关注,查看后续文章。

12.5 网络命名空间

一个网卡可能只在某个特定命名空间可见。

struct   net:

        表示一个网络命名空间,用于隔离网络资源。

                资源包括:网络设备、路由表、ARP等。

struct    net    {

        refcount_t                         count;         // 引用计数。

        struct   list_head               list;             // 连接 所有 struct net。

        struct user_namespace    *user_ns;   //所属的user命名空间。

        struct list_head                 dev_base_head;

                // 连接该命名空间中所有网络设备。

        struct hlist_head               *dev_name_head;

                // 以name计算hash值,为数组dev_name_head索引,连接所有网络设备。

        struct hlist_head               *dev_index_head;

                // 以 index 计算hash值,为数组dev_index_head索引,连接所有网络设备。

        struct proc_dir_entry         *proc_root;                 // 指向 /proc目录。

        struct proc_dir_entry         *proc_net;                 // 指向 /proc/net 目录。

        struct proc_dir_entry         *proc_net_stat;         // 指向 /proc/net/stat 目录。

        struct net_device               *loopback_dev;         // 环回设备。

        struct netns_core               core;

        struct netns_mib                 mib;                         // tcp,udp,ip,icmp等统计信息。

        struct netns_packet            packet;

        struct netns_unix                unx;

        struct netns_ipv4                ipv4;         //包含IPv4信息,如FIB表,iptable表。

        struct netns_ipv6                ipv6;

        struct sock                         *nfnl;         //与路由子系统通信的socket。

} __randomize_layout;

一个硬件设备对应多个逻辑接口。

init_net:默认命名空间。

struct   net     init_net      =      {

        .count                      =      REFCOUNT_INIT(1),

        .dev_base_head      =      LIST_HEAD_INIT(init_net.dev_base_head),

};

12.6 套接字缓冲区

套接字缓冲区:socket buffer。

        即 struct sk_buff 结构体。

        代表一个数据包的缓冲区。

        作用:通过指针偏移,实现网络各层传递中的数据修改。而不用赋值数据。

12.6.1 使用 sk_buff 管理数据

struct      sk_buff      {

        struct sk_buff         *next,*prev;

                // 链接多个 sk_buff,便于遍历和管理多个数据包。

        struct sock                   *sk;         //拥有此数据包的sock,转发时为NULL。

        struct net_device         *dev;      // 收发包的网络设备。

        struct net_device         *input_dev;         // 收到包的原始设备,用于流量控制。

        __u8                            ip_summed:2      // CHECKSUM_PARTIAL则卸载到硬件checksum

        __u8                            encapsulation:1;   // 该skb是否是隧道报文。

        __be16                        protocol;

        __u16                          transport_header;         // 传输层头。

        __u16                          network_header;          // 网络层头。

        __u16                          mac_header;                // MAC头。

        sk_buff_data_t             tail;                               // 有效数据的结尾。

        sk_buff_data_t             end;                             // 申请数据的结尾。

        unsigned char              *head,                         // 申请数据的开始。

        unsigned char              *data;                          // 有效数据的开始。

        ktime_t                         tstamp:                     // 数据包收发时间戳。

        unsigned int                 len,                              // 该sk_buff 分配的总长度。

        unsigned int                 data_len;                     // 仅数据负载。即data到end的长度。

}

部分成员与报文关系:

发送报文时,head,data,tail,end成员的操作流程:

        1. malloc 分配 sk_buff 结构体,初始化head,data,tail,end。

        2. skb_reserve,预留头部空间。

        3. skb_put,存储报文数据。

        4. skb_push,封装协议头。

收包:

        4 -> 3:调用skb_pull,删除协议头,解封装协议头。

skb_trim:

        从数据区尾部移走 len 数据,skb->tail = skb->tail - len(tail 指针向上移动)。

产生新分组时,TCP 分配大于实际需要长度的内存,便于底层协议增加头部(如上述左图)

sk_buff 相关API:

        alloc_skb                              分配新的 sk_buff。

        skb_copy                              复制 sk_buff 及其数据。

        skb_clone                             只复制sk_buff,但数据共享。

        skb_tailroom                         返回末端空闲长度。

        skb_headroom                      返回头部空闲长度。

        skb_realloc_headroom         增加head空间。

        skb_transport_header(struct sk_buff *skb)

                获取传输层首部地址。

        skb_reset_transport_header(struct sk_buff *skb)

                传输层首部重置为数据部分起始。

        skb_set_transport_header(struct sk_buff *skb, int offset)

                数据部分中偏移指定量设为传输层首部起始。

struct   tcphdr    *tcp_hdr(const struct   sk_buff   *skb)

{

        return     (struct tcphdr *) skb_transport_header(skb);

                // 即 skb->head   +   skb->transport_header;

}

struct iphdr      *ip_hdr(const struct sk_buff    *skb)

{

        return     (struct iphdr *) skb->head  +  skb->network_header;

}

12.6.2 管理套接字缓冲区数据

struct sk_buff {

        ktime_t                           tstamp;         //分组到达的时间戳。

        struct net_device           *dev;

                //处理该分组的设备,处理过程中可能会改变 如:转发。

        int                                   skb_iif; //接收分组的接口索引号。

        struct sock                      *sk; //处理该分组的socket。

        struct sk_buff                 *next;

        struct sk_buff                 *prev;

        ...

}

struc   sk_buff_head {         // sk_buff 的等待队列。

        struct sk_buff         *next;

        struct sk_buff         *prev;

        __u32                    qlen;         // 队列长度。

        spinlock_t               lock;

};

  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山下小童

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值