[10/12] batman-adv: Adding unicast_safe packet reception

Message ID 1299086321-25116-11-git-send-email-linus.luessing@ascom.ch (mailing list archive)
State Rejected, archived
Headers

Commit Message

Linus Lüssing March 2, 2011, 5:18 p.m. UTC
  With this commit unicast_safe packets generated by a node in redundant
bonding mode will be processed on reception. It is being transformed
back to a normal unicast packet if the packet is for the node itself or
if redundant bonding mode is deactivated on this node. Otherwise it is
being passed on as is to the routing functions.

Signed-off-by: Linus Lüssing <linus.luessing@ascom.ch>
---
 hard-interface.c |    5 ++++
 routing.c        |   60 ++++++++++++++++++++++++++++++++++++++++++++++++++---
 routing.h        |    1 +
 3 files changed, 62 insertions(+), 4 deletions(-)
  

Patch

diff --git a/hard-interface.c b/hard-interface.c
index b0105e9..7164b1f 100644
--- a/hard-interface.c
+++ b/hard-interface.c
@@ -624,6 +624,11 @@  static int batman_skb_recv(struct sk_buff *skb, struct net_device *dev,
 		ret = recv_ucast_frag_packet(skb, hard_iface);
 		break;
 
+		/* fragmented unicast packet */
+	case BAT_UNICAST_SAFE:
+		ret = recv_ucast_safe_packet(skb, hard_iface);
+		break;
+
 		/* broadcast packet */
 	case BAT_BCAST:
 		ret = recv_bcast_packet(skb, hard_iface);
diff --git a/routing.c b/routing.c
index f17834a..d31a7ad 100644
--- a/routing.c
+++ b/routing.c
@@ -1018,6 +1018,29 @@  out:
 	return ret;
 }
 
+static void unicast_safe_to_unicast(struct sk_buff *skb)
+{
+	struct unicast_packet_safe unicast_packet_safe;
+	struct unicast_packet *unicast_packet;
+
+	unicast_packet_safe = *((struct unicast_packet_safe *)skb->data);
+	unicast_packet = (struct unicast_packet *) skb_pull(skb,
+					sizeof(struct unicast_packet_safe) -
+					sizeof(struct unicast_packet));
+
+	unicast_packet->header = unicast_packet_safe.header;
+	unicast_packet->header.packet_type = BAT_UNICAST;
+	memcpy(unicast_packet->dest, unicast_packet_safe.dest, ETH_ALEN);
+}
+
+static void set_unicast_safe_options(struct bat_priv *bat_priv,
+				struct unicast_packet_safe *unicast_packet)
+{
+	memcpy(unicast_packet->orig, bat_priv->primary_if->net_dev->dev_addr,
+	       ETH_ALEN);
+	unicast_packet->seqno = htonl(atomic_inc_return(&bat_priv->dup_seqno));
+}
+
 static int unicast_to_unicast_safe(struct sk_buff *skb,
 				   struct bat_priv *bat_priv)
 {
@@ -1033,10 +1056,7 @@  static int unicast_to_unicast_safe(struct sk_buff *skb,
 	unicast_packet_safe->header = unicast_packet.header;
 	memcpy(unicast_packet_safe->dest, unicast_packet.dest, ETH_ALEN);
 	unicast_packet_safe->header.packet_type = BAT_UNICAST_SAFE;
-	memcpy(unicast_packet_safe->orig,
-	       bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
-	unicast_packet_safe->seqno =
-				htonl(atomic_inc_return(&bat_priv->dup_seqno));
+	set_unicast_safe_options(bat_priv, unicast_packet_safe);
 
 	return 0;
 }
@@ -1384,6 +1404,38 @@  int recv_ucast_frag_packet(struct sk_buff *skb, struct hard_iface *recv_if)
 	return route_unicast_packet(bonding_mode, skb, recv_if, orig_node);
 }
 
+int recv_ucast_safe_packet(struct sk_buff *skb, struct hard_iface *recv_if)
+{
+	struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface);
+	struct unicast_packet_safe *unicast_packet;
+	struct orig_node *orig_node;
+	int hdr_size = sizeof(struct unicast_packet);
+	int bonding_mode;
+
+	if (check_unicast_packet(skb, hdr_size) < 0)
+		return NET_RX_DROP;
+
+	unicast_packet = (struct unicast_packet_safe *)skb->data;
+
+	/* packet for me */
+	if (is_my_mac(unicast_packet->dest)) {
+		unicast_safe_to_unicast(skb);
+
+		interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size);
+		return NET_RX_SUCCESS;
+	}
+
+	bonding_mode = atomic_read(&bat_priv->bonding) <<
+			atomic_read(&bat_priv->red_bonding);
+
+	if (bonding_mode != REDUNDANT_BONDING)
+		unicast_safe_to_unicast(skb);
+	else
+		set_unicast_safe_options(bat_priv, unicast_packet);
+
+	orig_node = hash_find_orig(bat_priv, unicast_packet->dest);
+	return route_unicast_packet(bonding_mode, skb, recv_if, orig_node);
+}
 
 int recv_bcast_packet(struct sk_buff *skb, struct hard_iface *recv_if)
 {
diff --git a/routing.h b/routing.h
index 1530c6d..8608ac3 100644
--- a/routing.h
+++ b/routing.h
@@ -36,6 +36,7 @@  int route_unicast_packet(int bonding_mode, struct sk_buff *skb,
 int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if);
 int recv_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if);
 int recv_ucast_frag_packet(struct sk_buff *skb, struct hard_iface *recv_if);
+int recv_ucast_safe_packet(struct sk_buff *skb, struct hard_iface *recv_if);
 int recv_bcast_packet(struct sk_buff *skb, struct hard_iface *recv_if);
 int recv_vis_packet(struct sk_buff *skb, struct hard_iface *recv_if);
 int recv_bat_packet(struct sk_buff *skb, struct hard_iface *recv_if);