aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/bridge/br_device.c15
-rw-r--r--net/bridge/br_input.c18
2 files changed, 29 insertions, 4 deletions
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 91dffe7574d6..eb7062d2e9e5 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -25,6 +25,7 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
25 struct net_bridge *br = netdev_priv(dev); 25 struct net_bridge *br = netdev_priv(dev);
26 const unsigned char *dest = skb->data; 26 const unsigned char *dest = skb->data;
27 struct net_bridge_fdb_entry *dst; 27 struct net_bridge_fdb_entry *dst;
28 struct net_bridge_mdb_entry *mdst;
28 29
29 BR_INPUT_SKB_CB(skb)->brdev = dev; 30 BR_INPUT_SKB_CB(skb)->brdev = dev;
30 31
@@ -34,13 +35,21 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
34 skb_reset_mac_header(skb); 35 skb_reset_mac_header(skb);
35 skb_pull(skb, ETH_HLEN); 36 skb_pull(skb, ETH_HLEN);
36 37
37 if (dest[0] & 1) 38 if (dest[0] & 1) {
38 br_flood_deliver(br, skb); 39 if (br_multicast_rcv(br, NULL, skb))
39 else if ((dst = __br_fdb_get(br, dest)) != NULL) 40 goto out;
41
42 mdst = br_mdb_get(br, skb);
43 if (mdst || BR_INPUT_SKB_CB(skb)->mrouters_only)
44 br_multicast_deliver(mdst, skb);
45 else
46 br_flood_deliver(br, skb);
47 } else if ((dst = __br_fdb_get(br, dest)) != NULL)
40 br_deliver(dst->dst, skb); 48 br_deliver(dst->dst, skb);
41 else 49 else
42 br_flood_deliver(br, skb); 50 br_flood_deliver(br, skb);
43 51
52out:
44 return NETDEV_TX_OK; 53 return NETDEV_TX_OK;
45} 54}
46 55
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index edfdaef44296..53b39851d87d 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -41,6 +41,7 @@ int br_handle_frame_finish(struct sk_buff *skb)
41 struct net_bridge_port *p = rcu_dereference(skb->dev->br_port); 41 struct net_bridge_port *p = rcu_dereference(skb->dev->br_port);
42 struct net_bridge *br; 42 struct net_bridge *br;
43 struct net_bridge_fdb_entry *dst; 43 struct net_bridge_fdb_entry *dst;
44 struct net_bridge_mdb_entry *mdst;
44 struct sk_buff *skb2; 45 struct sk_buff *skb2;
45 46
46 if (!p || p->state == BR_STATE_DISABLED) 47 if (!p || p->state == BR_STATE_DISABLED)
@@ -50,6 +51,10 @@ int br_handle_frame_finish(struct sk_buff *skb)
50 br = p->br; 51 br = p->br;
51 br_fdb_update(br, p, eth_hdr(skb)->h_source); 52 br_fdb_update(br, p, eth_hdr(skb)->h_source);
52 53
54 if (is_multicast_ether_addr(dest) &&
55 br_multicast_rcv(br, p, skb))
56 goto drop;
57
53 if (p->state == BR_STATE_LEARNING) 58 if (p->state == BR_STATE_LEARNING)
54 goto drop; 59 goto drop;
55 60
@@ -64,8 +69,19 @@ int br_handle_frame_finish(struct sk_buff *skb)
64 dst = NULL; 69 dst = NULL;
65 70
66 if (is_multicast_ether_addr(dest)) { 71 if (is_multicast_ether_addr(dest)) {
72 mdst = br_mdb_get(br, skb);
73 if (mdst || BR_INPUT_SKB_CB(skb)->mrouters_only) {
74 if ((mdst && !hlist_unhashed(&mdst->mglist)) ||
75 br_multicast_is_router(br))
76 skb2 = skb;
77 br_multicast_forward(mdst, skb, skb2);
78 skb = NULL;
79 if (!skb2)
80 goto out;
81 } else
82 skb2 = skb;
83
67 br->dev->stats.multicast++; 84 br->dev->stats.multicast++;
68 skb2 = skb;
69 } else if ((dst = __br_fdb_get(br, dest)) && dst->is_local) { 85 } else if ((dst = __br_fdb_get(br, dest)) && dst->is_local) {
70 skb2 = skb; 86 skb2 = skb;
71 /* Do not forward the packet since it's local. */ 87 /* Do not forward the packet since it's local. */