閑來無事, 把 Understanding Linux Network Internals 抓來看看, 剛好看到了
sk_buff 這個恐怖的 structure. 其中有個 sk_buff->cb[64] 這個 64 bytes 的
東西, 專門拿來把一些 control information 放進去裡面的, 各層 protocol 都
可以拿來用, 但要小心別互相給蓋掉了...
看一下 definition:
include/linux/skbuff.h:
struct sk_buff {
/* These two members must be first. */
struct sk_buff *next;
struct sk_buff *prev;
:
:
/*
* This is the control buffer. It is free to use for every
* layer. Please put your private variables there. If you
* want to keep them across layers you have to do a skb_clone()
* first. This is owned by whoever has the skb queued ATM.
*/
char cb[64];
:
:
}
再來看一下 TCP layer 裡面有用到的部份...
include/net/tcp.h:
/* This is what the send packet queuing engine uses to pass
* TCP per-packet control information to the transmission
* code. We also store the host-order sequence numbers in
* here too. This is 36 bytes on 32-bit architectures,
* 40 bytes on 64-bit machines, if this grows please adjust
* skbuff.h:skbuff->cb[xxx] size appropriately.
*/
struct tcp_skb_cb {
union {
struct inet_skb_parm h4;
#if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE)
struct inet6_skb_parm h6;
#endif
} header; /* For incoming frames */
__u32 seq; /* Starting sequence number */
__u32 end_seq; /* SEQ + FIN + SYN + datalen */
__u32 when; /* used to compute rtt's */
__u8 flags; /* TCP header flags. */
/* NOTE: These must match up to the flags byte in a
* real TCP header.
*/
:
:
__u8 sacked; /* State flags for SACK/FACK. */
:
:
__u16 urg_ptr; /* Valid w/URG flags is set. */
__u32 ack_seq; /* Sequence number ACK'd */
};
#define TCP_SKB_CB(__skb) ((struct tcp_skb_cb *)&((__skb)->cb[0]))
struct inet_skb_parm 是啥鬼捏?
include/net/ip.h:
struct inet_skb_parm
{
struct ip_options opt; /* Compiled IP options
unsigned char flags;
:
:
};
哇靠, 又來一個 struct ip_options...
include/linux/ip.h:
struct ip_options {
__u32 faddr; /* Saved first hop address */
unsigned char optlen;
unsigned char srr;
unsigned char rr;
unsigned char ts;
unsigned char is_setbyuser:1, /* Set by setsockopt?
is_data:1, /* Options in __data, rather th
is_strictroute:1, /* Strict source route
srr_is_hit:1, /* Packet destination addr was
is_changed:1, /* IP checksum more not valid
rr_needaddr:1, /* Need to record addr of outgo
ts_needtime:1, /* Need to record timestamp
ts_needaddr:1; /* Need to record addr of outgo
unsigned char router_alert;
unsigned char __pad1;
unsigned char __pad2;
unsigned char __data[0];
};
Total 大約會用到 36 bytes (32bit machine), or 40 bytes (64bit machine)...
事實上在 protocol layer 裡還有其他幾個地方會用到 skb->cb 的咚咚:
[MVL4 include/net]$ grep "cb\[" *
ipx.h:#define IPX_SKB_CB(__skb) ((struct ipx_cb *)&((__skb)->cb[0]))
llc_conn.h: skb->cb[sizeof(skb->cb) - 1] = type;
llc_conn.h: return skb->cb[sizeof(skb->cb) - 1];
tcp.h: * skbuff.h:skbuff->cb[xxx] size appropriately.
tcp.h:#define TCP_SKB_CB(__skb) ((struct tcp_skb_cb *)&((__skb)->cb[0]))
[MVL4 include/linux]$ grep "cb\[" *
if_vlan.h:#define VLAN_TX_SKB_CB(__skb) ((struct vlan_skb_tx_cookie *)&((__skb)->cb[0]))
if_vlan.h: * Puts the VLAN tag in @skb->cb[] and lets the device do the rest
if_vlan.h: * __vlan_hwaccel_get_tag - get the VLAN ID that is in @skb->cb[]
if_vlan.h: * Returns error if @skb->cb[] is not set correctly
llc.h:#define llc_ui_skb_cb(__skb) ((struct sockaddr_llc *)&((__skb)->cb[0]))
所以盡量要使用 skb->cb[] 內容的話, 把它給擺在 cb[36] 以後吧, 反正有 64 bytes 可用...
... 這也難怪了... 先前把東西擺在 cb[0] & cb[1], 老是會不見 @_@ 唉啊, 真是沒看清楚啊~~~
沒有留言:
張貼留言