diff options
Diffstat (limited to 'net/bridge/br_input.c')
-rw-r--r-- | net/bridge/br_input.c | 33 |
1 files changed, 28 insertions, 5 deletions
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index f06ee39c73fd..6f9f8c014725 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c | |||
@@ -162,14 +162,37 @@ rx_handler_result_t br_handle_frame(struct sk_buff **pskb) | |||
162 | p = br_port_get_rcu(skb->dev); | 162 | p = br_port_get_rcu(skb->dev); |
163 | 163 | ||
164 | if (unlikely(is_link_local(dest))) { | 164 | if (unlikely(is_link_local(dest))) { |
165 | /* Pause frames shouldn't be passed up by driver anyway */ | 165 | /* |
166 | if (skb->protocol == htons(ETH_P_PAUSE)) | 166 | * See IEEE 802.1D Table 7-10 Reserved addresses |
167 | * | ||
168 | * Assignment Value | ||
169 | * Bridge Group Address 01-80-C2-00-00-00 | ||
170 | * (MAC Control) 802.3 01-80-C2-00-00-01 | ||
171 | * (Link Aggregation) 802.3 01-80-C2-00-00-02 | ||
172 | * 802.1X PAE address 01-80-C2-00-00-03 | ||
173 | * | ||
174 | * 802.1AB LLDP 01-80-C2-00-00-0E | ||
175 | * | ||
176 | * Others reserved for future standardization | ||
177 | */ | ||
178 | switch (dest[5]) { | ||
179 | case 0x00: /* Bridge Group Address */ | ||
180 | /* If STP is turned off, | ||
181 | then must forward to keep loop detection */ | ||
182 | if (p->br->stp_enabled == BR_NO_STP) | ||
183 | goto forward; | ||
184 | break; | ||
185 | |||
186 | case 0x01: /* IEEE MAC (Pause) */ | ||
167 | goto drop; | 187 | goto drop; |
168 | 188 | ||
169 | /* If STP is turned off, then forward */ | 189 | default: |
170 | if (p->br->stp_enabled == BR_NO_STP && dest[5] == 0) | 190 | /* Allow selective forwarding for most other protocols */ |
171 | goto forward; | 191 | if (p->br->group_fwd_mask & (1u << dest[5])) |
192 | goto forward; | ||
193 | } | ||
172 | 194 | ||
195 | /* Deliver packet to local host only */ | ||
173 | if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev, | 196 | if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev, |
174 | NULL, br_handle_local_finish)) { | 197 | NULL, br_handle_local_finish)) { |
175 | return RX_HANDLER_CONSUMED; /* consumed by filter */ | 198 | return RX_HANDLER_CONSUMED; /* consumed by filter */ |