kernel version:2.6.32.61
在netif_receive_skb中会调用桥处理函数handle_bridge进行桥相关处理。
主要处理是在br_handle_frame_hook中进行的,而br_handle_frame_hook是在br_init中进行的。
net/bridge/br.c
在br_handle_frame中,区分了本地包和转发包。主要的处理集中在
162 NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
163 br_handle_frame_finish);
代码如下:
net/bridge/br_input.c
在走过桥的NF_BR_PRE_ROUTING的hook点之后,就进入了br_handle_frame_finish中。
这里首先更新了fdb,然后根据fdb查找结果决定直接转发还是flood转发。
这里还有需要注意的是br_pass_frame_up会将包的dev改成桥,然后重新进入netif_receive_skb。
net/bridge/br_input.c
在netif_receive_skb中会调用桥处理函数handle_bridge进行桥相关处理。
net/core/dev.c
2151 static inline struct sk_buff *handle_bridge(struct sk_buff *skb,
2152 struct packet_type **pt_prev, int *ret,
2153 struct net_device *orig_dev)
2154 {
2155 struct net_bridge_port *port;
2156
2157 if (skb->pkt_type == PACKET_LOOPBACK ||
2158 (port = rcu_dereference(skb->dev->br_port)) == NULL)
2159 return skb;
2160
2161 if (*pt_prev) {
2162 *ret = deliver_skb(skb, *pt_prev, orig_dev);
2163 *pt_prev = NULL;
2164 }
2165
2166 return br_handle_frame_hook(port, skb);
2167 }
主要处理是在br_handle_frame_hook中进行的,而br_handle_frame_hook是在br_init中进行的。
net/bridge/br.c
35 static int __init br_init(void)
36 {
37 int err;
38
39 err = stp_proto_register(&br_stp_proto);
40 if (err < 0) {
41 printk(KERN_ERR "bridge: can't register sap for STP\n");
42 return err;
43 }
44
// 使用SLAB,初始化fdb
45 err = br_fdb_init();
46 if (err)
47 goto err_out;
48
49 err = register_pernet_subsys(&br_net_ops);
50 if (err)
51 goto err_out1;
52
// 初始化桥的netfilter
53 err = br_netfilter_init();
54 if (err)
55 goto err_out2;
56
// 注册通知链
57 err = register_netdevice_notifier(&br_device_notifier);
58 if (err)
59 goto err_out3;
60
// netlink初始化
61 err = br_netlink_init();
62 if (err)
63 goto err_out4;
64
65 brioctl_set(br_ioctl_deviceless_stub);
// 初始化br_handle_frame_hook
66 br_handle_frame_hook = br_handle_frame;
67
68 #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE)
69 br_fdb_test_addr_hook = br_fdb_test_addr;
70 #endif
71
72 return 0;
73 err_out4:
74 unregister_netdevice_notifier(&br_device_notifier);
75 err_out3:
76 br_netfilter_fini();
77 err_out2:
78 unregister_pernet_subsys(&br_net_ops);
79 err_out1:
80 br_fdb_fini();
81 err_out:
82 stp_proto_unregister(&br_stp_proto);
83 return err;
84 }
在br_handle_frame中,区分了本地包和转发包。主要的处理集中在
162 NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
163 br_handle_frame_finish);
代码如下:
net/bridge/br_input.c
120 struct sk_buff *br_handle_frame(struct net_bridge_port *p, struct sk_buff *skb)
121 {
122 const unsigned char *dest = eth_hdr(skb)->h_dest;
123 int (*rhook)(struct sk_buff *skb);
124
125 if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
126 goto drop;
127
128 skb = skb_share_check(skb, GFP_ATOMIC);
129 if (!skb)
130 return NULL;
131
132 if (unlikely(is_link_local(dest))) {
133 /* Pause frames shouldn't be passed up by driver anyway */
134 if (skb->protocol == htons(ETH_P_PAUSE))
135 goto drop;
136
137 /* If STP is turned off, then forward */
138 if (p->br->stp_enabled == BR_NO_STP && dest[5] == 0)
139 goto forward;
140
141 if (NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev,
142 NULL, br_handle_local_finish))
143 return NULL; /* frame consumed by filter */
144 else
145 return skb; /* continue processing */
146 }
147
148 forward:
149 switch (p->state) {
150 case BR_STATE_FORWARDING:
151 rhook = rcu_dereference(br_should_route_hook);
152 if (rhook != NULL) {
153 if (rhook(skb))
154 return skb;
155 dest = eth_hdr(skb)->h_dest;
156 }
// 注意此处没有break
157 /* fall through */
158 case BR_STATE_LEARNING:
159 if (!compare_ether_addr(p->br->dev->dev_addr, dest))
160 skb->pkt_type = PACKET_HOST;
161
162 NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
163 br_handle_frame_finish);
164 break;
165 default:
166 drop:
167 kfree_skb(skb);
168 }
169 return NULL;
170 }
在走过桥的NF_BR_PRE_ROUTING的hook点之后,就进入了br_handle_frame_finish中。
这里首先更新了fdb,然后根据fdb查找结果决定直接转发还是flood转发。
这里还有需要注意的是br_pass_frame_up会将包的dev改成桥,然后重新进入netif_receive_skb。
net/bridge/br_input.c
38 int br_handle_frame_finish(struct sk_buff *skb)
39 {
40 const unsigned char *dest = eth_hdr(skb)->h_dest;
41 struct net_bridge_port *p = rcu_dereference(skb->dev->br_port);
42 struct net_bridge *br;
43 struct net_bridge_fdb_entry *dst;
44 struct sk_buff *skb2;
45
46 if (!p || p->state == BR_STATE_DISABLED)
47 goto drop;
48
49 /* insert into forwarding database after filtering to avoid spoofing */
50 br = p->br;
// 更新fdb
51 br_fdb_update(br, p, eth_hdr(skb)->h_source);
52
53 if (p->state == BR_STATE_LEARNING)
54 goto drop;
55
56 /* The packet skb2 goes to the local host (NULL to skip). */
57 skb2 = NULL;
58
59 if (br->dev->flags & IFF_PROMISC)
60 skb2 = skb;
61
62 dst = NULL;
63
64 if (is_multicast_ether_addr(dest)) {
65 br->dev->stats.multicast++;
66 skb2 = skb;
67 } else if ((dst = __br_fdb_get(br, dest)) && dst->is_local) {
68 skb2 = skb;
69 /* Do not forward the packet since it's local. */
70 skb = NULL;
71 }
72
73 if (skb2 == skb)
74 skb2 = skb_clone(skb, GFP_ATOMIC);
75
76 if (skb2)
// 将dev改为桥,发往netif_receive_skb
77 br_pass_frame_up(br, skb2);
78
79 if (skb) {
80 if (dst)
// 转发到学习到的对应端口
81 br_forward(dst->dst, skb);
82 else
// flood转发
83 br_flood_forward(br, skb);
84 }
85
86 out:
87 return 0;
88 drop:
89 kfree_skb(skb);
90 goto out;
91 }