]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - net/batman-adv/routing.c
Merge tag 'tag-sh-for-4.6' of git://git.libc.org/linux-sh
[karo-tx-linux.git] / net / batman-adv / routing.c
index bcaa7870038b33c6cfb5a1469086b478fc10a29f..4dd646a52f1a16ca297a3cdb1abeff56206df166 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007-2015 B.A.T.M.A.N. contributors:
+/* Copyright (C) 2007-201 B.A.T.M.A.N. contributors:
  *
  * Marek Lindner, Simon Wunderlich
  *
@@ -25,6 +25,7 @@
 #include <linux/etherdevice.h>
 #include <linux/if_ether.h>
 #include <linux/jiffies.h>
+#include <linux/kref.h>
 #include <linux/netdevice.h>
 #include <linux/printk.h>
 #include <linux/rculist.h>
@@ -72,7 +73,7 @@ static void _batadv_update_route(struct batadv_priv *bat_priv,
 
        rcu_read_lock();
        curr_router = rcu_dereference(orig_ifinfo->router);
-       if (curr_router && !atomic_inc_not_zero(&curr_router->refcount))
+       if (curr_router && !kref_get_unless_zero(&curr_router->refcount))
                curr_router = NULL;
        rcu_read_unlock();
 
@@ -97,20 +98,20 @@ static void _batadv_update_route(struct batadv_priv *bat_priv,
        }
 
        if (curr_router)
-               batadv_neigh_node_free_ref(curr_router);
+               batadv_neigh_node_put(curr_router);
 
        /* increase refcount of new best neighbor */
-       if (neigh_node && !atomic_inc_not_zero(&neigh_node->refcount))
+       if (neigh_node && !kref_get_unless_zero(&neigh_node->refcount))
                neigh_node = NULL;
 
        spin_lock_bh(&orig_node->neigh_list_lock);
        rcu_assign_pointer(orig_ifinfo->router, neigh_node);
        spin_unlock_bh(&orig_node->neigh_list_lock);
-       batadv_orig_ifinfo_free_ref(orig_ifinfo);
+       batadv_orig_ifinfo_put(orig_ifinfo);
 
        /* decrease refcount of previous best neighbor */
        if (curr_router)
-               batadv_neigh_node_free_ref(curr_router);
+               batadv_neigh_node_put(curr_router);
 }
 
 /**
@@ -137,27 +138,38 @@ void batadv_update_route(struct batadv_priv *bat_priv,
 
 out:
        if (router)
-               batadv_neigh_node_free_ref(router);
+               batadv_neigh_node_put(router);
 }
 
 /**
- * batadv_window_protected checks whether the host restarted and is in the
+ * batadv_window_protected checks whether the host restarted and is in the
  *  protection time.
+ * @bat_priv: the bat priv with all the soft interface information
+ * @seq_num_diff: difference between the current/received sequence number and
+ *  the last sequence number
+ * @seq_old_max_diff: maximum age of sequence number not considered as restart
+ * @last_reset: jiffies timestamp of the last reset, will be updated when reset
+ *  is detected
+ * @protection_started: is set to true if the protection window was started,
+ *   doesn't change otherwise.
  *
  * Return:
  *  0 if the packet is to be accepted.
  *  1 if the packet is to be ignored.
  */
 int batadv_window_protected(struct batadv_priv *bat_priv, s32 seq_num_diff,
-                           unsigned long *last_reset)
+                           s32 seq_old_max_diff, unsigned long *last_reset,
+                           bool *protection_started)
 {
-       if (seq_num_diff <= -BATADV_TQ_LOCAL_WINDOW_SIZE ||
+       if (seq_num_diff <= -seq_old_max_diff ||
            seq_num_diff >= BATADV_EXPECTED_SEQNO_RANGE) {
                if (!batadv_has_timed_out(*last_reset,
                                          BATADV_RESET_PROTECTION_MS))
                        return 1;
 
                *last_reset = jiffies;
+               if (protection_started)
+                       *protection_started = true;
                batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
                           "old packet received, start protection\n");
        }
@@ -257,9 +269,9 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv,
        }
 out:
        if (primary_if)
-               batadv_hardif_free_ref(primary_if);
+               batadv_hardif_put(primary_if);
        if (orig_node)
-               batadv_orig_node_free_ref(orig_node);
+               batadv_orig_node_put(orig_node);
        return ret;
 }
 
@@ -305,9 +317,9 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv,
 
 out:
        if (primary_if)
-               batadv_hardif_free_ref(primary_if);
+               batadv_hardif_put(primary_if);
        if (orig_node)
-               batadv_orig_node_free_ref(orig_node);
+               batadv_orig_node_put(orig_node);
        return ret;
 }
 
@@ -391,7 +403,7 @@ int batadv_recv_icmp_packet(struct sk_buff *skb,
 
 out:
        if (orig_node)
-               batadv_orig_node_free_ref(orig_node);
+               batadv_orig_node_put(orig_node);
        return ret;
 }
 
