Skip to content

Commit 7ea7b4a

Browse files
committed
batman-adv: make the TT CRC logic VLAN specific
This change allows nodes to handle the TT table on a per-VLAN basis. This is needed because nodes may have to store only some of the global entries advertised by another node. In this scenario such nodes would re-create only a partial global table and would not be able to compute a correct CRC anymore. This patch splits the logic and introduces one CRC per VLAN. In this way a node fetching only some entries belonging to some VLANs is still able to compute the needed CRCs and still check the table correctness. With this patch the shape of the TVLV-TT is changed too because now a node needs to advertise all the CRCs of all the VLANs that it is wired to. The debug output of the local Translation Table now shows the CRC along with each entry since there is not a common value for the entire table anymore. Signed-off-by: Antonio Quartulli <antonio@open-mesh.com> Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
1 parent a70a9aa commit 7ea7b4a

File tree

5 files changed

+730
-157
lines changed

5 files changed

+730
-157
lines changed

net/batman-adv/originator.c

Lines changed: 98 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,88 @@ static int batadv_compare_orig(const struct hlist_node *node, const void *data2)
4444
return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0);
4545
}
4646

47+
/**
48+
* batadv_orig_node_vlan_get - get an orig_node_vlan object
49+
* @orig_node: the originator serving the VLAN
50+
* @vid: the VLAN identifier
51+
*
52+
* Returns the vlan object identified by vid and belonging to orig_node or NULL
53+
* if it does not exist.
54+
*/
55+
struct batadv_orig_node_vlan *
56+
batadv_orig_node_vlan_get(struct batadv_orig_node *orig_node,
57+
unsigned short vid)
58+
{
59+
struct batadv_orig_node_vlan *vlan = NULL, *tmp;
60+
61+
rcu_read_lock();
62+
list_for_each_entry_rcu(tmp, &orig_node->vlan_list, list) {
63+
if (tmp->vid != vid)
64+
continue;
65+
66+
if (!atomic_inc_not_zero(&tmp->refcount))
67+
continue;
68+
69+
vlan = tmp;
70+
71+
break;
72+
}
73+
rcu_read_unlock();
74+
75+
return vlan;
76+
}
77+
78+
/**
79+
* batadv_orig_node_vlan_new - search and possibly create an orig_node_vlan
80+
* object
81+
* @orig_node: the originator serving the VLAN
82+
* @vid: the VLAN identifier
83+
*
84+
* Returns NULL in case of failure or the vlan object identified by vid and
85+
* belonging to orig_node otherwise. The object is created and added to the list
86+
* if it does not exist.
87+
*
88+
* The object is returned with refcounter increased by 1.
89+
*/
90+
struct batadv_orig_node_vlan *
91+
batadv_orig_node_vlan_new(struct batadv_orig_node *orig_node,
92+
unsigned short vid)
93+
{
94+
struct batadv_orig_node_vlan *vlan;
95+
96+
spin_lock_bh(&orig_node->vlan_list_lock);
97+
98+
/* first look if an object for this vid already exists */
99+
vlan = batadv_orig_node_vlan_get(orig_node, vid);
100+
if (vlan)
101+
goto out;
102+
103+
vlan = kzalloc(sizeof(*vlan), GFP_ATOMIC);
104+
if (!vlan)
105+
goto out;
106+
107+
atomic_set(&vlan->refcount, 2);
108+
vlan->vid = vid;
109+
110+
list_add_rcu(&vlan->list, &orig_node->vlan_list);
111+
112+
out:
113+
spin_unlock_bh(&orig_node->vlan_list_lock);
114+
115+
return vlan;
116+
}
117+
118+
/**
119+
* batadv_orig_node_vlan_free_ref - decrement the refcounter and possibly free
120+
* the originator-vlan object
121+
* @orig_vlan: the originator-vlan object to release
122+
*/
123+
void batadv_orig_node_vlan_free_ref(struct batadv_orig_node_vlan *orig_vlan)
124+
{
125+
if (atomic_dec_and_test(&orig_vlan->refcount))
126+
kfree_rcu(orig_vlan, rcu);
127+
}
128+
47129
int batadv_originator_init(struct batadv_priv *bat_priv)
48130
{
49131
if (bat_priv->orig_hash)
@@ -218,6 +300,7 @@ struct batadv_orig_node *batadv_get_orig_node(struct batadv_priv *bat_priv,
218300
const uint8_t *addr)
219301
{
220302
struct batadv_orig_node *orig_node;
303+
struct batadv_orig_node_vlan *vlan;
221304
int size, i;
222305
int hash_added;
223306
unsigned long reset_time;
@@ -235,11 +318,13 @@ struct batadv_orig_node *batadv_get_orig_node(struct batadv_priv *bat_priv,
235318

236319
INIT_HLIST_HEAD(&orig_node->neigh_list);
237320
INIT_LIST_HEAD(&orig_node->bond_list);
321+
INIT_LIST_HEAD(&orig_node->vlan_list);
238322
spin_lock_init(&orig_node->ogm_cnt_lock);
239323
spin_lock_init(&orig_node->bcast_seqno_lock);
240324
spin_lock_init(&orig_node->neigh_list_lock);
241325
spin_lock_init(&orig_node->tt_buff_lock);
242326
spin_lock_init(&orig_node->tt_lock);
327+
spin_lock_init(&orig_node->vlan_list_lock);
243328

244329
batadv_nc_init_orig(orig_node);
245330

@@ -251,22 +336,30 @@ struct batadv_orig_node *batadv_get_orig_node(struct batadv_priv *bat_priv,
251336
memcpy(orig_node->orig, addr, ETH_ALEN);
252337
batadv_dat_init_orig_node_addr(orig_node);
253338
orig_node->router = NULL;
254-
orig_node->tt_crc = 0;
255339
atomic_set(&orig_node->last_ttvn, 0);
256340
orig_node->tt_buff = NULL;
257341
orig_node->tt_buff_len = 0;
258-
atomic_set(&orig_node->tt_size, 0);
259342
reset_time = jiffies - 1 - msecs_to_jiffies(BATADV_RESET_PROTECTION_MS);
260343
orig_node->bcast_seqno_reset = reset_time;
261344
orig_node->batman_seqno_reset = reset_time;
262345

263346
atomic_set(&orig_node->bond_candidates, 0);
264347

348+
/* create a vlan object for the "untagged" LAN */
349+
vlan = batadv_orig_node_vlan_new(orig_node, BATADV_NO_FLAGS);
350+
if (!vlan)
351+
goto free_orig_node;
352+
/* batadv_orig_node_vlan_new() increases the refcounter.
353+
* Immediately release vlan since it is not needed anymore in this
354+
* context
355+
*/
356+
batadv_orig_node_vlan_free_ref(vlan);
357+
265358
size = bat_priv->num_ifaces * sizeof(unsigned long) * BATADV_NUM_WORDS;
266359

267360
orig_node->bcast_own = kzalloc(size, GFP_ATOMIC);
268361
if (!orig_node->bcast_own)
269-
goto free_orig_node;
362+
goto free_vlan;
270363

271364
size = bat_priv->num_ifaces * sizeof(uint8_t);
272365
orig_node->bcast_own_sum = kzalloc(size, GFP_ATOMIC);
@@ -291,6 +384,8 @@ struct batadv_orig_node *batadv_get_orig_node(struct batadv_priv *bat_priv,
291384
kfree(orig_node->bcast_own_sum);
292385
free_bcast_own:
293386
kfree(orig_node->bcast_own);
387+
free_vlan:
388+
batadv_orig_node_vlan_free_ref(vlan);
294389
free_orig_node:
295390
kfree(orig_node);
296391
return NULL;

net/batman-adv/originator.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,13 @@ int batadv_orig_hash_add_if(struct batadv_hard_iface *hard_iface,
4040
int max_if_num);
4141
int batadv_orig_hash_del_if(struct batadv_hard_iface *hard_iface,
4242
int max_if_num);
43+
struct batadv_orig_node_vlan *
44+
batadv_orig_node_vlan_new(struct batadv_orig_node *orig_node,
45+
unsigned short vid);
46+
struct batadv_orig_node_vlan *
47+
batadv_orig_node_vlan_get(struct batadv_orig_node *orig_node,
48+
unsigned short vid);
49+
void batadv_orig_node_vlan_free_ref(struct batadv_orig_node_vlan *orig_vlan);
4350

4451

4552
/* hashfunction to choose an entry in a hash table of given size

net/batman-adv/packet.h

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -391,14 +391,26 @@ struct batadv_tvlv_gateway_data {
391391
* struct batadv_tvlv_tt_data - tt data propagated through the tt tvlv container
392392
* @flags: translation table flags (see batadv_tt_data_flags)
393393
* @ttvn: translation table version number
394-
* @reserved: field reserved for future use
395-
* @crc: crc32 checksum of the local translation table
394+
* @vlan_num: number of announced VLANs. In the TVLV this struct is followed by
395+
* one batadv_tvlv_tt_vlan_data object per announced vlan
396396
*/
397397
struct batadv_tvlv_tt_data {
398398
uint8_t flags;
399399
uint8_t ttvn;
400+
__be16 num_vlan;
401+
};
402+
403+
/**
404+
* struct batadv_tvlv_tt_vlan_data - vlan specific tt data propagated through
405+
* the tt tvlv container
406+
* @crc: crc32 checksum of the entries belonging to this vlan
407+
* @vid: vlan identifier
408+
* @reserved: unused, useful for alignment purposes
409+
*/
410+
struct batadv_tvlv_tt_vlan_data {
411+
__be32 crc;
412+
__be16 vid;
400413
uint16_t reserved;
401-
__be32 crc;
402414
};
403415

404416
/**

0 commit comments

Comments
 (0)