@@ -98,6 +98,7 @@ void gw_election(struct bat_priv *bat_priv)
98
98
{
99
99
struct hlist_node * node ;
100
100
struct gw_node * gw_node , * curr_gw , * curr_gw_tmp = NULL ;
101
+ struct neigh_node * router ;
101
102
uint8_t max_tq = 0 ;
102
103
uint32_t max_gw_factor = 0 , tmp_gw_factor = 0 ;
103
104
int down , up ;
@@ -133,26 +134,26 @@ void gw_election(struct bat_priv *bat_priv)
133
134
}
134
135
135
136
hlist_for_each_entry_rcu (gw_node , node , & bat_priv -> gw_list , list ) {
136
- if (! gw_node -> orig_node -> router )
137
+ if (gw_node -> deleted )
137
138
continue ;
138
139
139
- if (gw_node -> deleted )
140
+ router = orig_node_get_router (gw_node -> orig_node );
141
+ if (!router )
140
142
continue ;
141
143
142
144
switch (atomic_read (& bat_priv -> gw_sel_class )) {
143
145
case 1 : /* fast connection */
144
146
gw_bandwidth_to_kbit (gw_node -> orig_node -> gw_flags ,
145
147
& down , & up );
146
148
147
- tmp_gw_factor = (gw_node -> orig_node -> router -> tq_avg *
148
- gw_node -> orig_node -> router -> tq_avg *
149
+ tmp_gw_factor = (router -> tq_avg * router -> tq_avg *
149
150
down * 100 * 100 ) /
150
151
(TQ_LOCAL_WINDOW_SIZE *
151
152
TQ_LOCAL_WINDOW_SIZE * 64 );
152
153
153
154
if ((tmp_gw_factor > max_gw_factor ) ||
154
155
((tmp_gw_factor == max_gw_factor ) &&
155
- (gw_node -> orig_node -> router -> tq_avg > max_tq )))
156
+ (router -> tq_avg > max_tq )))
156
157
curr_gw_tmp = gw_node ;
157
158
break ;
158
159
@@ -164,19 +165,25 @@ void gw_election(struct bat_priv *bat_priv)
164
165
* soon as a better gateway appears which has
165
166
* $routing_class more tq points)
166
167
**/
167
- if (gw_node -> orig_node -> router -> tq_avg > max_tq )
168
+ if (router -> tq_avg > max_tq )
168
169
curr_gw_tmp = gw_node ;
169
170
break ;
170
171
}
171
172
172
- if (gw_node -> orig_node -> router -> tq_avg > max_tq )
173
- max_tq = gw_node -> orig_node -> router -> tq_avg ;
173
+ if (router -> tq_avg > max_tq )
174
+ max_tq = router -> tq_avg ;
174
175
175
176
if (tmp_gw_factor > max_gw_factor )
176
177
max_gw_factor = tmp_gw_factor ;
178
+
179
+ neigh_node_free_ref (router );
177
180
}
178
181
179
182
if (curr_gw != curr_gw_tmp ) {
183
+ router = orig_node_get_router (curr_gw_tmp -> orig_node );
184
+ if (!router )
185
+ goto out ;
186
+
180
187
if ((curr_gw ) && (!curr_gw_tmp ))
181
188
bat_dbg (DBG_BATMAN , bat_priv ,
182
189
"Removing selected gateway - "
@@ -187,45 +194,47 @@ void gw_election(struct bat_priv *bat_priv)
187
194
"(gw_flags: %i, tq: %i)\n" ,
188
195
curr_gw_tmp -> orig_node -> orig ,
189
196
curr_gw_tmp -> orig_node -> gw_flags ,
190
- curr_gw_tmp -> orig_node -> router -> tq_avg );
197
+ router -> tq_avg );
191
198
else
192
199
bat_dbg (DBG_BATMAN , bat_priv ,
193
200
"Changing route to gateway %pM "
194
201
"(gw_flags: %i, tq: %i)\n" ,
195
202
curr_gw_tmp -> orig_node -> orig ,
196
203
curr_gw_tmp -> orig_node -> gw_flags ,
197
- curr_gw_tmp -> orig_node -> router -> tq_avg );
204
+ router -> tq_avg );
198
205
206
+ neigh_node_free_ref (router );
199
207
gw_select (bat_priv , curr_gw_tmp );
200
208
}
201
209
210
+ out :
202
211
rcu_read_unlock ();
203
212
}
204
213
205
214
void gw_check_election (struct bat_priv * bat_priv , struct orig_node * orig_node )
206
215
{
207
216
struct orig_node * curr_gw_orig ;
217
+ struct neigh_node * router_gw = NULL , * router_orig = NULL ;
208
218
uint8_t gw_tq_avg , orig_tq_avg ;
209
219
210
220
curr_gw_orig = gw_get_selected (bat_priv );
211
221
if (!curr_gw_orig )
212
222
goto deselect ;
213
223
214
- rcu_read_lock ( );
215
- if (!curr_gw_orig -> router )
216
- goto deselect_rcu ;
224
+ router_gw = orig_node_get_router ( curr_gw_orig );
225
+ if (!router_gw )
226
+ goto deselect ;
217
227
218
228
/* this node already is the gateway */
219
229
if (curr_gw_orig == orig_node )
220
- goto out_rcu ;
221
-
222
- if (!orig_node -> router )
223
- goto out_rcu ;
230
+ goto out ;
224
231
225
- gw_tq_avg = curr_gw_orig -> router -> tq_avg ;
226
- rcu_read_unlock ();
232
+ router_orig = orig_node_get_router (orig_node );
233
+ if (!router_orig )
234
+ goto out ;
227
235
228
- orig_tq_avg = orig_node -> router -> tq_avg ;
236
+ gw_tq_avg = router_gw -> tq_avg ;
237
+ orig_tq_avg = router_orig -> tq_avg ;
229
238
230
239
/* the TQ value has to be better */
231
240
if (orig_tq_avg < gw_tq_avg )
@@ -243,18 +252,16 @@ void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node)
243
252
"Restarting gateway selection: better gateway found (tq curr: "
244
253
"%i, tq new: %i)\n" ,
245
254
gw_tq_avg , orig_tq_avg );
246
- goto deselect ;
247
255
248
- out_rcu :
249
- rcu_read_unlock ();
250
- goto out ;
251
- deselect_rcu :
252
- rcu_read_unlock ();
253
256
deselect :
254
257
gw_deselect (bat_priv );
255
258
out :
256
259
if (curr_gw_orig )
257
260
orig_node_free_ref (curr_gw_orig );
261
+ if (router_gw )
262
+ neigh_node_free_ref (router_gw );
263
+ if (router_orig )
264
+ neigh_node_free_ref (router_orig );
258
265
259
266
return ;
260
267
}
@@ -362,30 +369,39 @@ void gw_node_purge(struct bat_priv *bat_priv)
362
369
spin_unlock_bh (& bat_priv -> gw_list_lock );
363
370
}
364
371
372
+ /**
373
+ * fails if orig_node has no router
374
+ */
365
375
static int _write_buffer_text (struct bat_priv * bat_priv ,
366
376
struct seq_file * seq , struct gw_node * gw_node )
367
377
{
368
378
struct gw_node * curr_gw ;
369
- int down , up , ret ;
379
+ struct neigh_node * router ;
380
+ int down , up , ret = -1 ;
370
381
371
382
gw_bandwidth_to_kbit (gw_node -> orig_node -> gw_flags , & down , & up );
372
383
384
+ router = orig_node_get_router (gw_node -> orig_node );
385
+ if (!router )
386
+ goto out ;
387
+
373
388
rcu_read_lock ();
374
389
curr_gw = rcu_dereference (bat_priv -> curr_gw );
375
390
376
391
ret = seq_printf (seq , "%s %pM (%3i) %pM [%10s]: %3i - %i%s/%i%s\n" ,
377
392
(curr_gw == gw_node ? "=>" : " " ),
378
393
gw_node -> orig_node -> orig ,
379
- gw_node -> orig_node -> router -> tq_avg ,
380
- gw_node -> orig_node -> router -> addr ,
381
- gw_node -> orig_node -> router -> if_incoming -> net_dev -> name ,
394
+ router -> tq_avg , router -> addr ,
395
+ router -> if_incoming -> net_dev -> name ,
382
396
gw_node -> orig_node -> gw_flags ,
383
397
(down > 2048 ? down / 1024 : down ),
384
398
(down > 2048 ? "MBit" : "KBit" ),
385
399
(up > 2048 ? up / 1024 : up ),
386
400
(up > 2048 ? "MBit" : "KBit" ));
387
401
388
402
rcu_read_unlock ();
403
+ neigh_node_free_ref (router );
404
+ out :
389
405
return ret ;
390
406
}
391
407
@@ -423,10 +439,10 @@ int gw_client_seq_print_text(struct seq_file *seq, void *offset)
423
439
if (gw_node -> deleted )
424
440
continue ;
425
441
426
- if (!gw_node -> orig_node -> router )
442
+ /* fails if orig_node has no router */
443
+ if (_write_buffer_text (bat_priv , seq , gw_node ) < 0 )
427
444
continue ;
428
445
429
- _write_buffer_text (bat_priv , seq , gw_node );
430
446
gw_count ++ ;
431
447
}
432
448
rcu_read_unlock ();
0 commit comments