From 551586292b39da6e4fbfbb5b96b57b68decfdab9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20L=C3=BCssing?= Date: Mon, 14 Mar 2011 22:43:27 +0000 Subject: batman-adv: Move bonding / iface alternating router search to own functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This decreases the size of find_router() by outsourcing the router search for the bonding and interface alternating modes to their own sub functions. This shall make it easier to keep track of the correct refcounting later. Signed-off-by: Linus Lüssing Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann --- net/batman-adv/routing.c | 180 +++++++++++++++++++++++++++-------------------- 1 file changed, 105 insertions(+), 75 deletions(-) (limited to 'net/batman-adv') diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index c172f5d0e05a..f212abe745bc 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -1092,6 +1092,106 @@ out: return ret; } +/* In the bonding case, send the packets in a round + * robin fashion over the remaining interfaces. + * + * This method rotates the bonding list and increases the + * returned router's refcount. */ +static struct neigh_node *find_bond_router(struct orig_node *primary_orig, + struct hard_iface *recv_if) +{ + struct neigh_node *tmp_neigh_node; + struct neigh_node *router = NULL, *first_candidate = NULL; + + rcu_read_lock(); + list_for_each_entry_rcu(tmp_neigh_node, &primary_orig->bond_list, + bonding_list) { + if (!first_candidate) + first_candidate = tmp_neigh_node; + + /* recv_if == NULL on the first node. */ + if (tmp_neigh_node->if_incoming == recv_if) + continue; + + if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) + continue; + + router = tmp_neigh_node; + break; + } + + /* use the first candidate if nothing was found. */ + if (!router && first_candidate && + atomic_inc_not_zero(&first_candidate->refcount)) + router = first_candidate; + + if (!router) + goto out; + + /* selected should point to the next element + * after the current router */ + spin_lock_bh(&primary_orig->neigh_list_lock); + /* this is a list_move(), which unfortunately + * does not exist as rcu version */ + list_del_rcu(&primary_orig->bond_list); + list_add_rcu(&primary_orig->bond_list, + &router->bonding_list); + spin_unlock_bh(&primary_orig->neigh_list_lock); + +out: + rcu_read_unlock(); + return router; +} + +/* Interface Alternating: Use the best of the + * remaining candidates which are not using + * this interface. + * + * Increases the returned router's refcount */ +static struct neigh_node *find_ifalter_router(struct orig_node *primary_orig, + struct hard_iface *recv_if) +{ + struct neigh_node *tmp_neigh_node; + struct neigh_node *router = NULL, *first_candidate = NULL; + + rcu_read_lock(); + list_for_each_entry_rcu(tmp_neigh_node, &primary_orig->bond_list, + bonding_list) { + if (!first_candidate) + first_candidate = tmp_neigh_node; + + /* recv_if == NULL on the first node. */ + if (tmp_neigh_node->if_incoming == recv_if) + continue; + + if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) + continue; + + /* if we don't have a router yet + * or this one is better, choose it. */ + if ((!router) || + (tmp_neigh_node->tq_avg > router->tq_avg)) { + /* decrement refcount of + * previously selected router */ + if (router) + neigh_node_free_ref(router); + + router = tmp_neigh_node; + atomic_inc_not_zero(&router->refcount); + } + + neigh_node_free_ref(tmp_neigh_node); + } + + /* use the first candidate if nothing was found. */ + if (!router && first_candidate && + atomic_inc_not_zero(&first_candidate->refcount)) + router = first_candidate; + + rcu_read_unlock(); + return router; +} + /* find a suitable router for this originator, and use * bonding if possible. increases the found neighbors * refcount.*/ @@ -1101,7 +1201,7 @@ struct neigh_node *find_router(struct bat_priv *bat_priv, { struct orig_node *primary_orig_node; struct orig_node *router_orig; - struct neigh_node *router, *first_candidate, *tmp_neigh_node; + struct neigh_node *router; static uint8_t zero_mac[ETH_ALEN] = {0, 0, 0, 0, 0, 0}; int bonding_enabled; @@ -1157,82 +1257,12 @@ struct neigh_node *find_router(struct bat_priv *bat_priv, * in. */ neigh_node_free_ref(router); - first_candidate = NULL; - router = NULL; - - if (bonding_enabled) { - /* in the bonding case, send the packets in a round - * robin fashion over the remaining interfaces. */ - - list_for_each_entry_rcu(tmp_neigh_node, - &primary_orig_node->bond_list, bonding_list) { - if (!first_candidate) - first_candidate = tmp_neigh_node; - /* recv_if == NULL on the first node. */ - if (tmp_neigh_node->if_incoming != recv_if && - atomic_inc_not_zero(&tmp_neigh_node->refcount)) { - router = tmp_neigh_node; - break; - } - } - - /* use the first candidate if nothing was found. */ - if (!router && first_candidate && - atomic_inc_not_zero(&first_candidate->refcount)) - router = first_candidate; - if (!router) { - rcu_read_unlock(); - return NULL; - } - - /* selected should point to the next element - * after the current router */ - spin_lock_bh(&primary_orig_node->neigh_list_lock); - /* this is a list_move(), which unfortunately - * does not exist as rcu version */ - list_del_rcu(&primary_orig_node->bond_list); - list_add_rcu(&primary_orig_node->bond_list, - &router->bonding_list); - spin_unlock_bh(&primary_orig_node->neigh_list_lock); - - } else { - /* if bonding is disabled, use the best of the - * remaining candidates which are not using - * this interface. */ - list_for_each_entry_rcu(tmp_neigh_node, - &primary_orig_node->bond_list, bonding_list) { - if (!first_candidate) - first_candidate = tmp_neigh_node; - - /* recv_if == NULL on the first node. */ - if (tmp_neigh_node->if_incoming == recv_if) - continue; - - if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) - continue; - - /* if we don't have a router yet - * or this one is better, choose it. */ - if ((!router) || - (tmp_neigh_node->tq_avg > router->tq_avg)) { - /* decrement refcount of - * previously selected router */ - if (router) - neigh_node_free_ref(router); - - router = tmp_neigh_node; - atomic_inc_not_zero(&router->refcount); - } - - neigh_node_free_ref(tmp_neigh_node); - } + if (bonding_enabled) + router = find_bond_router(primary_orig_node, recv_if); + else + router = find_ifalter_router(primary_orig_node, recv_if); - /* use the first candidate if nothing was found. */ - if (!router && first_candidate && - atomic_inc_not_zero(&first_candidate->refcount)) - router = first_candidate; - } return_router: rcu_read_unlock(); return router; -- cgit v1.2.3 From 4c804850572f70a2350e4d1e79d6659392b07733 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20L=C3=BCssing?= Date: Mon, 14 Mar 2011 22:43:30 +0000 Subject: batman-adv: Make gateway_get_selected type safe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the return value explicit instead of (void *). Signed-off-by: Linus Lüssing Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann --- net/batman-adv/gateway_client.c | 2 +- net/batman-adv/gateway_client.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'net/batman-adv') diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index 3cc43558cf9c..27b87add044b 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c @@ -42,7 +42,7 @@ static void gw_node_free_ref(struct gw_node *gw_node) call_rcu(&gw_node->rcu, gw_node_free_rcu); } -void *gw_get_selected(struct bat_priv *bat_priv) +struct orig_node *gw_get_selected(struct bat_priv *bat_priv) { struct gw_node *curr_gateway_tmp; struct orig_node *orig_node = NULL; diff --git a/net/batman-adv/gateway_client.h b/net/batman-adv/gateway_client.h index 2aa439124ee3..97c31d178163 100644 --- a/net/batman-adv/gateway_client.h +++ b/net/batman-adv/gateway_client.h @@ -24,7 +24,7 @@ void gw_deselect(struct bat_priv *bat_priv); void gw_election(struct bat_priv *bat_priv); -void *gw_get_selected(struct bat_priv *bat_priv); +struct orig_node *gw_get_selected(struct bat_priv *bat_priv); void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node); void gw_node_update(struct bat_priv *bat_priv, struct orig_node *orig_node, uint8_t new_gwflags); -- cgit v1.2.3 From 57f0c07c4d0da8bcc23e21c330fe9c7c5cf776b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20L=C3=BCssing?= Date: Mon, 14 Mar 2011 22:43:33 +0000 Subject: batman-adv: Simplify gw_check_election(), use gw_get_selected() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gw_get_selected() can get us the desired orig_node directly, therefore reusing that function in gw_check_election(). Signed-off-by: Linus Lüssing Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann --- net/batman-adv/gateway_client.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'net/batman-adv') diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index 27b87add044b..879ac1594869 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c @@ -23,6 +23,7 @@ #include "gateway_client.h" #include "gateway_common.h" #include "hard-interface.h" +#include "originator.h" #include #include #include @@ -203,28 +204,25 @@ void gw_election(struct bat_priv *bat_priv) void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node) { - struct gw_node *curr_gateway_tmp; + struct orig_node *curr_gw_orig; uint8_t gw_tq_avg, orig_tq_avg; - rcu_read_lock(); - curr_gateway_tmp = rcu_dereference(bat_priv->curr_gw); - if (!curr_gateway_tmp) - goto out_rcu; + curr_gw_orig = gw_get_selected(bat_priv); + if (!curr_gw_orig) + goto deselect; - if (!curr_gateway_tmp->orig_node) - goto deselect_rcu; - - if (!curr_gateway_tmp->orig_node->router) + rcu_read_lock(); + if (!curr_gw_orig->router) goto deselect_rcu; /* this node already is the gateway */ - if (curr_gateway_tmp->orig_node == orig_node) + if (curr_gw_orig == orig_node) goto out_rcu; if (!orig_node->router) goto out_rcu; - gw_tq_avg = curr_gateway_tmp->orig_node->router->tq_avg; + gw_tq_avg = curr_gw_orig->router->tq_avg; rcu_read_unlock(); orig_tq_avg = orig_node->router->tq_avg; @@ -255,6 +253,9 @@ deselect_rcu: deselect: gw_deselect(bat_priv); out: + if (curr_gw_orig) + orig_node_free_ref(curr_gw_orig); + return; } -- cgit v1.2.3 From e1a5382f978b67b5cc36eec65e6046730ce07714 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20L=C3=BCssing?= Date: Mon, 14 Mar 2011 22:43:37 +0000 Subject: batman-adv: Make orig_node->router an rcu protected pointer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The rcu protected macros rcu_dereference() and rcu_assign_pointer() for the orig_node->router need to be used, as well as spin/rcu locking. Otherwise we might end up using a router pointer pointing to already freed memory. Therefore this commit introduces the safe getter method orig_node_get_router(). Signed-off-by: Linus Lüssing Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann --- net/batman-adv/gateway_client.c | 80 ++++++++++------- net/batman-adv/icmp_socket.c | 18 +--- net/batman-adv/originator.c | 37 ++++++-- net/batman-adv/originator.h | 1 + net/batman-adv/routing.c | 194 +++++++++++++++++++--------------------- net/batman-adv/send.c | 19 ++-- net/batman-adv/types.h | 4 +- net/batman-adv/vis.c | 91 ++++++++++--------- 8 files changed, 232 insertions(+), 212 deletions(-) (limited to 'net/batman-adv') diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index 879ac1594869..42a8a7ba06e6 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c @@ -98,6 +98,7 @@ void gw_election(struct bat_priv *bat_priv) { struct hlist_node *node; struct gw_node *gw_node, *curr_gw, *curr_gw_tmp = NULL; + struct neigh_node *router; uint8_t max_tq = 0; uint32_t max_gw_factor = 0, tmp_gw_factor = 0; int down, up; @@ -133,10 +134,11 @@ void gw_election(struct bat_priv *bat_priv) } hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) { - if (!gw_node->orig_node->router) + if (gw_node->deleted) continue; - if (gw_node->deleted) + router = orig_node_get_router(gw_node->orig_node); + if (!router) continue; switch (atomic_read(&bat_priv->gw_sel_class)) { @@ -144,15 +146,14 @@ void gw_election(struct bat_priv *bat_priv) gw_bandwidth_to_kbit(gw_node->orig_node->gw_flags, &down, &up); - tmp_gw_factor = (gw_node->orig_node->router->tq_avg * - gw_node->orig_node->router->tq_avg * + tmp_gw_factor = (router->tq_avg * router->tq_avg * down * 100 * 100) / (TQ_LOCAL_WINDOW_SIZE * TQ_LOCAL_WINDOW_SIZE * 64); if ((tmp_gw_factor > max_gw_factor) || ((tmp_gw_factor == max_gw_factor) && - (gw_node->orig_node->router->tq_avg > max_tq))) + (router->tq_avg > max_tq))) curr_gw_tmp = gw_node; break; @@ -164,19 +165,25 @@ void gw_election(struct bat_priv *bat_priv) * soon as a better gateway appears which has * $routing_class more tq points) **/ - if (gw_node->orig_node->router->tq_avg > max_tq) + if (router->tq_avg > max_tq) curr_gw_tmp = gw_node; break; } - if (gw_node->orig_node->router->tq_avg > max_tq) - max_tq = gw_node->orig_node->router->tq_avg; + if (router->tq_avg > max_tq) + max_tq = router->tq_avg; if (tmp_gw_factor > max_gw_factor) max_gw_factor = tmp_gw_factor; + + neigh_node_free_ref(router); } if (curr_gw != curr_gw_tmp) { + router = orig_node_get_router(curr_gw_tmp->orig_node); + if (!router) + goto out; + if ((curr_gw) && (!curr_gw_tmp)) bat_dbg(DBG_BATMAN, bat_priv, "Removing selected gateway - " @@ -187,45 +194,47 @@ void gw_election(struct bat_priv *bat_priv) "(gw_flags: %i, tq: %i)\n", curr_gw_tmp->orig_node->orig, curr_gw_tmp->orig_node->gw_flags, - curr_gw_tmp->orig_node->router->tq_avg); + router->tq_avg); else bat_dbg(DBG_BATMAN, bat_priv, "Changing route to gateway %pM " "(gw_flags: %i, tq: %i)\n", curr_gw_tmp->orig_node->orig, curr_gw_tmp->orig_node->gw_flags, - curr_gw_tmp->orig_node->router->tq_avg); + router->tq_avg); + neigh_node_free_ref(router); gw_select(bat_priv, curr_gw_tmp); } +out: rcu_read_unlock(); } void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node) { struct orig_node *curr_gw_orig; + struct neigh_node *router_gw = NULL, *router_orig = NULL; uint8_t gw_tq_avg, orig_tq_avg; curr_gw_orig = gw_get_selected(bat_priv); if (!curr_gw_orig) goto deselect; - rcu_read_lock(); - if (!curr_gw_orig->router) - goto deselect_rcu; + router_gw = orig_node_get_router(curr_gw_orig); + if (!router_gw) + goto deselect; /* this node already is the gateway */ if (curr_gw_orig == orig_node) - goto out_rcu; - - if (!orig_node->router) - goto out_rcu; + goto out; - gw_tq_avg = curr_gw_orig->router->tq_avg; - rcu_read_unlock(); + router_orig = orig_node_get_router(orig_node); + if (!router_orig) + goto out; - orig_tq_avg = orig_node->router->tq_avg; + gw_tq_avg = router_gw->tq_avg; + orig_tq_avg = router_orig->tq_avg; /* the TQ value has to be better */ if (orig_tq_avg < gw_tq_avg) @@ -243,18 +252,16 @@ void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node) "Restarting gateway selection: better gateway found (tq curr: " "%i, tq new: %i)\n", gw_tq_avg, orig_tq_avg); - goto deselect; -out_rcu: - rcu_read_unlock(); - goto out; -deselect_rcu: - rcu_read_unlock(); deselect: gw_deselect(bat_priv); out: if (curr_gw_orig) orig_node_free_ref(curr_gw_orig); + if (router_gw) + neigh_node_free_ref(router_gw); + if (router_orig) + neigh_node_free_ref(router_orig); return; } @@ -362,23 +369,30 @@ void gw_node_purge(struct bat_priv *bat_priv) spin_unlock_bh(&bat_priv->gw_list_lock); } +/** + * fails if orig_node has no router + */ static int _write_buffer_text(struct bat_priv *bat_priv, struct seq_file *seq, struct gw_node *gw_node) { struct gw_node *curr_gw; - int down, up, ret; + struct neigh_node *router; + int down, up, ret = -1; gw_bandwidth_to_kbit(gw_node->orig_node->gw_flags, &down, &up); + router = orig_node_get_router(gw_node->orig_node); + if (!router) + goto out; + rcu_read_lock(); curr_gw = rcu_dereference(bat_priv->curr_gw); ret = seq_printf(seq, "%s %pM (%3i) %pM [%10s]: %3i - %i%s/%i%s\n", (curr_gw == gw_node ? "=>" : " "), gw_node->orig_node->orig, - gw_node->orig_node->router->tq_avg, - gw_node->orig_node->router->addr, - gw_node->orig_node->router->if_incoming->net_dev->name, + router->tq_avg, router->addr, + router->if_incoming->net_dev->name, gw_node->orig_node->gw_flags, (down > 2048 ? down / 1024 : down), (down > 2048 ? "MBit" : "KBit"), @@ -386,6 +400,8 @@ static int _write_buffer_text(struct bat_priv *bat_priv, (up > 2048 ? "MBit" : "KBit")); rcu_read_unlock(); + neigh_node_free_ref(router); +out: return ret; } @@ -423,10 +439,10 @@ int gw_client_seq_print_text(struct seq_file *seq, void *offset) if (gw_node->deleted) continue; - if (!gw_node->orig_node->router) + /* fails if orig_node has no router */ + if (_write_buffer_text(bat_priv, seq, gw_node) < 0) continue; - _write_buffer_text(bat_priv, seq, gw_node); gw_count++; } rcu_read_unlock(); diff --git a/net/batman-adv/icmp_socket.c b/net/batman-adv/icmp_socket.c index 34ce56c358e5..49079c254476 100644 --- a/net/batman-adv/icmp_socket.c +++ b/net/batman-adv/icmp_socket.c @@ -218,23 +218,13 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE) goto dst_unreach; - rcu_read_lock(); orig_node = orig_hash_find(bat_priv, icmp_packet->dst); - if (!orig_node) - goto unlock; - - neigh_node = orig_node->router; + goto dst_unreach; + neigh_node = orig_node_get_router(orig_node); if (!neigh_node) - goto unlock; - - if (!atomic_inc_not_zero(&neigh_node->refcount)) { - neigh_node = NULL; - goto unlock; - } - - rcu_read_unlock(); + goto dst_unreach; if (!neigh_node->if_incoming) goto dst_unreach; @@ -252,8 +242,6 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); goto out; -unlock: - rcu_read_unlock(); dst_unreach: icmp_packet->msg_type = DESTINATION_UNREACHABLE; bat_socket_add_packet(socket_client, icmp_packet, packet_len); diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index 0b9133022d2d..b4cfe3686155 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -70,6 +70,21 @@ void neigh_node_free_ref(struct neigh_node *neigh_node) call_rcu(&neigh_node->rcu, neigh_node_free_rcu); } +/* increases the refcounter of a found router */ +struct neigh_node *orig_node_get_router(struct orig_node *orig_node) +{ + struct neigh_node *router; + + rcu_read_lock(); + router = rcu_dereference(orig_node->router); + + if (router && !atomic_inc_not_zero(&router->refcount)) + router = NULL; + + rcu_read_unlock(); + return router; +} + struct neigh_node *create_neighbor(struct orig_node *orig_node, struct orig_node *orig_neigh_node, uint8_t *neigh, @@ -390,7 +405,7 @@ int orig_seq_print_text(struct seq_file *seq, void *offset) struct hlist_node *node, *node_tmp; struct hlist_head *head; struct orig_node *orig_node; - struct neigh_node *neigh_node; + struct neigh_node *neigh_node, *neigh_node_tmp; int batman_count = 0; int last_seen_secs; int last_seen_msecs; @@ -421,37 +436,41 @@ int orig_seq_print_text(struct seq_file *seq, void *offset) rcu_read_lock(); hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) { - if (!orig_node->router) + neigh_node = orig_node_get_router(orig_node); + if (!neigh_node) continue; - if (orig_node->router->tq_avg == 0) - continue; + if (neigh_node->tq_avg == 0) + goto next; last_seen_secs = jiffies_to_msecs(jiffies - orig_node->last_valid) / 1000; last_seen_msecs = jiffies_to_msecs(jiffies - orig_node->last_valid) % 1000; - neigh_node = orig_node->router; seq_printf(seq, "%pM %4i.%03is (%3i) %pM [%10s]:", orig_node->orig, last_seen_secs, last_seen_msecs, neigh_node->tq_avg, neigh_node->addr, neigh_node->if_incoming->net_dev->name); - hlist_for_each_entry_rcu(neigh_node, node_tmp, + hlist_for_each_entry_rcu(neigh_node_tmp, node_tmp, &orig_node->neigh_list, list) { - seq_printf(seq, " %pM (%3i)", neigh_node->addr, - neigh_node->tq_avg); + seq_printf(seq, " %pM (%3i)", + neigh_node_tmp->addr, + neigh_node_tmp->tq_avg); } seq_printf(seq, "\n"); batman_count++; + +next: + neigh_node_free_ref(neigh_node); } rcu_read_unlock(); } - if ((batman_count == 0)) + if (batman_count == 0) seq_printf(seq, "No batman nodes in range ...\n"); return 0; diff --git a/net/batman-adv/originator.h b/net/batman-adv/originator.h index 5cc011057da1..e1d641f27aa9 100644 --- a/net/batman-adv/originator.h +++ b/net/batman-adv/originator.h @@ -34,6 +34,7 @@ struct neigh_node *create_neighbor(struct orig_node *orig_node, uint8_t *neigh, struct hard_iface *if_incoming); void neigh_node_free_ref(struct neigh_node *neigh_node); +struct neigh_node *orig_node_get_router(struct orig_node *orig_node); int orig_seq_print_text(struct seq_file *seq, void *offset); int orig_hash_add_if(struct hard_iface *hard_iface, int max_if_num); int orig_hash_del_if(struct hard_iface *hard_iface, int max_if_num); diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index f212abe745bc..b7d43caaa9c8 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -87,18 +87,20 @@ static void update_route(struct bat_priv *bat_priv, struct neigh_node *neigh_node, unsigned char *hna_buff, int hna_buff_len) { - struct neigh_node *neigh_node_tmp; + struct neigh_node *curr_router; + + curr_router = orig_node_get_router(orig_node); /* route deleted */ - if ((orig_node->router) && (!neigh_node)) { + if ((curr_router) && (!neigh_node)) { bat_dbg(DBG_ROUTES, bat_priv, "Deleting route towards: %pM\n", orig_node->orig); hna_global_del_orig(bat_priv, orig_node, "originator timed out"); - /* route added */ - } else if ((!orig_node->router) && (neigh_node)) { + /* route added */ + } else if ((!curr_router) && (neigh_node)) { bat_dbg(DBG_ROUTES, bat_priv, "Adding route towards: %pM (via %pM)\n", @@ -106,21 +108,29 @@ static void update_route(struct bat_priv *bat_priv, hna_global_add_orig(bat_priv, orig_node, hna_buff, hna_buff_len); - /* route changed */ + /* route changed */ } else { bat_dbg(DBG_ROUTES, bat_priv, "Changing route towards: %pM " "(now via %pM - was via %pM)\n", orig_node->orig, neigh_node->addr, - orig_node->router->addr); + curr_router->addr); } + if (curr_router) + neigh_node_free_ref(curr_router); + + /* increase refcount of new best neighbor */ if (neigh_node && !atomic_inc_not_zero(&neigh_node->refcount)) neigh_node = NULL; - neigh_node_tmp = orig_node->router; - orig_node->router = neigh_node; - if (neigh_node_tmp) - neigh_node_free_ref(neigh_node_tmp); + + spin_lock_bh(&orig_node->neigh_list_lock); + rcu_assign_pointer(orig_node->router, neigh_node); + spin_unlock_bh(&orig_node->neigh_list_lock); + + /* decrease refcount of previous best neighbor */ + if (curr_router) + neigh_node_free_ref(curr_router); } @@ -128,16 +138,23 @@ void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node, struct neigh_node *neigh_node, unsigned char *hna_buff, int hna_buff_len) { + struct neigh_node *router = NULL; if (!orig_node) - return; + goto out; + + router = orig_node_get_router(orig_node); - if (orig_node->router != neigh_node) + if (router != neigh_node) update_route(bat_priv, orig_node, neigh_node, hna_buff, hna_buff_len); /* may be just HNA changed */ else update_HNA(bat_priv, orig_node, hna_buff, hna_buff_len); + +out: + if (router) + neigh_node_free_ref(router); } static int is_bidirectional_neigh(struct orig_node *orig_node, @@ -288,8 +305,8 @@ static void bonding_candidate_add(struct orig_node *orig_node, struct neigh_node *neigh_node) { struct hlist_node *node; - struct neigh_node *tmp_neigh_node; - uint8_t best_tq, interference_candidate = 0; + struct neigh_node *tmp_neigh_node, *router = NULL; + uint8_t interference_candidate = 0; spin_lock_bh(&orig_node->neigh_list_lock); @@ -298,13 +315,12 @@ static void bonding_candidate_add(struct orig_node *orig_node, neigh_node->orig_node->primary_addr)) goto candidate_del; - if (!orig_node->router) + router = orig_node_get_router(orig_node); + if (!router) goto candidate_del; - best_tq = orig_node->router->tq_avg; - /* ... and is good enough to be considered */ - if (neigh_node->tq_avg < best_tq - BONDING_TQ_THRESHOLD) + if (neigh_node->tq_avg < router->tq_avg - BONDING_TQ_THRESHOLD) goto candidate_del; /** @@ -350,7 +366,9 @@ candidate_del: out: spin_unlock_bh(&orig_node->neigh_list_lock); - return; + + if (router) + neigh_node_free_ref(router); } /* copy primary address for bonding */ @@ -373,6 +391,7 @@ static void update_orig(struct bat_priv *bat_priv, char is_duplicate) { struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL; + struct neigh_node *router = NULL; struct orig_node *orig_node_tmp; struct hlist_node *node; int tmp_hna_buff_len; @@ -441,19 +460,18 @@ static void update_orig(struct bat_priv *bat_priv, /* if this neighbor already is our next hop there is nothing * to change */ - if (orig_node->router == neigh_node) + router = orig_node_get_router(orig_node); + if (router == neigh_node) goto update_hna; /* if this neighbor does not offer a better TQ we won't consider it */ - if ((orig_node->router) && - (orig_node->router->tq_avg > neigh_node->tq_avg)) + if (router && (router->tq_avg > neigh_node->tq_avg)) goto update_hna; /* if the TQ is the same and the link not more symetric we * won't consider it either */ - if ((orig_node->router) && - (neigh_node->tq_avg == orig_node->router->tq_avg)) { - orig_node_tmp = orig_node->router->orig_node; + if (router && (neigh_node->tq_avg == router->tq_avg)) { + orig_node_tmp = router->orig_node; spin_lock_bh(&orig_node_tmp->ogm_cnt_lock); bcast_own_sum_orig = orig_node_tmp->bcast_own_sum[if_incoming->if_num]; @@ -474,7 +492,7 @@ static void update_orig(struct bat_priv *bat_priv, goto update_gw; update_hna: - update_routes(bat_priv, orig_node, orig_node->router, + update_routes(bat_priv, orig_node, router, hna_buff, tmp_hna_buff_len); update_gw: @@ -496,6 +514,8 @@ unlock: out: if (neigh_node) neigh_node_free_ref(neigh_node); + if (router) + neigh_node_free_ref(router); } /* checks whether the host restarted and is in the protection time. @@ -603,6 +623,8 @@ void receive_bat_packet(struct ethhdr *ethhdr, struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); struct hard_iface *hard_iface; struct orig_node *orig_neigh_node, *orig_node; + struct neigh_node *router = NULL, *router_router = NULL; + struct neigh_node *orig_neigh_router = NULL; char has_directlink_flag; char is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0; char is_broadcast = 0, is_bidirectional, is_single_hop_neigh; @@ -747,14 +769,15 @@ void receive_bat_packet(struct ethhdr *ethhdr, goto out; } + router = orig_node_get_router(orig_node); + if (router) + router_router = orig_node_get_router(router->orig_node); + /* avoid temporary routing loops */ - if ((orig_node->router) && - (orig_node->router->orig_node->router) && - (compare_eth(orig_node->router->addr, - batman_packet->prev_sender)) && + if (router && router_router && + (compare_eth(router->addr, batman_packet->prev_sender)) && !(compare_eth(batman_packet->orig, batman_packet->prev_sender)) && - (compare_eth(orig_node->router->addr, - orig_node->router->orig_node->router->addr))) { + (compare_eth(router->addr, router_router->addr))) { bat_dbg(DBG_BATMAN, bat_priv, "Drop packet: ignoring all rebroadcast packets that " "may make me loop (sender: %pM)\n", ethhdr->h_source); @@ -769,9 +792,11 @@ void receive_bat_packet(struct ethhdr *ethhdr, if (!orig_neigh_node) goto out; + orig_neigh_router = orig_node_get_router(orig_neigh_node); + /* drop packet if sender is not a direct neighbor and if we * don't route towards it */ - if (!is_single_hop_neigh && (!orig_neigh_node->router)) { + if (!is_single_hop_neigh && (!orig_neigh_router)) { bat_dbg(DBG_BATMAN, bat_priv, "Drop packet: OGM via unknown neighbor!\n"); goto out_neigh; @@ -825,6 +850,13 @@ out_neigh: if ((orig_neigh_node) && (!is_single_hop_neigh)) orig_node_free_ref(orig_neigh_node); out: + if (router) + neigh_node_free_ref(router); + if (router_router) + neigh_node_free_ref(router_router); + if (orig_neigh_router) + neigh_node_free_ref(orig_neigh_router); + orig_node_free_ref(orig_node); } @@ -869,7 +901,7 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv, struct sk_buff *skb, size_t icmp_len) { struct orig_node *orig_node = NULL; - struct neigh_node *neigh_node = NULL; + struct neigh_node *router = NULL; struct icmp_packet_rr *icmp_packet; int ret = NET_RX_DROP; @@ -886,23 +918,13 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv, /* answer echo request (ping) */ /* get routing information */ - rcu_read_lock(); orig_node = orig_hash_find(bat_priv, icmp_packet->orig); - if (!orig_node) - goto unlock; - - neigh_node = orig_node->router; - - if (!neigh_node) - goto unlock; - - if (!atomic_inc_not_zero(&neigh_node->refcount)) { - neigh_node = NULL; - goto unlock; - } + goto out; - rcu_read_unlock(); + router = orig_node_get_router(orig_node); + if (!router) + goto out; /* create a copy of the skb, if needed, to modify it. */ if (skb_cow(skb, sizeof(struct ethhdr)) < 0) @@ -916,15 +938,12 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv, icmp_packet->msg_type = ECHO_REPLY; icmp_packet->ttl = TTL; - send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); + send_skb_packet(skb, router->if_incoming, router->addr); ret = NET_RX_SUCCESS; - goto out; -unlock: - rcu_read_unlock(); out: - if (neigh_node) - neigh_node_free_ref(neigh_node); + if (router) + neigh_node_free_ref(router); if (orig_node) orig_node_free_ref(orig_node); return ret; @@ -934,7 +953,7 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv, struct sk_buff *skb) { struct orig_node *orig_node = NULL; - struct neigh_node *neigh_node = NULL; + struct neigh_node *router = NULL; struct icmp_packet *icmp_packet; int ret = NET_RX_DROP; @@ -952,23 +971,13 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv, goto out; /* get routing information */ - rcu_read_lock(); orig_node = orig_hash_find(bat_priv, icmp_packet->orig); - if (!orig_node) - goto unlock; - - neigh_node = orig_node->router; - - if (!neigh_node) - goto unlock; - - if (!atomic_inc_not_zero(&neigh_node->refcount)) { - neigh_node = NULL; - goto unlock; - } + goto out; - rcu_read_unlock(); + router = orig_node_get_router(orig_node); + if (!router) + goto out; /* create a copy of the skb, if needed, to modify it. */ if (skb_cow(skb, sizeof(struct ethhdr)) < 0) @@ -982,15 +991,12 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv, icmp_packet->msg_type = TTL_EXCEEDED; icmp_packet->ttl = TTL; - send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); + send_skb_packet(skb, router->if_incoming, router->addr); ret = NET_RX_SUCCESS; - goto out; -unlock: - rcu_read_unlock(); out: - if (neigh_node) - neigh_node_free_ref(neigh_node); + if (router) + neigh_node_free_ref(router); if (orig_node) orig_node_free_ref(orig_node); return ret; @@ -1003,7 +1009,7 @@ int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if) struct icmp_packet_rr *icmp_packet; struct ethhdr *ethhdr; struct orig_node *orig_node = NULL; - struct neigh_node *neigh_node = NULL; + struct neigh_node *router = NULL; int hdr_size = sizeof(struct icmp_packet); int ret = NET_RX_DROP; @@ -1050,23 +1056,13 @@ int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if) return recv_icmp_ttl_exceeded(bat_priv, skb); /* get routing information */ - rcu_read_lock(); orig_node = orig_hash_find(bat_priv, icmp_packet->dst); - if (!orig_node) - goto unlock; - - neigh_node = orig_node->router; - - if (!neigh_node) - goto unlock; - - if (!atomic_inc_not_zero(&neigh_node->refcount)) { - neigh_node = NULL; - goto unlock; - } + goto out; - rcu_read_unlock(); + router = orig_node_get_router(orig_node); + if (!router) + goto out; /* create a copy of the skb, if needed, to modify it. */ if (skb_cow(skb, sizeof(struct ethhdr)) < 0) @@ -1078,15 +1074,12 @@ int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if) icmp_packet->ttl--; /* route it */ - send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); + send_skb_packet(skb, router->if_incoming, router->addr); ret = NET_RX_SUCCESS; - goto out; -unlock: - rcu_read_unlock(); out: - if (neigh_node) - neigh_node_free_ref(neigh_node); + if (router) + neigh_node_free_ref(router); if (orig_node) orig_node_free_ref(orig_node); return ret; @@ -1208,7 +1201,8 @@ struct neigh_node *find_router(struct bat_priv *bat_priv, if (!orig_node) return NULL; - if (!orig_node->router) + router = orig_node_get_router(orig_node); + if (!router) return NULL; /* without bonding, the first node should @@ -1217,9 +1211,8 @@ struct neigh_node *find_router(struct bat_priv *bat_priv, rcu_read_lock(); /* select default router to output */ - router = orig_node->router; - router_orig = orig_node->router->orig_node; - if (!router_orig || !atomic_inc_not_zero(&router->refcount)) { + router_orig = router->orig_node; + if (!router_orig) { rcu_read_unlock(); return NULL; } @@ -1251,7 +1244,6 @@ struct neigh_node *find_router(struct bat_priv *bat_priv, if (atomic_read(&primary_orig_node->bond_candidates) < 2) goto return_router; - /* all nodes between should choose a candidate which * is is not on the interface where the packet came * in. */ diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c index d49e54d932af..e78670c3c4b7 100644 --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c @@ -308,6 +308,7 @@ void schedule_forward_packet(struct orig_node *orig_node, struct hard_iface *if_incoming) { struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); + struct neigh_node *router; unsigned char in_tq, in_ttl, tq_avg = 0; unsigned long send_time; @@ -316,6 +317,8 @@ void schedule_forward_packet(struct orig_node *orig_node, return; } + router = orig_node_get_router(orig_node); + in_tq = batman_packet->tq; in_ttl = batman_packet->ttl; @@ -324,20 +327,22 @@ void schedule_forward_packet(struct orig_node *orig_node, /* rebroadcast tq of our best ranking neighbor to ensure the rebroadcast * of our best tq value */ - if ((orig_node->router) && (orig_node->router->tq_avg != 0)) { + if (router && router->tq_avg != 0) { /* rebroadcast ogm of best ranking neighbor as is */ - if (!compare_eth(orig_node->router->addr, ethhdr->h_source)) { - batman_packet->tq = orig_node->router->tq_avg; + if (!compare_eth(router->addr, ethhdr->h_source)) { + batman_packet->tq = router->tq_avg; - if (orig_node->router->last_ttl) - batman_packet->ttl = orig_node->router->last_ttl - - 1; + if (router->last_ttl) + batman_packet->ttl = router->last_ttl - 1; } - tq_avg = orig_node->router->tq_avg; + tq_avg = router->tq_avg; } + if (router) + neigh_node_free_ref(router); + /* apply hop penalty */ batman_packet->tq = hop_penalty(batman_packet->tq, bat_priv); diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 83445cf0cc9f..1854cbb4c1b6 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -67,7 +67,7 @@ struct hard_iface { struct orig_node { uint8_t orig[ETH_ALEN]; uint8_t primary_addr[ETH_ALEN]; - struct neigh_node *router; + struct neigh_node __rcu *router; /* rcu protected pointer */ unsigned long *bcast_own; uint8_t *bcast_own_sum; unsigned long last_valid; @@ -83,7 +83,7 @@ struct orig_node { uint32_t last_bcast_seqno; struct hlist_head neigh_list; struct list_head frag_list; - spinlock_t neigh_list_lock; /* protects neighbor list */ + spinlock_t neigh_list_lock; /* protects neigh_list and router */ atomic_t refcount; struct rcu_head rcu; struct hlist_node hash_entry; diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c index f90212f42082..d4cc4f5399f4 100644 --- a/net/batman-adv/vis.c +++ b/net/batman-adv/vis.c @@ -558,6 +558,7 @@ static int find_best_vis_server(struct bat_priv *bat_priv, struct vis_info *info) { struct hashtable_t *hash = bat_priv->orig_hash; + struct neigh_node *router; struct hlist_node *node; struct hlist_head *head; struct orig_node *orig_node; @@ -571,13 +572,17 @@ static int find_best_vis_server(struct bat_priv *bat_priv, rcu_read_lock(); hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) { - if ((orig_node) && (orig_node->router) && - (orig_node->flags & VIS_SERVER) && - (orig_node->router->tq_avg > best_tq)) { - best_tq = orig_node->router->tq_avg; + router = orig_node_get_router(orig_node); + if (!router) + continue; + + if ((orig_node->flags & VIS_SERVER) && + (router->tq_avg > best_tq)) { + best_tq = router->tq_avg; memcpy(packet->target_orig, orig_node->orig, ETH_ALEN); } + neigh_node_free_ref(router); } rcu_read_unlock(); } @@ -605,7 +610,7 @@ static int generate_vis_packet(struct bat_priv *bat_priv) struct hlist_node *node; struct hlist_head *head; struct orig_node *orig_node; - struct neigh_node *neigh_node; + struct neigh_node *router; struct vis_info *info = (struct vis_info *)bat_priv->my_vis_info; struct vis_packet *packet = (struct vis_packet *)info->skb_packet->data; struct vis_info_entry *entry; @@ -633,30 +638,32 @@ static int generate_vis_packet(struct bat_priv *bat_priv) rcu_read_lock(); hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) { - neigh_node = orig_node->router; - - if (!neigh_node) + router = orig_node_get_router(orig_node); + if (!router) continue; - if (!compare_eth(neigh_node->addr, orig_node->orig)) - continue; + if (!compare_eth(router->addr, orig_node->orig)) + goto next; - if (neigh_node->if_incoming->if_status != IF_ACTIVE) - continue; + if (router->if_incoming->if_status != IF_ACTIVE) + goto next; - if (neigh_node->tq_avg < 1) - continue; + if (router->tq_avg < 1) + goto next; /* fill one entry into buffer. */ entry = (struct vis_info_entry *) skb_put(info->skb_packet, sizeof(*entry)); memcpy(entry->src, - neigh_node->if_incoming->net_dev->dev_addr, + router->if_incoming->net_dev->dev_addr, ETH_ALEN); memcpy(entry->dest, orig_node->orig, ETH_ALEN); - entry->quality = neigh_node->tq_avg; + entry->quality = router->tq_avg; packet->entries++; +next: + neigh_node_free_ref(router); + if (vis_packet_full(info)) goto unlock; } @@ -725,6 +732,7 @@ static void purge_vis_packets(struct bat_priv *bat_priv) static void broadcast_vis_packet(struct bat_priv *bat_priv, struct vis_info *info) { + struct neigh_node *router; struct hashtable_t *hash = bat_priv->orig_hash; struct hlist_node *node; struct hlist_head *head; @@ -745,19 +753,26 @@ static void broadcast_vis_packet(struct bat_priv *bat_priv, rcu_read_lock(); hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) { /* if it's a vis server and reachable, send it. */ - if ((!orig_node) || (!orig_node->router)) - continue; if (!(orig_node->flags & VIS_SERVER)) continue; + + router = orig_node_get_router(orig_node); + if (!router) + continue; + /* don't send it if we already received the packet from - * this node. */ + * this node. */ if (recv_list_is_in(bat_priv, &info->recv_list, - orig_node->orig)) + orig_node->orig)) { + neigh_node_free_ref(router); continue; + } memcpy(packet->target_orig, orig_node->orig, ETH_ALEN); - hard_iface = orig_node->router->if_incoming; - memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); + hard_iface = router->if_incoming; + memcpy(dstaddr, router->addr, ETH_ALEN); + + neigh_node_free_ref(router); skb = skb_clone(info->skb_packet, GFP_ATOMIC); if (skb) @@ -772,45 +787,29 @@ static void unicast_vis_packet(struct bat_priv *bat_priv, struct vis_info *info) { struct orig_node *orig_node; - struct neigh_node *neigh_node = NULL; + struct neigh_node *router = NULL; struct sk_buff *skb; struct vis_packet *packet; packet = (struct vis_packet *)info->skb_packet->data; - rcu_read_lock(); orig_node = orig_hash_find(bat_priv, packet->target_orig); - if (!orig_node) - goto unlock; + goto out; - neigh_node = orig_node->router; - - if (!neigh_node) - goto unlock; - - if (!atomic_inc_not_zero(&neigh_node->refcount)) { - neigh_node = NULL; - goto unlock; - } - - rcu_read_unlock(); + router = orig_node_get_router(orig_node); + if (!router) + goto out; skb = skb_clone(info->skb_packet, GFP_ATOMIC); if (skb) - send_skb_packet(skb, neigh_node->if_incoming, - neigh_node->addr); - - goto out; + send_skb_packet(skb, router->if_incoming, router->addr); -unlock: - rcu_read_unlock(); out: - if (neigh_node) - neigh_node_free_ref(neigh_node); + if (router) + neigh_node_free_ref(router); if (orig_node) orig_node_free_ref(orig_node); - return; } /* only send one vis packet. called from send_vis_packets() */ -- cgit v1.2.3 From 68003903e4eeec5288f074ff0751a381750ceb34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20L=C3=BCssing?= Date: Mon, 14 Mar 2011 22:43:40 +0000 Subject: batman-adv: Protect global TQ window with a spinlock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Linus Lüssing Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann --- net/batman-adv/originator.c | 1 + net/batman-adv/routing.c | 4 ++++ net/batman-adv/types.h | 1 + 3 files changed, 6 insertions(+) (limited to 'net/batman-adv') diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index b4cfe3686155..5b8fe32043da 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -102,6 +102,7 @@ struct neigh_node *create_neighbor(struct orig_node *orig_node, INIT_HLIST_NODE(&neigh_node->list); INIT_LIST_HEAD(&neigh_node->bonding_list); + spin_lock_init(&neigh_node->tq_lock); memcpy(neigh_node->addr, neigh, ETH_ALEN); neigh_node->orig_node = orig_neigh_node; diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index b7d43caaa9c8..f6c642246972 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -415,10 +415,12 @@ static void update_orig(struct bat_priv *bat_priv, if (is_duplicate) continue; + spin_lock_bh(&tmp_neigh_node->tq_lock); ring_buffer_set(tmp_neigh_node->tq_recv, &tmp_neigh_node->tq_index, 0); tmp_neigh_node->tq_avg = ring_buffer_avg(tmp_neigh_node->tq_recv); + spin_unlock_bh(&tmp_neigh_node->tq_lock); } if (!neigh_node) { @@ -443,10 +445,12 @@ static void update_orig(struct bat_priv *bat_priv, orig_node->flags = batman_packet->flags; neigh_node->last_valid = jiffies; + spin_lock_bh(&neigh_node->tq_lock); ring_buffer_set(neigh_node->tq_recv, &neigh_node->tq_index, batman_packet->tq); neigh_node->tq_avg = ring_buffer_avg(neigh_node->tq_recv); + spin_unlock_bh(&neigh_node->tq_lock); if (!is_duplicate) { orig_node->last_ttl = batman_packet->ttl; diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 1854cbb4c1b6..091476df4f0e 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -125,6 +125,7 @@ struct neigh_node { struct rcu_head rcu; struct orig_node *orig_node; struct hard_iface *if_incoming; + spinlock_t tq_lock; /* protects: tq_recv, tq_index */ }; -- cgit v1.2.3 From c4aac1ab9b973798163b34939b522f01e4d28ac9 Mon Sep 17 00:00:00 2001 From: Marek Lindner Date: Wed, 23 Mar 2011 11:24:34 +0100 Subject: batman-adv: concentrate all curr_gw related rcu operations in select/deselect functions Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann --- net/batman-adv/gateway_client.c | 170 +++++++++++++++++++++++----------------- net/batman-adv/gateway_client.h | 2 +- net/batman-adv/unicast.c | 2 +- 3 files changed, 100 insertions(+), 74 deletions(-) (limited to 'net/batman-adv') diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index 42a8a7ba06e6..2acd7a666bda 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c @@ -43,61 +43,75 @@ static void gw_node_free_ref(struct gw_node *gw_node) call_rcu(&gw_node->rcu, gw_node_free_rcu); } -struct orig_node *gw_get_selected(struct bat_priv *bat_priv) +static struct gw_node *gw_get_selected_gw_node(struct bat_priv *bat_priv) { - struct gw_node *curr_gateway_tmp; - struct orig_node *orig_node = NULL; + struct gw_node *gw_node; rcu_read_lock(); - curr_gateway_tmp = rcu_dereference(bat_priv->curr_gw); - if (!curr_gateway_tmp) - goto out; - - orig_node = curr_gateway_tmp->orig_node; - if (!orig_node) + gw_node = rcu_dereference(bat_priv->curr_gw); + if (!gw_node) goto out; - if (!atomic_inc_not_zero(&orig_node->refcount)) - orig_node = NULL; + if (!atomic_inc_not_zero(&gw_node->refcount)) + gw_node = NULL; out: rcu_read_unlock(); - return orig_node; + return gw_node; } -void gw_deselect(struct bat_priv *bat_priv) +struct orig_node *gw_get_selected_orig(struct bat_priv *bat_priv) { struct gw_node *gw_node; + struct orig_node *orig_node = NULL; - spin_lock_bh(&bat_priv->gw_list_lock); - gw_node = rcu_dereference(bat_priv->curr_gw); - rcu_assign_pointer(bat_priv->curr_gw, NULL); - spin_unlock_bh(&bat_priv->gw_list_lock); + gw_node = gw_get_selected_gw_node(bat_priv); + if (!gw_node) + goto out; + + rcu_read_lock(); + orig_node = gw_node->orig_node; + if (!orig_node) + goto unlock; + + if (!atomic_inc_not_zero(&orig_node->refcount)) + orig_node = NULL; +unlock: + rcu_read_unlock(); +out: if (gw_node) gw_node_free_ref(gw_node); + return orig_node; } static void gw_select(struct bat_priv *bat_priv, struct gw_node *new_gw_node) { struct gw_node *curr_gw_node; + spin_lock_bh(&bat_priv->gw_list_lock); + if (new_gw_node && !atomic_inc_not_zero(&new_gw_node->refcount)) new_gw_node = NULL; - spin_lock_bh(&bat_priv->gw_list_lock); - curr_gw_node = rcu_dereference(bat_priv->curr_gw); + curr_gw_node = bat_priv->curr_gw; rcu_assign_pointer(bat_priv->curr_gw, new_gw_node); - spin_unlock_bh(&bat_priv->gw_list_lock); if (curr_gw_node) gw_node_free_ref(curr_gw_node); + + spin_unlock_bh(&bat_priv->gw_list_lock); +} + +void gw_deselect(struct bat_priv *bat_priv) +{ + gw_select(bat_priv, NULL); } void gw_election(struct bat_priv *bat_priv) { struct hlist_node *node; - struct gw_node *gw_node, *curr_gw, *curr_gw_tmp = NULL; + struct gw_node *gw_node, *curr_gw = NULL, *curr_gw_tmp = NULL; struct neigh_node *router; uint8_t max_tq = 0; uint32_t max_gw_factor = 0, tmp_gw_factor = 0; @@ -112,25 +126,17 @@ void gw_election(struct bat_priv *bat_priv) if (atomic_read(&bat_priv->gw_mode) != GW_MODE_CLIENT) return; - rcu_read_lock(); - curr_gw = rcu_dereference(bat_priv->curr_gw); - if (curr_gw) { - rcu_read_unlock(); - return; - } + curr_gw = gw_get_selected_gw_node(bat_priv); + if (!curr_gw) + goto out; + rcu_read_lock(); if (hlist_empty(&bat_priv->gw_list)) { - - if (curr_gw) { - rcu_read_unlock(); - bat_dbg(DBG_BATMAN, bat_priv, - "Removing selected gateway - " - "no gateway in range\n"); - gw_deselect(bat_priv); - } else - rcu_read_unlock(); - - return; + bat_dbg(DBG_BATMAN, bat_priv, + "Removing selected gateway - " + "no gateway in range\n"); + gw_deselect(bat_priv); + goto unlock; } hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) { @@ -182,7 +188,7 @@ void gw_election(struct bat_priv *bat_priv) if (curr_gw != curr_gw_tmp) { router = orig_node_get_router(curr_gw_tmp->orig_node); if (!router) - goto out; + goto unlock; if ((curr_gw) && (!curr_gw_tmp)) bat_dbg(DBG_BATMAN, bat_priv, @@ -207,8 +213,11 @@ void gw_election(struct bat_priv *bat_priv) gw_select(bat_priv, curr_gw_tmp); } -out: +unlock: rcu_read_unlock(); +out: + if (curr_gw) + gw_node_free_ref(curr_gw); } void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node) @@ -217,7 +226,7 @@ void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node) struct neigh_node *router_gw = NULL, *router_orig = NULL; uint8_t gw_tq_avg, orig_tq_avg; - curr_gw_orig = gw_get_selected(bat_priv); + curr_gw_orig = gw_get_selected_orig(bat_priv); if (!curr_gw_orig) goto deselect; @@ -299,7 +308,11 @@ void gw_node_update(struct bat_priv *bat_priv, struct orig_node *orig_node, uint8_t new_gwflags) { struct hlist_node *node; - struct gw_node *gw_node; + struct gw_node *gw_node, *curr_gw; + + curr_gw = gw_get_selected_gw_node(bat_priv); + if (!curr_gw) + goto out; rcu_read_lock(); hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) { @@ -320,22 +333,26 @@ void gw_node_update(struct bat_priv *bat_priv, "Gateway %pM removed from gateway list\n", orig_node->orig); - if (gw_node == rcu_dereference(bat_priv->curr_gw)) { - rcu_read_unlock(); - gw_deselect(bat_priv); - return; - } + if (gw_node == curr_gw) + goto deselect; } - rcu_read_unlock(); - return; + goto unlock; } - rcu_read_unlock(); if (new_gwflags == 0) - return; + goto unlock; gw_node_add(bat_priv, orig_node, new_gwflags); + goto unlock; + +deselect: + gw_deselect(bat_priv); +unlock: + rcu_read_unlock(); +out: + if (curr_gw) + gw_node_free_ref(curr_gw); } void gw_node_delete(struct bat_priv *bat_priv, struct orig_node *orig_node) @@ -345,9 +362,12 @@ void gw_node_delete(struct bat_priv *bat_priv, struct orig_node *orig_node) void gw_node_purge(struct bat_priv *bat_priv) { - struct gw_node *gw_node; + struct gw_node *gw_node, *curr_gw; struct hlist_node *node, *node_tmp; unsigned long timeout = 2 * PURGE_TIMEOUT * HZ; + char do_deselect = 0; + + curr_gw = gw_get_selected_gw_node(bat_priv); spin_lock_bh(&bat_priv->gw_list_lock); @@ -358,15 +378,21 @@ void gw_node_purge(struct bat_priv *bat_priv) atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE) continue; - if (rcu_dereference(bat_priv->curr_gw) == gw_node) - gw_deselect(bat_priv); + if (curr_gw == gw_node) + do_deselect = 1; hlist_del_rcu(&gw_node->list); gw_node_free_ref(gw_node); } - spin_unlock_bh(&bat_priv->gw_list_lock); + + /* gw_deselect() needs to acquire the gw_list_lock */ + if (do_deselect) + gw_deselect(bat_priv); + + if (curr_gw) + gw_node_free_ref(curr_gw); } /** @@ -385,22 +411,22 @@ static int _write_buffer_text(struct bat_priv *bat_priv, if (!router) goto out; - rcu_read_lock(); - curr_gw = rcu_dereference(bat_priv->curr_gw); + curr_gw = gw_get_selected_gw_node(bat_priv); ret = seq_printf(seq, "%s %pM (%3i) %pM [%10s]: %3i - %i%s/%i%s\n", - (curr_gw == gw_node ? "=>" : " "), - gw_node->orig_node->orig, - router->tq_avg, router->addr, - router->if_incoming->net_dev->name, - gw_node->orig_node->gw_flags, - (down > 2048 ? down / 1024 : down), - (down > 2048 ? "MBit" : "KBit"), - (up > 2048 ? up / 1024 : up), - (up > 2048 ? "MBit" : "KBit")); + (curr_gw == gw_node ? "=>" : " "), + gw_node->orig_node->orig, + router->tq_avg, router->addr, + router->if_incoming->net_dev->name, + gw_node->orig_node->gw_flags, + (down > 2048 ? down / 1024 : down), + (down > 2048 ? "MBit" : "KBit"), + (up > 2048 ? up / 1024 : up), + (up > 2048 ? "MBit" : "KBit")); - rcu_read_unlock(); neigh_node_free_ref(router); + if (curr_gw) + gw_node_free_ref(curr_gw); out: return ret; } @@ -459,6 +485,7 @@ int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb) struct iphdr *iphdr; struct ipv6hdr *ipv6hdr; struct udphdr *udphdr; + struct gw_node *curr_gw; unsigned int header_len = 0; if (atomic_read(&bat_priv->gw_mode) == GW_MODE_OFF) @@ -523,12 +550,11 @@ int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb) if (atomic_read(&bat_priv->gw_mode) == GW_MODE_SERVER) return -1; - rcu_read_lock(); - if (!rcu_dereference(bat_priv->curr_gw)) { - rcu_read_unlock(); + curr_gw = gw_get_selected_gw_node(bat_priv); + if (!curr_gw) return 0; - } - rcu_read_unlock(); + if (curr_gw) + gw_node_free_ref(curr_gw); return 1; } diff --git a/net/batman-adv/gateway_client.h b/net/batman-adv/gateway_client.h index 97c31d178163..1ce8c6066da1 100644 --- a/net/batman-adv/gateway_client.h +++ b/net/batman-adv/gateway_client.h @@ -24,7 +24,7 @@ void gw_deselect(struct bat_priv *bat_priv); void gw_election(struct bat_priv *bat_priv); -struct orig_node *gw_get_selected(struct bat_priv *bat_priv); +struct orig_node *gw_get_selected_orig(struct bat_priv *bat_priv); void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node); void gw_node_update(struct bat_priv *bat_priv, struct orig_node *orig_node, uint8_t new_gwflags); diff --git a/net/batman-adv/unicast.c b/net/batman-adv/unicast.c index 19f84bd443af..d46acc815138 100644 --- a/net/batman-adv/unicast.c +++ b/net/batman-adv/unicast.c @@ -289,7 +289,7 @@ int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv) /* get routing information */ if (is_multicast_ether_addr(ethhdr->h_dest)) { - orig_node = (struct orig_node *)gw_get_selected(bat_priv); + orig_node = (struct orig_node *)gw_get_selected_orig(bat_priv); if (orig_node) goto find_router; } -- cgit v1.2.3 From ba85fac28005a59e6e03fdb13918fc6f6e69a3ca Mon Sep 17 00:00:00 2001 From: Simon Wunderlich Date: Sun, 17 Apr 2011 20:34:27 +0200 Subject: batman-adv: protect softif_neigh by rcu Add get/set wrapper functions for softif_neigh and use rcu functions to manipulate the pointers. Signed-off-by: Simon Wunderlich Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann --- net/batman-adv/soft-interface.c | 114 ++++++++++++++++++++++++++++++---------- net/batman-adv/types.h | 2 +- 2 files changed, 88 insertions(+), 28 deletions(-) (limited to 'net/batman-adv') diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 9ed26140a269..ad6da4c7ddb5 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -90,10 +90,51 @@ static void softif_neigh_free_ref(struct softif_neigh *softif_neigh) call_rcu(&softif_neigh->rcu, softif_neigh_free_rcu); } +static struct softif_neigh *softif_neigh_get_selected(struct bat_priv *bat_priv) +{ + struct softif_neigh *neigh; + + rcu_read_lock(); + neigh = rcu_dereference(bat_priv->softif_neigh); + + if (neigh && !atomic_inc_not_zero(&neigh->refcount)) + neigh = NULL; + + rcu_read_unlock(); + return neigh; +} + +static void softif_neigh_select(struct bat_priv *bat_priv, + struct softif_neigh *new_neigh) +{ + struct softif_neigh *curr_neigh; + + spin_lock_bh(&bat_priv->softif_neigh_lock); + + if (new_neigh && !atomic_inc_not_zero(&new_neigh->refcount)) + new_neigh = NULL; + + curr_neigh = bat_priv->softif_neigh; + rcu_assign_pointer(bat_priv->softif_neigh, new_neigh); + + if (curr_neigh) + softif_neigh_free_ref(curr_neigh); + + spin_unlock_bh(&bat_priv->softif_neigh_lock); +} + +static void softif_neigh_deselect(struct bat_priv *bat_priv) +{ + softif_neigh_select(bat_priv, NULL); +} + void softif_neigh_purge(struct bat_priv *bat_priv) { - struct softif_neigh *softif_neigh, *softif_neigh_tmp; + struct softif_neigh *softif_neigh, *curr_softif_neigh; struct hlist_node *node, *node_tmp; + char do_deselect = 0; + + curr_softif_neigh = softif_neigh_get_selected(bat_priv); spin_lock_bh(&bat_priv->softif_neigh_lock); @@ -105,22 +146,26 @@ void softif_neigh_purge(struct bat_priv *bat_priv) (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE)) continue; - hlist_del_rcu(&softif_neigh->list); - - if (bat_priv->softif_neigh == softif_neigh) { + if (curr_softif_neigh == softif_neigh) { bat_dbg(DBG_ROUTES, bat_priv, "Current mesh exit point '%pM' vanished " "(vid: %d).\n", softif_neigh->addr, softif_neigh->vid); - softif_neigh_tmp = bat_priv->softif_neigh; - bat_priv->softif_neigh = NULL; - softif_neigh_free_ref(softif_neigh_tmp); + do_deselect = 1; } + hlist_del_rcu(&softif_neigh->list); softif_neigh_free_ref(softif_neigh); } spin_unlock_bh(&bat_priv->softif_neigh_lock); + + /* soft_neigh_deselect() needs to acquire the softif_neigh_lock */ + if (do_deselect) + softif_neigh_deselect(bat_priv); + + if (curr_softif_neigh) + softif_neigh_free_ref(curr_softif_neigh); } static struct softif_neigh *softif_neigh_get(struct bat_priv *bat_priv, @@ -171,6 +216,7 @@ int softif_neigh_seq_print_text(struct seq_file *seq, void *offset) struct bat_priv *bat_priv = netdev_priv(net_dev); struct softif_neigh *softif_neigh; struct hlist_node *node; + struct softif_neigh *curr_softif_neigh; if (!bat_priv->primary_if) { return seq_printf(seq, "BATMAN mesh %s disabled - " @@ -180,14 +226,17 @@ int softif_neigh_seq_print_text(struct seq_file *seq, void *offset) seq_printf(seq, "Softif neighbor list (%s)\n", net_dev->name); + curr_softif_neigh = softif_neigh_get_selected(bat_priv); rcu_read_lock(); hlist_for_each_entry_rcu(softif_neigh, node, &bat_priv->softif_neigh_list, list) seq_printf(seq, "%s %pM (vid: %d)\n", - bat_priv->softif_neigh == softif_neigh + curr_softif_neigh == softif_neigh ? "=>" : " ", softif_neigh->addr, softif_neigh->vid); rcu_read_unlock(); + if (curr_softif_neigh) + softif_neigh_free_ref(curr_softif_neigh); return 0; } @@ -198,7 +247,8 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev, struct bat_priv *bat_priv = netdev_priv(dev); struct ethhdr *ethhdr = (struct ethhdr *)skb->data; struct batman_packet *batman_packet; - struct softif_neigh *softif_neigh, *softif_neigh_tmp; + struct softif_neigh *softif_neigh; + struct softif_neigh *curr_softif_neigh = NULL; if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) batman_packet = (struct batman_packet *) @@ -223,7 +273,8 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev, if (!softif_neigh) goto err; - if (bat_priv->softif_neigh == softif_neigh) + curr_softif_neigh = softif_neigh_get_selected(bat_priv); + if (curr_softif_neigh == softif_neigh) goto out; /* we got a neighbor but its mac is 'bigger' than ours */ @@ -232,38 +283,39 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev, goto out; /* switch to new 'smallest neighbor' */ - if ((bat_priv->softif_neigh) && - (memcmp(softif_neigh->addr, bat_priv->softif_neigh->addr, + if ((curr_softif_neigh) && + (memcmp(softif_neigh->addr, curr_softif_neigh->addr, ETH_ALEN) < 0)) { bat_dbg(DBG_ROUTES, bat_priv, "Changing mesh exit point from %pM (vid: %d) " "to %pM (vid: %d).\n", - bat_priv->softif_neigh->addr, - bat_priv->softif_neigh->vid, + curr_softif_neigh->addr, + curr_softif_neigh->vid, softif_neigh->addr, softif_neigh->vid); - softif_neigh_tmp = bat_priv->softif_neigh; - bat_priv->softif_neigh = softif_neigh; - softif_neigh_free_ref(softif_neigh_tmp); - /* we need to hold the additional reference */ - goto err; + + softif_neigh_select(bat_priv, softif_neigh); + goto out; } /* close own batX device and use softif_neigh as exit node */ - if ((!bat_priv->softif_neigh) && + if ((!curr_softif_neigh) && (memcmp(softif_neigh->addr, bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN) < 0)) { bat_dbg(DBG_ROUTES, bat_priv, "Setting mesh exit point to %pM (vid: %d).\n", softif_neigh->addr, softif_neigh->vid); - bat_priv->softif_neigh = softif_neigh; - /* we need to hold the additional reference */ - goto err; + + softif_neigh_select(bat_priv, softif_neigh); + goto out; } out: softif_neigh_free_ref(softif_neigh); err: kfree_skb(skb); + if (curr_softif_neigh) + softif_neigh_free_ref(curr_softif_neigh); + return; } @@ -321,6 +373,7 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) struct bat_priv *bat_priv = netdev_priv(soft_iface); struct bcast_packet *bcast_packet; struct vlan_ethhdr *vhdr; + struct softif_neigh *curr_softif_neigh = NULL; int data_len = skb->len, ret; short vid = -1; bool do_bcast = false; @@ -348,7 +401,8 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) * if we have a another chosen mesh exit node in range * it will transport the packets to the mesh */ - if ((bat_priv->softif_neigh) && (bat_priv->softif_neigh->vid == vid)) + curr_softif_neigh = softif_neigh_get_selected(bat_priv); + if ((curr_softif_neigh) && (curr_softif_neigh->vid == vid)) goto dropped; /* TODO: check this for locks */ @@ -410,6 +464,8 @@ dropped: dropped_freed: bat_priv->stats.tx_dropped++; end: + if (curr_softif_neigh) + softif_neigh_free_ref(curr_softif_neigh); return NETDEV_TX_OK; } @@ -421,6 +477,7 @@ void interface_rx(struct net_device *soft_iface, struct unicast_packet *unicast_packet; struct ethhdr *ethhdr; struct vlan_ethhdr *vhdr; + struct softif_neigh *curr_softif_neigh = NULL; short vid = -1; int ret; @@ -450,7 +507,8 @@ void interface_rx(struct net_device *soft_iface, * if we have a another chosen mesh exit node in range * it will transport the packets to the non-mesh network */ - if ((bat_priv->softif_neigh) && (bat_priv->softif_neigh->vid == vid)) { + curr_softif_neigh = softif_neigh_get_selected(bat_priv); + if (curr_softif_neigh && (curr_softif_neigh->vid == vid)) { skb_push(skb, hdr_size); unicast_packet = (struct unicast_packet *)skb->data; @@ -461,7 +519,7 @@ void interface_rx(struct net_device *soft_iface, skb_reset_mac_header(skb); memcpy(unicast_packet->dest, - bat_priv->softif_neigh->addr, ETH_ALEN); + curr_softif_neigh->addr, ETH_ALEN); ret = route_unicast_packet(skb, recv_if); if (ret == NET_RX_DROP) goto dropped; @@ -486,11 +544,13 @@ void interface_rx(struct net_device *soft_iface, soft_iface->last_rx = jiffies; netif_rx(skb); - return; + goto out; dropped: kfree_skb(skb); out: + if (curr_softif_neigh) + softif_neigh_free_ref(curr_softif_neigh); return; } diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 091476df4f0e..75123b1ae0de 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -147,7 +147,7 @@ struct bat_priv { atomic_t batman_queue_left; char num_ifaces; struct hlist_head softif_neigh_list; - struct softif_neigh *softif_neigh; + struct softif_neigh __rcu *softif_neigh; struct debug_log *debug_log; struct hard_iface *primary_if; struct kobject *mesh_obj; -- cgit v1.2.3 From af20b710479ae662829cf739b521390daa7fcbcb Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Sun, 17 Apr 2011 20:39:07 +0200 Subject: batman-adv: Set the txqueuelen to zero when creating soft interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Like other virtual interfaces, e.g. br0, we don't need a transmit queue. Packets should only be queued on real interfaces which are underneath. In practice this patch makes little difference since the virtual interfaces can accept packets as fast as they come, but the patch will avoid bufferbloat questions to the mailling lists in the future. Signed-off-by: Andrew Lunn Tested-by: Linus Lüssing Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann --- net/batman-adv/soft-interface.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net/batman-adv') diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index ad6da4c7ddb5..58ce4400d581 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -584,6 +584,7 @@ static void interface_setup(struct net_device *dev) dev->hard_start_xmit = interface_tx; #endif dev->destructor = free_netdev; + dev->tx_queue_len = 0; /** * can't call min_mtu, because the needed variables -- cgit v1.2.3 From 97dbee73978497c615a46d324e4f5629b9772f86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Miros=C5=82aw?= Date: Tue, 19 Apr 2011 00:43:20 +0000 Subject: net: batman-adv: remove rx_csum ethtool_ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Michał Mirosław Signed-off-by: David S. Miller --- net/batman-adv/soft-interface.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'net/batman-adv') diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 1f6f756bc584..f4d80ad008c2 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -43,8 +43,6 @@ static void bat_get_drvinfo(struct net_device *dev, static u32 bat_get_msglevel(struct net_device *dev); static void bat_set_msglevel(struct net_device *dev, u32 value); static u32 bat_get_link(struct net_device *dev); -static u32 bat_get_rx_csum(struct net_device *dev); -static int bat_set_rx_csum(struct net_device *dev, u32 data); static const struct ethtool_ops bat_ethtool_ops = { .get_settings = bat_get_settings, @@ -52,8 +50,6 @@ static const struct ethtool_ops bat_ethtool_ops = { .get_msglevel = bat_get_msglevel, .set_msglevel = bat_set_msglevel, .get_link = bat_get_link, - .get_rx_csum = bat_get_rx_csum, - .set_rx_csum = bat_set_rx_csum }; int my_skb_head_push(struct sk_buff *skb, unsigned int len) @@ -736,12 +732,3 @@ static u32 bat_get_link(struct net_device *dev) return 1; } -static u32 bat_get_rx_csum(struct net_device *dev) -{ - return 0; -} - -static int bat_set_rx_csum(struct net_device *dev, u32 data) -{ - return -EOPNOTSUPP; -} -- cgit v1.2.3 From 707394972093e2056e1e8cc39be19cf9bcb3e7b3 Mon Sep 17 00:00:00 2001 From: David Decotigny Date: Wed, 27 Apr 2011 18:32:40 +0000 Subject: ethtool: cosmetic: Use ethtool ethtool_cmd_speed API This updates the network drivers so that they don't access the ethtool_cmd::speed field directly, but use ethtool_cmd_speed() instead. For most of the drivers, these changes are purely cosmetic and don't fix any problem, such as for those 1GbE/10GbE drivers that indirectly call their own ethtool get_settings()/mii_ethtool_gset(). The changes are meant to enforce code consistency and provide robustness with future larger throughputs, at the expense of a few CPU cycles for each ethtool operation. All drivers compiled with make allyesconfig ion x86_64 have been updated. Tested: make allyesconfig on x86_64 + e1000e/bnx2x work Signed-off-by: David Decotigny Signed-off-by: David S. Miller --- net/batman-adv/soft-interface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/batman-adv') diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index f4d80ad008c2..eeabbb89172c 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -697,7 +697,7 @@ static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) { cmd->supported = 0; cmd->advertising = 0; - cmd->speed = SPEED_10; + ethtool_cmd_speed_set(cmd, SPEED_10); cmd->duplex = DUPLEX_FULL; cmd->port = PORT_TP; cmd->phy_address = 0; -- cgit v1.2.3 From b5a6f69c5ca024bea43496d517c3b7ccfdb084a6 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Sat, 16 Apr 2011 11:30:57 +0200 Subject: batman-adv: orig_hash_find() manages rcu_lock/unlock internally orig_hash_find() manages rcu_lock/unlock internally and doesn't need to be surrounded by rcu_read_lock() / rcu_read_unlock() anymore Signed-off-by: Antonio Quartulli Acked-by: Marek Lindner Signed-off-by: Sven Eckelmann --- net/batman-adv/routing.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) (limited to 'net/batman-adv') diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index f6c642246972..2d77bd3a3e9a 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -1310,13 +1310,10 @@ int route_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if) } /* get routing information */ - rcu_read_lock(); orig_node = orig_hash_find(bat_priv, unicast_packet->dest); if (!orig_node) - goto unlock; - - rcu_read_unlock(); + goto out; /* find_router() increases neigh_nodes refcount if found. */ neigh_node = find_router(bat_priv, orig_node, recv_if); @@ -1362,10 +1359,7 @@ int route_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if) /* route it */ send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); ret = NET_RX_SUCCESS; - goto out; -unlock: - rcu_read_unlock(); out: if (neigh_node) neigh_node_free_ref(neigh_node); @@ -1464,13 +1458,10 @@ int recv_bcast_packet(struct sk_buff *skb, struct hard_iface *recv_if) if (bcast_packet->ttl < 2) goto out; - rcu_read_lock(); orig_node = orig_hash_find(bat_priv, bcast_packet->orig); if (!orig_node) - goto rcu_unlock; - - rcu_read_unlock(); + goto out; spin_lock_bh(&orig_node->bcast_seqno_lock); @@ -1501,9 +1492,6 @@ int recv_bcast_packet(struct sk_buff *skb, struct hard_iface *recv_if) ret = NET_RX_SUCCESS; goto out; -rcu_unlock: - rcu_read_unlock(); - goto out; spin_unlock: spin_unlock_bh(&orig_node->bcast_seqno_lock); out: -- cgit v1.2.3 From 5f657ec0d2103571a31707711926b443a27b0c66 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Wed, 20 Apr 2011 09:52:56 +0200 Subject: batman-adv: Move definition of atomic_dec_not_zero() into main.h atomic_dec_not_zero() is very useful and it is currently defined multiple times. So it is possible to move it in main.h Signed-off-by: Antonio Quartulli Signed-off-by: Sven Eckelmann --- net/batman-adv/aggregation.c | 1 - net/batman-adv/main.h | 2 ++ net/batman-adv/send.c | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) (limited to 'net/batman-adv') diff --git a/net/batman-adv/aggregation.c b/net/batman-adv/aggregation.c index af45d6b2031f..c11788c4c1a1 100644 --- a/net/batman-adv/aggregation.c +++ b/net/batman-adv/aggregation.c @@ -95,7 +95,6 @@ static bool can_aggregate_with(struct batman_packet *new_batman_packet, return false; } -#define atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0) /* create a new aggregated packet and add this packet to it */ static void new_aggregated_packet(unsigned char *packet_buff, int packet_len, unsigned long send_time, bool direct_link, diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index dc248697de71..ace72852ed7b 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h @@ -175,4 +175,6 @@ static inline int compare_eth(void *data1, void *data2) return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0); } +#define atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0) + #endif /* _NET_BATMAN_ADV_MAIN_H_ */ diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c index e78670c3c4b7..7650e2bf187d 100644 --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c @@ -393,7 +393,6 @@ static void _add_bcast_packet_to_list(struct bat_priv *bat_priv, send_time); } -#define atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0) /* add a broadcast packet to the queue and setup timers. broadcast packets * are sent multiple times to increase probability for beeing received. * -- cgit v1.2.3 From 71e4aa9c465fd66c110667ab5d620fb6a4ef2157 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Mon, 25 Apr 2011 22:44:32 +0200 Subject: batman-adv: fix gw_node_update() and gw_election() This is a regression from c4aac1ab9b973798163b34939b522f01e4d28ac9 - gw_node_update() doesn't add a new gw_node in case of empty curr_gw. This means that at the beginning no gw_node is added, leading to an empty gateway list. - gw_election() is terminating in case of curr_gw == NULL. It has to terminate in case of curr_gw != NULL Signed-off-by: Antonio Quartulli Signed-off-by: Sven Eckelmann --- net/batman-adv/gateway_client.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'net/batman-adv') diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index 2acd7a666bda..af128eff2edf 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c @@ -127,7 +127,7 @@ void gw_election(struct bat_priv *bat_priv) return; curr_gw = gw_get_selected_gw_node(bat_priv); - if (!curr_gw) + if (curr_gw) goto out; rcu_read_lock(); @@ -310,9 +310,13 @@ void gw_node_update(struct bat_priv *bat_priv, struct hlist_node *node; struct gw_node *gw_node, *curr_gw; + /** + * Note: We don't need a NULL check here, since curr_gw never gets + * dereferenced. If curr_gw is NULL we also should not exit as we may + * have this gateway in our list (duplication check!) even though we + * have no currently selected gateway. + */ curr_gw = gw_get_selected_gw_node(bat_priv); - if (!curr_gw) - goto out; rcu_read_lock(); hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) { @@ -350,7 +354,7 @@ deselect: gw_deselect(bat_priv); unlock: rcu_read_unlock(); -out: + if (curr_gw) gw_node_free_ref(curr_gw); } -- cgit v1.2.3 From 32ae9b221e788413ce68feaae2ca39e406211a0a Mon Sep 17 00:00:00 2001 From: Marek Lindner Date: Wed, 20 Apr 2011 15:40:58 +0200 Subject: batman-adv: Make bat_priv->primary_if an rcu protected pointer The rcu protected macros rcu_dereference() and rcu_assign_pointer() for the bat_priv->primary_if need to be used, as well as spin/rcu locking. Otherwise we might end up using a primary_if pointer pointing to already freed memory. Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann --- net/batman-adv/gateway_client.c | 33 ++++++++------- net/batman-adv/hard-interface.c | 83 ++++++++++++++++++++++++++------------ net/batman-adv/hard-interface.h | 18 +++++++++ net/batman-adv/icmp_socket.c | 19 ++++++--- net/batman-adv/originator.c | 34 ++++++++++------ net/batman-adv/routing.c | 18 ++++++--- net/batman-adv/send.c | 17 ++++++-- net/batman-adv/soft-interface.c | 64 ++++++++++++++++++++--------- net/batman-adv/translation-table.c | 57 +++++++++++++++++++------- net/batman-adv/types.h | 2 +- net/batman-adv/unicast.c | 16 +++++--- net/batman-adv/vis.c | 37 ++++++++++++----- 12 files changed, 280 insertions(+), 118 deletions(-) (limited to 'net/batman-adv') diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index af128eff2edf..65f39530799d 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c @@ -439,30 +439,32 @@ int gw_client_seq_print_text(struct seq_file *seq, void *offset) { struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); + struct hard_iface *primary_if; struct gw_node *gw_node; struct hlist_node *node; - int gw_count = 0; + int gw_count = 0, ret = 0; - if (!bat_priv->primary_if) { - - return seq_printf(seq, "BATMAN mesh %s disabled - please " - "specify interfaces to enable it\n", - net_dev->name); + primary_if = primary_if_get_selected(bat_priv); + if (!primary_if) { + ret = seq_printf(seq, "BATMAN mesh %s disabled - please " + "specify interfaces to enable it\n", + net_dev->name); + goto out; } - if (bat_priv->primary_if->if_status != IF_ACTIVE) { - - return seq_printf(seq, "BATMAN mesh %s disabled - " - "primary interface not active\n", - net_dev->name); + if (primary_if->if_status != IF_ACTIVE) { + ret = seq_printf(seq, "BATMAN mesh %s disabled - " + "primary interface not active\n", + net_dev->name); + goto out; } seq_printf(seq, " %-12s (%s/%i) %17s [%10s]: gw_class ... " "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%pM (%s)]\n", "Gateway", "#", TQ_MAX_VALUE, "Nexthop", "outgoingIF", SOURCE_VERSION, REVISION_VERSION_STR, - bat_priv->primary_if->net_dev->name, - bat_priv->primary_if->net_dev->dev_addr, net_dev->name); + primary_if->net_dev->name, + primary_if->net_dev->dev_addr, net_dev->name); rcu_read_lock(); hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) { @@ -480,7 +482,10 @@ int gw_client_seq_print_text(struct seq_file *seq, void *offset) if (gw_count == 0) seq_printf(seq, "No gateways in range ...\n"); - return 0; +out: + if (primary_if) + hardif_free_ref(primary_if); + return ret; } int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb) diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index b3058e46ee6b..3e888f133d75 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c @@ -110,47 +110,60 @@ out: return hard_iface; } -static void update_primary_addr(struct bat_priv *bat_priv) +static void primary_if_update_addr(struct bat_priv *bat_priv) { struct vis_packet *vis_packet; + struct hard_iface *primary_if; + + primary_if = primary_if_get_selected(bat_priv); + if (!primary_if) + goto out; vis_packet = (struct vis_packet *) bat_priv->my_vis_info->skb_packet->data; - memcpy(vis_packet->vis_orig, - bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); + memcpy(vis_packet->vis_orig, primary_if->net_dev->dev_addr, ETH_ALEN); memcpy(vis_packet->sender_orig, - bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); + primary_if->net_dev->dev_addr, ETH_ALEN); + +out: + if (primary_if) + hardif_free_ref(primary_if); } -static void set_primary_if(struct bat_priv *bat_priv, - struct hard_iface *hard_iface) +static void primary_if_select(struct bat_priv *bat_priv, + struct hard_iface *new_hard_iface) { + struct hard_iface *curr_hard_iface; struct batman_packet *batman_packet; - struct hard_iface *old_if; - if (hard_iface && !atomic_inc_not_zero(&hard_iface->refcount)) - hard_iface = NULL; + spin_lock_bh(&hardif_list_lock); - old_if = bat_priv->primary_if; - bat_priv->primary_if = hard_iface; + if (new_hard_iface && !atomic_inc_not_zero(&new_hard_iface->refcount)) + new_hard_iface = NULL; - if (old_if) - hardif_free_ref(old_if); + curr_hard_iface = bat_priv->primary_if; + rcu_assign_pointer(bat_priv->primary_if, new_hard_iface); - if (!bat_priv->primary_if) - return; + if (curr_hard_iface) + hardif_free_ref(curr_hard_iface); - batman_packet = (struct batman_packet *)(hard_iface->packet_buff); + if (!new_hard_iface) + goto out; + + batman_packet = (struct batman_packet *)(new_hard_iface->packet_buff); batman_packet->flags = PRIMARIES_FIRST_HOP; batman_packet->ttl = TTL; - update_primary_addr(bat_priv); + primary_if_update_addr(bat_priv); /*** * hacky trick to make sure that we send the HNA information via * our new primary interface */ atomic_set(&bat_priv->hna_local_changed, 1); + +out: + spin_unlock_bh(&hardif_list_lock); } static bool hardif_is_iface_up(struct hard_iface *hard_iface) @@ -236,9 +249,10 @@ void update_min_mtu(struct net_device *soft_iface) static void hardif_activate_interface(struct hard_iface *hard_iface) { struct bat_priv *bat_priv; + struct hard_iface *primary_if = NULL; if (hard_iface->if_status != IF_INACTIVE) - return; + goto out; bat_priv = netdev_priv(hard_iface->soft_iface); @@ -249,14 +263,18 @@ static void hardif_activate_interface(struct hard_iface *hard_iface) * the first active interface becomes our primary interface or * the next active interface after the old primay interface was removed */ - if (!bat_priv->primary_if) - set_primary_if(bat_priv, hard_iface); + primary_if = primary_if_get_selected(bat_priv); + if (!primary_if) + primary_if_select(bat_priv, hard_iface); bat_info(hard_iface->soft_iface, "Interface activated: %s\n", hard_iface->net_dev->name); update_min_mtu(hard_iface->soft_iface); - return; + +out: + if (primary_if) + hardif_free_ref(primary_if); } static void hardif_deactivate_interface(struct hard_iface *hard_iface) @@ -386,12 +404,13 @@ err: void hardif_disable_interface(struct hard_iface *hard_iface) { struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface); + struct hard_iface *primary_if = NULL; if (hard_iface->if_status == IF_ACTIVE) hardif_deactivate_interface(hard_iface); if (hard_iface->if_status != IF_INACTIVE) - return; + goto out; bat_info(hard_iface->soft_iface, "Removing interface: %s\n", hard_iface->net_dev->name); @@ -400,11 +419,12 @@ void hardif_disable_interface(struct hard_iface *hard_iface) bat_priv->num_ifaces--; orig_hash_del_if(hard_iface, bat_priv->num_ifaces); - if (hard_iface == bat_priv->primary_if) { + primary_if = primary_if_get_selected(bat_priv); + if (hard_iface == primary_if) { struct hard_iface *new_if; new_if = hardif_get_active(hard_iface->soft_iface); - set_primary_if(bat_priv, new_if); + primary_if_select(bat_priv, new_if); if (new_if) hardif_free_ref(new_if); @@ -425,6 +445,10 @@ void hardif_disable_interface(struct hard_iface *hard_iface) hard_iface->soft_iface = NULL; hardif_free_ref(hard_iface); + +out: + if (primary_if) + hardif_free_ref(primary_if); } static struct hard_iface *hardif_add_interface(struct net_device *net_dev) @@ -514,6 +538,7 @@ static int hard_if_event(struct notifier_block *this, { struct net_device *net_dev = (struct net_device *)ptr; struct hard_iface *hard_iface = hardif_get_by_netdev(net_dev); + struct hard_iface *primary_if = NULL; struct bat_priv *bat_priv; if (!hard_iface && event == NETDEV_REGISTER) @@ -549,8 +574,12 @@ static int hard_if_event(struct notifier_block *this, update_mac_addresses(hard_iface); bat_priv = netdev_priv(hard_iface->soft_iface); - if (hard_iface == bat_priv->primary_if) - update_primary_addr(bat_priv); + primary_if = primary_if_get_selected(bat_priv); + if (!primary_if) + goto hardif_put; + + if (hard_iface == primary_if) + primary_if_update_addr(bat_priv); break; default: break; @@ -559,6 +588,8 @@ static int hard_if_event(struct notifier_block *this, hardif_put: hardif_free_ref(hard_iface); out: + if (primary_if) + hardif_free_ref(primary_if); return NOTIFY_DONE; } diff --git a/net/batman-adv/hard-interface.h b/net/batman-adv/hard-interface.h index a9ddf36e51c8..64265991460b 100644 --- a/net/batman-adv/hard-interface.h +++ b/net/batman-adv/hard-interface.h @@ -45,4 +45,22 @@ static inline void hardif_free_ref(struct hard_iface *hard_iface) call_rcu(&hard_iface->rcu, hardif_free_rcu); } +static inline struct hard_iface *primary_if_get_selected( + struct bat_priv *bat_priv) +{ + struct hard_iface *hard_iface; + + rcu_read_lock(); + hard_iface = rcu_dereference(bat_priv->primary_if); + if (!hard_iface) + goto out; + + if (!atomic_inc_not_zero(&hard_iface->refcount)) + hard_iface = NULL; + +out: + rcu_read_unlock(); + return hard_iface; +} + #endif /* _NET_BATMAN_ADV_HARD_INTERFACE_H_ */ diff --git a/net/batman-adv/icmp_socket.c b/net/batman-adv/icmp_socket.c index 49079c254476..fa22ba2bb832 100644 --- a/net/batman-adv/icmp_socket.c +++ b/net/batman-adv/icmp_socket.c @@ -153,6 +153,7 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, { struct socket_client *socket_client = file->private_data; struct bat_priv *bat_priv = socket_client->bat_priv; + struct hard_iface *primary_if = NULL; struct sk_buff *skb; struct icmp_packet_rr *icmp_packet; @@ -167,15 +168,21 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, return -EINVAL; } - if (!bat_priv->primary_if) - return -EFAULT; + primary_if = primary_if_get_selected(bat_priv); + + if (!primary_if) { + len = -EFAULT; + goto out; + } if (len >= sizeof(struct icmp_packet_rr)) packet_len = sizeof(struct icmp_packet_rr); skb = dev_alloc_skb(packet_len + sizeof(struct ethhdr)); - if (!skb) - return -ENOMEM; + if (!skb) { + len = -ENOMEM; + goto out; + } skb_reserve(skb, sizeof(struct ethhdr)); icmp_packet = (struct icmp_packet_rr *)skb_put(skb, packet_len); @@ -233,7 +240,7 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, goto dst_unreach; memcpy(icmp_packet->orig, - bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); + primary_if->net_dev->dev_addr, ETH_ALEN); if (packet_len == sizeof(struct icmp_packet_rr)) memcpy(icmp_packet->rr, @@ -248,6 +255,8 @@ dst_unreach: free_skb: kfree_skb(skb); out: + if (primary_if) + hardif_free_ref(primary_if); if (neigh_node) neigh_node_free_ref(neigh_node); if (orig_node) diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index 5b8fe32043da..ef4a9be7613a 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -405,29 +405,34 @@ int orig_seq_print_text(struct seq_file *seq, void *offset) struct hashtable_t *hash = bat_priv->orig_hash; struct hlist_node *node, *node_tmp; struct hlist_head *head; + struct hard_iface *primary_if; struct orig_node *orig_node; struct neigh_node *neigh_node, *neigh_node_tmp; int batman_count = 0; int last_seen_secs; int last_seen_msecs; - int i; + int i, ret = 0; + + primary_if = primary_if_get_selected(bat_priv); - if ((!bat_priv->primary_if) || - (bat_priv->primary_if->if_status != IF_ACTIVE)) { - if (!bat_priv->primary_if) - return seq_printf(seq, "BATMAN mesh %s disabled - " - "please specify interfaces to enable it\n", - net_dev->name); + if (!primary_if) { + ret = seq_printf(seq, "BATMAN mesh %s disabled - " + "please specify interfaces to enable it\n", + net_dev->name); + goto out; + } - return seq_printf(seq, "BATMAN mesh %s " - "disabled - primary interface not active\n", - net_dev->name); + if (primary_if->if_status != IF_ACTIVE) { + ret = seq_printf(seq, "BATMAN mesh %s " + "disabled - primary interface not active\n", + net_dev->name); + goto out; } seq_printf(seq, "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%pM (%s)]\n", SOURCE_VERSION, REVISION_VERSION_STR, - bat_priv->primary_if->net_dev->name, - bat_priv->primary_if->net_dev->dev_addr, net_dev->name); + primary_if->net_dev->name, + primary_if->net_dev->dev_addr, net_dev->name); seq_printf(seq, " %-15s %s (%s/%i) %17s [%10s]: %20s ...\n", "Originator", "last-seen", "#", TQ_MAX_VALUE, "Nexthop", "outgoingIF", "Potential nexthops"); @@ -474,7 +479,10 @@ next: if (batman_count == 0) seq_printf(seq, "No batman nodes in range ...\n"); - return 0; +out: + if (primary_if) + hardif_free_ref(primary_if); + return ret; } static int orig_node_add_if(struct orig_node *orig_node, int max_if_num) diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index 2d77bd3a3e9a..49f571553050 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -904,6 +904,7 @@ int recv_bat_packet(struct sk_buff *skb, struct hard_iface *hard_iface) static int recv_my_icmp_packet(struct bat_priv *bat_priv, struct sk_buff *skb, size_t icmp_len) { + struct hard_iface *primary_if = NULL; struct orig_node *orig_node = NULL; struct neigh_node *router = NULL; struct icmp_packet_rr *icmp_packet; @@ -917,7 +918,8 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv, goto out; } - if (!bat_priv->primary_if) + primary_if = primary_if_get_selected(bat_priv); + if (!primary_if) goto out; /* answer echo request (ping) */ @@ -937,8 +939,7 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv, icmp_packet = (struct icmp_packet_rr *)skb->data; memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); - memcpy(icmp_packet->orig, - bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); + memcpy(icmp_packet->orig, primary_if->net_dev->dev_addr, ETH_ALEN); icmp_packet->msg_type = ECHO_REPLY; icmp_packet->ttl = TTL; @@ -946,6 +947,8 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv, ret = NET_RX_SUCCESS; out: + if (primary_if) + hardif_free_ref(primary_if); if (router) neigh_node_free_ref(router); if (orig_node) @@ -956,6 +959,7 @@ out: static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv, struct sk_buff *skb) { + struct hard_iface *primary_if = NULL; struct orig_node *orig_node = NULL; struct neigh_node *router = NULL; struct icmp_packet *icmp_packet; @@ -971,7 +975,8 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv, goto out; } - if (!bat_priv->primary_if) + primary_if = primary_if_get_selected(bat_priv); + if (!primary_if) goto out; /* get routing information */ @@ -990,8 +995,7 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv, icmp_packet = (struct icmp_packet *)skb->data; memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); - memcpy(icmp_packet->orig, - bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); + memcpy(icmp_packet->orig, primary_if->net_dev->dev_addr, ETH_ALEN); icmp_packet->msg_type = TTL_EXCEEDED; icmp_packet->ttl = TTL; @@ -999,6 +1003,8 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv, ret = NET_RX_SUCCESS; out: + if (primary_if) + hardif_free_ref(primary_if); if (router) neigh_node_free_ref(router); if (orig_node) diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c index 7650e2bf187d..02b541a6dfef 100644 --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c @@ -244,6 +244,7 @@ static void rebuild_batman_packet(struct bat_priv *bat_priv, void schedule_own_packet(struct hard_iface *hard_iface) { struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface); + struct hard_iface *primary_if; unsigned long send_time; struct batman_packet *batman_packet; int vis_server; @@ -253,6 +254,7 @@ void schedule_own_packet(struct hard_iface *hard_iface) return; vis_server = atomic_read(&bat_priv->vis_mode); + primary_if = primary_if_get_selected(bat_priv); /** * the interface gets activated here to avoid race conditions between @@ -266,7 +268,7 @@ void schedule_own_packet(struct hard_iface *hard_iface) /* if local hna has changed and interface is a primary interface */ if ((atomic_read(&bat_priv->hna_local_changed)) && - (hard_iface == bat_priv->primary_if)) + (hard_iface == primary_if)) rebuild_batman_packet(bat_priv, hard_iface); /** @@ -284,7 +286,7 @@ void schedule_own_packet(struct hard_iface *hard_iface) else batman_packet->flags &= ~VIS_SERVER; - if ((hard_iface == bat_priv->primary_if) && + if ((hard_iface == primary_if) && (atomic_read(&bat_priv->gw_mode) == GW_MODE_SERVER)) batman_packet->gw_flags = (uint8_t)atomic_read(&bat_priv->gw_bandwidth); @@ -299,6 +301,9 @@ void schedule_own_packet(struct hard_iface *hard_iface) hard_iface->packet_buff, hard_iface->packet_len, hard_iface, 1, send_time); + + if (primary_if) + hardif_free_ref(primary_if); } void schedule_forward_packet(struct orig_node *orig_node, @@ -403,6 +408,7 @@ static void _add_bcast_packet_to_list(struct bat_priv *bat_priv, * skb is freed. */ int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb) { + struct hard_iface *primary_if = NULL; struct forw_packet *forw_packet; struct bcast_packet *bcast_packet; @@ -411,7 +417,8 @@ int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb) goto out; } - if (!bat_priv->primary_if) + primary_if = primary_if_get_selected(bat_priv); + if (!primary_if) goto out; forw_packet = kmalloc(sizeof(struct forw_packet), GFP_ATOMIC); @@ -430,7 +437,7 @@ int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb) skb_reset_mac_header(skb); forw_packet->skb = skb; - forw_packet->if_incoming = bat_priv->primary_if; + forw_packet->if_incoming = primary_if; /* how often did we send the bcast packet ? */ forw_packet->num_packets = 0; @@ -443,6 +450,8 @@ packet_free: out_and_inc: atomic_inc(&bat_priv->bcast_queue_left); out: + if (primary_if) + hardif_free_ref(primary_if); return NETDEV_TX_BUSY; } diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 58ce4400d581..ea5e58c252f0 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -215,13 +215,24 @@ int softif_neigh_seq_print_text(struct seq_file *seq, void *offset) struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); struct softif_neigh *softif_neigh; + struct hard_iface *primary_if; struct hlist_node *node; struct softif_neigh *curr_softif_neigh; + int ret = 0; - if (!bat_priv->primary_if) { - return seq_printf(seq, "BATMAN mesh %s disabled - " - "please specify interfaces to enable it\n", - net_dev->name); + primary_if = primary_if_get_selected(bat_priv); + if (!primary_if) { + ret = seq_printf(seq, "BATMAN mesh %s disabled - " + "please specify interfaces to enable it\n", + net_dev->name); + goto out; + } + + if (primary_if->if_status != IF_ACTIVE) { + ret = seq_printf(seq, "BATMAN mesh %s " + "disabled - primary interface not active\n", + net_dev->name); + goto out; } seq_printf(seq, "Softif neighbor list (%s)\n", net_dev->name); @@ -238,7 +249,10 @@ int softif_neigh_seq_print_text(struct seq_file *seq, void *offset) if (curr_softif_neigh) softif_neigh_free_ref(curr_softif_neigh); - return 0; +out: + if (primary_if) + hardif_free_ref(primary_if); + return ret; } static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev, @@ -247,7 +261,8 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev, struct bat_priv *bat_priv = netdev_priv(dev); struct ethhdr *ethhdr = (struct ethhdr *)skb->data; struct batman_packet *batman_packet; - struct softif_neigh *softif_neigh; + struct softif_neigh *softif_neigh = NULL; + struct hard_iface *primary_if = NULL; struct softif_neigh *curr_softif_neigh = NULL; if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) @@ -257,28 +272,34 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev, batman_packet = (struct batman_packet *)(skb->data + ETH_HLEN); if (batman_packet->version != COMPAT_VERSION) - goto err; + goto out; if (batman_packet->packet_type != BAT_PACKET) - goto err; + goto out; if (!(batman_packet->flags & PRIMARIES_FIRST_HOP)) - goto err; + goto out; if (is_my_mac(batman_packet->orig)) - goto err; + goto out; softif_neigh = softif_neigh_get(bat_priv, batman_packet->orig, vid); - if (!softif_neigh) - goto err; + goto out; curr_softif_neigh = softif_neigh_get_selected(bat_priv); + if (!curr_softif_neigh) + goto out; + if (curr_softif_neigh == softif_neigh) goto out; + primary_if = primary_if_get_selected(bat_priv); + if (!primary_if) + goto out; + /* we got a neighbor but its mac is 'bigger' than ours */ - if (memcmp(bat_priv->primary_if->net_dev->dev_addr, + if (memcmp(primary_if->net_dev->dev_addr, softif_neigh->addr, ETH_ALEN) < 0) goto out; @@ -300,7 +321,7 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev, /* close own batX device and use softif_neigh as exit node */ if ((!curr_softif_neigh) && (memcmp(softif_neigh->addr, - bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN) < 0)) { + primary_if->net_dev->dev_addr, ETH_ALEN) < 0)) { bat_dbg(DBG_ROUTES, bat_priv, "Setting mesh exit point to %pM (vid: %d).\n", softif_neigh->addr, softif_neigh->vid); @@ -310,12 +331,13 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev, } out: - softif_neigh_free_ref(softif_neigh); -err: kfree_skb(skb); + if (softif_neigh) + softif_neigh_free_ref(softif_neigh); if (curr_softif_neigh) softif_neigh_free_ref(curr_softif_neigh); - + if (primary_if) + hardif_free_ref(primary_if); return; } @@ -371,6 +393,7 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) { struct ethhdr *ethhdr = (struct ethhdr *)skb->data; struct bat_priv *bat_priv = netdev_priv(soft_iface); + struct hard_iface *primary_if = NULL; struct bcast_packet *bcast_packet; struct vlan_ethhdr *vhdr; struct softif_neigh *curr_softif_neigh = NULL; @@ -420,7 +443,8 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) /* ethernet packet should be broadcasted */ if (do_bcast) { - if (!bat_priv->primary_if) + primary_if = primary_if_get_selected(bat_priv); + if (!primary_if) goto dropped; if (my_skb_head_push(skb, sizeof(struct bcast_packet)) < 0) @@ -436,7 +460,7 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) /* hw address of first interface is the orig mac because only * this mac is known throughout the mesh */ memcpy(bcast_packet->orig, - bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); + primary_if->net_dev->dev_addr, ETH_ALEN); /* set broadcast sequence number */ bcast_packet->seqno = @@ -466,6 +490,8 @@ dropped_freed: end: if (curr_softif_neigh) softif_neigh_free_ref(curr_softif_neigh); + if (primary_if) + hardif_free_ref(primary_if); return NETDEV_TX_OK; } diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index 8d15b48d1692..f931830d630e 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -22,6 +22,7 @@ #include "main.h" #include "translation-table.h" #include "soft-interface.h" +#include "hard-interface.h" #include "hash.h" #include "originator.h" @@ -237,16 +238,26 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset) struct bat_priv *bat_priv = netdev_priv(net_dev); struct hashtable_t *hash = bat_priv->hna_local_hash; struct hna_local_entry *hna_local_entry; + struct hard_iface *primary_if; struct hlist_node *node; struct hlist_head *head; size_t buf_size, pos; char *buff; - int i; + int i, ret = 0; - if (!bat_priv->primary_if) { - return seq_printf(seq, "BATMAN mesh %s disabled - " - "please specify interfaces to enable it\n", - net_dev->name); + primary_if = primary_if_get_selected(bat_priv); + if (!primary_if) { + ret = seq_printf(seq, "BATMAN mesh %s disabled - " + "please specify interfaces to enable it\n", + net_dev->name); + goto out; + } + + if (primary_if->if_status != IF_ACTIVE) { + ret = seq_printf(seq, "BATMAN mesh %s disabled - " + "primary interface not active\n", + net_dev->name); + goto out; } seq_printf(seq, "Locally retrieved addresses (from %s) " @@ -269,7 +280,8 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset) buff = kmalloc(buf_size, GFP_ATOMIC); if (!buff) { spin_unlock_bh(&bat_priv->hna_lhash_lock); - return -ENOMEM; + ret = -ENOMEM; + goto out; } buff[0] = '\0'; @@ -291,7 +303,10 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset) seq_printf(seq, "%s", buff); kfree(buff); - return 0; +out: + if (primary_if) + hardif_free_ref(primary_if); + return ret; } static void _hna_local_del(struct hlist_node *node, void *arg) @@ -468,16 +483,26 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset) struct bat_priv *bat_priv = netdev_priv(net_dev); struct hashtable_t *hash = bat_priv->hna_global_hash; struct hna_global_entry *hna_global_entry; + struct hard_iface *primary_if; struct hlist_node *node; struct hlist_head *head; size_t buf_size, pos; char *buff; - int i; + int i, ret = 0; - if (!bat_priv->primary_if) { - return seq_printf(seq, "BATMAN mesh %s disabled - " - "please specify interfaces to enable it\n", - net_dev->name); + primary_if = primary_if_get_selected(bat_priv); + if (!primary_if) { + ret = seq_printf(seq, "BATMAN mesh %s disabled - please " + "specify interfaces to enable it\n", + net_dev->name); + goto out; + } + + if (primary_if->if_status != IF_ACTIVE) { + ret = seq_printf(seq, "BATMAN mesh %s disabled - " + "primary interface not active\n", + net_dev->name); + goto out; } seq_printf(seq, "Globally announced HNAs received via the mesh %s\n", @@ -499,7 +524,8 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset) buff = kmalloc(buf_size, GFP_ATOMIC); if (!buff) { spin_unlock_bh(&bat_priv->hna_ghash_lock); - return -ENOMEM; + ret = -ENOMEM; + goto out; } buff[0] = '\0'; pos = 0; @@ -522,7 +548,10 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset) seq_printf(seq, "%s", buff); kfree(buff); - return 0; +out: + if (primary_if) + hardif_free_ref(primary_if); + return ret; } static void _hna_global_del_orig(struct bat_priv *bat_priv, diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 75123b1ae0de..947bafc6431a 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -149,7 +149,6 @@ struct bat_priv { struct hlist_head softif_neigh_list; struct softif_neigh __rcu *softif_neigh; struct debug_log *debug_log; - struct hard_iface *primary_if; struct kobject *mesh_obj; struct dentry *debug_dir; struct hlist_head forw_bat_list; @@ -174,6 +173,7 @@ struct bat_priv { struct delayed_work orig_work; struct delayed_work vis_work; struct gw_node __rcu *curr_gw; /* rcu protected pointer */ + struct hard_iface __rcu *primary_if; /* rcu protected pointer */ struct vis_info *my_vis_info; }; diff --git a/net/batman-adv/unicast.c b/net/batman-adv/unicast.c index d46acc815138..b46cbf1507e4 100644 --- a/net/batman-adv/unicast.c +++ b/net/batman-adv/unicast.c @@ -221,15 +221,17 @@ int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv, struct hard_iface *hard_iface, uint8_t dstaddr[]) { struct unicast_packet tmp_uc, *unicast_packet; + struct hard_iface *primary_if; struct sk_buff *frag_skb; struct unicast_frag_packet *frag1, *frag2; int uc_hdr_len = sizeof(struct unicast_packet); int ucf_hdr_len = sizeof(struct unicast_frag_packet); int data_len = skb->len - uc_hdr_len; - int large_tail = 0; + int large_tail = 0, ret = NET_RX_DROP; uint16_t seqno; - if (!bat_priv->primary_if) + primary_if = primary_if_get_selected(bat_priv); + if (!primary_if) goto dropped; frag_skb = dev_alloc_skb(data_len - (data_len / 2) + ucf_hdr_len); @@ -254,7 +256,7 @@ int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv, frag1->version = COMPAT_VERSION; frag1->packet_type = BAT_UNICAST_FRAG; - memcpy(frag1->orig, bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); + memcpy(frag1->orig, primary_if->net_dev->dev_addr, ETH_ALEN); memcpy(frag2, frag1, sizeof(struct unicast_frag_packet)); if (data_len & 1) @@ -269,13 +271,17 @@ int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv, send_skb_packet(skb, hard_iface, dstaddr); send_skb_packet(frag_skb, hard_iface, dstaddr); - return NET_RX_SUCCESS; + ret = NET_RX_SUCCESS; + goto out; drop_frag: kfree_skb(frag_skb); dropped: kfree_skb(skb); - return NET_RX_DROP; +out: + if (primary_if) + hardif_free_ref(primary_if); + return ret; } int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv) diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c index d4cc4f5399f4..c8f571d3b5d4 100644 --- a/net/batman-adv/vis.c +++ b/net/batman-adv/vis.c @@ -204,6 +204,7 @@ static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry, int vis_seq_print_text(struct seq_file *seq, void *offset) { + struct hard_iface *primary_if; struct hlist_node *node; struct hlist_head *head; struct vis_info *info; @@ -215,15 +216,18 @@ int vis_seq_print_text(struct seq_file *seq, void *offset) HLIST_HEAD(vis_if_list); struct if_list_entry *entry; struct hlist_node *pos, *n; - int i, j; + int i, j, ret = 0; int vis_server = atomic_read(&bat_priv->vis_mode); size_t buff_pos, buf_size; char *buff; int compare; - if ((!bat_priv->primary_if) || - (vis_server == VIS_TYPE_CLIENT_UPDATE)) - return 0; + primary_if = primary_if_get_selected(bat_priv); + if (!primary_if) + goto out; + + if (vis_server == VIS_TYPE_CLIENT_UPDATE) + goto out; buf_size = 1; /* Estimate length */ @@ -270,7 +274,8 @@ int vis_seq_print_text(struct seq_file *seq, void *offset) buff = kmalloc(buf_size, GFP_ATOMIC); if (!buff) { spin_unlock_bh(&bat_priv->vis_hash_lock); - return -ENOMEM; + ret = -ENOMEM; + goto out; } buff[0] = '\0'; buff_pos = 0; @@ -328,7 +333,10 @@ int vis_seq_print_text(struct seq_file *seq, void *offset) seq_printf(seq, "%s", buff); kfree(buff); - return 0; +out: + if (primary_if) + hardif_free_ref(primary_if); + return ret; } /* add the info packet to the send list, if it was not @@ -815,16 +823,20 @@ out: /* only send one vis packet. called from send_vis_packets() */ static void send_vis_packet(struct bat_priv *bat_priv, struct vis_info *info) { + struct hard_iface *primary_if; struct vis_packet *packet; + primary_if = primary_if_get_selected(bat_priv); + if (!primary_if) + goto out; + packet = (struct vis_packet *)info->skb_packet->data; if (packet->ttl < 2) { pr_debug("Error - can't send vis packet: ttl exceeded\n"); - return; + goto out; } - memcpy(packet->sender_orig, bat_priv->primary_if->net_dev->dev_addr, - ETH_ALEN); + memcpy(packet->sender_orig, primary_if->net_dev->dev_addr, ETH_ALEN); packet->ttl--; if (is_broadcast_ether_addr(packet->target_orig)) @@ -832,6 +844,10 @@ static void send_vis_packet(struct bat_priv *bat_priv, struct vis_info *info) else unicast_vis_packet(bat_priv, info); packet->ttl++; /* restore TTL */ + +out: + if (primary_if) + hardif_free_ref(primary_if); } /* called from timer; send (and maybe generate) vis packet. */ @@ -858,8 +874,7 @@ static void send_vis_packets(struct work_struct *work) kref_get(&info->refcount); spin_unlock_bh(&bat_priv->vis_hash_lock); - if (bat_priv->primary_if) - send_vis_packet(bat_priv, info); + send_vis_packet(bat_priv, info); spin_lock_bh(&bat_priv->vis_hash_lock); send_list_del(info); -- cgit v1.2.3 From 28f8e546e6bc4c2bc6687d7c8dcbe9934cebe639 Mon Sep 17 00:00:00 2001 From: Marek Lindner Date: Mon, 2 May 2011 16:37:13 +0200 Subject: batman-adv: remove misplaced comment Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann --- net/batman-adv/originator.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'net/batman-adv') diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index ef4a9be7613a..51af91b7a35b 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -19,8 +19,6 @@ * */ -/* increase the reference counter for this originator */ - #include "main.h" #include "originator.h" #include "hash.h" -- cgit v1.2.3 From 61906ae86d8989e5bd3bc1f51b2fb8d32ffde2c5 Mon Sep 17 00:00:00 2001 From: Marek Lindner Date: Thu, 21 Apr 2011 15:52:17 +0200 Subject: batman-adv: multi vlan support for bridge loop detection The bridge loop detection for batman-adv allows the bat0 interface to be bridged into an ethernet segment which other batman-adv nodes are connected to. In order to also allow multiple VLANs on top of the bat0 interface to be bridged into the ethernet segment this patch extends the aforementioned bridge loop detection. Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann --- net/batman-adv/main.c | 3 +- net/batman-adv/soft-interface.c | 393 +++++++++++++++++++++++++++++----------- net/batman-adv/types.h | 15 +- 3 files changed, 298 insertions(+), 113 deletions(-) (limited to 'net/batman-adv') diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index 709b33bbdf43..705e8be07c8d 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c @@ -87,11 +87,12 @@ int mesh_init(struct net_device *soft_iface) spin_lock_init(&bat_priv->vis_hash_lock); spin_lock_init(&bat_priv->vis_list_lock); spin_lock_init(&bat_priv->softif_neigh_lock); + spin_lock_init(&bat_priv->softif_neigh_vid_lock); INIT_HLIST_HEAD(&bat_priv->forw_bat_list); INIT_HLIST_HEAD(&bat_priv->forw_bcast_list); INIT_HLIST_HEAD(&bat_priv->gw_list); - INIT_HLIST_HEAD(&bat_priv->softif_neigh_list); + INIT_HLIST_HEAD(&bat_priv->softif_neigh_vids); if (originator_init(bat_priv) < 1) goto err; diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index ea5e58c252f0..8cb13a03b0e1 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -90,135 +90,251 @@ static void softif_neigh_free_ref(struct softif_neigh *softif_neigh) call_rcu(&softif_neigh->rcu, softif_neigh_free_rcu); } -static struct softif_neigh *softif_neigh_get_selected(struct bat_priv *bat_priv) +static void softif_neigh_vid_free_rcu(struct rcu_head *rcu) { - struct softif_neigh *neigh; - - rcu_read_lock(); - neigh = rcu_dereference(bat_priv->softif_neigh); - - if (neigh && !atomic_inc_not_zero(&neigh->refcount)) - neigh = NULL; - - rcu_read_unlock(); - return neigh; -} + struct softif_neigh_vid *softif_neigh_vid; + struct softif_neigh *softif_neigh; + struct hlist_node *node, *node_tmp; + struct bat_priv *bat_priv; -static void softif_neigh_select(struct bat_priv *bat_priv, - struct softif_neigh *new_neigh) -{ - struct softif_neigh *curr_neigh; + softif_neigh_vid = container_of(rcu, struct softif_neigh_vid, rcu); + bat_priv = softif_neigh_vid->bat_priv; spin_lock_bh(&bat_priv->softif_neigh_lock); - - if (new_neigh && !atomic_inc_not_zero(&new_neigh->refcount)) - new_neigh = NULL; - - curr_neigh = bat_priv->softif_neigh; - rcu_assign_pointer(bat_priv->softif_neigh, new_neigh); - - if (curr_neigh) - softif_neigh_free_ref(curr_neigh); - + hlist_for_each_entry_safe(softif_neigh, node, node_tmp, + &softif_neigh_vid->softif_neigh_list, list) { + hlist_del_rcu(&softif_neigh->list); + softif_neigh_free_ref(softif_neigh); + } spin_unlock_bh(&bat_priv->softif_neigh_lock); + + kfree(softif_neigh_vid); } -static void softif_neigh_deselect(struct bat_priv *bat_priv) +static void softif_neigh_vid_free_ref(struct softif_neigh_vid *softif_neigh_vid) { - softif_neigh_select(bat_priv, NULL); + if (atomic_dec_and_test(&softif_neigh_vid->refcount)) + call_rcu(&softif_neigh_vid->rcu, softif_neigh_vid_free_rcu); } -void softif_neigh_purge(struct bat_priv *bat_priv) +static struct softif_neigh_vid *softif_neigh_vid_get(struct bat_priv *bat_priv, + short vid) { - struct softif_neigh *softif_neigh, *curr_softif_neigh; - struct hlist_node *node, *node_tmp; - char do_deselect = 0; - - curr_softif_neigh = softif_neigh_get_selected(bat_priv); - - spin_lock_bh(&bat_priv->softif_neigh_lock); - - hlist_for_each_entry_safe(softif_neigh, node, node_tmp, - &bat_priv->softif_neigh_list, list) { + struct softif_neigh_vid *softif_neigh_vid; + struct hlist_node *node; - if ((!time_after(jiffies, softif_neigh->last_seen + - msecs_to_jiffies(SOFTIF_NEIGH_TIMEOUT))) && - (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE)) + rcu_read_lock(); + hlist_for_each_entry_rcu(softif_neigh_vid, node, + &bat_priv->softif_neigh_vids, list) { + if (softif_neigh_vid->vid != vid) continue; - if (curr_softif_neigh == softif_neigh) { - bat_dbg(DBG_ROUTES, bat_priv, - "Current mesh exit point '%pM' vanished " - "(vid: %d).\n", - softif_neigh->addr, softif_neigh->vid); - do_deselect = 1; - } + if (!atomic_inc_not_zero(&softif_neigh_vid->refcount)) + continue; - hlist_del_rcu(&softif_neigh->list); - softif_neigh_free_ref(softif_neigh); + goto out; } - spin_unlock_bh(&bat_priv->softif_neigh_lock); + softif_neigh_vid = kzalloc(sizeof(struct softif_neigh_vid), + GFP_ATOMIC); + if (!softif_neigh_vid) + goto out; - /* soft_neigh_deselect() needs to acquire the softif_neigh_lock */ - if (do_deselect) - softif_neigh_deselect(bat_priv); + softif_neigh_vid->vid = vid; + softif_neigh_vid->bat_priv = bat_priv; - if (curr_softif_neigh) - softif_neigh_free_ref(curr_softif_neigh); + /* initialize with 2 - caller decrements counter by one */ + atomic_set(&softif_neigh_vid->refcount, 2); + INIT_HLIST_HEAD(&softif_neigh_vid->softif_neigh_list); + INIT_HLIST_NODE(&softif_neigh_vid->list); + spin_lock_bh(&bat_priv->softif_neigh_vid_lock); + hlist_add_head_rcu(&softif_neigh_vid->list, + &bat_priv->softif_neigh_vids); + spin_unlock_bh(&bat_priv->softif_neigh_vid_lock); + +out: + rcu_read_unlock(); + return softif_neigh_vid; } static struct softif_neigh *softif_neigh_get(struct bat_priv *bat_priv, uint8_t *addr, short vid) { - struct softif_neigh *softif_neigh; + struct softif_neigh_vid *softif_neigh_vid; + struct softif_neigh *softif_neigh = NULL; struct hlist_node *node; + softif_neigh_vid = softif_neigh_vid_get(bat_priv, vid); + if (!softif_neigh_vid) + goto out; + rcu_read_lock(); hlist_for_each_entry_rcu(softif_neigh, node, - &bat_priv->softif_neigh_list, list) { + &softif_neigh_vid->softif_neigh_list, + list) { if (!compare_eth(softif_neigh->addr, addr)) continue; - if (softif_neigh->vid != vid) - continue; - if (!atomic_inc_not_zero(&softif_neigh->refcount)) continue; softif_neigh->last_seen = jiffies; - goto out; + goto unlock; } softif_neigh = kzalloc(sizeof(struct softif_neigh), GFP_ATOMIC); if (!softif_neigh) - goto out; + goto unlock; memcpy(softif_neigh->addr, addr, ETH_ALEN); - softif_neigh->vid = vid; softif_neigh->last_seen = jiffies; /* initialize with 2 - caller decrements counter by one */ atomic_set(&softif_neigh->refcount, 2); INIT_HLIST_NODE(&softif_neigh->list); spin_lock_bh(&bat_priv->softif_neigh_lock); - hlist_add_head_rcu(&softif_neigh->list, &bat_priv->softif_neigh_list); + hlist_add_head_rcu(&softif_neigh->list, + &softif_neigh_vid->softif_neigh_list); spin_unlock_bh(&bat_priv->softif_neigh_lock); +unlock: + rcu_read_unlock(); out: + if (softif_neigh_vid) + softif_neigh_vid_free_ref(softif_neigh_vid); + return softif_neigh; +} + +static struct softif_neigh *softif_neigh_get_selected( + struct softif_neigh_vid *softif_neigh_vid) +{ + struct softif_neigh *softif_neigh; + + rcu_read_lock(); + softif_neigh = rcu_dereference(softif_neigh_vid->softif_neigh); + + if (softif_neigh && !atomic_inc_not_zero(&softif_neigh->refcount)) + softif_neigh = NULL; + rcu_read_unlock(); return softif_neigh; } +static struct softif_neigh *softif_neigh_vid_get_selected( + struct bat_priv *bat_priv, + short vid) +{ + struct softif_neigh_vid *softif_neigh_vid; + struct softif_neigh *softif_neigh = NULL; + + softif_neigh_vid = softif_neigh_vid_get(bat_priv, vid); + if (!softif_neigh_vid) + goto out; + + softif_neigh = softif_neigh_get_selected(softif_neigh_vid); +out: + if (softif_neigh_vid) + softif_neigh_vid_free_ref(softif_neigh_vid); + return softif_neigh; +} + +static void softif_neigh_vid_select(struct bat_priv *bat_priv, + struct softif_neigh *new_neigh, + short vid) +{ + struct softif_neigh_vid *softif_neigh_vid; + struct softif_neigh *curr_neigh; + + softif_neigh_vid = softif_neigh_vid_get(bat_priv, vid); + if (!softif_neigh_vid) + goto out; + + spin_lock_bh(&bat_priv->softif_neigh_lock); + + if (new_neigh && !atomic_inc_not_zero(&new_neigh->refcount)) + new_neigh = NULL; + + curr_neigh = softif_neigh_vid->softif_neigh; + rcu_assign_pointer(softif_neigh_vid->softif_neigh, new_neigh); + + if ((curr_neigh) && (!new_neigh)) + bat_dbg(DBG_ROUTES, bat_priv, + "Removing mesh exit point on vid: %d (prev: %pM).\n", + vid, curr_neigh->addr); + else if ((curr_neigh) && (new_neigh)) + bat_dbg(DBG_ROUTES, bat_priv, + "Changing mesh exit point on vid: %d from %pM " + "to %pM.\n", vid, curr_neigh->addr, new_neigh->addr); + else if ((!curr_neigh) && (new_neigh)) + bat_dbg(DBG_ROUTES, bat_priv, + "Setting mesh exit point on vid: %d to %pM.\n", + vid, new_neigh->addr); + + if (curr_neigh) + softif_neigh_free_ref(curr_neigh); + + spin_unlock_bh(&bat_priv->softif_neigh_lock); + +out: + if (softif_neigh_vid) + softif_neigh_vid_free_ref(softif_neigh_vid); +} + +static void softif_neigh_vid_deselect(struct bat_priv *bat_priv, + struct softif_neigh_vid *softif_neigh_vid) +{ + struct softif_neigh *curr_neigh; + struct softif_neigh *softif_neigh = NULL, *softif_neigh_tmp; + struct hard_iface *primary_if = NULL; + struct hlist_node *node; + + primary_if = primary_if_get_selected(bat_priv); + if (!primary_if) + goto out; + + /* find new softif_neigh immediately to avoid temporary loops */ + rcu_read_lock(); + curr_neigh = rcu_dereference(softif_neigh_vid->softif_neigh); + + hlist_for_each_entry_rcu(softif_neigh_tmp, node, + &softif_neigh_vid->softif_neigh_list, + list) { + if (softif_neigh_tmp == curr_neigh) + continue; + + /* we got a neighbor but its mac is 'bigger' than ours */ + if (memcmp(primary_if->net_dev->dev_addr, + softif_neigh_tmp->addr, ETH_ALEN) < 0) + continue; + + if (!atomic_inc_not_zero(&softif_neigh_tmp->refcount)) + continue; + + softif_neigh = softif_neigh_tmp; + goto unlock; + } + +unlock: + rcu_read_unlock(); +out: + softif_neigh_vid_select(bat_priv, softif_neigh, softif_neigh_vid->vid); + + if (primary_if) + hardif_free_ref(primary_if); + if (softif_neigh) + softif_neigh_free_ref(softif_neigh); +} + int softif_neigh_seq_print_text(struct seq_file *seq, void *offset) { struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); + struct softif_neigh_vid *softif_neigh_vid; struct softif_neigh *softif_neigh; struct hard_iface *primary_if; - struct hlist_node *node; + struct hlist_node *node, *node_tmp; struct softif_neigh *curr_softif_neigh; - int ret = 0; + int ret = 0, last_seen_secs, last_seen_msecs; primary_if = primary_if_get_selected(bat_priv); if (!primary_if) { @@ -237,17 +353,33 @@ int softif_neigh_seq_print_text(struct seq_file *seq, void *offset) seq_printf(seq, "Softif neighbor list (%s)\n", net_dev->name); - curr_softif_neigh = softif_neigh_get_selected(bat_priv); rcu_read_lock(); - hlist_for_each_entry_rcu(softif_neigh, node, - &bat_priv->softif_neigh_list, list) - seq_printf(seq, "%s %pM (vid: %d)\n", - curr_softif_neigh == softif_neigh - ? "=>" : " ", softif_neigh->addr, - softif_neigh->vid); + hlist_for_each_entry_rcu(softif_neigh_vid, node, + &bat_priv->softif_neigh_vids, list) { + seq_printf(seq, " %-15s %s on vid: %d\n", + "Originator", "last-seen", softif_neigh_vid->vid); + + curr_softif_neigh = softif_neigh_get_selected(softif_neigh_vid); + + hlist_for_each_entry_rcu(softif_neigh, node_tmp, + &softif_neigh_vid->softif_neigh_list, + list) { + last_seen_secs = jiffies_to_msecs(jiffies - + softif_neigh->last_seen) / 1000; + last_seen_msecs = jiffies_to_msecs(jiffies - + softif_neigh->last_seen) % 1000; + seq_printf(seq, "%s %pM %3i.%03is\n", + curr_softif_neigh == softif_neigh + ? "=>" : " ", softif_neigh->addr, + last_seen_secs, last_seen_msecs); + } + + if (curr_softif_neigh) + softif_neigh_free_ref(curr_softif_neigh); + + seq_printf(seq, "\n"); + } rcu_read_unlock(); - if (curr_softif_neigh) - softif_neigh_free_ref(curr_softif_neigh); out: if (primary_if) @@ -255,6 +387,70 @@ out: return ret; } +void softif_neigh_purge(struct bat_priv *bat_priv) +{ + struct softif_neigh *softif_neigh, *curr_softif_neigh; + struct softif_neigh_vid *softif_neigh_vid; + struct hlist_node *node, *node_tmp, *node_tmp2; + char do_deselect; + + rcu_read_lock(); + hlist_for_each_entry_rcu(softif_neigh_vid, node, + &bat_priv->softif_neigh_vids, list) { + if (!atomic_inc_not_zero(&softif_neigh_vid->refcount)) + continue; + + curr_softif_neigh = softif_neigh_get_selected(softif_neigh_vid); + do_deselect = 0; + + spin_lock_bh(&bat_priv->softif_neigh_lock); + hlist_for_each_entry_safe(softif_neigh, node_tmp, node_tmp2, + &softif_neigh_vid->softif_neigh_list, + list) { + if ((!time_after(jiffies, softif_neigh->last_seen + + msecs_to_jiffies(SOFTIF_NEIGH_TIMEOUT))) && + (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE)) + continue; + + if (curr_softif_neigh == softif_neigh) { + bat_dbg(DBG_ROUTES, bat_priv, + "Current mesh exit point on vid: %d " + "'%pM' vanished.\n", + softif_neigh_vid->vid, + softif_neigh->addr); + do_deselect = 1; + } + + hlist_del_rcu(&softif_neigh->list); + softif_neigh_free_ref(softif_neigh); + } + spin_unlock_bh(&bat_priv->softif_neigh_lock); + + /* soft_neigh_vid_deselect() needs to acquire the + * softif_neigh_lock */ + if (do_deselect) + softif_neigh_vid_deselect(bat_priv, softif_neigh_vid); + + if (curr_softif_neigh) + softif_neigh_free_ref(curr_softif_neigh); + + softif_neigh_vid_free_ref(softif_neigh_vid); + } + rcu_read_unlock(); + + spin_lock_bh(&bat_priv->softif_neigh_vid_lock); + hlist_for_each_entry_safe(softif_neigh_vid, node, node_tmp, + &bat_priv->softif_neigh_vids, list) { + if (!hlist_empty(&softif_neigh_vid->softif_neigh_list)) + continue; + + hlist_del_rcu(&softif_neigh_vid->list); + softif_neigh_vid_free_ref(softif_neigh_vid); + } + spin_unlock_bh(&bat_priv->softif_neigh_vid_lock); + +} + static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev, short vid) { @@ -287,10 +483,7 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev, if (!softif_neigh) goto out; - curr_softif_neigh = softif_neigh_get_selected(bat_priv); - if (!curr_softif_neigh) - goto out; - + curr_softif_neigh = softif_neigh_vid_get_selected(bat_priv, vid); if (curr_softif_neigh == softif_neigh) goto out; @@ -303,33 +496,16 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev, softif_neigh->addr, ETH_ALEN) < 0) goto out; - /* switch to new 'smallest neighbor' */ - if ((curr_softif_neigh) && - (memcmp(softif_neigh->addr, curr_softif_neigh->addr, - ETH_ALEN) < 0)) { - bat_dbg(DBG_ROUTES, bat_priv, - "Changing mesh exit point from %pM (vid: %d) " - "to %pM (vid: %d).\n", - curr_softif_neigh->addr, - curr_softif_neigh->vid, - softif_neigh->addr, softif_neigh->vid); - - softif_neigh_select(bat_priv, softif_neigh); - goto out; - } - /* close own batX device and use softif_neigh as exit node */ - if ((!curr_softif_neigh) && - (memcmp(softif_neigh->addr, - primary_if->net_dev->dev_addr, ETH_ALEN) < 0)) { - bat_dbg(DBG_ROUTES, bat_priv, - "Setting mesh exit point to %pM (vid: %d).\n", - softif_neigh->addr, softif_neigh->vid); - - softif_neigh_select(bat_priv, softif_neigh); + if (!curr_softif_neigh) { + softif_neigh_vid_select(bat_priv, softif_neigh, vid); goto out; } + /* switch to new 'smallest neighbor' */ + if (memcmp(softif_neigh->addr, curr_softif_neigh->addr, ETH_ALEN) < 0) + softif_neigh_vid_select(bat_priv, softif_neigh, vid); + out: kfree_skb(skb); if (softif_neigh) @@ -424,8 +600,8 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) * if we have a another chosen mesh exit node in range * it will transport the packets to the mesh */ - curr_softif_neigh = softif_neigh_get_selected(bat_priv); - if ((curr_softif_neigh) && (curr_softif_neigh->vid == vid)) + curr_softif_neigh = softif_neigh_vid_get_selected(bat_priv, vid); + if (curr_softif_neigh) goto dropped; /* TODO: check this for locks */ @@ -533,8 +709,8 @@ void interface_rx(struct net_device *soft_iface, * if we have a another chosen mesh exit node in range * it will transport the packets to the non-mesh network */ - curr_softif_neigh = softif_neigh_get_selected(bat_priv); - if (curr_softif_neigh && (curr_softif_neigh->vid == vid)) { + curr_softif_neigh = softif_neigh_vid_get_selected(bat_priv, vid); + if (curr_softif_neigh) { skb_push(skb, hdr_size); unicast_packet = (struct unicast_packet *)skb->data; @@ -671,7 +847,6 @@ struct net_device *softif_create(char *name) bat_priv->primary_if = NULL; bat_priv->num_ifaces = 0; - bat_priv->softif_neigh = NULL; ret = sysfs_add_meshif(soft_iface); if (ret < 0) diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 947bafc6431a..9ae507ab7bbe 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -146,14 +146,13 @@ struct bat_priv { atomic_t bcast_queue_left; atomic_t batman_queue_left; char num_ifaces; - struct hlist_head softif_neigh_list; - struct softif_neigh __rcu *softif_neigh; struct debug_log *debug_log; struct kobject *mesh_obj; struct dentry *debug_dir; struct hlist_head forw_bat_list; struct hlist_head forw_bcast_list; struct hlist_head gw_list; + struct hlist_head softif_neigh_vids; struct list_head vis_send_list; struct hashtable_t *orig_hash; struct hashtable_t *hna_local_hash; @@ -167,6 +166,7 @@ struct bat_priv { spinlock_t vis_hash_lock; /* protects vis_hash */ spinlock_t vis_list_lock; /* protects vis_info::recv_list */ spinlock_t softif_neigh_lock; /* protects soft-interface neigh list */ + spinlock_t softif_neigh_vid_lock; /* protects soft-interface vid list */ int16_t num_local_hna; atomic_t hna_local_changed; struct delayed_work hna_work; @@ -270,11 +270,20 @@ struct recvlist_node { uint8_t mac[ETH_ALEN]; }; +struct softif_neigh_vid { + struct hlist_node list; + struct bat_priv *bat_priv; + short vid; + atomic_t refcount; + struct softif_neigh __rcu *softif_neigh; + struct rcu_head rcu; + struct hlist_head softif_neigh_list; +}; + struct softif_neigh { struct hlist_node list; uint8_t addr[ETH_ALEN]; unsigned long last_seen; - short vid; atomic_t refcount; struct rcu_head rcu; }; -- cgit v1.2.3 From c3caf5196c47a5d1c325308d8eb7f6b020ba12df Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Tue, 3 May 2011 11:51:38 +0200 Subject: batman-adv: Remove unnecessary hardif_list_lock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit hardif_list_lock is unneccessary because we already ensure that no multiple admin operations can take place through rtnl_lock. hardif_list_lock only adds additional overhead and complexity. Critical functions now check whether they are called with rtnl_lock using ASSERT_RTNL. It indirectly fixes the problem that orig_hash_del_if() expects that only one interface is deleted from hardif_list at a time, but hardif_remove_interfaces() removes all at once and then calls orig_hash_del_if(). Reported-by: Linus Lüssing Signed-off-by: Sven Eckelmann --- net/batman-adv/bat_sysfs.c | 2 ++ net/batman-adv/hard-interface.c | 30 +++++++----------------------- net/batman-adv/main.c | 3 +++ net/batman-adv/soft-interface.c | 2 +- 4 files changed, 13 insertions(+), 24 deletions(-) (limited to 'net/batman-adv') diff --git a/net/batman-adv/bat_sysfs.c b/net/batman-adv/bat_sysfs.c index e449bf6353e0..85ba20d98a66 100644 --- a/net/batman-adv/bat_sysfs.c +++ b/net/batman-adv/bat_sysfs.c @@ -502,7 +502,9 @@ static ssize_t store_mesh_iface(struct kobject *kobj, struct attribute *attr, rtnl_unlock(); } + rtnl_lock(); ret = hardif_enable_interface(hard_iface, buff); + rtnl_unlock(); out: hardif_free_ref(hard_iface); diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index 3e888f133d75..7e2f7728f706 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c @@ -31,9 +31,6 @@ #include -/* protect update critical side of hardif_list - but not the content */ -static DEFINE_SPINLOCK(hardif_list_lock); - static int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, @@ -136,7 +133,7 @@ static void primary_if_select(struct bat_priv *bat_priv, struct hard_iface *curr_hard_iface; struct batman_packet *batman_packet; - spin_lock_bh(&hardif_list_lock); + ASSERT_RTNL(); if (new_hard_iface && !atomic_inc_not_zero(&new_hard_iface->refcount)) new_hard_iface = NULL; @@ -148,7 +145,7 @@ static void primary_if_select(struct bat_priv *bat_priv, hardif_free_ref(curr_hard_iface); if (!new_hard_iface) - goto out; + return; batman_packet = (struct batman_packet *)(new_hard_iface->packet_buff); batman_packet->flags = PRIMARIES_FIRST_HOP; @@ -161,9 +158,6 @@ static void primary_if_select(struct bat_priv *bat_priv, * our new primary interface */ atomic_set(&bat_priv->hna_local_changed, 1); - -out: - spin_unlock_bh(&hardif_list_lock); } static bool hardif_is_iface_up(struct hard_iface *hard_iface) @@ -456,6 +450,8 @@ static struct hard_iface *hardif_add_interface(struct net_device *net_dev) struct hard_iface *hard_iface; int ret; + ASSERT_RTNL(); + ret = is_valid_iface(net_dev); if (ret != 1) goto out; @@ -482,10 +478,7 @@ static struct hard_iface *hardif_add_interface(struct net_device *net_dev) atomic_set(&hard_iface->refcount, 2); check_known_mac_addr(hard_iface->net_dev); - - spin_lock(&hardif_list_lock); list_add_tail_rcu(&hard_iface->list, &hardif_list); - spin_unlock(&hardif_list_lock); return hard_iface; @@ -499,6 +492,8 @@ out: static void hardif_remove_interface(struct hard_iface *hard_iface) { + ASSERT_RTNL(); + /* first deactivate interface */ if (hard_iface->if_status != IF_NOT_IN_USE) hardif_disable_interface(hard_iface); @@ -514,20 +509,11 @@ static void hardif_remove_interface(struct hard_iface *hard_iface) void hardif_remove_interfaces(void) { struct hard_iface *hard_iface, *hard_iface_tmp; - struct list_head if_queue; - - INIT_LIST_HEAD(&if_queue); - spin_lock(&hardif_list_lock); + rtnl_lock(); list_for_each_entry_safe(hard_iface, hard_iface_tmp, &hardif_list, list) { list_del_rcu(&hard_iface->list); - list_add_tail(&hard_iface->list, &if_queue); - } - spin_unlock(&hardif_list_lock); - - rtnl_lock(); - list_for_each_entry_safe(hard_iface, hard_iface_tmp, &if_queue, list) { hardif_remove_interface(hard_iface); } rtnl_unlock(); @@ -556,9 +542,7 @@ static int hard_if_event(struct notifier_block *this, hardif_deactivate_interface(hard_iface); break; case NETDEV_UNREGISTER: - spin_lock(&hardif_list_lock); list_del_rcu(&hard_iface->list); - spin_unlock(&hardif_list_lock); hardif_remove_interface(hard_iface); break; diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index 705e8be07c8d..7edf8d719e15 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c @@ -33,6 +33,9 @@ #include "vis.h" #include "hash.h" + +/* List manipulations on hardif_list have to be rtnl_lock()'ed, + * list traversals just rcu-locked */ struct list_head hardif_list; unsigned char broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 8cb13a03b0e1..9301e21052e7 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -819,7 +819,7 @@ struct net_device *softif_create(char *name) goto out; } - ret = register_netdev(soft_iface); + ret = register_netdevice(soft_iface); if (ret < 0) { pr_err("Unable to register the batman interface '%s': %i\n", name, ret); -- cgit v1.2.3 From 3a4375a9f0080e6ae40af63e2e2c1e70a6dcb775 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Tue, 3 May 2011 13:10:06 +0200 Subject: batman-adv: Avoid deadlock between rtnl_lock and s_active The hard_if_event is called by the notifier with rtnl_lock and tries to remove sysfs entries when a NETDEV_UNREGISTER event is received. This will automatically take the s_active lock. The s_active lock is also used when a new interface is added to a meshif through sysfs. In that situation we cannot wait for the rntl_lock before creating the actual batman-adv interface to prevent a deadlock. It is still possible to try to get the rtnl_lock and immediately abort the current operation when the trylock call failed. Signed-off-by: Sven Eckelmann --- net/batman-adv/bat_sysfs.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'net/batman-adv') diff --git a/net/batman-adv/bat_sysfs.c b/net/batman-adv/bat_sysfs.c index 85ba20d98a66..497a0700cc3c 100644 --- a/net/batman-adv/bat_sysfs.c +++ b/net/batman-adv/bat_sysfs.c @@ -488,24 +488,24 @@ static ssize_t store_mesh_iface(struct kobject *kobj, struct attribute *attr, (strncmp(hard_iface->soft_iface->name, buff, IFNAMSIZ) == 0)) goto out; + if (!rtnl_trylock()) { + ret = -ERESTARTSYS; + goto out; + } + if (status_tmp == IF_NOT_IN_USE) { - rtnl_lock(); hardif_disable_interface(hard_iface); - rtnl_unlock(); - goto out; + goto unlock; } /* if the interface already is in use */ - if (hard_iface->if_status != IF_NOT_IN_USE) { - rtnl_lock(); + if (hard_iface->if_status != IF_NOT_IN_USE) hardif_disable_interface(hard_iface); - rtnl_unlock(); - } - rtnl_lock(); ret = hardif_enable_interface(hard_iface, buff); - rtnl_unlock(); +unlock: + rtnl_unlock(); out: hardif_free_ref(hard_iface); return ret; -- cgit v1.2.3 From 01df2b65e97735547ce37844f4134b5ea99b4037 Mon Sep 17 00:00:00 2001 From: Marek Lindner Date: Thu, 5 May 2011 14:14:46 +0200 Subject: batman-adv: Fix refcount imbalance in find_router Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann --- net/batman-adv/routing.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'net/batman-adv') diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index 49f571553050..d8cde2b8d1cf 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -1213,7 +1213,7 @@ struct neigh_node *find_router(struct bat_priv *bat_priv, router = orig_node_get_router(orig_node); if (!router) - return NULL; + goto err; /* without bonding, the first node should * always choose the default router. */ @@ -1222,10 +1222,8 @@ struct neigh_node *find_router(struct bat_priv *bat_priv, rcu_read_lock(); /* select default router to output */ router_orig = router->orig_node; - if (!router_orig) { - rcu_read_unlock(); - return NULL; - } + if (!router_orig) + goto err_unlock; if ((!recv_if) && (!bonding_enabled)) goto return_router; @@ -1268,6 +1266,12 @@ struct neigh_node *find_router(struct bat_priv *bat_priv, return_router: rcu_read_unlock(); return router; +err_unlock: + rcu_read_unlock(); +err: + if (router) + neigh_node_free_ref(router); + return NULL; } static int check_unicast_packet(struct sk_buff *skb, int hdr_size) -- cgit v1.2.3 From 2dafb49d84a9195193b28ac5047df1bbab6053b9 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Thu, 5 May 2011 08:42:45 +0200 Subject: batman-adv: rename everything from *hna* into *tt* (translation table) To be coherent, all the functions/variables/constants have been renamed to the TranslationTable style Signed-off-by: Antonio Quartulli Signed-off-by: Sven Eckelmann --- net/batman-adv/aggregation.c | 16 +- net/batman-adv/aggregation.h | 4 +- net/batman-adv/bat_debugfs.c | 4 +- net/batman-adv/hard-interface.c | 6 +- net/batman-adv/main.c | 14 +- net/batman-adv/main.h | 4 +- net/batman-adv/originator.c | 8 +- net/batman-adv/packet.h | 2 +- net/batman-adv/routing.c | 74 +++---- net/batman-adv/routing.h | 6 +- net/batman-adv/send.c | 16 +- net/batman-adv/send.h | 2 +- net/batman-adv/soft-interface.c | 10 +- net/batman-adv/translation-table.c | 417 +++++++++++++++++++------------------ net/batman-adv/translation-table.h | 24 +-- net/batman-adv/types.h | 24 +-- net/batman-adv/unicast.c | 2 +- net/batman-adv/vis.c | 18 +- 18 files changed, 326 insertions(+), 325 deletions(-) (limited to 'net/batman-adv') diff --git a/net/batman-adv/aggregation.c b/net/batman-adv/aggregation.c index c11788c4c1a1..9b9459024479 100644 --- a/net/batman-adv/aggregation.c +++ b/net/batman-adv/aggregation.c @@ -24,10 +24,10 @@ #include "send.h" #include "routing.h" -/* calculate the size of the hna information for a given packet */ -static int hna_len(struct batman_packet *batman_packet) +/* calculate the size of the tt information for a given packet */ +static int tt_len(struct batman_packet *batman_packet) { - return batman_packet->num_hna * ETH_ALEN; + return batman_packet->num_tt * ETH_ALEN; } /* return true if new_packet can be aggregated with forw_packet */ @@ -250,7 +250,7 @@ void receive_aggr_bat_packet(struct ethhdr *ethhdr, unsigned char *packet_buff, { struct batman_packet *batman_packet; int buff_pos = 0; - unsigned char *hna_buff; + unsigned char *tt_buff; batman_packet = (struct batman_packet *)packet_buff; @@ -259,14 +259,14 @@ void receive_aggr_bat_packet(struct ethhdr *ethhdr, unsigned char *packet_buff, orig_interval. */ batman_packet->seqno = ntohl(batman_packet->seqno); - hna_buff = packet_buff + buff_pos + BAT_PACKET_LEN; + tt_buff = packet_buff + buff_pos + BAT_PACKET_LEN; receive_bat_packet(ethhdr, batman_packet, - hna_buff, hna_len(batman_packet), + tt_buff, tt_len(batman_packet), if_incoming); - buff_pos += BAT_PACKET_LEN + hna_len(batman_packet); + buff_pos += BAT_PACKET_LEN + tt_len(batman_packet); batman_packet = (struct batman_packet *) (packet_buff + buff_pos); } while (aggregated_packet(buff_pos, packet_len, - batman_packet->num_hna)); + batman_packet->num_tt)); } diff --git a/net/batman-adv/aggregation.h b/net/batman-adv/aggregation.h index 062204289d1f..7e6d72fbf540 100644 --- a/net/batman-adv/aggregation.h +++ b/net/batman-adv/aggregation.h @@ -25,9 +25,9 @@ #include "main.h" /* is there another aggregated packet here? */ -static inline int aggregated_packet(int buff_pos, int packet_len, int num_hna) +static inline int aggregated_packet(int buff_pos, int packet_len, int num_tt) { - int next_buff_pos = buff_pos + BAT_PACKET_LEN + (num_hna * ETH_ALEN); + int next_buff_pos = buff_pos + BAT_PACKET_LEN + (num_tt * ETH_ALEN); return (next_buff_pos <= packet_len) && (next_buff_pos <= MAX_AGGREGATION_BYTES); diff --git a/net/batman-adv/bat_debugfs.c b/net/batman-adv/bat_debugfs.c index 0e9d43509935..abaeec5f6247 100644 --- a/net/batman-adv/bat_debugfs.c +++ b/net/batman-adv/bat_debugfs.c @@ -241,13 +241,13 @@ static int softif_neigh_open(struct inode *inode, struct file *file) static int transtable_global_open(struct inode *inode, struct file *file) { struct net_device *net_dev = (struct net_device *)inode->i_private; - return single_open(file, hna_global_seq_print_text, net_dev); + return single_open(file, tt_global_seq_print_text, net_dev); } static int transtable_local_open(struct inode *inode, struct file *file) { struct net_device *net_dev = (struct net_device *)inode->i_private; - return single_open(file, hna_local_seq_print_text, net_dev); + return single_open(file, tt_local_seq_print_text, net_dev); } static int vis_data_open(struct inode *inode, struct file *file) diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index 7e2f7728f706..dfbfccc9fe40 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c @@ -154,10 +154,10 @@ static void primary_if_select(struct bat_priv *bat_priv, primary_if_update_addr(bat_priv); /*** - * hacky trick to make sure that we send the HNA information via + * hacky trick to make sure that we send the TT information via * our new primary interface */ - atomic_set(&bat_priv->hna_local_changed, 1); + atomic_set(&bat_priv->tt_local_changed, 1); } static bool hardif_is_iface_up(struct hard_iface *hard_iface) @@ -339,7 +339,7 @@ int hardif_enable_interface(struct hard_iface *hard_iface, char *iface_name) batman_packet->flags = 0; batman_packet->ttl = 2; batman_packet->tq = TQ_MAX_VALUE; - batman_packet->num_hna = 0; + batman_packet->num_tt = 0; hard_iface->if_num = bat_priv->num_ifaces; bat_priv->num_ifaces++; diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index 7edf8d719e15..0a7cee0076f4 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c @@ -84,8 +84,8 @@ int mesh_init(struct net_device *soft_iface) spin_lock_init(&bat_priv->forw_bat_list_lock); spin_lock_init(&bat_priv->forw_bcast_list_lock); - spin_lock_init(&bat_priv->hna_lhash_lock); - spin_lock_init(&bat_priv->hna_ghash_lock); + spin_lock_init(&bat_priv->tt_lhash_lock); + spin_lock_init(&bat_priv->tt_ghash_lock); spin_lock_init(&bat_priv->gw_list_lock); spin_lock_init(&bat_priv->vis_hash_lock); spin_lock_init(&bat_priv->vis_list_lock); @@ -100,13 +100,13 @@ int mesh_init(struct net_device *soft_iface) if (originator_init(bat_priv) < 1) goto err; - if (hna_local_init(bat_priv) < 1) + if (tt_local_init(bat_priv) < 1) goto err; - if (hna_global_init(bat_priv) < 1) + if (tt_global_init(bat_priv) < 1) goto err; - hna_local_add(soft_iface, soft_iface->dev_addr); + tt_local_add(soft_iface, soft_iface->dev_addr); if (vis_init(bat_priv) < 1) goto err; @@ -137,8 +137,8 @@ void mesh_free(struct net_device *soft_iface) gw_node_purge(bat_priv); originator_free(bat_priv); - hna_local_free(bat_priv); - hna_global_free(bat_priv); + tt_local_free(bat_priv); + tt_global_free(bat_priv); softif_neigh_purge(bat_priv); diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index ace72852ed7b..9ef6ef9b1e18 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h @@ -39,7 +39,7 @@ #define PURGE_TIMEOUT 200 /* purge originators after time in seconds if no * valid packet comes in -> TODO: check * influence on TQ_LOCAL_WINDOW_SIZE */ -#define LOCAL_HNA_TIMEOUT 3600 /* in seconds */ +#define TT_LOCAL_TIMEOUT 3600 /* in seconds */ #define TQ_LOCAL_WINDOW_SIZE 64 /* sliding packet range of received originator * messages in squence numbers (should be a @@ -89,7 +89,7 @@ #define DBG_BATMAN 1 /* all messages related to routing / flooding / * broadcasting / etc */ -#define DBG_ROUTES 2 /* route or hna added / changed / deleted */ +#define DBG_ROUTES 2 /* route or tt entry added / changed / deleted */ #define DBG_ALL 3 diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index 51af91b7a35b..080ec88330a3 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -142,7 +142,7 @@ static void orig_node_free_rcu(struct rcu_head *rcu) spin_unlock_bh(&orig_node->neigh_list_lock); frag_list_free(&orig_node->frag_list); - hna_global_del_orig(orig_node->bat_priv, orig_node, + tt_global_del_orig(orig_node->bat_priv, orig_node, "originator timed out"); kfree(orig_node->bcast_own); @@ -220,7 +220,7 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr) orig_node->bat_priv = bat_priv; memcpy(orig_node->orig, addr, ETH_ALEN); orig_node->router = NULL; - orig_node->hna_buff = NULL; + orig_node->tt_buff = NULL; orig_node->bcast_seqno_reset = jiffies - 1 - msecs_to_jiffies(RESET_PROTECTION_MS); orig_node->batman_seqno_reset = jiffies - 1 @@ -331,8 +331,8 @@ static bool purge_orig_node(struct bat_priv *bat_priv, &best_neigh_node)) { update_routes(bat_priv, orig_node, best_neigh_node, - orig_node->hna_buff, - orig_node->hna_buff_len); + orig_node->tt_buff, + orig_node->tt_buff_len); } } diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h index e7571879af3f..c225c3acc55f 100644 --- a/net/batman-adv/packet.h +++ b/net/batman-adv/packet.h @@ -61,7 +61,7 @@ struct batman_packet { uint8_t orig[6]; uint8_t prev_sender[6]; uint8_t ttl; - uint8_t num_hna; + uint8_t num_tt; uint8_t gw_flags; /* flags related to gateway class */ uint8_t align; } __packed; diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index d8cde2b8d1cf..7648b92aec47 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -64,28 +64,28 @@ void slide_own_bcast_window(struct hard_iface *hard_iface) } } -static void update_HNA(struct bat_priv *bat_priv, struct orig_node *orig_node, - unsigned char *hna_buff, int hna_buff_len) +static void update_TT(struct bat_priv *bat_priv, struct orig_node *orig_node, + unsigned char *tt_buff, int tt_buff_len) { - if ((hna_buff_len != orig_node->hna_buff_len) || - ((hna_buff_len > 0) && - (orig_node->hna_buff_len > 0) && - (memcmp(orig_node->hna_buff, hna_buff, hna_buff_len) != 0))) { - - if (orig_node->hna_buff_len > 0) - hna_global_del_orig(bat_priv, orig_node, - "originator changed hna"); - - if ((hna_buff_len > 0) && (hna_buff)) - hna_global_add_orig(bat_priv, orig_node, - hna_buff, hna_buff_len); + if ((tt_buff_len != orig_node->tt_buff_len) || + ((tt_buff_len > 0) && + (orig_node->tt_buff_len > 0) && + (memcmp(orig_node->tt_buff, tt_buff, tt_buff_len) != 0))) { + + if (orig_node->tt_buff_len > 0) + tt_global_del_orig(bat_priv, orig_node, + "originator changed tt"); + + if ((tt_buff_len > 0) && (tt_buff)) + tt_global_add_orig(bat_priv, orig_node, + tt_buff, tt_buff_len); } } static void update_route(struct bat_priv *bat_priv, struct orig_node *orig_node, struct neigh_node *neigh_node, - unsigned char *hna_buff, int hna_buff_len) + unsigned char *tt_buff, int tt_buff_len) { struct neigh_node *curr_router; @@ -96,7 +96,7 @@ static void update_route(struct bat_priv *bat_priv, bat_dbg(DBG_ROUTES, bat_priv, "Deleting route towards: %pM\n", orig_node->orig); - hna_global_del_orig(bat_priv, orig_node, + tt_global_del_orig(bat_priv, orig_node, "originator timed out"); /* route added */ @@ -105,8 +105,8 @@ static void update_route(struct bat_priv *bat_priv, bat_dbg(DBG_ROUTES, bat_priv, "Adding route towards: %pM (via %pM)\n", orig_node->orig, neigh_node->addr); - hna_global_add_orig(bat_priv, orig_node, - hna_buff, hna_buff_len); + tt_global_add_orig(bat_priv, orig_node, + tt_buff, tt_buff_len); /* route changed */ } else { @@ -135,8 +135,8 @@ static void update_route(struct bat_priv *bat_priv, void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node, - struct neigh_node *neigh_node, unsigned char *hna_buff, - int hna_buff_len) + struct neigh_node *neigh_node, unsigned char *tt_buff, + int tt_buff_len) { struct neigh_node *router = NULL; @@ -147,10 +147,10 @@ void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node, if (router != neigh_node) update_route(bat_priv, orig_node, neigh_node, - hna_buff, hna_buff_len); - /* may be just HNA changed */ + tt_buff, tt_buff_len); + /* may be just TT changed */ else - update_HNA(bat_priv, orig_node, hna_buff, hna_buff_len); + update_TT(bat_priv, orig_node, tt_buff, tt_buff_len); out: if (router) @@ -387,14 +387,14 @@ static void update_orig(struct bat_priv *bat_priv, struct ethhdr *ethhdr, struct batman_packet *batman_packet, struct hard_iface *if_incoming, - unsigned char *hna_buff, int hna_buff_len, + unsigned char *tt_buff, int tt_buff_len, char is_duplicate) { struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL; struct neigh_node *router = NULL; struct orig_node *orig_node_tmp; struct hlist_node *node; - int tmp_hna_buff_len; + int tmp_tt_buff_len; uint8_t bcast_own_sum_orig, bcast_own_sum_neigh; bat_dbg(DBG_BATMAN, bat_priv, "update_originator(): " @@ -459,18 +459,18 @@ static void update_orig(struct bat_priv *bat_priv, bonding_candidate_add(orig_node, neigh_node); - tmp_hna_buff_len = (hna_buff_len > batman_packet->num_hna * ETH_ALEN ? - batman_packet->num_hna * ETH_ALEN : hna_buff_len); + tmp_tt_buff_len = (tt_buff_len > batman_packet->num_tt * ETH_ALEN ? + batman_packet->num_tt * ETH_ALEN : tt_buff_len); /* if this neighbor already is our next hop there is nothing * to change */ router = orig_node_get_router(orig_node); if (router == neigh_node) - goto update_hna; + goto update_tt; /* if this neighbor does not offer a better TQ we won't consider it */ if (router && (router->tq_avg > neigh_node->tq_avg)) - goto update_hna; + goto update_tt; /* if the TQ is the same and the link not more symetric we * won't consider it either */ @@ -488,16 +488,16 @@ static void update_orig(struct bat_priv *bat_priv, spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock); if (bcast_own_sum_orig >= bcast_own_sum_neigh) - goto update_hna; + goto update_tt; } update_routes(bat_priv, orig_node, neigh_node, - hna_buff, tmp_hna_buff_len); + tt_buff, tmp_tt_buff_len); goto update_gw; -update_hna: +update_tt: update_routes(bat_priv, orig_node, router, - hna_buff, tmp_hna_buff_len); + tt_buff, tmp_tt_buff_len); update_gw: if (orig_node->gw_flags != batman_packet->gw_flags) @@ -621,7 +621,7 @@ out: void receive_bat_packet(struct ethhdr *ethhdr, struct batman_packet *batman_packet, - unsigned char *hna_buff, int hna_buff_len, + unsigned char *tt_buff, int tt_buff_len, struct hard_iface *if_incoming) { struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); @@ -818,14 +818,14 @@ void receive_bat_packet(struct ethhdr *ethhdr, ((orig_node->last_real_seqno == batman_packet->seqno) && (orig_node->last_ttl - 3 <= batman_packet->ttl)))) update_orig(bat_priv, orig_node, ethhdr, batman_packet, - if_incoming, hna_buff, hna_buff_len, is_duplicate); + if_incoming, tt_buff, tt_buff_len, is_duplicate); /* is single hop (direct) neighbor */ if (is_single_hop_neigh) { /* mark direct link on incoming interface */ schedule_forward_packet(orig_node, ethhdr, batman_packet, - 1, hna_buff_len, if_incoming); + 1, tt_buff_len, if_incoming); bat_dbg(DBG_BATMAN, bat_priv, "Forwarding packet: " "rebroadcast neighbor packet with direct link flag\n"); @@ -848,7 +848,7 @@ void receive_bat_packet(struct ethhdr *ethhdr, bat_dbg(DBG_BATMAN, bat_priv, "Forwarding packet: rebroadcast originator packet\n"); schedule_forward_packet(orig_node, ethhdr, batman_packet, - 0, hna_buff_len, if_incoming); + 0, tt_buff_len, if_incoming); out_neigh: if ((orig_neigh_node) && (!is_single_hop_neigh)) diff --git a/net/batman-adv/routing.h b/net/batman-adv/routing.h index b5a064c88a4f..870f29842b28 100644 --- a/net/batman-adv/routing.h +++ b/net/batman-adv/routing.h @@ -25,11 +25,11 @@ void slide_own_bcast_window(struct hard_iface *hard_iface); void receive_bat_packet(struct ethhdr *ethhdr, struct batman_packet *batman_packet, - unsigned char *hna_buff, int hna_buff_len, + unsigned char *tt_buff, int tt_buff_len, struct hard_iface *if_incoming); void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node, - struct neigh_node *neigh_node, unsigned char *hna_buff, - int hna_buff_len); + struct neigh_node *neigh_node, unsigned char *tt_buff, + int tt_buff_len); int route_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if); 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); diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c index 02b541a6dfef..f30d0c69ccbb 100644 --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c @@ -121,7 +121,7 @@ static void send_packet_to_if(struct forw_packet *forw_packet, /* adjust all flags and log packets */ while (aggregated_packet(buff_pos, forw_packet->packet_len, - batman_packet->num_hna)) { + batman_packet->num_tt)) { /* we might have aggregated direct link packets with an * ordinary base packet */ @@ -146,7 +146,7 @@ static void send_packet_to_if(struct forw_packet *forw_packet, hard_iface->net_dev->dev_addr); buff_pos += sizeof(struct batman_packet) + - (batman_packet->num_hna * ETH_ALEN); + (batman_packet->num_tt * ETH_ALEN); packet_num++; batman_packet = (struct batman_packet *) (forw_packet->skb->data + buff_pos); @@ -222,7 +222,7 @@ static void rebuild_batman_packet(struct bat_priv *bat_priv, struct batman_packet *batman_packet; new_len = sizeof(struct batman_packet) + - (bat_priv->num_local_hna * ETH_ALEN); + (bat_priv->num_local_tt * ETH_ALEN); new_buff = kmalloc(new_len, GFP_ATOMIC); /* keep old buffer if kmalloc should fail */ @@ -231,7 +231,7 @@ static void rebuild_batman_packet(struct bat_priv *bat_priv, sizeof(struct batman_packet)); batman_packet = (struct batman_packet *)new_buff; - batman_packet->num_hna = hna_local_fill_buffer(bat_priv, + batman_packet->num_tt = tt_local_fill_buffer(bat_priv, new_buff + sizeof(struct batman_packet), new_len - sizeof(struct batman_packet)); @@ -266,8 +266,8 @@ void schedule_own_packet(struct hard_iface *hard_iface) if (hard_iface->if_status == IF_TO_BE_ACTIVATED) hard_iface->if_status = IF_ACTIVE; - /* if local hna has changed and interface is a primary interface */ - if ((atomic_read(&bat_priv->hna_local_changed)) && + /* if local tt has changed and interface is a primary interface */ + if ((atomic_read(&bat_priv->tt_local_changed)) && (hard_iface == primary_if)) rebuild_batman_packet(bat_priv, hard_iface); @@ -309,7 +309,7 @@ void schedule_own_packet(struct hard_iface *hard_iface) void schedule_forward_packet(struct orig_node *orig_node, struct ethhdr *ethhdr, struct batman_packet *batman_packet, - uint8_t directlink, int hna_buff_len, + uint8_t directlink, int tt_buff_len, struct hard_iface *if_incoming) { struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); @@ -369,7 +369,7 @@ void schedule_forward_packet(struct orig_node *orig_node, send_time = forward_send_time(); add_bat_packet_to_list(bat_priv, (unsigned char *)batman_packet, - sizeof(struct batman_packet) + hna_buff_len, + sizeof(struct batman_packet) + tt_buff_len, if_incoming, 0, send_time); } diff --git a/net/batman-adv/send.h b/net/batman-adv/send.h index 7b2ff19c05e7..247172d71e4b 100644 --- a/net/batman-adv/send.h +++ b/net/batman-adv/send.h @@ -29,7 +29,7 @@ void schedule_own_packet(struct hard_iface *hard_iface); void schedule_forward_packet(struct orig_node *orig_node, struct ethhdr *ethhdr, struct batman_packet *batman_packet, - uint8_t directlink, int hna_buff_len, + uint8_t directlink, int tt_buff_len, struct hard_iface *if_outgoing); int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb); void send_outstanding_bat_packet(struct work_struct *work); diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 9301e21052e7..d6aaf9fa64d4 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -543,11 +543,11 @@ static int interface_set_mac_addr(struct net_device *dev, void *p) if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; - /* only modify hna-table if it has been initialised before */ + /* only modify transtable if it has been initialised before */ if (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE) { - hna_local_remove(bat_priv, dev->dev_addr, + tt_local_remove(bat_priv, dev->dev_addr, "mac address changed"); - hna_local_add(dev, addr->sa_data); + tt_local_add(dev, addr->sa_data); } memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); @@ -605,7 +605,7 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) goto dropped; /* TODO: check this for locks */ - hna_local_add(soft_iface, ethhdr->h_source); + tt_local_add(soft_iface, ethhdr->h_source); if (is_multicast_ether_addr(ethhdr->h_dest)) { ret = gw_is_target(bat_priv, skb); @@ -843,7 +843,7 @@ struct net_device *softif_create(char *name) atomic_set(&bat_priv->mesh_state, MESH_INACTIVE); atomic_set(&bat_priv->bcast_seqno, 1); - atomic_set(&bat_priv->hna_local_changed, 0); + atomic_set(&bat_priv->tt_local_changed, 0); bat_priv->primary_if = NULL; bat_priv->num_ifaces = 0; diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index f931830d630e..7b729660cbfd 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -26,40 +26,40 @@ #include "hash.h" #include "originator.h" -static void hna_local_purge(struct work_struct *work); -static void _hna_global_del_orig(struct bat_priv *bat_priv, - struct hna_global_entry *hna_global_entry, +static void tt_local_purge(struct work_struct *work); +static void _tt_global_del_orig(struct bat_priv *bat_priv, + struct tt_global_entry *tt_global_entry, char *message); /* returns 1 if they are the same mac addr */ -static int compare_lhna(struct hlist_node *node, void *data2) +static int compare_ltt(struct hlist_node *node, void *data2) { - void *data1 = container_of(node, struct hna_local_entry, hash_entry); + void *data1 = container_of(node, struct tt_local_entry, hash_entry); return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0); } /* returns 1 if they are the same mac addr */ -static int compare_ghna(struct hlist_node *node, void *data2) +static int compare_gtt(struct hlist_node *node, void *data2) { - void *data1 = container_of(node, struct hna_global_entry, hash_entry); + void *data1 = container_of(node, struct tt_global_entry, hash_entry); return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0); } -static void hna_local_start_timer(struct bat_priv *bat_priv) +static void tt_local_start_timer(struct bat_priv *bat_priv) { - INIT_DELAYED_WORK(&bat_priv->hna_work, hna_local_purge); - queue_delayed_work(bat_event_workqueue, &bat_priv->hna_work, 10 * HZ); + INIT_DELAYED_WORK(&bat_priv->tt_work, tt_local_purge); + queue_delayed_work(bat_event_workqueue, &bat_priv->tt_work, 10 * HZ); } -static struct hna_local_entry *hna_local_hash_find(struct bat_priv *bat_priv, +static struct tt_local_entry *tt_local_hash_find(struct bat_priv *bat_priv, void *data) { - struct hashtable_t *hash = bat_priv->hna_local_hash; + struct hashtable_t *hash = bat_priv->tt_local_hash; struct hlist_head *head; struct hlist_node *node; - struct hna_local_entry *hna_local_entry, *hna_local_entry_tmp = NULL; + struct tt_local_entry *tt_local_entry, *tt_local_entry_tmp = NULL; int index; if (!hash) @@ -69,26 +69,26 @@ static struct hna_local_entry *hna_local_hash_find(struct bat_priv *bat_priv, head = &hash->table[index]; rcu_read_lock(); - hlist_for_each_entry_rcu(hna_local_entry, node, head, hash_entry) { - if (!compare_eth(hna_local_entry, data)) + hlist_for_each_entry_rcu(tt_local_entry, node, head, hash_entry) { + if (!compare_eth(tt_local_entry, data)) continue; - hna_local_entry_tmp = hna_local_entry; + tt_local_entry_tmp = tt_local_entry; break; } rcu_read_unlock(); - return hna_local_entry_tmp; + return tt_local_entry_tmp; } -static struct hna_global_entry *hna_global_hash_find(struct bat_priv *bat_priv, +static struct tt_global_entry *tt_global_hash_find(struct bat_priv *bat_priv, void *data) { - struct hashtable_t *hash = bat_priv->hna_global_hash; + struct hashtable_t *hash = bat_priv->tt_global_hash; struct hlist_head *head; struct hlist_node *node; - struct hna_global_entry *hna_global_entry; - struct hna_global_entry *hna_global_entry_tmp = NULL; + struct tt_global_entry *tt_global_entry; + struct tt_global_entry *tt_global_entry_tmp = NULL; int index; if (!hash) @@ -98,125 +98,125 @@ static struct hna_global_entry *hna_global_hash_find(struct bat_priv *bat_priv, head = &hash->table[index]; rcu_read_lock(); - hlist_for_each_entry_rcu(hna_global_entry, node, head, hash_entry) { - if (!compare_eth(hna_global_entry, data)) + hlist_for_each_entry_rcu(tt_global_entry, node, head, hash_entry) { + if (!compare_eth(tt_global_entry, data)) continue; - hna_global_entry_tmp = hna_global_entry; + tt_global_entry_tmp = tt_global_entry; break; } rcu_read_unlock(); - return hna_global_entry_tmp; + return tt_global_entry_tmp; } -int hna_local_init(struct bat_priv *bat_priv) +int tt_local_init(struct bat_priv *bat_priv) { - if (bat_priv->hna_local_hash) + if (bat_priv->tt_local_hash) return 1; - bat_priv->hna_local_hash = hash_new(1024); + bat_priv->tt_local_hash = hash_new(1024); - if (!bat_priv->hna_local_hash) + if (!bat_priv->tt_local_hash) return 0; - atomic_set(&bat_priv->hna_local_changed, 0); - hna_local_start_timer(bat_priv); + atomic_set(&bat_priv->tt_local_changed, 0); + tt_local_start_timer(bat_priv); return 1; } -void hna_local_add(struct net_device *soft_iface, uint8_t *addr) +void tt_local_add(struct net_device *soft_iface, uint8_t *addr) { struct bat_priv *bat_priv = netdev_priv(soft_iface); - struct hna_local_entry *hna_local_entry; - struct hna_global_entry *hna_global_entry; + struct tt_local_entry *tt_local_entry; + struct tt_global_entry *tt_global_entry; int required_bytes; - spin_lock_bh(&bat_priv->hna_lhash_lock); - hna_local_entry = hna_local_hash_find(bat_priv, addr); - spin_unlock_bh(&bat_priv->hna_lhash_lock); + spin_lock_bh(&bat_priv->tt_lhash_lock); + tt_local_entry = tt_local_hash_find(bat_priv, addr); + spin_unlock_bh(&bat_priv->tt_lhash_lock); - if (hna_local_entry) { - hna_local_entry->last_seen = jiffies; + if (tt_local_entry) { + tt_local_entry->last_seen = jiffies; return; } /* only announce as many hosts as possible in the batman-packet and - space in batman_packet->num_hna That also should give a limit to + space in batman_packet->num_tt That also should give a limit to MAC-flooding. */ - required_bytes = (bat_priv->num_local_hna + 1) * ETH_ALEN; + required_bytes = (bat_priv->num_local_tt + 1) * ETH_ALEN; required_bytes += BAT_PACKET_LEN; if ((required_bytes > ETH_DATA_LEN) || (atomic_read(&bat_priv->aggregated_ogms) && required_bytes > MAX_AGGREGATION_BYTES) || - (bat_priv->num_local_hna + 1 > 255)) { + (bat_priv->num_local_tt + 1 > 255)) { bat_dbg(DBG_ROUTES, bat_priv, - "Can't add new local hna entry (%pM): " - "number of local hna entries exceeds packet size\n", + "Can't add new local tt entry (%pM): " + "number of local tt entries exceeds packet size\n", addr); return; } bat_dbg(DBG_ROUTES, bat_priv, - "Creating new local hna entry: %pM\n", addr); + "Creating new local tt entry: %pM\n", addr); - hna_local_entry = kmalloc(sizeof(struct hna_local_entry), GFP_ATOMIC); - if (!hna_local_entry) + tt_local_entry = kmalloc(sizeof(struct tt_local_entry), GFP_ATOMIC); + if (!tt_local_entry) return; - memcpy(hna_local_entry->addr, addr, ETH_ALEN); - hna_local_entry->last_seen = jiffies; + memcpy(tt_local_entry->addr, addr, ETH_ALEN); + tt_local_entry->last_seen = jiffies; /* the batman interface mac address should never be purged */ if (compare_eth(addr, soft_iface->dev_addr)) - hna_local_entry->never_purge = 1; + tt_local_entry->never_purge = 1; else - hna_local_entry->never_purge = 0; + tt_local_entry->never_purge = 0; - spin_lock_bh(&bat_priv->hna_lhash_lock); + spin_lock_bh(&bat_priv->tt_lhash_lock); - hash_add(bat_priv->hna_local_hash, compare_lhna, choose_orig, - hna_local_entry, &hna_local_entry->hash_entry); - bat_priv->num_local_hna++; - atomic_set(&bat_priv->hna_local_changed, 1); + hash_add(bat_priv->tt_local_hash, compare_ltt, choose_orig, + tt_local_entry, &tt_local_entry->hash_entry); + bat_priv->num_local_tt++; + atomic_set(&bat_priv->tt_local_changed, 1); - spin_unlock_bh(&bat_priv->hna_lhash_lock); + spin_unlock_bh(&bat_priv->tt_lhash_lock); /* remove address from global hash if present */ - spin_lock_bh(&bat_priv->hna_ghash_lock); + spin_lock_bh(&bat_priv->tt_ghash_lock); - hna_global_entry = hna_global_hash_find(bat_priv, addr); + tt_global_entry = tt_global_hash_find(bat_priv, addr); - if (hna_global_entry) - _hna_global_del_orig(bat_priv, hna_global_entry, - "local hna received"); + if (tt_global_entry) + _tt_global_del_orig(bat_priv, tt_global_entry, + "local tt received"); - spin_unlock_bh(&bat_priv->hna_ghash_lock); + spin_unlock_bh(&bat_priv->tt_ghash_lock); } -int hna_local_fill_buffer(struct bat_priv *bat_priv, +int tt_local_fill_buffer(struct bat_priv *bat_priv, unsigned char *buff, int buff_len) { - struct hashtable_t *hash = bat_priv->hna_local_hash; - struct hna_local_entry *hna_local_entry; + struct hashtable_t *hash = bat_priv->tt_local_hash; + struct tt_local_entry *tt_local_entry; struct hlist_node *node; struct hlist_head *head; int i, count = 0; - spin_lock_bh(&bat_priv->hna_lhash_lock); + spin_lock_bh(&bat_priv->tt_lhash_lock); for (i = 0; i < hash->size; i++) { head = &hash->table[i]; rcu_read_lock(); - hlist_for_each_entry_rcu(hna_local_entry, node, + hlist_for_each_entry_rcu(tt_local_entry, node, head, hash_entry) { if (buff_len < (count + 1) * ETH_ALEN) break; - memcpy(buff + (count * ETH_ALEN), hna_local_entry->addr, + memcpy(buff + (count * ETH_ALEN), tt_local_entry->addr, ETH_ALEN); count++; @@ -224,20 +224,20 @@ int hna_local_fill_buffer(struct bat_priv *bat_priv, rcu_read_unlock(); } - /* if we did not get all new local hnas see you next time ;-) */ - if (count == bat_priv->num_local_hna) - atomic_set(&bat_priv->hna_local_changed, 0); + /* if we did not get all new local tts see you next time ;-) */ + if (count == bat_priv->num_local_tt) + atomic_set(&bat_priv->tt_local_changed, 0); - spin_unlock_bh(&bat_priv->hna_lhash_lock); + spin_unlock_bh(&bat_priv->tt_lhash_lock); return count; } -int hna_local_seq_print_text(struct seq_file *seq, void *offset) +int tt_local_seq_print_text(struct seq_file *seq, void *offset) { struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); - struct hashtable_t *hash = bat_priv->hna_local_hash; - struct hna_local_entry *hna_local_entry; + struct hashtable_t *hash = bat_priv->tt_local_hash; + struct tt_local_entry *tt_local_entry; struct hard_iface *primary_if; struct hlist_node *node; struct hlist_head *head; @@ -261,10 +261,10 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset) } seq_printf(seq, "Locally retrieved addresses (from %s) " - "announced via HNA:\n", + "announced via TT:\n", net_dev->name); - spin_lock_bh(&bat_priv->hna_lhash_lock); + spin_lock_bh(&bat_priv->tt_lhash_lock); buf_size = 1; /* Estimate length for: " * xx:xx:xx:xx:xx:xx\n" */ @@ -279,7 +279,7 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset) buff = kmalloc(buf_size, GFP_ATOMIC); if (!buff) { - spin_unlock_bh(&bat_priv->hna_lhash_lock); + spin_unlock_bh(&bat_priv->tt_lhash_lock); ret = -ENOMEM; goto out; } @@ -291,15 +291,15 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset) head = &hash->table[i]; rcu_read_lock(); - hlist_for_each_entry_rcu(hna_local_entry, node, + hlist_for_each_entry_rcu(tt_local_entry, node, head, hash_entry) { pos += snprintf(buff + pos, 22, " * %pM\n", - hna_local_entry->addr); + tt_local_entry->addr); } rcu_read_unlock(); } - spin_unlock_bh(&bat_priv->hna_lhash_lock); + spin_unlock_bh(&bat_priv->tt_lhash_lock); seq_printf(seq, "%s", buff); kfree(buff); @@ -309,180 +309,180 @@ out: return ret; } -static void _hna_local_del(struct hlist_node *node, void *arg) +static void _tt_local_del(struct hlist_node *node, void *arg) { struct bat_priv *bat_priv = (struct bat_priv *)arg; - void *data = container_of(node, struct hna_local_entry, hash_entry); + void *data = container_of(node, struct tt_local_entry, hash_entry); kfree(data); - bat_priv->num_local_hna--; - atomic_set(&bat_priv->hna_local_changed, 1); + bat_priv->num_local_tt--; + atomic_set(&bat_priv->tt_local_changed, 1); } -static void hna_local_del(struct bat_priv *bat_priv, - struct hna_local_entry *hna_local_entry, +static void tt_local_del(struct bat_priv *bat_priv, + struct tt_local_entry *tt_local_entry, char *message) { - bat_dbg(DBG_ROUTES, bat_priv, "Deleting local hna entry (%pM): %s\n", - hna_local_entry->addr, message); + bat_dbg(DBG_ROUTES, bat_priv, "Deleting local tt entry (%pM): %s\n", + tt_local_entry->addr, message); - hash_remove(bat_priv->hna_local_hash, compare_lhna, choose_orig, - hna_local_entry->addr); - _hna_local_del(&hna_local_entry->hash_entry, bat_priv); + hash_remove(bat_priv->tt_local_hash, compare_ltt, choose_orig, + tt_local_entry->addr); + _tt_local_del(&tt_local_entry->hash_entry, bat_priv); } -void hna_local_remove(struct bat_priv *bat_priv, +void tt_local_remove(struct bat_priv *bat_priv, uint8_t *addr, char *message) { - struct hna_local_entry *hna_local_entry; + struct tt_local_entry *tt_local_entry; - spin_lock_bh(&bat_priv->hna_lhash_lock); + spin_lock_bh(&bat_priv->tt_lhash_lock); - hna_local_entry = hna_local_hash_find(bat_priv, addr); + tt_local_entry = tt_local_hash_find(bat_priv, addr); - if (hna_local_entry) - hna_local_del(bat_priv, hna_local_entry, message); + if (tt_local_entry) + tt_local_del(bat_priv, tt_local_entry, message); - spin_unlock_bh(&bat_priv->hna_lhash_lock); + spin_unlock_bh(&bat_priv->tt_lhash_lock); } -static void hna_local_purge(struct work_struct *work) +static void tt_local_purge(struct work_struct *work) { struct delayed_work *delayed_work = container_of(work, struct delayed_work, work); struct bat_priv *bat_priv = - container_of(delayed_work, struct bat_priv, hna_work); - struct hashtable_t *hash = bat_priv->hna_local_hash; - struct hna_local_entry *hna_local_entry; + container_of(delayed_work, struct bat_priv, tt_work); + struct hashtable_t *hash = bat_priv->tt_local_hash; + struct tt_local_entry *tt_local_entry; struct hlist_node *node, *node_tmp; struct hlist_head *head; unsigned long timeout; int i; - spin_lock_bh(&bat_priv->hna_lhash_lock); + spin_lock_bh(&bat_priv->tt_lhash_lock); for (i = 0; i < hash->size; i++) { head = &hash->table[i]; - hlist_for_each_entry_safe(hna_local_entry, node, node_tmp, + hlist_for_each_entry_safe(tt_local_entry, node, node_tmp, head, hash_entry) { - if (hna_local_entry->never_purge) + if (tt_local_entry->never_purge) continue; - timeout = hna_local_entry->last_seen; - timeout += LOCAL_HNA_TIMEOUT * HZ; + timeout = tt_local_entry->last_seen; + timeout += TT_LOCAL_TIMEOUT * HZ; if (time_before(jiffies, timeout)) continue; - hna_local_del(bat_priv, hna_local_entry, + tt_local_del(bat_priv, tt_local_entry, "address timed out"); } } - spin_unlock_bh(&bat_priv->hna_lhash_lock); - hna_local_start_timer(bat_priv); + spin_unlock_bh(&bat_priv->tt_lhash_lock); + tt_local_start_timer(bat_priv); } -void hna_local_free(struct bat_priv *bat_priv) +void tt_local_free(struct bat_priv *bat_priv) { - if (!bat_priv->hna_local_hash) + if (!bat_priv->tt_local_hash) return; - cancel_delayed_work_sync(&bat_priv->hna_work); - hash_delete(bat_priv->hna_local_hash, _hna_local_del, bat_priv); - bat_priv->hna_local_hash = NULL; + cancel_delayed_work_sync(&bat_priv->tt_work); + hash_delete(bat_priv->tt_local_hash, _tt_local_del, bat_priv); + bat_priv->tt_local_hash = NULL; } -int hna_global_init(struct bat_priv *bat_priv) +int tt_global_init(struct bat_priv *bat_priv) { - if (bat_priv->hna_global_hash) + if (bat_priv->tt_global_hash) return 1; - bat_priv->hna_global_hash = hash_new(1024); + bat_priv->tt_global_hash = hash_new(1024); - if (!bat_priv->hna_global_hash) + if (!bat_priv->tt_global_hash) return 0; return 1; } -void hna_global_add_orig(struct bat_priv *bat_priv, +void tt_global_add_orig(struct bat_priv *bat_priv, struct orig_node *orig_node, - unsigned char *hna_buff, int hna_buff_len) + unsigned char *tt_buff, int tt_buff_len) { - struct hna_global_entry *hna_global_entry; - struct hna_local_entry *hna_local_entry; - int hna_buff_count = 0; - unsigned char *hna_ptr; + struct tt_global_entry *tt_global_entry; + struct tt_local_entry *tt_local_entry; + int tt_buff_count = 0; + unsigned char *tt_ptr; - while ((hna_buff_count + 1) * ETH_ALEN <= hna_buff_len) { - spin_lock_bh(&bat_priv->hna_ghash_lock); + while ((tt_buff_count + 1) * ETH_ALEN <= tt_buff_len) { + spin_lock_bh(&bat_priv->tt_ghash_lock); - hna_ptr = hna_buff + (hna_buff_count * ETH_ALEN); - hna_global_entry = hna_global_hash_find(bat_priv, hna_ptr); + tt_ptr = tt_buff + (tt_buff_count * ETH_ALEN); + tt_global_entry = tt_global_hash_find(bat_priv, tt_ptr); - if (!hna_global_entry) { - spin_unlock_bh(&bat_priv->hna_ghash_lock); + if (!tt_global_entry) { + spin_unlock_bh(&bat_priv->tt_ghash_lock); - hna_global_entry = - kmalloc(sizeof(struct hna_global_entry), + tt_global_entry = + kmalloc(sizeof(struct tt_global_entry), GFP_ATOMIC); - if (!hna_global_entry) + if (!tt_global_entry) break; - memcpy(hna_global_entry->addr, hna_ptr, ETH_ALEN); + memcpy(tt_global_entry->addr, tt_ptr, ETH_ALEN); bat_dbg(DBG_ROUTES, bat_priv, - "Creating new global hna entry: " + "Creating new global tt entry: " "%pM (via %pM)\n", - hna_global_entry->addr, orig_node->orig); + tt_global_entry->addr, orig_node->orig); - spin_lock_bh(&bat_priv->hna_ghash_lock); - hash_add(bat_priv->hna_global_hash, compare_ghna, - choose_orig, hna_global_entry, - &hna_global_entry->hash_entry); + spin_lock_bh(&bat_priv->tt_ghash_lock); + hash_add(bat_priv->tt_global_hash, compare_gtt, + choose_orig, tt_global_entry, + &tt_global_entry->hash_entry); } - hna_global_entry->orig_node = orig_node; - spin_unlock_bh(&bat_priv->hna_ghash_lock); + tt_global_entry->orig_node = orig_node; + spin_unlock_bh(&bat_priv->tt_ghash_lock); /* remove address from local hash if present */ - spin_lock_bh(&bat_priv->hna_lhash_lock); + spin_lock_bh(&bat_priv->tt_lhash_lock); - hna_ptr = hna_buff + (hna_buff_count * ETH_ALEN); - hna_local_entry = hna_local_hash_find(bat_priv, hna_ptr); + tt_ptr = tt_buff + (tt_buff_count * ETH_ALEN); + tt_local_entry = tt_local_hash_find(bat_priv, tt_ptr); - if (hna_local_entry) - hna_local_del(bat_priv, hna_local_entry, - "global hna received"); + if (tt_local_entry) + tt_local_del(bat_priv, tt_local_entry, + "global tt received"); - spin_unlock_bh(&bat_priv->hna_lhash_lock); + spin_unlock_bh(&bat_priv->tt_lhash_lock); - hna_buff_count++; + tt_buff_count++; } /* initialize, and overwrite if malloc succeeds */ - orig_node->hna_buff = NULL; - orig_node->hna_buff_len = 0; - - if (hna_buff_len > 0) { - orig_node->hna_buff = kmalloc(hna_buff_len, GFP_ATOMIC); - if (orig_node->hna_buff) { - memcpy(orig_node->hna_buff, hna_buff, hna_buff_len); - orig_node->hna_buff_len = hna_buff_len; + orig_node->tt_buff = NULL; + orig_node->tt_buff_len = 0; + + if (tt_buff_len > 0) { + orig_node->tt_buff = kmalloc(tt_buff_len, GFP_ATOMIC); + if (orig_node->tt_buff) { + memcpy(orig_node->tt_buff, tt_buff, tt_buff_len); + orig_node->tt_buff_len = tt_buff_len; } } } -int hna_global_seq_print_text(struct seq_file *seq, void *offset) +int tt_global_seq_print_text(struct seq_file *seq, void *offset) { struct net_device *net_dev = (struct net_device *)seq->private; struct bat_priv *bat_priv = netdev_priv(net_dev); - struct hashtable_t *hash = bat_priv->hna_global_hash; - struct hna_global_entry *hna_global_entry; + struct hashtable_t *hash = bat_priv->tt_global_hash; + struct tt_global_entry *tt_global_entry; struct hard_iface *primary_if; struct hlist_node *node; struct hlist_head *head; @@ -505,10 +505,11 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset) goto out; } - seq_printf(seq, "Globally announced HNAs received via the mesh %s\n", + seq_printf(seq, + "Globally announced TT entries received via the mesh %s\n", net_dev->name); - spin_lock_bh(&bat_priv->hna_ghash_lock); + spin_lock_bh(&bat_priv->tt_ghash_lock); buf_size = 1; /* Estimate length for: " * xx:xx:xx:xx:xx:xx via xx:xx:xx:xx:xx:xx\n"*/ @@ -523,7 +524,7 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset) buff = kmalloc(buf_size, GFP_ATOMIC); if (!buff) { - spin_unlock_bh(&bat_priv->hna_ghash_lock); + spin_unlock_bh(&bat_priv->tt_ghash_lock); ret = -ENOMEM; goto out; } @@ -534,17 +535,17 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset) head = &hash->table[i]; rcu_read_lock(); - hlist_for_each_entry_rcu(hna_global_entry, node, + hlist_for_each_entry_rcu(tt_global_entry, node, head, hash_entry) { pos += snprintf(buff + pos, 44, " * %pM via %pM\n", - hna_global_entry->addr, - hna_global_entry->orig_node->orig); + tt_global_entry->addr, + tt_global_entry->orig_node->orig); } rcu_read_unlock(); } - spin_unlock_bh(&bat_priv->hna_ghash_lock); + spin_unlock_bh(&bat_priv->tt_ghash_lock); seq_printf(seq, "%s", buff); kfree(buff); @@ -554,84 +555,84 @@ out: return ret; } -static void _hna_global_del_orig(struct bat_priv *bat_priv, - struct hna_global_entry *hna_global_entry, +static void _tt_global_del_orig(struct bat_priv *bat_priv, + struct tt_global_entry *tt_global_entry, char *message) { bat_dbg(DBG_ROUTES, bat_priv, - "Deleting global hna entry %pM (via %pM): %s\n", - hna_global_entry->addr, hna_global_entry->orig_node->orig, + "Deleting global tt entry %pM (via %pM): %s\n", + tt_global_entry->addr, tt_global_entry->orig_node->orig, message); - hash_remove(bat_priv->hna_global_hash, compare_ghna, choose_orig, - hna_global_entry->addr); - kfree(hna_global_entry); + hash_remove(bat_priv->tt_global_hash, compare_gtt, choose_orig, + tt_global_entry->addr); + kfree(tt_global_entry); } -void hna_global_del_orig(struct bat_priv *bat_priv, +void tt_global_del_orig(struct bat_priv *bat_priv, struct orig_node *orig_node, char *message) { - struct hna_global_entry *hna_global_entry; - int hna_buff_count = 0; - unsigned char *hna_ptr; + struct tt_global_entry *tt_global_entry; + int tt_buff_count = 0; + unsigned char *tt_ptr; - if (orig_node->hna_buff_len == 0) + if (orig_node->tt_buff_len == 0) return; - spin_lock_bh(&bat_priv->hna_ghash_lock); + spin_lock_bh(&bat_priv->tt_ghash_lock); - while ((hna_buff_count + 1) * ETH_ALEN <= orig_node->hna_buff_len) { - hna_ptr = orig_node->hna_buff + (hna_buff_count * ETH_ALEN); - hna_global_entry = hna_global_hash_find(bat_priv, hna_ptr); + while ((tt_buff_count + 1) * ETH_ALEN <= orig_node->tt_buff_len) { + tt_ptr = orig_node->tt_buff + (tt_buff_count * ETH_ALEN); + tt_global_entry = tt_global_hash_find(bat_priv, tt_ptr); - if ((hna_global_entry) && - (hna_global_entry->orig_node == orig_node)) - _hna_global_del_orig(bat_priv, hna_global_entry, + if ((tt_global_entry) && + (tt_global_entry->orig_node == orig_node)) + _tt_global_del_orig(bat_priv, tt_global_entry, message); - hna_buff_count++; + tt_buff_count++; } - spin_unlock_bh(&bat_priv->hna_ghash_lock); + spin_unlock_bh(&bat_priv->tt_ghash_lock); - orig_node->hna_buff_len = 0; - kfree(orig_node->hna_buff); - orig_node->hna_buff = NULL; + orig_node->tt_buff_len = 0; + kfree(orig_node->tt_buff); + orig_node->tt_buff = NULL; } -static void hna_global_del(struct hlist_node *node, void *arg) +static void tt_global_del(struct hlist_node *node, void *arg) { - void *data = container_of(node, struct hna_global_entry, hash_entry); + void *data = container_of(node, struct tt_global_entry, hash_entry); kfree(data); } -void hna_global_free(struct bat_priv *bat_priv) +void tt_global_free(struct bat_priv *bat_priv) { - if (!bat_priv->hna_global_hash) + if (!bat_priv->tt_global_hash) return; - hash_delete(bat_priv->hna_global_hash, hna_global_del, NULL); - bat_priv->hna_global_hash = NULL; + hash_delete(bat_priv->tt_global_hash, tt_global_del, NULL); + bat_priv->tt_global_hash = NULL; } struct orig_node *transtable_search(struct bat_priv *bat_priv, uint8_t *addr) { - struct hna_global_entry *hna_global_entry; + struct tt_global_entry *tt_global_entry; struct orig_node *orig_node = NULL; - spin_lock_bh(&bat_priv->hna_ghash_lock); - hna_global_entry = hna_global_hash_find(bat_priv, addr); + spin_lock_bh(&bat_priv->tt_ghash_lock); + tt_global_entry = tt_global_hash_find(bat_priv, addr); - if (!hna_global_entry) + if (!tt_global_entry) goto out; - if (!atomic_inc_not_zero(&hna_global_entry->orig_node->refcount)) + if (!atomic_inc_not_zero(&tt_global_entry->orig_node->refcount)) goto out; - orig_node = hna_global_entry->orig_node; + orig_node = tt_global_entry->orig_node; out: - spin_unlock_bh(&bat_priv->hna_ghash_lock); + spin_unlock_bh(&bat_priv->tt_ghash_lock); return orig_node; } diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h index f19931ca1457..46152c38cc95 100644 --- a/net/batman-adv/translation-table.h +++ b/net/batman-adv/translation-table.h @@ -22,22 +22,22 @@ #ifndef _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ #define _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ -int hna_local_init(struct bat_priv *bat_priv); -void hna_local_add(struct net_device *soft_iface, uint8_t *addr); -void hna_local_remove(struct bat_priv *bat_priv, +int tt_local_init(struct bat_priv *bat_priv); +void tt_local_add(struct net_device *soft_iface, uint8_t *addr); +void tt_local_remove(struct bat_priv *bat_priv, uint8_t *addr, char *message); -int hna_local_fill_buffer(struct bat_priv *bat_priv, +int tt_local_fill_buffer(struct bat_priv *bat_priv, unsigned char *buff, int buff_len); -int hna_local_seq_print_text(struct seq_file *seq, void *offset); -void hna_local_free(struct bat_priv *bat_priv); -int hna_global_init(struct bat_priv *bat_priv); -void hna_global_add_orig(struct bat_priv *bat_priv, +int tt_local_seq_print_text(struct seq_file *seq, void *offset); +void tt_local_free(struct bat_priv *bat_priv); +int tt_global_init(struct bat_priv *bat_priv); +void tt_global_add_orig(struct bat_priv *bat_priv, struct orig_node *orig_node, - unsigned char *hna_buff, int hna_buff_len); -int hna_global_seq_print_text(struct seq_file *seq, void *offset); -void hna_global_del_orig(struct bat_priv *bat_priv, + unsigned char *tt_buff, int tt_buff_len); +int tt_global_seq_print_text(struct seq_file *seq, void *offset); +void tt_global_del_orig(struct bat_priv *bat_priv, struct orig_node *orig_node, char *message); -void hna_global_free(struct bat_priv *bat_priv); +void tt_global_free(struct bat_priv *bat_priv); struct orig_node *transtable_search(struct bat_priv *bat_priv, uint8_t *addr); #endif /* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */ diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 9ae507ab7bbe..6b6c32e01c54 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -75,8 +75,8 @@ struct orig_node { unsigned long batman_seqno_reset; uint8_t gw_flags; uint8_t flags; - unsigned char *hna_buff; - int16_t hna_buff_len; + unsigned char *tt_buff; + int16_t tt_buff_len; uint32_t last_real_seqno; uint8_t last_ttl; unsigned long bcast_bits[NUM_WORDS]; @@ -155,21 +155,21 @@ struct bat_priv { struct hlist_head softif_neigh_vids; struct list_head vis_send_list; struct hashtable_t *orig_hash; - struct hashtable_t *hna_local_hash; - struct hashtable_t *hna_global_hash; + struct hashtable_t *tt_local_hash; + struct hashtable_t *tt_global_hash; struct hashtable_t *vis_hash; spinlock_t forw_bat_list_lock; /* protects forw_bat_list */ spinlock_t forw_bcast_list_lock; /* protects */ - spinlock_t hna_lhash_lock; /* protects hna_local_hash */ - spinlock_t hna_ghash_lock; /* protects hna_global_hash */ + spinlock_t tt_lhash_lock; /* protects tt_local_hash */ + spinlock_t tt_ghash_lock; /* protects tt_global_hash */ spinlock_t gw_list_lock; /* protects gw_list and curr_gw */ spinlock_t vis_hash_lock; /* protects vis_hash */ spinlock_t vis_list_lock; /* protects vis_info::recv_list */ spinlock_t softif_neigh_lock; /* protects soft-interface neigh list */ spinlock_t softif_neigh_vid_lock; /* protects soft-interface vid list */ - int16_t num_local_hna; - atomic_t hna_local_changed; - struct delayed_work hna_work; + int16_t num_local_tt; + atomic_t tt_local_changed; + struct delayed_work tt_work; struct delayed_work orig_work; struct delayed_work vis_work; struct gw_node __rcu *curr_gw; /* rcu protected pointer */ @@ -192,14 +192,14 @@ struct socket_packet { struct icmp_packet_rr icmp_packet; }; -struct hna_local_entry { +struct tt_local_entry { uint8_t addr[ETH_ALEN]; unsigned long last_seen; char never_purge; struct hlist_node hash_entry; }; -struct hna_global_entry { +struct tt_global_entry { uint8_t addr[ETH_ALEN]; struct orig_node *orig_node; struct hlist_node hash_entry; @@ -262,7 +262,7 @@ struct vis_info { struct vis_info_entry { uint8_t src[ETH_ALEN]; uint8_t dest[ETH_ALEN]; - uint8_t quality; /* quality = 0 means HNA */ + uint8_t quality; /* quality = 0 client */ } __packed; struct recvlist_node { diff --git a/net/batman-adv/unicast.c b/net/batman-adv/unicast.c index b46cbf1507e4..19c3daf34ac6 100644 --- a/net/batman-adv/unicast.c +++ b/net/batman-adv/unicast.c @@ -300,7 +300,7 @@ int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv) goto find_router; } - /* check for hna host - increases orig_node refcount */ + /* check for tt host - increases orig_node refcount */ orig_node = transtable_search(bat_priv, ethhdr->h_dest); find_router: diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c index c8f571d3b5d4..c39f20cc1ba6 100644 --- a/net/batman-adv/vis.c +++ b/net/batman-adv/vis.c @@ -194,7 +194,7 @@ static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry, { /* maximal length: max(4+17+2, 3+17+1+3+2) == 26 */ if (primary && entry->quality == 0) - return sprintf(buff, "HNA %pM, ", entry->dest); + return sprintf(buff, "TT %pM, ", entry->dest); else if (compare_eth(entry->src, src)) return sprintf(buff, "TQ %pM %d, ", entry->dest, entry->quality); @@ -622,7 +622,7 @@ static int generate_vis_packet(struct bat_priv *bat_priv) struct vis_info *info = (struct vis_info *)bat_priv->my_vis_info; struct vis_packet *packet = (struct vis_packet *)info->skb_packet->data; struct vis_info_entry *entry; - struct hna_local_entry *hna_local_entry; + struct tt_local_entry *tt_local_entry; int best_tq = -1, i; info->first_seen = jiffies; @@ -678,29 +678,29 @@ next: rcu_read_unlock(); } - hash = bat_priv->hna_local_hash; + hash = bat_priv->tt_local_hash; - spin_lock_bh(&bat_priv->hna_lhash_lock); + spin_lock_bh(&bat_priv->tt_lhash_lock); for (i = 0; i < hash->size; i++) { head = &hash->table[i]; - hlist_for_each_entry(hna_local_entry, node, head, hash_entry) { + hlist_for_each_entry(tt_local_entry, node, head, hash_entry) { entry = (struct vis_info_entry *) skb_put(info->skb_packet, sizeof(*entry)); memset(entry->src, 0, ETH_ALEN); - memcpy(entry->dest, hna_local_entry->addr, ETH_ALEN); - entry->quality = 0; /* 0 means HNA */ + memcpy(entry->dest, tt_local_entry->addr, ETH_ALEN); + entry->quality = 0; /* 0 means TT */ packet->entries++; if (vis_packet_full(info)) { - spin_unlock_bh(&bat_priv->hna_lhash_lock); + spin_unlock_bh(&bat_priv->tt_lhash_lock); return 0; } } } - spin_unlock_bh(&bat_priv->hna_lhash_lock); + spin_unlock_bh(&bat_priv->tt_lhash_lock); return 0; unlock: -- cgit v1.2.3 From 6e215fd8eb4930373d01da0fac16a0889804fac3 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Sun, 8 May 2011 12:45:45 +0200 Subject: batman-adv: Remove multiline comments from line ending It is slightly irritating that comments after a long line span over multiple lines without any code. It is easier to put them before the actual code and reduce the number of lines which the eye has to read. Signed-off-by: Sven Eckelmann --- net/batman-adv/main.h | 40 +++++++++++++++++++++------------------- net/batman-adv/packet.h | 3 +-- net/batman-adv/soft-interface.c | 4 ++-- net/batman-adv/types.h | 10 +++++----- 4 files changed, 29 insertions(+), 28 deletions(-) (limited to 'net/batman-adv') diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index 9ef6ef9b1e18..148b49e02642 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h @@ -34,16 +34,18 @@ #define TQ_MAX_VALUE 255 #define JITTER 20 -#define TTL 50 /* Time To Live of broadcast messages */ -#define PURGE_TIMEOUT 200 /* purge originators after time in seconds if no - * valid packet comes in -> TODO: check - * influence on TQ_LOCAL_WINDOW_SIZE */ + /* Time To Live of broadcast messages */ +#define TTL 50 + +/* purge originators after time in seconds if no valid packet comes in + * -> TODO: check influence on TQ_LOCAL_WINDOW_SIZE */ +#define PURGE_TIMEOUT 200 #define TT_LOCAL_TIMEOUT 3600 /* in seconds */ -#define TQ_LOCAL_WINDOW_SIZE 64 /* sliding packet range of received originator - * messages in squence numbers (should be a - * multiple of our word size) */ +/* sliding packet range of received originator messages in squence numbers + * (should be a multiple of our word size) */ +#define TQ_LOCAL_WINDOW_SIZE 64 #define TQ_GLOBAL_WINDOW_SIZE 5 #define TQ_LOCAL_BIDRECT_SEND_MINIMUM 1 #define TQ_LOCAL_BIDRECT_RECV_MINIMUM 1 @@ -55,21 +57,20 @@ #define VIS_INTERVAL 5000 /* 5 seconds */ -/* how much worse secondary interfaces may be to - * to be considered as bonding candidates */ - +/* how much worse secondary interfaces may be to be considered as bonding + * candidates */ #define BONDING_TQ_THRESHOLD 50 -#define MAX_AGGREGATION_BYTES 512 /* should not be bigger than 512 bytes or - * change the size of - * forw_packet->direct_link_flags */ +/* should not be bigger than 512 bytes or change the size of + * forw_packet->direct_link_flags */ +#define MAX_AGGREGATION_BYTES 512 #define MAX_AGGREGATION_MS 100 #define SOFTIF_NEIGH_TIMEOUT 180000 /* 3 minutes */ +/* don't reset again within 30 seconds */ #define RESET_PROTECTION_MS 30000 #define EXPECTED_SEQNO_RANGE 65536 -/* don't reset again within 30 seconds */ #define MESH_INACTIVE 0 #define MESH_ACTIVE 1 @@ -84,12 +85,13 @@ #ifdef pr_fmt #undef pr_fmt #endif -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt /* Append 'batman-adv: ' before - * kernel messages */ +/* Append 'batman-adv: ' before kernel messages */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#define DBG_BATMAN 1 /* all messages related to routing / flooding / - * broadcasting / etc */ -#define DBG_ROUTES 2 /* route or tt entry added / changed / deleted */ +/* all messages related to routing / flooding / broadcasting / etc */ +#define DBG_BATMAN 1 +/* route or tt entry added / changed / deleted */ +#define DBG_ROUTES 2 #define DBG_ALL 3 diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h index c225c3acc55f..eda99650e9f8 100644 --- a/net/batman-adv/packet.h +++ b/net/batman-adv/packet.h @@ -128,8 +128,7 @@ struct vis_packet { uint8_t entries; /* number of entries behind this struct */ uint32_t seqno; /* sequence number */ uint8_t ttl; /* TTL */ - uint8_t vis_orig[6]; /* originator that informs about its - * neighbors */ + uint8_t vis_orig[6]; /* originator that announces its neighbors */ uint8_t target_orig[6]; /* who should receive this packet */ uint8_t sender_orig[6]; /* who sent or rebroadcasted this packet */ } __packed; diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index d6aaf9fa64d4..8e962e3aa427 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -793,8 +793,8 @@ static void interface_setup(struct net_device *dev) * have not been initialized yet */ dev->mtu = ETH_DATA_LEN; - dev->hard_header_len = BAT_HEADER_LEN; /* reserve more space in the - * skbuff for our header */ + /* reserve more space in the skbuff for our header */ + dev->hard_header_len = BAT_HEADER_LEN; /* generate random address */ random_ether_addr(dev_addr); diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 6b6c32e01c54..fab70e8b16ee 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -89,11 +89,11 @@ struct orig_node { struct hlist_node hash_entry; struct bat_priv *bat_priv; unsigned long last_frag_packet; - spinlock_t ogm_cnt_lock; /* protects: bcast_own, bcast_own_sum, - * neigh_node->real_bits, - * neigh_node->real_packet_count */ - spinlock_t bcast_seqno_lock; /* protects bcast_bits, - * last_bcast_seqno */ + /* ogm_cnt_lock protects: bcast_own, bcast_own_sum, + * neigh_node->real_bits, neigh_node->real_packet_count */ + spinlock_t ogm_cnt_lock; + /* bcast_seqno_lock protects bcast_bits, last_bcast_seqno */ + spinlock_t bcast_seqno_lock; atomic_t bond_candidates; struct list_head bond_list; }; -- cgit v1.2.3 From 27aea2128ec09924dfe08e97739b2bf8b15c8619 Mon Sep 17 00:00:00 2001 From: Daniele Furlan Date: Sat, 7 May 2011 22:45:19 +0200 Subject: batman-adv: remove duplicate code from function is_bidirectional_neigh() In function is_bidirectional_neigh the code that find out the one hop neighbor is duplicated. Signed-off-by: Daniele Furlan Signed-off-by: Sven Eckelmann --- net/batman-adv/routing.c | 74 ++++++++++++++++-------------------------------- 1 file changed, 25 insertions(+), 49 deletions(-) (limited to 'net/batman-adv') diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index 7648b92aec47..bb1c3ec7e3ff 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -169,65 +169,41 @@ static int is_bidirectional_neigh(struct orig_node *orig_node, uint8_t orig_eq_count, neigh_rq_count, tq_own; int tq_asym_penalty, ret = 0; - if (orig_node == orig_neigh_node) { - rcu_read_lock(); - hlist_for_each_entry_rcu(tmp_neigh_node, node, - &orig_node->neigh_list, list) { - - if (!compare_eth(tmp_neigh_node->addr, - orig_neigh_node->orig)) - continue; - - if (tmp_neigh_node->if_incoming != if_incoming) - continue; - - if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) - continue; - - neigh_node = tmp_neigh_node; - } - rcu_read_unlock(); + /* find corresponding one hop neighbor */ + rcu_read_lock(); + hlist_for_each_entry_rcu(tmp_neigh_node, node, + &orig_neigh_node->neigh_list, list) { - if (!neigh_node) - neigh_node = create_neighbor(orig_node, - orig_neigh_node, - orig_neigh_node->orig, - if_incoming); - if (!neigh_node) - goto out; + if (!compare_eth(tmp_neigh_node->addr, orig_neigh_node->orig)) + continue; - neigh_node->last_valid = jiffies; - } else { - /* find packet count of corresponding one hop neighbor */ - rcu_read_lock(); - hlist_for_each_entry_rcu(tmp_neigh_node, node, - &orig_neigh_node->neigh_list, list) { + if (tmp_neigh_node->if_incoming != if_incoming) + continue; - if (!compare_eth(tmp_neigh_node->addr, - orig_neigh_node->orig)) - continue; + if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) + continue; - if (tmp_neigh_node->if_incoming != if_incoming) - continue; + neigh_node = tmp_neigh_node; + break; + } + rcu_read_unlock(); - if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) - continue; + if (!neigh_node) + neigh_node = create_neighbor(orig_neigh_node, + orig_neigh_node, + orig_neigh_node->orig, + if_incoming); - neigh_node = tmp_neigh_node; - } - rcu_read_unlock(); + if (!neigh_node) + goto out; - if (!neigh_node) - neigh_node = create_neighbor(orig_neigh_node, - orig_neigh_node, - orig_neigh_node->orig, - if_incoming); - if (!neigh_node) - goto out; - } + /* if orig_node is direct neighbour update neigh_node last_valid */ + if (orig_node == orig_neigh_node) + neigh_node->last_valid = jiffies; orig_node->last_valid = jiffies; + /* find packet count of corresponding one hop neighbor */ spin_lock_bh(&orig_node->ogm_cnt_lock); orig_eq_count = orig_neigh_node->bcast_own_sum[if_incoming->if_num]; neigh_rq_count = neigh_node->real_packet_count; -- cgit v1.2.3 From 6d5808d4ae1b0851c3b732d9ec2860d5f7804294 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Wed, 11 May 2011 20:59:06 +0200 Subject: batman-adv: Add missing hardif_free_ref in forw_packet_free add_bcast_packet_to_list increases the refcount for if_incoming but the reference count is never decreased. The reference count must be increased for all kinds of forwarded packets which have the primary interface stored and forw_packet_free must decrease them. Also purge_outstanding_packets has to invoke forw_packet_free when a work item was really cancelled. This regression was introduced in 32ae9b221e788413ce68feaae2ca39e406211a0a. Reported-by: Antonio Quartulli Signed-off-by: Sven Eckelmann --- net/batman-adv/aggregation.c | 14 +++++++++++--- net/batman-adv/send.c | 17 +++++++++++++++-- 2 files changed, 26 insertions(+), 5 deletions(-) (limited to 'net/batman-adv') diff --git a/net/batman-adv/aggregation.c b/net/batman-adv/aggregation.c index 9b9459024479..a8c32030527c 100644 --- a/net/batman-adv/aggregation.c +++ b/net/batman-adv/aggregation.c @@ -23,6 +23,7 @@ #include "aggregation.h" #include "send.h" #include "routing.h" +#include "hard-interface.h" /* calculate the size of the tt information for a given packet */ static int tt_len(struct batman_packet *batman_packet) @@ -105,12 +106,15 @@ static void new_aggregated_packet(unsigned char *packet_buff, int packet_len, struct forw_packet *forw_packet_aggr; unsigned char *skb_buff; + if (!atomic_inc_not_zero(&if_incoming->refcount)) + return; + /* own packet should always be scheduled */ if (!own_packet) { if (!atomic_dec_not_zero(&bat_priv->batman_queue_left)) { bat_dbg(DBG_BATMAN, bat_priv, "batman packet queue full\n"); - return; + goto out; } } @@ -118,7 +122,7 @@ static void new_aggregated_packet(unsigned char *packet_buff, int packet_len, if (!forw_packet_aggr) { if (!own_packet) atomic_inc(&bat_priv->batman_queue_left); - return; + goto out; } if ((atomic_read(&bat_priv->aggregated_ogms)) && @@ -133,7 +137,7 @@ static void new_aggregated_packet(unsigned char *packet_buff, int packet_len, if (!own_packet) atomic_inc(&bat_priv->batman_queue_left); kfree(forw_packet_aggr); - return; + goto out; } skb_reserve(forw_packet_aggr->skb, sizeof(struct ethhdr)); @@ -164,6 +168,10 @@ static void new_aggregated_packet(unsigned char *packet_buff, int packet_len, queue_delayed_work(bat_event_workqueue, &forw_packet_aggr->delayed_work, send_time - jiffies); + + return; +out: + hardif_free_ref(if_incoming); } /* aggregate a new packet into the existing aggregation */ diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c index f30d0c69ccbb..76daa46efe19 100644 --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c @@ -377,6 +377,8 @@ static void forw_packet_free(struct forw_packet *forw_packet) { if (forw_packet->skb) kfree_skb(forw_packet->skb); + if (forw_packet->if_incoming) + hardif_free_ref(forw_packet->if_incoming); kfree(forw_packet); } @@ -539,6 +541,7 @@ void purge_outstanding_packets(struct bat_priv *bat_priv, { struct forw_packet *forw_packet; struct hlist_node *tmp_node, *safe_tmp_node; + bool pending; if (hard_iface) bat_dbg(DBG_BATMAN, bat_priv, @@ -567,8 +570,13 @@ void purge_outstanding_packets(struct bat_priv *bat_priv, * send_outstanding_bcast_packet() will lock the list to * delete the item from the list */ - cancel_delayed_work_sync(&forw_packet->delayed_work); + pending = cancel_delayed_work_sync(&forw_packet->delayed_work); spin_lock_bh(&bat_priv->forw_bcast_list_lock); + + if (pending) { + hlist_del(&forw_packet->list); + forw_packet_free(forw_packet); + } } spin_unlock_bh(&bat_priv->forw_bcast_list_lock); @@ -591,8 +599,13 @@ void purge_outstanding_packets(struct bat_priv *bat_priv, * send_outstanding_bat_packet() will lock the list to * delete the item from the list */ - cancel_delayed_work_sync(&forw_packet->delayed_work); + pending = cancel_delayed_work_sync(&forw_packet->delayed_work); spin_lock_bh(&bat_priv->forw_bat_list_lock); + + if (pending) { + hlist_del(&forw_packet->list); + forw_packet_free(forw_packet); + } } spin_unlock_bh(&bat_priv->forw_bat_list_lock); } -- cgit v1.2.3 From ca06c6eb9a31ae782e74596231fb23df4fc5e46d Mon Sep 17 00:00:00 2001 From: Marek Lindner Date: Sat, 14 May 2011 20:01:22 +0200 Subject: batman-adv: reset broadcast flood protection on error The broadcast flood protection should be reset to its original value if the primary interface could not be retrieved. Signed-off-by: Marek Lindner Signed-off-by: Sven Eckelmann --- net/batman-adv/send.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/batman-adv') diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c index 76daa46efe19..33779278f1b2 100644 --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c @@ -421,7 +421,7 @@ int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb) primary_if = primary_if_get_selected(bat_priv); if (!primary_if) - goto out; + goto out_and_inc; forw_packet = kmalloc(sizeof(struct forw_packet), GFP_ATOMIC); -- cgit v1.2.3