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(-)
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);