Linux kernel packet traveling diagram
源:http://blog.csdn.net/maeom/article/details/6092501
http://mailman.ds9a.nl/pipermail/lartc/2002q2/004245.html
Network
-----------+-----------
|
+-------+------+
| mangle |
| PREROUTING | <- MARK REWRITE
+-------+------+
|
+-------+------+
| nat |
| PREROUTING | <- DEST REWRITE
+-------+------+
|
+-------+------+
| ipchains |
| FILTER |
+-------+------+
|
+-------+------+
| QOS |
| INGRESS | <- controlled by tc
+-------+------+
|
packet is for +-------+------+ packet is for
this address | INPUT | another address
+--------------+ ROUTING +---------------+
| | + PRDB | |
| +--------------+ |
+-------+------+ |
| filter | |
| INPUT | |
+-------+------+ |
| |
+-------+------+ |
| Local | |
| Process | |
+-------+------+ |
| |
+-------+------+ |
| OUTPUT | +-------+-------+
| ROUTING | | filter |
+-------+------+ | FORWARD |
| +-------+-------+
+-------+------+ |
| mangle | |
| OUTPUT | MARK REWRITE |
+-------+------+ |
| |
+-------+------+ |
| nat | |
| OUTPUT | DEST REWRITE |
+-------+------+ |
| |
+-------+------+ |
| filter | |
| OUTPUT | |
+-------+------+ |
| |
+----------------+ +--------------------+
| |
+--+-------+---+
| ipchains |
| FILTER |
+-------+------+
|
+-------+------+
| nat |
| POSTROUTING | SOURCE REWRITE
+-------+------+
|
+-------+------+
| QOS |
| EGRESS | <- controlled by tc
+-------+------+
|
-----------+-----------
Network
以上为linux中TC(Traffic Control)控制部分,和网络包在内核中的走向,下面是一个图。
源:http://open-source.arkoon.net/kernel.php
当然这个图和现在的kernel还是有点出入的,
在linux-2.6.36中。
ip_forward_finish() -->return dst_output(skb);--->ip_output()
然后是POSTOUTING是
ip_output()-->NF_IP_POSTOUTING-->ip_finish_output()这样处理过程
如果是ip_gre 活ip_ip协议的话,那么是在ip_local_deliver_finish内,调用相应的handler函数,去掉gre/ip头后处理完成后再调用netif_rx()函数。相信在代码中都是一目了然的。代码内核版本为:2.6.36
1 /*
2 * net/ipv4/ip_output.c
3 */
4 int ip_local_out(struct sk_buff *skb)
5 {
6 err = __ip_local_out(skb);
7 }
8 int __ip_local_out(struct sk_buff *skb)
9 {
10 return nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT, skb, NULL,
11 skb_dst(skb)->dev, dst_output);
12 }
13 /* 经过LOCAL_OUT过滤节点
14 * include/net/dst.h
15 */
16 static inline int dst_output(struct sk_buff *skb)
17 {
18 return skb_dst(skb)->output(skb);
19 }
20 int ip_output(struct sk_buff *skb)
21 {
22 return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, skb, NULL, dev,
23 ip_finish_output,
24 !(IPCB(skb)->flags & IPSKB_REROUTED));
25 }
26 /**
27 * 经过POST_ROUTING过滤函数
28 **/
29 static int ip_finish_output(struct sk_buff *skb)
30 {
31 return ip_finish_output2(skb);
32 }
33 static inline int ip_finish_output2(struct sk_buff *skb)
34 {
35 else if (dst->neighbour)
36 {
37 printk(KERN_INFO "jsh ip_finish_output2 neighbour/n");
38 return dst->neighbour->output(skb);
39 }
40 }
41 /*
42 * net/core/dev.c
43 */
44 int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
45 struct netdev_queue *txq)
46 {
47 rc = ops->ndo_start_xmit(skb, dev);
48 }
49 /* net/ipv4/ip_gre.c
50 * 这个文件中有这样的赋值语句:ndo_start_xmit = ipgre_tunnel_xmit,
51 *
52 */
53 static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev)
54 {
55 IPTUNNEL_XMIT();
56 }
57 /* include/net/ipip.h
58 *
59 */
60 #define IPTUNNEL_XMIT() do {/
61 err = ip_local_out(skb);/
62 } while (0)
63 /*net/ipv4/ip_output.c
64 *
65 */
66 int ip_local_out(struct sk_buff *skb)
67 {
68 err = __ip_local_out(skb);
69 }
70 int __ip_local_out(struct sk_buff *skb)
71 {
72 return nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT, skb, NULL,
73 skb_dst(skb)->dev, dst_output);
74 }
75 /*
76 * 通过LOCAL_OUT包过滤函数后进入ip_output()函数
77 * 进入如上ip_output() ---> dev_hard_start_xmit()的过程循环
78 */