X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=drivers%2Fstaging%2Fbatman-adv%2Frouting.c;h=1b35486349040199d8abe7d9ab1de47ed1863b2f;hb=641ee3f8f4375bde4e216aacd26d286a34efed61;hp=90102631330b883ad1f3df3bc45f3494b7f06d91;hpb=3985c7ce85039adacdf882904ca096f091d39346;p=firefly-linux-kernel-4.4.55.git diff --git a/drivers/staging/batman-adv/routing.c b/drivers/staging/batman-adv/routing.c index 90102631330b..1b3548634904 100644 --- a/drivers/staging/batman-adv/routing.c +++ b/drivers/staging/batman-adv/routing.c @@ -1000,10 +1000,10 @@ int recv_icmp_packet(struct sk_buff *skb, struct batman_if *recv_if) /* find a suitable router for this originator, and use * bonding if possible. */ -struct neigh_node *find_router(struct orig_node *orig_node, +struct neigh_node *find_router(struct bat_priv *bat_priv, + struct orig_node *orig_node, struct batman_if *recv_if) { - struct bat_priv *bat_priv; struct orig_node *primary_orig_node; struct orig_node *router_orig; struct neigh_node *router, *first_candidate, *best_router; @@ -1019,13 +1019,9 @@ struct neigh_node *find_router(struct orig_node *orig_node, /* without bonding, the first node should * always choose the default router. */ - if (!recv_if) - return orig_node->router; - - bat_priv = netdev_priv(recv_if->soft_iface); - bonding_enabled = atomic_read(&bat_priv->bonding_enabled); + bonding_enabled = atomic_read(&bat_priv->bonding); - if (!bonding_enabled) + if ((!recv_if) && (!bonding_enabled)) return orig_node->router; router_orig = orig_node->router->orig_node; @@ -1121,8 +1117,8 @@ static int check_unicast_packet(struct sk_buff *skb, int hdr_size) return 0; } -static int route_unicast_packet(struct sk_buff *skb, - struct batman_if *recv_if, int hdr_size) +int route_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if, + int hdr_size) { struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface); struct orig_node *orig_node; @@ -1132,15 +1128,11 @@ static int route_unicast_packet(struct sk_buff *skb, unsigned long flags; struct unicast_packet *unicast_packet; struct ethhdr *ethhdr = (struct ethhdr *)skb_mac_header(skb); + int ret; + struct sk_buff *new_skb; unicast_packet = (struct unicast_packet *)skb->data; - /* packet for me */ - if (is_my_mac(unicast_packet->dest)) { - interface_rx(recv_if->soft_iface, skb, hdr_size); - return NET_RX_SUCCESS; - } - /* TTL exceeded */ if (unicast_packet->ttl < 2) { pr_debug("Warning - can't forward unicast packet from %pM to " @@ -1154,7 +1146,7 @@ static int route_unicast_packet(struct sk_buff *skb, orig_node = ((struct orig_node *) hash_find(bat_priv->orig_hash, unicast_packet->dest)); - router = find_router(orig_node, recv_if); + router = find_router(bat_priv, orig_node, recv_if); if (!router) { spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags); @@ -1174,7 +1166,28 @@ static int route_unicast_packet(struct sk_buff *skb, return NET_RX_DROP; unicast_packet = (struct unicast_packet *)skb->data; - ethhdr = (struct ethhdr *)skb_mac_header(skb); + + if (unicast_packet->packet_type == BAT_UNICAST && + atomic_read(&bat_priv->fragmentation) && + skb->len > batman_if->net_dev->mtu) + return frag_send_skb(skb, bat_priv, batman_if, + dstaddr); + + if (unicast_packet->packet_type == BAT_UNICAST_FRAG && + 2 * skb->len - hdr_size <= batman_if->net_dev->mtu) { + + ret = frag_reassemble_skb(skb, bat_priv, &new_skb); + + if (ret == NET_RX_DROP) + return NET_RX_DROP; + + /* packet was buffered for late merge */ + if (!new_skb) + return NET_RX_SUCCESS; + + skb = new_skb; + unicast_packet = (struct unicast_packet *)skb->data; + } /* decrement ttl */ unicast_packet->ttl--; @@ -1197,7 +1210,7 @@ int recv_unicast_packet(struct sk_buff *skb, struct batman_if *recv_if) /* packet for me */ if (is_my_mac(unicast_packet->dest)) { - interface_rx(recv_if->soft_iface, skb, hdr_size); + interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size); return NET_RX_SUCCESS; } @@ -1208,10 +1221,9 @@ int recv_ucast_frag_packet(struct sk_buff *skb, struct batman_if *recv_if) { struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface); struct unicast_frag_packet *unicast_packet; - struct orig_node *orig_node; - struct frag_packet_list_entry *tmp_frag_entry; int hdr_size = sizeof(struct unicast_frag_packet); - unsigned long flags; + struct sk_buff *new_skb = NULL; + int ret; if (check_unicast_packet(skb, hdr_size) < 0) return NET_RX_DROP; @@ -1221,44 +1233,17 @@ int recv_ucast_frag_packet(struct sk_buff *skb, struct batman_if *recv_if) /* packet for me */ if (is_my_mac(unicast_packet->dest)) { - spin_lock_irqsave(&bat_priv->orig_hash_lock, flags); - orig_node = ((struct orig_node *) - hash_find(bat_priv->orig_hash, unicast_packet->orig)); + ret = frag_reassemble_skb(skb, bat_priv, &new_skb); - if (!orig_node) { - pr_debug("couldn't find orig node for fragmentation\n"); - spin_unlock_irqrestore(&bat_priv->orig_hash_lock, - flags); + if (ret == NET_RX_DROP) return NET_RX_DROP; - } - orig_node->last_frag_packet = jiffies; - - if (list_empty(&orig_node->frag_list) && - create_frag_buffer(&orig_node->frag_list)) { - spin_unlock_irqrestore(&bat_priv->orig_hash_lock, - flags); - return NET_RX_DROP; - } - - tmp_frag_entry = - search_frag_packet(&orig_node->frag_list, - unicast_packet); - - if (!tmp_frag_entry) { - create_frag_entry(&orig_node->frag_list, skb); - spin_unlock_irqrestore(&bat_priv->orig_hash_lock, - flags); + /* packet was buffered for late merge */ + if (!new_skb) return NET_RX_SUCCESS; - } - - skb = merge_frag_packet(&orig_node->frag_list, - tmp_frag_entry, skb); - spin_unlock_irqrestore(&bat_priv->orig_hash_lock, flags); - if (!skb) - return NET_RX_DROP; - interface_rx(recv_if->soft_iface, skb, hdr_size); + interface_rx(recv_if->soft_iface, new_skb, recv_if, + sizeof(struct unicast_packet)); return NET_RX_SUCCESS; } @@ -1339,7 +1324,7 @@ int recv_bcast_packet(struct sk_buff *skb, struct batman_if *recv_if) add_bcast_packet_to_list(bat_priv, skb); /* broadcast for me */ - interface_rx(recv_if->soft_iface, skb, hdr_size); + interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size); return NET_RX_SUCCESS; }