Skip to content

Commit 9b40d5a

Browse files
committed
Merge tag 'batman-adv-fix-for-davem' of git://git.open-mesh.org/linux-merge
Antonio Quartulli says: ==================== In this small batch of patches you have: - a fix for our Distributed ARP Table that makes sure that the input provided to the hash function during a query is the same as the one provided during an insert (so to prevent false negatives), by Antonio Quartulli - a fix for our new protocol implementation B.A.T.M.A.N. V that ensures that a hard interface is properly re-activated when it is brought down and then up again, by Antonio Quartulli - two fixes respectively to the reference counting of the tt_local_entry and neigh_node objects, by Sven Eckelmann. Such bug is rather severe as it would prevent the netdev objects references by batman-adv from being released after shutdown. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents 33656a1 + abe59c6 commit 9b40d5a

File tree

6 files changed

+41
-56
lines changed

6 files changed

+41
-56
lines changed

net/batman-adv/bat_v.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,21 @@
3232

3333
#include "bat_v_elp.h"
3434
#include "bat_v_ogm.h"
35+
#include "hard-interface.h"
3536
#include "hash.h"
3637
#include "originator.h"
3738
#include "packet.h"
3839

40+
static void batadv_v_iface_activate(struct batadv_hard_iface *hard_iface)
41+
{
42+
/* B.A.T.M.A.N. V does not use any queuing mechanism, therefore it can
43+
* set the interface as ACTIVE right away, without any risk of race
44+
* condition
45+
*/
46+
if (hard_iface->if_status == BATADV_IF_TO_BE_ACTIVATED)
47+
hard_iface->if_status = BATADV_IF_ACTIVE;
48+
}
49+
3950
static int batadv_v_iface_enable(struct batadv_hard_iface *hard_iface)
4051
{
4152
int ret;
@@ -274,6 +285,7 @@ static bool batadv_v_neigh_is_sob(struct batadv_neigh_node *neigh1,
274285

275286
static struct batadv_algo_ops batadv_batman_v __read_mostly = {
276287
.name = "BATMAN_V",
288+
.bat_iface_activate = batadv_v_iface_activate,
277289
.bat_iface_enable = batadv_v_iface_enable,
278290
.bat_iface_disable = batadv_v_iface_disable,
279291
.bat_iface_update_mac = batadv_v_iface_update_mac,

net/batman-adv/distributed-arp-table.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,7 @@ static void batadv_choose_next_candidate(struct batadv_priv *bat_priv,
568568
* be sent to
569569
* @bat_priv: the bat priv with all the soft interface information
570570
* @ip_dst: ipv4 to look up in the DHT
571+
* @vid: VLAN identifier
571572
*
572573
* An originator O is selected if and only if its DHT_ID value is one of three
573574
* closest values (from the LEFT, with wrap around if needed) then the hash
@@ -576,7 +577,8 @@ static void batadv_choose_next_candidate(struct batadv_priv *bat_priv,
576577
* Return: the candidate array of size BATADV_DAT_CANDIDATE_NUM.
577578
*/
578579
static struct batadv_dat_candidate *
579-
batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst)
580+
batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst,
581+
unsigned short vid)
580582
{
581583
int select;
582584
batadv_dat_addr_t last_max = BATADV_DAT_ADDR_MAX, ip_key;
@@ -592,7 +594,7 @@ batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst)
592594
return NULL;
593595

594596
dat.ip = ip_dst;
595-
dat.vid = 0;
597+
dat.vid = vid;
596598
ip_key = (batadv_dat_addr_t)batadv_hash_dat(&dat,
597599
BATADV_DAT_ADDR_MAX);
598600

@@ -612,6 +614,7 @@ batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst)
612614
* @bat_priv: the bat priv with all the soft interface information
613615
* @skb: payload to send
614616
* @ip: the DHT key
617+
* @vid: VLAN identifier
615618
* @packet_subtype: unicast4addr packet subtype to use
616619
*
617620
* This function copies the skb with pskb_copy() and is sent as unicast packet
@@ -622,7 +625,7 @@ batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst)
622625
*/
623626
static bool batadv_dat_send_data(struct batadv_priv *bat_priv,
624627
struct sk_buff *skb, __be32 ip,
625-
int packet_subtype)
628+
unsigned short vid, int packet_subtype)
626629
{
627630
int i;
628631
bool ret = false;
@@ -631,7 +634,7 @@ static bool batadv_dat_send_data(struct batadv_priv *bat_priv,
631634
struct sk_buff *tmp_skb;
632635
struct batadv_dat_candidate *cand;
633636

634-
cand = batadv_dat_select_candidates(bat_priv, ip);
637+
cand = batadv_dat_select_candidates(bat_priv, ip, vid);
635638
if (!cand)
636639
goto out;
637640

@@ -1022,7 +1025,7 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
10221025
ret = true;
10231026
} else {
10241027
/* Send the request to the DHT */
1025-
ret = batadv_dat_send_data(bat_priv, skb, ip_dst,
1028+
ret = batadv_dat_send_data(bat_priv, skb, ip_dst, vid,
10261029
BATADV_P_DAT_DHT_GET);
10271030
}
10281031
out:
@@ -1150,8 +1153,8 @@ void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv,
11501153
/* Send the ARP reply to the candidates for both the IP addresses that
11511154
* the node obtained from the ARP reply
11521155
*/
1153-
batadv_dat_send_data(bat_priv, skb, ip_src, BATADV_P_DAT_DHT_PUT);
1154-
batadv_dat_send_data(bat_priv, skb, ip_dst, BATADV_P_DAT_DHT_PUT);
1156+
batadv_dat_send_data(bat_priv, skb, ip_src, vid, BATADV_P_DAT_DHT_PUT);
1157+
batadv_dat_send_data(bat_priv, skb, ip_dst, vid, BATADV_P_DAT_DHT_PUT);
11551158
}
11561159

11571160
/**

net/batman-adv/hard-interface.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,9 @@ batadv_hardif_activate_interface(struct batadv_hard_iface *hard_iface)
407407

408408
batadv_update_min_mtu(hard_iface->soft_iface);
409409

410+
if (bat_priv->bat_algo_ops->bat_iface_activate)
411+
bat_priv->bat_algo_ops->bat_iface_activate(hard_iface);
412+
410413
out:
411414
if (primary_if)
412415
batadv_hardif_put(primary_if);

net/batman-adv/originator.c

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,6 @@ static void batadv_neigh_node_release(struct kref *ref)
250250
{
251251
struct hlist_node *node_tmp;
252252
struct batadv_neigh_node *neigh_node;
253-
struct batadv_hardif_neigh_node *hardif_neigh;
254253
struct batadv_neigh_ifinfo *neigh_ifinfo;
255254
struct batadv_algo_ops *bao;
256255

@@ -262,13 +261,7 @@ static void batadv_neigh_node_release(struct kref *ref)
262261
batadv_neigh_ifinfo_put(neigh_ifinfo);
263262
}
264263

265-
hardif_neigh = batadv_hardif_neigh_get(neigh_node->if_incoming,
266-
neigh_node->addr);
267-
if (hardif_neigh) {
268-
/* batadv_hardif_neigh_get() increases refcount too */
269-
batadv_hardif_neigh_put(hardif_neigh);
270-
batadv_hardif_neigh_put(hardif_neigh);
271-
}
264+
batadv_hardif_neigh_put(neigh_node->hardif_neigh);
272265

