[15/19] batman-adv: Receive multicast data packets BAT_MCAST

Message ID 1295659302-7171-16-git-send-email-linus.luessing@saxnet.de (mailing list archive)
State Superseded, archived
Headers

Commit Message

Linus Lüssing Jan. 22, 2011, 1:21 a.m. UTC
  This patch adds the forwarding of multicast data packets to the local
soft interface if this receiving node is a member of the same multicast
group as specified in the multicast packet.

Signed-off-by: Linus Lüssing <linus.luessing@saxnet.de>
---
 hard-interface.c |    5 +++++
 routing.c        |   29 +++++++++++++++++++++++++++++
 routing.h        |    1 +
 3 files changed, 35 insertions(+), 0 deletions(-)
  

Patch

diff --git a/batman-adv/hard-interface.c b/batman-adv/hard-interface.c
index f478c4b..a535e09 100644
--- a/batman-adv/hard-interface.c
+++ b/batman-adv/hard-interface.c
@@ -624,6 +624,11 @@  int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
 		ret = recv_bcast_packet(skb, batman_if);
 		break;
 
+		/* multicast packet */
+	case BAT_MCAST:
+		ret = recv_mcast_packet(skb, batman_if);
+		break;
+
 		/* multicast tracker packet */
 	case BAT_MCAST_TRACKER:
 		ret = recv_mcast_tracker_packet(skb, batman_if);
diff --git a/batman-adv/routing.c b/batman-adv/routing.c
index 9482db2..b5559c0 100644
--- a/batman-adv/routing.c
+++ b/batman-adv/routing.c
@@ -1510,6 +1510,35 @@  out:
 	return ret;
 }
 
+int recv_mcast_packet(struct sk_buff *skb, struct batman_if *recv_if)
+{
+	struct ethhdr *ethhdr;
+	MC_LIST *mc_entry;
+	int ret = 1;
+	int hdr_size = sizeof(struct mcast_packet);
+
+	/* multicast data packets might be received via unicast or broadcast */
+	if (check_unicast_packet(skb, hdr_size) < 0 &&
+	    check_broadcast_packet(skb, hdr_size) < 0)
+		return NET_RX_DROP;
+
+	ethhdr = (struct ethhdr *)(skb->data + sizeof(struct mcast_packet));
+
+	/* multicast for me? */
+	netif_addr_lock_bh(recv_if->soft_iface);
+	netdev_for_each_mc_addr(mc_entry, recv_if->soft_iface) {
+		ret = memcmp(mc_entry->MC_LIST_ADDR, ethhdr->h_dest, ETH_ALEN);
+		if (!ret)
+			break;
+	}
+	netif_addr_unlock_bh(recv_if->soft_iface);
+
+	if (!ret)
+		interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size);
+
+	return NET_RX_SUCCESS;
+}
+
 int recv_mcast_tracker_packet(struct sk_buff *skb, struct batman_if *recv_if)
 {
 	struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
diff --git a/batman-adv/routing.h b/batman-adv/routing.h
index 0fad12a..722d837 100644
--- a/batman-adv/routing.h
+++ b/batman-adv/routing.h
@@ -38,6 +38,7 @@  int recv_icmp_packet(struct sk_buff *skb, struct batman_if *recv_if);
 int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if);
 int recv_ucast_frag_packet(struct sk_buff *skb, struct batman_if *recv_if);
 int recv_bcast_packet(struct sk_buff *skb, struct batman_if *recv_if);
+int recv_mcast_packet(struct sk_buff *skb, struct batman_if *recv_if);
 int recv_mcast_tracker_packet(struct sk_buff *skb, struct batman_if *recv_if);
 int recv_vis_packet(struct sk_buff *skb, struct batman_if *recv_if);
 int recv_bat_packet(struct sk_buff *skb, struct batman_if *recv_if);