转:http://blog.csdn.net/nerdx/article/details/12289997
-
-
-
-
-
-
-
1.1 int br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
-
{
-
struct net_bridge *br = netdev_priv(dev);
-
const unsigned char *dest = skb->data;
-
struct net_bridge_fdb_entry *dst;
-
-
br->statistics.tx_packets++;
-
br->statistics.tx_bytes += skb->len;
-
-
skb->mac.raw = skb->data;
-
skb_pull(skb, ETH_HLEN);
-
-
rcu_read_lock();
-
if (dest[0] & 1)
-
br_flood_deliver(br, skb, 0);
-
else if ((dst = __br_fdb_get(br, dest)) != NULL)
-
br_deliver(dst->dst, skb);
-
else
-
br_flood_deliver(br, skb, 0);
-
-
rcu_read_unlock();
-
return 0;
-
}
-
-
-
-
-
-
1.3 static void br_flood(struct net_bridge *br, struct sk_buff *skb, int clone,
-
void (*__packet_hook)(const struct net_bridge_port *p,
-
struct sk_buff *skb))
-
{
-
struct net_bridge_port *p;
-
struct net_bridge_port *prev;
-
-
if (clone) {
-
struct sk_buff *skb2;
-
-
if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL) {
-
br->statistics.tx_dropped++;
-
return;
-
}
-
-
skb = skb2;
-
}
-
-
prev = NULL;
-
-
list_for_each_entry_rcu(p, &br->port_list, list) {
-
if (should_deliver(p, skb)) {
-
if (prev != NULL) {
-
struct sk_buff *skb2;
-
-
if ((skb2 = skb_clone(skb, GFP_ATOMIC)) == NULL) {
-
br->statistics.tx_dropped++;
-
kfree_skb(skb);
-
return;
-
}
-
-
__packet_hook(prev, skb2);
-
}
-
-
prev = p;
-
}
-
}
-
-
if (prev != NULL) {
-
__packet_hook(prev, skb);
-
return;
-
}
-
-
kfree_skb(skb);
-
}
-
-
-
-
1.6 int br_dev_queue_push_xmit(struct sk_buff *skb)
-
{
-
if (skb->len > skb->dev->mtu)
-
kfree_skb(skb);
-
else {
-
skb_push(skb, ETH_HLEN);
-
dev_queue_xmit(skb);
-
}
-
-
return 0;
-
}
-
-
-
-
-
-
1.7 static inline int should_deliver(const struct net_bridge_port *p,
-
const struct sk_buff *skb)
-
{
-
if (skb->dev == p->dev ||
-
p->state != BR_STATE_FORWARDING)
-
return 0;
-
-
return 1;
-
}
-
-
-
-
-
-
-
-
-
2.1 static __inline__ int handle_bridge(struct sk_buff **pskb,
-
struct packet_type **pt_prev, int *ret)
-
{
-
struct net_bridge_port *port;
-
-
if ((*pskb)->pkt_type == PACKET_LOOPBACK ||
-
(port = rcu_dereference((*pskb)->dev->br_port)) == NULL)
-
return 0;
-
-
if (*pt_prev) {
-
*ret = deliver_skb(*pskb, *pt_prev);
-
*pt_prev = NULL;
-
}
-
-
return br_handle_frame_hook(port, pskb);
-
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
2.2 int br_handle_frame(struct net_bridge_port *p, struct sk_buff **pskb)
-
{
-
struct sk_buff *skb = *pskb;
-
const unsigned char *dest = eth_hdr(skb)->h_dest;
-
-
if (p->state == BR_STATE_DISABLED)
-
goto err;
-
-
if (eth_hdr(skb)->h_source[0] & 1)
-
goto err;
-
-
if (p->state == BR_STATE_LEARNING ||
-
p->state == BR_STATE_FORWARDING)
-
br_fdb_insert(p->br, p, eth_hdr(skb)->h_source, 0);
-
-
if (p->br->stp_enabled &&
-
!memcmp(dest, bridge_ula, 5) &&
-
!(dest[5] & 0xF0)) {
-
if (!dest[5]) {
-
NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev,
-
NULL, br_stp_handle_bpdu);
-
return 1;
-
}
-
}
-
-
else if (p->state == BR_STATE_FORWARDING) {
-
if (br_should_route_hook) {
-
if (br_should_route_hook(pskb))
-
return 0;
-
skb = *pskb;
-
dest = eth_hdr(skb)->h_dest;
-
}
-
-
if (!memcmp(p->br->dev->dev_addr, dest, ETH_ALEN))
-
skb->pkt_type = PACKET_HOST;
-
-
NF_HOOK(PF_BRIDGE, NF_BR_PRE_ROUTING, skb, skb->dev, NULL,
-
br_handle_frame_finish);
-
return 1;
-
}
-
-
err:
-
kfree_skb(skb);
-
return 1;
-
}
-
-
-
-
-
-
-
-
-
-
-
-
2.3 int br_handle_frame_finish(struct sk_buff *skb)
-
{
-
const unsigned char *dest = eth_hdr(skb)->h_dest;
-
struct net_bridge_port *p = skb->dev->br_port;
-
struct net_bridge *br = p->br;
-
struct net_bridge_fdb_entry *dst;
-
int passedup = 0;
-
-
if (br->dev->flags & IFF_PROMISC) {
-
struct sk_buff *skb2;
-
-
skb2 = skb_clone(skb, GFP_ATOMIC);
-
if (skb2 != NULL) {
-
passedup = 1;
-
br_pass_frame_up(br, skb2);
-
}
-
}
-
-
if (dest[0] & 1) {
-
br_flood_forward(br, skb, !passedup);
-
if (!passedup)
-
br_pass_frame_up(br, skb);
-
goto out;
-
}
-
-
dst = __br_fdb_get(br, dest);
-
if (dst != NULL && dst->is_local) {
-
if (!passedup)
-
br_pass_frame_up(br, skb);
-
else
-
kfree_skb(skb);
-
goto out;
-
}
-
-
if (dst != NULL) {
-
br_forward(dst->dst, skb);
-
goto out;
-
}
-
-
br_flood_forward(br, skb, 0);
-
-
out:
-
return 0;
-
}
-
-
-
-
-
-
-
-
-
2.4 static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb)
-
{
-
struct net_device *indev;
-
-
-
br->statistics.rx_packets++;
-
br->statistics.rx_bytes += skb->len;
-
-
indev = skb->dev;
-
skb->dev = br->dev;
-
-
NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, indev, NULL,
-
br_pass_frame_up_finish);
-
}
-
-
-
-
-
2.5 static int br_pass_frame_up_finish(struct sk_buff *skb)
-
{
-
-
netif_rx(skb);
-
return 0;
-
}
-
阅读(838) | 评论(0) | 转发(0) |