diff options
author | David S. Miller <davem@davemloft.net> | 2011-08-24 13:33:00 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-08-24 13:33:00 -0400 |
commit | 0e43182c0c9482a26a4108da9254f3e2869a8e18 (patch) | |
tree | 4631b42bebca8dd9bca61e167e543aabd3b981a7 | |
parent | 131ea6675c761f655d43b808dd0fe83d15d5cdd3 (diff) | |
parent | a943cac144e035c21d4f1b31b95f15b33c33a480 (diff) |
Merge branch 'batman-adv/next' of git://git.open-mesh.org/linux-merge
-rw-r--r-- | Documentation/ABI/testing/sysfs-class-net-mesh | 8 | ||||
-rw-r--r-- | net/batman-adv/aggregation.h | 3 | ||||
-rw-r--r-- | net/batman-adv/bat_sysfs.c | 2 | ||||
-rw-r--r-- | net/batman-adv/bitarray.c | 6 | ||||
-rw-r--r-- | net/batman-adv/gateway_client.c | 10 | ||||
-rw-r--r-- | net/batman-adv/hard-interface.c | 34 | ||||
-rw-r--r-- | net/batman-adv/hard-interface.h | 1 | ||||
-rw-r--r-- | net/batman-adv/hash.h | 25 | ||||
-rw-r--r-- | net/batman-adv/main.c | 2 | ||||
-rw-r--r-- | net/batman-adv/main.h | 6 | ||||
-rw-r--r-- | net/batman-adv/originator.c | 2 | ||||
-rw-r--r-- | net/batman-adv/packet.h | 1 | ||||
-rw-r--r-- | net/batman-adv/routing.c | 77 | ||||
-rw-r--r-- | net/batman-adv/send.c | 10 | ||||
-rw-r--r-- | net/batman-adv/soft-interface.c | 13 | ||||
-rw-r--r-- | net/batman-adv/translation-table.c | 199 | ||||
-rw-r--r-- | net/batman-adv/translation-table.h | 21 | ||||
-rw-r--r-- | net/batman-adv/types.h | 5 | ||||
-rw-r--r-- | net/batman-adv/unicast.c | 6 | ||||
-rw-r--r-- | net/batman-adv/unicast.h | 2 | ||||
-rw-r--r-- | net/batman-adv/vis.c | 6 |
21 files changed, 291 insertions, 148 deletions
diff --git a/Documentation/ABI/testing/sysfs-class-net-mesh b/Documentation/ABI/testing/sysfs-class-net-mesh index 748fe1701d25..b02001488eef 100644 --- a/Documentation/ABI/testing/sysfs-class-net-mesh +++ b/Documentation/ABI/testing/sysfs-class-net-mesh | |||
@@ -22,6 +22,14 @@ Description: | |||
22 | mesh will be fragmented or silently discarded if the | 22 | mesh will be fragmented or silently discarded if the |
23 | packet size exceeds the outgoing interface MTU. | 23 | packet size exceeds the outgoing interface MTU. |
24 | 24 | ||
25 | What: /sys/class/net/<mesh_iface>/mesh/ap_isolation | ||
26 | Date: May 2011 | ||
27 | Contact: Antonio Quartulli <ordex@autistici.org> | ||
28 | Description: | ||
29 | Indicates whether the data traffic going from a | ||
30 | wireless client to another wireless client will be | ||
31 | silently dropped. | ||
32 | |||
25 | What: /sys/class/net/<mesh_iface>/mesh/gw_bandwidth | 33 | What: /sys/class/net/<mesh_iface>/mesh/gw_bandwidth |
26 | Date: October 2010 | 34 | Date: October 2010 |
27 | Contact: Marek Lindner <lindner_marek@yahoo.de> | 35 | Contact: Marek Lindner <lindner_marek@yahoo.de> |
diff --git a/net/batman-adv/aggregation.h b/net/batman-adv/aggregation.h index 216337bb841f..df4a5a943088 100644 --- a/net/batman-adv/aggregation.h +++ b/net/batman-adv/aggregation.h | |||
@@ -28,8 +28,7 @@ | |||
28 | static inline int aggregated_packet(int buff_pos, int packet_len, | 28 | static inline int aggregated_packet(int buff_pos, int packet_len, |
29 | int tt_num_changes) | 29 | int tt_num_changes) |
30 | { | 30 | { |
31 | int next_buff_pos = buff_pos + BAT_PACKET_LEN + (tt_num_changes * | 31 | int next_buff_pos = buff_pos + BAT_PACKET_LEN + tt_len(tt_num_changes); |
32 | sizeof(struct tt_change)); | ||
33 | 32 | ||
34 | return (next_buff_pos <= packet_len) && | 33 | return (next_buff_pos <= packet_len) && |
35 | (next_buff_pos <= MAX_AGGREGATION_BYTES); | 34 | (next_buff_pos <= MAX_AGGREGATION_BYTES); |
diff --git a/net/batman-adv/bat_sysfs.c b/net/batman-adv/bat_sysfs.c index cd15deba60a1..b8a7414c3571 100644 --- a/net/batman-adv/bat_sysfs.c +++ b/net/batman-adv/bat_sysfs.c | |||
@@ -380,6 +380,7 @@ static ssize_t store_gw_bwidth(struct kobject *kobj, struct attribute *attr, | |||
380 | BAT_ATTR_BOOL(aggregated_ogms, S_IRUGO | S_IWUSR, NULL); | 380 | BAT_ATTR_BOOL(aggregated_ogms, S_IRUGO | S_IWUSR, NULL); |
381 | BAT_ATTR_BOOL(bonding, S_IRUGO | S_IWUSR, NULL); | 381 | BAT_ATTR_BOOL(bonding, S_IRUGO | S_IWUSR, NULL); |
382 | BAT_ATTR_BOOL(fragmentation, S_IRUGO | S_IWUSR, update_min_mtu); | 382 | BAT_ATTR_BOOL(fragmentation, S_IRUGO | S_IWUSR, update_min_mtu); |
383 | BAT_ATTR_BOOL(ap_isolation, S_IRUGO | S_IWUSR, NULL); | ||
383 | static BAT_ATTR(vis_mode, S_IRUGO | S_IWUSR, show_vis_mode, store_vis_mode); | 384 | static BAT_ATTR(vis_mode, S_IRUGO | S_IWUSR, show_vis_mode, store_vis_mode); |
384 | static BAT_ATTR(gw_mode, S_IRUGO | S_IWUSR, show_gw_mode, store_gw_mode); | 385 | static BAT_ATTR(gw_mode, S_IRUGO | S_IWUSR, show_gw_mode, store_gw_mode); |
385 | BAT_ATTR_UINT(orig_interval, S_IRUGO | S_IWUSR, 2 * JITTER, INT_MAX, NULL); | 386 | BAT_ATTR_UINT(orig_interval, S_IRUGO | S_IWUSR, 2 * JITTER, INT_MAX, NULL); |
@@ -396,6 +397,7 @@ static struct bat_attribute *mesh_attrs[] = { | |||
396 | &bat_attr_aggregated_ogms, | 397 | &bat_attr_aggregated_ogms, |
397 | &bat_attr_bonding, | 398 | &bat_attr_bonding, |
398 | &bat_attr_fragmentation, | 399 | &bat_attr_fragmentation, |
400 | &bat_attr_ap_isolation, | ||
399 | &bat_attr_vis_mode, | 401 | &bat_attr_vis_mode, |
400 | &bat_attr_gw_mode, | 402 | &bat_attr_gw_mode, |
401 | &bat_attr_orig_interval, | 403 | &bat_attr_orig_interval, |
diff --git a/net/batman-adv/bitarray.c b/net/batman-adv/bitarray.c index c1f4bfc09cc3..0be9ff346fa0 100644 --- a/net/batman-adv/bitarray.c +++ b/net/batman-adv/bitarray.c | |||
@@ -97,12 +97,12 @@ static void bit_shift(unsigned long *seq_bits, int32_t n) | |||
97 | (seq_bits[i - word_num - 1] >> | 97 | (seq_bits[i - word_num - 1] >> |
98 | (WORD_BIT_SIZE-word_offset)); | 98 | (WORD_BIT_SIZE-word_offset)); |
99 | /* and the upper part of the right half and shift it left to | 99 | /* and the upper part of the right half and shift it left to |
100 | * it's position */ | 100 | * its position */ |
101 | /* for our example that would be: word[0] = 9800 + 0076 = | 101 | /* for our example that would be: word[0] = 9800 + 0076 = |
102 | * 9876 */ | 102 | * 9876 */ |
103 | } | 103 | } |
104 | /* now for our last word, i==word_num, we only have the it's "left" | 104 | /* now for our last word, i==word_num, we only have its "left" half. |
105 | * half. that's the 1000 word in our example.*/ | 105 | * that's the 1000 word in our example.*/ |
106 | 106 | ||
107 | seq_bits[i] = (seq_bits[i - word_num] << word_offset); | 107 | seq_bits[i] = (seq_bits[i - word_num] << word_offset); |
108 | 108 | ||
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index 056180ef9e1a..619fb73b3b76 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c | |||
@@ -532,14 +532,14 @@ static bool is_type_dhcprequest(struct sk_buff *skb, int header_len) | |||
532 | pkt_len -= header_len + DHCP_OPTIONS_OFFSET + 1; | 532 | pkt_len -= header_len + DHCP_OPTIONS_OFFSET + 1; |
533 | 533 | ||
534 | /* Access the dhcp option lists. Each entry is made up by: | 534 | /* Access the dhcp option lists. Each entry is made up by: |
535 | * - octect 1: option type | 535 | * - octet 1: option type |
536 | * - octect 2: option data len (only if type != 255 and 0) | 536 | * - octet 2: option data len (only if type != 255 and 0) |
537 | * - octect 3: option data */ | 537 | * - octet 3: option data */ |
538 | while (*p != 255 && !ret) { | 538 | while (*p != 255 && !ret) { |
539 | /* p now points to the first octect: option type */ | 539 | /* p now points to the first octet: option type */ |
540 | if (*p == 53) { | 540 | if (*p == 53) { |
541 | /* type 53 is the message type option. | 541 | /* type 53 is the message type option. |
542 | * Jump the len octect and go to the data octect */ | 542 | * Jump the len octet and go to the data octet */ |
543 | if (pkt_len < 2) | 543 | if (pkt_len < 2) |
544 | goto out; | 544 | goto out; |
545 | p += 2; | 545 | p += 2; |
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index db7aacf1e095..bf91e4d8a47f 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c | |||
@@ -249,7 +249,7 @@ static void hardif_activate_interface(struct hard_iface *hard_iface) | |||
249 | 249 | ||
250 | /** | 250 | /** |
251 | * the first active interface becomes our primary interface or | 251 | * the first active interface becomes our primary interface or |
252 | * the next active interface after the old primay interface was removed | 252 | * the next active interface after the old primary interface was removed |
253 | */ | 253 | */ |
254 | primary_if = primary_if_get_selected(bat_priv); | 254 | primary_if = primary_if_get_selected(bat_priv); |
255 | if (!primary_if) | 255 | if (!primary_if) |
@@ -573,7 +573,7 @@ out: | |||
573 | return NOTIFY_DONE; | 573 | return NOTIFY_DONE; |
574 | } | 574 | } |
575 | 575 | ||
576 | /* receive a packet with the batman ethertype coming on a hard | 576 | /* incoming packets with the batman ethertype received on any active hard |
577 | * interface */ | 577 | * interface */ |
578 | static int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, | 578 | static int batman_skb_recv(struct sk_buff *skb, struct net_device *dev, |
579 | struct packet_type *ptype, | 579 | struct packet_type *ptype, |
@@ -681,6 +681,36 @@ err_out: | |||
681 | return NET_RX_DROP; | 681 | return NET_RX_DROP; |
682 | } | 682 | } |
683 | 683 | ||
684 | /* This function returns true if the interface represented by ifindex is a | ||
685 | * 802.11 wireless device */ | ||
686 | bool is_wifi_iface(int ifindex) | ||
687 | { | ||
688 | struct net_device *net_device = NULL; | ||
689 | bool ret = false; | ||
690 | |||
691 | if (ifindex == NULL_IFINDEX) | ||
692 | goto out; | ||
693 | |||
694 | net_device = dev_get_by_index(&init_net, ifindex); | ||
695 | if (!net_device) | ||
696 | goto out; | ||
697 | |||
698 | #ifdef CONFIG_WIRELESS_EXT | ||
699 | /* pre-cfg80211 drivers have to implement WEXT, so it is possible to | ||
700 | * check for wireless_handlers != NULL */ | ||
701 | if (net_device->wireless_handlers) | ||
702 | ret = true; | ||
703 | else | ||
704 | #endif | ||
705 | /* cfg80211 drivers have to set ieee80211_ptr */ | ||
706 | if (net_device->ieee80211_ptr) | ||
707 | ret = true; | ||
708 | out: | ||
709 | if (net_device) | ||
710 | dev_put(net_device); | ||
711 | return ret; | ||
712 | } | ||
713 | |||
684 | struct notifier_block hard_if_notifier = { | 714 | struct notifier_block hard_if_notifier = { |
685 | .notifier_call = hard_if_event, | 715 | .notifier_call = hard_if_event, |
686 | }; | 716 | }; |
diff --git a/net/batman-adv/hard-interface.h b/net/batman-adv/hard-interface.h index 442eacbc9e3a..67f78d1a63b4 100644 --- a/net/batman-adv/hard-interface.h +++ b/net/batman-adv/hard-interface.h | |||
@@ -42,6 +42,7 @@ void hardif_remove_interfaces(void); | |||
42 | int hardif_min_mtu(struct net_device *soft_iface); | 42 | int hardif_min_mtu(struct net_device *soft_iface); |
43 | void update_min_mtu(struct net_device *soft_iface); | 43 | void update_min_mtu(struct net_device *soft_iface); |
44 | void hardif_free_rcu(struct rcu_head *rcu); | 44 | void hardif_free_rcu(struct rcu_head *rcu); |
45 | bool is_wifi_iface(int ifindex); | ||
45 | 46 | ||
46 | static inline void hardif_free_ref(struct hard_iface *hard_iface) | 47 | static inline void hardif_free_ref(struct hard_iface *hard_iface) |
47 | { | 48 | { |
diff --git a/net/batman-adv/hash.h b/net/batman-adv/hash.h index dd5c9fd7a905..d20aa71ba1e8 100644 --- a/net/batman-adv/hash.h +++ b/net/batman-adv/hash.h | |||
@@ -76,19 +76,30 @@ static inline void hash_delete(struct hashtable_t *hash, | |||
76 | hash_destroy(hash); | 76 | hash_destroy(hash); |
77 | } | 77 | } |
78 | 78 | ||
79 | /* adds data to the hashtable. returns 0 on success, -1 on error */ | 79 | /** |
80 | * hash_add - adds data to the hashtable | ||
81 | * @hash: storage hash table | ||
82 | * @compare: callback to determine if 2 hash elements are identical | ||
83 | * @choose: callback calculating the hash index | ||
84 | * @data: data passed to the aforementioned callbacks as argument | ||
85 | * @data_node: to be added element | ||
86 | * | ||
87 | * Returns 0 on success, 1 if the element already is in the hash | ||
88 | * and -1 on error. | ||
89 | */ | ||
90 | |||
80 | static inline int hash_add(struct hashtable_t *hash, | 91 | static inline int hash_add(struct hashtable_t *hash, |
81 | hashdata_compare_cb compare, | 92 | hashdata_compare_cb compare, |
82 | hashdata_choose_cb choose, | 93 | hashdata_choose_cb choose, |
83 | const void *data, struct hlist_node *data_node) | 94 | const void *data, struct hlist_node *data_node) |
84 | { | 95 | { |
85 | int index; | 96 | int index, ret = -1; |
86 | struct hlist_head *head; | 97 | struct hlist_head *head; |
87 | struct hlist_node *node; | 98 | struct hlist_node *node; |
88 | spinlock_t *list_lock; /* spinlock to protect write access */ | 99 | spinlock_t *list_lock; /* spinlock to protect write access */ |
89 | 100 | ||
90 | if (!hash) | 101 | if (!hash) |
91 | goto err; | 102 | goto out; |
92 | 103 | ||
93 | index = choose(data, hash->size); | 104 | index = choose(data, hash->size); |
94 | head = &hash->table[index]; | 105 | head = &hash->table[index]; |
@@ -99,6 +110,7 @@ static inline int hash_add(struct hashtable_t *hash, | |||
99 | if (!compare(node, data)) | 110 | if (!compare(node, data)) |
100 | continue; | 111 | continue; |
101 | 112 | ||
113 | ret = 1; | ||
102 | goto err_unlock; | 114 | goto err_unlock; |
103 | } | 115 | } |
104 | rcu_read_unlock(); | 116 | rcu_read_unlock(); |
@@ -108,12 +120,13 @@ static inline int hash_add(struct hashtable_t *hash, | |||
108 | hlist_add_head_rcu(data_node, head); | 120 | hlist_add_head_rcu(data_node, head); |
109 | spin_unlock_bh(list_lock); | 121 | spin_unlock_bh(list_lock); |
110 | 122 | ||
111 | return 0; | 123 | ret = 0; |
124 | goto out; | ||
112 | 125 | ||
113 | err_unlock: | 126 | err_unlock: |
114 | rcu_read_unlock(); | 127 | rcu_read_unlock(); |
115 | err: | 128 | out: |
116 | return -1; | 129 | return ret; |
117 | } | 130 | } |
118 | 131 | ||
119 | /* removes data from hash, if found. returns pointer do data on success, so you | 132 | /* removes data from hash, if found. returns pointer do data on success, so you |
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index b0f9068ade57..79b9ae522ce9 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c | |||
@@ -107,7 +107,7 @@ int mesh_init(struct net_device *soft_iface) | |||
107 | if (tt_init(bat_priv) < 1) | 107 | if (tt_init(bat_priv) < 1) |
108 | goto err; | 108 | goto err; |
109 | 109 | ||
110 | tt_local_add(soft_iface, soft_iface->dev_addr); | 110 | tt_local_add(soft_iface, soft_iface->dev_addr, NULL_IFINDEX); |
111 | 111 | ||
112 | if (vis_init(bat_priv) < 1) | 112 | if (vis_init(bat_priv) < 1) |
113 | goto err; | 113 | goto err; |
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index a6df61a6933b..60b369635b4d 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h | |||
@@ -44,7 +44,7 @@ | |||
44 | #define PURGE_TIMEOUT 200 | 44 | #define PURGE_TIMEOUT 200 |
45 | #define TT_LOCAL_TIMEOUT 3600 /* in seconds */ | 45 | #define TT_LOCAL_TIMEOUT 3600 /* in seconds */ |
46 | #define TT_CLIENT_ROAM_TIMEOUT 600 | 46 | #define TT_CLIENT_ROAM_TIMEOUT 600 |
47 | /* sliding packet range of received originator messages in squence numbers | 47 | /* sliding packet range of received originator messages in sequence numbers |
48 | * (should be a multiple of our word size) */ | 48 | * (should be a multiple of our word size) */ |
49 | #define TQ_LOCAL_WINDOW_SIZE 64 | 49 | #define TQ_LOCAL_WINDOW_SIZE 64 |
50 | #define TT_REQUEST_TIMEOUT 3 /* seconds we have to keep pending tt_req */ | 50 | #define TT_REQUEST_TIMEOUT 3 /* seconds we have to keep pending tt_req */ |
@@ -62,6 +62,8 @@ | |||
62 | 62 | ||
63 | #define NO_FLAGS 0 | 63 | #define NO_FLAGS 0 |
64 | 64 | ||
65 | #define NULL_IFINDEX 0 /* dummy ifindex used to avoid iface checks */ | ||
66 | |||
65 | #define NUM_WORDS (TQ_LOCAL_WINDOW_SIZE / WORD_BIT_SIZE) | 67 | #define NUM_WORDS (TQ_LOCAL_WINDOW_SIZE / WORD_BIT_SIZE) |
66 | 68 | ||
67 | #define LOG_BUF_LEN 8192 /* has to be a power of 2 */ | 69 | #define LOG_BUF_LEN 8192 /* has to be a power of 2 */ |
@@ -133,7 +135,7 @@ enum dbg_level { | |||
133 | #include <linux/mutex.h> /* mutex */ | 135 | #include <linux/mutex.h> /* mutex */ |
134 | #include <linux/module.h> /* needed by all modules */ | 136 | #include <linux/module.h> /* needed by all modules */ |
135 | #include <linux/netdevice.h> /* netdevice */ | 137 | #include <linux/netdevice.h> /* netdevice */ |
136 | #include <linux/etherdevice.h> /* ethernet address classifaction */ | 138 | #include <linux/etherdevice.h> /* ethernet address classification */ |
137 | #include <linux/if_ether.h> /* ethernet header */ | 139 | #include <linux/if_ether.h> /* ethernet header */ |
138 | #include <linux/poll.h> /* poll_table */ | 140 | #include <linux/poll.h> /* poll_table */ |
139 | #include <linux/kthread.h> /* kernel threads */ | 141 | #include <linux/kthread.h> /* kernel threads */ |
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index f3c3f620d195..d448018e514f 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c | |||
@@ -252,7 +252,7 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, const uint8_t *addr) | |||
252 | 252 | ||
253 | hash_added = hash_add(bat_priv->orig_hash, compare_orig, | 253 | hash_added = hash_add(bat_priv->orig_hash, compare_orig, |
254 | choose_orig, orig_node, &orig_node->hash_entry); | 254 | choose_orig, orig_node, &orig_node->hash_entry); |
255 | if (hash_added < 0) | 255 | if (hash_added != 0) |
256 | goto free_bcast_own_sum; | 256 | goto free_bcast_own_sum; |
257 | 257 | ||
258 | return orig_node; | 258 | return orig_node; |
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h index b76b4be10b92..8802eab2a46d 100644 --- a/net/batman-adv/packet.h +++ b/net/batman-adv/packet.h | |||
@@ -84,6 +84,7 @@ enum tt_query_flags { | |||
84 | enum tt_client_flags { | 84 | enum tt_client_flags { |
85 | TT_CLIENT_DEL = 1 << 0, | 85 | TT_CLIENT_DEL = 1 << 0, |
86 | TT_CLIENT_ROAM = 1 << 1, | 86 | TT_CLIENT_ROAM = 1 << 1, |
87 | TT_CLIENT_WIFI = 1 << 2, | ||
87 | TT_CLIENT_NOPURGE = 1 << 8, | 88 | TT_CLIENT_NOPURGE = 1 << 8, |
88 | TT_CLIENT_NEW = 1 << 9, | 89 | TT_CLIENT_NEW = 1 << 9, |
89 | TT_CLIENT_PENDING = 1 << 10 | 90 | TT_CLIENT_PENDING = 1 << 10 |
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index 0f32c818874d..19499281b695 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c | |||
@@ -64,66 +64,6 @@ void slide_own_bcast_window(struct hard_iface *hard_iface) | |||
64 | } | 64 | } |
65 | } | 65 | } |
66 | 66 | ||
67 | static void update_transtable(struct bat_priv *bat_priv, | ||
68 | struct orig_node *orig_node, | ||
69 | const unsigned char *tt_buff, | ||
70 | uint8_t tt_num_changes, uint8_t ttvn, | ||
71 | uint16_t tt_crc) | ||
72 | { | ||
73 | uint8_t orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); | ||
74 | bool full_table = true; | ||
75 | |||
76 | /* the ttvn increased by one -> we can apply the attached changes */ | ||
77 | if (ttvn - orig_ttvn == 1) { | ||
78 | /* the OGM could not contain the changes because they were too | ||
79 | * many to fit in one frame or because they have already been | ||
80 | * sent TT_OGM_APPEND_MAX times. In this case send a tt | ||
81 | * request */ | ||
82 | if (!tt_num_changes) { | ||
83 | full_table = false; | ||
84 | goto request_table; | ||
85 | } | ||
86 | |||
87 | tt_update_changes(bat_priv, orig_node, tt_num_changes, ttvn, | ||
88 | (struct tt_change *)tt_buff); | ||
89 | |||
90 | /* Even if we received the crc into the OGM, we prefer | ||
91 | * to recompute it to spot any possible inconsistency | ||
92 | * in the global table */ | ||
93 | orig_node->tt_crc = tt_global_crc(bat_priv, orig_node); | ||
94 | |||
95 | /* The ttvn alone is not enough to guarantee consistency | ||
96 | * because a single value could repesent different states | ||
97 | * (due to the wrap around). Thus a node has to check whether | ||
98 | * the resulting table (after applying the changes) is still | ||
99 | * consistent or not. E.g. a node could disconnect while its | ||
100 | * ttvn is X and reconnect on ttvn = X + TTVN_MAX: in this case | ||
101 | * checking the CRC value is mandatory to detect the | ||
102 | * inconsistency */ | ||
103 | if (orig_node->tt_crc != tt_crc) | ||
104 | goto request_table; | ||
105 | |||
106 | /* Roaming phase is over: tables are in sync again. I can | ||
107 | * unset the flag */ | ||
108 | orig_node->tt_poss_change = false; | ||
109 | } else { | ||
110 | /* if we missed more than one change or our tables are not | ||
111 | * in sync anymore -> request fresh tt data */ | ||
112 | if (ttvn != orig_ttvn || orig_node->tt_crc != tt_crc) { | ||
113 | request_table: | ||
114 | bat_dbg(DBG_TT, bat_priv, "TT inconsistency for %pM. " | ||
115 | "Need to retrieve the correct information " | ||
116 | "(ttvn: %u last_ttvn: %u crc: %u last_crc: " | ||
117 | "%u num_changes: %u)\n", orig_node->orig, ttvn, | ||
118 | orig_ttvn, tt_crc, orig_node->tt_crc, | ||
119 | tt_num_changes); | ||
120 | send_tt_request(bat_priv, orig_node, ttvn, tt_crc, | ||
121 | full_table); | ||
122 | return; | ||
123 | } | ||
124 | } | ||
125 | } | ||
126 | |||
127 | static void update_route(struct bat_priv *bat_priv, | 67 | static void update_route(struct bat_priv *bat_priv, |
128 | struct orig_node *orig_node, | 68 | struct orig_node *orig_node, |
129 | struct neigh_node *neigh_node) | 69 | struct neigh_node *neigh_node) |
@@ -228,7 +168,7 @@ static int is_bidirectional_neigh(struct orig_node *orig_node, | |||
228 | if (!neigh_node) | 168 | if (!neigh_node) |
229 | goto out; | 169 | goto out; |
230 | 170 | ||
231 | /* if orig_node is direct neighbour update neigh_node last_valid */ | 171 | /* if orig_node is direct neighbor update neigh_node last_valid */ |
232 | if (orig_node == orig_neigh_node) | 172 | if (orig_node == orig_neigh_node) |
233 | neigh_node->last_valid = jiffies; | 173 | neigh_node->last_valid = jiffies; |
234 | 174 | ||
@@ -473,7 +413,7 @@ static void update_orig(struct bat_priv *bat_priv, struct orig_node *orig_node, | |||
473 | if (router && (router->tq_avg > neigh_node->tq_avg)) | 413 | if (router && (router->tq_avg > neigh_node->tq_avg)) |
474 | goto update_tt; | 414 | goto update_tt; |
475 | 415 | ||
476 | /* if the TQ is the same and the link not more symetric we | 416 | /* if the TQ is the same and the link not more symmetric we |
477 | * won't consider it either */ | 417 | * won't consider it either */ |
478 | if (router && (neigh_node->tq_avg == router->tq_avg)) { | 418 | if (router && (neigh_node->tq_avg == router->tq_avg)) { |
479 | orig_node_tmp = router->orig_node; | 419 | orig_node_tmp = router->orig_node; |
@@ -500,10 +440,9 @@ update_tt: | |||
500 | if (((batman_packet->orig != ethhdr->h_source) && | 440 | if (((batman_packet->orig != ethhdr->h_source) && |
501 | (batman_packet->ttl > 2)) || | 441 | (batman_packet->ttl > 2)) || |
502 | (batman_packet->flags & PRIMARIES_FIRST_HOP)) | 442 | (batman_packet->flags & PRIMARIES_FIRST_HOP)) |
503 | update_transtable(bat_priv, orig_node, tt_buff, | 443 | tt_update_orig(bat_priv, orig_node, tt_buff, |
504 | batman_packet->tt_num_changes, | 444 | batman_packet->tt_num_changes, |
505 | batman_packet->ttvn, | 445 | batman_packet->ttvn, batman_packet->tt_crc); |
506 | batman_packet->tt_crc); | ||
507 | 446 | ||
508 | if (orig_node->gw_flags != batman_packet->gw_flags) | 447 | if (orig_node->gw_flags != batman_packet->gw_flags) |
509 | gw_node_update(bat_priv, orig_node, batman_packet->gw_flags); | 448 | gw_node_update(bat_priv, orig_node, batman_packet->gw_flags); |
@@ -1243,7 +1182,7 @@ int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if) | |||
1243 | } | 1182 | } |
1244 | break; | 1183 | break; |
1245 | case TT_RESPONSE: | 1184 | case TT_RESPONSE: |
1246 | /* packet needs to be linearised to access the TT changes */ | 1185 | /* packet needs to be linearized to access the TT changes */ |
1247 | if (skb_linearize(skb) < 0) | 1186 | if (skb_linearize(skb) < 0) |
1248 | goto out; | 1187 | goto out; |
1249 | 1188 | ||
@@ -1300,7 +1239,7 @@ int recv_roam_adv(struct sk_buff *skb, struct hard_iface *recv_if) | |||
1300 | roam_adv_packet->client); | 1239 | roam_adv_packet->client); |
1301 | 1240 | ||
1302 | tt_global_add(bat_priv, orig_node, roam_adv_packet->client, | 1241 | tt_global_add(bat_priv, orig_node, roam_adv_packet->client, |
1303 | atomic_read(&orig_node->last_ttvn) + 1, true); | 1242 | atomic_read(&orig_node->last_ttvn) + 1, true, false); |
1304 | 1243 | ||
1305 | /* Roaming phase starts: I have new information but the ttvn has not | 1244 | /* Roaming phase starts: I have new information but the ttvn has not |
1306 | * been incremented yet. This flag will make me check all the incoming | 1245 | * been incremented yet. This flag will make me check all the incoming |
@@ -1536,7 +1475,7 @@ static int check_unicast_ttvn(struct bat_priv *bat_priv, | |||
1536 | 1475 | ||
1537 | ethhdr = (struct ethhdr *)(skb->data + | 1476 | ethhdr = (struct ethhdr *)(skb->data + |
1538 | sizeof(struct unicast_packet)); | 1477 | sizeof(struct unicast_packet)); |
1539 | orig_node = transtable_search(bat_priv, ethhdr->h_dest); | 1478 | orig_node = transtable_search(bat_priv, NULL, ethhdr->h_dest); |
1540 | 1479 | ||
1541 | if (!orig_node) { | 1480 | if (!orig_node) { |
1542 | if (!is_my_client(bat_priv, ethhdr->h_dest)) | 1481 | if (!is_my_client(bat_priv, ethhdr->h_dest)) |
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c index 58d14472068c..57ae80936911 100644 --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c | |||
@@ -135,7 +135,7 @@ static void send_packet_to_if(struct forw_packet *forw_packet, | |||
135 | "Forwarding")); | 135 | "Forwarding")); |
136 | bat_dbg(DBG_BATMAN, bat_priv, | 136 | bat_dbg(DBG_BATMAN, bat_priv, |
137 | "%s %spacket (originator %pM, seqno %d, TQ %d, TTL %d," | 137 | "%s %spacket (originator %pM, seqno %d, TQ %d, TTL %d," |
138 | " IDF %s, hvn %d) on interface %s [%pM]\n", | 138 | " IDF %s, ttvn %d) on interface %s [%pM]\n", |
139 | fwd_str, (packet_num > 0 ? "aggregated " : ""), | 139 | fwd_str, (packet_num > 0 ? "aggregated " : ""), |
140 | batman_packet->orig, ntohl(batman_packet->seqno), | 140 | batman_packet->orig, ntohl(batman_packet->seqno), |
141 | batman_packet->tq, batman_packet->ttl, | 141 | batman_packet->tq, batman_packet->ttl, |
@@ -313,7 +313,7 @@ void schedule_own_packet(struct hard_iface *hard_iface) | |||
313 | prepare_packet_buffer(bat_priv, hard_iface); | 313 | prepare_packet_buffer(bat_priv, hard_iface); |
314 | } | 314 | } |
315 | 315 | ||
316 | /* if the changes have been sent enough times */ | 316 | /* if the changes have been sent often enough */ |
317 | if (!atomic_dec_not_zero(&bat_priv->tt_ogm_append_cnt)) | 317 | if (!atomic_dec_not_zero(&bat_priv->tt_ogm_append_cnt)) |
318 | reset_packet_buffer(bat_priv, hard_iface); | 318 | reset_packet_buffer(bat_priv, hard_iface); |
319 | } | 319 | } |
@@ -454,7 +454,7 @@ static void _add_bcast_packet_to_list(struct bat_priv *bat_priv, | |||
454 | } | 454 | } |
455 | 455 | ||
456 | /* add a broadcast packet to the queue and setup timers. broadcast packets | 456 | /* add a broadcast packet to the queue and setup timers. broadcast packets |
457 | * are sent multiple times to increase probability for beeing received. | 457 | * are sent multiple times to increase probability for being received. |
458 | * | 458 | * |
459 | * This function returns NETDEV_TX_OK on success and NETDEV_TX_BUSY on | 459 | * This function returns NETDEV_TX_OK on success and NETDEV_TX_BUSY on |
460 | * errors. | 460 | * errors. |
@@ -612,7 +612,7 @@ void purge_outstanding_packets(struct bat_priv *bat_priv, | |||
612 | &bat_priv->forw_bcast_list, list) { | 612 | &bat_priv->forw_bcast_list, list) { |
613 | 613 | ||
614 | /** | 614 | /** |
615 | * if purge_outstanding_packets() was called with an argmument | 615 | * if purge_outstanding_packets() was called with an argument |
616 | * we delete only packets belonging to the given interface | 616 | * we delete only packets belonging to the given interface |
617 | */ | 617 | */ |
618 | if ((hard_iface) && | 618 | if ((hard_iface) && |
@@ -641,7 +641,7 @@ void purge_outstanding_packets(struct bat_priv *bat_priv, | |||
641 | &bat_priv->forw_bat_list, list) { | 641 | &bat_priv->forw_bat_list, list) { |
642 | 642 | ||
643 | /** | 643 | /** |
644 | * if purge_outstanding_packets() was called with an argmument | 644 | * if purge_outstanding_packets() was called with an argument |
645 | * we delete only packets belonging to the given interface | 645 | * we delete only packets belonging to the given interface |
646 | */ | 646 | */ |
647 | if ((hard_iface) && | 647 | if ((hard_iface) && |
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 3e2f91ffa4e2..402fd96239d8 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c | |||
@@ -532,11 +532,11 @@ static int interface_set_mac_addr(struct net_device *dev, void *p) | |||
532 | if (!is_valid_ether_addr(addr->sa_data)) | 532 | if (!is_valid_ether_addr(addr->sa_data)) |
533 | return -EADDRNOTAVAIL; | 533 | return -EADDRNOTAVAIL; |
534 | 534 | ||
535 | /* only modify transtable if it has been initialised before */ | 535 | /* only modify transtable if it has been initialized before */ |
536 | if (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE) { | 536 | if (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE) { |
537 | tt_local_remove(bat_priv, dev->dev_addr, | 537 | tt_local_remove(bat_priv, dev->dev_addr, |
538 | "mac address changed", false); | 538 | "mac address changed", false); |
539 | tt_local_add(dev, addr->sa_data); | 539 | tt_local_add(dev, addr->sa_data, NULL_IFINDEX); |
540 | } | 540 | } |
541 | 541 | ||
542 | memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); | 542 | memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); |
@@ -595,9 +595,10 @@ static int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) | |||
595 | goto dropped; | 595 | goto dropped; |
596 | 596 | ||
597 | /* Register the client MAC in the transtable */ | 597 | /* Register the client MAC in the transtable */ |
598 | tt_local_add(soft_iface, ethhdr->h_source); | 598 | tt_local_add(soft_iface, ethhdr->h_source, skb->skb_iif); |
599 | 599 | ||
600 | orig_node = transtable_search(bat_priv, ethhdr->h_dest); | 600 | orig_node = transtable_search(bat_priv, ethhdr->h_source, |
601 | ethhdr->h_dest); | ||
601 | if (is_multicast_ether_addr(ethhdr->h_dest) || | 602 | if (is_multicast_ether_addr(ethhdr->h_dest) || |
602 | (orig_node && orig_node->gw_flags)) { | 603 | (orig_node && orig_node->gw_flags)) { |
603 | ret = gw_is_target(bat_priv, skb, orig_node); | 604 | ret = gw_is_target(bat_priv, skb, orig_node); |
@@ -739,6 +740,9 @@ void interface_rx(struct net_device *soft_iface, | |||
739 | 740 | ||
740 | soft_iface->last_rx = jiffies; | 741 | soft_iface->last_rx = jiffies; |
741 | 742 | ||
743 | if (is_ap_isolated(bat_priv, ethhdr->h_source, ethhdr->h_dest)) | ||
744 | goto dropped; | ||
745 | |||
742 | netif_rx(skb); | 746 | netif_rx(skb); |
743 | goto out; | 747 | goto out; |
744 | 748 | ||
@@ -812,6 +816,7 @@ struct net_device *softif_create(const char *name) | |||
812 | 816 | ||
813 | atomic_set(&bat_priv->aggregated_ogms, 1); | 817 | atomic_set(&bat_priv->aggregated_ogms, 1); |
814 | atomic_set(&bat_priv->bonding, 0); | 818 | atomic_set(&bat_priv->bonding, 0); |
819 | atomic_set(&bat_priv->ap_isolation, 0); | ||
815 | atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE); | 820 | atomic_set(&bat_priv->vis_mode, VIS_TYPE_CLIENT_UPDATE); |
816 | atomic_set(&bat_priv->gw_mode, GW_MODE_OFF); | 821 | atomic_set(&bat_priv->gw_mode, GW_MODE_OFF); |
817 | atomic_set(&bat_priv->gw_sel_class, 20); | 822 | atomic_set(&bat_priv->gw_sel_class, 20); |
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index fb6931d00cd7..cc53f78e448c 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c | |||
@@ -183,7 +183,8 @@ static int tt_local_init(struct bat_priv *bat_priv) | |||
183 | return 1; | 183 | return 1; |
184 | } | 184 | } |
185 | 185 | ||
186 | void tt_local_add(struct net_device *soft_iface, const uint8_t *addr) | 186 | void tt_local_add(struct net_device *soft_iface, const uint8_t *addr, |
187 | int ifindex) | ||
187 | { | 188 | { |
188 | struct bat_priv *bat_priv = netdev_priv(soft_iface); | 189 | struct bat_priv *bat_priv = netdev_priv(soft_iface); |
189 | struct tt_local_entry *tt_local_entry = NULL; | 190 | struct tt_local_entry *tt_local_entry = NULL; |
@@ -207,6 +208,8 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr) | |||
207 | memcpy(tt_local_entry->addr, addr, ETH_ALEN); | 208 | memcpy(tt_local_entry->addr, addr, ETH_ALEN); |
208 | tt_local_entry->last_seen = jiffies; | 209 | tt_local_entry->last_seen = jiffies; |
209 | tt_local_entry->flags = NO_FLAGS; | 210 | tt_local_entry->flags = NO_FLAGS; |
211 | if (is_wifi_iface(ifindex)) | ||
212 | tt_local_entry->flags |= TT_CLIENT_WIFI; | ||
210 | atomic_set(&tt_local_entry->refcount, 2); | 213 | atomic_set(&tt_local_entry->refcount, 2); |
211 | 214 | ||
212 | /* the batman interface mac address should never be purged */ | 215 | /* the batman interface mac address should never be purged */ |
@@ -329,7 +332,7 @@ int tt_local_seq_print_text(struct seq_file *seq, void *offset) | |||
329 | 332 | ||
330 | rcu_read_lock(); | 333 | rcu_read_lock(); |
331 | __hlist_for_each_rcu(node, head) | 334 | __hlist_for_each_rcu(node, head) |
332 | buf_size += 21; | 335 | buf_size += 29; |
333 | rcu_read_unlock(); | 336 | rcu_read_unlock(); |
334 | } | 337 | } |
335 | 338 | ||
@@ -348,8 +351,19 @@ int tt_local_seq_print_text(struct seq_file *seq, void *offset) | |||
348 | rcu_read_lock(); | 351 | rcu_read_lock(); |
349 | hlist_for_each_entry_rcu(tt_local_entry, node, | 352 | hlist_for_each_entry_rcu(tt_local_entry, node, |
350 | head, hash_entry) { | 353 | head, hash_entry) { |
351 | pos += snprintf(buff + pos, 22, " * %pM\n", | 354 | pos += snprintf(buff + pos, 30, " * %pM " |
352 | tt_local_entry->addr); | 355 | "[%c%c%c%c%c]\n", |
356 | tt_local_entry->addr, | ||
357 | (tt_local_entry->flags & | ||
358 | TT_CLIENT_ROAM ? 'R' : '.'), | ||
359 | (tt_local_entry->flags & | ||
360 | TT_CLIENT_NOPURGE ? 'P' : '.'), | ||
361 | (tt_local_entry->flags & | ||
362 | TT_CLIENT_NEW ? 'N' : '.'), | ||
363 | (tt_local_entry->flags & | ||
364 | TT_CLIENT_PENDING ? 'X' : '.'), | ||
365 | (tt_local_entry->flags & | ||
366 | TT_CLIENT_WIFI ? 'W' : '.')); | ||
353 | } | 367 | } |
354 | rcu_read_unlock(); | 368 | rcu_read_unlock(); |
355 | } | 369 | } |
@@ -369,8 +383,8 @@ static void tt_local_set_pending(struct bat_priv *bat_priv, | |||
369 | tt_local_event(bat_priv, tt_local_entry->addr, | 383 | tt_local_event(bat_priv, tt_local_entry->addr, |
370 | tt_local_entry->flags | flags); | 384 | tt_local_entry->flags | flags); |
371 | 385 | ||
372 | /* The local client has to be merked as "pending to be removed" but has | 386 | /* The local client has to be marked as "pending to be removed" but has |
373 | * to be kept in the table in order to send it in an full tables | 387 | * to be kept in the table in order to send it in a full table |
374 | * response issued before the net ttvn increment (consistency check) */ | 388 | * response issued before the net ttvn increment (consistency check) */ |
375 | tt_local_entry->flags |= TT_CLIENT_PENDING; | 389 | tt_local_entry->flags |= TT_CLIENT_PENDING; |
376 | } | 390 | } |
@@ -495,7 +509,8 @@ static void tt_changes_list_free(struct bat_priv *bat_priv) | |||
495 | 509 | ||
496 | /* caller must hold orig_node refcount */ | 510 | /* caller must hold orig_node refcount */ |
497 | int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node, | 511 | int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node, |
498 | const unsigned char *tt_addr, uint8_t ttvn, bool roaming) | 512 | const unsigned char *tt_addr, uint8_t ttvn, bool roaming, |
513 | bool wifi) | ||
499 | { | 514 | { |
500 | struct tt_global_entry *tt_global_entry; | 515 | struct tt_global_entry *tt_global_entry; |
501 | struct orig_node *orig_node_tmp; | 516 | struct orig_node *orig_node_tmp; |
@@ -537,6 +552,9 @@ int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node, | |||
537 | tt_global_entry->roam_at = 0; | 552 | tt_global_entry->roam_at = 0; |
538 | } | 553 | } |
539 | 554 | ||
555 | if (wifi) | ||
556 | tt_global_entry->flags |= TT_CLIENT_WIFI; | ||
557 | |||
540 | bat_dbg(DBG_TT, bat_priv, | 558 | bat_dbg(DBG_TT, bat_priv, |
541 | "Creating new global tt entry: %pM (via %pM)\n", | 559 | "Creating new global tt entry: %pM (via %pM)\n", |
542 | tt_global_entry->addr, orig_node->orig); | 560 | tt_global_entry->addr, orig_node->orig); |
@@ -582,8 +600,8 @@ int tt_global_seq_print_text(struct seq_file *seq, void *offset) | |||
582 | seq_printf(seq, | 600 | seq_printf(seq, |
583 | "Globally announced TT entries received via the mesh %s\n", | 601 | "Globally announced TT entries received via the mesh %s\n", |
584 | net_dev->name); | 602 | net_dev->name); |
585 | seq_printf(seq, " %-13s %s %-15s %s\n", | 603 | seq_printf(seq, " %-13s %s %-15s %s %s\n", |
586 | "Client", "(TTVN)", "Originator", "(Curr TTVN)"); | 604 | "Client", "(TTVN)", "Originator", "(Curr TTVN)", "Flags"); |
587 | 605 | ||
588 | buf_size = 1; | 606 | buf_size = 1; |
589 | /* Estimate length for: " * xx:xx:xx:xx:xx:xx (ttvn) via | 607 | /* Estimate length for: " * xx:xx:xx:xx:xx:xx (ttvn) via |
@@ -593,7 +611,7 @@ int tt_global_seq_print_text(struct seq_file *seq, void *offset) | |||
593 | 611 | ||
594 | rcu_read_lock(); | 612 | rcu_read_lock(); |
595 | __hlist_for_each_rcu(node, head) | 613 | __hlist_for_each_rcu(node, head) |
596 | buf_size += 59; | 614 | buf_size += 67; |
597 | rcu_read_unlock(); | 615 | rcu_read_unlock(); |
598 | } | 616 | } |
599 | 617 | ||
@@ -612,14 +630,20 @@ int tt_global_seq_print_text(struct seq_file *seq, void *offset) | |||
612 | rcu_read_lock(); | 630 | rcu_read_lock(); |
613 | hlist_for_each_entry_rcu(tt_global_entry, node, | 631 | hlist_for_each_entry_rcu(tt_global_entry, node, |
614 | head, hash_entry) { | 632 | head, hash_entry) { |
615 | pos += snprintf(buff + pos, 61, | 633 | pos += snprintf(buff + pos, 69, |
616 | " * %pM (%3u) via %pM (%3u)\n", | 634 | " * %pM (%3u) via %pM (%3u) " |
617 | tt_global_entry->addr, | 635 | "[%c%c%c]\n", tt_global_entry->addr, |
618 | tt_global_entry->ttvn, | 636 | tt_global_entry->ttvn, |
619 | tt_global_entry->orig_node->orig, | 637 | tt_global_entry->orig_node->orig, |
620 | (uint8_t) atomic_read( | 638 | (uint8_t) atomic_read( |
621 | &tt_global_entry->orig_node-> | 639 | &tt_global_entry->orig_node-> |
622 | last_ttvn)); | 640 | last_ttvn), |
641 | (tt_global_entry->flags & | ||
642 | TT_CLIENT_ROAM ? 'R' : '.'), | ||
643 | (tt_global_entry->flags & | ||
644 | TT_CLIENT_PENDING ? 'X' : '.'), | ||
645 | (tt_global_entry->flags & | ||
646 | TT_CLIENT_WIFI ? 'W' : '.')); | ||
623 | } | 647 | } |
624 | rcu_read_unlock(); | 648 | rcu_read_unlock(); |
625 | } | 649 | } |
@@ -774,30 +798,56 @@ static void tt_global_table_free(struct bat_priv *bat_priv) | |||
774 | bat_priv->tt_global_hash = NULL; | 798 | bat_priv->tt_global_hash = NULL; |
775 | } | 799 | } |
776 | 800 | ||
801 | static bool _is_ap_isolated(struct tt_local_entry *tt_local_entry, | ||
802 | struct tt_global_entry *tt_global_entry) | ||
803 | { | ||
804 | bool ret = false; | ||
805 | |||
806 | if (tt_local_entry->flags & TT_CLIENT_WIFI && | ||
807 | tt_global_entry->flags & TT_CLIENT_WIFI) | ||
808 | ret = true; | ||
809 | |||
810 | return ret; | ||
811 | } | ||
812 | |||
777 | struct orig_node *transtable_search(struct bat_priv *bat_priv, | 813 | struct orig_node *transtable_search(struct bat_priv *bat_priv, |
778 | const uint8_t *addr) | 814 | const uint8_t *src, const uint8_t *addr) |
779 | { | 815 | { |
780 | struct tt_global_entry *tt_global_entry; | 816 | struct tt_local_entry *tt_local_entry = NULL; |
817 | struct tt_global_entry *tt_global_entry = NULL; | ||
781 | struct orig_node *orig_node = NULL; | 818 | struct orig_node *orig_node = NULL; |
782 | 819 | ||
783 | tt_global_entry = tt_global_hash_find(bat_priv, addr); | 820 | if (src && atomic_read(&bat_priv->ap_isolation)) { |
821 | tt_local_entry = tt_local_hash_find(bat_priv, src); | ||
822 | if (!tt_local_entry) | ||
823 | goto out; | ||
824 | } | ||
784 | 825 | ||
826 | tt_global_entry = tt_global_hash_find(bat_priv, addr); | ||
785 | if (!tt_global_entry) | 827 | if (!tt_global_entry) |
786 | goto out; | 828 | goto out; |
787 | 829 | ||
830 | /* check whether the clients should not communicate due to AP | ||
831 | * isolation */ | ||
832 | if (tt_local_entry && _is_ap_isolated(tt_local_entry, tt_global_entry)) | ||
833 | goto out; | ||
834 | |||
788 | if (!atomic_inc_not_zero(&tt_global_entry->orig_node->refcount)) | 835 | if (!atomic_inc_not_zero(&tt_global_entry->orig_node->refcount)) |
789 | goto free_tt; | 836 | goto out; |
790 | 837 | ||
791 | /* A global client marked as PENDING has already moved from that | 838 | /* A global client marked as PENDING has already moved from that |
792 | * originator */ | 839 | * originator */ |
793 | if (tt_global_entry->flags & TT_CLIENT_PENDING) | 840 | if (tt_global_entry->flags & TT_CLIENT_PENDING) |
794 | goto free_tt; | 841 | goto out; |
795 | 842 | ||
796 | orig_node = tt_global_entry->orig_node; | 843 | orig_node = tt_global_entry->orig_node; |
797 | 844 | ||
798 | free_tt: | ||
799 | tt_global_entry_free_ref(tt_global_entry); | ||
800 | out: | 845 | out: |
846 | if (tt_global_entry) | ||
847 | tt_global_entry_free_ref(tt_global_entry); | ||
848 | if (tt_local_entry) | ||
849 | tt_local_entry_free_ref(tt_local_entry); | ||
850 | |||
801 | return orig_node; | 851 | return orig_node; |
802 | } | 852 | } |
803 | 853 | ||
@@ -1029,8 +1079,9 @@ out: | |||
1029 | return skb; | 1079 | return skb; |
1030 | } | 1080 | } |
1031 | 1081 | ||
1032 | int send_tt_request(struct bat_priv *bat_priv, struct orig_node *dst_orig_node, | 1082 | static int send_tt_request(struct bat_priv *bat_priv, |
1033 | uint8_t ttvn, uint16_t tt_crc, bool full_table) | 1083 | struct orig_node *dst_orig_node, |
1084 | uint8_t ttvn, uint16_t tt_crc, bool full_table) | ||
1034 | { | 1085 | { |
1035 | struct sk_buff *skb = NULL; | 1086 | struct sk_buff *skb = NULL; |
1036 | struct tt_query_packet *tt_request; | 1087 | struct tt_query_packet *tt_request; |
@@ -1137,12 +1188,12 @@ static bool send_other_tt_response(struct bat_priv *bat_priv, | |||
1137 | orig_ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn); | 1188 | orig_ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn); |
1138 | req_ttvn = tt_request->ttvn; | 1189 | req_ttvn = tt_request->ttvn; |
1139 | 1190 | ||
1140 | /* I have not the requested data */ | 1191 | /* I don't have the requested data */ |
1141 | if (orig_ttvn != req_ttvn || | 1192 | if (orig_ttvn != req_ttvn || |
1142 | tt_request->tt_data != req_dst_orig_node->tt_crc) | 1193 | tt_request->tt_data != req_dst_orig_node->tt_crc) |
1143 | goto out; | 1194 | goto out; |
1144 | 1195 | ||
1145 | /* If it has explicitly been requested the full table */ | 1196 | /* If the full table has been explicitly requested */ |
1146 | if (tt_request->flags & TT_FULL_TABLE || | 1197 | if (tt_request->flags & TT_FULL_TABLE || |
1147 | !req_dst_orig_node->tt_buff) | 1198 | !req_dst_orig_node->tt_buff) |
1148 | full_table = true; | 1199 | full_table = true; |
@@ -1363,7 +1414,9 @@ static void _tt_update_changes(struct bat_priv *bat_priv, | |||
1363 | (tt_change + i)->flags & TT_CLIENT_ROAM); | 1414 | (tt_change + i)->flags & TT_CLIENT_ROAM); |
1364 | else | 1415 | else |
1365 | if (!tt_global_add(bat_priv, orig_node, | 1416 | if (!tt_global_add(bat_priv, orig_node, |
1366 | (tt_change + i)->addr, ttvn, false)) | 1417 | (tt_change + i)->addr, ttvn, false, |
1418 | (tt_change + i)->flags & | ||
1419 | TT_CLIENT_WIFI)) | ||
1367 | /* In case of problem while storing a | 1420 | /* In case of problem while storing a |
1368 | * global_entry, we stop the updating | 1421 | * global_entry, we stop the updating |
1369 | * procedure without committing the | 1422 | * procedure without committing the |
@@ -1403,9 +1456,10 @@ out: | |||
1403 | orig_node_free_ref(orig_node); | 1456 | orig_node_free_ref(orig_node); |
1404 | } | 1457 | } |
1405 | 1458 | ||
1406 | void tt_update_changes(struct bat_priv *bat_priv, struct orig_node *orig_node, | 1459 | static void tt_update_changes(struct bat_priv *bat_priv, |
1407 | uint16_t tt_num_changes, uint8_t ttvn, | 1460 | struct orig_node *orig_node, |
1408 | struct tt_change *tt_change) | 1461 | uint16_t tt_num_changes, uint8_t ttvn, |
1462 | struct tt_change *tt_change) | ||
1409 | { | 1463 | { |
1410 | _tt_update_changes(bat_priv, orig_node, tt_change, tt_num_changes, | 1464 | _tt_update_changes(bat_priv, orig_node, tt_change, tt_num_changes, |
1411 | ttvn); | 1465 | ttvn); |
@@ -1720,3 +1774,90 @@ void tt_commit_changes(struct bat_priv *bat_priv) | |||
1720 | atomic_inc(&bat_priv->ttvn); | 1774 | atomic_inc(&bat_priv->ttvn); |
1721 | bat_priv->tt_poss_change = false; | 1775 | bat_priv->tt_poss_change = false; |
1722 | } | 1776 | } |
1777 | |||
1778 | bool is_ap_isolated(struct bat_priv *bat_priv, uint8_t *src, uint8_t *dst) | ||
1779 | { | ||
1780 | struct tt_local_entry *tt_local_entry = NULL; | ||
1781 | struct tt_global_entry *tt_global_entry = NULL; | ||
1782 | bool ret = true; | ||
1783 | |||
1784 | if (!atomic_read(&bat_priv->ap_isolation)) | ||
1785 | return false; | ||
1786 | |||
1787 | tt_local_entry = tt_local_hash_find(bat_priv, dst); | ||
1788 | if (!tt_local_entry) | ||
1789 | goto out; | ||
1790 | |||
1791 | tt_global_entry = tt_global_hash_find(bat_priv, src); | ||
1792 | if (!tt_global_entry) | ||
1793 | goto out; | ||
1794 | |||
1795 | if (_is_ap_isolated(tt_local_entry, tt_global_entry)) | ||
1796 | goto out; | ||
1797 | |||
1798 | ret = false; | ||
1799 | |||
1800 | out: | ||
1801 | if (tt_global_entry) | ||
1802 | tt_global_entry_free_ref(tt_global_entry); | ||
1803 | if (tt_local_entry) | ||
1804 | tt_local_entry_free_ref(tt_local_entry); | ||
1805 | return ret; | ||
1806 | } | ||
1807 | |||
1808 | void tt_update_orig(struct bat_priv *bat_priv, struct orig_node *orig_node, | ||
1809 | const unsigned char *tt_buff, uint8_t tt_num_changes, | ||
1810 | uint8_t ttvn, uint16_t tt_crc) | ||
1811 | { | ||
1812 | uint8_t orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); | ||
1813 | bool full_table = true; | ||
1814 | |||
1815 | /* the ttvn increased by one -> we can apply the attached changes */ | ||
1816 | if (ttvn - orig_ttvn == 1) { | ||
1817 | /* the OGM could not contain the changes due to their size or | ||
1818 | * because they have already been sent TT_OGM_APPEND_MAX times. | ||
1819 | * In this case send a tt request */ | ||
1820 | if (!tt_num_changes) { | ||
1821 | full_table = false; | ||
1822 | goto request_table; | ||
1823 | } | ||
1824 | |||
1825 | tt_update_changes(bat_priv, orig_node, tt_num_changes, ttvn, | ||
1826 | (struct tt_change *)tt_buff); | ||
1827 | |||
1828 | /* Even if we received the precomputed crc with the OGM, we | ||
1829 | * prefer to recompute it to spot any possible inconsistency | ||
1830 | * in the global table */ | ||
1831 | orig_node->tt_crc = tt_global_crc(bat_priv, orig_node); | ||
1832 | |||
1833 | /* The ttvn alone is not enough to guarantee consistency | ||
1834 | * because a single value could represent different states | ||
1835 | * (due to the wrap around). Thus a node has to check whether | ||
1836 | * the resulting table (after applying the changes) is still | ||
1837 | * consistent or not. E.g. a node could disconnect while its | ||
1838 | * ttvn is X and reconnect on ttvn = X + TTVN_MAX: in this case | ||
1839 | * checking the CRC value is mandatory to detect the | ||
1840 | * inconsistency */ | ||
1841 | if (orig_node->tt_crc != tt_crc) | ||
1842 | goto request_table; | ||
1843 | |||
1844 | /* Roaming phase is over: tables are in sync again. I can | ||
1845 | * unset the flag */ | ||
1846 | orig_node->tt_poss_change = false; | ||
1847 | } else { | ||
1848 | /* if we missed more than one change or our tables are not | ||
1849 | * in sync anymore -> request fresh tt data */ | ||
1850 | if (ttvn != orig_ttvn || orig_node->tt_crc != tt_crc) { | ||
1851 | request_table: | ||
1852 | bat_dbg(DBG_TT, bat_priv, "TT inconsistency for %pM. " | ||
1853 | "Need to retrieve the correct information " | ||
1854 | "(ttvn: %u last_ttvn: %u crc: %u last_crc: " | ||
1855 | "%u num_changes: %u)\n", orig_node->orig, ttvn, | ||
1856 | orig_ttvn, tt_crc, orig_node->tt_crc, | ||
1857 | tt_num_changes); | ||
1858 | send_tt_request(bat_priv, orig_node, ttvn, tt_crc, | ||
1859 | full_table); | ||
1860 | return; | ||
1861 | } | ||
1862 | } | ||
1863 | } | ||
diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h index d4122cba53b8..30efd49881a3 100644 --- a/net/batman-adv/translation-table.h +++ b/net/batman-adv/translation-table.h | |||
@@ -26,15 +26,16 @@ int tt_len(int changes_num); | |||
26 | int tt_changes_fill_buffer(struct bat_priv *bat_priv, | 26 | int tt_changes_fill_buffer(struct bat_priv *bat_priv, |
27 | unsigned char *buff, int buff_len); | 27 | unsigned char *buff, int buff_len); |
28 | int tt_init(struct bat_priv *bat_priv); | 28 | int tt_init(struct bat_priv *bat_priv); |
29 | void tt_local_add(struct net_device *soft_iface, const uint8_t *addr); | 29 | void tt_local_add(struct net_device *soft_iface, const uint8_t *addr, |
30 | int ifindex); | ||
30 | void tt_local_remove(struct bat_priv *bat_priv, | 31 | void tt_local_remove(struct bat_priv *bat_priv, |
31 | const uint8_t *addr, const char *message, bool roaming); | 32 | const uint8_t *addr, const char *message, bool roaming); |
32 | int tt_local_seq_print_text(struct seq_file *seq, void *offset); | 33 | int tt_local_seq_print_text(struct seq_file *seq, void *offset); |
33 | void tt_global_add_orig(struct bat_priv *bat_priv, struct orig_node *orig_node, | 34 | void tt_global_add_orig(struct bat_priv *bat_priv, struct orig_node *orig_node, |
34 | const unsigned char *tt_buff, int tt_buff_len); | 35 | const unsigned char *tt_buff, int tt_buff_len); |
35 | int tt_global_add(struct bat_priv *bat_priv, | 36 | int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node, |
36 | struct orig_node *orig_node, const unsigned char *addr, | 37 | const unsigned char *addr, uint8_t ttvn, bool roaming, |
37 | uint8_t ttvn, bool roaming); | 38 | bool wifi); |
38 | int tt_global_seq_print_text(struct seq_file *seq, void *offset); | 39 | int tt_global_seq_print_text(struct seq_file *seq, void *offset); |
39 | void tt_global_del_orig(struct bat_priv *bat_priv, | 40 | void tt_global_del_orig(struct bat_priv *bat_priv, |
40 | struct orig_node *orig_node, const char *message); | 41 | struct orig_node *orig_node, const char *message); |
@@ -42,25 +43,23 @@ void tt_global_del(struct bat_priv *bat_priv, | |||
42 | struct orig_node *orig_node, const unsigned char *addr, | 43 | struct orig_node *orig_node, const unsigned char *addr, |
43 | const char *message, bool roaming); | 44 | const char *message, bool roaming); |
44 | struct orig_node *transtable_search(struct bat_priv *bat_priv, | 45 | struct orig_node *transtable_search(struct bat_priv *bat_priv, |
45 | const uint8_t *addr); | 46 | const uint8_t *src, const uint8_t *addr); |
46 | void tt_save_orig_buffer(struct bat_priv *bat_priv, struct orig_node *orig_node, | 47 | void tt_save_orig_buffer(struct bat_priv *bat_priv, struct orig_node *orig_node, |
47 | const unsigned char *tt_buff, uint8_t tt_num_changes); | 48 | const unsigned char *tt_buff, uint8_t tt_num_changes); |
48 | uint16_t tt_local_crc(struct bat_priv *bat_priv); | 49 | uint16_t tt_local_crc(struct bat_priv *bat_priv); |
49 | uint16_t tt_global_crc(struct bat_priv *bat_priv, struct orig_node *orig_node); | 50 | uint16_t tt_global_crc(struct bat_priv *bat_priv, struct orig_node *orig_node); |
50 | void tt_free(struct bat_priv *bat_priv); | 51 | void tt_free(struct bat_priv *bat_priv); |
51 | int send_tt_request(struct bat_priv *bat_priv, | ||
52 | struct orig_node *dst_orig_node, uint8_t hvn, | ||
53 | uint16_t tt_crc, bool full_table); | ||
54 | bool send_tt_response(struct bat_priv *bat_priv, | 52 | bool send_tt_response(struct bat_priv *bat_priv, |
55 | struct tt_query_packet *tt_request); | 53 | struct tt_query_packet *tt_request); |
56 | void tt_update_changes(struct bat_priv *bat_priv, struct orig_node *orig_node, | ||
57 | uint16_t tt_num_changes, uint8_t ttvn, | ||
58 | struct tt_change *tt_change); | ||
59 | bool is_my_client(struct bat_priv *bat_priv, const uint8_t *addr); | 54 | bool is_my_client(struct bat_priv *bat_priv, const uint8_t *addr); |
60 | void handle_tt_response(struct bat_priv *bat_priv, | 55 | void handle_tt_response(struct bat_priv *bat_priv, |
61 | struct tt_query_packet *tt_response); | 56 | struct tt_query_packet *tt_response); |
62 | void send_roam_adv(struct bat_priv *bat_priv, uint8_t *client, | 57 | void send_roam_adv(struct bat_priv *bat_priv, uint8_t *client, |
63 | struct orig_node *orig_node); | 58 | struct orig_node *orig_node); |
64 | void tt_commit_changes(struct bat_priv *bat_priv); | 59 | void tt_commit_changes(struct bat_priv *bat_priv); |
60 | bool is_ap_isolated(struct bat_priv *bat_priv, uint8_t *src, uint8_t *dst); | ||
61 | void tt_update_orig(struct bat_priv *bat_priv, struct orig_node *orig_node, | ||
62 | const unsigned char *tt_buff, uint8_t tt_num_changes, | ||
63 | uint8_t ttvn, uint16_t tt_crc); | ||
65 | 64 | ||
66 | #endif /* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */ | 65 | #endif /* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */ |
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 25bd1db35370..1ae355750511 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h | |||
@@ -57,7 +57,7 @@ struct hard_iface { | |||
57 | * @batman_seqno_reset: time when the batman seqno window was reset | 57 | * @batman_seqno_reset: time when the batman seqno window was reset |
58 | * @gw_flags: flags related to gateway class | 58 | * @gw_flags: flags related to gateway class |
59 | * @flags: for now only VIS_SERVER flag | 59 | * @flags: for now only VIS_SERVER flag |
60 | * @last_real_seqno: last and best known squence number | 60 | * @last_real_seqno: last and best known sequence number |
61 | * @last_ttl: ttl of last received packet | 61 | * @last_ttl: ttl of last received packet |
62 | * @last_bcast_seqno: last broadcast sequence number received by this host | 62 | * @last_bcast_seqno: last broadcast sequence number received by this host |
63 | * | 63 | * |
@@ -146,6 +146,7 @@ struct bat_priv { | |||
146 | atomic_t aggregated_ogms; /* boolean */ | 146 | atomic_t aggregated_ogms; /* boolean */ |
147 | atomic_t bonding; /* boolean */ | 147 | atomic_t bonding; /* boolean */ |
148 | atomic_t fragmentation; /* boolean */ | 148 | atomic_t fragmentation; /* boolean */ |
149 | atomic_t ap_isolation; /* boolean */ | ||
149 | atomic_t vis_mode; /* VIS_TYPE_* */ | 150 | atomic_t vis_mode; /* VIS_TYPE_* */ |
150 | atomic_t gw_mode; /* GW_MODE_* */ | 151 | atomic_t gw_mode; /* GW_MODE_* */ |
151 | atomic_t gw_sel_class; /* uint */ | 152 | atomic_t gw_sel_class; /* uint */ |
@@ -156,7 +157,7 @@ struct bat_priv { | |||
156 | atomic_t bcast_seqno; | 157 | atomic_t bcast_seqno; |
157 | atomic_t bcast_queue_left; | 158 | atomic_t bcast_queue_left; |
158 | atomic_t batman_queue_left; | 159 | atomic_t batman_queue_left; |
159 | atomic_t ttvn; /* tranlation table version number */ | 160 | atomic_t ttvn; /* translation table version number */ |
160 | atomic_t tt_ogm_append_cnt; | 161 | atomic_t tt_ogm_append_cnt; |
161 | atomic_t tt_local_changes; /* changes registered in a OGM interval */ | 162 | atomic_t tt_local_changes; /* changes registered in a OGM interval */ |
162 | /* The tt_poss_change flag is used to detect an ongoing roaming phase. | 163 | /* The tt_poss_change flag is used to detect an ongoing roaming phase. |
diff --git a/net/batman-adv/unicast.c b/net/batman-adv/unicast.c index 32b125fb3d3b..07d1c1da89dd 100644 --- a/net/batman-adv/unicast.c +++ b/net/batman-adv/unicast.c | |||
@@ -299,8 +299,10 @@ int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv) | |||
299 | goto find_router; | 299 | goto find_router; |
300 | } | 300 | } |
301 | 301 | ||
302 | /* check for tt host - increases orig_node refcount */ | 302 | /* check for tt host - increases orig_node refcount. |
303 | orig_node = transtable_search(bat_priv, ethhdr->h_dest); | 303 | * returns NULL in case of AP isolation */ |
304 | orig_node = transtable_search(bat_priv, ethhdr->h_source, | ||
305 | ethhdr->h_dest); | ||
304 | 306 | ||
305 | find_router: | 307 | find_router: |
306 | /** | 308 | /** |
diff --git a/net/batman-adv/unicast.h b/net/batman-adv/unicast.h index 62f54b954625..8fd5535544b9 100644 --- a/net/batman-adv/unicast.h +++ b/net/batman-adv/unicast.h | |||
@@ -24,7 +24,7 @@ | |||
24 | 24 | ||
25 | #include "packet.h" | 25 | #include "packet.h" |
26 | 26 | ||
27 | #define FRAG_TIMEOUT 10000 /* purge frag list entrys after time in ms */ | 27 | #define FRAG_TIMEOUT 10000 /* purge frag list entries after time in ms */ |
28 | #define FRAG_BUFFER_SIZE 6 /* number of list elements in buffer */ | 28 | #define FRAG_BUFFER_SIZE 6 /* number of list elements in buffer */ |
29 | 29 | ||
30 | int frag_reassemble_skb(struct sk_buff *skb, struct bat_priv *bat_priv, | 30 | int frag_reassemble_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 8a1b98589d76..fb9b19fc638d 100644 --- a/net/batman-adv/vis.c +++ b/net/batman-adv/vis.c | |||
@@ -131,7 +131,7 @@ static void vis_data_insert_interface(const uint8_t *interface, | |||
131 | return; | 131 | return; |
132 | } | 132 | } |
133 | 133 | ||
134 | /* its a new address, add it to the list */ | 134 | /* it's a new address, add it to the list */ |
135 | entry = kmalloc(sizeof(*entry), GFP_ATOMIC); | 135 | entry = kmalloc(sizeof(*entry), GFP_ATOMIC); |
136 | if (!entry) | 136 | if (!entry) |
137 | return; | 137 | return; |
@@ -465,7 +465,7 @@ static struct vis_info *add_packet(struct bat_priv *bat_priv, | |||
465 | /* try to add it */ | 465 | /* try to add it */ |
466 | hash_added = hash_add(bat_priv->vis_hash, vis_info_cmp, vis_info_choose, | 466 | hash_added = hash_add(bat_priv->vis_hash, vis_info_cmp, vis_info_choose, |
467 | info, &info->hash_entry); | 467 | info, &info->hash_entry); |
468 | if (hash_added < 0) { | 468 | if (hash_added != 0) { |
469 | /* did not work (for some reason) */ | 469 | /* did not work (for some reason) */ |
470 | kref_put(&info->refcount, free_info); | 470 | kref_put(&info->refcount, free_info); |
471 | info = NULL; | 471 | info = NULL; |
@@ -920,7 +920,7 @@ int vis_init(struct bat_priv *bat_priv) | |||
920 | hash_added = hash_add(bat_priv->vis_hash, vis_info_cmp, vis_info_choose, | 920 | hash_added = hash_add(bat_priv->vis_hash, vis_info_cmp, vis_info_choose, |
921 | bat_priv->my_vis_info, | 921 | bat_priv->my_vis_info, |
922 | &bat_priv->my_vis_info->hash_entry); | 922 | &bat_priv->my_vis_info->hash_entry); |
923 | if (hash_added < 0) { | 923 | if (hash_added != 0) { |
924 | pr_err("Can't add own vis packet into hash\n"); | 924 | pr_err("Can't add own vis packet into hash\n"); |
925 | /* not in hash, need to remove it manually. */ | 925 | /* not in hash, need to remove it manually. */ |
926 | kref_put(&bat_priv->my_vis_info->refcount, free_info); | 926 | kref_put(&bat_priv->my_vis_info->refcount, free_info); |