aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/bearer.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/tipc/bearer.c')
-rw-r--r--net/tipc/bearer.c96
1 files changed, 51 insertions, 45 deletions
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c
index 574b86193b15..3fef7eb776dc 100644
--- a/net/tipc/bearer.c
+++ b/net/tipc/bearer.c
@@ -49,9 +49,9 @@ static struct tipc_media * const media_info_array[] = {
49 NULL 49 NULL
50}; 50};
51 51
52struct tipc_bearer tipc_bearers[MAX_BEARERS]; 52struct tipc_bearer *bearer_list[MAX_BEARERS + 1];
53 53
54static void bearer_disable(struct tipc_bearer *b_ptr); 54static void bearer_disable(struct tipc_bearer *b_ptr, bool shutting_down);
55 55
56/** 56/**
57 * tipc_media_find - locates specified media object by name 57 * tipc_media_find - locates specified media object by name
@@ -177,8 +177,9 @@ struct tipc_bearer *tipc_bearer_find(const char *name)
177 struct tipc_bearer *b_ptr; 177 struct tipc_bearer *b_ptr;
178 u32 i; 178 u32 i;
179 179
180 for (i = 0, b_ptr = tipc_bearers; i < MAX_BEARERS; i++, b_ptr++) { 180 for (i = 0; i < MAX_BEARERS; i++) {
181 if (b_ptr->active && (!strcmp(b_ptr->name, name))) 181 b_ptr = bearer_list[i];
182 if (b_ptr && (!strcmp(b_ptr->name, name)))
182 return b_ptr; 183 return b_ptr;
183 } 184 }
184 return NULL; 185 return NULL;
@@ -200,8 +201,10 @@ struct sk_buff *tipc_bearer_get_names(void)
200 read_lock_bh(&tipc_net_lock); 201 read_lock_bh(&tipc_net_lock);
201 for (i = 0; media_info_array[i] != NULL; i++) { 202 for (i = 0; media_info_array[i] != NULL; i++) {
202 for (j = 0; j < MAX_BEARERS; j++) { 203 for (j = 0; j < MAX_BEARERS; j++) {
203 b = &tipc_bearers[j]; 204 b = bearer_list[j];
204 if (b->active && (b->media == media_info_array[i])) { 205 if (!b)
206 continue;
207 if (b->media == media_info_array[i]) {
205 tipc_cfg_append_tlv(buf, TIPC_TLV_BEARER_NAME, 208 tipc_cfg_append_tlv(buf, TIPC_TLV_BEARER_NAME,
206 b->name, 209 b->name,
207 strlen(b->name) + 1); 210 strlen(b->name) + 1);
@@ -284,16 +287,17 @@ restart:
284 bearer_id = MAX_BEARERS; 287 bearer_id = MAX_BEARERS;
285 with_this_prio = 1; 288 with_this_prio = 1;
286 for (i = MAX_BEARERS; i-- != 0; ) { 289 for (i = MAX_BEARERS; i-- != 0; ) {
287 if (!tipc_bearers[i].active) { 290 b_ptr = bearer_list[i];
291 if (!b_ptr) {
288 bearer_id = i; 292 bearer_id = i;
289 continue; 293 continue;
290 } 294 }
291 if (!strcmp(name, tipc_bearers[i].name)) { 295 if (!strcmp(name, b_ptr->name)) {
292 pr_warn("Bearer <%s> rejected, already enabled\n", 296 pr_warn("Bearer <%s> rejected, already enabled\n",
293 name); 297 name);
294 goto exit; 298 goto exit;
295 } 299 }
296 if ((tipc_bearers[i].priority == priority) && 300 if ((b_ptr->priority == priority) &&
297 (++with_this_prio > 2)) { 301 (++with_this_prio > 2)) {
298 if (priority-- == 0) { 302 if (priority-- == 0) {
299 pr_warn("Bearer <%s> rejected, duplicate priority\n", 303 pr_warn("Bearer <%s> rejected, duplicate priority\n",
@@ -311,7 +315,11 @@ restart:
311 goto exit; 315 goto exit;
312 } 316 }
313 317
314 b_ptr = &tipc_bearers[bearer_id]; 318 b_ptr = kzalloc(sizeof(*b_ptr), GFP_ATOMIC);
319 if (!b_ptr) {
320 res = -ENOMEM;
321 goto exit;
322 }
315 strcpy(b_ptr->name, name); 323 strcpy(b_ptr->name, name);
316 b_ptr->media = m_ptr; 324 b_ptr->media = m_ptr;
317 res = m_ptr->enable_media(b_ptr); 325 res = m_ptr->enable_media(b_ptr);
@@ -324,19 +332,20 @@ restart:
324 b_ptr->identity = bearer_id; 332 b_ptr->identity = bearer_id;
325 b_ptr->tolerance = m_ptr->tolerance; 333 b_ptr->tolerance = m_ptr->tolerance;
326 b_ptr->window = m_ptr->window; 334 b_ptr->window = m_ptr->window;
335 b_ptr->domain = disc_domain;
327 b_ptr->net_plane = bearer_id + 'A'; 336 b_ptr->net_plane = bearer_id + 'A';
328 b_ptr->active = 1;
329 b_ptr->priority = priority; 337 b_ptr->priority = priority;
330 INIT_LIST_HEAD(&b_ptr->links);
331 spin_lock_init(&b_ptr->lock);
332 338
333 res = tipc_disc_create(b_ptr, &b_ptr->bcast_addr, disc_domain); 339 res = tipc_disc_create(b_ptr, &b_ptr->bcast_addr);
334 if (res) { 340 if (res) {
335 bearer_disable(b_ptr); 341 bearer_disable(b_ptr, false);
336 pr_warn("Bearer <%s> rejected, discovery object creation failed\n", 342 pr_warn("Bearer <%s> rejected, discovery object creation failed\n",
337 name); 343 name);
338 goto exit; 344 goto exit;
339 } 345 }
346
347 bearer_list[bearer_id] = b_ptr;
348
340 pr_info("Enabled bearer <%s>, discovery domain %s, priority %u\n", 349 pr_info("Enabled bearer <%s>, discovery domain %s, priority %u\n",
341 name, 350 name,
342 tipc_addr_string_fill(addr_string, disc_domain), priority); 351 tipc_addr_string_fill(addr_string, disc_domain), priority);
@@ -350,20 +359,11 @@ exit:
350 */ 359 */
351static int tipc_reset_bearer(struct tipc_bearer *b_ptr) 360static int tipc_reset_bearer(struct tipc_bearer *b_ptr)
352{ 361{
353 struct tipc_link *l_ptr;
354 struct tipc_link *temp_l_ptr;
355
356 read_lock_bh(&tipc_net_lock); 362 read_lock_bh(&tipc_net_lock);
357 pr_info("Resetting bearer <%s>\n", b_ptr->name); 363 pr_info("Resetting bearer <%s>\n", b_ptr->name);
358 spin_lock_bh(&b_ptr->lock); 364 tipc_disc_delete(b_ptr->link_req);
359 list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { 365 tipc_link_reset_list(b_ptr->identity);
360 struct tipc_node *n_ptr = l_ptr->owner; 366 tipc_disc_create(b_ptr, &b_ptr->bcast_addr);
361
362 spin_lock_bh(&n_ptr->lock);
363 tipc_link_reset(l_ptr);
364 spin_unlock_bh(&n_ptr->lock);
365 }
366 spin_unlock_bh(&b_ptr->lock);
367 read_unlock_bh(&tipc_net_lock); 367 read_unlock_bh(&tipc_net_lock);
368 return 0; 368 return 0;
369} 369}
@@ -373,26 +373,24 @@ static int tipc_reset_bearer(struct tipc_bearer *b_ptr)
373 * 373 *
374 * Note: This routine assumes caller holds tipc_net_lock. 374 * Note: This routine assumes caller holds tipc_net_lock.
375 */ 375 */
376static void bearer_disable(struct tipc_bearer *b_ptr) 376static void bearer_disable(struct tipc_bearer *b_ptr, bool shutting_down)
377{ 377{
378 struct tipc_link *l_ptr; 378 u32 i;
379 struct tipc_link *temp_l_ptr;
380 struct tipc_link_req *temp_req;
381 379
382 pr_info("Disabling bearer <%s>\n", b_ptr->name); 380 pr_info("Disabling bearer <%s>\n", b_ptr->name);
383 spin_lock_bh(&b_ptr->lock);
384 b_ptr->media->disable_media(b_ptr); 381 b_ptr->media->disable_media(b_ptr);
385 list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) {
386 tipc_link_delete(l_ptr);
387 }
388 temp_req = b_ptr->link_req;
389 b_ptr->link_req = NULL;
390 spin_unlock_bh(&b_ptr->lock);
391 382
392 if (temp_req) 383 tipc_link_delete_list(b_ptr->identity, shutting_down);
393 tipc_disc_delete(temp_req); 384 if (b_ptr->link_req)
385 tipc_disc_delete(b_ptr->link_req);
394 386
395 memset(b_ptr, 0, sizeof(struct tipc_bearer)); 387 for (i = 0; i < MAX_BEARERS; i++) {
388 if (b_ptr == bearer_list[i]) {
389 bearer_list[i] = NULL;
390 break;
391 }
392 }
393 kfree(b_ptr);
396} 394}
397 395
398int tipc_disable_bearer(const char *name) 396int tipc_disable_bearer(const char *name)
@@ -406,7 +404,7 @@ int tipc_disable_bearer(const char *name)
406 pr_warn("Attempt to disable unknown bearer <%s>\n", name); 404 pr_warn("Attempt to disable unknown bearer <%s>\n", name);
407 res = -EINVAL; 405 res = -EINVAL;
408 } else { 406 } else {
409 bearer_disable(b_ptr); 407 bearer_disable(b_ptr, false);
410 res = 0; 408 res = 0;
411 } 409 }
412 write_unlock_bh(&tipc_net_lock); 410 write_unlock_bh(&tipc_net_lock);
@@ -585,7 +583,11 @@ static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt,
585 break; 583 break;
586 case NETDEV_DOWN: 584 case NETDEV_DOWN:
587 case NETDEV_CHANGEMTU: 585 case NETDEV_CHANGEMTU:
586 tipc_reset_bearer(b_ptr);
587 break;
588 case NETDEV_CHANGEADDR: 588 case NETDEV_CHANGEADDR:
589 tipc_l2_media_addr_set(b_ptr, &b_ptr->addr,
590 (char *)dev->dev_addr);
589 tipc_reset_bearer(b_ptr); 591 tipc_reset_bearer(b_ptr);
590 break; 592 break;
591 case NETDEV_UNREGISTER: 593 case NETDEV_UNREGISTER:
@@ -599,7 +601,7 @@ static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt,
599} 601}
600 602
601static struct packet_type tipc_packet_type __read_mostly = { 603static struct packet_type tipc_packet_type __read_mostly = {
602 .type = __constant_htons(ETH_P_TIPC), 604 .type = htons(ETH_P_TIPC),
603 .func = tipc_l2_rcv_msg, 605 .func = tipc_l2_rcv_msg,
604}; 606};
605 607
@@ -627,10 +629,14 @@ void tipc_bearer_cleanup(void)
627 629
628void tipc_bearer_stop(void) 630void tipc_bearer_stop(void)
629{ 631{
632 struct tipc_bearer *b_ptr;
630 u32 i; 633 u32 i;
631 634
632 for (i = 0; i < MAX_BEARERS; i++) { 635 for (i = 0; i < MAX_BEARERS; i++) {
633 if (tipc_bearers[i].active) 636 b_ptr = bearer_list[i];
634 bearer_disable(&tipc_bearers[i]); 637 if (b_ptr) {
638 bearer_disable(b_ptr, true);
639 bearer_list[i] = NULL;
640 }
635 } 641 }
636} 642}