对于一个给定的网络功能,你必须考虑如下几个方面:
1.如果是你,你会如何设计相关的数据结构和锁机制
2.是否需要在用户空间提供一个配置工具,如果需要则配置工具通过什么方式和内核交互,系统调用,ioctl命令还是其他的方式
3.是否需要一个新的通知链或则是否需要注册到一个已经存在的链。linux中用链表管理一批数据,有时需要将自己的数据结构注册到链表上。
4.他们和防火墙的关系如何
5.是否需要cache,垃圾回收机制,统计数据等等
在学习之前准备的工具:
1.编辑器和源码浏览器选择为vim ctags
2.阅读英文文档用的翻译为openyoudao
3.可能需要绘制流程图,使用yEd
关键的数据结构
1.sk_buff
网络是分层设计的,接收的数据包由低层一级一级的处理,然后送到上一层,发送的数据包由上层处理后发送的下一层,这要求必须有一种结构来表示这样的数据包
1.其可以管理变长的内存
2.可以很方面的在其头部和尾部添加信息
3.尽可能的减少拷贝
在2.6内核的网络中,sk_buff结构担负起了这个责任.
其定义如下
struct sk_buff {
/* These two members must be first. */
struct sk_buff *next;
struct sk_buff *prev;
struct sk_buff_head *list;
struct sock *sk;
struct timeval stamp;
struct net_device *dev;
struct net_device *input_dev;
struct net_device *real_dev;
union {
struct tcphdr *th;
struct udphdr *uh;
struct icmphdr *icmph;
struct igmphdr *igmph;
struct iphdr *ipiph;
struct ipv6hdr *ipv6h;
unsigned char *raw;
} h;
union {
struct iphdr *iph;
struct ipv6hdr *ipv6h;
struct arphdr *arph;
unsigned char *raw;
} nh;
union {
unsigned char *raw;
} mac;
struct dst_entry *dst;
struct sec_path *sp;
/*
* 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[40];
unsigned int len,
data_len,
mac_len,
csum;
unsigned char local_df,
cloned,
pkt_type,
ip_summed;
__u32 priority;
unsigned short protocol,
security;
void (*destructor)(struct sk_buff *skb);
#ifdef CONFIG_NETFILTER
unsigned long nfmark;
__u32 nfcache;
__u32 nfctinfo;
struct nf_conntrack *nfct;
#ifdef CONFIG_NETFILTER_DEBUG
unsigned int nf_debug;
#endif
#ifdef CONFIG_BRIDGE_NETFILTER
struct nf_bridge_info *nf_bridge;
#endif
#endif /* CONFIG_NETFILTER */
#if defined(CONFIG_HIPPI)
union {
__u32 ifield;
} private;
#endif
#ifdef CONFIG_NET_SCHED
__u32 tc_index; /* traffic control index */
#ifdef CONFIG_NET_CLS_ACT
__u32 tc_verd; /* traffic control verdict */
__u32 tc_classid; /* traffic control classid */
#endif
#endif
/* These elements must be at the end, see alloc_skb() for details. */
unsigned int truesize;
atomic_t users;
unsigned char *head,
*data,
*tail,
*end;
};