273266
if (bao->bat_neigh_free)
274267
bao->bat_neigh_free(neigh_node);
@@ -665,6 +658,10 @@ batadv_neigh_node_new(struct batadv_orig_node *orig_node,
665658
neigh_node->orig_node = orig_node;
666659
neigh_node->last_seen = jiffies;
667660

661+
/* increment unique neighbor refcount */
662+
kref_get(&hardif_neigh->refcount);
663+
neigh_node->hardif_neigh = hardif_neigh;
664+
668665
/* extra reference for return */
669666
kref_init(&neigh_node->refcount);
670667
kref_get(&neigh_node->refcount);
@@ -673,9 +670,6 @@ batadv_neigh_node_new(struct batadv_orig_node *orig_node,
673670
hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list);
674671
spin_unlock_bh(&orig_node->neigh_list_lock);
675672

676-
/* increment unique neighbor refcount */
677-
kref_get(&hardif_neigh->refcount);
678-
679673
batadv_dbg(BATADV_DBG_BATMAN, orig_node->bat_priv,
680674
"Creating new neighbor %pM for orig_node %pM on interface %s\n",
681675
neigh_addr, orig_node->orig, hard_iface->net_dev->name);

net/batman-adv/translation-table.c

Lines changed: 4 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,8 @@ static void batadv_tt_local_entry_release(struct kref *ref)
215215
tt_local_entry = container_of(ref, struct batadv_tt_local_entry,
216216
common.refcount);
217217

218+
batadv_softif_vlan_put(tt_local_entry->vlan);
219+
218220
kfree_rcu(tt_local_entry, common.rcu);
219221
}
220222

