The following commit has been merged in the master branch: commit 21262e4e5fef0e3f3ba05c98d7bbcbb053972c72 Merge: 4ca2a01e057606b8d5c08bb53dd62f95ffaf446b d523a2f417dfdecbee5ef87f7d98694d60c39ac6 Author: Marek Lindner lindner_marek@yahoo.de Date: Tue Feb 28 19:04:04 2012 +0800
Merge branch 'next'
Conflicts: hard-interface.c soft-interface.c
diff --combined bat_sysfs.c index abf7300,b00101d..7b8bb66 --- a/bat_sysfs.c +++ b/bat_sysfs.c @@@ -321,11 -321,11 +321,11 @@@ static ssize_t store_gw_mode(struct kob gw_mode_tmp = GW_MODE_OFF;
if (strncmp(buff, GW_MODE_CLIENT_NAME, - strlen(GW_MODE_CLIENT_NAME)) == 0) + strlen(GW_MODE_CLIENT_NAME)) == 0) gw_mode_tmp = GW_MODE_CLIENT;
if (strncmp(buff, GW_MODE_SERVER_NAME, - strlen(GW_MODE_SERVER_NAME)) == 0) + strlen(GW_MODE_SERVER_NAME)) == 0) gw_mode_tmp = GW_MODE_SERVER;
if (gw_mode_tmp < 0) { @@@ -386,9 -386,6 +386,9 @@@ static ssize_t store_gw_bwidth(struct k
BAT_ATTR_BOOL(aggregated_ogms, S_IRUGO | S_IWUSR, NULL); BAT_ATTR_BOOL(bonding, S_IRUGO | S_IWUSR, NULL); +#ifdef CONFIG_BATMAN_ADV_BLA +BAT_ATTR_BOOL(bridge_loop_avoidance, S_IRUGO | S_IWUSR, NULL); +#endif BAT_ATTR_BOOL(fragmentation, S_IRUGO | S_IWUSR, update_min_mtu); BAT_ATTR_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL); static BAT_ATTR(vis_mode, S_IRUGO | S_IWUSR, show_vis_mode, store_vis_mode); @@@ -401,15 -398,12 +401,15 @@@ BAT_ATTR_UINT(gw_sel_class, S_IRUGO | S static BAT_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, show_gw_bwidth, store_gw_bwidth); #ifdef CONFIG_BATMAN_ADV_DEBUG -BAT_ATTR_UINT(log_level, S_IRUGO | S_IWUSR, 0, 7, NULL); +BAT_ATTR_UINT(log_level, S_IRUGO | S_IWUSR, 0, 31, NULL); #endif
static struct bat_attribute *mesh_attrs[] = { &bat_attr_aggregated_ogms, &bat_attr_bonding, +#ifdef CONFIG_BATMAN_ADV_BLA + &bat_attr_bridge_loop_avoidance, +#endif &bat_attr_fragmentation, &bat_attr_ap_isolation, &bat_attr_vis_mode, diff --combined bitarray.c index 6f71fec,6d0aa21..07ae6e1 --- a/bitarray.c +++ b/bitarray.c @@@ -24,13 -24,100 +24,13 @@@
#include <linux/bitops.h>
-/* returns true if the corresponding bit in the given seq_bits indicates true - * and curr_seqno is within range of last_seqno */ -int get_bit_status(const unsigned long *seq_bits, uint32_t last_seqno, - uint32_t curr_seqno) -{ - int32_t diff, word_offset, word_num; - - diff = last_seqno - curr_seqno; - if (diff < 0 || diff >= TQ_LOCAL_WINDOW_SIZE) { - return 0; - } else { - /* which word */ - word_num = (last_seqno - curr_seqno) / WORD_BIT_SIZE; - /* which position in the selected word */ - word_offset = (last_seqno - curr_seqno) % WORD_BIT_SIZE; - - if (test_bit(word_offset, &seq_bits[word_num])) - return 1; - else - return 0; - } -} - -/* turn corresponding bit on, so we can remember that we got the packet */ -void bit_mark(unsigned long *seq_bits, int32_t n) -{ - int32_t word_offset, word_num; - - /* if too old, just drop it */ - if (n < 0 || n >= TQ_LOCAL_WINDOW_SIZE) - return; - - /* which word */ - word_num = n / WORD_BIT_SIZE; - /* which position in the selected word */ - word_offset = n % WORD_BIT_SIZE; - - set_bit(word_offset, &seq_bits[word_num]); /* turn the position on */ -} - /* shift the packet array by n places. */ -static void bit_shift(unsigned long *seq_bits, int32_t n) +static void bat_bitmap_shift_left(unsigned long *seq_bits, int32_t n) { if (n <= 0 || n >= TQ_LOCAL_WINDOW_SIZE) return;
- word_offset = n % WORD_BIT_SIZE;/* shift how much inside each word */ - word_num = n / WORD_BIT_SIZE; /* shift over how much (full) words */ - - for (i = NUM_WORDS - 1; i > word_num; i--) { - /* going from old to new, so we don't overwrite the data we copy - * from. - * - * left is high, right is low: FEDC BA98 7654 3210 - * ^^ ^^ - * vvvv - * ^^^^ = from, vvvvv =to, we'd have word_num==1 and - * word_offset==WORD_BIT_SIZE/2 ????? in this example. - * (=24 bits) - * - * our desired output would be: 9876 5432 1000 0000 - * */ - - seq_bits[i] = - (seq_bits[i - word_num] << word_offset) + - /* take the lower port from the left half, shift it left - * to its final position */ - (seq_bits[i - word_num - 1] >> - (WORD_BIT_SIZE-word_offset)); - /* and the upper part of the right half and shift it left to - * its position */ - /* for our example that would be: word[0] = 9800 + 0076 = - * 9876 */ - } - /* now for our last word, i==word_num, we only have its "left" half. - * that's the 1000 word in our example.*/ - - seq_bits[i] = (seq_bits[i - word_num] << word_offset); - - /* pad the rest with 0, if there is anything */ - i--; - - for (; i >= 0; i--) - seq_bits[i] = 0; -} - -static void bit_reset_window(unsigned long *seq_bits) -{ - int i; - for (i = 0; i < NUM_WORDS; i++) - seq_bits[i] = 0; + bitmap_shift_left(seq_bits, seq_bits, n, TQ_LOCAL_WINDOW_SIZE); }
@@@ -50,7 -137,7 +50,7 @@@ int bit_get_packet(void *priv, unsigne
if ((seq_num_diff <= 0) && (seq_num_diff > -TQ_LOCAL_WINDOW_SIZE)) { if (set_mark) - bit_mark(seq_bits, -seq_num_diff); + bat_set_bit(seq_bits, -seq_num_diff); return 0; }
@@@ -58,23 -145,23 +58,23 @@@ * set the mark if required */
if ((seq_num_diff > 0) && (seq_num_diff < TQ_LOCAL_WINDOW_SIZE)) { - bit_shift(seq_bits, seq_num_diff); + bat_bitmap_shift_left(seq_bits, seq_num_diff);
if (set_mark) - bit_mark(seq_bits, 0); + bat_set_bit(seq_bits, 0); return 1; }
/* sequence number is much newer, probably missed a lot of packets */
- if ((seq_num_diff >= TQ_LOCAL_WINDOW_SIZE) - && (seq_num_diff < EXPECTED_SEQNO_RANGE)) { + if ((seq_num_diff >= TQ_LOCAL_WINDOW_SIZE) && + (seq_num_diff < EXPECTED_SEQNO_RANGE)) { bat_dbg(DBG_BATMAN, bat_priv, "We missed a lot of packets (%i) !\n", seq_num_diff - 1); - bit_reset_window(seq_bits); + bitmap_zero(seq_bits, TQ_LOCAL_WINDOW_SIZE); if (set_mark) - bit_mark(seq_bits, 0); + bat_set_bit(seq_bits, 0); return 1; }
@@@ -83,15 -170,15 +83,15 @@@ * packet should be dropped without calling this function if the * seqno window is protected. */
- if ((seq_num_diff <= -TQ_LOCAL_WINDOW_SIZE) - || (seq_num_diff >= EXPECTED_SEQNO_RANGE)) { + if ((seq_num_diff <= -TQ_LOCAL_WINDOW_SIZE) || + (seq_num_diff >= EXPECTED_SEQNO_RANGE)) {
bat_dbg(DBG_BATMAN, bat_priv, "Other host probably restarted!\n");
- bit_reset_window(seq_bits); + bitmap_zero(seq_bits, TQ_LOCAL_WINDOW_SIZE); if (set_mark) - bit_mark(seq_bits, 0); + bat_set_bit(seq_bits, 0);
return 1; } @@@ -99,3 -186,16 +99,3 @@@ /* never reached */ return 0; } - -/* count the hamming weight, how many good packets did we receive? just count - * the 1's. - */ -int bit_packet_count(const unsigned long *seq_bits) -{ - int i, hamming = 0; - - for (i = 0; i < NUM_WORDS; i++) - hamming += hweight_long(seq_bits[i]); - - return hamming; -} diff --combined gateway_client.c index 1f7e92d,0fa8e2d..c8f3f19 --- a/gateway_client.c +++ b/gateway_client.c @@@ -563,10 -563,10 +563,10 @@@ static bool is_type_dhcprequest(struct p++;
/* ...and then we jump over the data */ - if (pkt_len < *p) + if (pkt_len < 1 + (*p)) goto out; - pkt_len -= *p; - p += (*p); + pkt_len -= 1 + (*p); + p += 1 + (*p); } } out: @@@ -629,7 -629,7 +629,7 @@@ bool gw_is_dhcp_target(struct sk_buff *
/* check for bootp port */ if ((ntohs(ethhdr->h_proto) == ETH_P_IP) && - (ntohs(udphdr->dest) != 67)) + (ntohs(udphdr->dest) != 67)) return false;
if ((ntohs(ethhdr->h_proto) == ETH_P_IPV6) && diff --combined hard-interface.c index 77e3163,409d027..cf43540 --- a/hard-interface.c +++ b/hard-interface.c @@@ -20,7 -20,6 +20,7 @@@ */
#include "main.h" +#include "distributed-arp-table.h" #include "hard-interface.h" #include "soft-interface.h" #include "send.h" @@@ -29,7 -28,6 +29,7 @@@ #include "bat_sysfs.h" #include "originator.h" #include "hash.h" +#include "bridge_loop_avoidance.h"
#include <linux/if_arp.h>
@@@ -109,8 -107,7 +109,8 @@@ out return hard_iface; }
-static void primary_if_update_addr(struct bat_priv *bat_priv) +static void primary_if_update_addr(struct bat_priv *bat_priv, + struct hard_iface *oldif) { struct vis_packet *vis_packet; struct hard_iface *primary_if; @@@ -119,15 -116,12 +119,15 @@@ if (!primary_if) goto out;
+ dat_init_own_dht_addr(bat_priv, primary_if); + vis_packet = (struct vis_packet *) bat_priv->my_vis_info->skb_packet->data; memcpy(vis_packet->vis_orig, primary_if->net_dev->dev_addr, ETH_ALEN); memcpy(vis_packet->sender_orig, primary_if->net_dev->dev_addr, ETH_ALEN);
+ bla_update_orig_address(bat_priv, primary_if, oldif); out: if (primary_if) hardif_free_ref(primary_if); @@@ -146,15 -140,14 +146,15 @@@ static void primary_if_select(struct ba curr_hard_iface = rcu_dereference_protected(bat_priv->primary_if, 1); rcu_assign_pointer(bat_priv->primary_if, new_hard_iface);
- if (curr_hard_iface) - hardif_free_ref(curr_hard_iface); - if (!new_hard_iface) - return; + goto out; + + bat_priv->bat_algo_ops->bat_primary_iface_set(new_hard_iface); + primary_if_update_addr(bat_priv, curr_hard_iface);
- bat_priv->bat_algo_ops->bat_ogm_init_primary(new_hard_iface); - primary_if_update_addr(bat_priv); +out: + if (curr_hard_iface) + hardif_free_ref(curr_hard_iface); }
static bool hardif_is_iface_up(const struct hard_iface *hard_iface) @@@ -313,17 -306,21 +313,17 @@@ int hardif_enable_interface(struct hard pr_err("Can't create batman mesh interface %s: " "already exists as regular interface\n", soft_iface->name); - dev_put(soft_iface); ret = -EINVAL; - goto err; + goto err_dev; }
hard_iface->soft_iface = soft_iface; bat_priv = netdev_priv(hard_iface->soft_iface);
- bat_priv->bat_algo_ops->bat_ogm_init(hard_iface); - - if (!hard_iface->packet_buff) { - bat_err(hard_iface->soft_iface, "Can't add interface packet " - "(%s): out of memory\n", hard_iface->net_dev->name); + ret = bat_priv->bat_algo_ops->bat_iface_enable(hard_iface); + if (ret < 0) { ret = -ENOMEM; - goto err; + goto err_dev; }
hard_iface->if_num = bat_priv->num_ifaces; @@@ -336,6 -333,7 +336,6 @@@ hard_iface->batman_adv_ptype.dev = hard_iface->net_dev; dev_add_pack(&hard_iface->batman_adv_ptype);
- atomic_set(&hard_iface->seqno, 1); atomic_set(&hard_iface->frag_seqno, 1); bat_info(hard_iface->soft_iface, "Adding interface: %s\n", hard_iface->net_dev->name); @@@ -343,23 -341,23 +343,23 @@@ if (atomic_read(&bat_priv->fragmentation) && hard_iface->net_dev->mtu < ETH_DATA_LEN + BAT_HEADER_LEN) bat_info(hard_iface->soft_iface, - "The MTU of interface %s is too small (%i) to handle " - "the transport of batman-adv packets. Packets going " - "over this interface will be fragmented on layer2 " - "which could impact the performance. Setting the MTU " - "to %zi would solve the problem.\n", - hard_iface->net_dev->name, hard_iface->net_dev->mtu, - ETH_DATA_LEN + BAT_HEADER_LEN); + "The MTU of interface %s is too small (%i) to handle " + "the transport of batman-adv packets. Packets going " + "over this interface will be fragmented on layer2 " + "which could impact the performance. Setting the MTU " + "to %zi would solve the problem.\n", + hard_iface->net_dev->name, hard_iface->net_dev->mtu, + ETH_DATA_LEN + BAT_HEADER_LEN);
if (!atomic_read(&bat_priv->fragmentation) && hard_iface->net_dev->mtu < ETH_DATA_LEN + BAT_HEADER_LEN) bat_info(hard_iface->soft_iface, - "The MTU of interface %s is too small (%i) to handle " - "the transport of batman-adv packets. If you experience" - " problems getting traffic through try increasing the " - "MTU to %zi.\n", - hard_iface->net_dev->name, hard_iface->net_dev->mtu, - ETH_DATA_LEN + BAT_HEADER_LEN); + "The MTU of interface %s is too small (%i) to handle " + "the transport of batman-adv packets. If you " + "experience problems getting traffic through try " + "increasing the MTU to %zi.\n", + hard_iface->net_dev->name, hard_iface->net_dev->mtu, + ETH_DATA_LEN + BAT_HEADER_LEN);
if (hardif_is_iface_up(hard_iface)) hardif_activate_interface(hard_iface); @@@ -374,8 -372,6 +374,8 @@@ out: return 0;
+err_dev: + dev_put(soft_iface); err: hardif_free_ref(hard_iface); return ret; @@@ -410,7 -406,8 +410,7 @@@ void hardif_disable_interface(struct ha hardif_free_ref(new_if); }
- kfree(hard_iface->packet_buff); - hard_iface->packet_buff = NULL; + bat_priv->bat_algo_ops->bat_iface_disable(hard_iface); hard_iface->if_status = IF_NOT_IN_USE;
/* delete all references to this hard_iface */ @@@ -462,13 -459,6 +462,13 @@@ static struct hard_iface *hardif_add_in check_known_mac_addr(hard_iface->net_dev); list_add_tail_rcu(&hard_iface->list, &hardif_list);
+ /** + * This can't be called via a bat_priv callback because + * we have no bat_priv yet. + */ + atomic_set(&hard_iface->seqno, 1); + hard_iface->packet_buff = NULL; + return hard_iface;
free_if: @@@ -553,7 -543,7 +553,7 @@@ static int hard_if_event(struct notifie goto hardif_put;
if (hard_iface == primary_if) - primary_if_update_addr(bat_priv); + primary_if_update_addr(bat_priv, NULL); break; default: break; @@@ -590,7 -580,8 +590,7 @@@ static int batman_skb_recv(struct sk_bu goto err_free;
/* expect a valid ethernet header here. */ - if (unlikely(skb->mac_len != sizeof(struct ethhdr) || - !skb_mac_header(skb))) + if (unlikely(skb->mac_len != ETH_HLEN || !skb_mac_header(skb))) goto err_free;
if (!hard_iface->soft_iface) @@@ -619,7 -610,7 +619,7 @@@
switch (batman_ogm_packet->header.packet_type) { /* batman originator packet */ - case BAT_OGM: + case BAT_IV_OGM: ret = recv_bat_ogm_packet(skb, hard_iface); break;
@@@ -630,7 -621,6 +630,7 @@@
/* unicast packet */ case BAT_UNICAST: + case BAT_UNICAST_4ADDR: ret = recv_unicast_packet(skb, hard_iface); break;
diff --combined originator.c index 1ee6e82,371cc93..06c8187 --- a/originator.c +++ b/originator.c @@@ -20,7 -20,6 +20,7 @@@ */
#include "main.h" +#include "distributed-arp-table.h" #include "originator.h" #include "hash.h" #include "translation-table.h" @@@ -29,7 -28,6 +29,7 @@@ #include "hard-interface.h" #include "unicast.h" #include "soft-interface.h" +#include "bridge_loop_avoidance.h"
static void purge_orig(struct work_struct *work);
@@@ -145,7 -143,7 +145,7 @@@ static void orig_node_free_rcu(struct r
frag_list_free(&orig_node->frag_list); tt_global_del_orig(orig_node->bat_priv, orig_node, - "originator timed out"); + "originator timed out");
kfree(orig_node->tt_buff); kfree(orig_node->bcast_own); @@@ -225,7 -223,6 +225,7 @@@ struct orig_node *get_orig_node(struct orig_node->tt_poss_change = false; orig_node->bat_priv = bat_priv; memcpy(orig_node->orig, addr, ETH_ALEN); + dat_init_orig_node_dht_addr(orig_node); orig_node->router = NULL; orig_node->tt_crc = 0; atomic_set(&orig_node->last_ttvn, 0); @@@ -336,9 -333,8 +336,8 @@@ static bool purge_orig_node(struct bat_ return true; } else { if (purge_orig_neighbors(bat_priv, orig_node, - &best_neigh_node)) { + &best_neigh_node)) update_route(bat_priv, orig_node, best_neigh_node); - } }
return false; @@@ -381,6 -377,8 +380,6 @@@ static void _purge_orig(struct bat_pri
gw_node_purge(bat_priv); gw_election(bat_priv); - - softif_neigh_purge(bat_priv); }
static void purge_orig(struct work_struct *work) diff --combined routing.c index f87b2ae,f535155..0da9f5a --- a/routing.c +++ b/routing.c @@@ -29,10 -29,6 +29,10 @@@ #include "originator.h" #include "vis.h" #include "unicast.h" +#include "bridge_loop_avoidance.h" + +static int route_unicast_packet(struct sk_buff *skb, + struct hard_iface *recv_if);
void slide_own_bcast_window(struct hard_iface *hard_iface) { @@@ -56,7 -52,7 +56,7 @@@
bit_get_packet(bat_priv, word, 1, 0); orig_node->bcast_own_sum[hard_iface->if_num] = - bit_packet_count(word); + bitmap_weight(word, TQ_LOCAL_WINDOW_SIZE); spin_unlock_bh(&orig_node->ogm_cnt_lock); } rcu_read_unlock(); @@@ -76,7 -72,7 +76,7 @@@ static void _update_route(struct bat_pr bat_dbg(DBG_ROUTES, bat_priv, "Deleting route towards: %pM\n", orig_node->orig); tt_global_del_orig(bat_priv, orig_node, - "Deleted route towards originator"); + "Deleted route towards originator");
/* route added */ } else if ((!curr_router) && (neigh_node)) { @@@ -233,8 -229,8 +233,8 @@@ void bonding_save_primary(const struct int window_protected(struct bat_priv *bat_priv, int32_t seq_num_diff, unsigned long *last_reset) { - if ((seq_num_diff <= -TQ_LOCAL_WINDOW_SIZE) - || (seq_num_diff >= EXPECTED_SEQNO_RANGE)) { + 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; @@@ -254,7 -250,7 +254,7 @@@ int recv_bat_ogm_packet(struct sk_buff struct ethhdr *ethhdr;
/* drop packet if it has not necessary minimum size */ - if (unlikely(!pskb_may_pull(skb, BATMAN_OGM_LEN))) + if (unlikely(!pskb_may_pull(skb, BATMAN_OGM_HLEN))) return NET_RX_DROP;
ethhdr = (struct ethhdr *)skb_mac_header(skb); @@@ -313,7 -309,7 +313,7 @@@ static int recv_my_icmp_packet(struct b goto out;
/* create a copy of the skb, if needed, to modify it. */ - if (skb_cow(skb, sizeof(struct ethhdr)) < 0) + if (skb_cow(skb, ETH_HLEN) < 0) goto out;
icmp_packet = (struct icmp_packet_rr *)skb->data; @@@ -369,7 -365,7 +369,7 @@@ static int recv_icmp_ttl_exceeded(struc goto out;
/* create a copy of the skb, if needed, to modify it. */ - if (skb_cow(skb, sizeof(struct ethhdr)) < 0) + if (skb_cow(skb, ETH_HLEN) < 0) goto out;
icmp_packet = (struct icmp_packet *)skb->data; @@@ -433,7 -429,7 +433,7 @@@ int recv_icmp_packet(struct sk_buff *sk if ((hdr_size == sizeof(struct icmp_packet_rr)) && (icmp_packet->rr_cur < BAT_RR_LEN)) { memcpy(&(icmp_packet->rr[icmp_packet->rr_cur]), - ethhdr->h_dest, ETH_ALEN); + ethhdr->h_dest, ETH_ALEN); icmp_packet->rr_cur++; }
@@@ -455,7 -451,7 +455,7 @@@ goto out;
/* create a copy of the skb, if needed, to modify it. */ - if (skb_cow(skb, sizeof(struct ethhdr)) < 0) + if (skb_cow(skb, ETH_HLEN) < 0) goto out;
icmp_packet = (struct icmp_packet_rr *)skb->data; @@@ -674,12 -670,6 +674,12 @@@ int recv_roam_adv(struct sk_buff *skb, if (!is_my_mac(roam_adv_packet->dst)) return route_unicast_packet(skb, recv_if);
+ /* check if it is a backbone gateway. we don't accept + * roaming advertisement from it, as it has the same + * entries as we have. */ + if (bla_is_backbone_gw_orig(bat_priv, roam_adv_packet->src)) + goto out; + orig_node = orig_hash_find(bat_priv, roam_adv_packet->src); if (!orig_node) goto out; @@@ -809,7 -799,7 +809,7 @@@ static int check_unicast_packet(struct return 0; }
-int route_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if) +static int route_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if) { struct bat_priv *bat_priv = netdev_priv(recv_if->soft_iface); struct orig_node *orig_node = NULL; @@@ -842,7 -832,7 +842,7 @@@ goto out;
/* create a copy of the skb, if needed, to modify it. */ - if (skb_cow(skb, sizeof(struct ethhdr)) < 0) + if (skb_cow(skb, ETH_HLEN) < 0) goto out;
unicast_packet = (struct unicast_packet *)skb->data; @@@ -960,18 -950,14 +960,18 @@@ int recv_unicast_packet(struct sk_buff struct unicast_packet *unicast_packet; int hdr_size = sizeof(*unicast_packet);
+ unicast_packet = (struct unicast_packet *)skb->data; + + /* the caller function should have already pulled 2 bytes */ + if (unicast_packet->header.packet_type == BAT_UNICAST_4ADDR) + hdr_size = sizeof(struct unicast_4addr_packet); + if (check_unicast_packet(skb, hdr_size) < 0) return NET_RX_DROP;
if (!check_unicast_ttvn(bat_priv, skb)) return NET_RX_DROP;
- unicast_packet = (struct unicast_packet *)skb->data; - /* packet for me */ if (is_my_mac(unicast_packet->dest)) { interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size); @@@ -1063,8 -1049,8 +1063,8 @@@ int recv_bcast_packet(struct sk_buff *s spin_lock_bh(&orig_node->bcast_seqno_lock);
/* check whether the packet is a duplicate */ - if (get_bit_status(orig_node->bcast_bits, orig_node->last_bcast_seqno, - ntohl(bcast_packet->seqno))) + if (bat_test_bit(orig_node->bcast_bits, orig_node->last_bcast_seqno, + ntohl(bcast_packet->seqno))) goto spin_unlock;
seq_diff = ntohl(bcast_packet->seqno) - orig_node->last_bcast_seqno; @@@ -1081,18 -1067,9 +1081,18 @@@
spin_unlock_bh(&orig_node->bcast_seqno_lock);
+ /* check whether this has been sent by another originator before */ + if (bla_check_bcast_duplist(bat_priv, bcast_packet, hdr_size)) + goto out; + /* rebroadcast packet */ add_bcast_packet_to_list(bat_priv, skb, 1);
+ /* don't hand the broadcast up if it is from an originator + * from the same backbone. */ + if (bla_is_backbone_gw(skb, orig_node, hdr_size)) + goto out; + /* broadcast for me */ interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size); ret = NET_RX_SUCCESS; diff --combined translation-table.c index 9a07882,c950705..a612d36 --- a/translation-table.c +++ b/translation-table.c @@@ -27,14 -27,13 +27,14 @@@ #include "hash.h" #include "originator.h" #include "routing.h" +#include "bridge_loop_avoidance.h"
#include <linux/crc16.h>
-static void _tt_global_del(struct bat_priv *bat_priv, - struct tt_global_entry *tt_global_entry, - const char *message); +static void send_roam_adv(struct bat_priv *bat_priv, uint8_t *client, + struct orig_node *orig_node); static void tt_purge(struct work_struct *work); +static void tt_global_del_orig_list(struct tt_global_entry *tt_global_entry);
/* returns 1 if they are the same mac addr */ static int compare_tt(const struct hlist_node *node, const void *data2) @@@ -124,31 -123,17 +124,31 @@@ static void tt_global_entry_free_rcu(st tt_global_entry = container_of(tt_common_entry, struct tt_global_entry, common);
- if (tt_global_entry->orig_node) - orig_node_free_ref(tt_global_entry->orig_node); - kfree(tt_global_entry); }
static void tt_global_entry_free_ref(struct tt_global_entry *tt_global_entry) { - if (atomic_dec_and_test(&tt_global_entry->common.refcount)) + if (atomic_dec_and_test(&tt_global_entry->common.refcount)) { + tt_global_del_orig_list(tt_global_entry); call_rcu(&tt_global_entry->common.rcu, tt_global_entry_free_rcu); + } +} + +static void tt_orig_list_entry_free_rcu(struct rcu_head *rcu) +{ + struct tt_orig_list_entry *orig_entry; + + orig_entry = container_of(rcu, struct tt_orig_list_entry, rcu); + atomic_dec(&orig_entry->orig_node->tt_size); + orig_node_free_ref(orig_entry->orig_node); + kfree(orig_entry); +} + +static void tt_orig_list_entry_free_ref(struct tt_orig_list_entry *orig_entry) +{ + call_rcu(&orig_entry->rcu, tt_orig_list_entry_free_rcu); }
static void tt_local_event(struct bat_priv *bat_priv, const uint8_t *addr, @@@ -197,9 -182,6 +197,9 @@@ void tt_local_add(struct net_device *so struct bat_priv *bat_priv = netdev_priv(soft_iface); struct tt_local_entry *tt_local_entry = NULL; struct tt_global_entry *tt_global_entry = NULL; + struct hlist_head *head; + struct hlist_node *node; + struct tt_orig_list_entry *orig_entry; int hash_added;
tt_local_entry = tt_local_hash_find(bat_priv, addr); @@@ -250,21 -232,14 +250,21 @@@
/* Check whether it is a roaming! */ if (tt_global_entry) { - /* This node is probably going to update its tt table */ - tt_global_entry->orig_node->tt_poss_change = true; - /* The global entry has to be marked as ROAMING and has to be - * kept for consistency purpose */ + /* These node are probably going to update their tt table */ + head = &tt_global_entry->orig_list; + rcu_read_lock(); + hlist_for_each_entry_rcu(orig_entry, node, head, list) { + orig_entry->orig_node->tt_poss_change = true; + + send_roam_adv(bat_priv, tt_global_entry->common.addr, + orig_entry->orig_node); + } + rcu_read_unlock(); + /* The global entry has to be marked as ROAMING and + * has to be kept for consistency purpose */ + tt_global_entry->common.flags |= TT_CLIENT_ROAM; tt_global_entry->roam_at = jiffies; - send_roam_adv(bat_priv, tt_global_entry->common.addr, - tt_global_entry->orig_node); } out: if (tt_local_entry) @@@ -286,7 -261,7 +286,7 @@@ int tt_changes_fill_buffer(struct bat_p atomic_set(&bat_priv->tt_local_changes, 0);
list_for_each_entry_safe(entry, safe, &bat_priv->tt_changes_list, - list) { + list) { if (count < tot_changes) { memcpy(buff + tt_len(count), &entry->change, sizeof(struct tt_change)); @@@ -358,17 -333,17 +358,17 @@@ int tt_local_seq_print_text(struct seq_ hlist_for_each_entry_rcu(tt_common_entry, node, head, hash_entry) { seq_printf(seq, " * %pM [%c%c%c%c%c]\n", - tt_common_entry->addr, - (tt_common_entry->flags & - TT_CLIENT_ROAM ? 'R' : '.'), - (tt_common_entry->flags & - TT_CLIENT_NOPURGE ? 'P' : '.'), - (tt_common_entry->flags & - TT_CLIENT_NEW ? 'N' : '.'), - (tt_common_entry->flags & - TT_CLIENT_PENDING ? 'X' : '.'), - (tt_common_entry->flags & - TT_CLIENT_WIFI ? 'W' : '.')); + tt_common_entry->addr, + (tt_common_entry->flags & + TT_CLIENT_ROAM ? 'R' : '.'), + (tt_common_entry->flags & + TT_CLIENT_NOPURGE ? 'P' : '.'), + (tt_common_entry->flags & + TT_CLIENT_NEW ? 'N' : '.'), + (tt_common_entry->flags & + TT_CLIENT_PENDING ? 'X' : '.'), + (tt_common_entry->flags & + TT_CLIENT_WIFI ? 'W' : '.')); } rcu_read_unlock(); } @@@ -514,75 -489,33 +514,75 @@@ static void tt_changes_list_free(struc spin_unlock_bh(&bat_priv->tt_changes_list_lock); }
+/* find out if an orig_node is already in the list of a tt_global_entry. + * returns 1 if found, 0 otherwise */ +static bool tt_global_entry_has_orig(const struct tt_global_entry *entry, + const struct orig_node *orig_node) +{ + struct tt_orig_list_entry *tmp_orig_entry; + const struct hlist_head *head; + struct hlist_node *node; + bool found = false; + + rcu_read_lock(); + head = &entry->orig_list; + hlist_for_each_entry_rcu(tmp_orig_entry, node, head, list) { + if (tmp_orig_entry->orig_node == orig_node) { + found = true; + break; + } + } + rcu_read_unlock(); + return found; +} + +static void tt_global_add_orig_entry(struct tt_global_entry *tt_global_entry, + struct orig_node *orig_node, + int ttvn) +{ + struct tt_orig_list_entry *orig_entry; + + orig_entry = kzalloc(sizeof(*orig_entry), GFP_ATOMIC); + if (!orig_entry) + return; + + INIT_HLIST_NODE(&orig_entry->list); + atomic_inc(&orig_node->refcount); + atomic_inc(&orig_node->tt_size); + orig_entry->orig_node = orig_node; + orig_entry->ttvn = ttvn; + + spin_lock_bh(&tt_global_entry->list_lock); + hlist_add_head_rcu(&orig_entry->list, + &tt_global_entry->orig_list); + spin_unlock_bh(&tt_global_entry->list_lock); +} + /* caller must hold orig_node refcount */ int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node, const unsigned char *tt_addr, uint8_t ttvn, bool roaming, bool wifi) { - struct tt_global_entry *tt_global_entry; - struct orig_node *orig_node_tmp; + struct tt_global_entry *tt_global_entry = NULL; int ret = 0; int hash_added;
tt_global_entry = tt_global_hash_find(bat_priv, tt_addr);
if (!tt_global_entry) { - tt_global_entry = - kmalloc(sizeof(*tt_global_entry), - GFP_ATOMIC); + tt_global_entry = kzalloc(sizeof(*tt_global_entry), + GFP_ATOMIC); if (!tt_global_entry) goto out;
memcpy(tt_global_entry->common.addr, tt_addr, ETH_ALEN); + tt_global_entry->common.flags = NO_FLAGS; - atomic_set(&tt_global_entry->common.refcount, 2); - /* Assign the new orig_node */ - atomic_inc(&orig_node->refcount); - tt_global_entry->orig_node = orig_node; - tt_global_entry->ttvn = ttvn; tt_global_entry->roam_at = 0; + atomic_set(&tt_global_entry->common.refcount, 2); + + INIT_HLIST_HEAD(&tt_global_entry->orig_list); + spin_lock_init(&tt_global_entry->list_lock);
hash_added = hash_add(bat_priv->tt_global_hash, compare_tt, choose_orig, &tt_global_entry->common, @@@ -593,28 -526,19 +593,28 @@@ tt_global_entry_free_ref(tt_global_entry); goto out_remove; } - atomic_inc(&orig_node->tt_size); + + tt_global_add_orig_entry(tt_global_entry, orig_node, ttvn); } else { - if (tt_global_entry->orig_node != orig_node) { - atomic_dec(&tt_global_entry->orig_node->tt_size); - orig_node_tmp = tt_global_entry->orig_node; - atomic_inc(&orig_node->refcount); - tt_global_entry->orig_node = orig_node; - orig_node_free_ref(orig_node_tmp); - atomic_inc(&orig_node->tt_size); + /* there is already a global entry, use this one. */ + + /* + * If there is the TT_CLIENT_ROAM flag set, there is only one + * originator left in the list and we previously received a + * delete + roaming change for this originator. + * + * We should first delete the old originator before adding the + * new one. + */ + if (tt_global_entry->common.flags & TT_CLIENT_ROAM) { + tt_global_del_orig_list(tt_global_entry); + tt_global_entry->common.flags &= ~TT_CLIENT_ROAM; + tt_global_entry->roam_at = 0; } - tt_global_entry->common.flags = NO_FLAGS; - tt_global_entry->ttvn = ttvn; - tt_global_entry->roam_at = 0; + + if (!tt_global_entry_has_orig(tt_global_entry, orig_node)) + tt_global_add_orig_entry(tt_global_entry, orig_node, + ttvn); }
if (wifi) @@@ -635,36 -559,6 +635,36 @@@ out return ret; }
+/* + * print all orig nodes who announce the address for this global entry. + * it is assumed that the caller holds rcu_read_lock(); + */ +static void tt_global_print_entry(struct tt_global_entry *tt_global_entry, + struct seq_file *seq) +{ + struct hlist_head *head; + struct hlist_node *node; + struct tt_orig_list_entry *orig_entry; + struct tt_common_entry *tt_common_entry; + uint16_t flags; + uint8_t last_ttvn; + + tt_common_entry = &tt_global_entry->common; + + head = &tt_global_entry->orig_list; + + hlist_for_each_entry_rcu(orig_entry, node, head, list) { + flags = tt_common_entry->flags; + last_ttvn = atomic_read(&orig_entry->orig_node->last_ttvn); + seq_printf(seq, " * %pM (%3u) via %pM (%3u) " + "[%c%c]\n", tt_global_entry->common.addr, + orig_entry->ttvn, + orig_entry->orig_node->orig, last_ttvn, + (flags & TT_CLIENT_ROAM ? 'R' : '.'), + (flags & TT_CLIENT_WIFI ? 'W' : '.')); + } +} + int tt_global_seq_print_text(struct seq_file *seq, void *offset) { struct net_device *net_dev = (struct net_device *)seq->private; @@@ -708,7 -602,18 +708,7 @@@ tt_global_entry = container_of(tt_common_entry, struct tt_global_entry, common); - seq_printf(seq, " * %pM (%3u) via %pM (%3u) " - "[%c%c]\n", - tt_global_entry->common.addr, - tt_global_entry->ttvn, - tt_global_entry->orig_node->orig, - (uint8_t) atomic_read( - &tt_global_entry->orig_node-> - last_ttvn), - (tt_global_entry->common.flags & - TT_CLIENT_ROAM ? 'R' : '.'), - (tt_global_entry->common.flags & - TT_CLIENT_WIFI ? 'W' : '.')); + tt_global_print_entry(tt_global_entry, seq); } rcu_read_unlock(); } @@@ -718,151 -623,59 +718,151 @@@ out return ret; }
-static void _tt_global_del(struct bat_priv *bat_priv, - struct tt_global_entry *tt_global_entry, - const char *message) +/* deletes the orig list of a tt_global_entry */ +static void tt_global_del_orig_list(struct tt_global_entry *tt_global_entry) { - if (!tt_global_entry) - goto out; + struct hlist_head *head; + struct hlist_node *node, *safe; + struct tt_orig_list_entry *orig_entry;
- bat_dbg(DBG_TT, bat_priv, - "Deleting global tt entry %pM (via %pM): %s\n", - tt_global_entry->common.addr, tt_global_entry->orig_node->orig, - message); + spin_lock_bh(&tt_global_entry->list_lock); + head = &tt_global_entry->orig_list; + hlist_for_each_entry_safe(orig_entry, node, safe, head, list) { + hlist_del_rcu(node); + tt_orig_list_entry_free_ref(orig_entry); + } + spin_unlock_bh(&tt_global_entry->list_lock);
- atomic_dec(&tt_global_entry->orig_node->tt_size); +} + +static void tt_global_del_orig_entry(struct bat_priv *bat_priv, + struct tt_global_entry *tt_global_entry, + struct orig_node *orig_node, + const char *message) +{ + struct hlist_head *head; + struct hlist_node *node, *safe; + struct tt_orig_list_entry *orig_entry; + + spin_lock_bh(&tt_global_entry->list_lock); + head = &tt_global_entry->orig_list; + hlist_for_each_entry_safe(orig_entry, node, safe, head, list) { + if (orig_entry->orig_node == orig_node) { + bat_dbg(DBG_TT, bat_priv, + "Deleting %pM from global tt entry %pM: %s\n", + orig_node->orig, tt_global_entry->common.addr, + message); + hlist_del_rcu(node); + tt_orig_list_entry_free_ref(orig_entry); + } + } + spin_unlock_bh(&tt_global_entry->list_lock); +} + +static void tt_global_del_struct(struct bat_priv *bat_priv, + struct tt_global_entry *tt_global_entry, + const char *message) +{ + bat_dbg(DBG_TT, bat_priv, + "Deleting global tt entry %pM: %s\n", + tt_global_entry->common.addr, message);
hash_remove(bat_priv->tt_global_hash, compare_tt, choose_orig, tt_global_entry->common.addr); -out: - if (tt_global_entry) - tt_global_entry_free_ref(tt_global_entry); + tt_global_entry_free_ref(tt_global_entry); + }
-void tt_global_del(struct bat_priv *bat_priv, - struct orig_node *orig_node, const unsigned char *addr, - const char *message, bool roaming) +/* + * If the client is to be deleted, we check if it is the last origantor entry + * within tt_global entry. If yes, we set the TT_CLIENT_ROAM flag and the timer, + * otherwise we simply remove the originator scheduled for deletion. + */ +static void tt_global_del_roaming(struct bat_priv *bat_priv, + struct tt_global_entry *tt_global_entry, + struct orig_node *orig_node, + const char *message) +{ + bool last_entry = true; + struct hlist_head *head; + struct hlist_node *node; + struct tt_orig_list_entry *orig_entry; + + /* + * no local entry exists, case 1: + * Check if this is the last one or if other entries exist. + */ + + rcu_read_lock(); + head = &tt_global_entry->orig_list; + hlist_for_each_entry_rcu(orig_entry, node, head, list) { + if (orig_entry->orig_node != orig_node) { + last_entry = false; + break; + } + } + rcu_read_unlock(); + + if (last_entry) { + /* its the last one, mark for roaming. */ + tt_global_entry->common.flags |= TT_CLIENT_ROAM; + tt_global_entry->roam_at = jiffies; + } else + /* there is another entry, we can simply delete this + * one and can still use the other one. */ + tt_global_del_orig_entry(bat_priv, tt_global_entry, + orig_node, message); +} + + + +static void tt_global_del(struct bat_priv *bat_priv, + struct orig_node *orig_node, + const unsigned char *addr, + const char *message, bool roaming) { struct tt_global_entry *tt_global_entry = NULL; struct tt_local_entry *tt_local_entry = NULL;
tt_global_entry = tt_global_hash_find(bat_priv, addr); - if (!tt_global_entry || tt_global_entry->orig_node != orig_node) + if (!tt_global_entry) goto out;
- if (!roaming) - goto out_del; + if (!roaming) { + tt_global_del_orig_entry(bat_priv, tt_global_entry, orig_node, + message); + + if (hlist_empty(&tt_global_entry->orig_list)) + tt_global_del_struct(bat_priv, tt_global_entry, + message); + + goto out; + }
/* if we are deleting a global entry due to a roam * event, there are two possibilities: - * 1) the client roamed from node A to node B => we mark + * 1) the client roamed from node A to node B => if there + * is only one originator left for this client, we mark * it with TT_CLIENT_ROAM, we start a timer and we * wait for node B to claim it. In case of timeout * the entry is purged. + * + * If there are other originators left, we directly delete + * the originator. * 2) the client roamed to us => we can directly delete * the global entry, since it is useless now. */ + tt_local_entry = tt_local_hash_find(bat_priv, tt_global_entry->common.addr); - if (!tt_local_entry) { - tt_global_entry->common.flags |= TT_CLIENT_ROAM; - tt_global_entry->roam_at = jiffies; - goto out; - } + if (tt_local_entry) { + /* local entry exists, case 2: client roamed to us. */ + tt_global_del_orig_list(tt_global_entry); + tt_global_del_struct(bat_priv, tt_global_entry, message); + } else + /* no local entry exists, case 1: check for roaming */ + tt_global_del_roaming(bat_priv, tt_global_entry, orig_node, + message);
-out_del: - _tt_global_del(bat_priv, tt_global_entry, message);
out: if (tt_global_entry) @@@ -895,14 -708,12 +895,14 @@@ void tt_global_del_orig(struct bat_pri tt_global_entry = container_of(tt_common_entry, struct tt_global_entry, common); - if (tt_global_entry->orig_node == orig_node) { + + tt_global_del_orig_entry(bat_priv, tt_global_entry, + orig_node, message); + + if (hlist_empty(&tt_global_entry->orig_list)) { bat_dbg(DBG_TT, bat_priv, - "Deleting global tt entry %pM " - "(via %pM): %s\n", + "Deleting global tt entry %pM: %s\n", tt_global_entry->common.addr, - tt_global_entry->orig_node->orig, message); hlist_del_rcu(node); tt_global_entry_free_ref(tt_global_entry); @@@ -943,7 -754,7 +943,7 @@@ static void tt_global_roam_purge(struc bat_dbg(DBG_TT, bat_priv, "Deleting global " "tt entry (%pM): Roaming timeout\n", tt_global_entry->common.addr); - atomic_dec(&tt_global_entry->orig_node->tt_size); + hlist_del_rcu(node); tt_global_entry_free_ref(tt_global_entry); } @@@ -1006,11 -817,6 +1006,11 @@@ struct orig_node *transtable_search(str struct tt_local_entry *tt_local_entry = NULL; struct tt_global_entry *tt_global_entry = NULL; struct orig_node *orig_node = NULL; + struct neigh_node *router = NULL; + struct hlist_head *head; + struct hlist_node *node; + struct tt_orig_list_entry *orig_entry; + int best_tq;
if (src && atomic_read(&bat_priv->ap_isolation)) { tt_local_entry = tt_local_hash_find(bat_priv, src); @@@ -1027,25 -833,11 +1027,25 @@@ if (tt_local_entry && _is_ap_isolated(tt_local_entry, tt_global_entry)) goto out;
- if (!atomic_inc_not_zero(&tt_global_entry->orig_node->refcount)) - goto out; + best_tq = 0;
- orig_node = tt_global_entry->orig_node; + rcu_read_lock(); + head = &tt_global_entry->orig_list; + hlist_for_each_entry_rcu(orig_entry, node, head, list) { + router = orig_node_get_router(orig_entry->orig_node); + if (!router) + continue;
+ if (router->tq_avg > best_tq) { + orig_node = orig_entry->orig_node; + best_tq = router->tq_avg; + } + neigh_node_free_ref(router); + } + /* found anything? */ + if (orig_node && !atomic_inc_not_zero(&orig_node->refcount)) + orig_node = NULL; + rcu_read_unlock(); out: if (tt_global_entry) tt_global_entry_free_ref(tt_global_entry); @@@ -1056,8 -848,7 +1056,8 @@@ }
/* Calculates the checksum of the local table of a given orig_node */ -uint16_t tt_global_crc(struct bat_priv *bat_priv, struct orig_node *orig_node) +static uint16_t tt_global_crc(struct bat_priv *bat_priv, + struct orig_node *orig_node) { uint16_t total = 0, total_one; struct hashtable_t *hash = bat_priv->tt_global_hash; @@@ -1077,24 -868,20 +1077,24 @@@ tt_global_entry = container_of(tt_common_entry, struct tt_global_entry, common); - if (compare_eth(tt_global_entry->orig_node, - orig_node)) { - /* Roaming clients are in the global table for - * consistency only. They don't have to be - * taken into account while computing the - * global crc */ - if (tt_common_entry->flags & TT_CLIENT_ROAM) - continue; - total_one = 0; - for (j = 0; j < ETH_ALEN; j++) - total_one = crc16_byte(total_one, - tt_common_entry->addr[j]); - total ^= total_one; - } + /* Roaming clients are in the global table for + * consistency only. They don't have to be + * taken into account while computing the + * global crc */ + if (tt_global_entry->common.flags & TT_CLIENT_ROAM) + continue; + + /* find out if this global entry is announced by this + * originator */ + if (!tt_global_entry_has_orig(tt_global_entry, + orig_node)) + continue; + + total_one = 0; + for (j = 0; j < ETH_ALEN; j++) + total_one = crc16_byte(total_one, + tt_global_entry->common.addr[j]); + total ^= total_one; } rcu_read_unlock(); } @@@ -1149,10 -936,8 +1149,10 @@@ static void tt_req_list_free(struct bat spin_unlock_bh(&bat_priv->tt_req_list_lock); }
-void tt_save_orig_buffer(struct bat_priv *bat_priv, struct orig_node *orig_node, - const unsigned char *tt_buff, uint8_t tt_num_changes) +static void tt_save_orig_buffer(struct bat_priv *bat_priv, + struct orig_node *orig_node, + const unsigned char *tt_buff, + uint8_t tt_num_changes) { uint16_t tt_buff_len = tt_len(tt_num_changes);
@@@ -1235,7 -1020,7 +1235,7 @@@ static int tt_global_valid_entry(const tt_global_entry = container_of(tt_common_entry, struct tt_global_entry, common);
- return (tt_global_entry->orig_node == orig_node); + return tt_global_entry_has_orig(tt_global_entry, orig_node); }
static struct sk_buff *tt_response_fill_table(uint16_t tt_len, uint8_t ttvn, @@@ -1617,13 -1402,9 +1617,13 @@@ out bool send_tt_response(struct bat_priv *bat_priv, struct tt_query_packet *tt_request) { - if (is_my_mac(tt_request->dst)) + if (is_my_mac(tt_request->dst)) { + /* don't answer backbone gws! */ + if (bla_is_backbone_gw_orig(bat_priv, tt_request->src)) + return true; + return send_my_tt_response(bat_priv, tt_request); - else + } else return send_other_tt_response(bat_priv, tt_request); }
@@@ -1729,10 -1510,6 +1729,10 @@@ void handle_tt_response(struct bat_pri tt_response->tt_data, (tt_response->flags & TT_FULL_TABLE ? 'F' : '.'));
+ /* we should have never asked a backbone gw */ + if (bla_is_backbone_gw_orig(bat_priv, tt_response->src)) + goto out; + orig_node = orig_hash_find(bat_priv, tt_response->src); if (!orig_node) goto out; @@@ -1852,8 -1629,8 +1852,8 @@@ unlock return ret; }
-void send_roam_adv(struct bat_priv *bat_priv, uint8_t *client, - struct orig_node *orig_node) +static void send_roam_adv(struct bat_priv *bat_priv, uint8_t *client, + struct orig_node *orig_node) { struct neigh_node *neigh_node = NULL; struct sk_buff *skb = NULL; @@@ -2020,8 -1797,6 +2020,8 @@@ void tt_commit_changes(struct bat_priv
/* Increment the TTVN only once per OGM interval */ atomic_inc(&bat_priv->ttvn); + bat_dbg(DBG_TT, bat_priv, "Local changes committed, updating to ttvn %u\n", + (uint8_t)atomic_read(&bat_priv->ttvn)); bat_priv->tt_poss_change = false; }
@@@ -2062,10 -1837,6 +2062,10 @@@ void tt_update_orig(struct bat_priv *ba uint8_t orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); bool full_table = true;
+ /* don't care about a backbone gateways updates. */ + if (bla_is_backbone_gw_orig(bat_priv, orig_node->orig)) + return; + /* orig table not initialised AND first diff is in the OGM OR the ttvn * increased by one -> we can apply the attached changes */ if ((!orig_node->tt_initialised && ttvn == 1) || @@@ -2103,7 -1874,6 +2103,7 @@@ } else { /* if we missed more than one change or our tables are not * in sync anymore -> request fresh tt data */ + if (!orig_node->tt_initialised || ttvn != orig_ttvn || orig_node->tt_crc != tt_crc) { request_table: