Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c4fcb78c authored by Herbert Xu's avatar Herbert Xu Committed by David S. Miller
Browse files

bridge: Add multicast data-path hooks



This patch finally hooks up the multicast snooping module to the
data path.  In particular, all multicast packets passing through
the bridge are fed into the module and switched by it.

Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3fe2d7c7
Loading
Loading
Loading
Loading
+12 −3
Original line number Original line Diff line number Diff line
@@ -25,6 +25,7 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
	struct net_bridge *br = netdev_priv(dev);
	struct net_bridge *br = netdev_priv(dev);
	const unsigned char *dest = skb->data;
	const unsigned char *dest = skb->data;
	struct net_bridge_fdb_entry *dst;
	struct net_bridge_fdb_entry *dst;
	struct net_bridge_mdb_entry *mdst;


	BR_INPUT_SKB_CB(skb)->brdev = dev;
	BR_INPUT_SKB_CB(skb)->brdev = dev;


@@ -34,13 +35,21 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
	skb_reset_mac_header(skb);
	skb_reset_mac_header(skb);
	skb_pull(skb, ETH_HLEN);
	skb_pull(skb, ETH_HLEN);


	if (dest[0] & 1)
	if (dest[0] & 1) {
		if (br_multicast_rcv(br, NULL, skb))
			goto out;

		mdst = br_mdb_get(br, skb);
		if (mdst || BR_INPUT_SKB_CB(skb)->mrouters_only)
			br_multicast_deliver(mdst, skb);
		else
			br_flood_deliver(br, skb);
			br_flood_deliver(br, skb);
	else if ((dst = __br_fdb_get(br, dest)) != NULL)
	} else if ((dst = __br_fdb_get(br, dest)) != NULL)
		br_deliver(dst->dst, skb);
		br_deliver(dst->dst, skb);
	else
	else
		br_flood_deliver(br, skb);
		br_flood_deliver(br, skb);


out:
	return NETDEV_TX_OK;
	return NETDEV_TX_OK;
}
}


+17 −1
Original line number Original line Diff line number Diff line
@@ -41,6 +41,7 @@ int br_handle_frame_finish(struct sk_buff *skb)
	struct net_bridge_port *p = rcu_dereference(skb->dev->br_port);
	struct net_bridge_port *p = rcu_dereference(skb->dev->br_port);
	struct net_bridge *br;
	struct net_bridge *br;
	struct net_bridge_fdb_entry *dst;
	struct net_bridge_fdb_entry *dst;
	struct net_bridge_mdb_entry *mdst;
	struct sk_buff *skb2;
	struct sk_buff *skb2;


	if (!p || p->state == BR_STATE_DISABLED)
	if (!p || p->state == BR_STATE_DISABLED)
@@ -50,6 +51,10 @@ int br_handle_frame_finish(struct sk_buff *skb)
	br = p->br;
	br = p->br;
	br_fdb_update(br, p, eth_hdr(skb)->h_source);
	br_fdb_update(br, p, eth_hdr(skb)->h_source);


	if (is_multicast_ether_addr(dest) &&
	    br_multicast_rcv(br, p, skb))
		goto drop;

	if (p->state == BR_STATE_LEARNING)
	if (p->state == BR_STATE_LEARNING)
		goto drop;
		goto drop;


@@ -64,8 +69,19 @@ int br_handle_frame_finish(struct sk_buff *skb)
	dst = NULL;
	dst = NULL;


	if (is_multicast_ether_addr(dest)) {
	if (is_multicast_ether_addr(dest)) {
		br->dev->stats.multicast++;
		mdst = br_mdb_get(br, skb);
		if (mdst || BR_INPUT_SKB_CB(skb)->mrouters_only) {
			if ((mdst && !hlist_unhashed(&mdst->mglist)) ||
			    br_multicast_is_router(br))
				skb2 = skb;
			br_multicast_forward(mdst, skb, skb2);
			skb = NULL;
			if (!skb2)
				goto out;
		} else
			skb2 = skb;
			skb2 = skb;

		br->dev->stats.multicast++;
	} else if ((dst = __br_fdb_get(br, dest)) && dst->is_local) {
	} else if ((dst = __br_fdb_get(br, dest)) && dst->is_local) {
		skb2 = skb;
		skb2 = skb;
		/* Do not forward the packet since it's local. */
		/* Do not forward the packet since it's local. */