@@ -673,6 +675,7 @@ bool batadv_tt_local_add(struct net_device *soft_iface, const u8 *addr,
673675
kref_get(&tt_local->common.refcount);
674676
tt_local->last_seen = jiffies;
675677
tt_local->common.added_at = tt_local->last_seen;
678+
tt_local->vlan = vlan;
676679

677680
/* the batman interface mac and multicast addresses should never be
678681
* purged
@@ -991,7 +994,6 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
991994
struct batadv_tt_common_entry *tt_common_entry;
992995
struct batadv_tt_local_entry *tt_local;
993996
struct batadv_hard_iface *primary_if;
994-
struct batadv_softif_vlan *vlan;
995997
struct hlist_head *head;
996998
unsigned short vid;
997999
u32 i;
@@ -1027,14 +1029,6 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
10271029
last_seen_msecs = last_seen_msecs % 1000;
10281030

10291031
no_purge = tt_common_entry->flags & np_flag;
1030-
1031-
vlan = batadv_softif_vlan_get(bat_priv, vid);
1032-
if (!vlan) {
1033-
seq_printf(seq, "Cannot retrieve VLAN %d\n",
1034-
BATADV_PRINT_VID(vid));
1035-
continue;
1036-
}
1037-
10381032
seq_printf(seq,
10391033
" * %pM %4i [%c%c%c%c%c%c] %3u.%03u (%#.8x)\n",
10401034
tt_common_entry->addr,
@@ -1052,9 +1046,7 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset)
10521046
BATADV_TT_CLIENT_ISOLA) ? 'I' : '.'),
10531047
no_purge ? 0 : last_seen_secs,
10541048
no_purge ? 0 : last_seen_msecs,
1055-
vlan->tt.crc);
1056-
1057-
batadv_softif_vlan_put(vlan);
1049+
tt_local->vlan->tt.crc);
10581050
}
10591051
rcu_read_unlock();
10601052
}
@@ -1099,7 +1091,6 @@ u16 batadv_tt_local_remove(struct batadv_priv *bat_priv, const u8 *addr,
10991091
{
11001092
struct batadv_tt_local_entry *tt_local_entry;
11011093
u16 flags, curr_flags = BATADV_NO_FLAGS;
1102-
struct batadv_softif_vlan *vlan;
11031094
void *tt_entry_exists;
11041095

11051096
tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr, vid);
@@ -1139,14 +1130,6 @@ u16 batadv_tt_local_remove(struct batadv_priv *bat_priv, const u8 *addr,
11391130
/* extra call to free the local tt entry */
11401131
batadv_tt_local_entry_put(tt_local_entry);
11411132

1142-
/* decrease the reference held for this vlan */
1143-
vlan = batadv_softif_vlan_get(bat_priv, vid);
1144-
if (!vlan)
1145-
goto out;
1146-
1147-
batadv_softif_vlan_put(vlan);
1148-
batadv_softif_vlan_put(vlan);
1149-
11501133
out:
11511134
if (tt_local_entry)
11521135
batadv_tt_local_entry_put(tt_local_entry);
@@ -1219,7 +1202,6 @@ static void batadv_tt_local_table_free(struct batadv_priv *bat_priv)
12191202
spinlock_t *list_lock; /* protects write access to the hash lists */
12201203
struct batadv_tt_common_entry *tt_common_entry;
12211204
struct batadv_tt_local_entry *tt_local;
1222-
struct batadv_softif_vlan *vlan;
12231205
struct hlist_node *node_tmp;
12241206
struct hlist_head *head;
12251207
u32 i;
@@ -1241,14 +1223,6 @@ static void batadv_tt_local_table_free(struct batadv_priv *bat_priv)
12411223
struct batadv_tt_local_entry,
12421224
common);
12431225