@@ -486,14 +498,14 @@ batadv_find_router(struct batadv_priv *bat_priv,
 
        hlist_for_each_entry_rcu(cand, &orig_node->ifinfo_list, list) {
                /* acquire some structures and references ... */
-               if (!atomic_inc_not_zero(&cand->refcount))
+               if (!kref_get_unless_zero(&cand->refcount))
                        continue;
 
                cand_router = rcu_dereference(cand->router);
                if (!cand_router)
                        goto next;
 
-               if (!atomic_inc_not_zero(&cand_router->refcount)) {
+               if (!kref_get_unless_zero(&cand_router->refcount)) {
                        cand_router = NULL;
                        goto next;
                }
@@ -512,8 +524,8 @@ batadv_find_router(struct batadv_priv *bat_priv,
 
                /* mark the first possible candidate */
                if (!first_candidate) {
-                       atomic_inc(&cand_router->refcount);
-                       atomic_inc(&cand->refcount);
+                       kref_get(&cand_router->refcount);
+                       kref_get(&cand->refcount);
                        first_candidate = cand;
                        first_candidate_router = cand_router;
                }
@@ -533,16 +545,16 @@ batadv_find_router(struct batadv_priv *bat_priv,
 next:
                /* free references */
                if (cand_router) {
-                       batadv_neigh_node_free_ref(cand_router);
+                       batadv_neigh_node_put(cand_router);
                        cand_router = NULL;
                }
-               batadv_orig_ifinfo_free_ref(cand);
+               batadv_orig_ifinfo_put(cand);
        }
        rcu_read_unlock();
 
        /* last_bonding_candidate is reset below, remove the old reference. */
        if (orig_node->last_bonding_candidate)
-               batadv_orig_ifinfo_free_ref(orig_node->last_bonding_candidate);
+               batadv_orig_ifinfo_put(orig_node->last_bonding_candidate);
 
        /* After finding candidates, handle the three cases:
         * 1) there is a next candidate, use that
@@ -550,17 +562,17 @@ next:
         * 3) there is no candidate at all, return the default router
         */
        if (next_candidate) {
-               batadv_neigh_node_free_ref(router);
+               batadv_neigh_node_put(router);
 
                /* remove references to first candidate, we don't need it. */
                if (first_candidate) {
-                       batadv_neigh_node_free_ref(first_candidate_router);
-                       batadv_orig_ifinfo_free_ref(first_candidate);
+                       batadv_neigh_node_put(first_candidate_router);
+                       batadv_orig_ifinfo_put(first_candidate);
                }
                router = next_candidate_router;
                orig_node->last_bonding_candidate = next_candidate;
        } else if (first_candidate) {
-               batadv_neigh_node_free_ref(router);
+               batadv_neigh_node_put(router);
 
                /* refcounting has already been done in the loop above. */
                router = first_candidate_router;
@@ -637,7 +649,7 @@ static int batadv_route_unicast_packet(struct sk_buff *skb,
 
 out:
        if (orig_node)
-               batadv_orig_node_free_ref(orig_node);
+               batadv_orig_node_put(orig_node);
        return ret;
 }
 
@@ -690,9 +702,9 @@ batadv_reroute_unicast_packet(struct batadv_priv *bat_priv,
        ret = true;
 out:
        if (primary_if)
-               batadv_hardif_free_ref(primary_if);
+               batadv_hardif_put(primary_if);
        if (orig_node)
-               batadv_orig_node_free_ref(orig_node);
+               batadv_orig_node_put(orig_node);
 
        return ret;
 }
@@ -756,7 +768,7 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
                        return 0;
 
                curr_ttvn = (u8)atomic_read(&orig_node->last_ttvn);
-               batadv_orig_node_free_ref(orig_node);
+               batadv_orig_node_put(orig_node);
        }
 
        /* check if the TTVN contained in the packet is fresher than what the
@@ -796,7 +808,7 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv,
 
        ether_addr_copy(unicast_packet->dest, primary_if->net_dev->dev_addr);
 
-       batadv_hardif_free_ref(primary_if);
+       batadv_hardif_put(primary_if);
 
        unicast_packet->ttvn = curr_ttvn;
 
@@ -896,7 +908,7 @@ int batadv_recv_unicast_packet(struct sk_buff *skb,
 
 rx_success:
                if (orig_node)
-                       batadv_orig_node_free_ref(orig_node);
+                       batadv_orig_node_put(orig_node);
 
                return NET_RX_SUCCESS;
        }
@@ -1007,7 +1019,7 @@ int batadv_recv_frag_packet(struct sk_buff *skb,
 
 out:
        if (orig_node_src)
-               batadv_orig_node_free_ref(orig_node_src);
+               batadv_orig_node_put(orig_node_src);
 
        return ret;
 }
@@ -1068,7 +1080,8 @@ int batadv_recv_bcast_packet(struct sk_buff *skb,
 
        /* check whether the packet is old and the host just restarted. */
        if (batadv_window_protected(bat_priv, seq_diff,
-                                   &orig_node->bcast_seqno_reset))
+                                   BATADV_BCAST_MAX_AGE,
+                                   &orig_node->bcast_seqno_reset, NULL))
                goto spin_unlock;
 
        /* mark broadcast in flood history, update window position
@@ -1111,6 +1124,6 @@ spin_unlock:
        spin_unlock_bh(&orig_node->bcast_seqno_lock);
 out:
        if (orig_node)
-               batadv_orig_node_free_ref(orig_node);
+               batadv_orig_node_put(orig_node);
        return ret;
 }