char cb[40]---"control buffer"


//-----------------------------------------------------------------------------
include/linux/skbuff.h

struct sk_buff {
//ztg
//    char            cb[80] __aligned(8);
    char            cb[80] __aligned(8);
}
//-----------------------------------------------------------------------------
./include/net/tcp.h

#define TCP_SKB_CB(__skb)    ((struct tcp_skb_cb *)&((__skb)->cb[0]))

struct tcp_skb_cb {                                // 在该结构体中 添加两个成员,用于控制 skb 重复发送几次后销毁

//ztg add 在该结构体中 添加两个成员,用于控制 skb 重复发送几次后销毁
#ifdef CONFIG_MPTCP
    __u16        sent_num;    // skb 重复发送次数,当发送次数 和 算法中计算的次数(冗余路径数) 相同,则 销毁 skb
    __u32        path_masks;    // skb 发送的路径
#endif

    __u32        ack_seq;    // Sequence number ACK'd

#ifdef CONFIG_MPTCP
    union {                // For MPTCP outgoing frames
        __u32 path_mask;     // paths that tried to send this skb
        __u32 dss[6];        // DSS options
    };
#endif
}

//-----------------------------------------------------------------------------

http://www.embeddedlinux.org.cn/linux_net/0596002556/understandlni-CHP-2-SECT-1.html

char cb[40]

This is a "control buffer," or storage for private information, maintained by each layer for internal use. It is statically allocated within the sk_buff structure (currently with a size of 40 bytes) and is large enough to hold whatever private data is needed by each layer. In the code for each layer, access is done through macros to make the code more readable. TCP, for example, uses that space to store a tcp_skb_cb data structure, which is defined in include/net/tcp.h:

struct tcp_skb_cb {
    ... ... ...
    _ _u32        seq;        /* Starting sequence number */
    _ _u32        end_seq;    /* SEQ + FIN + SYN + datalen*/
    _ _u32        when;       /* used to compute rtt's    */
    _ _u8         flags;      /* TCP header flags.        */
    ... ... ...
};

And this is the macro used by the TCP code to access the structure. The macro consists simply of a pointer cast:

#define TCP_SKB_CB(_ _skb)    ((struct tcp_skb_cb *)&((_ _skb)->cb[0]))

Here is an example where the TCP subsystem fills in the structure upon receipt of a segment:

int tcp_v4_rcv(struct sk_buff *skb)
{
        ... ... ...
        th = skb->h.th;
        TCP_SKB_CB(skb)->seq = ntohl(th->seq);
        TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin +
                                    skb->len - th->doff * 4);
        TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq);
        TCP_SKB_CB(skb)->when = 0;
        TCP_SKB_CB(skb)->flags = skb->nh.iph->tos;
        TCP_SKB_CB(skb)->sacked = 0;
        ... ... ...
}

To see how the parameters in the cb buffer are retrieved, take a look at the function tcp_transmit_skb in net/ipv4/tcp_output.c. That function is used by TCP to push a data segment down to the IP layer for transmission.

In Chapter 22, you will also see how IPv4 uses cb to store information about IP fragmentation.



相关