1244-
/* decrease the reference held for this vlan */
1245-
vlan = batadv_softif_vlan_get(bat_priv,
1246-
tt_common_entry->vid);
1247-
if (vlan) {
1248-
batadv_softif_vlan_put(vlan);
1249-
batadv_softif_vlan_put(vlan);
1250-
}
1251-
12521226
batadv_tt_local_entry_put(tt_local);
12531227
}
12541228
spin_unlock_bh(list_lock);
@@ -3309,7 +3283,6 @@ static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv)
33093283
struct batadv_hashtable *hash = bat_priv->tt.local_hash;
33103284
struct batadv_tt_common_entry *tt_common;
33113285
struct batadv_tt_local_entry *tt_local;
3312-
struct batadv_softif_vlan *vlan;
33133286
struct hlist_node *node_tmp;
33143287
struct hlist_head *head;
33153288
spinlock_t *list_lock; /* protects write access to the hash lists */
@@ -3339,13 +3312,6 @@ static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv)
33393312
struct batadv_tt_local_entry,
33403313
common);
33413314

3342-
/* decrease the reference held for this vlan */
3343-
vlan = batadv_softif_vlan_get(bat_priv, tt_common->vid);
3344-
if (vlan) {
3345-
batadv_softif_vlan_put(vlan);
3346-
batadv_softif_vlan_put(vlan);
3347-
}
3348-
33493315
batadv_tt_local_entry_put(tt_local);
33503316
}
33513317
spin_unlock_bh(list_lock);

net/batman-adv/types.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,7 @@ struct batadv_hardif_neigh_node {
433433
* @ifinfo_lock: lock protecting private ifinfo members and list
434434
* @if_incoming: pointer to incoming hard-interface
435435
* @last_seen: when last packet via this neighbor was received
436+
* @hardif_neigh: hardif_neigh of this neighbor
436437
* @refcount: number of contexts the object is used
437438
* @rcu: struct used for freeing in an RCU-safe manner
438439
*/
@@ -444,6 +445,7 @@ struct batadv_neigh_node {
444445
spinlock_t ifinfo_lock; /* protects ifinfo_list and its members */
445446
struct batadv_hard_iface *if_incoming;
446447
unsigned long last_seen;
448+
struct batadv_hardif_neigh_node *hardif_neigh;
447449
struct kref refcount;
448450
struct rcu_head rcu;
449451
};
@@ -1073,10 +1075,12 @@ struct batadv_tt_common_entry {
10731075
* struct batadv_tt_local_entry - translation table local entry data
10741076
* @common: general translation table data
10751077
* @last_seen: timestamp used for purging stale tt local entries
1078+
* @vlan: soft-interface vlan of the entry
10761079
*/
10771080
struct batadv_tt_local_entry {
10781081
struct batadv_tt_common_entry common;
10791082
unsigned long last_seen;
1083+
struct batadv_softif_vlan *vlan;
10801084
};
10811085

10821086
/**
@@ -1250,6 +1254,8 @@ struct batadv_forw_packet {
12501254
* struct batadv_algo_ops - mesh algorithm callbacks
12511255
* @list: list node for the batadv_algo_list
12521256
* @name: name of the algorithm
1257+
* @bat_iface_activate: start routing mechanisms when hard-interface is brought
1258+
* up
12531259
* @bat_iface_enable: init routing info when hard-interface is enabled
12541260
* @bat_iface_disable: de-init routing info when hard-interface is disabled
12551261
* @bat_iface_update_mac: (re-)init mac addresses of the protocol information
@@ -1277,6 +1283,7 @@ struct batadv_forw_packet {
12771283
struct batadv_algo_ops {
12781284
struct hlist_node list;
12791285
char *name;
1286+
void (*bat_iface_activate)(struct batadv_hard_iface *hard_iface);
12801287
int (*bat_iface_enable)(struct batadv_hard_iface *hard_iface);
12811288
void (*bat_iface_disable)(struct batadv_hard_iface *hard_iface);
12821289
void (*bat_iface_update_mac)(struct batadv_hard_iface *hard_iface);

0 commit comments

Comments
 (0)