Skip to content
This repository was archived by the owner on Dec 20, 2023. It is now read-only.

Commit dcfd9cd

Browse files
committed
Merge branch 'batman-adv/next' of git://git.open-mesh.org/ecsv/linux-merge
2 parents 5615787 + 32ae9b2 commit dcfd9cd

14 files changed

+292
-138
lines changed

net/batman-adv/aggregation.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,6 @@ static bool can_aggregate_with(struct batman_packet *new_batman_packet,
9595
return false;
9696
}
9797

98-
#define atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0)
9998
/* create a new aggregated packet and add this packet to it */
10099
static void new_aggregated_packet(unsigned char *packet_buff, int packet_len,
101100
unsigned long send_time, bool direct_link,

net/batman-adv/gateway_client.c

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ void gw_election(struct bat_priv *bat_priv)
127127
return;
128128

129129
curr_gw = gw_get_selected_gw_node(bat_priv);
130-
if (!curr_gw)
130+
if (curr_gw)
131131
goto out;
132132

133133
rcu_read_lock();
@@ -310,9 +310,13 @@ void gw_node_update(struct bat_priv *bat_priv,
310310
struct hlist_node *node;
311311
struct gw_node *gw_node, *curr_gw;
312312

313+
/**
314+
* Note: We don't need a NULL check here, since curr_gw never gets
315+
* dereferenced. If curr_gw is NULL we also should not exit as we may
316+
* have this gateway in our list (duplication check!) even though we
317+
* have no currently selected gateway.
318+
*/
313319
curr_gw = gw_get_selected_gw_node(bat_priv);
314-
if (!curr_gw)
315-
goto out;
316320

317321
rcu_read_lock();
318322
hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) {
@@ -350,7 +354,7 @@ void gw_node_update(struct bat_priv *bat_priv,
350354
gw_deselect(bat_priv);
351355
unlock:
352356
rcu_read_unlock();
353-
out:
357+
354358
if (curr_gw)
355359
gw_node_free_ref(curr_gw);
356360
}
@@ -435,30 +439,32 @@ int gw_client_seq_print_text(struct seq_file *seq, void *offset)
435439
{
436440
struct net_device *net_dev = (struct net_device *)seq->private;
437441
struct bat_priv *bat_priv = netdev_priv(net_dev);
442+
struct hard_iface *primary_if;
438443
struct gw_node *gw_node;
439444
struct hlist_node *node;
440-
int gw_count = 0;
445+
int gw_count = 0, ret = 0;
441446

442-
if (!bat_priv->primary_if) {
443-
444-
return seq_printf(seq, "BATMAN mesh %s disabled - please "
445-
"specify interfaces to enable it\n",
446-
net_dev->name);
447+
primary_if = primary_if_get_selected(bat_priv);
448+
if (!primary_if) {
449+
ret = seq_printf(seq, "BATMAN mesh %s disabled - please "
450+
"specify interfaces to enable it\n",
451+
net_dev->name);
452+
goto out;
447453
}
448454

449-
if (bat_priv->primary_if->if_status != IF_ACTIVE) {
450-
451-
return seq_printf(seq, "BATMAN mesh %s disabled - "
452-
"primary interface not active\n",
453-
net_dev->name);
455+
if (primary_if->if_status != IF_ACTIVE) {
456+
ret = seq_printf(seq, "BATMAN mesh %s disabled - "
457+
"primary interface not active\n",
458+
net_dev->name);
459+
goto out;
454460
}
455461

456462
seq_printf(seq, " %-12s (%s/%i) %17s [%10s]: gw_class ... "
457463
"[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%pM (%s)]\n",
458464
"Gateway", "#", TQ_MAX_VALUE, "Nexthop",
459465
"outgoingIF", SOURCE_VERSION, REVISION_VERSION_STR,
460-
bat_priv->primary_if->net_dev->name,
461-
bat_priv->primary_if->net_dev->dev_addr, net_dev->name);
466+
primary_if->net_dev->name,
467+
primary_if->net_dev->dev_addr, net_dev->name);
462468

463469
rcu_read_lock();
464470
hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) {
@@ -476,7 +482,10 @@ int gw_client_seq_print_text(struct seq_file *seq, void *offset)
476482
if (gw_count == 0)
477483
seq_printf(seq, "No gateways in range ...\n");
478484

479-
return 0;
485+
out:
486+
if (primary_if)
487+
hardif_free_ref(primary_if);
488+
return ret;
480489
}
481490

482491
int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb)

net/batman-adv/hard-interface.c

Lines changed: 57 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -110,47 +110,60 @@ static struct hard_iface *hardif_get_active(struct net_device *soft_iface)
110110
return hard_iface;
111111
}
112112

113-
static void update_primary_addr(struct bat_priv *bat_priv)
113+
static void primary_if_update_addr(struct bat_priv *bat_priv)
114114
{
115115
struct vis_packet *vis_packet;
116+
struct hard_iface *primary_if;
117+
118+
primary_if = primary_if_get_selected(bat_priv);
119+
if (!primary_if)
120+
goto out;
116121

117122
vis_packet = (struct vis_packet *)
118123
bat_priv->my_vis_info->skb_packet->data;
119-
memcpy(vis_packet->vis_orig,
120-
bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
124+
memcpy(vis_packet->vis_orig, primary_if->net_dev->dev_addr, ETH_ALEN);
121125
memcpy(vis_packet->sender_orig,
122-
bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
126+
primary_if->net_dev->dev_addr, ETH_ALEN);
127+
128+
out:
129+
if (primary_if)
130+
hardif_free_ref(primary_if);
123131
}
124132

125-
static void set_primary_if(struct bat_priv *bat_priv,
126-
struct hard_iface *hard_iface)
133+
static void primary_if_select(struct bat_priv *bat_priv,
134+
struct hard_iface *new_hard_iface)
127135
{
136+
struct hard_iface *curr_hard_iface;
128137
struct batman_packet *batman_packet;
129-
struct hard_iface *old_if;
130138

131-
if (hard_iface && !atomic_inc_not_zero(&hard_iface->refcount))
132-
hard_iface = NULL;
139+
spin_lock_bh(&hardif_list_lock);
133140

134-
old_if = bat_priv->primary_if;
135-
bat_priv->primary_if = hard_iface;
141+
if (new_hard_iface && !atomic_inc_not_zero(&new_hard_iface->refcount))
142+
new_hard_iface = NULL;
136143

137-
if (old_if)
138-
hardif_free_ref(old_if);
144+
curr_hard_iface = bat_priv->primary_if;
145+
rcu_assign_pointer(bat_priv->primary_if, new_hard_iface);
139146

140-
if (!bat_priv->primary_if)
141-
return;
147+
if (curr_hard_iface)
148+
hardif_free_ref(curr_hard_iface);
142149

143-
batman_packet = (struct batman_packet *)(hard_iface->packet_buff);
150+
if (!new_hard_iface)
151+
goto out;
152+
153+
batman_packet = (struct batman_packet *)(new_hard_iface->packet_buff);
144154
batman_packet->flags = PRIMARIES_FIRST_HOP;
145155
batman_packet->ttl = TTL;
146156

147-
update_primary_addr(bat_priv);
157+
primary_if_update_addr(bat_priv);
148158

149159
/***
150160
* hacky trick to make sure that we send the HNA information via
151161
* our new primary interface
152162
*/
153163
atomic_set(&bat_priv->hna_local_changed, 1);
164+
165+
out:
166+
spin_unlock_bh(&hardif_list_lock);
154167
}
155168

156169
static bool hardif_is_iface_up(struct hard_iface *hard_iface)
@@ -236,9 +249,10 @@ void update_min_mtu(struct net_device *soft_iface)
236249
static void hardif_activate_interface(struct hard_iface *hard_iface)
237250
{
238251
struct bat_priv *bat_priv;
252+
struct hard_iface *primary_if = NULL;
239253

240254
if (hard_iface->if_status != IF_INACTIVE)
241-
return;
255+
goto out;
242256

243257
bat_priv = netdev_priv(hard_iface->soft_iface);
244258

@@ -249,14 +263,18 @@ static void hardif_activate_interface(struct hard_iface *hard_iface)
249263
* the first active interface becomes our primary interface or
250264
* the next active interface after the old primay interface was removed
251265
*/
252-
if (!bat_priv->primary_if)
253-
set_primary_if(bat_priv, hard_iface);
266+
primary_if = primary_if_get_selected(bat_priv);
267+
if (!primary_if)
268+
primary_if_select(bat_priv, hard_iface);
254269

255270
bat_info(hard_iface->soft_iface, "Interface activated: %s\n",
256271
hard_iface->net_dev->name);
257272

258273
update_min_mtu(hard_iface->soft_iface);
259-
return;
274+
275+
out:
276+
if (primary_if)
277+
hardif_free_ref(primary_if);
260278
}
261279

262280
static void hardif_deactivate_interface(struct hard_iface *hard_iface)
@@ -386,12 +404,13 @@ int hardif_enable_interface(struct hard_iface *hard_iface, char *iface_name)
386404
void hardif_disable_interface(struct hard_iface *hard_iface)
387405
{
388406
struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
407+
struct hard_iface *primary_if = NULL;
389408

390409
if (hard_iface->if_status == IF_ACTIVE)
391410
hardif_deactivate_interface(hard_iface);
392411

393412
if (hard_iface->if_status != IF_INACTIVE)
394-
return;
413+
goto out;
395414

396415
bat_info(hard_iface->soft_iface, "Removing interface: %s\n",
397416
hard_iface->net_dev->name);
@@ -400,11 +419,12 @@ void hardif_disable_interface(struct hard_iface *hard_iface)
400419
bat_priv->num_ifaces--;
401420
orig_hash_del_if(hard_iface, bat_priv->num_ifaces);
402421

403-
if (hard_iface == bat_priv->primary_if) {
422+
primary_if = primary_if_get_selected(bat_priv);
423+
if (hard_iface == primary_if) {
404424
struct hard_iface *new_if;
405425

406426
new_if = hardif_get_active(hard_iface->soft_iface);
407-
set_primary_if(bat_priv, new_if);
427+
primary_if_select(bat_priv, new_if);
408428

409429
if (new_if)
410430
hardif_free_ref(new_if);
@@ -425,6 +445,10 @@ void hardif_disable_interface(struct hard_iface *hard_iface)
425445

426446
hard_iface->soft_iface = NULL;
427447
hardif_free_ref(hard_iface);
448+
449+
out:
450+
if (primary_if)
451+
hardif_free_ref(primary_if);
428452
}
429453

430454
static struct hard_iface *hardif_add_interface(struct net_device *net_dev)
@@ -514,6 +538,7 @@ static int hard_if_event(struct notifier_block *this,
514538
{
515539
struct net_device *net_dev = (struct net_device *)ptr;
516540
struct hard_iface *hard_iface = hardif_get_by_netdev(net_dev);
541+
struct hard_iface *primary_if = NULL;
517542
struct bat_priv *bat_priv;
518543

519544
if (!hard_iface && event == NETDEV_REGISTER)
@@ -549,8 +574,12 @@ static int hard_if_event(struct notifier_block *this,
549574
update_mac_addresses(hard_iface);
550575

551576
bat_priv = netdev_priv(hard_iface->soft_iface);
552-
if (hard_iface == bat_priv->primary_if)
553-
update_primary_addr(bat_priv);
577+
primary_if = primary_if_get_selected(bat_priv);
578+
if (!primary_if)
579+
goto hardif_put;
580+
581+
if (hard_iface == primary_if)
582+
primary_if_update_addr(bat_priv);
554583
break;
555584
default:
556585
break;
@@ -559,6 +588,8 @@ static int hard_if_event(struct notifier_block *this,
559588
hardif_put:
560589
hardif_free_ref(hard_iface);
561590
out:
591+
if (primary_if)
592+
hardif_free_ref(primary_if);
562593
return NOTIFY_DONE;
563594
}
564595

net/batman-adv/hard-interface.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,22 @@ static inline void hardif_free_ref(struct hard_iface *hard_iface)
4545
call_rcu(&hard_iface->rcu, hardif_free_rcu);
4646
}
4747

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+
4866
#endif /* _NET_BATMAN_ADV_HARD_INTERFACE_H_ */

net/batman-adv/icmp_socket.c

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
153153
{
154154
struct socket_client *socket_client = file->private_data;
155155
struct bat_priv *bat_priv = socket_client->bat_priv;
156+
struct hard_iface *primary_if = NULL;
156157
struct sk_buff *skb;
157158
struct icmp_packet_rr *icmp_packet;
158159

@@ -167,15 +168,21 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
167168
return -EINVAL;
168169
}
169170

170-
if (!bat_priv->primary_if)
171-
return -EFAULT;
171+
primary_if = primary_if_get_selected(bat_priv);
172+
173+
if (!primary_if) {
174+
len = -EFAULT;
175+
goto out;
176+
}
172177

173178
if (len >= sizeof(struct icmp_packet_rr))
174179
packet_len = sizeof(struct icmp_packet_rr);
175180

176181
skb = dev_alloc_skb(packet_len + sizeof(struct ethhdr));
177-
if (!skb)
178-
return -ENOMEM;
182+
if (!skb) {
183+
len = -ENOMEM;
184+
goto out;
185+
}
179186

180187
skb_reserve(skb, sizeof(struct ethhdr));
181188
icmp_packet = (struct icmp_packet_rr *)skb_put(skb, packet_len);
@@ -233,7 +240,7 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
233240
goto dst_unreach;
234241

235242
memcpy(icmp_packet->orig,
236-
bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN);
243+
primary_if->net_dev->dev_addr, ETH_ALEN);
237244

238245
if (packet_len == sizeof(struct icmp_packet_rr))
239246
memcpy(icmp_packet->rr,
@@ -248,6 +255,8 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff,
248255
free_skb:
249256
kfree_skb(skb);
250257
out:
258+
if (primary_if)
259+
hardif_free_ref(primary_if);
251260
if (neigh_node)
252261
neigh_node_free_ref(neigh_node);
253262
if (orig_node)

net/batman-adv/main.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,4 +175,6 @@ static inline int compare_eth(void *data1, void *data2)
175175
return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
176176
}
177177

178+
#define atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0)
179+
178180
#endif /* _NET_BATMAN_ADV_MAIN_H_ */

0 commit comments

Comments
 (0)