@@ -44,6 +44,88 @@ static int batadv_compare_orig(const struct hlist_node *node, const void *data2)
44
44
return (memcmp (data1 , data2 , ETH_ALEN ) == 0 ? 1 : 0 );
45
45
}
46
46
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
+
47
129
int batadv_originator_init (struct batadv_priv * bat_priv )
48
130
{
49
131
if (bat_priv -> orig_hash )
@@ -218,6 +300,7 @@ struct batadv_orig_node *batadv_get_orig_node(struct batadv_priv *bat_priv,
218
300
const uint8_t * addr )
219
301
{
220
302
struct batadv_orig_node * orig_node ;
303
+ struct batadv_orig_node_vlan * vlan ;
221
304
int size , i ;
222
305
int hash_added ;
223
306
unsigned long reset_time ;
@@ -235,11 +318,13 @@ struct batadv_orig_node *batadv_get_orig_node(struct batadv_priv *bat_priv,
235
318
236
319
INIT_HLIST_HEAD (& orig_node -> neigh_list );
237
320
INIT_LIST_HEAD (& orig_node -> bond_list );
321
+ INIT_LIST_HEAD (& orig_node -> vlan_list );
238
322
spin_lock_init (& orig_node -> ogm_cnt_lock );
239
323
spin_lock_init (& orig_node -> bcast_seqno_lock );
240
324
spin_lock_init (& orig_node -> neigh_list_lock );
241
325
spin_lock_init (& orig_node -> tt_buff_lock );
242
326
spin_lock_init (& orig_node -> tt_lock );
327
+ spin_lock_init (& orig_node -> vlan_list_lock );
243
328
244
329
batadv_nc_init_orig (orig_node );
245
330
@@ -251,22 +336,30 @@ struct batadv_orig_node *batadv_get_orig_node(struct batadv_priv *bat_priv,
251
336
memcpy (orig_node -> orig , addr , ETH_ALEN );
252
337
batadv_dat_init_orig_node_addr (orig_node );
253
338
orig_node -> router = NULL ;
254
- orig_node -> tt_crc = 0 ;
255
339
atomic_set (& orig_node -> last_ttvn , 0 );
256
340
orig_node -> tt_buff = NULL ;
257
341
orig_node -> tt_buff_len = 0 ;
258
- atomic_set (& orig_node -> tt_size , 0 );
259
342
reset_time = jiffies - 1 - msecs_to_jiffies (BATADV_RESET_PROTECTION_MS );
260
343
orig_node -> bcast_seqno_reset = reset_time ;
261
344
orig_node -> batman_seqno_reset = reset_time ;
262
345
263
346
atomic_set (& orig_node -> bond_candidates , 0 );
264
347
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
+
265
358
size = bat_priv -> num_ifaces * sizeof (unsigned long ) * BATADV_NUM_WORDS ;
266
359
267
360
orig_node -> bcast_own = kzalloc (size , GFP_ATOMIC );
268
361
if (!orig_node -> bcast_own )
269
- goto free_orig_node ;
362
+ goto free_vlan ;
270
363
271
364
size = bat_priv -> num_ifaces * sizeof (uint8_t );
272
365
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,
291
384
kfree (orig_node -> bcast_own_sum );
292
385
free_bcast_own :
293
386
kfree (orig_node -> bcast_own );
387
+ free_vlan :
388
+ batadv_orig_node_vlan_free_ref (vlan );
294
389
free_orig_node :
295
390
kfree (orig_node );
296
391
return NULL ;
0 commit comments