diff options
| author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-03-23 23:44:19 -0500 |
|---|---|---|
| committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-03-23 23:44:19 -0500 |
| commit | 1ebbe2b20091d306453a5cf480a87e6cd28ae76f (patch) | |
| tree | f5cd7a0fa69b8b1938cb5a0faed2e7b0628072a5 /net/bridge/br_input.c | |
| parent | ac58c9059da8886b5e8cde012a80266b18ca146e (diff) | |
| parent | 674a396c6d2ba0341ebdd7c1c9950f32f018e2dd (diff) | |
Merge branch 'linus'
Diffstat (limited to 'net/bridge/br_input.c')
| -rw-r--r-- | net/bridge/br_input.c | 43 |
1 files changed, 26 insertions, 17 deletions
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index 4eef83755315..b7766562d72c 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c | |||
| @@ -19,13 +19,8 @@ | |||
| 19 | #include <linux/netfilter_bridge.h> | 19 | #include <linux/netfilter_bridge.h> |
| 20 | #include "br_private.h" | 20 | #include "br_private.h" |
| 21 | 21 | ||
| 22 | const unsigned char bridge_ula[6] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 }; | 22 | /* Bridge group multicast address 802.1d (pg 51). */ |
| 23 | 23 | const u8 br_group_address[ETH_ALEN] = { 0x01, 0x80, 0xc2, 0x00, 0x00, 0x00 }; | |
| 24 | static int br_pass_frame_up_finish(struct sk_buff *skb) | ||
| 25 | { | ||
| 26 | netif_receive_skb(skb); | ||
| 27 | return 0; | ||
| 28 | } | ||
| 29 | 24 | ||
| 30 | static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb) | 25 | static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb) |
| 31 | { | 26 | { |
| @@ -38,7 +33,7 @@ static void br_pass_frame_up(struct net_bridge *br, struct sk_buff *skb) | |||
| 38 | skb->dev = br->dev; | 33 | skb->dev = br->dev; |
| 39 | 34 | ||
| 40 | NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, indev, NULL, | 35 | NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, indev, NULL, |
| 41 | br_pass_frame_up_finish); | 36 | netif_receive_skb); |
| 42 | } | 37 | } |
| 43 | 38 | ||
| 44 | /* note: already called with rcu_read_lock (preempt_disabled) */ | 39 | /* note: already called with rcu_read_lock (preempt_disabled) */ |
| @@ -100,6 +95,25 @@ drop: | |||
| 100 | goto out; | 95 | goto out; |
| 101 | } | 96 | } |
| 102 | 97 | ||
| 98 | /* note: already called with rcu_read_lock (preempt_disabled) */ | ||
| 99 | static int br_handle_local_finish(struct sk_buff *skb) | ||
| 100 | { | ||
| 101 | struct net_bridge_port *p = rcu_dereference(skb->dev->br_port); | ||
| 102 | |||
| 103 | if (p && p->state != BR_STATE_DISABLED) | ||
| 104 | br_fdb_update(p->br, p, eth_hdr(skb)->h_source); | ||
| 105 | |||
| 106 | return 0; /* process further */ | ||
| 107 | } | ||
| 108 | |||
| 109 | /* Does address match the link local multicast address. | ||
| 110 | * 01:80:c2:00:00:0X | ||
| 111 | */ | ||
| 112 | static inline int is_link_local(const unsigned char *dest) | ||
| 113 | { | ||
| 114 | return memcmp(dest, br_group_address, 5) == 0 && (dest[5] & 0xf0) == 0; | ||
| 115 | } | ||
| 116 | |||
| 103 | /* | 117 | /* |
| 104 | * Called via br_handle_frame_hook. | 118 | * Called via br_handle_frame_hook. |
| 105 | * Return 0 if *pskb should be processed furthur | 119 | * Return 0 if *pskb should be processed furthur |
| @@ -117,15 +131,10 @@ int br_handle_frame(struct net_bridge_port *p, struct sk_buff **pskb) | |||
| 117 | if (!is_valid_ether_addr(eth_hdr(skb)->h_source)) | 131 | if (!is_valid_ether_addr(eth_hdr(skb)->h_source)) |
| 118 | goto err; | 132 | goto err; |
| 119 | 133 | ||
| 120 | if (p->br->stp_enabled && | 134 | if (unlikely(is_link_local(dest))) { |
| 121 | !memcmp(dest, bridge_ula, 5) && | 135 | skb->pkt_type = PACKET_HOST; |
| 122 | !(dest[5] & 0xF0)) { | 136 | return NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev, |
| 123 | if (!dest[5]) { | 137 | NULL, br_handle_local_finish) != 0; |
| 124 | NF_HOOK(PF_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev, | ||
| 125 | NULL, br_stp_handle_bpdu); | ||
| 126 | return 1; | ||
| 127 | } | ||
| 128 | goto err; | ||
| 129 | } | 138 | } |
| 130 | 139 | ||
| 131 | if (p->state == BR_STATE_FORWARDING || p->state == BR_STATE_LEARNING) { | 140 | if (p->state == BR_STATE_FORWARDING || p->state == BR_STATE_LEARNING) { |
