diff options
Diffstat (limited to 'net/batman-adv')
-rw-r--r-- | net/batman-adv/aggregation.c | 31 | ||||
-rw-r--r-- | net/batman-adv/aggregation.h | 4 | ||||
-rw-r--r-- | net/batman-adv/bat_debugfs.c | 4 | ||||
-rw-r--r-- | net/batman-adv/bat_sysfs.c | 16 | ||||
-rw-r--r-- | net/batman-adv/gateway_client.c | 306 | ||||
-rw-r--r-- | net/batman-adv/gateway_client.h | 2 | ||||
-rw-r--r-- | net/batman-adv/hard-interface.c | 107 | ||||
-rw-r--r-- | net/batman-adv/hard-interface.h | 18 | ||||
-rw-r--r-- | net/batman-adv/icmp_socket.c | 37 | ||||
-rw-r--r-- | net/batman-adv/main.c | 20 | ||||
-rw-r--r-- | net/batman-adv/main.h | 44 | ||||
-rw-r--r-- | net/batman-adv/originator.c | 90 | ||||
-rw-r--r-- | net/batman-adv/originator.h | 1 | ||||
-rw-r--r-- | net/batman-adv/packet.h | 5 | ||||
-rw-r--r-- | net/batman-adv/routing.c | 572 | ||||
-rw-r--r-- | net/batman-adv/routing.h | 6 | ||||
-rw-r--r-- | net/batman-adv/send.c | 72 | ||||
-rw-r--r-- | net/batman-adv/send.h | 2 | ||||
-rw-r--r-- | net/batman-adv/soft-interface.c | 473 | ||||
-rw-r--r-- | net/batman-adv/translation-table.c | 474 | ||||
-rw-r--r-- | net/batman-adv/translation-table.h | 24 | ||||
-rw-r--r-- | net/batman-adv/types.h | 56 | ||||
-rw-r--r-- | net/batman-adv/unicast.c | 20 | ||||
-rw-r--r-- | net/batman-adv/vis.c | 146 |
24 files changed, 1483 insertions, 1047 deletions
diff --git a/net/batman-adv/aggregation.c b/net/batman-adv/aggregation.c index af45d6b2031f..a8c32030527c 100644 --- a/net/batman-adv/aggregation.c +++ b/net/batman-adv/aggregation.c | |||
@@ -23,11 +23,12 @@ | |||
23 | #include "aggregation.h" | 23 | #include "aggregation.h" |
24 | #include "send.h" | 24 | #include "send.h" |
25 | #include "routing.h" | 25 | #include "routing.h" |
26 | #include "hard-interface.h" | ||
26 | 27 | ||
27 | /* calculate the size of the hna information for a given packet */ | 28 | /* calculate the size of the tt information for a given packet */ |
28 | static int hna_len(struct batman_packet *batman_packet) | 29 | static int tt_len(struct batman_packet *batman_packet) |
29 | { | 30 | { |
30 | return batman_packet->num_hna * ETH_ALEN; | 31 | return batman_packet->num_tt * ETH_ALEN; |
31 | } | 32 | } |
32 | 33 | ||
33 | /* return true if new_packet can be aggregated with forw_packet */ | 34 | /* return true if new_packet can be aggregated with forw_packet */ |
@@ -95,7 +96,6 @@ static bool can_aggregate_with(struct batman_packet *new_batman_packet, | |||
95 | return false; | 96 | return false; |
96 | } | 97 | } |
97 | 98 | ||
98 | #define atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0) | ||
99 | /* create a new aggregated packet and add this packet to it */ | 99 | /* create a new aggregated packet and add this packet to it */ |
100 | static void new_aggregated_packet(unsigned char *packet_buff, int packet_len, | 100 | static void new_aggregated_packet(unsigned char *packet_buff, int packet_len, |
101 | unsigned long send_time, bool direct_link, | 101 | unsigned long send_time, bool direct_link, |
@@ -106,12 +106,15 @@ static void new_aggregated_packet(unsigned char *packet_buff, int packet_len, | |||
106 | struct forw_packet *forw_packet_aggr; | 106 | struct forw_packet *forw_packet_aggr; |
107 | unsigned char *skb_buff; | 107 | unsigned char *skb_buff; |
108 | 108 | ||
109 | if (!atomic_inc_not_zero(&if_incoming->refcount)) | ||
110 | return; | ||
111 | |||
109 | /* own packet should always be scheduled */ | 112 | /* own packet should always be scheduled */ |
110 | if (!own_packet) { | 113 | if (!own_packet) { |
111 | if (!atomic_dec_not_zero(&bat_priv->batman_queue_left)) { | 114 | if (!atomic_dec_not_zero(&bat_priv->batman_queue_left)) { |
112 | bat_dbg(DBG_BATMAN, bat_priv, | 115 | bat_dbg(DBG_BATMAN, bat_priv, |
113 | "batman packet queue full\n"); | 116 | "batman packet queue full\n"); |
114 | return; | 117 | goto out; |
115 | } | 118 | } |
116 | } | 119 | } |
117 | 120 | ||
@@ -119,7 +122,7 @@ static void new_aggregated_packet(unsigned char *packet_buff, int packet_len, | |||
119 | if (!forw_packet_aggr) { | 122 | if (!forw_packet_aggr) { |
120 | if (!own_packet) | 123 | if (!own_packet) |
121 | atomic_inc(&bat_priv->batman_queue_left); | 124 | atomic_inc(&bat_priv->batman_queue_left); |
122 | return; | 125 | goto out; |
123 | } | 126 | } |
124 | 127 | ||
125 | if ((atomic_read(&bat_priv->aggregated_ogms)) && | 128 | if ((atomic_read(&bat_priv->aggregated_ogms)) && |
@@ -134,7 +137,7 @@ static void new_aggregated_packet(unsigned char *packet_buff, int packet_len, | |||
134 | if (!own_packet) | 137 | if (!own_packet) |
135 | atomic_inc(&bat_priv->batman_queue_left); | 138 | atomic_inc(&bat_priv->batman_queue_left); |
136 | kfree(forw_packet_aggr); | 139 | kfree(forw_packet_aggr); |
137 | return; | 140 | goto out; |
138 | } | 141 | } |
139 | skb_reserve(forw_packet_aggr->skb, sizeof(struct ethhdr)); | 142 | skb_reserve(forw_packet_aggr->skb, sizeof(struct ethhdr)); |
140 | 143 | ||
@@ -165,6 +168,10 @@ static void new_aggregated_packet(unsigned char *packet_buff, int packet_len, | |||
165 | queue_delayed_work(bat_event_workqueue, | 168 | queue_delayed_work(bat_event_workqueue, |
166 | &forw_packet_aggr->delayed_work, | 169 | &forw_packet_aggr->delayed_work, |
167 | send_time - jiffies); | 170 | send_time - jiffies); |
171 | |||
172 | return; | ||
173 | out: | ||
174 | hardif_free_ref(if_incoming); | ||
168 | } | 175 | } |
169 | 176 | ||
170 | /* aggregate a new packet into the existing aggregation */ | 177 | /* aggregate a new packet into the existing aggregation */ |
@@ -251,7 +258,7 @@ void receive_aggr_bat_packet(struct ethhdr *ethhdr, unsigned char *packet_buff, | |||
251 | { | 258 | { |
252 | struct batman_packet *batman_packet; | 259 | struct batman_packet *batman_packet; |
253 | int buff_pos = 0; | 260 | int buff_pos = 0; |
254 | unsigned char *hna_buff; | 261 | unsigned char *tt_buff; |
255 | 262 | ||
256 | batman_packet = (struct batman_packet *)packet_buff; | 263 | batman_packet = (struct batman_packet *)packet_buff; |
257 | 264 | ||
@@ -260,14 +267,14 @@ void receive_aggr_bat_packet(struct ethhdr *ethhdr, unsigned char *packet_buff, | |||
260 | orig_interval. */ | 267 | orig_interval. */ |
261 | batman_packet->seqno = ntohl(batman_packet->seqno); | 268 | batman_packet->seqno = ntohl(batman_packet->seqno); |
262 | 269 | ||
263 | hna_buff = packet_buff + buff_pos + BAT_PACKET_LEN; | 270 | tt_buff = packet_buff + buff_pos + BAT_PACKET_LEN; |
264 | receive_bat_packet(ethhdr, batman_packet, | 271 | receive_bat_packet(ethhdr, batman_packet, |
265 | hna_buff, hna_len(batman_packet), | 272 | tt_buff, tt_len(batman_packet), |
266 | if_incoming); | 273 | if_incoming); |
267 | 274 | ||
268 | buff_pos += BAT_PACKET_LEN + hna_len(batman_packet); | 275 | buff_pos += BAT_PACKET_LEN + tt_len(batman_packet); |
269 | batman_packet = (struct batman_packet *) | 276 | batman_packet = (struct batman_packet *) |
270 | (packet_buff + buff_pos); | 277 | (packet_buff + buff_pos); |
271 | } while (aggregated_packet(buff_pos, packet_len, | 278 | } while (aggregated_packet(buff_pos, packet_len, |
272 | batman_packet->num_hna)); | 279 | batman_packet->num_tt)); |
273 | } | 280 | } |
diff --git a/net/batman-adv/aggregation.h b/net/batman-adv/aggregation.h index 062204289d1f..7e6d72fbf540 100644 --- a/net/batman-adv/aggregation.h +++ b/net/batman-adv/aggregation.h | |||
@@ -25,9 +25,9 @@ | |||
25 | #include "main.h" | 25 | #include "main.h" |
26 | 26 | ||
27 | /* is there another aggregated packet here? */ | 27 | /* is there another aggregated packet here? */ |
28 | static inline int aggregated_packet(int buff_pos, int packet_len, int num_hna) | 28 | static inline int aggregated_packet(int buff_pos, int packet_len, int num_tt) |
29 | { | 29 | { |
30 | int next_buff_pos = buff_pos + BAT_PACKET_LEN + (num_hna * ETH_ALEN); | 30 | int next_buff_pos = buff_pos + BAT_PACKET_LEN + (num_tt * ETH_ALEN); |
31 | 31 | ||
32 | return (next_buff_pos <= packet_len) && | 32 | return (next_buff_pos <= packet_len) && |
33 | (next_buff_pos <= MAX_AGGREGATION_BYTES); | 33 | (next_buff_pos <= MAX_AGGREGATION_BYTES); |
diff --git a/net/batman-adv/bat_debugfs.c b/net/batman-adv/bat_debugfs.c index 0e9d43509935..abaeec5f6247 100644 --- a/net/batman-adv/bat_debugfs.c +++ b/net/batman-adv/bat_debugfs.c | |||
@@ -241,13 +241,13 @@ static int softif_neigh_open(struct inode *inode, struct file *file) | |||
241 | static int transtable_global_open(struct inode *inode, struct file *file) | 241 | static int transtable_global_open(struct inode *inode, struct file *file) |
242 | { | 242 | { |
243 | struct net_device *net_dev = (struct net_device *)inode->i_private; | 243 | struct net_device *net_dev = (struct net_device *)inode->i_private; |
244 | return single_open(file, hna_global_seq_print_text, net_dev); | 244 | return single_open(file, tt_global_seq_print_text, net_dev); |
245 | } | 245 | } |
246 | 246 | ||
247 | static int transtable_local_open(struct inode *inode, struct file *file) | 247 | static int transtable_local_open(struct inode *inode, struct file *file) |
248 | { | 248 | { |
249 | struct net_device *net_dev = (struct net_device *)inode->i_private; | 249 | struct net_device *net_dev = (struct net_device *)inode->i_private; |
250 | return single_open(file, hna_local_seq_print_text, net_dev); | 250 | return single_open(file, tt_local_seq_print_text, net_dev); |
251 | } | 251 | } |
252 | 252 | ||
253 | static int vis_data_open(struct inode *inode, struct file *file) | 253 | static int vis_data_open(struct inode *inode, struct file *file) |
diff --git a/net/batman-adv/bat_sysfs.c b/net/batman-adv/bat_sysfs.c index e449bf6353e0..497a0700cc3c 100644 --- a/net/batman-adv/bat_sysfs.c +++ b/net/batman-adv/bat_sysfs.c | |||
@@ -488,22 +488,24 @@ static ssize_t store_mesh_iface(struct kobject *kobj, struct attribute *attr, | |||
488 | (strncmp(hard_iface->soft_iface->name, buff, IFNAMSIZ) == 0)) | 488 | (strncmp(hard_iface->soft_iface->name, buff, IFNAMSIZ) == 0)) |
489 | goto out; | 489 | goto out; |
490 | 490 | ||
491 | if (!rtnl_trylock()) { | ||
492 | ret = -ERESTARTSYS; | ||
493 | goto out; | ||
494 | } | ||
495 | |||
491 | if (status_tmp == IF_NOT_IN_USE) { | 496 | if (status_tmp == IF_NOT_IN_USE) { |
492 | rtnl_lock(); | ||
493 | hardif_disable_interface(hard_iface); | 497 | hardif_disable_interface(hard_iface); |
494 | rtnl_unlock(); | 498 | goto unlock; |
495 | goto out; | ||
496 | } | 499 | } |
497 | 500 | ||
498 | /* if the interface already is in use */ | 501 | /* if the interface already is in use */ |
499 | if (hard_iface->if_status != IF_NOT_IN_USE) { | 502 | if (hard_iface->if_status != IF_NOT_IN_USE) |
500 | rtnl_lock(); | ||
501 | hardif_disable_interface(hard_iface); | 503 | hardif_disable_interface(hard_iface); |
502 | rtnl_unlock(); | ||
503 | } | ||
504 | 504 | ||
505 | ret = hardif_enable_interface(hard_iface, buff); | 505 | ret = hardif_enable_interface(hard_iface, buff); |
506 | 506 | ||
507 | unlock: | ||
508 | rtnl_unlock(); | ||
507 | out: | 509 | out: |
508 | hardif_free_ref(hard_iface); | 510 | hardif_free_ref(hard_iface); |
509 | return ret; | 511 | return ret; |
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index 3cc43558cf9c..61605a0f3f39 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c | |||
@@ -23,80 +23,88 @@ | |||
23 | #include "gateway_client.h" | 23 | #include "gateway_client.h" |
24 | #include "gateway_common.h" | 24 | #include "gateway_common.h" |
25 | #include "hard-interface.h" | 25 | #include "hard-interface.h" |
26 | #include "originator.h" | ||
26 | #include <linux/ip.h> | 27 | #include <linux/ip.h> |
27 | #include <linux/ipv6.h> | 28 | #include <linux/ipv6.h> |
28 | #include <linux/udp.h> | 29 | #include <linux/udp.h> |
29 | #include <linux/if_vlan.h> | 30 | #include <linux/if_vlan.h> |
30 | 31 | ||
31 | static void gw_node_free_rcu(struct rcu_head *rcu) | ||
32 | { | ||
33 | struct gw_node *gw_node; | ||
34 | |||
35 | gw_node = container_of(rcu, struct gw_node, rcu); | ||
36 | kfree(gw_node); | ||
37 | } | ||
38 | |||
39 | static void gw_node_free_ref(struct gw_node *gw_node) | 32 | static void gw_node_free_ref(struct gw_node *gw_node) |
40 | { | 33 | { |
41 | if (atomic_dec_and_test(&gw_node->refcount)) | 34 | if (atomic_dec_and_test(&gw_node->refcount)) |
42 | call_rcu(&gw_node->rcu, gw_node_free_rcu); | 35 | kfree_rcu(gw_node, rcu); |
43 | } | 36 | } |
44 | 37 | ||
45 | void *gw_get_selected(struct bat_priv *bat_priv) | 38 | static struct gw_node *gw_get_selected_gw_node(struct bat_priv *bat_priv) |
46 | { | 39 | { |
47 | struct gw_node *curr_gateway_tmp; | 40 | struct gw_node *gw_node; |
48 | struct orig_node *orig_node = NULL; | ||
49 | 41 | ||
50 | rcu_read_lock(); | 42 | rcu_read_lock(); |
51 | curr_gateway_tmp = rcu_dereference(bat_priv->curr_gw); | 43 | gw_node = rcu_dereference(bat_priv->curr_gw); |
52 | if (!curr_gateway_tmp) | 44 | if (!gw_node) |
53 | goto out; | 45 | goto out; |
54 | 46 | ||
55 | orig_node = curr_gateway_tmp->orig_node; | 47 | if (!atomic_inc_not_zero(&gw_node->refcount)) |
56 | if (!orig_node) | 48 | gw_node = NULL; |
57 | goto out; | ||
58 | |||
59 | if (!atomic_inc_not_zero(&orig_node->refcount)) | ||
60 | orig_node = NULL; | ||
61 | 49 | ||
62 | out: | 50 | out: |
63 | rcu_read_unlock(); | 51 | rcu_read_unlock(); |
64 | return orig_node; | 52 | return gw_node; |
65 | } | 53 | } |
66 | 54 | ||
67 | void gw_deselect(struct bat_priv *bat_priv) | 55 | struct orig_node *gw_get_selected_orig(struct bat_priv *bat_priv) |
68 | { | 56 | { |
69 | struct gw_node *gw_node; | 57 | struct gw_node *gw_node; |
58 | struct orig_node *orig_node = NULL; | ||
70 | 59 | ||
71 | spin_lock_bh(&bat_priv->gw_list_lock); | 60 | gw_node = gw_get_selected_gw_node(bat_priv); |
72 | gw_node = rcu_dereference(bat_priv->curr_gw); | 61 | if (!gw_node) |
73 | rcu_assign_pointer(bat_priv->curr_gw, NULL); | 62 | goto out; |
74 | spin_unlock_bh(&bat_priv->gw_list_lock); | 63 | |
64 | rcu_read_lock(); | ||
65 | orig_node = gw_node->orig_node; | ||
66 | if (!orig_node) | ||
67 | goto unlock; | ||
75 | 68 | ||
69 | if (!atomic_inc_not_zero(&orig_node->refcount)) | ||
70 | orig_node = NULL; | ||
71 | |||
72 | unlock: | ||
73 | rcu_read_unlock(); | ||
74 | out: | ||
76 | if (gw_node) | 75 | if (gw_node) |
77 | gw_node_free_ref(gw_node); | 76 | gw_node_free_ref(gw_node); |
77 | return orig_node; | ||
78 | } | 78 | } |
79 | 79 | ||
80 | static void gw_select(struct bat_priv *bat_priv, struct gw_node *new_gw_node) | 80 | static void gw_select(struct bat_priv *bat_priv, struct gw_node *new_gw_node) |
81 | { | 81 | { |
82 | struct gw_node *curr_gw_node; | 82 | struct gw_node *curr_gw_node; |
83 | 83 | ||
84 | spin_lock_bh(&bat_priv->gw_list_lock); | ||
85 | |||
84 | if (new_gw_node && !atomic_inc_not_zero(&new_gw_node->refcount)) | 86 | if (new_gw_node && !atomic_inc_not_zero(&new_gw_node->refcount)) |
85 | new_gw_node = NULL; | 87 | new_gw_node = NULL; |
86 | 88 | ||
87 | spin_lock_bh(&bat_priv->gw_list_lock); | 89 | curr_gw_node = bat_priv->curr_gw; |
88 | curr_gw_node = rcu_dereference(bat_priv->curr_gw); | ||
89 | rcu_assign_pointer(bat_priv->curr_gw, new_gw_node); | 90 | rcu_assign_pointer(bat_priv->curr_gw, new_gw_node); |
90 | spin_unlock_bh(&bat_priv->gw_list_lock); | ||
91 | 91 | ||
92 | if (curr_gw_node) | 92 | if (curr_gw_node) |
93 | gw_node_free_ref(curr_gw_node); | 93 | gw_node_free_ref(curr_gw_node); |
94 | |||
95 | spin_unlock_bh(&bat_priv->gw_list_lock); | ||
96 | } | ||
97 | |||
98 | void gw_deselect(struct bat_priv *bat_priv) | ||
99 | { | ||
100 | gw_select(bat_priv, NULL); | ||
94 | } | 101 | } |
95 | 102 | ||
96 | void gw_election(struct bat_priv *bat_priv) | 103 | void gw_election(struct bat_priv *bat_priv) |
97 | { | 104 | { |
98 | struct hlist_node *node; | 105 | struct hlist_node *node; |
99 | struct gw_node *gw_node, *curr_gw, *curr_gw_tmp = NULL; | 106 | struct gw_node *gw_node, *curr_gw = NULL, *curr_gw_tmp = NULL; |
107 | struct neigh_node *router; | ||
100 | uint8_t max_tq = 0; | 108 | uint8_t max_tq = 0; |
101 | uint32_t max_gw_factor = 0, tmp_gw_factor = 0; | 109 | uint32_t max_gw_factor = 0, tmp_gw_factor = 0; |
102 | int down, up; | 110 | int down, up; |
@@ -110,32 +118,25 @@ void gw_election(struct bat_priv *bat_priv) | |||
110 | if (atomic_read(&bat_priv->gw_mode) != GW_MODE_CLIENT) | 118 | if (atomic_read(&bat_priv->gw_mode) != GW_MODE_CLIENT) |
111 | return; | 119 | return; |
112 | 120 | ||
113 | rcu_read_lock(); | 121 | curr_gw = gw_get_selected_gw_node(bat_priv); |
114 | curr_gw = rcu_dereference(bat_priv->curr_gw); | 122 | if (curr_gw) |
115 | if (curr_gw) { | 123 | goto out; |
116 | rcu_read_unlock(); | ||
117 | return; | ||
118 | } | ||
119 | 124 | ||
125 | rcu_read_lock(); | ||
120 | if (hlist_empty(&bat_priv->gw_list)) { | 126 | if (hlist_empty(&bat_priv->gw_list)) { |
121 | 127 | bat_dbg(DBG_BATMAN, bat_priv, | |
122 | if (curr_gw) { | 128 | "Removing selected gateway - " |
123 | rcu_read_unlock(); | 129 | "no gateway in range\n"); |
124 | bat_dbg(DBG_BATMAN, bat_priv, | 130 | gw_deselect(bat_priv); |
125 | "Removing selected gateway - " | 131 | goto unlock; |
126 | "no gateway in range\n"); | ||
127 | gw_deselect(bat_priv); | ||
128 | } else | ||
129 | rcu_read_unlock(); | ||
130 | |||
131 | return; | ||
132 | } | 132 | } |
133 | 133 | ||
134 | hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) { | 134 | hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) { |
135 | if (!gw_node->orig_node->router) | 135 | if (gw_node->deleted) |
136 | continue; | 136 | continue; |
137 | 137 | ||
138 | if (gw_node->deleted) | 138 | router = orig_node_get_router(gw_node->orig_node); |
139 | if (!router) | ||
139 | continue; | 140 | continue; |
140 | 141 | ||
141 | switch (atomic_read(&bat_priv->gw_sel_class)) { | 142 | switch (atomic_read(&bat_priv->gw_sel_class)) { |
@@ -143,15 +144,14 @@ void gw_election(struct bat_priv *bat_priv) | |||
143 | gw_bandwidth_to_kbit(gw_node->orig_node->gw_flags, | 144 | gw_bandwidth_to_kbit(gw_node->orig_node->gw_flags, |
144 | &down, &up); | 145 | &down, &up); |
145 | 146 | ||
146 | tmp_gw_factor = (gw_node->orig_node->router->tq_avg * | 147 | tmp_gw_factor = (router->tq_avg * router->tq_avg * |
147 | gw_node->orig_node->router->tq_avg * | ||
148 | down * 100 * 100) / | 148 | down * 100 * 100) / |
149 | (TQ_LOCAL_WINDOW_SIZE * | 149 | (TQ_LOCAL_WINDOW_SIZE * |
150 | TQ_LOCAL_WINDOW_SIZE * 64); | 150 | TQ_LOCAL_WINDOW_SIZE * 64); |
151 | 151 | ||
152 | if ((tmp_gw_factor > max_gw_factor) || | 152 | if ((tmp_gw_factor > max_gw_factor) || |
153 | ((tmp_gw_factor == max_gw_factor) && | 153 | ((tmp_gw_factor == max_gw_factor) && |
154 | (gw_node->orig_node->router->tq_avg > max_tq))) | 154 | (router->tq_avg > max_tq))) |
155 | curr_gw_tmp = gw_node; | 155 | curr_gw_tmp = gw_node; |
156 | break; | 156 | break; |
157 | 157 | ||
@@ -163,19 +163,25 @@ void gw_election(struct bat_priv *bat_priv) | |||
163 | * soon as a better gateway appears which has | 163 | * soon as a better gateway appears which has |
164 | * $routing_class more tq points) | 164 | * $routing_class more tq points) |
165 | **/ | 165 | **/ |
166 | if (gw_node->orig_node->router->tq_avg > max_tq) | 166 | if (router->tq_avg > max_tq) |
167 | curr_gw_tmp = gw_node; | 167 | curr_gw_tmp = gw_node; |
168 | break; | 168 | break; |
169 | } | 169 | } |
170 | 170 | ||
171 | if (gw_node->orig_node->router->tq_avg > max_tq) | 171 | if (router->tq_avg > max_tq) |
172 | max_tq = gw_node->orig_node->router->tq_avg; | 172 | max_tq = router->tq_avg; |
173 | 173 | ||
174 | if (tmp_gw_factor > max_gw_factor) | 174 | if (tmp_gw_factor > max_gw_factor) |
175 | max_gw_factor = tmp_gw_factor; | 175 | max_gw_factor = tmp_gw_factor; |
176 | |||
177 | neigh_node_free_ref(router); | ||
176 | } | 178 | } |
177 | 179 | ||
178 | if (curr_gw != curr_gw_tmp) { | 180 | if (curr_gw != curr_gw_tmp) { |
181 | router = orig_node_get_router(curr_gw_tmp->orig_node); | ||
182 | if (!router) | ||
183 | goto unlock; | ||
184 | |||
179 | if ((curr_gw) && (!curr_gw_tmp)) | 185 | if ((curr_gw) && (!curr_gw_tmp)) |
180 | bat_dbg(DBG_BATMAN, bat_priv, | 186 | bat_dbg(DBG_BATMAN, bat_priv, |
181 | "Removing selected gateway - " | 187 | "Removing selected gateway - " |
@@ -186,48 +192,50 @@ void gw_election(struct bat_priv *bat_priv) | |||
186 | "(gw_flags: %i, tq: %i)\n", | 192 | "(gw_flags: %i, tq: %i)\n", |
187 | curr_gw_tmp->orig_node->orig, | 193 | curr_gw_tmp->orig_node->orig, |
188 | curr_gw_tmp->orig_node->gw_flags, | 194 | curr_gw_tmp->orig_node->gw_flags, |
189 | curr_gw_tmp->orig_node->router->tq_avg); | 195 | router->tq_avg); |
190 | else | 196 | else |
191 | bat_dbg(DBG_BATMAN, bat_priv, | 197 | bat_dbg(DBG_BATMAN, bat_priv, |
192 | "Changing route to gateway %pM " | 198 | "Changing route to gateway %pM " |
193 | "(gw_flags: %i, tq: %i)\n", | 199 | "(gw_flags: %i, tq: %i)\n", |
194 | curr_gw_tmp->orig_node->orig, | 200 | curr_gw_tmp->orig_node->orig, |
195 | curr_gw_tmp->orig_node->gw_flags, | 201 | curr_gw_tmp->orig_node->gw_flags, |
196 | curr_gw_tmp->orig_node->router->tq_avg); | 202 | router->tq_avg); |
197 | 203 | ||
204 | neigh_node_free_ref(router); | ||
198 | gw_select(bat_priv, curr_gw_tmp); | 205 | gw_select(bat_priv, curr_gw_tmp); |
199 | } | 206 | } |
200 | 207 | ||
208 | unlock: | ||
201 | rcu_read_unlock(); | 209 | rcu_read_unlock(); |
210 | out: | ||
211 | if (curr_gw) | ||
212 | gw_node_free_ref(curr_gw); | ||
202 | } | 213 | } |
203 | 214 | ||
204 | void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node) | 215 | void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node) |
205 | { | 216 | { |
206 | struct gw_node *curr_gateway_tmp; | 217 | struct orig_node *curr_gw_orig; |
218 | struct neigh_node *router_gw = NULL, *router_orig = NULL; | ||
207 | uint8_t gw_tq_avg, orig_tq_avg; | 219 | uint8_t gw_tq_avg, orig_tq_avg; |
208 | 220 | ||
209 | rcu_read_lock(); | 221 | curr_gw_orig = gw_get_selected_orig(bat_priv); |
210 | curr_gateway_tmp = rcu_dereference(bat_priv->curr_gw); | 222 | if (!curr_gw_orig) |
211 | if (!curr_gateway_tmp) | 223 | goto deselect; |
212 | goto out_rcu; | ||
213 | |||
214 | if (!curr_gateway_tmp->orig_node) | ||
215 | goto deselect_rcu; | ||
216 | 224 | ||
217 | if (!curr_gateway_tmp->orig_node->router) | 225 | router_gw = orig_node_get_router(curr_gw_orig); |
218 | goto deselect_rcu; | 226 | if (!router_gw) |
227 | goto deselect; | ||
219 | 228 | ||
220 | /* this node already is the gateway */ | 229 | /* this node already is the gateway */ |
221 | if (curr_gateway_tmp->orig_node == orig_node) | 230 | if (curr_gw_orig == orig_node) |
222 | goto out_rcu; | 231 | goto out; |
223 | |||
224 | if (!orig_node->router) | ||
225 | goto out_rcu; | ||
226 | 232 | ||
227 | gw_tq_avg = curr_gateway_tmp->orig_node->router->tq_avg; | 233 | router_orig = orig_node_get_router(orig_node); |
228 | rcu_read_unlock(); | 234 | if (!router_orig) |
235 | goto out; | ||
229 | 236 | ||
230 | orig_tq_avg = orig_node->router->tq_avg; | 237 | gw_tq_avg = router_gw->tq_avg; |
238 | orig_tq_avg = router_orig->tq_avg; | ||
231 | 239 | ||
232 | /* the TQ value has to be better */ | 240 | /* the TQ value has to be better */ |
233 | if (orig_tq_avg < gw_tq_avg) | 241 | if (orig_tq_avg < gw_tq_avg) |
@@ -245,16 +253,17 @@ void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node) | |||
245 | "Restarting gateway selection: better gateway found (tq curr: " | 253 | "Restarting gateway selection: better gateway found (tq curr: " |
246 | "%i, tq new: %i)\n", | 254 | "%i, tq new: %i)\n", |
247 | gw_tq_avg, orig_tq_avg); | 255 | gw_tq_avg, orig_tq_avg); |
248 | goto deselect; | ||
249 | 256 | ||
250 | out_rcu: | ||
251 | rcu_read_unlock(); | ||
252 | goto out; | ||
253 | deselect_rcu: | ||
254 | rcu_read_unlock(); | ||
255 | deselect: | 257 | deselect: |
256 | gw_deselect(bat_priv); | 258 | gw_deselect(bat_priv); |
257 | out: | 259 | out: |
260 | if (curr_gw_orig) | ||
261 | orig_node_free_ref(curr_gw_orig); | ||
262 | if (router_gw) | ||
263 | neigh_node_free_ref(router_gw); | ||
264 | if (router_orig) | ||
265 | neigh_node_free_ref(router_orig); | ||
266 | |||
258 | return; | 267 | return; |
259 | } | 268 | } |
260 | 269 | ||
@@ -291,7 +300,15 @@ void gw_node_update(struct bat_priv *bat_priv, | |||
291 | struct orig_node *orig_node, uint8_t new_gwflags) | 300 | struct orig_node *orig_node, uint8_t new_gwflags) |
292 | { | 301 | { |
293 | struct hlist_node *node; | 302 | struct hlist_node *node; |
294 | struct gw_node *gw_node; | 303 | struct gw_node *gw_node, *curr_gw; |
304 | |||
305 | /** | ||
306 | * Note: We don't need a NULL check here, since curr_gw never gets | ||
307 | * dereferenced. If curr_gw is NULL we also should not exit as we may | ||
308 | * have this gateway in our list (duplication check!) even though we | ||
309 | * have no currently selected gateway. | ||
310 | */ | ||
311 | curr_gw = gw_get_selected_gw_node(bat_priv); | ||
295 | 312 | ||
296 | rcu_read_lock(); | 313 | rcu_read_lock(); |
297 | hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) { | 314 | hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) { |
@@ -312,22 +329,26 @@ void gw_node_update(struct bat_priv *bat_priv, | |||
312 | "Gateway %pM removed from gateway list\n", | 329 | "Gateway %pM removed from gateway list\n", |
313 | orig_node->orig); | 330 | orig_node->orig); |
314 | 331 | ||
315 | if (gw_node == rcu_dereference(bat_priv->curr_gw)) { | 332 | if (gw_node == curr_gw) |
316 | rcu_read_unlock(); | 333 | goto deselect; |
317 | gw_deselect(bat_priv); | ||
318 | return; | ||
319 | } | ||
320 | } | 334 | } |
321 | 335 | ||
322 | rcu_read_unlock(); | 336 | goto unlock; |
323 | return; | ||
324 | } | 337 | } |
325 | rcu_read_unlock(); | ||
326 | 338 | ||
327 | if (new_gwflags == 0) | 339 | if (new_gwflags == 0) |
328 | return; | 340 | goto unlock; |
329 | 341 | ||
330 | gw_node_add(bat_priv, orig_node, new_gwflags); | 342 | gw_node_add(bat_priv, orig_node, new_gwflags); |
343 | goto unlock; | ||
344 | |||
345 | deselect: | ||
346 | gw_deselect(bat_priv); | ||
347 | unlock: | ||
348 | rcu_read_unlock(); | ||
349 | |||
350 | if (curr_gw) | ||
351 | gw_node_free_ref(curr_gw); | ||
331 | } | 352 | } |
332 | 353 | ||
333 | void gw_node_delete(struct bat_priv *bat_priv, struct orig_node *orig_node) | 354 | void gw_node_delete(struct bat_priv *bat_priv, struct orig_node *orig_node) |
@@ -337,9 +358,12 @@ void gw_node_delete(struct bat_priv *bat_priv, struct orig_node *orig_node) | |||
337 | 358 | ||
338 | void gw_node_purge(struct bat_priv *bat_priv) | 359 | void gw_node_purge(struct bat_priv *bat_priv) |
339 | { | 360 | { |
340 | struct gw_node *gw_node; | 361 | struct gw_node *gw_node, *curr_gw; |
341 | struct hlist_node *node, *node_tmp; | 362 | struct hlist_node *node, *node_tmp; |
342 | unsigned long timeout = 2 * PURGE_TIMEOUT * HZ; | 363 | unsigned long timeout = 2 * PURGE_TIMEOUT * HZ; |
364 | char do_deselect = 0; | ||
365 | |||
366 | curr_gw = gw_get_selected_gw_node(bat_priv); | ||
343 | 367 | ||
344 | spin_lock_bh(&bat_priv->gw_list_lock); | 368 | spin_lock_bh(&bat_priv->gw_list_lock); |
345 | 369 | ||
@@ -350,41 +374,56 @@ void gw_node_purge(struct bat_priv *bat_priv) | |||
350 | atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE) | 374 | atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE) |
351 | continue; | 375 | continue; |
352 | 376 | ||
353 | if (rcu_dereference(bat_priv->curr_gw) == gw_node) | 377 | if (curr_gw == gw_node) |
354 | gw_deselect(bat_priv); | 378 | do_deselect = 1; |
355 | 379 | ||
356 | hlist_del_rcu(&gw_node->list); | 380 | hlist_del_rcu(&gw_node->list); |
357 | gw_node_free_ref(gw_node); | 381 | gw_node_free_ref(gw_node); |
358 | } | 382 | } |
359 | 383 | ||
360 | |||
361 | spin_unlock_bh(&bat_priv->gw_list_lock); | 384 | spin_unlock_bh(&bat_priv->gw_list_lock); |
385 | |||
386 | /* gw_deselect() needs to acquire the gw_list_lock */ | ||
387 | if (do_deselect) | ||
388 | gw_deselect(bat_priv); | ||
389 | |||
390 | if (curr_gw) | ||
391 | gw_node_free_ref(curr_gw); | ||
362 | } | 392 | } |
363 | 393 | ||
394 | /** | ||
395 | * fails if orig_node has no router | ||
396 | */ | ||
364 | static int _write_buffer_text(struct bat_priv *bat_priv, | 397 | static int _write_buffer_text(struct bat_priv *bat_priv, |
365 | struct seq_file *seq, struct gw_node *gw_node) | 398 | struct seq_file *seq, struct gw_node *gw_node) |
366 | { | 399 | { |
367 | struct gw_node *curr_gw; | 400 | struct gw_node *curr_gw; |
368 | int down, up, ret; | 401 | struct neigh_node *router; |
402 | int down, up, ret = -1; | ||
369 | 403 | ||
370 | gw_bandwidth_to_kbit(gw_node->orig_node->gw_flags, &down, &up); | 404 | gw_bandwidth_to_kbit(gw_node->orig_node->gw_flags, &down, &up); |
371 | 405 | ||
372 | rcu_read_lock(); | 406 | router = orig_node_get_router(gw_node->orig_node); |
373 | curr_gw = rcu_dereference(bat_priv->curr_gw); | 407 | if (!router) |
408 | goto out; | ||
374 | 409 | ||
375 | ret = seq_printf(seq, "%s %pM (%3i) %pM [%10s]: %3i - %i%s/%i%s\n", | 410 | curr_gw = gw_get_selected_gw_node(bat_priv); |
376 | (curr_gw == gw_node ? "=>" : " "), | ||
377 | gw_node->orig_node->orig, | ||
378 | gw_node->orig_node->router->tq_avg, | ||
379 | gw_node->orig_node->router->addr, | ||
380 | gw_node->orig_node->router->if_incoming->net_dev->name, | ||
381 | gw_node->orig_node->gw_flags, | ||
382 | (down > 2048 ? down / 1024 : down), | ||
383 | (down > 2048 ? "MBit" : "KBit"), | ||
384 | (up > 2048 ? up / 1024 : up), | ||
385 | (up > 2048 ? "MBit" : "KBit")); | ||
386 | 411 | ||
387 | rcu_read_unlock(); | 412 | ret = seq_printf(seq, "%s %pM (%3i) %pM [%10s]: %3i - %i%s/%i%s\n", |
413 | (curr_gw == gw_node ? "=>" : " "), | ||
414 | gw_node->orig_node->orig, | ||
415 | router->tq_avg, router->addr, | ||
416 | router->if_incoming->net_dev->name, | ||
417 | gw_node->orig_node->gw_flags, | ||
418 | (down > 2048 ? down / 1024 : down), | ||
419 | (down > 2048 ? "MBit" : "KBit"), | ||
420 | (up > 2048 ? up / 1024 : up), | ||
421 | (up > 2048 ? "MBit" : "KBit")); | ||
422 | |||
423 | neigh_node_free_ref(router); | ||
424 | if (curr_gw) | ||
425 | gw_node_free_ref(curr_gw); | ||
426 | out: | ||
388 | return ret; | 427 | return ret; |
389 | } | 428 | } |
390 | 429 | ||
@@ -392,40 +431,42 @@ int gw_client_seq_print_text(struct seq_file *seq, void *offset) | |||
392 | { | 431 | { |
393 | struct net_device *net_dev = (struct net_device *)seq->private; | 432 | struct net_device *net_dev = (struct net_device *)seq->private; |
394 | struct bat_priv *bat_priv = netdev_priv(net_dev); | 433 | struct bat_priv *bat_priv = netdev_priv(net_dev); |
434 | struct hard_iface *primary_if; | ||
395 | struct gw_node *gw_node; | 435 | struct gw_node *gw_node; |
396 | struct hlist_node *node; | 436 | struct hlist_node *node; |
397 | int gw_count = 0; | 437 | int gw_count = 0, ret = 0; |
398 | |||
399 | if (!bat_priv->primary_if) { | ||
400 | 438 | ||
401 | return seq_printf(seq, "BATMAN mesh %s disabled - please " | 439 | primary_if = primary_if_get_selected(bat_priv); |
402 | "specify interfaces to enable it\n", | 440 | if (!primary_if) { |
403 | net_dev->name); | 441 | ret = seq_printf(seq, "BATMAN mesh %s disabled - please " |
442 | "specify interfaces to enable it\n", | ||
443 | net_dev->name); | ||
444 | goto out; | ||
404 | } | 445 | } |
405 | 446 | ||
406 | if (bat_priv->primary_if->if_status != IF_ACTIVE) { | 447 | if (primary_if->if_status != IF_ACTIVE) { |
407 | 448 | ret = seq_printf(seq, "BATMAN mesh %s disabled - " | |
408 | return seq_printf(seq, "BATMAN mesh %s disabled - " | 449 | "primary interface not active\n", |
409 | "primary interface not active\n", | 450 | net_dev->name); |
410 | net_dev->name); | 451 | goto out; |
411 | } | 452 | } |
412 | 453 | ||
413 | seq_printf(seq, " %-12s (%s/%i) %17s [%10s]: gw_class ... " | 454 | seq_printf(seq, " %-12s (%s/%i) %17s [%10s]: gw_class ... " |
414 | "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%pM (%s)]\n", | 455 | "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%pM (%s)]\n", |
415 | "Gateway", "#", TQ_MAX_VALUE, "Nexthop", | 456 | "Gateway", "#", TQ_MAX_VALUE, "Nexthop", |
416 | "outgoingIF", SOURCE_VERSION, REVISION_VERSION_STR, | 457 | "outgoingIF", SOURCE_VERSION, REVISION_VERSION_STR, |
417 | bat_priv->primary_if->net_dev->name, | 458 | primary_if->net_dev->name, |
418 | bat_priv->primary_if->net_dev->dev_addr, net_dev->name); | 459 | primary_if->net_dev->dev_addr, net_dev->name); |
419 | 460 | ||
420 | rcu_read_lock(); | 461 | rcu_read_lock(); |
421 | hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) { | 462 | hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) { |
422 | if (gw_node->deleted) | 463 | if (gw_node->deleted) |
423 | continue; | 464 | continue; |
424 | 465 | ||
425 | if (!gw_node->orig_node->router) | 466 | /* fails if orig_node has no router */ |
467 | if (_write_buffer_text(bat_priv, seq, gw_node) < 0) | ||
426 | continue; | 468 | continue; |
427 | 469 | ||
428 | _write_buffer_text(bat_priv, seq, gw_node); | ||
429 | gw_count++; | 470 | gw_count++; |
430 | } | 471 | } |
431 | rcu_read_unlock(); | 472 | rcu_read_unlock(); |
@@ -433,7 +474,10 @@ int gw_client_seq_print_text(struct seq_file *seq, void *offset) | |||
433 | if (gw_count == 0) | 474 | if (gw_count == 0) |
434 | seq_printf(seq, "No gateways in range ...\n"); | 475 | seq_printf(seq, "No gateways in range ...\n"); |
435 | 476 | ||
436 | return 0; | 477 | out: |
478 | if (primary_if) | ||
479 | hardif_free_ref(primary_if); | ||
480 | return ret; | ||
437 | } | 481 | } |
438 | 482 | ||
439 | int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb) | 483 | int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb) |
@@ -442,6 +486,7 @@ int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb) | |||
442 | struct iphdr *iphdr; | 486 | struct iphdr *iphdr; |
443 | struct ipv6hdr *ipv6hdr; | 487 | struct ipv6hdr *ipv6hdr; |
444 | struct udphdr *udphdr; | 488 | struct udphdr *udphdr; |
489 | struct gw_node *curr_gw; | ||
445 | unsigned int header_len = 0; | 490 | unsigned int header_len = 0; |
446 | 491 | ||
447 | if (atomic_read(&bat_priv->gw_mode) == GW_MODE_OFF) | 492 | if (atomic_read(&bat_priv->gw_mode) == GW_MODE_OFF) |
@@ -506,12 +551,11 @@ int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb) | |||
506 | if (atomic_read(&bat_priv->gw_mode) == GW_MODE_SERVER) | 551 | if (atomic_read(&bat_priv->gw_mode) == GW_MODE_SERVER) |
507 | return -1; | 552 | return -1; |
508 | 553 | ||
509 | rcu_read_lock(); | 554 | curr_gw = gw_get_selected_gw_node(bat_priv); |
510 | if (!rcu_dereference(bat_priv->curr_gw)) { | 555 | if (!curr_gw) |
511 | rcu_read_unlock(); | ||
512 | return 0; | 556 | return 0; |
513 | } | ||
514 | rcu_read_unlock(); | ||
515 | 557 | ||
558 | if (curr_gw) | ||
559 | gw_node_free_ref(curr_gw); | ||
516 | return 1; | 560 | return 1; |
517 | } | 561 | } |
diff --git a/net/batman-adv/gateway_client.h b/net/batman-adv/gateway_client.h index 2aa439124ee3..1ce8c6066da1 100644 --- a/net/batman-adv/gateway_client.h +++ b/net/batman-adv/gateway_client.h | |||
@@ -24,7 +24,7 @@ | |||
24 | 24 | ||
25 | void gw_deselect(struct bat_priv *bat_priv); | 25 | void gw_deselect(struct bat_priv *bat_priv); |
26 | void gw_election(struct bat_priv *bat_priv); | 26 | void gw_election(struct bat_priv *bat_priv); |
27 | void *gw_get_selected(struct bat_priv *bat_priv); | 27 | struct orig_node *gw_get_selected_orig(struct bat_priv *bat_priv); |
28 | void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node); | 28 | void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node); |
29 | void gw_node_update(struct bat_priv *bat_priv, | 29 | void gw_node_update(struct bat_priv *bat_priv, |
30 | struct orig_node *orig_node, uint8_t new_gwflags); | 30 | struct orig_node *orig_node, uint8_t new_gwflags); |
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index b3058e46ee6b..dfbfccc9fe40 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c | |||
@@ -31,9 +31,6 @@ | |||
31 | 31 | ||
32 | #include <linux/if_arp.h> | 32 | #include <linux/if_arp.h> |
33 | 33 | ||
34 | /* protect update critical side of hardif_list - but not the content */ | ||
35 | static DEFINE_SPINLOCK(hardif_list_lock); | ||
36 | |||
37 | 34 | ||
38 | static int batman_skb_recv(struct sk_buff *skb, | 35 | static int batman_skb_recv(struct sk_buff *skb, |
39 | struct net_device *dev, | 36 | struct net_device *dev, |
@@ -110,47 +107,57 @@ out: | |||
110 | return hard_iface; | 107 | return hard_iface; |
111 | } | 108 | } |
112 | 109 | ||
113 | static void update_primary_addr(struct bat_priv *bat_priv) | 110 | static void primary_if_update_addr(struct bat_priv *bat_priv) |
114 | { | 111 | { |
115 | struct vis_packet *vis_packet; | 112 | struct vis_packet *vis_packet; |
113 | struct hard_iface *primary_if; | ||
114 | |||
115 | primary_if = primary_if_get_selected(bat_priv); | ||
116 | if (!primary_if) | ||
117 | goto out; | ||
116 | 118 | ||
117 | vis_packet = (struct vis_packet *) | 119 | vis_packet = (struct vis_packet *) |
118 | bat_priv->my_vis_info->skb_packet->data; | 120 | bat_priv->my_vis_info->skb_packet->data; |
119 | memcpy(vis_packet->vis_orig, | 121 | memcpy(vis_packet->vis_orig, primary_if->net_dev->dev_addr, ETH_ALEN); |
120 | bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); | ||
121 | memcpy(vis_packet->sender_orig, | 122 | memcpy(vis_packet->sender_orig, |
122 | bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); | 123 | primary_if->net_dev->dev_addr, ETH_ALEN); |
124 | |||
125 | out: | ||
126 | if (primary_if) | ||
127 | hardif_free_ref(primary_if); | ||
123 | } | 128 | } |
124 | 129 | ||
125 | static void set_primary_if(struct bat_priv *bat_priv, | 130 | static void primary_if_select(struct bat_priv *bat_priv, |
126 | struct hard_iface *hard_iface) | 131 | struct hard_iface *new_hard_iface) |
127 | { | 132 | { |
133 | struct hard_iface *curr_hard_iface; | ||
128 | struct batman_packet *batman_packet; | 134 | struct batman_packet *batman_packet; |
129 | struct hard_iface *old_if; | ||
130 | 135 | ||
131 | if (hard_iface && !atomic_inc_not_zero(&hard_iface->refcount)) | 136 | ASSERT_RTNL(); |
132 | hard_iface = NULL; | 137 | |
138 | if (new_hard_iface && !atomic_inc_not_zero(&new_hard_iface->refcount)) | ||
139 | new_hard_iface = NULL; | ||
133 | 140 | ||
134 | old_if = bat_priv->primary_if; | 141 | curr_hard_iface = bat_priv->primary_if; |
135 | bat_priv->primary_if = hard_iface; | 142 | rcu_assign_pointer(bat_priv->primary_if, new_hard_iface); |
136 | 143 | ||
137 | if (old_if) | 144 | if (curr_hard_iface) |
138 | hardif_free_ref(old_if); | 145 | hardif_free_ref(curr_hard_iface); |
139 | 146 | ||
140 | if (!bat_priv->primary_if) | 147 | if (!new_hard_iface) |
141 | return; | 148 | return; |
142 | 149 | ||
143 | batman_packet = (struct batman_packet *)(hard_iface->packet_buff); | 150 | batman_packet = (struct batman_packet *)(new_hard_iface->packet_buff); |
144 | batman_packet->flags = PRIMARIES_FIRST_HOP; | 151 | batman_packet->flags = PRIMARIES_FIRST_HOP; |
145 | batman_packet->ttl = TTL; | 152 | batman_packet->ttl = TTL; |
146 | 153 | ||
147 | update_primary_addr(bat_priv); | 154 | primary_if_update_addr(bat_priv); |
148 | 155 | ||
149 | /*** | 156 | /*** |
150 | * hacky trick to make sure that we send the HNA information via | 157 | * hacky trick to make sure that we send the TT information via |
151 | * our new primary interface | 158 | * our new primary interface |
152 | */ | 159 | */ |
153 | atomic_set(&bat_priv->hna_local_changed, 1); | 160 | atomic_set(&bat_priv->tt_local_changed, 1); |
154 | } | 161 | } |
155 | 162 | ||
156 | static bool hardif_is_iface_up(struct hard_iface *hard_iface) | 163 | static bool hardif_is_iface_up(struct hard_iface *hard_iface) |
@@ -236,9 +243,10 @@ void update_min_mtu(struct net_device *soft_iface) | |||
236 | static void hardif_activate_interface(struct hard_iface *hard_iface) | 243 | static void hardif_activate_interface(struct hard_iface *hard_iface) |
237 | { | 244 | { |
238 | struct bat_priv *bat_priv; | 245 | struct bat_priv *bat_priv; |
246 | struct hard_iface *primary_if = NULL; | ||
239 | 247 | ||
240 | if (hard_iface->if_status != IF_INACTIVE) | 248 | if (hard_iface->if_status != IF_INACTIVE) |
241 | return; | 249 | goto out; |
242 | 250 | ||
243 | bat_priv = netdev_priv(hard_iface->soft_iface); | 251 | bat_priv = netdev_priv(hard_iface->soft_iface); |
244 | 252 | ||
@@ -249,14 +257,18 @@ static void hardif_activate_interface(struct hard_iface *hard_iface) | |||
249 | * the first active interface becomes our primary interface or | 257 | * the first active interface becomes our primary interface or |
250 | * the next active interface after the old primay interface was removed | 258 | * the next active interface after the old primay interface was removed |
251 | */ | 259 | */ |
252 | if (!bat_priv->primary_if) | 260 | primary_if = primary_if_get_selected(bat_priv); |
253 | set_primary_if(bat_priv, hard_iface); | 261 | if (!primary_if) |
262 | primary_if_select(bat_priv, hard_iface); | ||
254 | 263 | ||
255 | bat_info(hard_iface->soft_iface, "Interface activated: %s\n", | 264 | bat_info(hard_iface->soft_iface, "Interface activated: %s\n", |
256 | hard_iface->net_dev->name); | 265 | hard_iface->net_dev->name); |
257 | 266 | ||
258 | update_min_mtu(hard_iface->soft_iface); | 267 | update_min_mtu(hard_iface->soft_iface); |
259 | return; | 268 | |
269 | out: | ||
270 | if (primary_if) | ||
271 | hardif_free_ref(primary_if); | ||
260 | } | 272 | } |
261 | 273 | ||
262 | static void hardif_deactivate_interface(struct hard_iface *hard_iface) | 274 | static void hardif_deactivate_interface(struct hard_iface *hard_iface) |
@@ -327,7 +339,7 @@ int hardif_enable_interface(struct hard_iface *hard_iface, char *iface_name) | |||
327 | batman_packet->flags = 0; | 339 | batman_packet->flags = 0; |
328 | batman_packet->ttl = 2; | 340 | batman_packet->ttl = 2; |
329 | batman_packet->tq = TQ_MAX_VALUE; | 341 | batman_packet->tq = TQ_MAX_VALUE; |
330 | batman_packet->num_hna = 0; | 342 | batman_packet->num_tt = 0; |
331 | 343 | ||
332 | hard_iface->if_num = bat_priv->num_ifaces; | 344 | hard_iface->if_num = bat_priv->num_ifaces; |
333 | bat_priv->num_ifaces++; | 345 | bat_priv->num_ifaces++; |
@@ -386,12 +398,13 @@ err: | |||
386 | void hardif_disable_interface(struct hard_iface *hard_iface) | 398 | void hardif_disable_interface(struct hard_iface *hard_iface) |
387 | { | 399 | { |
388 | struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface); | 400 | struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface); |
401 | struct hard_iface *primary_if = NULL; | ||
389 | 402 | ||
390 | if (hard_iface->if_status == IF_ACTIVE) | 403 | if (hard_iface->if_status == IF_ACTIVE) |
391 | hardif_deactivate_interface(hard_iface); | 404 | hardif_deactivate_interface(hard_iface); |
392 | 405 | ||
393 | if (hard_iface->if_status != IF_INACTIVE) | 406 | if (hard_iface->if_status != IF_INACTIVE) |
394 | return; | 407 | goto out; |
395 | 408 | ||
396 | bat_info(hard_iface->soft_iface, "Removing interface: %s\n", | 409 | bat_info(hard_iface->soft_iface, "Removing interface: %s\n", |
397 | hard_iface->net_dev->name); | 410 | hard_iface->net_dev->name); |
@@ -400,11 +413,12 @@ void hardif_disable_interface(struct hard_iface *hard_iface) | |||
400 | bat_priv->num_ifaces--; | 413 | bat_priv->num_ifaces--; |
401 | orig_hash_del_if(hard_iface, bat_priv->num_ifaces); | 414 | orig_hash_del_if(hard_iface, bat_priv->num_ifaces); |
402 | 415 | ||
403 | if (hard_iface == bat_priv->primary_if) { | 416 | primary_if = primary_if_get_selected(bat_priv); |
417 | if (hard_iface == primary_if) { | ||
404 | struct hard_iface *new_if; | 418 | struct hard_iface *new_if; |
405 | 419 | ||
406 | new_if = hardif_get_active(hard_iface->soft_iface); | 420 | new_if = hardif_get_active(hard_iface->soft_iface); |
407 | set_primary_if(bat_priv, new_if); | 421 | primary_if_select(bat_priv, new_if); |
408 | 422 | ||
409 | if (new_if) | 423 | if (new_if) |
410 | hardif_free_ref(new_if); | 424 | hardif_free_ref(new_if); |
@@ -425,6 +439,10 @@ void hardif_disable_interface(struct hard_iface *hard_iface) | |||
425 | 439 | ||
426 | hard_iface->soft_iface = NULL; | 440 | hard_iface->soft_iface = NULL; |
427 | hardif_free_ref(hard_iface); | 441 | hardif_free_ref(hard_iface); |
442 | |||
443 | out: | ||
444 | if (primary_if) | ||
445 | hardif_free_ref(primary_if); | ||
428 | } | 446 | } |
429 | 447 | ||
430 | static struct hard_iface *hardif_add_interface(struct net_device *net_dev) | 448 | static struct hard_iface *hardif_add_interface(struct net_device *net_dev) |
@@ -432,6 +450,8 @@ static struct hard_iface *hardif_add_interface(struct net_device *net_dev) | |||
432 | struct hard_iface *hard_iface; | 450 | struct hard_iface *hard_iface; |
433 | int ret; | 451 | int ret; |
434 | 452 | ||
453 | ASSERT_RTNL(); | ||
454 | |||
435 | ret = is_valid_iface(net_dev); | 455 | ret = is_valid_iface(net_dev); |
436 | if (ret != 1) | 456 | if (ret != 1) |
437 | goto out; | 457 | goto out; |
@@ -458,10 +478,7 @@ static struct hard_iface *hardif_add_interface(struct net_device *net_dev) | |||
458 | atomic_set(&hard_iface->refcount, 2); | 478 | atomic_set(&hard_iface->refcount, 2); |
459 | 479 | ||
460 | check_known_mac_addr(hard_iface->net_dev); | 480 | check_known_mac_addr(hard_iface->net_dev); |
461 | |||
462 | spin_lock(&hardif_list_lock); | ||
463 | list_add_tail_rcu(&hard_iface->list, &hardif_list); | 481 | list_add_tail_rcu(&hard_iface->list, &hardif_list); |
464 | spin_unlock(&hardif_list_lock); | ||
465 | 482 | ||
466 | return hard_iface; | 483 | return hard_iface; |
467 | 484 | ||
@@ -475,6 +492,8 @@ out: | |||
475 | 492 | ||
476 | static void hardif_remove_interface(struct hard_iface *hard_iface) | 493 | static void hardif_remove_interface(struct hard_iface *hard_iface) |
477 | { | 494 | { |
495 | ASSERT_RTNL(); | ||
496 | |||
478 | /* first deactivate interface */ | 497 | /* first deactivate interface */ |
479 | if (hard_iface->if_status != IF_NOT_IN_USE) | 498 | if (hard_iface->if_status != IF_NOT_IN_USE) |
480 | hardif_disable_interface(hard_iface); | 499 | hardif_disable_interface(hard_iface); |
@@ -490,20 +509,11 @@ static void hardif_remove_interface(struct hard_iface *hard_iface) | |||
490 | void hardif_remove_interfaces(void) | 509 | void hardif_remove_interfaces(void) |
491 | { | 510 | { |
492 | struct hard_iface *hard_iface, *hard_iface_tmp; | 511 | struct hard_iface *hard_iface, *hard_iface_tmp; |
493 | struct list_head if_queue; | ||
494 | |||
495 | INIT_LIST_HEAD(&if_queue); | ||
496 | 512 | ||
497 | spin_lock(&hardif_list_lock); | 513 | rtnl_lock(); |
498 | list_for_each_entry_safe(hard_iface, hard_iface_tmp, | 514 | list_for_each_entry_safe(hard_iface, hard_iface_tmp, |
499 | &hardif_list, list) { | 515 | &hardif_list, list) { |
500 | list_del_rcu(&hard_iface->list); | 516 | list_del_rcu(&hard_iface->list); |
501 | list_add_tail(&hard_iface->list, &if_queue); | ||
502 | } | ||
503 | spin_unlock(&hardif_list_lock); | ||
504 | |||
505 | rtnl_lock(); | ||
506 | list_for_each_entry_safe(hard_iface, hard_iface_tmp, &if_queue, list) { | ||
507 | hardif_remove_interface(hard_iface); | 517 | hardif_remove_interface(hard_iface); |
508 | } | 518 | } |
509 | rtnl_unlock(); | 519 | rtnl_unlock(); |
@@ -514,6 +524,7 @@ static int hard_if_event(struct notifier_block *this, | |||
514 | { | 524 | { |
515 | struct net_device *net_dev = (struct net_device *)ptr; | 525 | struct net_device *net_dev = (struct net_device *)ptr; |
516 | struct hard_iface *hard_iface = hardif_get_by_netdev(net_dev); | 526 | struct hard_iface *hard_iface = hardif_get_by_netdev(net_dev); |
527 | struct hard_iface *primary_if = NULL; | ||
517 | struct bat_priv *bat_priv; | 528 | struct bat_priv *bat_priv; |
518 | 529 | ||
519 | if (!hard_iface && event == NETDEV_REGISTER) | 530 | if (!hard_iface && event == NETDEV_REGISTER) |
@@ -531,9 +542,7 @@ static int hard_if_event(struct notifier_block *this, | |||
531 | hardif_deactivate_interface(hard_iface); | 542 | hardif_deactivate_interface(hard_iface); |
532 | break; | 543 | break; |
533 | case NETDEV_UNREGISTER: | 544 | case NETDEV_UNREGISTER: |
534 | spin_lock(&hardif_list_lock); | ||
535 | list_del_rcu(&hard_iface->list); | 545 | list_del_rcu(&hard_iface->list); |
536 | spin_unlock(&hardif_list_lock); | ||
537 | 546 | ||
538 | hardif_remove_interface(hard_iface); | 547 | hardif_remove_interface(hard_iface); |
539 | break; | 548 | break; |
@@ -549,8 +558,12 @@ static int hard_if_event(struct notifier_block *this, | |||
549 | update_mac_addresses(hard_iface); | 558 | update_mac_addresses(hard_iface); |
550 | 559 | ||
551 | bat_priv = netdev_priv(hard_iface->soft_iface); | 560 | bat_priv = netdev_priv(hard_iface->soft_iface); |
552 | if (hard_iface == bat_priv->primary_if) | 561 | primary_if = primary_if_get_selected(bat_priv); |
553 | update_primary_addr(bat_priv); | 562 | if (!primary_if) |
563 | goto hardif_put; | ||
564 | |||
565 | if (hard_iface == primary_if) | ||
566 | primary_if_update_addr(bat_priv); | ||
554 | break; | 567 | break; |
555 | default: | 568 | default: |
556 | break; | 569 | break; |
@@ -559,6 +572,8 @@ static int hard_if_event(struct notifier_block *this, | |||
559 | hardif_put: | 572 | hardif_put: |
560 | hardif_free_ref(hard_iface); | 573 | hardif_free_ref(hard_iface); |
561 | out: | 574 | out: |
575 | if (primary_if) | ||
576 | hardif_free_ref(primary_if); | ||
562 | return NOTIFY_DONE; | 577 | return NOTIFY_DONE; |
563 | } | 578 | } |
564 | 579 | ||
diff --git a/net/batman-adv/hard-interface.h b/net/batman-adv/hard-interface.h index a9ddf36e51c8..64265991460b 100644 --- a/net/batman-adv/hard-interface.h +++ b/net/batman-adv/hard-interface.h | |||
@@ -45,4 +45,22 @@ static inline void hardif_free_ref(struct hard_iface *hard_iface) | |||
45 | call_rcu(&hard_iface->rcu, hardif_free_rcu); | 45 | call_rcu(&hard_iface->rcu, hardif_free_rcu); |
46 | } | 46 | } |
47 | 47 | ||
48 | static inline struct hard_iface *primary_if_get_selected( | ||
49 | struct bat_priv *bat_priv) | ||
50 | { | ||
51 | struct hard_iface *hard_iface; | ||
52 | |||
53 | rcu_read_lock(); | ||
54 | hard_iface = rcu_dereference(bat_priv->primary_if); | ||
55 | if (!hard_iface) | ||
56 | goto out; | ||
57 | |||
58 | if (!atomic_inc_not_zero(&hard_iface->refcount)) | ||
59 | hard_iface = NULL; | ||
60 | |||
61 | out: | ||
62 | rcu_read_unlock(); | ||
63 | return hard_iface; | ||
64 | } | ||
65 | |||
48 | #endif /* _NET_BATMAN_ADV_HARD_INTERFACE_H_ */ | 66 | #endif /* _NET_BATMAN_ADV_HARD_INTERFACE_H_ */ |
diff --git a/net/batman-adv/icmp_socket.c b/net/batman-adv/icmp_socket.c index 34ce56c358e5..fa22ba2bb832 100644 --- a/net/batman-adv/icmp_socket.c +++ b/net/batman-adv/icmp_socket.c | |||
@@ -153,6 +153,7 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, | |||
153 | { | 153 | { |
154 | struct socket_client *socket_client = file->private_data; | 154 | struct socket_client *socket_client = file->private_data; |
155 | struct bat_priv *bat_priv = socket_client->bat_priv; | 155 | struct bat_priv *bat_priv = socket_client->bat_priv; |
156 | struct hard_iface *primary_if = NULL; | ||
156 | struct sk_buff *skb; | 157 | struct sk_buff *skb; |
157 | struct icmp_packet_rr *icmp_packet; | 158 | struct icmp_packet_rr *icmp_packet; |
158 | 159 | ||
@@ -167,15 +168,21 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, | |||
167 | return -EINVAL; | 168 | return -EINVAL; |
168 | } | 169 | } |
169 | 170 | ||
170 | if (!bat_priv->primary_if) | 171 | primary_if = primary_if_get_selected(bat_priv); |
171 | return -EFAULT; | 172 | |
173 | if (!primary_if) { | ||
174 | len = -EFAULT; | ||
175 | goto out; | ||
176 | } | ||
172 | 177 | ||
173 | if (len >= sizeof(struct icmp_packet_rr)) | 178 | if (len >= sizeof(struct icmp_packet_rr)) |
174 | packet_len = sizeof(struct icmp_packet_rr); | 179 | packet_len = sizeof(struct icmp_packet_rr); |
175 | 180 | ||
176 | skb = dev_alloc_skb(packet_len + sizeof(struct ethhdr)); | 181 | skb = dev_alloc_skb(packet_len + sizeof(struct ethhdr)); |
177 | if (!skb) | 182 | if (!skb) { |
178 | return -ENOMEM; | 183 | len = -ENOMEM; |
184 | goto out; | ||
185 | } | ||
179 | 186 | ||
180 | skb_reserve(skb, sizeof(struct ethhdr)); | 187 | skb_reserve(skb, sizeof(struct ethhdr)); |
181 | icmp_packet = (struct icmp_packet_rr *)skb_put(skb, packet_len); | 188 | icmp_packet = (struct icmp_packet_rr *)skb_put(skb, packet_len); |
@@ -218,23 +225,13 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, | |||
218 | if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE) | 225 | if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE) |
219 | goto dst_unreach; | 226 | goto dst_unreach; |
220 | 227 | ||
221 | rcu_read_lock(); | ||
222 | orig_node = orig_hash_find(bat_priv, icmp_packet->dst); | 228 | orig_node = orig_hash_find(bat_priv, icmp_packet->dst); |
223 | |||
224 | if (!orig_node) | 229 | if (!orig_node) |
225 | goto unlock; | 230 | goto dst_unreach; |
226 | |||
227 | neigh_node = orig_node->router; | ||
228 | 231 | ||
232 | neigh_node = orig_node_get_router(orig_node); | ||
229 | if (!neigh_node) | 233 | if (!neigh_node) |
230 | goto unlock; | 234 | goto dst_unreach; |
231 | |||
232 | if (!atomic_inc_not_zero(&neigh_node->refcount)) { | ||
233 | neigh_node = NULL; | ||
234 | goto unlock; | ||
235 | } | ||
236 | |||
237 | rcu_read_unlock(); | ||
238 | 235 | ||
239 | if (!neigh_node->if_incoming) | 236 | if (!neigh_node->if_incoming) |
240 | goto dst_unreach; | 237 | goto dst_unreach; |
@@ -243,7 +240,7 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, | |||
243 | goto dst_unreach; | 240 | goto dst_unreach; |
244 | 241 | ||
245 | memcpy(icmp_packet->orig, | 242 | memcpy(icmp_packet->orig, |
246 | bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); | 243 | primary_if->net_dev->dev_addr, ETH_ALEN); |
247 | 244 | ||
248 | if (packet_len == sizeof(struct icmp_packet_rr)) | 245 | if (packet_len == sizeof(struct icmp_packet_rr)) |
249 | memcpy(icmp_packet->rr, | 246 | memcpy(icmp_packet->rr, |
@@ -252,14 +249,14 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, | |||
252 | send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); | 249 | send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); |
253 | goto out; | 250 | goto out; |
254 | 251 | ||
255 | unlock: | ||
256 | rcu_read_unlock(); | ||
257 | dst_unreach: | 252 | dst_unreach: |
258 | icmp_packet->msg_type = DESTINATION_UNREACHABLE; | 253 | icmp_packet->msg_type = DESTINATION_UNREACHABLE; |
259 | bat_socket_add_packet(socket_client, icmp_packet, packet_len); | 254 | bat_socket_add_packet(socket_client, icmp_packet, packet_len); |
260 | free_skb: | 255 | free_skb: |
261 | kfree_skb(skb); | 256 | kfree_skb(skb); |
262 | out: | 257 | out: |
258 | if (primary_if) | ||
259 | hardif_free_ref(primary_if); | ||
263 | if (neigh_node) | 260 | if (neigh_node) |
264 | neigh_node_free_ref(neigh_node); | 261 | neigh_node_free_ref(neigh_node); |
265 | if (orig_node) | 262 | if (orig_node) |
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index 709b33bbdf43..0a7cee0076f4 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c | |||
@@ -33,6 +33,9 @@ | |||
33 | #include "vis.h" | 33 | #include "vis.h" |
34 | #include "hash.h" | 34 | #include "hash.h" |
35 | 35 | ||
36 | |||
37 | /* List manipulations on hardif_list have to be rtnl_lock()'ed, | ||
38 | * list traversals just rcu-locked */ | ||
36 | struct list_head hardif_list; | 39 | struct list_head hardif_list; |
37 | 40 | ||
38 | unsigned char broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | 41 | unsigned char broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; |
@@ -81,28 +84,29 @@ int mesh_init(struct net_device *soft_iface) | |||
81 | 84 | ||
82 | spin_lock_init(&bat_priv->forw_bat_list_lock); | 85 | spin_lock_init(&bat_priv->forw_bat_list_lock); |
83 | spin_lock_init(&bat_priv->forw_bcast_list_lock); | 86 | spin_lock_init(&bat_priv->forw_bcast_list_lock); |
84 | spin_lock_init(&bat_priv->hna_lhash_lock); | 87 | spin_lock_init(&bat_priv->tt_lhash_lock); |
85 | spin_lock_init(&bat_priv->hna_ghash_lock); | 88 | spin_lock_init(&bat_priv->tt_ghash_lock); |
86 | spin_lock_init(&bat_priv->gw_list_lock); | 89 | spin_lock_init(&bat_priv->gw_list_lock); |
87 | spin_lock_init(&bat_priv->vis_hash_lock); | 90 | spin_lock_init(&bat_priv->vis_hash_lock); |
88 | spin_lock_init(&bat_priv->vis_list_lock); | 91 | spin_lock_init(&bat_priv->vis_list_lock); |
89 | spin_lock_init(&bat_priv->softif_neigh_lock); | 92 | spin_lock_init(&bat_priv->softif_neigh_lock); |
93 | spin_lock_init(&bat_priv->softif_neigh_vid_lock); | ||
90 | 94 | ||
91 | INIT_HLIST_HEAD(&bat_priv->forw_bat_list); | 95 | INIT_HLIST_HEAD(&bat_priv->forw_bat_list); |
92 | INIT_HLIST_HEAD(&bat_priv->forw_bcast_list); | 96 | INIT_HLIST_HEAD(&bat_priv->forw_bcast_list); |
93 | INIT_HLIST_HEAD(&bat_priv->gw_list); | 97 | INIT_HLIST_HEAD(&bat_priv->gw_list); |
94 | INIT_HLIST_HEAD(&bat_priv->softif_neigh_list); | 98 | INIT_HLIST_HEAD(&bat_priv->softif_neigh_vids); |
95 | 99 | ||
96 | if (originator_init(bat_priv) < 1) | 100 | if (originator_init(bat_priv) < 1) |
97 | goto err; | 101 | goto err; |
98 | 102 | ||
99 | if (hna_local_init(bat_priv) < 1) | 103 | if (tt_local_init(bat_priv) < 1) |
100 | goto err; | 104 | goto err; |
101 | 105 | ||
102 | if (hna_global_init(bat_priv) < 1) | 106 | if (tt_global_init(bat_priv) < 1) |
103 | goto err; | 107 | goto err; |
104 | 108 | ||
105 | hna_local_add(soft_iface, soft_iface->dev_addr); | 109 | tt_local_add(soft_iface, soft_iface->dev_addr); |
106 | 110 | ||
107 | if (vis_init(bat_priv) < 1) | 111 | if (vis_init(bat_priv) < 1) |
108 | goto err; | 112 | goto err; |
@@ -133,8 +137,8 @@ void mesh_free(struct net_device *soft_iface) | |||
133 | gw_node_purge(bat_priv); | 137 | gw_node_purge(bat_priv); |
134 | originator_free(bat_priv); | 138 | originator_free(bat_priv); |
135 | 139 | ||
136 | hna_local_free(bat_priv); | 140 | tt_local_free(bat_priv); |
137 | hna_global_free(bat_priv); | 141 | tt_global_free(bat_priv); |
138 | 142 | ||
139 | softif_neigh_purge(bat_priv); | 143 | softif_neigh_purge(bat_priv); |
140 | 144 | ||
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index dc248697de71..148b49e02642 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h | |||
@@ -34,16 +34,18 @@ | |||
34 | 34 | ||
35 | #define TQ_MAX_VALUE 255 | 35 | #define TQ_MAX_VALUE 255 |
36 | #define JITTER 20 | 36 | #define JITTER 20 |
37 | #define TTL 50 /* Time To Live of broadcast messages */ | ||
38 | 37 | ||
39 | #define PURGE_TIMEOUT 200 /* purge originators after time in seconds if no | 38 | /* Time To Live of broadcast messages */ |
40 | * valid packet comes in -> TODO: check | 39 | #define TTL 50 |
41 | * influence on TQ_LOCAL_WINDOW_SIZE */ | ||
42 | #define LOCAL_HNA_TIMEOUT 3600 /* in seconds */ | ||
43 | 40 | ||
44 | #define TQ_LOCAL_WINDOW_SIZE 64 /* sliding packet range of received originator | 41 | /* purge originators after time in seconds if no valid packet comes in |
45 | * messages in squence numbers (should be a | 42 | * -> TODO: check influence on TQ_LOCAL_WINDOW_SIZE */ |
46 | * multiple of our word size) */ | 43 | #define PURGE_TIMEOUT 200 |
44 | #define TT_LOCAL_TIMEOUT 3600 /* in seconds */ | ||
45 | |||
46 | /* sliding packet range of received originator messages in squence numbers | ||
47 | * (should be a multiple of our word size) */ | ||
48 | #define TQ_LOCAL_WINDOW_SIZE 64 | ||
47 | #define TQ_GLOBAL_WINDOW_SIZE 5 | 49 | #define TQ_GLOBAL_WINDOW_SIZE 5 |
48 | #define TQ_LOCAL_BIDRECT_SEND_MINIMUM 1 | 50 | #define TQ_LOCAL_BIDRECT_SEND_MINIMUM 1 |
49 | #define TQ_LOCAL_BIDRECT_RECV_MINIMUM 1 | 51 | #define TQ_LOCAL_BIDRECT_RECV_MINIMUM 1 |
@@ -55,21 +57,20 @@ | |||
55 | 57 | ||
56 | #define VIS_INTERVAL 5000 /* 5 seconds */ | 58 | #define VIS_INTERVAL 5000 /* 5 seconds */ |
57 | 59 | ||
58 | /* how much worse secondary interfaces may be to | 60 | /* how much worse secondary interfaces may be to be considered as bonding |
59 | * to be considered as bonding candidates */ | 61 | * candidates */ |
60 | |||
61 | #define BONDING_TQ_THRESHOLD 50 | 62 | #define BONDING_TQ_THRESHOLD 50 |
62 | 63 | ||
63 | #define MAX_AGGREGATION_BYTES 512 /* should not be bigger than 512 bytes or | 64 | /* should not be bigger than 512 bytes or change the size of |
64 | * change the size of | 65 | * forw_packet->direct_link_flags */ |
65 | * forw_packet->direct_link_flags */ | 66 | #define MAX_AGGREGATION_BYTES 512 |
66 | #define MAX_AGGREGATION_MS 100 | 67 | #define MAX_AGGREGATION_MS 100 |
67 | 68 | ||
68 | #define SOFTIF_NEIGH_TIMEOUT 180000 /* 3 minutes */ | 69 | #define SOFTIF_NEIGH_TIMEOUT 180000 /* 3 minutes */ |
69 | 70 | ||
71 | /* don't reset again within 30 seconds */ | ||
70 | #define RESET_PROTECTION_MS 30000 | 72 | #define RESET_PROTECTION_MS 30000 |
71 | #define EXPECTED_SEQNO_RANGE 65536 | 73 | #define EXPECTED_SEQNO_RANGE 65536 |
72 | /* don't reset again within 30 seconds */ | ||
73 | 74 | ||
74 | #define MESH_INACTIVE 0 | 75 | #define MESH_INACTIVE 0 |
75 | #define MESH_ACTIVE 1 | 76 | #define MESH_ACTIVE 1 |
@@ -84,12 +85,13 @@ | |||
84 | #ifdef pr_fmt | 85 | #ifdef pr_fmt |
85 | #undef pr_fmt | 86 | #undef pr_fmt |
86 | #endif | 87 | #endif |
87 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt /* Append 'batman-adv: ' before | 88 | /* Append 'batman-adv: ' before kernel messages */ |
88 | * kernel messages */ | 89 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
89 | 90 | ||
90 | #define DBG_BATMAN 1 /* all messages related to routing / flooding / | 91 | /* all messages related to routing / flooding / broadcasting / etc */ |
91 | * broadcasting / etc */ | 92 | #define DBG_BATMAN 1 |
92 | #define DBG_ROUTES 2 /* route or hna added / changed / deleted */ | 93 | /* route or tt entry added / changed / deleted */ |
94 | #define DBG_ROUTES 2 | ||
93 | #define DBG_ALL 3 | 95 | #define DBG_ALL 3 |
94 | 96 | ||
95 | 97 | ||
@@ -175,4 +177,6 @@ static inline int compare_eth(void *data1, void *data2) | |||
175 | return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0); | 177 | return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0); |
176 | } | 178 | } |
177 | 179 | ||
180 | #define atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0) | ||
181 | |||
178 | #endif /* _NET_BATMAN_ADV_MAIN_H_ */ | 182 | #endif /* _NET_BATMAN_ADV_MAIN_H_ */ |
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index 0b9133022d2d..40a30bbcd147 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c | |||
@@ -19,8 +19,6 @@ | |||
19 | * | 19 | * |
20 | */ | 20 | */ |
21 | 21 | ||
22 | /* increase the reference counter for this originator */ | ||
23 | |||
24 | #include "main.h" | 22 | #include "main.h" |
25 | #include "originator.h" | 23 | #include "originator.h" |
26 | #include "hash.h" | 24 | #include "hash.h" |
@@ -56,18 +54,25 @@ err: | |||
56 | return 0; | 54 | return 0; |
57 | } | 55 | } |
58 | 56 | ||
59 | static void neigh_node_free_rcu(struct rcu_head *rcu) | 57 | void neigh_node_free_ref(struct neigh_node *neigh_node) |
60 | { | 58 | { |
61 | struct neigh_node *neigh_node; | 59 | if (atomic_dec_and_test(&neigh_node->refcount)) |
62 | 60 | kfree_rcu(neigh_node, rcu); | |
63 | neigh_node = container_of(rcu, struct neigh_node, rcu); | ||
64 | kfree(neigh_node); | ||
65 | } | 61 | } |
66 | 62 | ||
67 | void neigh_node_free_ref(struct neigh_node *neigh_node) | 63 | /* increases the refcounter of a found router */ |
64 | struct neigh_node *orig_node_get_router(struct orig_node *orig_node) | ||
68 | { | 65 | { |
69 | if (atomic_dec_and_test(&neigh_node->refcount)) | 66 | struct neigh_node *router; |
70 | call_rcu(&neigh_node->rcu, neigh_node_free_rcu); | 67 | |
68 | rcu_read_lock(); | ||
69 | router = rcu_dereference(orig_node->router); | ||
70 | |||
71 | if (router && !atomic_inc_not_zero(&router->refcount)) | ||
72 | router = NULL; | ||
73 | |||
74 | rcu_read_unlock(); | ||
75 | return router; | ||
71 | } | 76 | } |
72 | 77 | ||
73 | struct neigh_node *create_neighbor(struct orig_node *orig_node, | 78 | struct neigh_node *create_neighbor(struct orig_node *orig_node, |
@@ -87,6 +92,7 @@ struct neigh_node *create_neighbor(struct orig_node *orig_node, | |||
87 | 92 | ||
88 | INIT_HLIST_NODE(&neigh_node->list); | 93 | INIT_HLIST_NODE(&neigh_node->list); |
89 | INIT_LIST_HEAD(&neigh_node->bonding_list); | 94 | INIT_LIST_HEAD(&neigh_node->bonding_list); |
95 | spin_lock_init(&neigh_node->tq_lock); | ||
90 | 96 | ||
91 | memcpy(neigh_node->addr, neigh, ETH_ALEN); | 97 | memcpy(neigh_node->addr, neigh, ETH_ALEN); |
92 | neigh_node->orig_node = orig_neigh_node; | 98 | neigh_node->orig_node = orig_neigh_node; |
@@ -128,7 +134,7 @@ static void orig_node_free_rcu(struct rcu_head *rcu) | |||
128 | spin_unlock_bh(&orig_node->neigh_list_lock); | 134 | spin_unlock_bh(&orig_node->neigh_list_lock); |
129 | 135 | ||
130 | frag_list_free(&orig_node->frag_list); | 136 | frag_list_free(&orig_node->frag_list); |
131 | hna_global_del_orig(orig_node->bat_priv, orig_node, | 137 | tt_global_del_orig(orig_node->bat_priv, orig_node, |
132 | "originator timed out"); | 138 | "originator timed out"); |
133 | 139 | ||
134 | kfree(orig_node->bcast_own); | 140 | kfree(orig_node->bcast_own); |
@@ -206,7 +212,7 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr) | |||
206 | orig_node->bat_priv = bat_priv; | 212 | orig_node->bat_priv = bat_priv; |
207 | memcpy(orig_node->orig, addr, ETH_ALEN); | 213 | memcpy(orig_node->orig, addr, ETH_ALEN); |
208 | orig_node->router = NULL; | 214 | orig_node->router = NULL; |
209 | orig_node->hna_buff = NULL; | 215 | orig_node->tt_buff = NULL; |
210 | orig_node->bcast_seqno_reset = jiffies - 1 | 216 | orig_node->bcast_seqno_reset = jiffies - 1 |
211 | - msecs_to_jiffies(RESET_PROTECTION_MS); | 217 | - msecs_to_jiffies(RESET_PROTECTION_MS); |
212 | orig_node->batman_seqno_reset = jiffies - 1 | 218 | orig_node->batman_seqno_reset = jiffies - 1 |
@@ -317,8 +323,8 @@ static bool purge_orig_node(struct bat_priv *bat_priv, | |||
317 | &best_neigh_node)) { | 323 | &best_neigh_node)) { |
318 | update_routes(bat_priv, orig_node, | 324 | update_routes(bat_priv, orig_node, |
319 | best_neigh_node, | 325 | best_neigh_node, |
320 | orig_node->hna_buff, | 326 | orig_node->tt_buff, |
321 | orig_node->hna_buff_len); | 327 | orig_node->tt_buff_len); |
322 | } | 328 | } |
323 | } | 329 | } |
324 | 330 | ||
@@ -389,29 +395,34 @@ int orig_seq_print_text(struct seq_file *seq, void *offset) | |||
389 | struct hashtable_t *hash = bat_priv->orig_hash; | 395 | struct hashtable_t *hash = bat_priv->orig_hash; |
390 | struct hlist_node *node, *node_tmp; | 396 | struct hlist_node *node, *node_tmp; |
391 | struct hlist_head *head; | 397 | struct hlist_head *head; |
398 | struct hard_iface *primary_if; | ||
392 | struct orig_node *orig_node; | 399 | struct orig_node *orig_node; |
393 | struct neigh_node *neigh_node; | 400 | struct neigh_node *neigh_node, *neigh_node_tmp; |
394 | int batman_count = 0; | 401 | int batman_count = 0; |
395 | int last_seen_secs; | 402 | int last_seen_secs; |
396 | int last_seen_msecs; | 403 | int last_seen_msecs; |
397 | int i; | 404 | int i, ret = 0; |
405 | |||
406 | primary_if = primary_if_get_selected(bat_priv); | ||
398 | 407 | ||
399 | if ((!bat_priv->primary_if) || | 408 | if (!primary_if) { |
400 | (bat_priv->primary_if->if_status != IF_ACTIVE)) { | 409 | ret = seq_printf(seq, "BATMAN mesh %s disabled - " |
401 | if (!bat_priv->primary_if) | 410 | "please specify interfaces to enable it\n", |
402 | return seq_printf(seq, "BATMAN mesh %s disabled - " | 411 | net_dev->name); |
403 | "please specify interfaces to enable it\n", | 412 | goto out; |
404 | net_dev->name); | 413 | } |
405 | 414 | ||
406 | return seq_printf(seq, "BATMAN mesh %s " | 415 | if (primary_if->if_status != IF_ACTIVE) { |
407 | "disabled - primary interface not active\n", | 416 | ret = seq_printf(seq, "BATMAN mesh %s " |
408 | net_dev->name); | 417 | "disabled - primary interface not active\n", |
418 | net_dev->name); | ||
419 | goto out; | ||
409 | } | 420 | } |
410 | 421 | ||
411 | seq_printf(seq, "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%pM (%s)]\n", | 422 | seq_printf(seq, "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%pM (%s)]\n", |
412 | SOURCE_VERSION, REVISION_VERSION_STR, | 423 | SOURCE_VERSION, REVISION_VERSION_STR, |
413 | bat_priv->primary_if->net_dev->name, | 424 | primary_if->net_dev->name, |
414 | bat_priv->primary_if->net_dev->dev_addr, net_dev->name); | 425 | primary_if->net_dev->dev_addr, net_dev->name); |
415 | seq_printf(seq, " %-15s %s (%s/%i) %17s [%10s]: %20s ...\n", | 426 | seq_printf(seq, " %-15s %s (%s/%i) %17s [%10s]: %20s ...\n", |
416 | "Originator", "last-seen", "#", TQ_MAX_VALUE, "Nexthop", | 427 | "Originator", "last-seen", "#", TQ_MAX_VALUE, "Nexthop", |
417 | "outgoingIF", "Potential nexthops"); | 428 | "outgoingIF", "Potential nexthops"); |
@@ -421,40 +432,47 @@ int orig_seq_print_text(struct seq_file *seq, void *offset) | |||
421 | 432 | ||
422 | rcu_read_lock(); | 433 | rcu_read_lock(); |
423 | hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) { | 434 | hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) { |
424 | if (!orig_node->router) | 435 | neigh_node = orig_node_get_router(orig_node); |
436 | if (!neigh_node) | ||
425 | continue; | 437 | continue; |
426 | 438 | ||
427 | if (orig_node->router->tq_avg == 0) | 439 | if (neigh_node->tq_avg == 0) |
428 | continue; | 440 | goto next; |
429 | 441 | ||
430 | last_seen_secs = jiffies_to_msecs(jiffies - | 442 | last_seen_secs = jiffies_to_msecs(jiffies - |
431 | orig_node->last_valid) / 1000; | 443 | orig_node->last_valid) / 1000; |
432 | last_seen_msecs = jiffies_to_msecs(jiffies - | 444 | last_seen_msecs = jiffies_to_msecs(jiffies - |
433 | orig_node->last_valid) % 1000; | 445 | orig_node->last_valid) % 1000; |
434 | 446 | ||
435 | neigh_node = orig_node->router; | ||
436 | seq_printf(seq, "%pM %4i.%03is (%3i) %pM [%10s]:", | 447 | seq_printf(seq, "%pM %4i.%03is (%3i) %pM [%10s]:", |
437 | orig_node->orig, last_seen_secs, | 448 | orig_node->orig, last_seen_secs, |
438 | last_seen_msecs, neigh_node->tq_avg, | 449 | last_seen_msecs, neigh_node->tq_avg, |
439 | neigh_node->addr, | 450 | neigh_node->addr, |
440 | neigh_node->if_incoming->net_dev->name); | 451 | neigh_node->if_incoming->net_dev->name); |
441 | 452 | ||
442 | hlist_for_each_entry_rcu(neigh_node, node_tmp, | 453 | hlist_for_each_entry_rcu(neigh_node_tmp, node_tmp, |
443 | &orig_node->neigh_list, list) { | 454 | &orig_node->neigh_list, list) { |
444 | seq_printf(seq, " %pM (%3i)", neigh_node->addr, | 455 | seq_printf(seq, " %pM (%3i)", |
445 | neigh_node->tq_avg); | 456 | neigh_node_tmp->addr, |
457 | neigh_node_tmp->tq_avg); | ||
446 | } | 458 | } |
447 | 459 | ||
448 | seq_printf(seq, "\n"); | 460 | seq_printf(seq, "\n"); |
449 | batman_count++; | 461 | batman_count++; |
462 | |||
463 | next: | ||
464 | neigh_node_free_ref(neigh_node); | ||
450 | } | 465 | } |
451 | rcu_read_unlock(); | 466 | rcu_read_unlock(); |
452 | } | 467 | } |
453 | 468 | ||
454 | if ((batman_count == 0)) | 469 | if (batman_count == 0) |
455 | seq_printf(seq, "No batman nodes in range ...\n"); | 470 | seq_printf(seq, "No batman nodes in range ...\n"); |
456 | 471 | ||
457 | return 0; | 472 | out: |
473 | if (primary_if) | ||
474 | hardif_free_ref(primary_if); | ||
475 | return ret; | ||
458 | } | 476 | } |
459 | 477 | ||
460 | static int orig_node_add_if(struct orig_node *orig_node, int max_if_num) | 478 | static int orig_node_add_if(struct orig_node *orig_node, int max_if_num) |
diff --git a/net/batman-adv/originator.h b/net/batman-adv/originator.h index 5cc011057da1..e1d641f27aa9 100644 --- a/net/batman-adv/originator.h +++ b/net/batman-adv/originator.h | |||
@@ -34,6 +34,7 @@ struct neigh_node *create_neighbor(struct orig_node *orig_node, | |||
34 | uint8_t *neigh, | 34 | uint8_t *neigh, |
35 | struct hard_iface *if_incoming); | 35 | struct hard_iface *if_incoming); |
36 | void neigh_node_free_ref(struct neigh_node *neigh_node); | 36 | void neigh_node_free_ref(struct neigh_node *neigh_node); |
37 | struct neigh_node *orig_node_get_router(struct orig_node *orig_node); | ||
37 | int orig_seq_print_text(struct seq_file *seq, void *offset); | 38 | int orig_seq_print_text(struct seq_file *seq, void *offset); |
38 | int orig_hash_add_if(struct hard_iface *hard_iface, int max_if_num); | 39 | int orig_hash_add_if(struct hard_iface *hard_iface, int max_if_num); |
39 | int orig_hash_del_if(struct hard_iface *hard_iface, int max_if_num); | 40 | int orig_hash_del_if(struct hard_iface *hard_iface, int max_if_num); |
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h index e7571879af3f..eda99650e9f8 100644 --- a/net/batman-adv/packet.h +++ b/net/batman-adv/packet.h | |||
@@ -61,7 +61,7 @@ struct batman_packet { | |||
61 | uint8_t orig[6]; | 61 | uint8_t orig[6]; |
62 | uint8_t prev_sender[6]; | 62 | uint8_t prev_sender[6]; |
63 | uint8_t ttl; | 63 | uint8_t ttl; |
64 | uint8_t num_hna; | 64 | uint8_t num_tt; |
65 | uint8_t gw_flags; /* flags related to gateway class */ | 65 | uint8_t gw_flags; /* flags related to gateway class */ |
66 | uint8_t align; | 66 | uint8_t align; |
67 | } __packed; | 67 | } __packed; |
@@ -128,8 +128,7 @@ struct vis_packet { | |||
128 | uint8_t entries; /* number of entries behind this struct */ | 128 | uint8_t entries; /* number of entries behind this struct */ |
129 | uint32_t seqno; /* sequence number */ | 129 | uint32_t seqno; /* sequence number */ |
130 | uint8_t ttl; /* TTL */ | 130 | uint8_t ttl; /* TTL */ |
131 | uint8_t vis_orig[6]; /* originator that informs about its | 131 | uint8_t vis_orig[6]; /* originator that announces its neighbors */ |
132 | * neighbors */ | ||
133 | uint8_t target_orig[6]; /* who should receive this packet */ | 132 | uint8_t target_orig[6]; /* who should receive this packet */ |
134 | uint8_t sender_orig[6]; /* who sent or rebroadcasted this packet */ | 133 | uint8_t sender_orig[6]; /* who sent or rebroadcasted this packet */ |
135 | } __packed; | 134 | } __packed; |
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index c172f5d0e05a..bb1c3ec7e3ff 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c | |||
@@ -64,80 +64,97 @@ void slide_own_bcast_window(struct hard_iface *hard_iface) | |||
64 | } | 64 | } |
65 | } | 65 | } |
66 | 66 | ||
67 | static void update_HNA(struct bat_priv *bat_priv, struct orig_node *orig_node, | 67 | static void update_TT(struct bat_priv *bat_priv, struct orig_node *orig_node, |
68 | unsigned char *hna_buff, int hna_buff_len) | 68 | unsigned char *tt_buff, int tt_buff_len) |
69 | { | 69 | { |
70 | if ((hna_buff_len != orig_node->hna_buff_len) || | 70 | if ((tt_buff_len != orig_node->tt_buff_len) || |
71 | ((hna_buff_len > 0) && | 71 | ((tt_buff_len > 0) && |
72 | (orig_node->hna_buff_len > 0) && | 72 | (orig_node->tt_buff_len > 0) && |
73 | (memcmp(orig_node->hna_buff, hna_buff, hna_buff_len) != 0))) { | 73 | (memcmp(orig_node->tt_buff, tt_buff, tt_buff_len) != 0))) { |
74 | 74 | ||
75 | if (orig_node->hna_buff_len > 0) | 75 | if (orig_node->tt_buff_len > 0) |
76 | hna_global_del_orig(bat_priv, orig_node, | 76 | tt_global_del_orig(bat_priv, orig_node, |
77 | "originator changed hna"); | 77 | "originator changed tt"); |
78 | 78 | ||
79 | if ((hna_buff_len > 0) && (hna_buff)) | 79 | if ((tt_buff_len > 0) && (tt_buff)) |
80 | hna_global_add_orig(bat_priv, orig_node, | 80 | tt_global_add_orig(bat_priv, orig_node, |
81 | hna_buff, hna_buff_len); | 81 | tt_buff, tt_buff_len); |
82 | } | 82 | } |
83 | } | 83 | } |
84 | 84 | ||
85 | static void update_route(struct bat_priv *bat_priv, | 85 | static void update_route(struct bat_priv *bat_priv, |
86 | struct orig_node *orig_node, | 86 | struct orig_node *orig_node, |
87 | struct neigh_node *neigh_node, | 87 | struct neigh_node *neigh_node, |
88 | unsigned char *hna_buff, int hna_buff_len) | 88 | unsigned char *tt_buff, int tt_buff_len) |
89 | { | 89 | { |
90 | struct neigh_node *neigh_node_tmp; | 90 | struct neigh_node *curr_router; |
91 | |||
92 | curr_router = orig_node_get_router(orig_node); | ||
91 | 93 | ||
92 | /* route deleted */ | 94 | /* route deleted */ |
93 | if ((orig_node->router) && (!neigh_node)) { | 95 | if ((curr_router) && (!neigh_node)) { |
94 | 96 | ||
95 | bat_dbg(DBG_ROUTES, bat_priv, "Deleting route towards: %pM\n", | 97 | bat_dbg(DBG_ROUTES, bat_priv, "Deleting route towards: %pM\n", |
96 | orig_node->orig); | 98 | orig_node->orig); |
97 | hna_global_del_orig(bat_priv, orig_node, | 99 | tt_global_del_orig(bat_priv, orig_node, |
98 | "originator timed out"); | 100 | "originator timed out"); |
99 | 101 | ||
100 | /* route added */ | 102 | /* route added */ |
101 | } else if ((!orig_node->router) && (neigh_node)) { | 103 | } else if ((!curr_router) && (neigh_node)) { |
102 | 104 | ||
103 | bat_dbg(DBG_ROUTES, bat_priv, | 105 | bat_dbg(DBG_ROUTES, bat_priv, |
104 | "Adding route towards: %pM (via %pM)\n", | 106 | "Adding route towards: %pM (via %pM)\n", |
105 | orig_node->orig, neigh_node->addr); | 107 | orig_node->orig, neigh_node->addr); |
106 | hna_global_add_orig(bat_priv, orig_node, | 108 | tt_global_add_orig(bat_priv, orig_node, |
107 | hna_buff, hna_buff_len); | 109 | tt_buff, tt_buff_len); |
108 | 110 | ||
109 | /* route changed */ | 111 | /* route changed */ |
110 | } else { | 112 | } else { |
111 | bat_dbg(DBG_ROUTES, bat_priv, | 113 | bat_dbg(DBG_ROUTES, bat_priv, |
112 | "Changing route towards: %pM " | 114 | "Changing route towards: %pM " |
113 | "(now via %pM - was via %pM)\n", | 115 | "(now via %pM - was via %pM)\n", |
114 | orig_node->orig, neigh_node->addr, | 116 | orig_node->orig, neigh_node->addr, |
115 | orig_node->router->addr); | 117 | curr_router->addr); |
116 | } | 118 | } |
117 | 119 | ||
120 | if (curr_router) | ||
121 | neigh_node_free_ref(curr_router); | ||
122 | |||
123 | /* increase refcount of new best neighbor */ | ||
118 | if (neigh_node && !atomic_inc_not_zero(&neigh_node->refcount)) | 124 | if (neigh_node && !atomic_inc_not_zero(&neigh_node->refcount)) |
119 | neigh_node = NULL; | 125 | neigh_node = NULL; |
120 | neigh_node_tmp = orig_node->router; | 126 | |
121 | orig_node->router = neigh_node; | 127 | spin_lock_bh(&orig_node->neigh_list_lock); |
122 | if (neigh_node_tmp) | 128 | rcu_assign_pointer(orig_node->router, neigh_node); |
123 | neigh_node_free_ref(neigh_node_tmp); | 129 | spin_unlock_bh(&orig_node->neigh_list_lock); |
130 | |||
131 | /* decrease refcount of previous best neighbor */ | ||
132 | if (curr_router) | ||
133 | neigh_node_free_ref(curr_router); | ||
124 | } | 134 | } |
125 | 135 | ||
126 | 136 | ||
127 | void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node, | 137 | void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node, |
128 | struct neigh_node *neigh_node, unsigned char *hna_buff, | 138 | struct neigh_node *neigh_node, unsigned char *tt_buff, |
129 | int hna_buff_len) | 139 | int tt_buff_len) |
130 | { | 140 | { |
141 | struct neigh_node *router = NULL; | ||
131 | 142 | ||
132 | if (!orig_node) | 143 | if (!orig_node) |
133 | return; | 144 | goto out; |
145 | |||
146 | router = orig_node_get_router(orig_node); | ||
134 | 147 | ||
135 | if (orig_node->router != neigh_node) | 148 | if (router != neigh_node) |
136 | update_route(bat_priv, orig_node, neigh_node, | 149 | update_route(bat_priv, orig_node, neigh_node, |
137 | hna_buff, hna_buff_len); | 150 | tt_buff, tt_buff_len); |
138 | /* may be just HNA changed */ | 151 | /* may be just TT changed */ |
139 | else | 152 | else |
140 | update_HNA(bat_priv, orig_node, hna_buff, hna_buff_len); | 153 | update_TT(bat_priv, orig_node, tt_buff, tt_buff_len); |
154 | |||
155 | out: | ||
156 | if (router) | ||
157 | neigh_node_free_ref(router); | ||
141 | } | 158 | } |
142 | 159 | ||
143 | static int is_bidirectional_neigh(struct orig_node *orig_node, | 160 | static int is_bidirectional_neigh(struct orig_node *orig_node, |
@@ -152,65 +169,41 @@ static int is_bidirectional_neigh(struct orig_node *orig_node, | |||
152 | uint8_t orig_eq_count, neigh_rq_count, tq_own; | 169 | uint8_t orig_eq_count, neigh_rq_count, tq_own; |
153 | int tq_asym_penalty, ret = 0; | 170 | int tq_asym_penalty, ret = 0; |
154 | 171 | ||
155 | if (orig_node == orig_neigh_node) { | 172 | /* find corresponding one hop neighbor */ |
156 | rcu_read_lock(); | 173 | rcu_read_lock(); |
157 | hlist_for_each_entry_rcu(tmp_neigh_node, node, | 174 | hlist_for_each_entry_rcu(tmp_neigh_node, node, |
158 | &orig_node->neigh_list, list) { | 175 | &orig_neigh_node->neigh_list, list) { |
159 | |||
160 | if (!compare_eth(tmp_neigh_node->addr, | ||
161 | orig_neigh_node->orig)) | ||
162 | continue; | ||
163 | |||
164 | if (tmp_neigh_node->if_incoming != if_incoming) | ||
165 | continue; | ||
166 | |||
167 | if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) | ||
168 | continue; | ||
169 | |||
170 | neigh_node = tmp_neigh_node; | ||
171 | } | ||
172 | rcu_read_unlock(); | ||
173 | 176 | ||
174 | if (!neigh_node) | 177 | if (!compare_eth(tmp_neigh_node->addr, orig_neigh_node->orig)) |
175 | neigh_node = create_neighbor(orig_node, | 178 | continue; |
176 | orig_neigh_node, | ||
177 | orig_neigh_node->orig, | ||
178 | if_incoming); | ||
179 | if (!neigh_node) | ||
180 | goto out; | ||
181 | 179 | ||
182 | neigh_node->last_valid = jiffies; | 180 | if (tmp_neigh_node->if_incoming != if_incoming) |
183 | } else { | 181 | continue; |
184 | /* find packet count of corresponding one hop neighbor */ | ||
185 | rcu_read_lock(); | ||
186 | hlist_for_each_entry_rcu(tmp_neigh_node, node, | ||
187 | &orig_neigh_node->neigh_list, list) { | ||
188 | 182 | ||
189 | if (!compare_eth(tmp_neigh_node->addr, | 183 | if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) |
190 | orig_neigh_node->orig)) | 184 | continue; |
191 | continue; | ||
192 | 185 | ||
193 | if (tmp_neigh_node->if_incoming != if_incoming) | 186 | neigh_node = tmp_neigh_node; |
194 | continue; | 187 | break; |
188 | } | ||
189 | rcu_read_unlock(); | ||
195 | 190 | ||
196 | if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) | 191 | if (!neigh_node) |
197 | continue; | 192 | neigh_node = create_neighbor(orig_neigh_node, |
193 | orig_neigh_node, | ||
194 | orig_neigh_node->orig, | ||
195 | if_incoming); | ||
198 | 196 | ||
199 | neigh_node = tmp_neigh_node; | 197 | if (!neigh_node) |
200 | } | 198 | goto out; |
201 | rcu_read_unlock(); | ||
202 | 199 | ||
203 | if (!neigh_node) | 200 | /* if orig_node is direct neighbour update neigh_node last_valid */ |
204 | neigh_node = create_neighbor(orig_neigh_node, | 201 | if (orig_node == orig_neigh_node) |
205 | orig_neigh_node, | 202 | neigh_node->last_valid = jiffies; |
206 | orig_neigh_node->orig, | ||
207 | if_incoming); | ||
208 | if (!neigh_node) | ||
209 | goto out; | ||
210 | } | ||
211 | 203 | ||
212 | orig_node->last_valid = jiffies; | 204 | orig_node->last_valid = jiffies; |
213 | 205 | ||
206 | /* find packet count of corresponding one hop neighbor */ | ||
214 | spin_lock_bh(&orig_node->ogm_cnt_lock); | 207 | spin_lock_bh(&orig_node->ogm_cnt_lock); |
215 | orig_eq_count = orig_neigh_node->bcast_own_sum[if_incoming->if_num]; | 208 | orig_eq_count = orig_neigh_node->bcast_own_sum[if_incoming->if_num]; |
216 | neigh_rq_count = neigh_node->real_packet_count; | 209 | neigh_rq_count = neigh_node->real_packet_count; |
@@ -288,8 +281,8 @@ static void bonding_candidate_add(struct orig_node *orig_node, | |||
288 | struct neigh_node *neigh_node) | 281 | struct neigh_node *neigh_node) |
289 | { | 282 | { |
290 | struct hlist_node *node; | 283 | struct hlist_node *node; |
291 | struct neigh_node *tmp_neigh_node; | 284 | struct neigh_node *tmp_neigh_node, *router = NULL; |
292 | uint8_t best_tq, interference_candidate = 0; | 285 | uint8_t interference_candidate = 0; |
293 | 286 | ||
294 | spin_lock_bh(&orig_node->neigh_list_lock); | 287 | spin_lock_bh(&orig_node->neigh_list_lock); |
295 | 288 | ||
@@ -298,13 +291,12 @@ static void bonding_candidate_add(struct orig_node *orig_node, | |||
298 | neigh_node->orig_node->primary_addr)) | 291 | neigh_node->orig_node->primary_addr)) |
299 | goto candidate_del; | 292 | goto candidate_del; |
300 | 293 | ||
301 | if (!orig_node->router) | 294 | router = orig_node_get_router(orig_node); |
295 | if (!router) | ||
302 | goto candidate_del; | 296 | goto candidate_del; |
303 | 297 | ||
304 | best_tq = orig_node->router->tq_avg; | ||
305 | |||
306 | /* ... and is good enough to be considered */ | 298 | /* ... and is good enough to be considered */ |
307 | if (neigh_node->tq_avg < best_tq - BONDING_TQ_THRESHOLD) | 299 | if (neigh_node->tq_avg < router->tq_avg - BONDING_TQ_THRESHOLD) |
308 | goto candidate_del; | 300 | goto candidate_del; |
309 | 301 | ||
310 | /** | 302 | /** |
@@ -350,7 +342,9 @@ candidate_del: | |||
350 | 342 | ||
351 | out: | 343 | out: |
352 | spin_unlock_bh(&orig_node->neigh_list_lock); | 344 | spin_unlock_bh(&orig_node->neigh_list_lock); |
353 | return; | 345 | |
346 | if (router) | ||
347 | neigh_node_free_ref(router); | ||
354 | } | 348 | } |
355 | 349 | ||
356 | /* copy primary address for bonding */ | 350 | /* copy primary address for bonding */ |
@@ -369,13 +363,14 @@ static void update_orig(struct bat_priv *bat_priv, | |||
369 | struct ethhdr *ethhdr, | 363 | struct ethhdr *ethhdr, |
370 | struct batman_packet *batman_packet, | 364 | struct batman_packet *batman_packet, |
371 | struct hard_iface *if_incoming, | 365 | struct hard_iface *if_incoming, |
372 | unsigned char *hna_buff, int hna_buff_len, | 366 | unsigned char *tt_buff, int tt_buff_len, |
373 | char is_duplicate) | 367 | char is_duplicate) |
374 | { | 368 | { |
375 | struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL; | 369 | struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL; |
370 | struct neigh_node *router = NULL; | ||
376 | struct orig_node *orig_node_tmp; | 371 | struct orig_node *orig_node_tmp; |
377 | struct hlist_node *node; | 372 | struct hlist_node *node; |
378 | int tmp_hna_buff_len; | 373 | int tmp_tt_buff_len; |
379 | uint8_t bcast_own_sum_orig, bcast_own_sum_neigh; | 374 | uint8_t bcast_own_sum_orig, bcast_own_sum_neigh; |
380 | 375 | ||
381 | bat_dbg(DBG_BATMAN, bat_priv, "update_originator(): " | 376 | bat_dbg(DBG_BATMAN, bat_priv, "update_originator(): " |
@@ -396,10 +391,12 @@ static void update_orig(struct bat_priv *bat_priv, | |||
396 | if (is_duplicate) | 391 | if (is_duplicate) |
397 | continue; | 392 | continue; |
398 | 393 | ||
394 | spin_lock_bh(&tmp_neigh_node->tq_lock); | ||
399 | ring_buffer_set(tmp_neigh_node->tq_recv, | 395 | ring_buffer_set(tmp_neigh_node->tq_recv, |
400 | &tmp_neigh_node->tq_index, 0); | 396 | &tmp_neigh_node->tq_index, 0); |
401 | tmp_neigh_node->tq_avg = | 397 | tmp_neigh_node->tq_avg = |
402 | ring_buffer_avg(tmp_neigh_node->tq_recv); | 398 | ring_buffer_avg(tmp_neigh_node->tq_recv); |
399 | spin_unlock_bh(&tmp_neigh_node->tq_lock); | ||
403 | } | 400 | } |
404 | 401 | ||
405 | if (!neigh_node) { | 402 | if (!neigh_node) { |
@@ -424,10 +421,12 @@ static void update_orig(struct bat_priv *bat_priv, | |||
424 | orig_node->flags = batman_packet->flags; | 421 | orig_node->flags = batman_packet->flags; |
425 | neigh_node->last_valid = jiffies; | 422 | neigh_node->last_valid = jiffies; |
426 | 423 | ||
424 | spin_lock_bh(&neigh_node->tq_lock); | ||
427 | ring_buffer_set(neigh_node->tq_recv, | 425 | ring_buffer_set(neigh_node->tq_recv, |
428 | &neigh_node->tq_index, | 426 | &neigh_node->tq_index, |
429 | batman_packet->tq); | 427 | batman_packet->tq); |
430 | neigh_node->tq_avg = ring_buffer_avg(neigh_node->tq_recv); | 428 | neigh_node->tq_avg = ring_buffer_avg(neigh_node->tq_recv); |
429 | spin_unlock_bh(&neigh_node->tq_lock); | ||
431 | 430 | ||
432 | if (!is_duplicate) { | 431 | if (!is_duplicate) { |
433 | orig_node->last_ttl = batman_packet->ttl; | 432 | orig_node->last_ttl = batman_packet->ttl; |
@@ -436,24 +435,23 @@ static void update_orig(struct bat_priv *bat_priv, | |||
436 | 435 | ||
437 | bonding_candidate_add(orig_node, neigh_node); | 436 | bonding_candidate_add(orig_node, neigh_node); |
438 | 437 | ||
439 | tmp_hna_buff_len = (hna_buff_len > batman_packet->num_hna * ETH_ALEN ? | 438 | tmp_tt_buff_len = (tt_buff_len > batman_packet->num_tt * ETH_ALEN ? |
440 | batman_packet->num_hna * ETH_ALEN : hna_buff_len); | 439 | batman_packet->num_tt * ETH_ALEN : tt_buff_len); |
441 | 440 | ||
442 | /* if this neighbor already is our next hop there is nothing | 441 | /* if this neighbor already is our next hop there is nothing |
443 | * to change */ | 442 | * to change */ |
444 | if (orig_node->router == neigh_node) | 443 | router = orig_node_get_router(orig_node); |
445 | goto update_hna; | 444 | if (router == neigh_node) |
445 | goto update_tt; | ||
446 | 446 | ||
447 | /* if this neighbor does not offer a better TQ we won't consider it */ | 447 | /* if this neighbor does not offer a better TQ we won't consider it */ |
448 | if ((orig_node->router) && | 448 | if (router && (router->tq_avg > neigh_node->tq_avg)) |
449 | (orig_node->router->tq_avg > neigh_node->tq_avg)) | 449 | goto update_tt; |
450 | goto update_hna; | ||
451 | 450 | ||
452 | /* if the TQ is the same and the link not more symetric we | 451 | /* if the TQ is the same and the link not more symetric we |
453 | * won't consider it either */ | 452 | * won't consider it either */ |
454 | if ((orig_node->router) && | 453 | if (router && (neigh_node->tq_avg == router->tq_avg)) { |
455 | (neigh_node->tq_avg == orig_node->router->tq_avg)) { | 454 | orig_node_tmp = router->orig_node; |
456 | orig_node_tmp = orig_node->router->orig_node; | ||
457 | spin_lock_bh(&orig_node_tmp->ogm_cnt_lock); | 455 | spin_lock_bh(&orig_node_tmp->ogm_cnt_lock); |
458 | bcast_own_sum_orig = | 456 | bcast_own_sum_orig = |
459 | orig_node_tmp->bcast_own_sum[if_incoming->if_num]; | 457 | orig_node_tmp->bcast_own_sum[if_incoming->if_num]; |
@@ -466,16 +464,16 @@ static void update_orig(struct bat_priv *bat_priv, | |||
466 | spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock); | 464 | spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock); |
467 | 465 | ||
468 | if (bcast_own_sum_orig >= bcast_own_sum_neigh) | 466 | if (bcast_own_sum_orig >= bcast_own_sum_neigh) |
469 | goto update_hna; | 467 | goto update_tt; |
470 | } | 468 | } |
471 | 469 | ||
472 | update_routes(bat_priv, orig_node, neigh_node, | 470 | update_routes(bat_priv, orig_node, neigh_node, |
473 | hna_buff, tmp_hna_buff_len); | 471 | tt_buff, tmp_tt_buff_len); |
474 | goto update_gw; | 472 | goto update_gw; |
475 | 473 | ||
476 | update_hna: | 474 | update_tt: |
477 | update_routes(bat_priv, orig_node, orig_node->router, | 475 | update_routes(bat_priv, orig_node, router, |
478 | hna_buff, tmp_hna_buff_len); | 476 | tt_buff, tmp_tt_buff_len); |
479 | 477 | ||
480 | update_gw: | 478 | update_gw: |
481 | if (orig_node->gw_flags != batman_packet->gw_flags) | 479 | if (orig_node->gw_flags != batman_packet->gw_flags) |
@@ -496,6 +494,8 @@ unlock: | |||
496 | out: | 494 | out: |
497 | if (neigh_node) | 495 | if (neigh_node) |
498 | neigh_node_free_ref(neigh_node); | 496 | neigh_node_free_ref(neigh_node); |
497 | if (router) | ||
498 | neigh_node_free_ref(router); | ||
499 | } | 499 | } |
500 | 500 | ||
501 | /* checks whether the host restarted and is in the protection time. | 501 | /* checks whether the host restarted and is in the protection time. |
@@ -597,12 +597,14 @@ out: | |||
597 | 597 | ||
598 | void receive_bat_packet(struct ethhdr *ethhdr, | 598 | void receive_bat_packet(struct ethhdr *ethhdr, |
599 | struct batman_packet *batman_packet, | 599 | struct batman_packet *batman_packet, |
600 | unsigned char *hna_buff, int hna_buff_len, | 600 | unsigned char *tt_buff, int tt_buff_len, |
601 | struct hard_iface *if_incoming) | 601 | struct hard_iface *if_incoming) |
602 | { | 602 | { |
603 | struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); | 603 | struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); |
604 | struct hard_iface *hard_iface; | 604 | struct hard_iface *hard_iface; |
605 | struct orig_node *orig_neigh_node, *orig_node; | 605 | struct orig_node *orig_neigh_node, *orig_node; |
606 | struct neigh_node *router = NULL, *router_router = NULL; | ||
607 | struct neigh_node *orig_neigh_router = NULL; | ||
606 | char has_directlink_flag; | 608 | char has_directlink_flag; |
607 | char is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0; | 609 | char is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0; |
608 | char is_broadcast = 0, is_bidirectional, is_single_hop_neigh; | 610 | char is_broadcast = 0, is_bidirectional, is_single_hop_neigh; |
@@ -747,14 +749,15 @@ void receive_bat_packet(struct ethhdr *ethhdr, | |||
747 | goto out; | 749 | goto out; |
748 | } | 750 | } |
749 | 751 | ||
752 | router = orig_node_get_router(orig_node); | ||
753 | if (router) | ||
754 | router_router = orig_node_get_router(router->orig_node); | ||
755 | |||
750 | /* avoid temporary routing loops */ | 756 | /* avoid temporary routing loops */ |
751 | if ((orig_node->router) && | 757 | if (router && router_router && |
752 | (orig_node->router->orig_node->router) && | 758 | (compare_eth(router->addr, batman_packet->prev_sender)) && |
753 | (compare_eth(orig_node->router->addr, | ||
754 | batman_packet->prev_sender)) && | ||
755 | !(compare_eth(batman_packet->orig, batman_packet->prev_sender)) && | 759 | !(compare_eth(batman_packet->orig, batman_packet->prev_sender)) && |
756 | (compare_eth(orig_node->router->addr, | 760 | (compare_eth(router->addr, router_router->addr))) { |
757 | orig_node->router->orig_node->router->addr))) { | ||
758 | bat_dbg(DBG_BATMAN, bat_priv, | 761 | bat_dbg(DBG_BATMAN, bat_priv, |
759 | "Drop packet: ignoring all rebroadcast packets that " | 762 | "Drop packet: ignoring all rebroadcast packets that " |
760 | "may make me loop (sender: %pM)\n", ethhdr->h_source); | 763 | "may make me loop (sender: %pM)\n", ethhdr->h_source); |
@@ -769,9 +772,11 @@ void receive_bat_packet(struct ethhdr *ethhdr, | |||
769 | if (!orig_neigh_node) | 772 | if (!orig_neigh_node) |
770 | goto out; | 773 | goto out; |
771 | 774 | ||
775 | orig_neigh_router = orig_node_get_router(orig_neigh_node); | ||
776 | |||
772 | /* drop packet if sender is not a direct neighbor and if we | 777 | /* drop packet if sender is not a direct neighbor and if we |
773 | * don't route towards it */ | 778 | * don't route towards it */ |
774 | if (!is_single_hop_neigh && (!orig_neigh_node->router)) { | 779 | if (!is_single_hop_neigh && (!orig_neigh_router)) { |
775 | bat_dbg(DBG_BATMAN, bat_priv, | 780 | bat_dbg(DBG_BATMAN, bat_priv, |
776 | "Drop packet: OGM via unknown neighbor!\n"); | 781 | "Drop packet: OGM via unknown neighbor!\n"); |
777 | goto out_neigh; | 782 | goto out_neigh; |
@@ -789,14 +794,14 @@ void receive_bat_packet(struct ethhdr *ethhdr, | |||
789 | ((orig_node->last_real_seqno == batman_packet->seqno) && | 794 | ((orig_node->last_real_seqno == batman_packet->seqno) && |
790 | (orig_node->last_ttl - 3 <= batman_packet->ttl)))) | 795 | (orig_node->last_ttl - 3 <= batman_packet->ttl)))) |
791 | update_orig(bat_priv, orig_node, ethhdr, batman_packet, | 796 | update_orig(bat_priv, orig_node, ethhdr, batman_packet, |
792 | if_incoming, hna_buff, hna_buff_len, is_duplicate); | 797 | if_incoming, tt_buff, tt_buff_len, is_duplicate); |
793 | 798 | ||
794 | /* is single hop (direct) neighbor */ | 799 | /* is single hop (direct) neighbor */ |
795 | if (is_single_hop_neigh) { | 800 | if (is_single_hop_neigh) { |
796 | 801 | ||
797 | /* mark direct link on incoming interface */ | 802 | /* mark direct link on incoming interface */ |
798 | schedule_forward_packet(orig_node, ethhdr, batman_packet, | 803 | schedule_forward_packet(orig_node, ethhdr, batman_packet, |
799 | 1, hna_buff_len, if_incoming); | 804 | 1, tt_buff_len, if_incoming); |
800 | 805 | ||
801 | bat_dbg(DBG_BATMAN, bat_priv, "Forwarding packet: " | 806 | bat_dbg(DBG_BATMAN, bat_priv, "Forwarding packet: " |
802 | "rebroadcast neighbor packet with direct link flag\n"); | 807 | "rebroadcast neighbor packet with direct link flag\n"); |
@@ -819,12 +824,19 @@ void receive_bat_packet(struct ethhdr *ethhdr, | |||
819 | bat_dbg(DBG_BATMAN, bat_priv, | 824 | bat_dbg(DBG_BATMAN, bat_priv, |
820 | "Forwarding packet: rebroadcast originator packet\n"); | 825 | "Forwarding packet: rebroadcast originator packet\n"); |
821 | schedule_forward_packet(orig_node, ethhdr, batman_packet, | 826 | schedule_forward_packet(orig_node, ethhdr, batman_packet, |
822 | 0, hna_buff_len, if_incoming); | 827 | 0, tt_buff_len, if_incoming); |
823 | 828 | ||
824 | out_neigh: | 829 | out_neigh: |
825 | if ((orig_neigh_node) && (!is_single_hop_neigh)) | 830 | if ((orig_neigh_node) && (!is_single_hop_neigh)) |
826 | orig_node_free_ref(orig_neigh_node); | 831 | orig_node_free_ref(orig_neigh_node); |
827 | out: | 832 | out: |
833 | if (router) | ||
834 | neigh_node_free_ref(router); | ||
835 | if (router_router) | ||
836 | neigh_node_free_ref(router_router); | ||
837 | if (orig_neigh_router) | ||
838 | neigh_node_free_ref(orig_neigh_router); | ||
839 | |||
828 | orig_node_free_ref(orig_node); | 840 | orig_node_free_ref(orig_node); |
829 | } | 841 | } |
830 | 842 | ||
@@ -868,8 +880,9 @@ int recv_bat_packet(struct sk_buff *skb, struct hard_iface *hard_iface) | |||
868 | static int recv_my_icmp_packet(struct bat_priv *bat_priv, | 880 | static int recv_my_icmp_packet(struct bat_priv *bat_priv, |
869 | struct sk_buff *skb, size_t icmp_len) | 881 | struct sk_buff *skb, size_t icmp_len) |
870 | { | 882 | { |
883 | struct hard_iface *primary_if = NULL; | ||
871 | struct orig_node *orig_node = NULL; | 884 | struct orig_node *orig_node = NULL; |
872 | struct neigh_node *neigh_node = NULL; | 885 | struct neigh_node *router = NULL; |
873 | struct icmp_packet_rr *icmp_packet; | 886 | struct icmp_packet_rr *icmp_packet; |
874 | int ret = NET_RX_DROP; | 887 | int ret = NET_RX_DROP; |
875 | 888 | ||
@@ -881,28 +894,19 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv, | |||
881 | goto out; | 894 | goto out; |
882 | } | 895 | } |
883 | 896 | ||
884 | if (!bat_priv->primary_if) | 897 | primary_if = primary_if_get_selected(bat_priv); |
898 | if (!primary_if) | ||
885 | goto out; | 899 | goto out; |
886 | 900 | ||
887 | /* answer echo request (ping) */ | 901 | /* answer echo request (ping) */ |
888 | /* get routing information */ | 902 | /* get routing information */ |
889 | rcu_read_lock(); | ||
890 | orig_node = orig_hash_find(bat_priv, icmp_packet->orig); | 903 | orig_node = orig_hash_find(bat_priv, icmp_packet->orig); |
891 | |||
892 | if (!orig_node) | 904 | if (!orig_node) |
893 | goto unlock; | 905 | goto out; |
894 | |||
895 | neigh_node = orig_node->router; | ||
896 | |||
897 | if (!neigh_node) | ||
898 | goto unlock; | ||
899 | |||
900 | if (!atomic_inc_not_zero(&neigh_node->refcount)) { | ||
901 | neigh_node = NULL; | ||
902 | goto unlock; | ||
903 | } | ||
904 | 906 | ||
905 | rcu_read_unlock(); | 907 | router = orig_node_get_router(orig_node); |
908 | if (!router) | ||
909 | goto out; | ||
906 | 910 | ||
907 | /* create a copy of the skb, if needed, to modify it. */ | 911 | /* create a copy of the skb, if needed, to modify it. */ |
908 | if (skb_cow(skb, sizeof(struct ethhdr)) < 0) | 912 | if (skb_cow(skb, sizeof(struct ethhdr)) < 0) |
@@ -911,20 +915,18 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv, | |||
911 | icmp_packet = (struct icmp_packet_rr *)skb->data; | 915 | icmp_packet = (struct icmp_packet_rr *)skb->data; |
912 | 916 | ||
913 | memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); | 917 | memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); |
914 | memcpy(icmp_packet->orig, | 918 | memcpy(icmp_packet->orig, primary_if->net_dev->dev_addr, ETH_ALEN); |
915 | bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); | ||
916 | icmp_packet->msg_type = ECHO_REPLY; | 919 | icmp_packet->msg_type = ECHO_REPLY; |
917 | icmp_packet->ttl = TTL; | 920 | icmp_packet->ttl = TTL; |
918 | 921 | ||
919 | send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); | 922 | send_skb_packet(skb, router->if_incoming, router->addr); |
920 | ret = NET_RX_SUCCESS; | 923 | ret = NET_RX_SUCCESS; |
921 | goto out; | ||
922 | 924 | ||
923 | unlock: | ||
924 | rcu_read_unlock(); | ||
925 | out: | 925 | out: |
926 | if (neigh_node) | 926 | if (primary_if) |
927 | neigh_node_free_ref(neigh_node); | 927 | hardif_free_ref(primary_if); |
928 | if (router) | ||
929 | neigh_node_free_ref(router); | ||
928 | if (orig_node) | 930 | if (orig_node) |
929 | orig_node_free_ref(orig_node); | 931 | orig_node_free_ref(orig_node); |
930 | return ret; | 932 | return ret; |
@@ -933,8 +935,9 @@ out: | |||
933 | static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv, | 935 | static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv, |
934 | struct sk_buff *skb) | 936 | struct sk_buff *skb) |
935 | { | 937 | { |
938 | struct hard_iface *primary_if = NULL; | ||
936 | struct orig_node *orig_node = NULL; | 939 | struct orig_node *orig_node = NULL; |
937 | struct neigh_node *neigh_node = NULL; | 940 | struct neigh_node *router = NULL; |
938 | struct icmp_packet *icmp_packet; | 941 | struct icmp_packet *icmp_packet; |
939 | int ret = NET_RX_DROP; | 942 | int ret = NET_RX_DROP; |
940 | 943 | ||
@@ -948,27 +951,18 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv, | |||
948 | goto out; | 951 | goto out; |
949 | } | 952 | } |
950 | 953 | ||
951 | if (!bat_priv->primary_if) | 954 | primary_if = primary_if_get_selected(bat_priv); |
955 | if (!primary_if) | ||
952 | goto out; | 956 | goto out; |
953 | 957 | ||
954 | /* get routing information */ | 958 | /* get routing information */ |
955 | rcu_read_lock(); | ||
956 | orig_node = orig_hash_find(bat_priv, icmp_packet->orig); | 959 | orig_node = orig_hash_find(bat_priv, icmp_packet->orig); |
957 | |||
958 | if (!orig_node) | 960 | if (!orig_node) |
959 | goto unlock; | 961 | goto out; |
960 | |||
961 | neigh_node = orig_node->router; | ||
962 | |||
963 | if (!neigh_node) | ||
964 | goto unlock; | ||
965 | |||
966 | if (!atomic_inc_not_zero(&neigh_node->refcount)) { | ||
967 | neigh_node = NULL; | ||
968 | goto unlock; | ||
969 | } | ||
970 | 962 | ||
971 | rcu_read_unlock(); | 963 | router = orig_node_get_router(orig_node); |
964 | if (!router) | ||
965 | goto out; | ||
972 | 966 | ||
973 | /* create a copy of the skb, if needed, to modify it. */ | 967 | /* create a copy of the skb, if needed, to modify it. */ |
974 | if (skb_cow(skb, sizeof(struct ethhdr)) < 0) | 968 | if (skb_cow(skb, sizeof(struct ethhdr)) < 0) |
@@ -977,20 +971,18 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv, | |||
977 | icmp_packet = (struct icmp_packet *)skb->data; | 971 | icmp_packet = (struct icmp_packet *)skb->data; |
978 | 972 | ||
979 | memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); | 973 | memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); |
980 | memcpy(icmp_packet->orig, | 974 | memcpy(icmp_packet->orig, primary_if->net_dev->dev_addr, ETH_ALEN); |
981 | bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); | ||
982 | icmp_packet->msg_type = TTL_EXCEEDED; | 975 | icmp_packet->msg_type = TTL_EXCEEDED; |
983 | icmp_packet->ttl = TTL; | 976 | icmp_packet->ttl = TTL; |
984 | 977 | ||
985 | send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); | 978 | send_skb_packet(skb, router->if_incoming, router->addr); |
986 | ret = NET_RX_SUCCESS; | 979 | ret = NET_RX_SUCCESS; |
987 | goto out; | ||
988 | 980 | ||
989 | unlock: | ||
990 | rcu_read_unlock(); | ||
991 | out: | 981 | out: |
992 | if (neigh_node) | 982 | if (primary_if) |
993 | neigh_node_free_ref(neigh_node); | 983 | hardif_free_ref(primary_if); |
984 | if (router) | ||
985 | neigh_node_free_ref(router); | ||
994 | if (orig_node) | 986 | if (orig_node) |
995 | orig_node_free_ref(orig_node); | 987 | orig_node_free_ref(orig_node); |
996 | return ret; | 988 | return ret; |
@@ -1003,7 +995,7 @@ int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if) | |||
1003 | struct icmp_packet_rr *icmp_packet; | 995 | struct icmp_packet_rr *icmp_packet; |
1004 | struct ethhdr *ethhdr; | 996 | struct ethhdr *ethhdr; |
1005 | struct orig_node *orig_node = NULL; | 997 | struct orig_node *orig_node = NULL; |
1006 | struct neigh_node *neigh_node = NULL; | 998 | struct neigh_node *router = NULL; |
1007 | int hdr_size = sizeof(struct icmp_packet); | 999 | int hdr_size = sizeof(struct icmp_packet); |
1008 | int ret = NET_RX_DROP; | 1000 | int ret = NET_RX_DROP; |
1009 | 1001 | ||
@@ -1050,23 +1042,13 @@ int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if) | |||
1050 | return recv_icmp_ttl_exceeded(bat_priv, skb); | 1042 | return recv_icmp_ttl_exceeded(bat_priv, skb); |
1051 | 1043 | ||
1052 | /* get routing information */ | 1044 | /* get routing information */ |
1053 | rcu_read_lock(); | ||
1054 | orig_node = orig_hash_find(bat_priv, icmp_packet->dst); | 1045 | orig_node = orig_hash_find(bat_priv, icmp_packet->dst); |
1055 | |||
1056 | if (!orig_node) | 1046 | if (!orig_node) |
1057 | goto unlock; | 1047 | goto out; |
1058 | |||
1059 | neigh_node = orig_node->router; | ||
1060 | |||
1061 | if (!neigh_node) | ||
1062 | goto unlock; | ||
1063 | |||
1064 | if (!atomic_inc_not_zero(&neigh_node->refcount)) { | ||
1065 | neigh_node = NULL; | ||
1066 | goto unlock; | ||
1067 | } | ||
1068 | 1048 | ||
1069 | rcu_read_unlock(); | 1049 | router = orig_node_get_router(orig_node); |
1050 | if (!router) | ||
1051 | goto out; | ||
1070 | 1052 | ||
1071 | /* create a copy of the skb, if needed, to modify it. */ | 1053 | /* create a copy of the skb, if needed, to modify it. */ |
1072 | if (skb_cow(skb, sizeof(struct ethhdr)) < 0) | 1054 | if (skb_cow(skb, sizeof(struct ethhdr)) < 0) |
@@ -1078,20 +1060,117 @@ int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if) | |||
1078 | icmp_packet->ttl--; | 1060 | icmp_packet->ttl--; |
1079 | 1061 | ||
1080 | /* route it */ | 1062 | /* route it */ |
1081 | send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); | 1063 | send_skb_packet(skb, router->if_incoming, router->addr); |
1082 | ret = NET_RX_SUCCESS; | 1064 | ret = NET_RX_SUCCESS; |
1083 | goto out; | ||
1084 | 1065 | ||
1085 | unlock: | ||
1086 | rcu_read_unlock(); | ||
1087 | out: | 1066 | out: |
1088 | if (neigh_node) | 1067 | if (router) |
1089 | neigh_node_free_ref(neigh_node); | 1068 | neigh_node_free_ref(router); |
1090 | if (orig_node) | 1069 | if (orig_node) |
1091 | orig_node_free_ref(orig_node); | 1070 | orig_node_free_ref(orig_node); |
1092 | return ret; | 1071 | return ret; |
1093 | } | 1072 | } |
1094 | 1073 | ||
1074 | /* In the bonding case, send the packets in a round | ||
1075 | * robin fashion over the remaining interfaces. | ||
1076 | * | ||
1077 | * This method rotates the bonding list and increases the | ||
1078 | * returned router's refcount. */ | ||
1079 | static struct neigh_node *find_bond_router(struct orig_node *primary_orig, | ||
1080 | struct hard_iface *recv_if) | ||
1081 | { | ||
1082 | struct neigh_node *tmp_neigh_node; | ||
1083 | struct neigh_node *router = NULL, *first_candidate = NULL; | ||
1084 | |||
1085 | rcu_read_lock(); | ||
1086 | list_for_each_entry_rcu(tmp_neigh_node, &primary_orig->bond_list, | ||
1087 | bonding_list) { | ||
1088 | if (!first_candidate) | ||
1089 | first_candidate = tmp_neigh_node; | ||
1090 | |||
1091 | /* recv_if == NULL on the first node. */ | ||
1092 | if (tmp_neigh_node->if_incoming == recv_if) | ||
1093 | continue; | ||
1094 | |||
1095 | if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) | ||
1096 | continue; | ||
1097 | |||
1098 | router = tmp_neigh_node; | ||
1099 | break; | ||
1100 | } | ||
1101 | |||
1102 | /* use the first candidate if nothing was found. */ | ||
1103 | if (!router && first_candidate && | ||
1104 | atomic_inc_not_zero(&first_candidate->refcount)) | ||
1105 | router = first_candidate; | ||
1106 | |||
1107 | if (!router) | ||
1108 | goto out; | ||
1109 | |||
1110 | /* selected should point to the next element | ||
1111 | * after the current router */ | ||
1112 | spin_lock_bh(&primary_orig->neigh_list_lock); | ||
1113 | /* this is a list_move(), which unfortunately | ||
1114 | * does not exist as rcu version */ | ||
1115 | list_del_rcu(&primary_orig->bond_list); | ||
1116 | list_add_rcu(&primary_orig->bond_list, | ||
1117 | &router->bonding_list); | ||
1118 | spin_unlock_bh(&primary_orig->neigh_list_lock); | ||
1119 | |||
1120 | out: | ||
1121 | rcu_read_unlock(); | ||
1122 | return router; | ||
1123 | } | ||
1124 | |||
1125 | /* Interface Alternating: Use the best of the | ||
1126 | * remaining candidates which are not using | ||
1127 | * this interface. | ||
1128 | * | ||
1129 | * Increases the returned router's refcount */ | ||
1130 | static struct neigh_node *find_ifalter_router(struct orig_node *primary_orig, | ||
1131 | struct hard_iface *recv_if) | ||
1132 | { | ||
1133 | struct neigh_node *tmp_neigh_node; | ||
1134 | struct neigh_node *router = NULL, *first_candidate = NULL; | ||
1135 | |||
1136 | rcu_read_lock(); | ||
1137 | list_for_each_entry_rcu(tmp_neigh_node, &primary_orig->bond_list, | ||
1138 | bonding_list) { | ||
1139 | if (!first_candidate) | ||
1140 | first_candidate = tmp_neigh_node; | ||
1141 | |||
1142 | /* recv_if == NULL on the first node. */ | ||
1143 | if (tmp_neigh_node->if_incoming == recv_if) | ||
1144 | continue; | ||
1145 | |||
1146 | if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) | ||
1147 | continue; | ||
1148 | |||
1149 | /* if we don't have a router yet | ||
1150 | * or this one is better, choose it. */ | ||
1151 | if ((!router) || | ||
1152 | (tmp_neigh_node->tq_avg > router->tq_avg)) { | ||
1153 | /* decrement refcount of | ||
1154 | * previously selected router */ | ||
1155 | if (router) | ||
1156 | neigh_node_free_ref(router); | ||
1157 | |||
1158 | router = tmp_neigh_node; | ||
1159 | atomic_inc_not_zero(&router->refcount); | ||
1160 | } | ||
1161 | |||
1162 | neigh_node_free_ref(tmp_neigh_node); | ||
1163 | } | ||
1164 | |||
1165 | /* use the first candidate if nothing was found. */ | ||
1166 | if (!router && first_candidate && | ||
1167 | atomic_inc_not_zero(&first_candidate->refcount)) | ||
1168 | router = first_candidate; | ||
1169 | |||
1170 | rcu_read_unlock(); | ||
1171 | return router; | ||
1172 | } | ||
1173 | |||
1095 | /* find a suitable router for this originator, and use | 1174 | /* find a suitable router for this originator, and use |
1096 | * bonding if possible. increases the found neighbors | 1175 | * bonding if possible. increases the found neighbors |
1097 | * refcount.*/ | 1176 | * refcount.*/ |
@@ -1101,15 +1180,16 @@ struct neigh_node *find_router(struct bat_priv *bat_priv, | |||
1101 | { | 1180 | { |
1102 | struct orig_node *primary_orig_node; | 1181 | struct orig_node *primary_orig_node; |
1103 | struct orig_node *router_orig; | 1182 | struct orig_node *router_orig; |
1104 | struct neigh_node *router, *first_candidate, *tmp_neigh_node; | 1183 | struct neigh_node *router; |
1105 | static uint8_t zero_mac[ETH_ALEN] = {0, 0, 0, 0, 0, 0}; | 1184 | static uint8_t zero_mac[ETH_ALEN] = {0, 0, 0, 0, 0, 0}; |
1106 | int bonding_enabled; | 1185 | int bonding_enabled; |
1107 | 1186 | ||
1108 | if (!orig_node) | 1187 | if (!orig_node) |
1109 | return NULL; | 1188 | return NULL; |
1110 | 1189 | ||
1111 | if (!orig_node->router) | 1190 | router = orig_node_get_router(orig_node); |
1112 | return NULL; | 1191 | if (!router) |
1192 | goto err; | ||
1113 | 1193 | ||
1114 | /* without bonding, the first node should | 1194 | /* without bonding, the first node should |
1115 | * always choose the default router. */ | 1195 | * always choose the default router. */ |
@@ -1117,12 +1197,9 @@ struct neigh_node *find_router(struct bat_priv *bat_priv, | |||
1117 | 1197 | ||
1118 | rcu_read_lock(); | 1198 | rcu_read_lock(); |
1119 | /* select default router to output */ | 1199 | /* select default router to output */ |
1120 | router = orig_node->router; | 1200 | router_orig = router->orig_node; |
1121 | router_orig = orig_node->router->orig_node; | 1201 | if (!router_orig) |
1122 | if (!router_orig || !atomic_inc_not_zero(&router->refcount)) { | 1202 | goto err_unlock; |
1123 | rcu_read_unlock(); | ||
1124 | return NULL; | ||
1125 | } | ||
1126 | 1203 | ||
1127 | if ((!recv_if) && (!bonding_enabled)) | 1204 | if ((!recv_if) && (!bonding_enabled)) |
1128 | goto return_router; | 1205 | goto return_router; |
@@ -1151,91 +1228,26 @@ struct neigh_node *find_router(struct bat_priv *bat_priv, | |||
1151 | if (atomic_read(&primary_orig_node->bond_candidates) < 2) | 1228 | if (atomic_read(&primary_orig_node->bond_candidates) < 2) |
1152 | goto return_router; | 1229 | goto return_router; |
1153 | 1230 | ||
1154 | |||
1155 | /* all nodes between should choose a candidate which | 1231 | /* all nodes between should choose a candidate which |
1156 | * is is not on the interface where the packet came | 1232 | * is is not on the interface where the packet came |
1157 | * in. */ | 1233 | * in. */ |
1158 | 1234 | ||
1159 | neigh_node_free_ref(router); | 1235 | neigh_node_free_ref(router); |
1160 | first_candidate = NULL; | ||
1161 | router = NULL; | ||
1162 | |||
1163 | if (bonding_enabled) { | ||
1164 | /* in the bonding case, send the packets in a round | ||
1165 | * robin fashion over the remaining interfaces. */ | ||
1166 | |||
1167 | list_for_each_entry_rcu(tmp_neigh_node, | ||
1168 | &primary_orig_node->bond_list, bonding_list) { | ||
1169 | if (!first_candidate) | ||
1170 | first_candidate = tmp_neigh_node; | ||
1171 | /* recv_if == NULL on the first node. */ | ||
1172 | if (tmp_neigh_node->if_incoming != recv_if && | ||
1173 | atomic_inc_not_zero(&tmp_neigh_node->refcount)) { | ||
1174 | router = tmp_neigh_node; | ||
1175 | break; | ||
1176 | } | ||
1177 | } | ||
1178 | |||
1179 | /* use the first candidate if nothing was found. */ | ||
1180 | if (!router && first_candidate && | ||
1181 | atomic_inc_not_zero(&first_candidate->refcount)) | ||
1182 | router = first_candidate; | ||
1183 | 1236 | ||
1184 | if (!router) { | 1237 | if (bonding_enabled) |
1185 | rcu_read_unlock(); | 1238 | router = find_bond_router(primary_orig_node, recv_if); |
1186 | return NULL; | 1239 | else |
1187 | } | 1240 | router = find_ifalter_router(primary_orig_node, recv_if); |
1188 | |||
1189 | /* selected should point to the next element | ||
1190 | * after the current router */ | ||
1191 | spin_lock_bh(&primary_orig_node->neigh_list_lock); | ||
1192 | /* this is a list_move(), which unfortunately | ||
1193 | * does not exist as rcu version */ | ||
1194 | list_del_rcu(&primary_orig_node->bond_list); | ||
1195 | list_add_rcu(&primary_orig_node->bond_list, | ||
1196 | &router->bonding_list); | ||
1197 | spin_unlock_bh(&primary_orig_node->neigh_list_lock); | ||
1198 | |||
1199 | } else { | ||
1200 | /* if bonding is disabled, use the best of the | ||
1201 | * remaining candidates which are not using | ||
1202 | * this interface. */ | ||
1203 | list_for_each_entry_rcu(tmp_neigh_node, | ||
1204 | &primary_orig_node->bond_list, bonding_list) { | ||
1205 | if (!first_candidate) | ||
1206 | first_candidate = tmp_neigh_node; | ||
1207 | |||
1208 | /* recv_if == NULL on the first node. */ | ||
1209 | if (tmp_neigh_node->if_incoming == recv_if) | ||
1210 | continue; | ||
1211 | |||
1212 | if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) | ||
1213 | continue; | ||
1214 | |||
1215 | /* if we don't have a router yet | ||
1216 | * or this one is better, choose it. */ | ||
1217 | if ((!router) || | ||
1218 | (tmp_neigh_node->tq_avg > router->tq_avg)) { | ||
1219 | /* decrement refcount of | ||
1220 | * previously selected router */ | ||
1221 | if (router) | ||
1222 | neigh_node_free_ref(router); | ||
1223 | |||
1224 | router = tmp_neigh_node; | ||
1225 | atomic_inc_not_zero(&router->refcount); | ||
1226 | } | ||
1227 | |||
1228 | neigh_node_free_ref(tmp_neigh_node); | ||
1229 | } | ||
1230 | 1241 | ||
1231 | /* use the first candidate if nothing was found. */ | ||
1232 | if (!router && first_candidate && | ||
1233 | atomic_inc_not_zero(&first_candidate->refcount)) | ||
1234 | router = first_candidate; | ||
1235 | } | ||
1236 | return_router: | 1242 | return_router: |
1237 | rcu_read_unlock(); | 1243 | rcu_read_unlock(); |
1238 | return router; | 1244 | return router; |
1245 | err_unlock: | ||
1246 | rcu_read_unlock(); | ||
1247 | err: | ||
1248 | if (router) | ||
1249 | neigh_node_free_ref(router); | ||
1250 | return NULL; | ||
1239 | } | 1251 | } |
1240 | 1252 | ||
1241 | static int check_unicast_packet(struct sk_buff *skb, int hdr_size) | 1253 | static int check_unicast_packet(struct sk_buff *skb, int hdr_size) |
@@ -1284,13 +1296,10 @@ int route_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if) | |||
1284 | } | 1296 | } |
1285 | 1297 | ||
1286 | /* get routing information */ | 1298 | /* get routing information */ |
1287 | rcu_read_lock(); | ||
1288 | orig_node = orig_hash_find(bat_priv, unicast_packet->dest); | 1299 | orig_node = orig_hash_find(bat_priv, unicast_packet->dest); |
1289 | 1300 | ||
1290 | if (!orig_node) | 1301 | if (!orig_node) |
1291 | goto unlock; | 1302 | goto out; |
1292 | |||
1293 | rcu_read_unlock(); | ||
1294 | 1303 | ||
1295 | /* find_router() increases neigh_nodes refcount if found. */ | 1304 | /* find_router() increases neigh_nodes refcount if found. */ |
1296 | neigh_node = find_router(bat_priv, orig_node, recv_if); | 1305 | neigh_node = find_router(bat_priv, orig_node, recv_if); |
@@ -1336,10 +1345,7 @@ int route_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if) | |||
1336 | /* route it */ | 1345 | /* route it */ |
1337 | send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); | 1346 | send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); |
1338 | ret = NET_RX_SUCCESS; | 1347 | ret = NET_RX_SUCCESS; |
1339 | goto out; | ||
1340 | 1348 | ||
1341 | unlock: | ||
1342 | rcu_read_unlock(); | ||
1343 | out: | 1349 | out: |
1344 | if (neigh_node) | 1350 | if (neigh_node) |
1345 | neigh_node_free_ref(neigh_node); | 1351 | neigh_node_free_ref(neigh_node); |
@@ -1438,13 +1444,10 @@ int recv_bcast_packet(struct sk_buff *skb, struct hard_iface *recv_if) | |||
1438 | if (bcast_packet->ttl < 2) | 1444 | if (bcast_packet->ttl < 2) |
1439 | goto out; | 1445 | goto out; |
1440 | 1446 | ||
1441 | rcu_read_lock(); | ||
1442 | orig_node = orig_hash_find(bat_priv, bcast_packet->orig); | 1447 | orig_node = orig_hash_find(bat_priv, bcast_packet->orig); |
1443 | 1448 | ||
1444 | if (!orig_node) | 1449 | if (!orig_node) |
1445 | goto rcu_unlock; | 1450 | goto out; |
1446 | |||
1447 | rcu_read_unlock(); | ||
1448 | 1451 | ||
1449 | spin_lock_bh(&orig_node->bcast_seqno_lock); | 1452 | spin_lock_bh(&orig_node->bcast_seqno_lock); |
1450 | 1453 | ||
@@ -1475,9 +1478,6 @@ int recv_bcast_packet(struct sk_buff *skb, struct hard_iface *recv_if) | |||
1475 | ret = NET_RX_SUCCESS; | 1478 | ret = NET_RX_SUCCESS; |
1476 | goto out; | 1479 | goto out; |
1477 | 1480 | ||
1478 | rcu_unlock: | ||
1479 | rcu_read_unlock(); | ||
1480 | goto out; | ||
1481 | spin_unlock: | 1481 | spin_unlock: |
1482 | spin_unlock_bh(&orig_node->bcast_seqno_lock); | 1482 | spin_unlock_bh(&orig_node->bcast_seqno_lock); |
1483 | out: | 1483 | out: |
diff --git a/net/batman-adv/routing.h b/net/batman-adv/routing.h index b5a064c88a4f..870f29842b28 100644 --- a/net/batman-adv/routing.h +++ b/net/batman-adv/routing.h | |||
@@ -25,11 +25,11 @@ | |||
25 | void slide_own_bcast_window(struct hard_iface *hard_iface); | 25 | void slide_own_bcast_window(struct hard_iface *hard_iface); |
26 | void receive_bat_packet(struct ethhdr *ethhdr, | 26 | void receive_bat_packet(struct ethhdr *ethhdr, |
27 | struct batman_packet *batman_packet, | 27 | struct batman_packet *batman_packet, |
28 | unsigned char *hna_buff, int hna_buff_len, | 28 | unsigned char *tt_buff, int tt_buff_len, |
29 | struct hard_iface *if_incoming); | 29 | struct hard_iface *if_incoming); |
30 | void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node, | 30 | void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node, |
31 | struct neigh_node *neigh_node, unsigned char *hna_buff, | 31 | struct neigh_node *neigh_node, unsigned char *tt_buff, |
32 | int hna_buff_len); | 32 | int tt_buff_len); |
33 | int route_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if); | 33 | int route_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if); |
34 | int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if); | 34 | int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if); |
35 | int recv_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if); | 35 | int recv_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if); |
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c index d49e54d932af..33779278f1b2 100644 --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c | |||
@@ -121,7 +121,7 @@ static void send_packet_to_if(struct forw_packet *forw_packet, | |||
121 | /* adjust all flags and log packets */ | 121 | /* adjust all flags and log packets */ |
122 | while (aggregated_packet(buff_pos, | 122 | while (aggregated_packet(buff_pos, |
123 | forw_packet->packet_len, | 123 | forw_packet->packet_len, |
124 | batman_packet->num_hna)) { | 124 | batman_packet->num_tt)) { |
125 | 125 | ||
126 | /* we might have aggregated direct link packets with an | 126 | /* we might have aggregated direct link packets with an |
127 | * ordinary base packet */ | 127 | * ordinary base packet */ |
@@ -146,7 +146,7 @@ static void send_packet_to_if(struct forw_packet *forw_packet, | |||
146 | hard_iface->net_dev->dev_addr); | 146 | hard_iface->net_dev->dev_addr); |
147 | 147 | ||
148 | buff_pos += sizeof(struct batman_packet) + | 148 | buff_pos += sizeof(struct batman_packet) + |
149 | (batman_packet->num_hna * ETH_ALEN); | 149 | (batman_packet->num_tt * ETH_ALEN); |
150 | packet_num++; | 150 | packet_num++; |
151 | batman_packet = (struct batman_packet *) | 151 | batman_packet = (struct batman_packet *) |
152 | (forw_packet->skb->data + buff_pos); | 152 | (forw_packet->skb->data + buff_pos); |
@@ -222,7 +222,7 @@ static void rebuild_batman_packet(struct bat_priv *bat_priv, | |||
222 | struct batman_packet *batman_packet; | 222 | struct batman_packet *batman_packet; |
223 | 223 | ||
224 | new_len = sizeof(struct batman_packet) + | 224 | new_len = sizeof(struct batman_packet) + |
225 | (bat_priv->num_local_hna * ETH_ALEN); | 225 | (bat_priv->num_local_tt * ETH_ALEN); |
226 | new_buff = kmalloc(new_len, GFP_ATOMIC); | 226 | new_buff = kmalloc(new_len, GFP_ATOMIC); |
227 | 227 | ||
228 | /* keep old buffer if kmalloc should fail */ | 228 | /* keep old buffer if kmalloc should fail */ |
@@ -231,7 +231,7 @@ static void rebuild_batman_packet(struct bat_priv *bat_priv, | |||
231 | sizeof(struct batman_packet)); | 231 | sizeof(struct batman_packet)); |
232 | batman_packet = (struct batman_packet *)new_buff; | 232 | batman_packet = (struct batman_packet *)new_buff; |
233 | 233 | ||
234 | batman_packet->num_hna = hna_local_fill_buffer(bat_priv, | 234 | batman_packet->num_tt = tt_local_fill_buffer(bat_priv, |
235 | new_buff + sizeof(struct batman_packet), | 235 | new_buff + sizeof(struct batman_packet), |
236 | new_len - sizeof(struct batman_packet)); | 236 | new_len - sizeof(struct batman_packet)); |
237 | 237 | ||
@@ -244,6 +244,7 @@ static void rebuild_batman_packet(struct bat_priv *bat_priv, | |||
244 | void schedule_own_packet(struct hard_iface *hard_iface) | 244 | void schedule_own_packet(struct hard_iface *hard_iface) |
245 | { | 245 | { |
246 | struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface); | 246 | struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface); |
247 | struct hard_iface *primary_if; | ||
247 | unsigned long send_time; | 248 | unsigned long send_time; |
248 | struct batman_packet *batman_packet; | 249 | struct batman_packet *batman_packet; |
249 | int vis_server; | 250 | int vis_server; |
@@ -253,6 +254,7 @@ void schedule_own_packet(struct hard_iface *hard_iface) | |||
253 | return; | 254 | return; |
254 | 255 | ||
255 | vis_server = atomic_read(&bat_priv->vis_mode); | 256 | vis_server = atomic_read(&bat_priv->vis_mode); |
257 | primary_if = primary_if_get_selected(bat_priv); | ||
256 | 258 | ||
257 | /** | 259 | /** |
258 | * the interface gets activated here to avoid race conditions between | 260 | * the interface gets activated here to avoid race conditions between |
@@ -264,9 +266,9 @@ void schedule_own_packet(struct hard_iface *hard_iface) | |||
264 | if (hard_iface->if_status == IF_TO_BE_ACTIVATED) | 266 | if (hard_iface->if_status == IF_TO_BE_ACTIVATED) |
265 | hard_iface->if_status = IF_ACTIVE; | 267 | hard_iface->if_status = IF_ACTIVE; |
266 | 268 | ||
267 | /* if local hna has changed and interface is a primary interface */ | 269 | /* if local tt has changed and interface is a primary interface */ |
268 | if ((atomic_read(&bat_priv->hna_local_changed)) && | 270 | if ((atomic_read(&bat_priv->tt_local_changed)) && |
269 | (hard_iface == bat_priv->primary_if)) | 271 | (hard_iface == primary_if)) |
270 | rebuild_batman_packet(bat_priv, hard_iface); | 272 | rebuild_batman_packet(bat_priv, hard_iface); |
271 | 273 | ||
272 | /** | 274 | /** |
@@ -284,7 +286,7 @@ void schedule_own_packet(struct hard_iface *hard_iface) | |||
284 | else | 286 | else |
285 | batman_packet->flags &= ~VIS_SERVER; | 287 | batman_packet->flags &= ~VIS_SERVER; |
286 | 288 | ||
287 | if ((hard_iface == bat_priv->primary_if) && | 289 | if ((hard_iface == primary_if) && |
288 | (atomic_read(&bat_priv->gw_mode) == GW_MODE_SERVER)) | 290 | (atomic_read(&bat_priv->gw_mode) == GW_MODE_SERVER)) |
289 | batman_packet->gw_flags = | 291 | batman_packet->gw_flags = |
290 | (uint8_t)atomic_read(&bat_priv->gw_bandwidth); | 292 | (uint8_t)atomic_read(&bat_priv->gw_bandwidth); |
@@ -299,15 +301,19 @@ void schedule_own_packet(struct hard_iface *hard_iface) | |||
299 | hard_iface->packet_buff, | 301 | hard_iface->packet_buff, |
300 | hard_iface->packet_len, | 302 | hard_iface->packet_len, |
301 | hard_iface, 1, send_time); | 303 | hard_iface, 1, send_time); |
304 | |||
305 | if (primary_if) | ||
306 | hardif_free_ref(primary_if); | ||
302 | } | 307 | } |
303 | 308 | ||
304 | void schedule_forward_packet(struct orig_node *orig_node, | 309 | void schedule_forward_packet(struct orig_node *orig_node, |
305 | struct ethhdr *ethhdr, | 310 | struct ethhdr *ethhdr, |
306 | struct batman_packet *batman_packet, | 311 | struct batman_packet *batman_packet, |
307 | uint8_t directlink, int hna_buff_len, | 312 | uint8_t directlink, int tt_buff_len, |
308 | struct hard_iface *if_incoming) | 313 | struct hard_iface *if_incoming) |
309 | { | 314 | { |
310 | struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); | 315 | struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); |
316 | struct neigh_node *router; | ||
311 | unsigned char in_tq, in_ttl, tq_avg = 0; | 317 | unsigned char in_tq, in_ttl, tq_avg = 0; |
312 | unsigned long send_time; | 318 | unsigned long send_time; |
313 | 319 | ||
@@ -316,6 +322,8 @@ void schedule_forward_packet(struct orig_node *orig_node, | |||
316 | return; | 322 | return; |
317 | } | 323 | } |
318 | 324 | ||
325 | router = orig_node_get_router(orig_node); | ||
326 | |||
319 | in_tq = batman_packet->tq; | 327 | in_tq = batman_packet->tq; |
320 | in_ttl = batman_packet->ttl; | 328 | in_ttl = batman_packet->ttl; |
321 | 329 | ||
@@ -324,20 +332,22 @@ void schedule_forward_packet(struct orig_node *orig_node, | |||
324 | 332 | ||
325 | /* rebroadcast tq of our best ranking neighbor to ensure the rebroadcast | 333 | /* rebroadcast tq of our best ranking neighbor to ensure the rebroadcast |
326 | * of our best tq value */ | 334 | * of our best tq value */ |
327 | if ((orig_node->router) && (orig_node->router->tq_avg != 0)) { | 335 | if (router && router->tq_avg != 0) { |
328 | 336 | ||
329 | /* rebroadcast ogm of best ranking neighbor as is */ | 337 | /* rebroadcast ogm of best ranking neighbor as is */ |
330 | if (!compare_eth(orig_node->router->addr, ethhdr->h_source)) { | 338 | if (!compare_eth(router->addr, ethhdr->h_source)) { |
331 | batman_packet->tq = orig_node->router->tq_avg; | 339 | batman_packet->tq = router->tq_avg; |
332 | 340 | ||
333 | if (orig_node->router->last_ttl) | 341 | if (router->last_ttl) |
334 | batman_packet->ttl = orig_node->router->last_ttl | 342 | batman_packet->ttl = router->last_ttl - 1; |
335 | - 1; | ||
336 | } | 343 | } |
337 | 344 | ||
338 | tq_avg = orig_node->router->tq_avg; | 345 | tq_avg = router->tq_avg; |
339 | } | 346 | } |
340 | 347 | ||
348 | if (router) | ||
349 | neigh_node_free_ref(router); | ||
350 | |||
341 | /* apply hop penalty */ | 351 | /* apply hop penalty */ |
342 | batman_packet->tq = hop_penalty(batman_packet->tq, bat_priv); | 352 | batman_packet->tq = hop_penalty(batman_packet->tq, bat_priv); |
343 | 353 | ||
@@ -359,7 +369,7 @@ void schedule_forward_packet(struct orig_node *orig_node, | |||
359 | send_time = forward_send_time(); | 369 | send_time = forward_send_time(); |
360 | add_bat_packet_to_list(bat_priv, | 370 | add_bat_packet_to_list(bat_priv, |
361 | (unsigned char *)batman_packet, | 371 | (unsigned char *)batman_packet, |
362 | sizeof(struct batman_packet) + hna_buff_len, | 372 | sizeof(struct batman_packet) + tt_buff_len, |
363 | if_incoming, 0, send_time); | 373 | if_incoming, 0, send_time); |
364 | } | 374 | } |
365 | 375 | ||
@@ -367,6 +377,8 @@ static void forw_packet_free(struct forw_packet *forw_packet) | |||
367 | { | 377 | { |
368 | if (forw_packet->skb) | 378 | if (forw_packet->skb) |
369 | kfree_skb(forw_packet->skb); | 379 | kfree_skb(forw_packet->skb); |
380 | if (forw_packet->if_incoming) | ||
381 | hardif_free_ref(forw_packet->if_incoming); | ||
370 | kfree(forw_packet); | 382 | kfree(forw_packet); |
371 | } | 383 | } |
372 | 384 | ||
@@ -388,7 +400,6 @@ static void _add_bcast_packet_to_list(struct bat_priv *bat_priv, | |||
388 | send_time); | 400 | send_time); |
389 | } | 401 | } |
390 | 402 | ||
391 | #define atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0) | ||
392 | /* add a broadcast packet to the queue and setup timers. broadcast packets | 403 | /* add a broadcast packet to the queue and setup timers. broadcast packets |
393 | * are sent multiple times to increase probability for beeing received. | 404 | * are sent multiple times to increase probability for beeing received. |
394 | * | 405 | * |
@@ -399,6 +410,7 @@ static void _add_bcast_packet_to_list(struct bat_priv *bat_priv, | |||
399 | * skb is freed. */ | 410 | * skb is freed. */ |
400 | int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb) | 411 | int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb) |
401 | { | 412 | { |
413 | struct hard_iface *primary_if = NULL; | ||
402 | struct forw_packet *forw_packet; | 414 | struct forw_packet *forw_packet; |
403 | struct bcast_packet *bcast_packet; | 415 | struct bcast_packet *bcast_packet; |
404 | 416 | ||
@@ -407,8 +419,9 @@ int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb) | |||
407 | goto out; | 419 | goto out; |
408 | } | 420 | } |
409 | 421 | ||
410 | if (!bat_priv->primary_if) | 422 | primary_if = primary_if_get_selected(bat_priv); |
411 | goto out; | 423 | if (!primary_if) |
424 | goto out_and_inc; | ||
412 | 425 | ||
413 | forw_packet = kmalloc(sizeof(struct forw_packet), GFP_ATOMIC); | 426 | forw_packet = kmalloc(sizeof(struct forw_packet), GFP_ATOMIC); |
414 | 427 | ||
@@ -426,7 +439,7 @@ int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb) | |||
426 | skb_reset_mac_header(skb); | 439 | skb_reset_mac_header(skb); |
427 | 440 | ||
428 | forw_packet->skb = skb; | 441 | forw_packet->skb = skb; |
429 | forw_packet->if_incoming = bat_priv->primary_if; | 442 | forw_packet->if_incoming = primary_if; |
430 | 443 | ||
431 | /* how often did we send the bcast packet ? */ | 444 | /* how often did we send the bcast packet ? */ |
432 | forw_packet->num_packets = 0; | 445 | forw_packet->num_packets = 0; |
@@ -439,6 +452,8 @@ packet_free: | |||
439 | out_and_inc: | 452 | out_and_inc: |
440 | atomic_inc(&bat_priv->bcast_queue_left); | 453 | atomic_inc(&bat_priv->bcast_queue_left); |
441 | out: | 454 | out: |
455 | if (primary_if) | ||
456 | hardif_free_ref(primary_if); | ||
442 | return NETDEV_TX_BUSY; | 457 | return NETDEV_TX_BUSY; |
443 | } | 458 | } |
444 | 459 | ||
@@ -526,6 +541,7 @@ void purge_outstanding_packets(struct bat_priv *bat_priv, | |||
526 | { | 541 | { |
527 | struct forw_packet *forw_packet; | 542 | struct forw_packet *forw_packet; |
528 | struct hlist_node *tmp_node, *safe_tmp_node; | 543 | struct hlist_node *tmp_node, *safe_tmp_node; |
544 | bool pending; | ||
529 | 545 | ||
530 | if (hard_iface) | 546 | if (hard_iface) |
531 | bat_dbg(DBG_BATMAN, bat_priv, | 547 | bat_dbg(DBG_BATMAN, bat_priv, |
@@ -554,8 +570,13 @@ void purge_outstanding_packets(struct bat_priv *bat_priv, | |||
554 | * send_outstanding_bcast_packet() will lock the list to | 570 | * send_outstanding_bcast_packet() will lock the list to |
555 | * delete the item from the list | 571 | * delete the item from the list |
556 | */ | 572 | */ |
557 | cancel_delayed_work_sync(&forw_packet->delayed_work); | 573 | pending = cancel_delayed_work_sync(&forw_packet->delayed_work); |
558 | spin_lock_bh(&bat_priv->forw_bcast_list_lock); | 574 | spin_lock_bh(&bat_priv->forw_bcast_list_lock); |
575 | |||
576 | if (pending) { | ||
577 | hlist_del(&forw_packet->list); | ||
578 | forw_packet_free(forw_packet); | ||
579 | } | ||
559 | } | 580 | } |
560 | spin_unlock_bh(&bat_priv->forw_bcast_list_lock); | 581 | spin_unlock_bh(&bat_priv->forw_bcast_list_lock); |
561 | 582 | ||
@@ -578,8 +599,13 @@ void purge_outstanding_packets(struct bat_priv *bat_priv, | |||
578 | * send_outstanding_bat_packet() will lock the list to | 599 | * send_outstanding_bat_packet() will lock the list to |
579 | * delete the item from the list | 600 | * delete the item from the list |
580 | */ | 601 | */ |
581 | cancel_delayed_work_sync(&forw_packet->delayed_work); | 602 | pending = cancel_delayed_work_sync(&forw_packet->delayed_work); |
582 | spin_lock_bh(&bat_priv->forw_bat_list_lock); | 603 | spin_lock_bh(&bat_priv->forw_bat_list_lock); |
604 | |||
605 | if (pending) { | ||
606 | hlist_del(&forw_packet->list); | ||
607 | forw_packet_free(forw_packet); | ||
608 | } | ||
583 | } | 609 | } |
584 | spin_unlock_bh(&bat_priv->forw_bat_list_lock); | 610 | spin_unlock_bh(&bat_priv->forw_bat_list_lock); |
585 | } | 611 | } |
diff --git a/net/batman-adv/send.h b/net/batman-adv/send.h index 7b2ff19c05e7..247172d71e4b 100644 --- a/net/batman-adv/send.h +++ b/net/batman-adv/send.h | |||
@@ -29,7 +29,7 @@ void schedule_own_packet(struct hard_iface *hard_iface); | |||
29 | void schedule_forward_packet(struct orig_node *orig_node, | 29 | void schedule_forward_packet(struct orig_node *orig_node, |
30 | struct ethhdr *ethhdr, | 30 | struct ethhdr *ethhdr, |
31 | struct batman_packet *batman_packet, | 31 | struct batman_packet *batman_packet, |
32 | uint8_t directlink, int hna_buff_len, | 32 | uint8_t directlink, int tt_buff_len, |
33 | struct hard_iface *if_outgoing); | 33 | struct hard_iface *if_outgoing); |
34 | int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb); | 34 | int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb); |
35 | void send_outstanding_bat_packet(struct work_struct *work); | 35 | void send_outstanding_bat_packet(struct work_struct *work); |
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 824e1f6e50f2..d5aa60999e83 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c | |||
@@ -43,8 +43,6 @@ static void bat_get_drvinfo(struct net_device *dev, | |||
43 | static u32 bat_get_msglevel(struct net_device *dev); | 43 | static u32 bat_get_msglevel(struct net_device *dev); |
44 | static void bat_set_msglevel(struct net_device *dev, u32 value); | 44 | static void bat_set_msglevel(struct net_device *dev, u32 value); |
45 | static u32 bat_get_link(struct net_device *dev); | 45 | static u32 bat_get_link(struct net_device *dev); |
46 | static u32 bat_get_rx_csum(struct net_device *dev); | ||
47 | static int bat_set_rx_csum(struct net_device *dev, u32 data); | ||
48 | 46 | ||
49 | static const struct ethtool_ops bat_ethtool_ops = { | 47 | static const struct ethtool_ops bat_ethtool_ops = { |
50 | .get_settings = bat_get_settings, | 48 | .get_settings = bat_get_settings, |
@@ -52,8 +50,6 @@ static const struct ethtool_ops bat_ethtool_ops = { | |||
52 | .get_msglevel = bat_get_msglevel, | 50 | .get_msglevel = bat_get_msglevel, |
53 | .set_msglevel = bat_set_msglevel, | 51 | .set_msglevel = bat_set_msglevel, |
54 | .get_link = bat_get_link, | 52 | .get_link = bat_get_link, |
55 | .get_rx_csum = bat_get_rx_csum, | ||
56 | .set_rx_csum = bat_set_rx_csum | ||
57 | }; | 53 | }; |
58 | 54 | ||
59 | int my_skb_head_push(struct sk_buff *skb, unsigned int len) | 55 | int my_skb_head_push(struct sk_buff *skb, unsigned int len) |
@@ -76,120 +72,371 @@ int my_skb_head_push(struct sk_buff *skb, unsigned int len) | |||
76 | return 0; | 72 | return 0; |
77 | } | 73 | } |
78 | 74 | ||
79 | static void softif_neigh_free_rcu(struct rcu_head *rcu) | ||
80 | { | ||
81 | struct softif_neigh *softif_neigh; | ||
82 | |||
83 | softif_neigh = container_of(rcu, struct softif_neigh, rcu); | ||
84 | kfree(softif_neigh); | ||
85 | } | ||
86 | |||
87 | static void softif_neigh_free_ref(struct softif_neigh *softif_neigh) | 75 | static void softif_neigh_free_ref(struct softif_neigh *softif_neigh) |
88 | { | 76 | { |
89 | if (atomic_dec_and_test(&softif_neigh->refcount)) | 77 | if (atomic_dec_and_test(&softif_neigh->refcount)) |
90 | call_rcu(&softif_neigh->rcu, softif_neigh_free_rcu); | 78 | kfree_rcu(softif_neigh, rcu); |
91 | } | 79 | } |
92 | 80 | ||
93 | void softif_neigh_purge(struct bat_priv *bat_priv) | 81 | static void softif_neigh_vid_free_rcu(struct rcu_head *rcu) |
94 | { | 82 | { |
95 | struct softif_neigh *softif_neigh, *softif_neigh_tmp; | 83 | struct softif_neigh_vid *softif_neigh_vid; |
84 | struct softif_neigh *softif_neigh; | ||
96 | struct hlist_node *node, *node_tmp; | 85 | struct hlist_node *node, *node_tmp; |
86 | struct bat_priv *bat_priv; | ||
97 | 87 | ||
98 | spin_lock_bh(&bat_priv->softif_neigh_lock); | 88 | softif_neigh_vid = container_of(rcu, struct softif_neigh_vid, rcu); |
89 | bat_priv = softif_neigh_vid->bat_priv; | ||
99 | 90 | ||
91 | spin_lock_bh(&bat_priv->softif_neigh_lock); | ||
100 | hlist_for_each_entry_safe(softif_neigh, node, node_tmp, | 92 | hlist_for_each_entry_safe(softif_neigh, node, node_tmp, |
101 | &bat_priv->softif_neigh_list, list) { | 93 | &softif_neigh_vid->softif_neigh_list, list) { |
94 | hlist_del_rcu(&softif_neigh->list); | ||
95 | softif_neigh_free_ref(softif_neigh); | ||
96 | } | ||
97 | spin_unlock_bh(&bat_priv->softif_neigh_lock); | ||
102 | 98 | ||
103 | if ((!time_after(jiffies, softif_neigh->last_seen + | 99 | kfree(softif_neigh_vid); |
104 | msecs_to_jiffies(SOFTIF_NEIGH_TIMEOUT))) && | 100 | } |
105 | (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE)) | ||
106 | continue; | ||
107 | 101 | ||
108 | hlist_del_rcu(&softif_neigh->list); | 102 | static void softif_neigh_vid_free_ref(struct softif_neigh_vid *softif_neigh_vid) |
103 | { | ||
104 | if (atomic_dec_and_test(&softif_neigh_vid->refcount)) | ||
105 | call_rcu(&softif_neigh_vid->rcu, softif_neigh_vid_free_rcu); | ||
106 | } | ||
109 | 107 | ||
110 | if (bat_priv->softif_neigh == softif_neigh) { | 108 | static struct softif_neigh_vid *softif_neigh_vid_get(struct bat_priv *bat_priv, |
111 | bat_dbg(DBG_ROUTES, bat_priv, | 109 | short vid) |
112 | "Current mesh exit point '%pM' vanished " | 110 | { |
113 | "(vid: %d).\n", | 111 | struct softif_neigh_vid *softif_neigh_vid; |
114 | softif_neigh->addr, softif_neigh->vid); | 112 | struct hlist_node *node; |
115 | softif_neigh_tmp = bat_priv->softif_neigh; | ||
116 | bat_priv->softif_neigh = NULL; | ||
117 | softif_neigh_free_ref(softif_neigh_tmp); | ||
118 | } | ||
119 | 113 | ||
120 | softif_neigh_free_ref(softif_neigh); | 114 | rcu_read_lock(); |
115 | hlist_for_each_entry_rcu(softif_neigh_vid, node, | ||
116 | &bat_priv->softif_neigh_vids, list) { | ||
117 | if (softif_neigh_vid->vid != vid) | ||
118 | continue; | ||
119 | |||
120 | if (!atomic_inc_not_zero(&softif_neigh_vid->refcount)) | ||
121 | continue; | ||
122 | |||
123 | goto out; | ||
121 | } | 124 | } |
122 | 125 | ||
123 | spin_unlock_bh(&bat_priv->softif_neigh_lock); | 126 | softif_neigh_vid = kzalloc(sizeof(struct softif_neigh_vid), |
127 | GFP_ATOMIC); | ||
128 | if (!softif_neigh_vid) | ||
129 | goto out; | ||
130 | |||
131 | softif_neigh_vid->vid = vid; | ||
132 | softif_neigh_vid->bat_priv = bat_priv; | ||
133 | |||
134 | /* initialize with 2 - caller decrements counter by one */ | ||
135 | atomic_set(&softif_neigh_vid->refcount, 2); | ||
136 | INIT_HLIST_HEAD(&softif_neigh_vid->softif_neigh_list); | ||
137 | INIT_HLIST_NODE(&softif_neigh_vid->list); | ||
138 | spin_lock_bh(&bat_priv->softif_neigh_vid_lock); | ||
139 | hlist_add_head_rcu(&softif_neigh_vid->list, | ||
140 | &bat_priv->softif_neigh_vids); | ||
141 | spin_unlock_bh(&bat_priv->softif_neigh_vid_lock); | ||
142 | |||
143 | out: | ||
144 | rcu_read_unlock(); | ||
145 | return softif_neigh_vid; | ||
124 | } | 146 | } |
125 | 147 | ||
126 | static struct softif_neigh *softif_neigh_get(struct bat_priv *bat_priv, | 148 | static struct softif_neigh *softif_neigh_get(struct bat_priv *bat_priv, |
127 | uint8_t *addr, short vid) | 149 | uint8_t *addr, short vid) |
128 | { | 150 | { |
129 | struct softif_neigh *softif_neigh; | 151 | struct softif_neigh_vid *softif_neigh_vid; |
152 | struct softif_neigh *softif_neigh = NULL; | ||
130 | struct hlist_node *node; | 153 | struct hlist_node *node; |
131 | 154 | ||
155 | softif_neigh_vid = softif_neigh_vid_get(bat_priv, vid); | ||
156 | if (!softif_neigh_vid) | ||
157 | goto out; | ||
158 | |||
132 | rcu_read_lock(); | 159 | rcu_read_lock(); |
133 | hlist_for_each_entry_rcu(softif_neigh, node, | 160 | hlist_for_each_entry_rcu(softif_neigh, node, |
134 | &bat_priv->softif_neigh_list, list) { | 161 | &softif_neigh_vid->softif_neigh_list, |
162 | list) { | ||
135 | if (!compare_eth(softif_neigh->addr, addr)) | 163 | if (!compare_eth(softif_neigh->addr, addr)) |
136 | continue; | 164 | continue; |
137 | 165 | ||
138 | if (softif_neigh->vid != vid) | ||
139 | continue; | ||
140 | |||
141 | if (!atomic_inc_not_zero(&softif_neigh->refcount)) | 166 | if (!atomic_inc_not_zero(&softif_neigh->refcount)) |
142 | continue; | 167 | continue; |
143 | 168 | ||
144 | softif_neigh->last_seen = jiffies; | 169 | softif_neigh->last_seen = jiffies; |
145 | goto out; | 170 | goto unlock; |
146 | } | 171 | } |
147 | 172 | ||
148 | softif_neigh = kzalloc(sizeof(struct softif_neigh), GFP_ATOMIC); | 173 | softif_neigh = kzalloc(sizeof(struct softif_neigh), GFP_ATOMIC); |
149 | if (!softif_neigh) | 174 | if (!softif_neigh) |
150 | goto out; | 175 | goto unlock; |
151 | 176 | ||
152 | memcpy(softif_neigh->addr, addr, ETH_ALEN); | 177 | memcpy(softif_neigh->addr, addr, ETH_ALEN); |
153 | softif_neigh->vid = vid; | ||
154 | softif_neigh->last_seen = jiffies; | 178 | softif_neigh->last_seen = jiffies; |
155 | /* initialize with 2 - caller decrements counter by one */ | 179 | /* initialize with 2 - caller decrements counter by one */ |
156 | atomic_set(&softif_neigh->refcount, 2); | 180 | atomic_set(&softif_neigh->refcount, 2); |
157 | 181 | ||
158 | INIT_HLIST_NODE(&softif_neigh->list); | 182 | INIT_HLIST_NODE(&softif_neigh->list); |
159 | spin_lock_bh(&bat_priv->softif_neigh_lock); | 183 | spin_lock_bh(&bat_priv->softif_neigh_lock); |
160 | hlist_add_head_rcu(&softif_neigh->list, &bat_priv->softif_neigh_list); | 184 | hlist_add_head_rcu(&softif_neigh->list, |
185 | &softif_neigh_vid->softif_neigh_list); | ||
161 | spin_unlock_bh(&bat_priv->softif_neigh_lock); | 186 | spin_unlock_bh(&bat_priv->softif_neigh_lock); |
162 | 187 | ||
188 | unlock: | ||
189 | rcu_read_unlock(); | ||
163 | out: | 190 | out: |
191 | if (softif_neigh_vid) | ||
192 | softif_neigh_vid_free_ref(softif_neigh_vid); | ||
193 | return softif_neigh; | ||
194 | } | ||
195 | |||
196 | static struct softif_neigh *softif_neigh_get_selected( | ||
197 | struct softif_neigh_vid *softif_neigh_vid) | ||
198 | { | ||
199 | struct softif_neigh *softif_neigh; | ||
200 | |||
201 | rcu_read_lock(); | ||
202 | softif_neigh = rcu_dereference(softif_neigh_vid->softif_neigh); | ||
203 | |||
204 | if (softif_neigh && !atomic_inc_not_zero(&softif_neigh->refcount)) | ||
205 | softif_neigh = NULL; | ||
206 | |||
164 | rcu_read_unlock(); | 207 | rcu_read_unlock(); |
165 | return softif_neigh; | 208 | return softif_neigh; |
166 | } | 209 | } |
167 | 210 | ||
211 | static struct softif_neigh *softif_neigh_vid_get_selected( | ||
212 | struct bat_priv *bat_priv, | ||
213 | short vid) | ||
214 | { | ||
215 | struct softif_neigh_vid *softif_neigh_vid; | ||
216 | struct softif_neigh *softif_neigh = NULL; | ||
217 | |||
218 | softif_neigh_vid = softif_neigh_vid_get(bat_priv, vid); | ||
219 | if (!softif_neigh_vid) | ||
220 | goto out; | ||
221 | |||
222 | softif_neigh = softif_neigh_get_selected(softif_neigh_vid); | ||
223 | out: | ||
224 | if (softif_neigh_vid) | ||
225 | softif_neigh_vid_free_ref(softif_neigh_vid); | ||
226 | return softif_neigh; | ||
227 | } | ||
228 | |||
229 | static void softif_neigh_vid_select(struct bat_priv *bat_priv, | ||
230 | struct softif_neigh *new_neigh, | ||
231 | short vid) | ||
232 | { | ||
233 | struct softif_neigh_vid *softif_neigh_vid; | ||
234 | struct softif_neigh *curr_neigh; | ||
235 | |||
236 | softif_neigh_vid = softif_neigh_vid_get(bat_priv, vid); | ||
237 | if (!softif_neigh_vid) | ||
238 | goto out; | ||
239 | |||
240 | spin_lock_bh(&bat_priv->softif_neigh_lock); | ||
241 | |||
242 | if (new_neigh && !atomic_inc_not_zero(&new_neigh->refcount)) | ||
243 | new_neigh = NULL; | ||
244 | |||
245 | curr_neigh = softif_neigh_vid->softif_neigh; | ||
246 | rcu_assign_pointer(softif_neigh_vid->softif_neigh, new_neigh); | ||
247 | |||
248 | if ((curr_neigh) && (!new_neigh)) | ||
249 | bat_dbg(DBG_ROUTES, bat_priv, | ||
250 | "Removing mesh exit point on vid: %d (prev: %pM).\n", | ||
251 | vid, curr_neigh->addr); | ||
252 | else if ((curr_neigh) && (new_neigh)) | ||
253 | bat_dbg(DBG_ROUTES, bat_priv, | ||
254 | "Changing mesh exit point on vid: %d from %pM " | ||
255 | "to %pM.\n", vid, curr_neigh->addr, new_neigh->addr); | ||
256 | else if ((!curr_neigh) && (new_neigh)) | ||
257 | bat_dbg(DBG_ROUTES, bat_priv, | ||
258 | "Setting mesh exit point on vid: %d to %pM.\n", | ||
259 | vid, new_neigh->addr); | ||
260 | |||
261 | if (curr_neigh) | ||
262 | softif_neigh_free_ref(curr_neigh); | ||
263 | |||
264 | spin_unlock_bh(&bat_priv->softif_neigh_lock); | ||
265 | |||
266 | out: | ||
267 | if (softif_neigh_vid) | ||
268 | softif_neigh_vid_free_ref(softif_neigh_vid); | ||
269 | } | ||
270 | |||
271 | static void softif_neigh_vid_deselect(struct bat_priv *bat_priv, | ||
272 | struct softif_neigh_vid *softif_neigh_vid) | ||
273 | { | ||
274 | struct softif_neigh *curr_neigh; | ||
275 | struct softif_neigh *softif_neigh = NULL, *softif_neigh_tmp; | ||
276 | struct hard_iface *primary_if = NULL; | ||
277 | struct hlist_node *node; | ||
278 | |||
279 | primary_if = primary_if_get_selected(bat_priv); | ||
280 | if (!primary_if) | ||
281 | goto out; | ||
282 | |||
283 | /* find new softif_neigh immediately to avoid temporary loops */ | ||
284 | rcu_read_lock(); | ||
285 | curr_neigh = rcu_dereference(softif_neigh_vid->softif_neigh); | ||
286 | |||
287 | hlist_for_each_entry_rcu(softif_neigh_tmp, node, | ||
288 | &softif_neigh_vid->softif_neigh_list, | ||
289 | list) { | ||
290 | if (softif_neigh_tmp == curr_neigh) | ||
291 | continue; | ||
292 | |||
293 | /* we got a neighbor but its mac is 'bigger' than ours */ | ||
294 | if (memcmp(primary_if->net_dev->dev_addr, | ||
295 | softif_neigh_tmp->addr, ETH_ALEN) < 0) | ||
296 | continue; | ||
297 | |||
298 | if (!atomic_inc_not_zero(&softif_neigh_tmp->refcount)) | ||
299 | continue; | ||
300 | |||
301 | softif_neigh = softif_neigh_tmp; | ||
302 | goto unlock; | ||
303 | } | ||
304 | |||
305 | unlock: | ||
306 | rcu_read_unlock(); | ||
307 | out: | ||
308 | softif_neigh_vid_select(bat_priv, softif_neigh, softif_neigh_vid->vid); | ||
309 | |||
310 | if (primary_if) | ||
311 | hardif_free_ref(primary_if); | ||
312 | if (softif_neigh) | ||
313 | softif_neigh_free_ref(softif_neigh); | ||
314 | } | ||
315 | |||
168 | int softif_neigh_seq_print_text(struct seq_file *seq, void *offset) | 316 | int softif_neigh_seq_print_text(struct seq_file *seq, void *offset) |
169 | { | 317 | { |
170 | struct net_device *net_dev = (struct net_device *)seq->private; | 318 | struct net_device *net_dev = (struct net_device *)seq->private; |
171 | struct bat_priv *bat_priv = netdev_priv(net_dev); | 319 | struct bat_priv *bat_priv = netdev_priv(net_dev); |
320 | struct softif_neigh_vid *softif_neigh_vid; | ||
172 | struct softif_neigh *softif_neigh; | 321 | struct softif_neigh *softif_neigh; |
173 | struct hlist_node *node; | 322 | struct hard_iface *primary_if; |
323 | struct hlist_node *node, *node_tmp; | ||
324 | struct softif_neigh *curr_softif_neigh; | ||
325 | int ret = 0, last_seen_secs, last_seen_msecs; | ||
326 | |||
327 | primary_if = primary_if_get_selected(bat_priv); | ||
328 | if (!primary_if) { | ||
329 | ret = seq_printf(seq, "BATMAN mesh %s disabled - " | ||
330 | "please specify interfaces to enable it\n", | ||
331 | net_dev->name); | ||
332 | goto out; | ||
333 | } | ||
174 | 334 | ||
175 | if (!bat_priv->primary_if) { | 335 | if (primary_if->if_status != IF_ACTIVE) { |
176 | return seq_printf(seq, "BATMAN mesh %s disabled - " | 336 | ret = seq_printf(seq, "BATMAN mesh %s " |
177 | "please specify interfaces to enable it\n", | 337 | "disabled - primary interface not active\n", |
178 | net_dev->name); | 338 | net_dev->name); |
339 | goto out; | ||
179 | } | 340 | } |
180 | 341 | ||
181 | seq_printf(seq, "Softif neighbor list (%s)\n", net_dev->name); | 342 | seq_printf(seq, "Softif neighbor list (%s)\n", net_dev->name); |
182 | 343 | ||
183 | rcu_read_lock(); | 344 | rcu_read_lock(); |
184 | hlist_for_each_entry_rcu(softif_neigh, node, | 345 | hlist_for_each_entry_rcu(softif_neigh_vid, node, |
185 | &bat_priv->softif_neigh_list, list) | 346 | &bat_priv->softif_neigh_vids, list) { |
186 | seq_printf(seq, "%s %pM (vid: %d)\n", | 347 | seq_printf(seq, " %-15s %s on vid: %d\n", |
187 | bat_priv->softif_neigh == softif_neigh | 348 | "Originator", "last-seen", softif_neigh_vid->vid); |
188 | ? "=>" : " ", softif_neigh->addr, | 349 | |
189 | softif_neigh->vid); | 350 | curr_softif_neigh = softif_neigh_get_selected(softif_neigh_vid); |
351 | |||
352 | hlist_for_each_entry_rcu(softif_neigh, node_tmp, | ||
353 | &softif_neigh_vid->softif_neigh_list, | ||
354 | list) { | ||
355 | last_seen_secs = jiffies_to_msecs(jiffies - | ||
356 | softif_neigh->last_seen) / 1000; | ||
357 | last_seen_msecs = jiffies_to_msecs(jiffies - | ||
358 | softif_neigh->last_seen) % 1000; | ||
359 | seq_printf(seq, "%s %pM %3i.%03is\n", | ||
360 | curr_softif_neigh == softif_neigh | ||
361 | ? "=>" : " ", softif_neigh->addr, | ||
362 | last_seen_secs, last_seen_msecs); | ||
363 | } | ||
364 | |||
365 | if (curr_softif_neigh) | ||
366 | softif_neigh_free_ref(curr_softif_neigh); | ||
367 | |||
368 | seq_printf(seq, "\n"); | ||
369 | } | ||
190 | rcu_read_unlock(); | 370 | rcu_read_unlock(); |
191 | 371 | ||
192 | return 0; | 372 | out: |
373 | if (primary_if) | ||
374 | hardif_free_ref(primary_if); | ||
375 | return ret; | ||
376 | } | ||
377 | |||
378 | void softif_neigh_purge(struct bat_priv *bat_priv) | ||
379 | { | ||
380 | struct softif_neigh *softif_neigh, *curr_softif_neigh; | ||
381 | struct softif_neigh_vid *softif_neigh_vid; | ||
382 | struct hlist_node *node, *node_tmp, *node_tmp2; | ||
383 | char do_deselect; | ||
384 | |||
385 | rcu_read_lock(); | ||
386 | hlist_for_each_entry_rcu(softif_neigh_vid, node, | ||
387 | &bat_priv->softif_neigh_vids, list) { | ||
388 | if (!atomic_inc_not_zero(&softif_neigh_vid->refcount)) | ||
389 | continue; | ||
390 | |||
391 | curr_softif_neigh = softif_neigh_get_selected(softif_neigh_vid); | ||
392 | do_deselect = 0; | ||
393 | |||
394 | spin_lock_bh(&bat_priv->softif_neigh_lock); | ||
395 | hlist_for_each_entry_safe(softif_neigh, node_tmp, node_tmp2, | ||
396 | &softif_neigh_vid->softif_neigh_list, | ||
397 | list) { | ||
398 | if ((!time_after(jiffies, softif_neigh->last_seen + | ||
399 | msecs_to_jiffies(SOFTIF_NEIGH_TIMEOUT))) && | ||
400 | (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE)) | ||
401 | continue; | ||
402 | |||
403 | if (curr_softif_neigh == softif_neigh) { | ||
404 | bat_dbg(DBG_ROUTES, bat_priv, | ||
405 | "Current mesh exit point on vid: %d " | ||
406 | "'%pM' vanished.\n", | ||
407 | softif_neigh_vid->vid, | ||
408 | softif_neigh->addr); | ||
409 | do_deselect = 1; | ||
410 | } | ||
411 | |||
412 | hlist_del_rcu(&softif_neigh->list); | ||
413 | softif_neigh_free_ref(softif_neigh); | ||
414 | } | ||
415 | spin_unlock_bh(&bat_priv->softif_neigh_lock); | ||
416 | |||
417 | /* soft_neigh_vid_deselect() needs to acquire the | ||
418 | * softif_neigh_lock */ | ||
419 | if (do_deselect) | ||
420 | softif_neigh_vid_deselect(bat_priv, softif_neigh_vid); | ||
421 | |||
422 | if (curr_softif_neigh) | ||
423 | softif_neigh_free_ref(curr_softif_neigh); | ||
424 | |||
425 | softif_neigh_vid_free_ref(softif_neigh_vid); | ||
426 | } | ||
427 | rcu_read_unlock(); | ||
428 | |||
429 | spin_lock_bh(&bat_priv->softif_neigh_vid_lock); | ||
430 | hlist_for_each_entry_safe(softif_neigh_vid, node, node_tmp, | ||
431 | &bat_priv->softif_neigh_vids, list) { | ||
432 | if (!hlist_empty(&softif_neigh_vid->softif_neigh_list)) | ||
433 | continue; | ||
434 | |||
435 | hlist_del_rcu(&softif_neigh_vid->list); | ||
436 | softif_neigh_vid_free_ref(softif_neigh_vid); | ||
437 | } | ||
438 | spin_unlock_bh(&bat_priv->softif_neigh_vid_lock); | ||
439 | |||
193 | } | 440 | } |
194 | 441 | ||
195 | static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev, | 442 | static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev, |
@@ -198,7 +445,9 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev, | |||
198 | struct bat_priv *bat_priv = netdev_priv(dev); | 445 | struct bat_priv *bat_priv = netdev_priv(dev); |
199 | struct ethhdr *ethhdr = (struct ethhdr *)skb->data; | 446 | struct ethhdr *ethhdr = (struct ethhdr *)skb->data; |
200 | struct batman_packet *batman_packet; | 447 | struct batman_packet *batman_packet; |
201 | struct softif_neigh *softif_neigh, *softif_neigh_tmp; | 448 | struct softif_neigh *softif_neigh = NULL; |
449 | struct hard_iface *primary_if = NULL; | ||
450 | struct softif_neigh *curr_softif_neigh = NULL; | ||
202 | 451 | ||
203 | if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) | 452 | if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) |
204 | batman_packet = (struct batman_packet *) | 453 | batman_packet = (struct batman_packet *) |
@@ -207,63 +456,52 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev, | |||
207 | batman_packet = (struct batman_packet *)(skb->data + ETH_HLEN); | 456 | batman_packet = (struct batman_packet *)(skb->data + ETH_HLEN); |
208 | 457 | ||
209 | if (batman_packet->version != COMPAT_VERSION) | 458 | if (batman_packet->version != COMPAT_VERSION) |
210 | goto err; | 459 | goto out; |
211 | 460 | ||
212 | if (batman_packet->packet_type != BAT_PACKET) | 461 | if (batman_packet->packet_type != BAT_PACKET) |
213 | goto err; | 462 | goto out; |
214 | 463 | ||
215 | if (!(batman_packet->flags & PRIMARIES_FIRST_HOP)) | 464 | if (!(batman_packet->flags & PRIMARIES_FIRST_HOP)) |
216 | goto err; | 465 | goto out; |
217 | 466 | ||
218 | if (is_my_mac(batman_packet->orig)) | 467 | if (is_my_mac(batman_packet->orig)) |
219 | goto err; | 468 | goto out; |
220 | 469 | ||
221 | softif_neigh = softif_neigh_get(bat_priv, batman_packet->orig, vid); | 470 | softif_neigh = softif_neigh_get(bat_priv, batman_packet->orig, vid); |
222 | |||
223 | if (!softif_neigh) | 471 | if (!softif_neigh) |
224 | goto err; | 472 | goto out; |
473 | |||
474 | curr_softif_neigh = softif_neigh_vid_get_selected(bat_priv, vid); | ||
475 | if (curr_softif_neigh == softif_neigh) | ||
476 | goto out; | ||
225 | 477 | ||
226 | if (bat_priv->softif_neigh == softif_neigh) | 478 | primary_if = primary_if_get_selected(bat_priv); |
479 | if (!primary_if) | ||
227 | goto out; | 480 | goto out; |
228 | 481 | ||
229 | /* we got a neighbor but its mac is 'bigger' than ours */ | 482 | /* we got a neighbor but its mac is 'bigger' than ours */ |
230 | if (memcmp(bat_priv->primary_if->net_dev->dev_addr, | 483 | if (memcmp(primary_if->net_dev->dev_addr, |
231 | softif_neigh->addr, ETH_ALEN) < 0) | 484 | softif_neigh->addr, ETH_ALEN) < 0) |
232 | goto out; | 485 | goto out; |
233 | 486 | ||
234 | /* switch to new 'smallest neighbor' */ | ||
235 | if ((bat_priv->softif_neigh) && | ||
236 | (memcmp(softif_neigh->addr, bat_priv->softif_neigh->addr, | ||
237 | ETH_ALEN) < 0)) { | ||
238 | bat_dbg(DBG_ROUTES, bat_priv, | ||
239 | "Changing mesh exit point from %pM (vid: %d) " | ||
240 | "to %pM (vid: %d).\n", | ||
241 | bat_priv->softif_neigh->addr, | ||
242 | bat_priv->softif_neigh->vid, | ||
243 | softif_neigh->addr, softif_neigh->vid); | ||
244 | softif_neigh_tmp = bat_priv->softif_neigh; | ||
245 | bat_priv->softif_neigh = softif_neigh; | ||
246 | softif_neigh_free_ref(softif_neigh_tmp); | ||
247 | /* we need to hold the additional reference */ | ||
248 | goto err; | ||
249 | } | ||
250 | |||
251 | /* close own batX device and use softif_neigh as exit node */ | 487 | /* close own batX device and use softif_neigh as exit node */ |
252 | if ((!bat_priv->softif_neigh) && | 488 | if (!curr_softif_neigh) { |
253 | (memcmp(softif_neigh->addr, | 489 | softif_neigh_vid_select(bat_priv, softif_neigh, vid); |
254 | bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN) < 0)) { | 490 | goto out; |
255 | bat_dbg(DBG_ROUTES, bat_priv, | ||
256 | "Setting mesh exit point to %pM (vid: %d).\n", | ||
257 | softif_neigh->addr, softif_neigh->vid); | ||
258 | bat_priv->softif_neigh = softif_neigh; | ||
259 | /* we need to hold the additional reference */ | ||
260 | goto err; | ||
261 | } | 491 | } |
262 | 492 | ||
493 | /* switch to new 'smallest neighbor' */ | ||
494 | if (memcmp(softif_neigh->addr, curr_softif_neigh->addr, ETH_ALEN) < 0) | ||
495 | softif_neigh_vid_select(bat_priv, softif_neigh, vid); | ||
496 | |||
263 | out: | 497 | out: |
264 | softif_neigh_free_ref(softif_neigh); | ||
265 | err: | ||
266 | kfree_skb(skb); | 498 | kfree_skb(skb); |
499 | if (softif_neigh) | ||
500 | softif_neigh_free_ref(softif_neigh); | ||
501 | if (curr_softif_neigh) | ||
502 | softif_neigh_free_ref(curr_softif_neigh); | ||
503 | if (primary_if) | ||
504 | hardif_free_ref(primary_if); | ||
267 | return; | 505 | return; |
268 | } | 506 | } |
269 | 507 | ||
@@ -293,11 +531,11 @@ static int interface_set_mac_addr(struct net_device *dev, void *p) | |||
293 | if (!is_valid_ether_addr(addr->sa_data)) | 531 | if (!is_valid_ether_addr(addr->sa_data)) |
294 | return -EADDRNOTAVAIL; | 532 | return -EADDRNOTAVAIL; |
295 | 533 | ||
296 | /* only modify hna-table if it has been initialised before */ | 534 | /* only modify transtable if it has been initialised before */ |
297 | if (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE) { | 535 | if (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE) { |
298 | hna_local_remove(bat_priv, dev->dev_addr, | 536 | tt_local_remove(bat_priv, dev->dev_addr, |
299 | "mac address changed"); | 537 | "mac address changed"); |
300 | hna_local_add(dev, addr->sa_data); | 538 | tt_local_add(dev, addr->sa_data); |
301 | } | 539 | } |
302 | 540 | ||
303 | memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); | 541 | memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); |
@@ -319,8 +557,10 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) | |||
319 | { | 557 | { |
320 | struct ethhdr *ethhdr = (struct ethhdr *)skb->data; | 558 | struct ethhdr *ethhdr = (struct ethhdr *)skb->data; |
321 | struct bat_priv *bat_priv = netdev_priv(soft_iface); | 559 | struct bat_priv *bat_priv = netdev_priv(soft_iface); |
560 | struct hard_iface *primary_if = NULL; | ||
322 | struct bcast_packet *bcast_packet; | 561 | struct bcast_packet *bcast_packet; |
323 | struct vlan_ethhdr *vhdr; | 562 | struct vlan_ethhdr *vhdr; |
563 | struct softif_neigh *curr_softif_neigh = NULL; | ||
324 | int data_len = skb->len, ret; | 564 | int data_len = skb->len, ret; |
325 | short vid = -1; | 565 | short vid = -1; |
326 | bool do_bcast = false; | 566 | bool do_bcast = false; |
@@ -348,11 +588,12 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) | |||
348 | * if we have a another chosen mesh exit node in range | 588 | * if we have a another chosen mesh exit node in range |
349 | * it will transport the packets to the mesh | 589 | * it will transport the packets to the mesh |
350 | */ | 590 | */ |
351 | if ((bat_priv->softif_neigh) && (bat_priv->softif_neigh->vid == vid)) | 591 | curr_softif_neigh = softif_neigh_vid_get_selected(bat_priv, vid); |
592 | if (curr_softif_neigh) | ||
352 | goto dropped; | 593 | goto dropped; |
353 | 594 | ||
354 | /* TODO: check this for locks */ | 595 | /* TODO: check this for locks */ |
355 | hna_local_add(soft_iface, ethhdr->h_source); | 596 | tt_local_add(soft_iface, ethhdr->h_source); |
356 | 597 | ||
357 | if (is_multicast_ether_addr(ethhdr->h_dest)) { | 598 | if (is_multicast_ether_addr(ethhdr->h_dest)) { |
358 | ret = gw_is_target(bat_priv, skb); | 599 | ret = gw_is_target(bat_priv, skb); |
@@ -366,7 +607,8 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) | |||
366 | 607 | ||
367 | /* ethernet packet should be broadcasted */ | 608 | /* ethernet packet should be broadcasted */ |
368 | if (do_bcast) { | 609 | if (do_bcast) { |
369 | if (!bat_priv->primary_if) | 610 | primary_if = primary_if_get_selected(bat_priv); |
611 | if (!primary_if) | ||
370 | goto dropped; | 612 | goto dropped; |
371 | 613 | ||
372 | if (my_skb_head_push(skb, sizeof(struct bcast_packet)) < 0) | 614 | if (my_skb_head_push(skb, sizeof(struct bcast_packet)) < 0) |
@@ -382,7 +624,7 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) | |||
382 | /* hw address of first interface is the orig mac because only | 624 | /* hw address of first interface is the orig mac because only |
383 | * this mac is known throughout the mesh */ | 625 | * this mac is known throughout the mesh */ |
384 | memcpy(bcast_packet->orig, | 626 | memcpy(bcast_packet->orig, |
385 | bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); | 627 | primary_if->net_dev->dev_addr, ETH_ALEN); |
386 | 628 | ||
387 | /* set broadcast sequence number */ | 629 | /* set broadcast sequence number */ |
388 | bcast_packet->seqno = | 630 | bcast_packet->seqno = |
@@ -410,6 +652,10 @@ dropped: | |||
410 | dropped_freed: | 652 | dropped_freed: |
411 | bat_priv->stats.tx_dropped++; | 653 | bat_priv->stats.tx_dropped++; |
412 | end: | 654 | end: |
655 | if (curr_softif_neigh) | ||
656 | softif_neigh_free_ref(curr_softif_neigh); | ||
657 | if (primary_if) | ||
658 | hardif_free_ref(primary_if); | ||
413 | return NETDEV_TX_OK; | 659 | return NETDEV_TX_OK; |
414 | } | 660 | } |
415 | 661 | ||
@@ -421,6 +667,7 @@ void interface_rx(struct net_device *soft_iface, | |||
421 | struct unicast_packet *unicast_packet; | 667 | struct unicast_packet *unicast_packet; |
422 | struct ethhdr *ethhdr; | 668 | struct ethhdr *ethhdr; |
423 | struct vlan_ethhdr *vhdr; | 669 | struct vlan_ethhdr *vhdr; |
670 | struct softif_neigh *curr_softif_neigh = NULL; | ||
424 | short vid = -1; | 671 | short vid = -1; |
425 | int ret; | 672 | int ret; |
426 | 673 | ||
@@ -450,7 +697,8 @@ void interface_rx(struct net_device *soft_iface, | |||
450 | * if we have a another chosen mesh exit node in range | 697 | * if we have a another chosen mesh exit node in range |
451 | * it will transport the packets to the non-mesh network | 698 | * it will transport the packets to the non-mesh network |
452 | */ | 699 | */ |
453 | if ((bat_priv->softif_neigh) && (bat_priv->softif_neigh->vid == vid)) { | 700 | curr_softif_neigh = softif_neigh_vid_get_selected(bat_priv, vid); |
701 | if (curr_softif_neigh) { | ||
454 | skb_push(skb, hdr_size); | 702 | skb_push(skb, hdr_size); |
455 | unicast_packet = (struct unicast_packet *)skb->data; | 703 | unicast_packet = (struct unicast_packet *)skb->data; |
456 | 704 | ||
@@ -461,7 +709,7 @@ void interface_rx(struct net_device *soft_iface, | |||
461 | skb_reset_mac_header(skb); | 709 | skb_reset_mac_header(skb); |
462 | 710 | ||
463 | memcpy(unicast_packet->dest, | 711 | memcpy(unicast_packet->dest, |
464 | bat_priv->softif_neigh->addr, ETH_ALEN); | 712 | curr_softif_neigh->addr, ETH_ALEN); |
465 | ret = route_unicast_packet(skb, recv_if); | 713 | ret = route_unicast_packet(skb, recv_if); |
466 | if (ret == NET_RX_DROP) | 714 | if (ret == NET_RX_DROP) |
467 | goto dropped; | 715 | goto dropped; |
@@ -486,11 +734,13 @@ void interface_rx(struct net_device *soft_iface, | |||
486 | soft_iface->last_rx = jiffies; | 734 | soft_iface->last_rx = jiffies; |
487 | 735 | ||
488 | netif_rx(skb); | 736 | netif_rx(skb); |
489 | return; | 737 | goto out; |
490 | 738 | ||
491 | dropped: | 739 | dropped: |
492 | kfree_skb(skb); | 740 | kfree_skb(skb); |
493 | out: | 741 | out: |
742 | if (curr_softif_neigh) | ||
743 | softif_neigh_free_ref(curr_softif_neigh); | ||
494 | return; | 744 | return; |
495 | } | 745 | } |
496 | 746 | ||
@@ -524,14 +774,15 @@ static void interface_setup(struct net_device *dev) | |||
524 | dev->hard_start_xmit = interface_tx; | 774 | dev->hard_start_xmit = interface_tx; |
525 | #endif | 775 | #endif |
526 | dev->destructor = free_netdev; | 776 | dev->destructor = free_netdev; |
777 | dev->tx_queue_len = 0; | ||
527 | 778 | ||
528 | /** | 779 | /** |
529 | * can't call min_mtu, because the needed variables | 780 | * can't call min_mtu, because the needed variables |
530 | * have not been initialized yet | 781 | * have not been initialized yet |
531 | */ | 782 | */ |
532 | dev->mtu = ETH_DATA_LEN; | 783 | dev->mtu = ETH_DATA_LEN; |
533 | dev->hard_header_len = BAT_HEADER_LEN; /* reserve more space in the | 784 | /* reserve more space in the skbuff for our header */ |
534 | * skbuff for our header */ | 785 | dev->hard_header_len = BAT_HEADER_LEN; |
535 | 786 | ||
536 | /* generate random address */ | 787 | /* generate random address */ |
537 | random_ether_addr(dev_addr); | 788 | random_ether_addr(dev_addr); |
@@ -556,7 +807,7 @@ struct net_device *softif_create(char *name) | |||
556 | goto out; | 807 | goto out; |
557 | } | 808 | } |
558 | 809 | ||
559 | ret = register_netdev(soft_iface); | 810 | ret = register_netdevice(soft_iface); |
560 | if (ret < 0) { | 811 | if (ret < 0) { |
561 | pr_err("Unable to register the batman interface '%s': %i\n", | 812 | pr_err("Unable to register the batman interface '%s': %i\n", |
562 | name, ret); | 813 | name, ret); |
@@ -580,11 +831,10 @@ struct net_device *softif_create(char *name) | |||
580 | 831 | ||
581 | atomic_set(&bat_priv->mesh_state, MESH_INACTIVE); | 832 | atomic_set(&bat_priv->mesh_state, MESH_INACTIVE); |
582 | atomic_set(&bat_priv->bcast_seqno, 1); | 833 | atomic_set(&bat_priv->bcast_seqno, 1); |
583 | atomic_set(&bat_priv->hna_local_changed, 0); | 834 | atomic_set(&bat_priv->tt_local_changed, 0); |
584 | 835 | ||
585 | bat_priv->primary_if = NULL; | 836 | bat_priv->primary_if = NULL; |
586 | bat_priv->num_ifaces = 0; | 837 | bat_priv->num_ifaces = 0; |
587 | bat_priv->softif_neigh = NULL; | ||
588 | 838 | ||
589 | ret = sysfs_add_meshif(soft_iface); | 839 | ret = sysfs_add_meshif(soft_iface); |
590 | if (ret < 0) | 840 | if (ret < 0) |
@@ -640,7 +890,7 @@ static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
640 | { | 890 | { |
641 | cmd->supported = 0; | 891 | cmd->supported = 0; |
642 | cmd->advertising = 0; | 892 | cmd->advertising = 0; |
643 | cmd->speed = SPEED_10; | 893 | ethtool_cmd_speed_set(cmd, SPEED_10); |
644 | cmd->duplex = DUPLEX_FULL; | 894 | cmd->duplex = DUPLEX_FULL; |
645 | cmd->port = PORT_TP; | 895 | cmd->port = PORT_TP; |
646 | cmd->phy_address = 0; | 896 | cmd->phy_address = 0; |
@@ -675,12 +925,3 @@ static u32 bat_get_link(struct net_device *dev) | |||
675 | return 1; | 925 | return 1; |
676 | } | 926 | } |
677 | 927 | ||
678 | static u32 bat_get_rx_csum(struct net_device *dev) | ||
679 | { | ||
680 | return 0; | ||
681 | } | ||
682 | |||
683 | static int bat_set_rx_csum(struct net_device *dev, u32 data) | ||
684 | { | ||
685 | return -EOPNOTSUPP; | ||
686 | } | ||
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index 8d15b48d1692..7b729660cbfd 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c | |||
@@ -22,43 +22,44 @@ | |||
22 | #include "main.h" | 22 | #include "main.h" |
23 | #include "translation-table.h" | 23 | #include "translation-table.h" |
24 | #include "soft-interface.h" | 24 | #include "soft-interface.h" |
25 | #include "hard-interface.h" | ||
25 | #include "hash.h" | 26 | #include "hash.h" |
26 | #include "originator.h" | 27 | #include "originator.h" |
27 | 28 | ||
28 | static void hna_local_purge(struct work_struct *work); | 29 | static void tt_local_purge(struct work_struct *work); |
29 | static void _hna_global_del_orig(struct bat_priv *bat_priv, | 30 | static void _tt_global_del_orig(struct bat_priv *bat_priv, |
30 | struct hna_global_entry *hna_global_entry, | 31 | struct tt_global_entry *tt_global_entry, |
31 | char *message); | 32 | char *message); |
32 | 33 | ||
33 | /* returns 1 if they are the same mac addr */ | 34 | /* returns 1 if they are the same mac addr */ |
34 | static int compare_lhna(struct hlist_node *node, void *data2) | 35 | static int compare_ltt(struct hlist_node *node, void *data2) |
35 | { | 36 | { |
36 | void *data1 = container_of(node, struct hna_local_entry, hash_entry); | 37 | void *data1 = container_of(node, struct tt_local_entry, hash_entry); |
37 | 38 | ||
38 | return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0); | 39 | return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0); |
39 | } | 40 | } |
40 | 41 | ||
41 | /* returns 1 if they are the same mac addr */ | 42 | /* returns 1 if they are the same mac addr */ |
42 | static int compare_ghna(struct hlist_node *node, void *data2) | 43 | static int compare_gtt(struct hlist_node *node, void *data2) |
43 | { | 44 | { |
44 | void *data1 = container_of(node, struct hna_global_entry, hash_entry); | 45 | void *data1 = container_of(node, struct tt_global_entry, hash_entry); |
45 | 46 | ||
46 | return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0); | 47 | return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0); |
47 | } | 48 | } |
48 | 49 | ||
49 | static void hna_local_start_timer(struct bat_priv *bat_priv) | 50 | static void tt_local_start_timer(struct bat_priv *bat_priv) |
50 | { | 51 | { |
51 | INIT_DELAYED_WORK(&bat_priv->hna_work, hna_local_purge); | 52 | INIT_DELAYED_WORK(&bat_priv->tt_work, tt_local_purge); |
52 | queue_delayed_work(bat_event_workqueue, &bat_priv->hna_work, 10 * HZ); | 53 | queue_delayed_work(bat_event_workqueue, &bat_priv->tt_work, 10 * HZ); |
53 | } | 54 | } |
54 | 55 | ||
55 | static struct hna_local_entry *hna_local_hash_find(struct bat_priv *bat_priv, | 56 | static struct tt_local_entry *tt_local_hash_find(struct bat_priv *bat_priv, |
56 | void *data) | 57 | void *data) |
57 | { | 58 | { |
58 | struct hashtable_t *hash = bat_priv->hna_local_hash; | 59 | struct hashtable_t *hash = bat_priv->tt_local_hash; |
59 | struct hlist_head *head; | 60 | struct hlist_head *head; |
60 | struct hlist_node *node; | 61 | struct hlist_node *node; |
61 | struct hna_local_entry *hna_local_entry, *hna_local_entry_tmp = NULL; | 62 | struct tt_local_entry *tt_local_entry, *tt_local_entry_tmp = NULL; |
62 | int index; | 63 | int index; |
63 | 64 | ||
64 | if (!hash) | 65 | if (!hash) |
@@ -68,26 +69,26 @@ static struct hna_local_entry *hna_local_hash_find(struct bat_priv *bat_priv, | |||
68 | head = &hash->table[index]; | 69 | head = &hash->table[index]; |
69 | 70 | ||
70 | rcu_read_lock(); | 71 | rcu_read_lock(); |
71 | hlist_for_each_entry_rcu(hna_local_entry, node, head, hash_entry) { | 72 | hlist_for_each_entry_rcu(tt_local_entry, node, head, hash_entry) { |
72 | if (!compare_eth(hna_local_entry, data)) | 73 | if (!compare_eth(tt_local_entry, data)) |
73 | continue; | 74 | continue; |
74 | 75 | ||
75 | hna_local_entry_tmp = hna_local_entry; | 76 | tt_local_entry_tmp = tt_local_entry; |
76 | break; | 77 | break; |
77 | } | 78 | } |
78 | rcu_read_unlock(); | 79 | rcu_read_unlock(); |
79 | 80 | ||
80 | return hna_local_entry_tmp; | 81 | return tt_local_entry_tmp; |
81 | } | 82 | } |
82 | 83 | ||
83 | static struct hna_global_entry *hna_global_hash_find(struct bat_priv *bat_priv, | 84 | static struct tt_global_entry *tt_global_hash_find(struct bat_priv *bat_priv, |
84 | void *data) | 85 | void *data) |
85 | { | 86 | { |
86 | struct hashtable_t *hash = bat_priv->hna_global_hash; | 87 | struct hashtable_t *hash = bat_priv->tt_global_hash; |
87 | struct hlist_head *head; | 88 | struct hlist_head *head; |
88 | struct hlist_node *node; | 89 | struct hlist_node *node; |
89 | struct hna_global_entry *hna_global_entry; | 90 | struct tt_global_entry *tt_global_entry; |
90 | struct hna_global_entry *hna_global_entry_tmp = NULL; | 91 | struct tt_global_entry *tt_global_entry_tmp = NULL; |
91 | int index; | 92 | int index; |
92 | 93 | ||
93 | if (!hash) | 94 | if (!hash) |
@@ -97,125 +98,125 @@ static struct hna_global_entry *hna_global_hash_find(struct bat_priv *bat_priv, | |||
97 | head = &hash->table[index]; | 98 | head = &hash->table[index]; |
98 | 99 | ||
99 | rcu_read_lock(); | 100 | rcu_read_lock(); |
100 | hlist_for_each_entry_rcu(hna_global_entry, node, head, hash_entry) { | 101 | hlist_for_each_entry_rcu(tt_global_entry, node, head, hash_entry) { |
101 | if (!compare_eth(hna_global_entry, data)) | 102 | if (!compare_eth(tt_global_entry, data)) |
102 | continue; | 103 | continue; |
103 | 104 | ||
104 | hna_global_entry_tmp = hna_global_entry; | 105 | tt_global_entry_tmp = tt_global_entry; |
105 | break; | 106 | break; |
106 | } | 107 | } |
107 | rcu_read_unlock(); | 108 | rcu_read_unlock(); |
108 | 109 | ||
109 | return hna_global_entry_tmp; | 110 | return tt_global_entry_tmp; |
110 | } | 111 | } |
111 | 112 | ||
112 | int hna_local_init(struct bat_priv *bat_priv) | 113 | int tt_local_init(struct bat_priv *bat_priv) |
113 | { | 114 | { |
114 | if (bat_priv->hna_local_hash) | 115 | if (bat_priv->tt_local_hash) |
115 | return 1; | 116 | return 1; |
116 | 117 | ||
117 | bat_priv->hna_local_hash = hash_new(1024); | 118 | bat_priv->tt_local_hash = hash_new(1024); |
118 | 119 | ||
119 | if (!bat_priv->hna_local_hash) | 120 | if (!bat_priv->tt_local_hash) |
120 | return 0; | 121 | return 0; |
121 | 122 | ||
122 | atomic_set(&bat_priv->hna_local_changed, 0); | 123 | atomic_set(&bat_priv->tt_local_changed, 0); |
123 | hna_local_start_timer(bat_priv); | 124 | tt_local_start_timer(bat_priv); |
124 | 125 | ||
125 | return 1; | 126 | return 1; |
126 | } | 127 | } |
127 | 128 | ||
128 | void hna_local_add(struct net_device *soft_iface, uint8_t *addr) | 129 | void tt_local_add(struct net_device *soft_iface, uint8_t *addr) |
129 | { | 130 | { |
130 | struct bat_priv *bat_priv = netdev_priv(soft_iface); | 131 | struct bat_priv *bat_priv = netdev_priv(soft_iface); |
131 | struct hna_local_entry *hna_local_entry; | 132 | struct tt_local_entry *tt_local_entry; |
132 | struct hna_global_entry *hna_global_entry; | 133 | struct tt_global_entry *tt_global_entry; |
133 | int required_bytes; | 134 | int required_bytes; |
134 | 135 | ||
135 | spin_lock_bh(&bat_priv->hna_lhash_lock); | 136 | spin_lock_bh(&bat_priv->tt_lhash_lock); |
136 | hna_local_entry = hna_local_hash_find(bat_priv, addr); | 137 | tt_local_entry = tt_local_hash_find(bat_priv, addr); |
137 | spin_unlock_bh(&bat_priv->hna_lhash_lock); | 138 | spin_unlock_bh(&bat_priv->tt_lhash_lock); |
138 | 139 | ||
139 | if (hna_local_entry) { | 140 | if (tt_local_entry) { |
140 | hna_local_entry->last_seen = jiffies; | 141 | tt_local_entry->last_seen = jiffies; |
141 | return; | 142 | return; |
142 | } | 143 | } |
143 | 144 | ||
144 | /* only announce as many hosts as possible in the batman-packet and | 145 | /* only announce as many hosts as possible in the batman-packet and |
145 | space in batman_packet->num_hna That also should give a limit to | 146 | space in batman_packet->num_tt That also should give a limit to |
146 | MAC-flooding. */ | 147 | MAC-flooding. */ |
147 | required_bytes = (bat_priv->num_local_hna + 1) * ETH_ALEN; | 148 | required_bytes = (bat_priv->num_local_tt + 1) * ETH_ALEN; |
148 | required_bytes += BAT_PACKET_LEN; | 149 | required_bytes += BAT_PACKET_LEN; |
149 | 150 | ||
150 | if ((required_bytes > ETH_DATA_LEN) || | 151 | if ((required_bytes > ETH_DATA_LEN) || |
151 | (atomic_read(&bat_priv->aggregated_ogms) && | 152 | (atomic_read(&bat_priv->aggregated_ogms) && |
152 | required_bytes > MAX_AGGREGATION_BYTES) || | 153 | required_bytes > MAX_AGGREGATION_BYTES) || |
153 | (bat_priv->num_local_hna + 1 > 255)) { | 154 | (bat_priv->num_local_tt + 1 > 255)) { |
154 | bat_dbg(DBG_ROUTES, bat_priv, | 155 | bat_dbg(DBG_ROUTES, bat_priv, |
155 | "Can't add new local hna entry (%pM): " | 156 | "Can't add new local tt entry (%pM): " |
156 | "number of local hna entries exceeds packet size\n", | 157 | "number of local tt entries exceeds packet size\n", |
157 | addr); | 158 | addr); |
158 | return; | 159 | return; |
159 | } | 160 | } |
160 | 161 | ||
161 | bat_dbg(DBG_ROUTES, bat_priv, | 162 | bat_dbg(DBG_ROUTES, bat_priv, |
162 | "Creating new local hna entry: %pM\n", addr); | 163 | "Creating new local tt entry: %pM\n", addr); |
163 | 164 | ||
164 | hna_local_entry = kmalloc(sizeof(struct hna_local_entry), GFP_ATOMIC); | 165 | tt_local_entry = kmalloc(sizeof(struct tt_local_entry), GFP_ATOMIC); |
165 | if (!hna_local_entry) | 166 | if (!tt_local_entry) |
166 | return; | 167 | return; |
167 | 168 | ||
168 | memcpy(hna_local_entry->addr, addr, ETH_ALEN); | 169 | memcpy(tt_local_entry->addr, addr, ETH_ALEN); |
169 | hna_local_entry->last_seen = jiffies; | 170 | tt_local_entry->last_seen = jiffies; |
170 | 171 | ||
171 | /* the batman interface mac address should never be purged */ | 172 | /* the batman interface mac address should never be purged */ |
172 | if (compare_eth(addr, soft_iface->dev_addr)) | 173 | if (compare_eth(addr, soft_iface->dev_addr)) |
173 | hna_local_entry->never_purge = 1; | 174 | tt_local_entry->never_purge = 1; |
174 | else | 175 | else |
175 | hna_local_entry->never_purge = 0; | 176 | tt_local_entry->never_purge = 0; |
176 | 177 | ||
177 | spin_lock_bh(&bat_priv->hna_lhash_lock); | 178 | spin_lock_bh(&bat_priv->tt_lhash_lock); |
178 | 179 | ||
179 | hash_add(bat_priv->hna_local_hash, compare_lhna, choose_orig, | 180 | hash_add(bat_priv->tt_local_hash, compare_ltt, choose_orig, |
180 | hna_local_entry, &hna_local_entry->hash_entry); | 181 | tt_local_entry, &tt_local_entry->hash_entry); |
181 | bat_priv->num_local_hna++; | 182 | bat_priv->num_local_tt++; |
182 | atomic_set(&bat_priv->hna_local_changed, 1); | 183 | atomic_set(&bat_priv->tt_local_changed, 1); |
183 | 184 | ||
184 | spin_unlock_bh(&bat_priv->hna_lhash_lock); | 185 | spin_unlock_bh(&bat_priv->tt_lhash_lock); |
185 | 186 | ||
186 | /* remove address from global hash if present */ | 187 | /* remove address from global hash if present */ |
187 | spin_lock_bh(&bat_priv->hna_ghash_lock); | 188 | spin_lock_bh(&bat_priv->tt_ghash_lock); |
188 | 189 | ||
189 | hna_global_entry = hna_global_hash_find(bat_priv, addr); | 190 | tt_global_entry = tt_global_hash_find(bat_priv, addr); |
190 | 191 | ||
191 | if (hna_global_entry) | 192 | if (tt_global_entry) |
192 | _hna_global_del_orig(bat_priv, hna_global_entry, | 193 | _tt_global_del_orig(bat_priv, tt_global_entry, |
193 | "local hna received"); | 194 | "local tt received"); |
194 | 195 | ||
195 | spin_unlock_bh(&bat_priv->hna_ghash_lock); | 196 | spin_unlock_bh(&bat_priv->tt_ghash_lock); |
196 | } | 197 | } |
197 | 198 | ||
198 | int hna_local_fill_buffer(struct bat_priv *bat_priv, | 199 | int tt_local_fill_buffer(struct bat_priv *bat_priv, |
199 | unsigned char *buff, int buff_len) | 200 | unsigned char *buff, int buff_len) |
200 | { | 201 | { |
201 | struct hashtable_t *hash = bat_priv->hna_local_hash; | 202 | struct hashtable_t *hash = bat_priv->tt_local_hash; |
202 | struct hna_local_entry *hna_local_entry; | 203 | struct tt_local_entry *tt_local_entry; |
203 | struct hlist_node *node; | 204 | struct hlist_node *node; |
204 | struct hlist_head *head; | 205 | struct hlist_head *head; |
205 | int i, count = 0; | 206 | int i, count = 0; |
206 | 207 | ||
207 | spin_lock_bh(&bat_priv->hna_lhash_lock); | 208 | spin_lock_bh(&bat_priv->tt_lhash_lock); |
208 | 209 | ||
209 | for (i = 0; i < hash->size; i++) { | 210 | for (i = 0; i < hash->size; i++) { |
210 | head = &hash->table[i]; | 211 | head = &hash->table[i]; |
211 | 212 | ||
212 | rcu_read_lock(); | 213 | rcu_read_lock(); |
213 | hlist_for_each_entry_rcu(hna_local_entry, node, | 214 | hlist_for_each_entry_rcu(tt_local_entry, node, |
214 | head, hash_entry) { | 215 | head, hash_entry) { |
215 | if (buff_len < (count + 1) * ETH_ALEN) | 216 | if (buff_len < (count + 1) * ETH_ALEN) |
216 | break; | 217 | break; |
217 | 218 | ||
218 | memcpy(buff + (count * ETH_ALEN), hna_local_entry->addr, | 219 | memcpy(buff + (count * ETH_ALEN), tt_local_entry->addr, |
219 | ETH_ALEN); | 220 | ETH_ALEN); |
220 | 221 | ||
221 | count++; | 222 | count++; |
@@ -223,37 +224,47 @@ int hna_local_fill_buffer(struct bat_priv *bat_priv, | |||
223 | rcu_read_unlock(); | 224 | rcu_read_unlock(); |
224 | } | 225 | } |
225 | 226 | ||
226 | /* if we did not get all new local hnas see you next time ;-) */ | 227 | /* if we did not get all new local tts see you next time ;-) */ |
227 | if (count == bat_priv->num_local_hna) | 228 | if (count == bat_priv->num_local_tt) |
228 | atomic_set(&bat_priv->hna_local_changed, 0); | 229 | atomic_set(&bat_priv->tt_local_changed, 0); |
229 | 230 | ||
230 | spin_unlock_bh(&bat_priv->hna_lhash_lock); | 231 | spin_unlock_bh(&bat_priv->tt_lhash_lock); |
231 | return count; | 232 | return count; |
232 | } | 233 | } |
233 | 234 | ||
234 | int hna_local_seq_print_text(struct seq_file *seq, void *offset) | 235 | int tt_local_seq_print_text(struct seq_file *seq, void *offset) |
235 | { | 236 | { |
236 | struct net_device *net_dev = (struct net_device *)seq->private; | 237 | struct net_device *net_dev = (struct net_device *)seq->private; |
237 | struct bat_priv *bat_priv = netdev_priv(net_dev); | 238 | struct bat_priv *bat_priv = netdev_priv(net_dev); |
238 | struct hashtable_t *hash = bat_priv->hna_local_hash; | 239 | struct hashtable_t *hash = bat_priv->tt_local_hash; |
239 | struct hna_local_entry *hna_local_entry; | 240 | struct tt_local_entry *tt_local_entry; |
241 | struct hard_iface *primary_if; | ||
240 | struct hlist_node *node; | 242 | struct hlist_node *node; |
241 | struct hlist_head *head; | 243 | struct hlist_head *head; |
242 | size_t buf_size, pos; | 244 | size_t buf_size, pos; |
243 | char *buff; | 245 | char *buff; |
244 | int i; | 246 | int i, ret = 0; |
245 | 247 | ||
246 | if (!bat_priv->primary_if) { | 248 | primary_if = primary_if_get_selected(bat_priv); |
247 | return seq_printf(seq, "BATMAN mesh %s disabled - " | 249 | if (!primary_if) { |
248 | "please specify interfaces to enable it\n", | 250 | ret = seq_printf(seq, "BATMAN mesh %s disabled - " |
249 | net_dev->name); | 251 | "please specify interfaces to enable it\n", |
252 | net_dev->name); | ||
253 | goto out; | ||
254 | } | ||
255 | |||
256 | if (primary_if->if_status != IF_ACTIVE) { | ||
257 | ret = seq_printf(seq, "BATMAN mesh %s disabled - " | ||
258 | "primary interface not active\n", | ||
259 | net_dev->name); | ||
260 | goto out; | ||
250 | } | 261 | } |
251 | 262 | ||
252 | seq_printf(seq, "Locally retrieved addresses (from %s) " | 263 | seq_printf(seq, "Locally retrieved addresses (from %s) " |
253 | "announced via HNA:\n", | 264 | "announced via TT:\n", |
254 | net_dev->name); | 265 | net_dev->name); |
255 | 266 | ||
256 | spin_lock_bh(&bat_priv->hna_lhash_lock); | 267 | spin_lock_bh(&bat_priv->tt_lhash_lock); |
257 | 268 | ||
258 | buf_size = 1; | 269 | buf_size = 1; |
259 | /* Estimate length for: " * xx:xx:xx:xx:xx:xx\n" */ | 270 | /* Estimate length for: " * xx:xx:xx:xx:xx:xx\n" */ |
@@ -268,8 +279,9 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset) | |||
268 | 279 | ||
269 | buff = kmalloc(buf_size, GFP_ATOMIC); | 280 | buff = kmalloc(buf_size, GFP_ATOMIC); |
270 | if (!buff) { | 281 | if (!buff) { |
271 | spin_unlock_bh(&bat_priv->hna_lhash_lock); | 282 | spin_unlock_bh(&bat_priv->tt_lhash_lock); |
272 | return -ENOMEM; | 283 | ret = -ENOMEM; |
284 | goto out; | ||
273 | } | 285 | } |
274 | 286 | ||
275 | buff[0] = '\0'; | 287 | buff[0] = '\0'; |
@@ -279,211 +291,225 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset) | |||
279 | head = &hash->table[i]; | 291 | head = &hash->table[i]; |
280 | 292 | ||
281 | rcu_read_lock(); | 293 | rcu_read_lock(); |
282 | hlist_for_each_entry_rcu(hna_local_entry, node, | 294 | hlist_for_each_entry_rcu(tt_local_entry, node, |
283 | head, hash_entry) { | 295 | head, hash_entry) { |
284 | pos += snprintf(buff + pos, 22, " * %pM\n", | 296 | pos += snprintf(buff + pos, 22, " * %pM\n", |
285 | hna_local_entry->addr); | 297 | tt_local_entry->addr); |
286 | } | 298 | } |
287 | rcu_read_unlock(); | 299 | rcu_read_unlock(); |
288 | } | 300 | } |
289 | 301 | ||
290 | spin_unlock_bh(&bat_priv->hna_lhash_lock); | 302 | spin_unlock_bh(&bat_priv->tt_lhash_lock); |
291 | 303 | ||
292 | seq_printf(seq, "%s", buff); | 304 | seq_printf(seq, "%s", buff); |
293 | kfree(buff); | 305 | kfree(buff); |
294 | return 0; | 306 | out: |
307 | if (primary_if) | ||
308 | hardif_free_ref(primary_if); | ||
309 | return ret; | ||
295 | } | 310 | } |
296 | 311 | ||
297 | static void _hna_local_del(struct hlist_node *node, void *arg) | 312 | static void _tt_local_del(struct hlist_node *node, void *arg) |
298 | { | 313 | { |
299 | struct bat_priv *bat_priv = (struct bat_priv *)arg; | 314 | struct bat_priv *bat_priv = (struct bat_priv *)arg; |
300 | void *data = container_of(node, struct hna_local_entry, hash_entry); | 315 | void *data = container_of(node, struct tt_local_entry, hash_entry); |
301 | 316 | ||
302 | kfree(data); | 317 | kfree(data); |
303 | bat_priv->num_local_hna--; | 318 | bat_priv->num_local_tt--; |
304 | atomic_set(&bat_priv->hna_local_changed, 1); | 319 | atomic_set(&bat_priv->tt_local_changed, 1); |
305 | } | 320 | } |
306 | 321 | ||
307 | static void hna_local_del(struct bat_priv *bat_priv, | 322 | static void tt_local_del(struct bat_priv *bat_priv, |
308 | struct hna_local_entry *hna_local_entry, | 323 | struct tt_local_entry *tt_local_entry, |
309 | char *message) | 324 | char *message) |
310 | { | 325 | { |
311 | bat_dbg(DBG_ROUTES, bat_priv, "Deleting local hna entry (%pM): %s\n", | 326 | bat_dbg(DBG_ROUTES, bat_priv, "Deleting local tt entry (%pM): %s\n", |
312 | hna_local_entry->addr, message); | 327 | tt_local_entry->addr, message); |
313 | 328 | ||
314 | hash_remove(bat_priv->hna_local_hash, compare_lhna, choose_orig, | 329 | hash_remove(bat_priv->tt_local_hash, compare_ltt, choose_orig, |
315 | hna_local_entry->addr); | 330 | tt_local_entry->addr); |
316 | _hna_local_del(&hna_local_entry->hash_entry, bat_priv); | 331 | _tt_local_del(&tt_local_entry->hash_entry, bat_priv); |
317 | } | 332 | } |
318 | 333 | ||
319 | void hna_local_remove(struct bat_priv *bat_priv, | 334 | void tt_local_remove(struct bat_priv *bat_priv, |
320 | uint8_t *addr, char *message) | 335 | uint8_t *addr, char *message) |
321 | { | 336 | { |
322 | struct hna_local_entry *hna_local_entry; | 337 | struct tt_local_entry *tt_local_entry; |
323 | 338 | ||
324 | spin_lock_bh(&bat_priv->hna_lhash_lock); | 339 | spin_lock_bh(&bat_priv->tt_lhash_lock); |
325 | 340 | ||
326 | hna_local_entry = hna_local_hash_find(bat_priv, addr); | 341 | tt_local_entry = tt_local_hash_find(bat_priv, addr); |
327 | 342 | ||
328 | if (hna_local_entry) | 343 | if (tt_local_entry) |
329 | hna_local_del(bat_priv, hna_local_entry, message); | 344 | tt_local_del(bat_priv, tt_local_entry, message); |
330 | 345 | ||
331 | spin_unlock_bh(&bat_priv->hna_lhash_lock); | 346 | spin_unlock_bh(&bat_priv->tt_lhash_lock); |
332 | } | 347 | } |
333 | 348 | ||
334 | static void hna_local_purge(struct work_struct *work) | 349 | static void tt_local_purge(struct work_struct *work) |
335 | { | 350 | { |
336 | struct delayed_work *delayed_work = | 351 | struct delayed_work *delayed_work = |
337 | container_of(work, struct delayed_work, work); | 352 | container_of(work, struct delayed_work, work); |
338 | struct bat_priv *bat_priv = | 353 | struct bat_priv *bat_priv = |
339 | container_of(delayed_work, struct bat_priv, hna_work); | 354 | container_of(delayed_work, struct bat_priv, tt_work); |
340 | struct hashtable_t *hash = bat_priv->hna_local_hash; | 355 | struct hashtable_t *hash = bat_priv->tt_local_hash; |
341 | struct hna_local_entry *hna_local_entry; | 356 | struct tt_local_entry *tt_local_entry; |
342 | struct hlist_node *node, *node_tmp; | 357 | struct hlist_node *node, *node_tmp; |
343 | struct hlist_head *head; | 358 | struct hlist_head *head; |
344 | unsigned long timeout; | 359 | unsigned long timeout; |
345 | int i; | 360 | int i; |
346 | 361 | ||
347 | spin_lock_bh(&bat_priv->hna_lhash_lock); | 362 | spin_lock_bh(&bat_priv->tt_lhash_lock); |
348 | 363 | ||
349 | for (i = 0; i < hash->size; i++) { | 364 | for (i = 0; i < hash->size; i++) { |
350 | head = &hash->table[i]; | 365 | head = &hash->table[i]; |
351 | 366 | ||
352 | hlist_for_each_entry_safe(hna_local_entry, node, node_tmp, | 367 | hlist_for_each_entry_safe(tt_local_entry, node, node_tmp, |
353 | head, hash_entry) { | 368 | head, hash_entry) { |
354 | if (hna_local_entry->never_purge) | 369 | if (tt_local_entry->never_purge) |
355 | continue; | 370 | continue; |
356 | 371 | ||
357 | timeout = hna_local_entry->last_seen; | 372 | timeout = tt_local_entry->last_seen; |
358 | timeout += LOCAL_HNA_TIMEOUT * HZ; | 373 | timeout += TT_LOCAL_TIMEOUT * HZ; |
359 | 374 | ||
360 | if (time_before(jiffies, timeout)) | 375 | if (time_before(jiffies, timeout)) |
361 | continue; | 376 | continue; |
362 | 377 | ||
363 | hna_local_del(bat_priv, hna_local_entry, | 378 | tt_local_del(bat_priv, tt_local_entry, |
364 | "address timed out"); | 379 | "address timed out"); |
365 | } | 380 | } |
366 | } | 381 | } |
367 | 382 | ||
368 | spin_unlock_bh(&bat_priv->hna_lhash_lock); | 383 | spin_unlock_bh(&bat_priv->tt_lhash_lock); |
369 | hna_local_start_timer(bat_priv); | 384 | tt_local_start_timer(bat_priv); |
370 | } | 385 | } |
371 | 386 | ||
372 | void hna_local_free(struct bat_priv *bat_priv) | 387 | void tt_local_free(struct bat_priv *bat_priv) |
373 | { | 388 | { |
374 | if (!bat_priv->hna_local_hash) | 389 | if (!bat_priv->tt_local_hash) |
375 | return; | 390 | return; |
376 | 391 | ||
377 | cancel_delayed_work_sync(&bat_priv->hna_work); | 392 | cancel_delayed_work_sync(&bat_priv->tt_work); |
378 | hash_delete(bat_priv->hna_local_hash, _hna_local_del, bat_priv); | 393 | hash_delete(bat_priv->tt_local_hash, _tt_local_del, bat_priv); |
379 | bat_priv->hna_local_hash = NULL; | 394 | bat_priv->tt_local_hash = NULL; |
380 | } | 395 | } |
381 | 396 | ||
382 | int hna_global_init(struct bat_priv *bat_priv) | 397 | int tt_global_init(struct bat_priv *bat_priv) |
383 | { | 398 | { |
384 | if (bat_priv->hna_global_hash) | 399 | if (bat_priv->tt_global_hash) |
385 | return 1; | 400 | return 1; |
386 | 401 | ||
387 | bat_priv->hna_global_hash = hash_new(1024); | 402 | bat_priv->tt_global_hash = hash_new(1024); |
388 | 403 | ||
389 | if (!bat_priv->hna_global_hash) | 404 | if (!bat_priv->tt_global_hash) |
390 | return 0; | 405 | return 0; |
391 | 406 | ||
392 | return 1; | 407 | return 1; |
393 | } | 408 | } |
394 | 409 | ||
395 | void hna_global_add_orig(struct bat_priv *bat_priv, | 410 | void tt_global_add_orig(struct bat_priv *bat_priv, |
396 | struct orig_node *orig_node, | 411 | struct orig_node *orig_node, |
397 | unsigned char *hna_buff, int hna_buff_len) | 412 | unsigned char *tt_buff, int tt_buff_len) |
398 | { | 413 | { |
399 | struct hna_global_entry *hna_global_entry; | 414 | struct tt_global_entry *tt_global_entry; |
400 | struct hna_local_entry *hna_local_entry; | 415 | struct tt_local_entry *tt_local_entry; |
401 | int hna_buff_count = 0; | 416 | int tt_buff_count = 0; |
402 | unsigned char *hna_ptr; | 417 | unsigned char *tt_ptr; |
403 | 418 | ||
404 | while ((hna_buff_count + 1) * ETH_ALEN <= hna_buff_len) { | 419 | while ((tt_buff_count + 1) * ETH_ALEN <= tt_buff_len) { |
405 | spin_lock_bh(&bat_priv->hna_ghash_lock); | 420 | spin_lock_bh(&bat_priv->tt_ghash_lock); |
406 | 421 | ||
407 | hna_ptr = hna_buff + (hna_buff_count * ETH_ALEN); | 422 | tt_ptr = tt_buff + (tt_buff_count * ETH_ALEN); |
408 | hna_global_entry = hna_global_hash_find(bat_priv, hna_ptr); | 423 | tt_global_entry = tt_global_hash_find(bat_priv, tt_ptr); |
409 | 424 | ||
410 | if (!hna_global_entry) { | 425 | if (!tt_global_entry) { |
411 | spin_unlock_bh(&bat_priv->hna_ghash_lock); | 426 | spin_unlock_bh(&bat_priv->tt_ghash_lock); |
412 | 427 | ||
413 | hna_global_entry = | 428 | tt_global_entry = |
414 | kmalloc(sizeof(struct hna_global_entry), | 429 | kmalloc(sizeof(struct tt_global_entry), |
415 | GFP_ATOMIC); | 430 | GFP_ATOMIC); |
416 | 431 | ||
417 | if (!hna_global_entry) | 432 | if (!tt_global_entry) |
418 | break; | 433 | break; |
419 | 434 | ||
420 | memcpy(hna_global_entry->addr, hna_ptr, ETH_ALEN); | 435 | memcpy(tt_global_entry->addr, tt_ptr, ETH_ALEN); |
421 | 436 | ||
422 | bat_dbg(DBG_ROUTES, bat_priv, | 437 | bat_dbg(DBG_ROUTES, bat_priv, |
423 | "Creating new global hna entry: " | 438 | "Creating new global tt entry: " |
424 | "%pM (via %pM)\n", | 439 | "%pM (via %pM)\n", |
425 | hna_global_entry->addr, orig_node->orig); | 440 | tt_global_entry->addr, orig_node->orig); |
426 | 441 | ||
427 | spin_lock_bh(&bat_priv->hna_ghash_lock); | 442 | spin_lock_bh(&bat_priv->tt_ghash_lock); |
428 | hash_add(bat_priv->hna_global_hash, compare_ghna, | 443 | hash_add(bat_priv->tt_global_hash, compare_gtt, |
429 | choose_orig, hna_global_entry, | 444 | choose_orig, tt_global_entry, |
430 | &hna_global_entry->hash_entry); | 445 | &tt_global_entry->hash_entry); |
431 | 446 | ||
432 | } | 447 | } |
433 | 448 | ||
434 | hna_global_entry->orig_node = orig_node; | 449 | tt_global_entry->orig_node = orig_node; |
435 | spin_unlock_bh(&bat_priv->hna_ghash_lock); | 450 | spin_unlock_bh(&bat_priv->tt_ghash_lock); |
436 | 451 | ||
437 | /* remove address from local hash if present */ | 452 | /* remove address from local hash if present */ |
438 | spin_lock_bh(&bat_priv->hna_lhash_lock); | 453 | spin_lock_bh(&bat_priv->tt_lhash_lock); |
439 | 454 | ||
440 | hna_ptr = hna_buff + (hna_buff_count * ETH_ALEN); | 455 | tt_ptr = tt_buff + (tt_buff_count * ETH_ALEN); |
441 | hna_local_entry = hna_local_hash_find(bat_priv, hna_ptr); | 456 | tt_local_entry = tt_local_hash_find(bat_priv, tt_ptr); |
442 | 457 | ||
443 | if (hna_local_entry) | 458 | if (tt_local_entry) |
444 | hna_local_del(bat_priv, hna_local_entry, | 459 | tt_local_del(bat_priv, tt_local_entry, |
445 | "global hna received"); | 460 | "global tt received"); |
446 | 461 | ||
447 | spin_unlock_bh(&bat_priv->hna_lhash_lock); | 462 | spin_unlock_bh(&bat_priv->tt_lhash_lock); |
448 | 463 | ||
449 | hna_buff_count++; | 464 | tt_buff_count++; |
450 | } | 465 | } |
451 | 466 | ||
452 | /* initialize, and overwrite if malloc succeeds */ | 467 | /* initialize, and overwrite if malloc succeeds */ |
453 | orig_node->hna_buff = NULL; | 468 | orig_node->tt_buff = NULL; |
454 | orig_node->hna_buff_len = 0; | 469 | orig_node->tt_buff_len = 0; |
455 | 470 | ||
456 | if (hna_buff_len > 0) { | 471 | if (tt_buff_len > 0) { |
457 | orig_node->hna_buff = kmalloc(hna_buff_len, GFP_ATOMIC); | 472 | orig_node->tt_buff = kmalloc(tt_buff_len, GFP_ATOMIC); |
458 | if (orig_node->hna_buff) { | 473 | if (orig_node->tt_buff) { |
459 | memcpy(orig_node->hna_buff, hna_buff, hna_buff_len); | 474 | memcpy(orig_node->tt_buff, tt_buff, tt_buff_len); |
460 | orig_node->hna_buff_len = hna_buff_len; | 475 | orig_node->tt_buff_len = tt_buff_len; |
461 | } | 476 | } |
462 | } | 477 | } |
463 | } | 478 | } |
464 | 479 | ||
465 | int hna_global_seq_print_text(struct seq_file *seq, void *offset) | 480 | int tt_global_seq_print_text(struct seq_file *seq, void *offset) |
466 | { | 481 | { |
467 | struct net_device *net_dev = (struct net_device *)seq->private; | 482 | struct net_device *net_dev = (struct net_device *)seq->private; |
468 | struct bat_priv *bat_priv = netdev_priv(net_dev); | 483 | struct bat_priv *bat_priv = netdev_priv(net_dev); |
469 | struct hashtable_t *hash = bat_priv->hna_global_hash; | 484 | struct hashtable_t *hash = bat_priv->tt_global_hash; |
470 | struct hna_global_entry *hna_global_entry; | 485 | struct tt_global_entry *tt_global_entry; |
486 | struct hard_iface *primary_if; | ||
471 | struct hlist_node *node; | 487 | struct hlist_node *node; |
472 | struct hlist_head *head; | 488 | struct hlist_head *head; |
473 | size_t buf_size, pos; | 489 | size_t buf_size, pos; |
474 | char *buff; | 490 | char *buff; |
475 | int i; | 491 | int i, ret = 0; |
476 | 492 | ||
477 | if (!bat_priv->primary_if) { | 493 | primary_if = primary_if_get_selected(bat_priv); |
478 | return seq_printf(seq, "BATMAN mesh %s disabled - " | 494 | if (!primary_if) { |
479 | "please specify interfaces to enable it\n", | 495 | ret = seq_printf(seq, "BATMAN mesh %s disabled - please " |
480 | net_dev->name); | 496 | "specify interfaces to enable it\n", |
497 | net_dev->name); | ||
498 | goto out; | ||
481 | } | 499 | } |
482 | 500 | ||
483 | seq_printf(seq, "Globally announced HNAs received via the mesh %s\n", | 501 | if (primary_if->if_status != IF_ACTIVE) { |
502 | ret = seq_printf(seq, "BATMAN mesh %s disabled - " | ||
503 | "primary interface not active\n", | ||
504 | net_dev->name); | ||
505 | goto out; | ||
506 | } | ||
507 | |||
508 | seq_printf(seq, | ||
509 | "Globally announced TT entries received via the mesh %s\n", | ||
484 | net_dev->name); | 510 | net_dev->name); |
485 | 511 | ||
486 | spin_lock_bh(&bat_priv->hna_ghash_lock); | 512 | spin_lock_bh(&bat_priv->tt_ghash_lock); |
487 | 513 | ||
488 | buf_size = 1; | 514 | buf_size = 1; |
489 | /* Estimate length for: " * xx:xx:xx:xx:xx:xx via xx:xx:xx:xx:xx:xx\n"*/ | 515 | /* Estimate length for: " * xx:xx:xx:xx:xx:xx via xx:xx:xx:xx:xx:xx\n"*/ |
@@ -498,8 +524,9 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset) | |||
498 | 524 | ||
499 | buff = kmalloc(buf_size, GFP_ATOMIC); | 525 | buff = kmalloc(buf_size, GFP_ATOMIC); |
500 | if (!buff) { | 526 | if (!buff) { |
501 | spin_unlock_bh(&bat_priv->hna_ghash_lock); | 527 | spin_unlock_bh(&bat_priv->tt_ghash_lock); |
502 | return -ENOMEM; | 528 | ret = -ENOMEM; |
529 | goto out; | ||
503 | } | 530 | } |
504 | buff[0] = '\0'; | 531 | buff[0] = '\0'; |
505 | pos = 0; | 532 | pos = 0; |
@@ -508,101 +535,104 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset) | |||
508 | head = &hash->table[i]; | 535 | head = &hash->table[i]; |
509 | 536 | ||
510 | rcu_read_lock(); | 537 | rcu_read_lock(); |
511 | hlist_for_each_entry_rcu(hna_global_entry, node, | 538 | hlist_for_each_entry_rcu(tt_global_entry, node, |
512 | head, hash_entry) { | 539 | head, hash_entry) { |
513 | pos += snprintf(buff + pos, 44, | 540 | pos += snprintf(buff + pos, 44, |
514 | " * %pM via %pM\n", | 541 | " * %pM via %pM\n", |
515 | hna_global_entry->addr, | 542 | tt_global_entry->addr, |
516 | hna_global_entry->orig_node->orig); | 543 | tt_global_entry->orig_node->orig); |
517 | } | 544 | } |
518 | rcu_read_unlock(); | 545 | rcu_read_unlock(); |
519 | } | 546 | } |
520 | 547 | ||
521 | spin_unlock_bh(&bat_priv->hna_ghash_lock); | 548 | spin_unlock_bh(&bat_priv->tt_ghash_lock); |
522 | 549 | ||
523 | seq_printf(seq, "%s", buff); | 550 | seq_printf(seq, "%s", buff); |
524 | kfree(buff); | 551 | kfree(buff); |
525 | return 0; | 552 | out: |
553 | if (primary_if) | ||
554 | hardif_free_ref(primary_if); | ||
555 | return ret; | ||
526 | } | 556 | } |
527 | 557 | ||
528 | static void _hna_global_del_orig(struct bat_priv *bat_priv, | 558 | static void _tt_global_del_orig(struct bat_priv *bat_priv, |
529 | struct hna_global_entry *hna_global_entry, | 559 | struct tt_global_entry *tt_global_entry, |
530 | char *message) | 560 | char *message) |
531 | { | 561 | { |
532 | bat_dbg(DBG_ROUTES, bat_priv, | 562 | bat_dbg(DBG_ROUTES, bat_priv, |
533 | "Deleting global hna entry %pM (via %pM): %s\n", | 563 | "Deleting global tt entry %pM (via %pM): %s\n", |
534 | hna_global_entry->addr, hna_global_entry->orig_node->orig, | 564 | tt_global_entry->addr, tt_global_entry->orig_node->orig, |
535 | message); | 565 | message); |
536 | 566 | ||
537 | hash_remove(bat_priv->hna_global_hash, compare_ghna, choose_orig, | 567 | hash_remove(bat_priv->tt_global_hash, compare_gtt, choose_orig, |
538 | hna_global_entry->addr); | 568 | tt_global_entry->addr); |
539 | kfree(hna_global_entry); | 569 | kfree(tt_global_entry); |
540 | } | 570 | } |
541 | 571 | ||
542 | void hna_global_del_orig(struct bat_priv *bat_priv, | 572 | void tt_global_del_orig(struct bat_priv *bat_priv, |
543 | struct orig_node *orig_node, char *message) | 573 | struct orig_node *orig_node, char *message) |
544 | { | 574 | { |
545 | struct hna_global_entry *hna_global_entry; | 575 | struct tt_global_entry *tt_global_entry; |
546 | int hna_buff_count = 0; | 576 | int tt_buff_count = 0; |
547 | unsigned char *hna_ptr; | 577 | unsigned char *tt_ptr; |
548 | 578 | ||
549 | if (orig_node->hna_buff_len == 0) | 579 | if (orig_node->tt_buff_len == 0) |
550 | return; | 580 | return; |
551 | 581 | ||
552 | spin_lock_bh(&bat_priv->hna_ghash_lock); | 582 | spin_lock_bh(&bat_priv->tt_ghash_lock); |
553 | 583 | ||
554 | while ((hna_buff_count + 1) * ETH_ALEN <= orig_node->hna_buff_len) { | 584 | while ((tt_buff_count + 1) * ETH_ALEN <= orig_node->tt_buff_len) { |
555 | hna_ptr = orig_node->hna_buff + (hna_buff_count * ETH_ALEN); | 585 | tt_ptr = orig_node->tt_buff + (tt_buff_count * ETH_ALEN); |
556 | hna_global_entry = hna_global_hash_find(bat_priv, hna_ptr); | 586 | tt_global_entry = tt_global_hash_find(bat_priv, tt_ptr); |
557 | 587 | ||
558 | if ((hna_global_entry) && | 588 | if ((tt_global_entry) && |
559 | (hna_global_entry->orig_node == orig_node)) | 589 | (tt_global_entry->orig_node == orig_node)) |
560 | _hna_global_del_orig(bat_priv, hna_global_entry, | 590 | _tt_global_del_orig(bat_priv, tt_global_entry, |
561 | message); | 591 | message); |
562 | 592 | ||
563 | hna_buff_count++; | 593 | tt_buff_count++; |
564 | } | 594 | } |
565 | 595 | ||
566 | spin_unlock_bh(&bat_priv->hna_ghash_lock); | 596 | spin_unlock_bh(&bat_priv->tt_ghash_lock); |
567 | 597 | ||
568 | orig_node->hna_buff_len = 0; | 598 | orig_node->tt_buff_len = 0; |
569 | kfree(orig_node->hna_buff); | 599 | kfree(orig_node->tt_buff); |
570 | orig_node->hna_buff = NULL; | 600 | orig_node->tt_buff = NULL; |
571 | } | 601 | } |
572 | 602 | ||
573 | static void hna_global_del(struct hlist_node *node, void *arg) | 603 | static void tt_global_del(struct hlist_node *node, void *arg) |
574 | { | 604 | { |
575 | void *data = container_of(node, struct hna_global_entry, hash_entry); | 605 | void *data = container_of(node, struct tt_global_entry, hash_entry); |
576 | 606 | ||
577 | kfree(data); | 607 | kfree(data); |
578 | } | 608 | } |
579 | 609 | ||
580 | void hna_global_free(struct bat_priv *bat_priv) | 610 | void tt_global_free(struct bat_priv *bat_priv) |
581 | { | 611 | { |
582 | if (!bat_priv->hna_global_hash) | 612 | if (!bat_priv->tt_global_hash) |
583 | return; | 613 | return; |
584 | 614 | ||
585 | hash_delete(bat_priv->hna_global_hash, hna_global_del, NULL); | 615 | hash_delete(bat_priv->tt_global_hash, tt_global_del, NULL); |
586 | bat_priv->hna_global_hash = NULL; | 616 | bat_priv->tt_global_hash = NULL; |
587 | } | 617 | } |
588 | 618 | ||
589 | struct orig_node *transtable_search(struct bat_priv *bat_priv, uint8_t *addr) | 619 | struct orig_node *transtable_search(struct bat_priv *bat_priv, uint8_t *addr) |
590 | { | 620 | { |
591 | struct hna_global_entry *hna_global_entry; | 621 | struct tt_global_entry *tt_global_entry; |
592 | struct orig_node *orig_node = NULL; | 622 | struct orig_node *orig_node = NULL; |
593 | 623 | ||
594 | spin_lock_bh(&bat_priv->hna_ghash_lock); | 624 | spin_lock_bh(&bat_priv->tt_ghash_lock); |
595 | hna_global_entry = hna_global_hash_find(bat_priv, addr); | 625 | tt_global_entry = tt_global_hash_find(bat_priv, addr); |
596 | 626 | ||
597 | if (!hna_global_entry) | 627 | if (!tt_global_entry) |
598 | goto out; | 628 | goto out; |
599 | 629 | ||
600 | if (!atomic_inc_not_zero(&hna_global_entry->orig_node->refcount)) | 630 | if (!atomic_inc_not_zero(&tt_global_entry->orig_node->refcount)) |
601 | goto out; | 631 | goto out; |
602 | 632 | ||
603 | orig_node = hna_global_entry->orig_node; | 633 | orig_node = tt_global_entry->orig_node; |
604 | 634 | ||
605 | out: | 635 | out: |
606 | spin_unlock_bh(&bat_priv->hna_ghash_lock); | 636 | spin_unlock_bh(&bat_priv->tt_ghash_lock); |
607 | return orig_node; | 637 | return orig_node; |
608 | } | 638 | } |
diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h index f19931ca1457..46152c38cc95 100644 --- a/net/batman-adv/translation-table.h +++ b/net/batman-adv/translation-table.h | |||
@@ -22,22 +22,22 @@ | |||
22 | #ifndef _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ | 22 | #ifndef _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ |
23 | #define _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ | 23 | #define _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ |
24 | 24 | ||
25 | int hna_local_init(struct bat_priv *bat_priv); | 25 | int tt_local_init(struct bat_priv *bat_priv); |
26 | void hna_local_add(struct net_device *soft_iface, uint8_t *addr); | 26 | void tt_local_add(struct net_device *soft_iface, uint8_t *addr); |
27 | void hna_local_remove(struct bat_priv *bat_priv, | 27 | void tt_local_remove(struct bat_priv *bat_priv, |
28 | uint8_t *addr, char *message); | 28 | uint8_t *addr, char *message); |
29 | int hna_local_fill_buffer(struct bat_priv *bat_priv, | 29 | int tt_local_fill_buffer(struct bat_priv *bat_priv, |
30 | unsigned char *buff, int buff_len); | 30 | unsigned char *buff, int buff_len); |
31 | int hna_local_seq_print_text(struct seq_file *seq, void *offset); | 31 | int tt_local_seq_print_text(struct seq_file *seq, void *offset); |
32 | void hna_local_free(struct bat_priv *bat_priv); | 32 | void tt_local_free(struct bat_priv *bat_priv); |
33 | int hna_global_init(struct bat_priv *bat_priv); | 33 | int tt_global_init(struct bat_priv *bat_priv); |
34 | void hna_global_add_orig(struct bat_priv *bat_priv, | 34 | void tt_global_add_orig(struct bat_priv *bat_priv, |
35 | struct orig_node *orig_node, | 35 | struct orig_node *orig_node, |
36 | unsigned char *hna_buff, int hna_buff_len); | 36 | unsigned char *tt_buff, int tt_buff_len); |
37 | int hna_global_seq_print_text(struct seq_file *seq, void *offset); | 37 | int tt_global_seq_print_text(struct seq_file *seq, void *offset); |
38 | void hna_global_del_orig(struct bat_priv *bat_priv, | 38 | void tt_global_del_orig(struct bat_priv *bat_priv, |
39 | struct orig_node *orig_node, char *message); | 39 | struct orig_node *orig_node, char *message); |
40 | void hna_global_free(struct bat_priv *bat_priv); | 40 | void tt_global_free(struct bat_priv *bat_priv); |
41 | struct orig_node *transtable_search(struct bat_priv *bat_priv, uint8_t *addr); | 41 | struct orig_node *transtable_search(struct bat_priv *bat_priv, uint8_t *addr); |
42 | 42 | ||
43 | #endif /* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */ | 43 | #endif /* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */ |
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 83445cf0cc9f..fab70e8b16ee 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h | |||
@@ -67,7 +67,7 @@ struct hard_iface { | |||
67 | struct orig_node { | 67 | struct orig_node { |
68 | uint8_t orig[ETH_ALEN]; | 68 | uint8_t orig[ETH_ALEN]; |
69 | uint8_t primary_addr[ETH_ALEN]; | 69 | uint8_t primary_addr[ETH_ALEN]; |
70 | struct neigh_node *router; | 70 | struct neigh_node __rcu *router; /* rcu protected pointer */ |
71 | unsigned long *bcast_own; | 71 | unsigned long *bcast_own; |
72 | uint8_t *bcast_own_sum; | 72 | uint8_t *bcast_own_sum; |
73 | unsigned long last_valid; | 73 | unsigned long last_valid; |
@@ -75,25 +75,25 @@ struct orig_node { | |||
75 | unsigned long batman_seqno_reset; | 75 | unsigned long batman_seqno_reset; |
76 | uint8_t gw_flags; | 76 | uint8_t gw_flags; |
77 | uint8_t flags; | 77 | uint8_t flags; |
78 | unsigned char *hna_buff; | 78 | unsigned char *tt_buff; |
79 | int16_t hna_buff_len; | 79 | int16_t tt_buff_len; |
80 | uint32_t last_real_seqno; | 80 | uint32_t last_real_seqno; |
81 | uint8_t last_ttl; | 81 | uint8_t last_ttl; |
82 | unsigned long bcast_bits[NUM_WORDS]; | 82 | unsigned long bcast_bits[NUM_WORDS]; |
83 | uint32_t last_bcast_seqno; | 83 | uint32_t last_bcast_seqno; |
84 | struct hlist_head neigh_list; | 84 | struct hlist_head neigh_list; |
85 | struct list_head frag_list; | 85 | struct list_head frag_list; |
86 | spinlock_t neigh_list_lock; /* protects neighbor list */ | 86 | spinlock_t neigh_list_lock; /* protects neigh_list and router */ |
87 | atomic_t refcount; | 87 | atomic_t refcount; |
88 | struct rcu_head rcu; | 88 | struct rcu_head rcu; |
89 | struct hlist_node hash_entry; | 89 | struct hlist_node hash_entry; |
90 | struct bat_priv *bat_priv; | 90 | struct bat_priv *bat_priv; |
91 | unsigned long last_frag_packet; | 91 | unsigned long last_frag_packet; |
92 | spinlock_t ogm_cnt_lock; /* protects: bcast_own, bcast_own_sum, | 92 | /* ogm_cnt_lock protects: bcast_own, bcast_own_sum, |
93 | * neigh_node->real_bits, | 93 | * neigh_node->real_bits, neigh_node->real_packet_count */ |
94 | * neigh_node->real_packet_count */ | 94 | spinlock_t ogm_cnt_lock; |
95 | spinlock_t bcast_seqno_lock; /* protects bcast_bits, | 95 | /* bcast_seqno_lock protects bcast_bits, last_bcast_seqno */ |
96 | * last_bcast_seqno */ | 96 | spinlock_t bcast_seqno_lock; |
97 | atomic_t bond_candidates; | 97 | atomic_t bond_candidates; |
98 | struct list_head bond_list; | 98 | struct list_head bond_list; |
99 | }; | 99 | }; |
@@ -125,6 +125,7 @@ struct neigh_node { | |||
125 | struct rcu_head rcu; | 125 | struct rcu_head rcu; |
126 | struct orig_node *orig_node; | 126 | struct orig_node *orig_node; |
127 | struct hard_iface *if_incoming; | 127 | struct hard_iface *if_incoming; |
128 | spinlock_t tq_lock; /* protects: tq_recv, tq_index */ | ||
128 | }; | 129 | }; |
129 | 130 | ||
130 | 131 | ||
@@ -145,34 +146,34 @@ struct bat_priv { | |||
145 | atomic_t bcast_queue_left; | 146 | atomic_t bcast_queue_left; |
146 | atomic_t batman_queue_left; | 147 | atomic_t batman_queue_left; |
147 | char num_ifaces; | 148 | char num_ifaces; |
148 | struct hlist_head softif_neigh_list; | ||
149 | struct softif_neigh *softif_neigh; | ||
150 | struct debug_log *debug_log; | 149 | struct debug_log *debug_log; |
151 | struct hard_iface *primary_if; | ||
152 | struct kobject *mesh_obj; | 150 | struct kobject *mesh_obj; |
153 | struct dentry *debug_dir; | 151 | struct dentry *debug_dir; |
154 | struct hlist_head forw_bat_list; | 152 | struct hlist_head forw_bat_list; |
155 | struct hlist_head forw_bcast_list; | 153 | struct hlist_head forw_bcast_list; |
156 | struct hlist_head gw_list; | 154 | struct hlist_head gw_list; |
155 | struct hlist_head softif_neigh_vids; | ||
157 | struct list_head vis_send_list; | 156 | struct list_head vis_send_list; |
158 | struct hashtable_t *orig_hash; | 157 | struct hashtable_t *orig_hash; |
159 | struct hashtable_t *hna_local_hash; | 158 | struct hashtable_t *tt_local_hash; |
160 | struct hashtable_t *hna_global_hash; | 159 | struct hashtable_t *tt_global_hash; |
161 | struct hashtable_t *vis_hash; | 160 | struct hashtable_t *vis_hash; |
162 | spinlock_t forw_bat_list_lock; /* protects forw_bat_list */ | 161 | spinlock_t forw_bat_list_lock; /* protects forw_bat_list */ |
163 | spinlock_t forw_bcast_list_lock; /* protects */ | 162 | spinlock_t forw_bcast_list_lock; /* protects */ |
164 | spinlock_t hna_lhash_lock; /* protects hna_local_hash */ | 163 | spinlock_t tt_lhash_lock; /* protects tt_local_hash */ |
165 | spinlock_t hna_ghash_lock; /* protects hna_global_hash */ | 164 | spinlock_t tt_ghash_lock; /* protects tt_global_hash */ |
166 | spinlock_t gw_list_lock; /* protects gw_list and curr_gw */ | 165 | spinlock_t gw_list_lock; /* protects gw_list and curr_gw */ |
167 | spinlock_t vis_hash_lock; /* protects vis_hash */ | 166 | spinlock_t vis_hash_lock; /* protects vis_hash */ |
168 | spinlock_t vis_list_lock; /* protects vis_info::recv_list */ | 167 | spinlock_t vis_list_lock; /* protects vis_info::recv_list */ |
169 | spinlock_t softif_neigh_lock; /* protects soft-interface neigh list */ | 168 | spinlock_t softif_neigh_lock; /* protects soft-interface neigh list */ |
170 | int16_t num_local_hna; | 169 | spinlock_t softif_neigh_vid_lock; /* protects soft-interface vid list */ |
171 | atomic_t hna_local_changed; | 170 | int16_t num_local_tt; |
172 | struct delayed_work hna_work; | 171 | atomic_t tt_local_changed; |
172 | struct delayed_work tt_work; | ||
173 | struct delayed_work orig_work; | 173 | struct delayed_work orig_work; |
174 | struct delayed_work vis_work; | 174 | struct delayed_work vis_work; |
175 | struct gw_node __rcu *curr_gw; /* rcu protected pointer */ | 175 | struct gw_node __rcu *curr_gw; /* rcu protected pointer */ |
176 | struct hard_iface __rcu *primary_if; /* rcu protected pointer */ | ||
176 | struct vis_info *my_vis_info; | 177 | struct vis_info *my_vis_info; |
177 | }; | 178 | }; |
178 | 179 | ||
@@ -191,14 +192,14 @@ struct socket_packet { | |||
191 | struct icmp_packet_rr icmp_packet; | 192 | struct icmp_packet_rr icmp_packet; |
192 | }; | 193 | }; |
193 | 194 | ||
194 | struct hna_local_entry { | 195 | struct tt_local_entry { |
195 | uint8_t addr[ETH_ALEN]; | 196 | uint8_t addr[ETH_ALEN]; |
196 | unsigned long last_seen; | 197 | unsigned long last_seen; |
197 | char never_purge; | 198 | char never_purge; |
198 | struct hlist_node hash_entry; | 199 | struct hlist_node hash_entry; |
199 | }; | 200 | }; |
200 | 201 | ||
201 | struct hna_global_entry { | 202 | struct tt_global_entry { |
202 | uint8_t addr[ETH_ALEN]; | 203 | uint8_t addr[ETH_ALEN]; |
203 | struct orig_node *orig_node; | 204 | struct orig_node *orig_node; |
204 | struct hlist_node hash_entry; | 205 | struct hlist_node hash_entry; |
@@ -261,7 +262,7 @@ struct vis_info { | |||
261 | struct vis_info_entry { | 262 | struct vis_info_entry { |
262 | uint8_t src[ETH_ALEN]; | 263 | uint8_t src[ETH_ALEN]; |
263 | uint8_t dest[ETH_ALEN]; | 264 | uint8_t dest[ETH_ALEN]; |
264 | uint8_t quality; /* quality = 0 means HNA */ | 265 | uint8_t quality; /* quality = 0 client */ |
265 | } __packed; | 266 | } __packed; |
266 | 267 | ||
267 | struct recvlist_node { | 268 | struct recvlist_node { |
@@ -269,11 +270,20 @@ struct recvlist_node { | |||
269 | uint8_t mac[ETH_ALEN]; | 270 | uint8_t mac[ETH_ALEN]; |
270 | }; | 271 | }; |
271 | 272 | ||
273 | struct softif_neigh_vid { | ||
274 | struct hlist_node list; | ||
275 | struct bat_priv *bat_priv; | ||
276 | short vid; | ||
277 | atomic_t refcount; | ||
278 | struct softif_neigh __rcu *softif_neigh; | ||
279 | struct rcu_head rcu; | ||
280 | struct hlist_head softif_neigh_list; | ||
281 | }; | ||
282 | |||
272 | struct softif_neigh { | 283 | struct softif_neigh { |
273 | struct hlist_node list; | 284 | struct hlist_node list; |
274 | uint8_t addr[ETH_ALEN]; | 285 | uint8_t addr[ETH_ALEN]; |
275 | unsigned long last_seen; | 286 | unsigned long last_seen; |
276 | short vid; | ||
277 | atomic_t refcount; | 287 | atomic_t refcount; |
278 | struct rcu_head rcu; | 288 | struct rcu_head rcu; |
279 | }; | 289 | }; |
diff --git a/net/batman-adv/unicast.c b/net/batman-adv/unicast.c index 19f84bd443af..19c3daf34ac6 100644 --- a/net/batman-adv/unicast.c +++ b/net/batman-adv/unicast.c | |||
@@ -221,15 +221,17 @@ int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv, | |||
221 | struct hard_iface *hard_iface, uint8_t dstaddr[]) | 221 | struct hard_iface *hard_iface, uint8_t dstaddr[]) |
222 | { | 222 | { |
223 | struct unicast_packet tmp_uc, *unicast_packet; | 223 | struct unicast_packet tmp_uc, *unicast_packet; |
224 | struct hard_iface *primary_if; | ||
224 | struct sk_buff *frag_skb; | 225 | struct sk_buff *frag_skb; |
225 | struct unicast_frag_packet *frag1, *frag2; | 226 | struct unicast_frag_packet *frag1, *frag2; |
226 | int uc_hdr_len = sizeof(struct unicast_packet); | 227 | int uc_hdr_len = sizeof(struct unicast_packet); |
227 | int ucf_hdr_len = sizeof(struct unicast_frag_packet); | 228 | int ucf_hdr_len = sizeof(struct unicast_frag_packet); |
228 | int data_len = skb->len - uc_hdr_len; | 229 | int data_len = skb->len - uc_hdr_len; |
229 | int large_tail = 0; | 230 | int large_tail = 0, ret = NET_RX_DROP; |
230 | uint16_t seqno; | 231 | uint16_t seqno; |
231 | 232 | ||
232 | if (!bat_priv->primary_if) | 233 | primary_if = primary_if_get_selected(bat_priv); |
234 | if (!primary_if) | ||
233 | goto dropped; | 235 | goto dropped; |
234 | 236 | ||
235 | frag_skb = dev_alloc_skb(data_len - (data_len / 2) + ucf_hdr_len); | 237 | frag_skb = dev_alloc_skb(data_len - (data_len / 2) + ucf_hdr_len); |
@@ -254,7 +256,7 @@ int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv, | |||
254 | frag1->version = COMPAT_VERSION; | 256 | frag1->version = COMPAT_VERSION; |
255 | frag1->packet_type = BAT_UNICAST_FRAG; | 257 | frag1->packet_type = BAT_UNICAST_FRAG; |
256 | 258 | ||
257 | memcpy(frag1->orig, bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); | 259 | memcpy(frag1->orig, primary_if->net_dev->dev_addr, ETH_ALEN); |
258 | memcpy(frag2, frag1, sizeof(struct unicast_frag_packet)); | 260 | memcpy(frag2, frag1, sizeof(struct unicast_frag_packet)); |
259 | 261 | ||
260 | if (data_len & 1) | 262 | if (data_len & 1) |
@@ -269,13 +271,17 @@ int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv, | |||
269 | 271 | ||
270 | send_skb_packet(skb, hard_iface, dstaddr); | 272 | send_skb_packet(skb, hard_iface, dstaddr); |
271 | send_skb_packet(frag_skb, hard_iface, dstaddr); | 273 | send_skb_packet(frag_skb, hard_iface, dstaddr); |
272 | return NET_RX_SUCCESS; | 274 | ret = NET_RX_SUCCESS; |
275 | goto out; | ||
273 | 276 | ||
274 | drop_frag: | 277 | drop_frag: |
275 | kfree_skb(frag_skb); | 278 | kfree_skb(frag_skb); |
276 | dropped: | 279 | dropped: |
277 | kfree_skb(skb); | 280 | kfree_skb(skb); |
278 | return NET_RX_DROP; | 281 | out: |
282 | if (primary_if) | ||
283 | hardif_free_ref(primary_if); | ||
284 | return ret; | ||
279 | } | 285 | } |
280 | 286 | ||
281 | int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv) | 287 | int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv) |
@@ -289,12 +295,12 @@ int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv) | |||
289 | 295 | ||
290 | /* get routing information */ | 296 | /* get routing information */ |
291 | if (is_multicast_ether_addr(ethhdr->h_dest)) { | 297 | if (is_multicast_ether_addr(ethhdr->h_dest)) { |
292 | orig_node = (struct orig_node *)gw_get_selected(bat_priv); | 298 | orig_node = (struct orig_node *)gw_get_selected_orig(bat_priv); |
293 | if (orig_node) | 299 | if (orig_node) |
294 | goto find_router; | 300 | goto find_router; |
295 | } | 301 | } |
296 | 302 | ||
297 | /* check for hna host - increases orig_node refcount */ | 303 | /* check for tt host - increases orig_node refcount */ |
298 | orig_node = transtable_search(bat_priv, ethhdr->h_dest); | 304 | orig_node = transtable_search(bat_priv, ethhdr->h_dest); |
299 | 305 | ||
300 | find_router: | 306 | find_router: |
diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c index f90212f42082..c39f20cc1ba6 100644 --- a/net/batman-adv/vis.c +++ b/net/batman-adv/vis.c | |||
@@ -194,7 +194,7 @@ static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry, | |||
194 | { | 194 | { |
195 | /* maximal length: max(4+17+2, 3+17+1+3+2) == 26 */ | 195 | /* maximal length: max(4+17+2, 3+17+1+3+2) == 26 */ |
196 | if (primary && entry->quality == 0) | 196 | if (primary && entry->quality == 0) |
197 | return sprintf(buff, "HNA %pM, ", entry->dest); | 197 | return sprintf(buff, "TT %pM, ", entry->dest); |
198 | else if (compare_eth(entry->src, src)) | 198 | else if (compare_eth(entry->src, src)) |
199 | return sprintf(buff, "TQ %pM %d, ", entry->dest, | 199 | return sprintf(buff, "TQ %pM %d, ", entry->dest, |
200 | entry->quality); | 200 | entry->quality); |
@@ -204,6 +204,7 @@ static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry, | |||
204 | 204 | ||
205 | int vis_seq_print_text(struct seq_file *seq, void *offset) | 205 | int vis_seq_print_text(struct seq_file *seq, void *offset) |
206 | { | 206 | { |
207 | struct hard_iface *primary_if; | ||
207 | struct hlist_node *node; | 208 | struct hlist_node *node; |
208 | struct hlist_head *head; | 209 | struct hlist_head *head; |
209 | struct vis_info *info; | 210 | struct vis_info *info; |
@@ -215,15 +216,18 @@ int vis_seq_print_text(struct seq_file *seq, void *offset) | |||
215 | HLIST_HEAD(vis_if_list); | 216 | HLIST_HEAD(vis_if_list); |
216 | struct if_list_entry *entry; | 217 | struct if_list_entry *entry; |
217 | struct hlist_node *pos, *n; | 218 | struct hlist_node *pos, *n; |
218 | int i, j; | 219 | int i, j, ret = 0; |
219 | int vis_server = atomic_read(&bat_priv->vis_mode); | 220 | int vis_server = atomic_read(&bat_priv->vis_mode); |
220 | size_t buff_pos, buf_size; | 221 | size_t buff_pos, buf_size; |
221 | char *buff; | 222 | char *buff; |
222 | int compare; | 223 | int compare; |
223 | 224 | ||
224 | if ((!bat_priv->primary_if) || | 225 | primary_if = primary_if_get_selected(bat_priv); |
225 | (vis_server == VIS_TYPE_CLIENT_UPDATE)) | 226 | if (!primary_if) |
226 | return 0; | 227 | goto out; |
228 | |||
229 | if (vis_server == VIS_TYPE_CLIENT_UPDATE) | ||
230 | goto out; | ||
227 | 231 | ||
228 | buf_size = 1; | 232 | buf_size = 1; |
229 | /* Estimate length */ | 233 | /* Estimate length */ |
@@ -270,7 +274,8 @@ int vis_seq_print_text(struct seq_file *seq, void *offset) | |||
270 | buff = kmalloc(buf_size, GFP_ATOMIC); | 274 | buff = kmalloc(buf_size, GFP_ATOMIC); |
271 | if (!buff) { | 275 | if (!buff) { |
272 | spin_unlock_bh(&bat_priv->vis_hash_lock); | 276 | spin_unlock_bh(&bat_priv->vis_hash_lock); |
273 | return -ENOMEM; | 277 | ret = -ENOMEM; |
278 | goto out; | ||
274 | } | 279 | } |
275 | buff[0] = '\0'; | 280 | buff[0] = '\0'; |
276 | buff_pos = 0; | 281 | buff_pos = 0; |
@@ -328,7 +333,10 @@ int vis_seq_print_text(struct seq_file *seq, void *offset) | |||
328 | seq_printf(seq, "%s", buff); | 333 | seq_printf(seq, "%s", buff); |
329 | kfree(buff); | 334 | kfree(buff); |
330 | 335 | ||
331 | return 0; | 336 | out: |
337 | if (primary_if) | ||
338 | hardif_free_ref(primary_if); | ||
339 | return ret; | ||
332 | } | 340 | } |
333 | 341 | ||
334 | /* add the info packet to the send list, if it was not | 342 | /* add the info packet to the send list, if it was not |
@@ -558,6 +566,7 @@ static int find_best_vis_server(struct bat_priv *bat_priv, | |||
558 | struct vis_info *info) | 566 | struct vis_info *info) |
559 | { | 567 | { |
560 | struct hashtable_t *hash = bat_priv->orig_hash; | 568 | struct hashtable_t *hash = bat_priv->orig_hash; |
569 | struct neigh_node *router; | ||
561 | struct hlist_node *node; | 570 | struct hlist_node *node; |
562 | struct hlist_head *head; | 571 | struct hlist_head *head; |
563 | struct orig_node *orig_node; | 572 | struct orig_node *orig_node; |
@@ -571,13 +580,17 @@ static int find_best_vis_server(struct bat_priv *bat_priv, | |||
571 | 580 | ||
572 | rcu_read_lock(); | 581 | rcu_read_lock(); |
573 | hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) { | 582 | hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) { |
574 | if ((orig_node) && (orig_node->router) && | 583 | router = orig_node_get_router(orig_node); |
575 | (orig_node->flags & VIS_SERVER) && | 584 | if (!router) |
576 | (orig_node->router->tq_avg > best_tq)) { | 585 | continue; |
577 | best_tq = orig_node->router->tq_avg; | 586 | |
587 | if ((orig_node->flags & VIS_SERVER) && | ||
588 | (router->tq_avg > best_tq)) { | ||
589 | best_tq = router->tq_avg; | ||
578 | memcpy(packet->target_orig, orig_node->orig, | 590 | memcpy(packet->target_orig, orig_node->orig, |
579 | ETH_ALEN); | 591 | ETH_ALEN); |
580 | } | 592 | } |
593 | neigh_node_free_ref(router); | ||
581 | } | 594 | } |
582 | rcu_read_unlock(); | 595 | rcu_read_unlock(); |
583 | } | 596 | } |
@@ -605,11 +618,11 @@ static int generate_vis_packet(struct bat_priv *bat_priv) | |||
605 | struct hlist_node *node; | 618 | struct hlist_node *node; |
606 | struct hlist_head *head; | 619 | struct hlist_head *head; |
607 | struct orig_node *orig_node; | 620 | struct orig_node *orig_node; |
608 | struct neigh_node *neigh_node; | 621 | struct neigh_node *router; |
609 | struct vis_info *info = (struct vis_info *)bat_priv->my_vis_info; | 622 | struct vis_info *info = (struct vis_info *)bat_priv->my_vis_info; |
610 | struct vis_packet *packet = (struct vis_packet *)info->skb_packet->data; | 623 | struct vis_packet *packet = (struct vis_packet *)info->skb_packet->data; |
611 | struct vis_info_entry *entry; | 624 | struct vis_info_entry *entry; |
612 | struct hna_local_entry *hna_local_entry; | 625 | struct tt_local_entry *tt_local_entry; |
613 | int best_tq = -1, i; | 626 | int best_tq = -1, i; |
614 | 627 | ||
615 | info->first_seen = jiffies; | 628 | info->first_seen = jiffies; |
@@ -633,59 +646,61 @@ static int generate_vis_packet(struct bat_priv *bat_priv) | |||
633 | 646 | ||
634 | rcu_read_lock(); | 647 | rcu_read_lock(); |
635 | hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) { | 648 | hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) { |
636 | neigh_node = orig_node->router; | 649 | router = orig_node_get_router(orig_node); |
637 | 650 | if (!router) | |
638 | if (!neigh_node) | ||
639 | continue; | 651 | continue; |
640 | 652 | ||
641 | if (!compare_eth(neigh_node->addr, orig_node->orig)) | 653 | if (!compare_eth(router->addr, orig_node->orig)) |
642 | continue; | 654 | goto next; |
643 | 655 | ||
644 | if (neigh_node->if_incoming->if_status != IF_ACTIVE) | 656 | if (router->if_incoming->if_status != IF_ACTIVE) |
645 | continue; | 657 | goto next; |
646 | 658 | ||
647 | if (neigh_node->tq_avg < 1) | 659 | if (router->tq_avg < 1) |
648 | continue; | 660 | goto next; |
649 | 661 | ||
650 | /* fill one entry into buffer. */ | 662 | /* fill one entry into buffer. */ |
651 | entry = (struct vis_info_entry *) | 663 | entry = (struct vis_info_entry *) |
652 | skb_put(info->skb_packet, sizeof(*entry)); | 664 | skb_put(info->skb_packet, sizeof(*entry)); |
653 | memcpy(entry->src, | 665 | memcpy(entry->src, |
654 | neigh_node->if_incoming->net_dev->dev_addr, | 666 | router->if_incoming->net_dev->dev_addr, |
655 | ETH_ALEN); | 667 | ETH_ALEN); |
656 | memcpy(entry->dest, orig_node->orig, ETH_ALEN); | 668 | memcpy(entry->dest, orig_node->orig, ETH_ALEN); |
657 | entry->quality = neigh_node->tq_avg; | 669 | entry->quality = router->tq_avg; |
658 | packet->entries++; | 670 | packet->entries++; |
659 | 671 | ||
672 | next: | ||
673 | neigh_node_free_ref(router); | ||
674 | |||
660 | if (vis_packet_full(info)) | 675 | if (vis_packet_full(info)) |
661 | goto unlock; | 676 | goto unlock; |
662 | } | 677 | } |
663 | rcu_read_unlock(); | 678 | rcu_read_unlock(); |
664 | } | 679 | } |
665 | 680 | ||
666 | hash = bat_priv->hna_local_hash; | 681 | hash = bat_priv->tt_local_hash; |
667 | 682 | ||
668 | spin_lock_bh(&bat_priv->hna_lhash_lock); | 683 | spin_lock_bh(&bat_priv->tt_lhash_lock); |
669 | for (i = 0; i < hash->size; i++) { | 684 | for (i = 0; i < hash->size; i++) { |
670 | head = &hash->table[i]; | 685 | head = &hash->table[i]; |
671 | 686 | ||
672 | hlist_for_each_entry(hna_local_entry, node, head, hash_entry) { | 687 | hlist_for_each_entry(tt_local_entry, node, head, hash_entry) { |
673 | entry = (struct vis_info_entry *) | 688 | entry = (struct vis_info_entry *) |
674 | skb_put(info->skb_packet, | 689 | skb_put(info->skb_packet, |
675 | sizeof(*entry)); | 690 | sizeof(*entry)); |
676 | memset(entry->src, 0, ETH_ALEN); | 691 | memset(entry->src, 0, ETH_ALEN); |
677 | memcpy(entry->dest, hna_local_entry->addr, ETH_ALEN); | 692 | memcpy(entry->dest, tt_local_entry->addr, ETH_ALEN); |
678 | entry->quality = 0; /* 0 means HNA */ | 693 | entry->quality = 0; /* 0 means TT */ |
679 | packet->entries++; | 694 | packet->entries++; |
680 | 695 | ||
681 | if (vis_packet_full(info)) { | 696 | if (vis_packet_full(info)) { |
682 | spin_unlock_bh(&bat_priv->hna_lhash_lock); | 697 | spin_unlock_bh(&bat_priv->tt_lhash_lock); |
683 | return 0; | 698 | return 0; |
684 | } | 699 | } |
685 | } | 700 | } |
686 | } | 701 | } |
687 | 702 | ||
688 | spin_unlock_bh(&bat_priv->hna_lhash_lock); | 703 | spin_unlock_bh(&bat_priv->tt_lhash_lock); |
689 | return 0; | 704 | return 0; |
690 | 705 | ||
691 | unlock: | 706 | unlock: |
@@ -725,6 +740,7 @@ static void purge_vis_packets(struct bat_priv *bat_priv) | |||
725 | static void broadcast_vis_packet(struct bat_priv *bat_priv, | 740 | static void broadcast_vis_packet(struct bat_priv *bat_priv, |
726 | struct vis_info *info) | 741 | struct vis_info *info) |
727 | { | 742 | { |
743 | struct neigh_node *router; | ||
728 | struct hashtable_t *hash = bat_priv->orig_hash; | 744 | struct hashtable_t *hash = bat_priv->orig_hash; |
729 | struct hlist_node *node; | 745 | struct hlist_node *node; |
730 | struct hlist_head *head; | 746 | struct hlist_head *head; |
@@ -745,19 +761,26 @@ static void broadcast_vis_packet(struct bat_priv *bat_priv, | |||
745 | rcu_read_lock(); | 761 | rcu_read_lock(); |
746 | hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) { | 762 | hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) { |
747 | /* if it's a vis server and reachable, send it. */ | 763 | /* if it's a vis server and reachable, send it. */ |
748 | if ((!orig_node) || (!orig_node->router)) | ||
749 | continue; | ||
750 | if (!(orig_node->flags & VIS_SERVER)) | 764 | if (!(orig_node->flags & VIS_SERVER)) |
751 | continue; | 765 | continue; |
766 | |||
767 | router = orig_node_get_router(orig_node); | ||
768 | if (!router) | ||
769 | continue; | ||
770 | |||
752 | /* don't send it if we already received the packet from | 771 | /* don't send it if we already received the packet from |
753 | * this node. */ | 772 | * this node. */ |
754 | if (recv_list_is_in(bat_priv, &info->recv_list, | 773 | if (recv_list_is_in(bat_priv, &info->recv_list, |
755 | orig_node->orig)) | 774 | orig_node->orig)) { |
775 | neigh_node_free_ref(router); | ||
756 | continue; | 776 | continue; |
777 | } | ||
757 | 778 | ||
758 | memcpy(packet->target_orig, orig_node->orig, ETH_ALEN); | 779 | memcpy(packet->target_orig, orig_node->orig, ETH_ALEN); |
759 | hard_iface = orig_node->router->if_incoming; | 780 | hard_iface = router->if_incoming; |
760 | memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); | 781 | memcpy(dstaddr, router->addr, ETH_ALEN); |
782 | |||
783 | neigh_node_free_ref(router); | ||
761 | 784 | ||
762 | skb = skb_clone(info->skb_packet, GFP_ATOMIC); | 785 | skb = skb_clone(info->skb_packet, GFP_ATOMIC); |
763 | if (skb) | 786 | if (skb) |
@@ -772,60 +795,48 @@ static void unicast_vis_packet(struct bat_priv *bat_priv, | |||
772 | struct vis_info *info) | 795 | struct vis_info *info) |
773 | { | 796 | { |
774 | struct orig_node *orig_node; | 797 | struct orig_node *orig_node; |
775 | struct neigh_node *neigh_node = NULL; | 798 | struct neigh_node *router = NULL; |
776 | struct sk_buff *skb; | 799 | struct sk_buff *skb; |
777 | struct vis_packet *packet; | 800 | struct vis_packet *packet; |
778 | 801 | ||
779 | packet = (struct vis_packet *)info->skb_packet->data; | 802 | packet = (struct vis_packet *)info->skb_packet->data; |
780 | 803 | ||
781 | rcu_read_lock(); | ||
782 | orig_node = orig_hash_find(bat_priv, packet->target_orig); | 804 | orig_node = orig_hash_find(bat_priv, packet->target_orig); |
783 | |||
784 | if (!orig_node) | 805 | if (!orig_node) |
785 | goto unlock; | 806 | goto out; |
786 | |||
787 | neigh_node = orig_node->router; | ||
788 | 807 | ||
789 | if (!neigh_node) | 808 | router = orig_node_get_router(orig_node); |
790 | goto unlock; | 809 | if (!router) |
791 | 810 | goto out; | |
792 | if (!atomic_inc_not_zero(&neigh_node->refcount)) { | ||
793 | neigh_node = NULL; | ||
794 | goto unlock; | ||
795 | } | ||
796 | |||
797 | rcu_read_unlock(); | ||
798 | 811 | ||
799 | skb = skb_clone(info->skb_packet, GFP_ATOMIC); | 812 | skb = skb_clone(info->skb_packet, GFP_ATOMIC); |
800 | if (skb) | 813 | if (skb) |
801 | send_skb_packet(skb, neigh_node->if_incoming, | 814 | send_skb_packet(skb, router->if_incoming, router->addr); |
802 | neigh_node->addr); | ||
803 | 815 | ||
804 | goto out; | ||
805 | |||
806 | unlock: | ||
807 | rcu_read_unlock(); | ||
808 | out: | 816 | out: |
809 | if (neigh_node) | 817 | if (router) |
810 | neigh_node_free_ref(neigh_node); | 818 | neigh_node_free_ref(router); |
811 | if (orig_node) | 819 | if (orig_node) |
812 | orig_node_free_ref(orig_node); | 820 | orig_node_free_ref(orig_node); |
813 | return; | ||
814 | } | 821 | } |
815 | 822 | ||
816 | /* only send one vis packet. called from send_vis_packets() */ | 823 | /* only send one vis packet. called from send_vis_packets() */ |
817 | static void send_vis_packet(struct bat_priv *bat_priv, struct vis_info *info) | 824 | static void send_vis_packet(struct bat_priv *bat_priv, struct vis_info *info) |
818 | { | 825 | { |
826 | struct hard_iface *primary_if; | ||
819 | struct vis_packet *packet; | 827 | struct vis_packet *packet; |
820 | 828 | ||
829 | primary_if = primary_if_get_selected(bat_priv); | ||
830 | if (!primary_if) | ||
831 | goto out; | ||
832 | |||
821 | packet = (struct vis_packet *)info->skb_packet->data; | 833 | packet = (struct vis_packet *)info->skb_packet->data; |
822 | if (packet->ttl < 2) { | 834 | if (packet->ttl < 2) { |
823 | pr_debug("Error - can't send vis packet: ttl exceeded\n"); | 835 | pr_debug("Error - can't send vis packet: ttl exceeded\n"); |
824 | return; | 836 | goto out; |
825 | } | 837 | } |
826 | 838 | ||
827 | memcpy(packet->sender_orig, bat_priv->primary_if->net_dev->dev_addr, | 839 | memcpy(packet->sender_orig, primary_if->net_dev->dev_addr, ETH_ALEN); |
828 | ETH_ALEN); | ||
829 | packet->ttl--; | 840 | packet->ttl--; |
830 | 841 | ||
831 | if (is_broadcast_ether_addr(packet->target_orig)) | 842 | if (is_broadcast_ether_addr(packet->target_orig)) |
@@ -833,6 +844,10 @@ static void send_vis_packet(struct bat_priv *bat_priv, struct vis_info *info) | |||
833 | else | 844 | else |
834 | unicast_vis_packet(bat_priv, info); | 845 | unicast_vis_packet(bat_priv, info); |
835 | packet->ttl++; /* restore TTL */ | 846 | packet->ttl++; /* restore TTL */ |
847 | |||
848 | out: | ||
849 | if (primary_if) | ||
850 | hardif_free_ref(primary_if); | ||
836 | } | 851 | } |
837 | 852 | ||
838 | /* called from timer; send (and maybe generate) vis packet. */ | 853 | /* called from timer; send (and maybe generate) vis packet. */ |
@@ -859,8 +874,7 @@ static void send_vis_packets(struct work_struct *work) | |||
859 | kref_get(&info->refcount); | 874 | kref_get(&info->refcount); |
860 | spin_unlock_bh(&bat_priv->vis_hash_lock); | 875 | spin_unlock_bh(&bat_priv->vis_hash_lock); |
861 | 876 | ||
862 | if (bat_priv->primary_if) | 877 | send_vis_packet(bat_priv, info); |
863 | send_vis_packet(bat_priv, info); | ||
864 | 878 | ||
865 | spin_lock_bh(&bat_priv->vis_hash_lock); | 879 | spin_lock_bh(&bat_priv->vis_hash_lock); |
866 | send_list_del(info); | 880 | send_list_del(info); |