diff --git a/Documentation/networking/batman-adv.txt b/Documentation/networking/batman-adv.txt index 220a58c2fb11..75a592365af9 100644 --- a/Documentation/networking/batman-adv.txt +++ b/Documentation/networking/batman-adv.txt @@ -1,5 +1,3 @@ -[state: 21-08-2011] - BATMAN-ADV ---------- @@ -68,10 +66,11 @@ All mesh wide settings can be found in batman's own interface folder: # ls /sys/class/net/bat0/mesh/ -# aggregated_ogms fragmentation hop_penalty -# ap_isolation gw_bandwidth log_level -# bonding gw_mode orig_interval -# bridge_loop_avoidance gw_sel_class vis_mode +# aggregated_ogms gw_bandwidth log_level +# ap_isolation gw_mode orig_interval +# bonding gw_sel_class routing_algo +# bridge_loop_avoidance hop_penalty vis_mode +# fragmentation There is a special folder for debugging information: diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index abd10c490fd9..dc53798ebb47 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -43,7 +43,6 @@ static struct neigh_node *bat_iv_ogm_neigh_new(struct hard_iface *hard_iface, goto out; INIT_LIST_HEAD(&neigh_node->bonding_list); - spin_lock_init(&neigh_node->tq_lock); neigh_node->orig_node = orig_neigh; neigh_node->if_incoming = hard_iface; @@ -637,12 +636,12 @@ static void bat_iv_ogm_orig_update(struct bat_priv *bat_priv, if (is_duplicate) continue; - spin_lock_bh(&tmp_neigh_node->tq_lock); + spin_lock_bh(&tmp_neigh_node->lq_update_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); + spin_unlock_bh(&tmp_neigh_node->lq_update_lock); } if (!neigh_node) { @@ -668,12 +667,12 @@ static void bat_iv_ogm_orig_update(struct bat_priv *bat_priv, orig_node->flags = batman_ogm_packet->flags; neigh_node->last_seen = jiffies; - spin_lock_bh(&neigh_node->tq_lock); + spin_lock_bh(&neigh_node->lq_update_lock); ring_buffer_set(neigh_node->tq_recv, &neigh_node->tq_index, batman_ogm_packet->tq); neigh_node->tq_avg = ring_buffer_avg(neigh_node->tq_recv); - spin_unlock_bh(&neigh_node->tq_lock); + spin_unlock_bh(&neigh_node->lq_update_lock); if (!is_duplicate) { orig_node->last_ttl = batman_ogm_packet->header.ttl; diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index 0b84bb1b62c4..dc334fa89847 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c @@ -173,9 +173,9 @@ static void check_known_mac_addr(const struct net_device *net_dev) net_dev->dev_addr)) continue; - pr_warning("The newly added mac address (%pM) already exists on: %s\n", - net_dev->dev_addr, hard_iface->net_dev->name); - pr_warning("It is strongly recommended to keep mac addresses unique to avoid problems!\n"); + pr_warn("The newly added mac address (%pM) already exists on: %s\n", + net_dev->dev_addr, hard_iface->net_dev->name); + pr_warn("It is strongly recommended to keep mac addresses unique to avoid problems!\n"); } rcu_read_unlock(); } diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index fd83acd48b28..f4a3ec003479 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h @@ -28,7 +28,7 @@ #define DRIVER_DEVICE "batman-adv" #ifndef SOURCE_VERSION -#define SOURCE_VERSION "2012.1.0" +#define SOURCE_VERSION "2012.2.0" #endif /* B.A.T.M.A.N. parameters */ diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index f4b62011ca3f..41147942ba53 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c @@ -99,6 +99,7 @@ struct neigh_node *batadv_neigh_node_new(struct hard_iface *hard_iface, INIT_HLIST_NODE(&neigh_node->list); memcpy(neigh_node->addr, neigh_addr, ETH_ALEN); + spin_lock_init(&neigh_node->lq_update_lock); /* extra reference for return */ atomic_set(&neigh_node->refcount, 2); diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index 7ed9d8f92916..840e2c64a301 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -234,17 +234,14 @@ int window_protected(struct bat_priv *bat_priv, int32_t seq_num_diff, { if ((seq_num_diff <= -TQ_LOCAL_WINDOW_SIZE) || (seq_num_diff >= EXPECTED_SEQNO_RANGE)) { - if (has_timed_out(*last_reset, RESET_PROTECTION_MS)) { - - *last_reset = jiffies; - bat_dbg(DBG_BATMAN, bat_priv, - "old packet received, start protection\n"); - - return 0; - } else { + if (!has_timed_out(*last_reset, RESET_PROTECTION_MS)) return 1; - } + + *last_reset = jiffies; + bat_dbg(DBG_BATMAN, bat_priv, + "old packet received, start protection\n"); } + return 0; } @@ -916,12 +913,20 @@ static int check_unicast_ttvn(struct bat_priv *bat_priv, /* Check whether I have to reroute the packet */ if (seq_before(unicast_packet->ttvn, curr_ttvn) || tt_poss_change) { - /* Linearize the skb before accessing it */ - if (skb_linearize(skb) < 0) + /* check if there is enough data before accessing it */ + if (pskb_may_pull(skb, sizeof(struct unicast_packet) + + ETH_HLEN) < 0) return 0; ethhdr = (struct ethhdr *)(skb->data + sizeof(struct unicast_packet)); + + /* we don't have an updated route for this client, so we should + * not try to reroute the packet!! + */ + if (tt_global_client_is_roaming(bat_priv, ethhdr->h_dest)) + return 1; + orig_node = transtable_search(bat_priv, NULL, ethhdr->h_dest); if (!orig_node) { diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c index 8e74d9763be3..f47299f22c68 100644 --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c @@ -45,8 +45,8 @@ int send_skb_packet(struct sk_buff *skb, struct hard_iface *hard_iface, goto send_skb_err; if (!(hard_iface->net_dev->flags & IFF_UP)) { - pr_warning("Interface %s is not up - can't send packet via that interface!\n", - hard_iface->net_dev->name); + pr_warn("Interface %s is not up - can't send packet via that interface!\n", + hard_iface->net_dev->name); goto send_skb_err; } diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index 2cb46f0bb163..a66c2dcd1088 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -206,6 +206,8 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr, if (tt_local_entry) { tt_local_entry->last_seen = jiffies; + /* possibly unset the TT_CLIENT_PENDING flag */ + tt_local_entry->common.flags &= ~TT_CLIENT_PENDING; goto out; } @@ -2117,3 +2119,22 @@ void tt_update_orig(struct bat_priv *bat_priv, struct orig_node *orig_node, } } } + +/* returns true whether we know that the client has moved from its old + * originator to another one. This entry is kept is still kept for consistency + * purposes + */ +bool tt_global_client_is_roaming(struct bat_priv *bat_priv, uint8_t *addr) +{ + struct tt_global_entry *tt_global_entry; + bool ret = false; + + tt_global_entry = tt_global_hash_find(bat_priv, addr); + if (!tt_global_entry) + goto out; + + ret = tt_global_entry->common.flags & TT_CLIENT_ROAM; + tt_global_entry_free_ref(tt_global_entry); +out: + return ret; +} diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h index 593d1b31217c..c43374dc364d 100644 --- a/net/batman-adv/translation-table.h +++ b/net/batman-adv/translation-table.h @@ -53,5 +53,7 @@ bool is_ap_isolated(struct bat_priv *bat_priv, uint8_t *src, uint8_t *dst); void tt_update_orig(struct bat_priv *bat_priv, struct orig_node *orig_node, const unsigned char *tt_buff, uint8_t tt_num_changes, uint8_t ttvn, uint16_t tt_crc); +bool tt_global_client_is_roaming(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 66a3750aa9e7..61308e8016ff 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -137,7 +137,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 */ + spinlock_t lq_update_lock; /* protects: tq_recv, tq_index */ }; #ifdef CONFIG_BATMAN_ADV_BLA diff --git a/net/batman-adv/unicast.c b/net/batman-adv/unicast.c index 676f6a626b2c..74175c210858 100644 --- a/net/batman-adv/unicast.c +++ b/net/batman-adv/unicast.c @@ -331,6 +331,14 @@ int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv) unicast_packet->ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); + /* inform the destination node that we are still missing a correct route + * for this client. The destination will receive this packet and will + * try to reroute it because the ttvn contained in the header is less + * than the current one + */ + if (tt_global_client_is_roaming(bat_priv, ethhdr->h_dest)) + unicast_packet->ttvn = unicast_packet->ttvn - 1; + if (atomic_read(&bat_priv->fragmentation) && data_len + sizeof(*unicast_packet) > neigh_node->if_incoming->net_dev->mtu) {