linux/net/tipc/bearer.c
<<
>>
Prefs
   1/*
   2 * net/tipc/bearer.c: TIPC bearer code
   3 *
   4 * Copyright (c) 1996-2006, Ericsson AB
   5 * Copyright (c) 2004-2006, 2010-2011, Wind River Systems
   6 * All rights reserved.
   7 *
   8 * Redistribution and use in source and binary forms, with or without
   9 * modification, are permitted provided that the following conditions are met:
  10 *
  11 * 1. Redistributions of source code must retain the above copyright
  12 *    notice, this list of conditions and the following disclaimer.
  13 * 2. Redistributions in binary form must reproduce the above copyright
  14 *    notice, this list of conditions and the following disclaimer in the
  15 *    documentation and/or other materials provided with the distribution.
  16 * 3. Neither the names of the copyright holders nor the names of its
  17 *    contributors may be used to endorse or promote products derived from
  18 *    this software without specific prior written permission.
  19 *
  20 * Alternatively, this software may be distributed under the terms of the
  21 * GNU General Public License ("GPL") version 2 as published by the Free
  22 * Software Foundation.
  23 *
  24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  34 * POSSIBILITY OF SUCH DAMAGE.
  35 */
  36
  37#include "core.h"
  38#include "config.h"
  39#include "bearer.h"
  40#include "discover.h"
  41
  42#define MAX_ADDR_STR 32
  43
  44static struct media media_list[MAX_MEDIA];
  45static u32 media_count;
  46
  47struct tipc_bearer tipc_bearers[MAX_BEARERS];
  48
  49static void bearer_disable(struct tipc_bearer *b_ptr);
  50
  51/**
  52 * media_name_valid - validate media name
  53 *
  54 * Returns 1 if media name is valid, otherwise 0.
  55 */
  56
  57static int media_name_valid(const char *name)
  58{
  59        u32 len;
  60
  61        len = strlen(name);
  62        if ((len + 1) > TIPC_MAX_MEDIA_NAME)
  63                return 0;
  64        return strspn(name, tipc_alphabet) == len;
  65}
  66
  67/**
  68 * media_find - locates specified media object by name
  69 */
  70
  71static struct media *media_find(const char *name)
  72{
  73        struct media *m_ptr;
  74        u32 i;
  75
  76        for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) {
  77                if (!strcmp(m_ptr->name, name))
  78                        return m_ptr;
  79        }
  80        return NULL;
  81}
  82
  83/**
  84 * tipc_register_media - register a media type
  85 *
  86 * Bearers for this media type must be activated separately at a later stage.
  87 */
  88
  89int  tipc_register_media(u32 media_type,
  90                         char *name,
  91                         int (*enable)(struct tipc_bearer *),
  92                         void (*disable)(struct tipc_bearer *),
  93                         int (*send_msg)(struct sk_buff *,
  94                                         struct tipc_bearer *,
  95                                         struct tipc_media_addr *),
  96                         char *(*addr2str)(struct tipc_media_addr *a,
  97                                           char *str_buf, int str_size),
  98                         struct tipc_media_addr *bcast_addr,
  99                         const u32 bearer_priority,
 100                         const u32 link_tolerance,  /* [ms] */
 101                         const u32 send_window_limit)
 102{
 103        struct media *m_ptr;
 104        u32 media_id;
 105        u32 i;
 106        int res = -EINVAL;
 107
 108        write_lock_bh(&tipc_net_lock);
 109
 110        if (tipc_mode != TIPC_NET_MODE) {
 111                warn("Media <%s> rejected, not in networked mode yet\n", name);
 112                goto exit;
 113        }
 114        if (!media_name_valid(name)) {
 115                warn("Media <%s> rejected, illegal name\n", name);
 116                goto exit;
 117        }
 118        if (!bcast_addr) {
 119                warn("Media <%s> rejected, no broadcast address\n", name);
 120                goto exit;
 121        }
 122        if ((bearer_priority < TIPC_MIN_LINK_PRI) ||
 123            (bearer_priority > TIPC_MAX_LINK_PRI)) {
 124                warn("Media <%s> rejected, illegal priority (%u)\n", name,
 125                     bearer_priority);
 126                goto exit;
 127        }
 128        if ((link_tolerance < TIPC_MIN_LINK_TOL) ||
 129            (link_tolerance > TIPC_MAX_LINK_TOL)) {
 130                warn("Media <%s> rejected, illegal tolerance (%u)\n", name,
 131                     link_tolerance);
 132                goto exit;
 133        }
 134
 135        media_id = media_count++;
 136        if (media_id >= MAX_MEDIA) {
 137                warn("Media <%s> rejected, media limit reached (%u)\n", name,
 138                     MAX_MEDIA);
 139                media_count--;
 140                goto exit;
 141        }
 142        for (i = 0; i < media_id; i++) {
 143                if (media_list[i].type_id == media_type) {
 144                        warn("Media <%s> rejected, duplicate type (%u)\n", name,
 145                             media_type);
 146                        media_count--;
 147                        goto exit;
 148                }
 149                if (!strcmp(name, media_list[i].name)) {
 150                        warn("Media <%s> rejected, duplicate name\n", name);
 151                        media_count--;
 152                        goto exit;
 153                }
 154        }
 155
 156        m_ptr = &media_list[media_id];
 157        m_ptr->type_id = media_type;
 158        m_ptr->send_msg = send_msg;
 159        m_ptr->enable_bearer = enable;
 160        m_ptr->disable_bearer = disable;
 161        m_ptr->addr2str = addr2str;
 162        memcpy(&m_ptr->bcast_addr, bcast_addr, sizeof(*bcast_addr));
 163        strcpy(m_ptr->name, name);
 164        m_ptr->priority = bearer_priority;
 165        m_ptr->tolerance = link_tolerance;
 166        m_ptr->window = send_window_limit;
 167        res = 0;
 168exit:
 169        write_unlock_bh(&tipc_net_lock);
 170        return res;
 171}
 172
 173/**
 174 * tipc_media_addr_printf - record media address in print buffer
 175 */
 176
 177void tipc_media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a)
 178{
 179        struct media *m_ptr;
 180        u32 media_type;
 181        u32 i;
 182
 183        media_type = ntohl(a->type);
 184        for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) {
 185                if (m_ptr->type_id == media_type)
 186                        break;
 187        }
 188
 189        if ((i < media_count) && (m_ptr->addr2str != NULL)) {
 190                char addr_str[MAX_ADDR_STR];
 191
 192                tipc_printf(pb, "%s(%s)", m_ptr->name,
 193                            m_ptr->addr2str(a, addr_str, sizeof(addr_str)));
 194        } else {
 195                unchar *addr = (unchar *)&a->dev_addr;
 196
 197                tipc_printf(pb, "UNKNOWN(%u)", media_type);
 198                for (i = 0; i < (sizeof(*a) - sizeof(a->type)); i++)
 199                        tipc_printf(pb, "-%02x", addr[i]);
 200        }
 201}
 202
 203/**
 204 * tipc_media_get_names - record names of registered media in buffer
 205 */
 206
 207struct sk_buff *tipc_media_get_names(void)
 208{
 209        struct sk_buff *buf;
 210        struct media *m_ptr;
 211        int i;
 212
 213        buf = tipc_cfg_reply_alloc(MAX_MEDIA * TLV_SPACE(TIPC_MAX_MEDIA_NAME));
 214        if (!buf)
 215                return NULL;
 216
 217        read_lock_bh(&tipc_net_lock);
 218        for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) {
 219                tipc_cfg_append_tlv(buf, TIPC_TLV_MEDIA_NAME, m_ptr->name,
 220                                    strlen(m_ptr->name) + 1);
 221        }
 222        read_unlock_bh(&tipc_net_lock);
 223        return buf;
 224}
 225
 226/**
 227 * bearer_name_validate - validate & (optionally) deconstruct bearer name
 228 * @name - ptr to bearer name string
 229 * @name_parts - ptr to area for bearer name components (or NULL if not needed)
 230 *
 231 * Returns 1 if bearer name is valid, otherwise 0.
 232 */
 233
 234static int bearer_name_validate(const char *name,
 235                                struct bearer_name *name_parts)
 236{
 237        char name_copy[TIPC_MAX_BEARER_NAME];
 238        char *media_name;
 239        char *if_name;
 240        u32 media_len;
 241        u32 if_len;
 242
 243        /* copy bearer name & ensure length is OK */
 244
 245        name_copy[TIPC_MAX_BEARER_NAME - 1] = 0;
 246        /* need above in case non-Posix strncpy() doesn't pad with nulls */
 247        strncpy(name_copy, name, TIPC_MAX_BEARER_NAME);
 248        if (name_copy[TIPC_MAX_BEARER_NAME - 1] != 0)
 249                return 0;
 250
 251        /* ensure all component parts of bearer name are present */
 252
 253        media_name = name_copy;
 254        if_name = strchr(media_name, ':');
 255        if (if_name == NULL)
 256                return 0;
 257        *(if_name++) = 0;
 258        media_len = if_name - media_name;
 259        if_len = strlen(if_name) + 1;
 260
 261        /* validate component parts of bearer name */
 262
 263        if ((media_len <= 1) || (media_len > TIPC_MAX_MEDIA_NAME) ||
 264            (if_len <= 1) || (if_len > TIPC_MAX_IF_NAME) ||
 265            (strspn(media_name, tipc_alphabet) != (media_len - 1)) ||
 266            (strspn(if_name, tipc_alphabet) != (if_len - 1)))
 267                return 0;
 268
 269        /* return bearer name components, if necessary */
 270
 271        if (name_parts) {
 272                strcpy(name_parts->media_name, media_name);
 273                strcpy(name_parts->if_name, if_name);
 274        }
 275        return 1;
 276}
 277
 278/**
 279 * bearer_find - locates bearer object with matching bearer name
 280 */
 281
 282static struct tipc_bearer *bearer_find(const char *name)
 283{
 284        struct tipc_bearer *b_ptr;
 285        u32 i;
 286
 287        for (i = 0, b_ptr = tipc_bearers; i < MAX_BEARERS; i++, b_ptr++) {
 288                if (b_ptr->active && (!strcmp(b_ptr->name, name)))
 289                        return b_ptr;
 290        }
 291        return NULL;
 292}
 293
 294/**
 295 * tipc_bearer_find_interface - locates bearer object with matching interface name
 296 */
 297
 298struct tipc_bearer *tipc_bearer_find_interface(const char *if_name)
 299{
 300        struct tipc_bearer *b_ptr;
 301        char *b_if_name;
 302        u32 i;
 303
 304        for (i = 0, b_ptr = tipc_bearers; i < MAX_BEARERS; i++, b_ptr++) {
 305                if (!b_ptr->active)
 306                        continue;
 307                b_if_name = strchr(b_ptr->name, ':') + 1;
 308                if (!strcmp(b_if_name, if_name))
 309                        return b_ptr;
 310        }
 311        return NULL;
 312}
 313
 314/**
 315 * tipc_bearer_get_names - record names of bearers in buffer
 316 */
 317
 318struct sk_buff *tipc_bearer_get_names(void)
 319{
 320        struct sk_buff *buf;
 321        struct media *m_ptr;
 322        struct tipc_bearer *b_ptr;
 323        int i, j;
 324
 325        buf = tipc_cfg_reply_alloc(MAX_BEARERS * TLV_SPACE(TIPC_MAX_BEARER_NAME));
 326        if (!buf)
 327                return NULL;
 328
 329        read_lock_bh(&tipc_net_lock);
 330        for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) {
 331                for (j = 0; j < MAX_BEARERS; j++) {
 332                        b_ptr = &tipc_bearers[j];
 333                        if (b_ptr->active && (b_ptr->media == m_ptr)) {
 334                                tipc_cfg_append_tlv(buf, TIPC_TLV_BEARER_NAME,
 335                                                    b_ptr->name,
 336                                                    strlen(b_ptr->name) + 1);
 337                        }
 338                }
 339        }
 340        read_unlock_bh(&tipc_net_lock);
 341        return buf;
 342}
 343
 344void tipc_bearer_add_dest(struct tipc_bearer *b_ptr, u32 dest)
 345{
 346        tipc_nmap_add(&b_ptr->nodes, dest);
 347        tipc_bcbearer_sort();
 348        tipc_disc_add_dest(b_ptr->link_req);
 349}
 350
 351void tipc_bearer_remove_dest(struct tipc_bearer *b_ptr, u32 dest)
 352{
 353        tipc_nmap_remove(&b_ptr->nodes, dest);
 354        tipc_bcbearer_sort();
 355        tipc_disc_remove_dest(b_ptr->link_req);
 356}
 357
 358/*
 359 * bearer_push(): Resolve bearer congestion. Force the waiting
 360 * links to push out their unsent packets, one packet per link
 361 * per iteration, until all packets are gone or congestion reoccurs.
 362 * 'tipc_net_lock' is read_locked when this function is called
 363 * bearer.lock must be taken before calling
 364 * Returns binary true(1) ore false(0)
 365 */
 366static int bearer_push(struct tipc_bearer *b_ptr)
 367{
 368        u32 res = 0;
 369        struct link *ln, *tln;
 370
 371        if (b_ptr->blocked)
 372                return 0;
 373
 374        while (!list_empty(&b_ptr->cong_links) && (res != PUSH_FAILED)) {
 375                list_for_each_entry_safe(ln, tln, &b_ptr->cong_links, link_list) {
 376                        res = tipc_link_push_packet(ln);
 377                        if (res == PUSH_FAILED)
 378                                break;
 379                        if (res == PUSH_FINISHED)
 380                                list_move_tail(&ln->link_list, &b_ptr->links);
 381                }
 382        }
 383        return list_empty(&b_ptr->cong_links);
 384}
 385
 386void tipc_bearer_lock_push(struct tipc_bearer *b_ptr)
 387{
 388        spin_lock_bh(&b_ptr->lock);
 389        bearer_push(b_ptr);
 390        spin_unlock_bh(&b_ptr->lock);
 391}
 392
 393
 394/*
 395 * Interrupt enabling new requests after bearer congestion or blocking:
 396 * See bearer_send().
 397 */
 398void tipc_continue(struct tipc_bearer *b_ptr)
 399{
 400        spin_lock_bh(&b_ptr->lock);
 401        if (!list_empty(&b_ptr->cong_links))
 402                tipc_k_signal((Handler)tipc_bearer_lock_push, (unsigned long)b_ptr);
 403        b_ptr->blocked = 0;
 404        spin_unlock_bh(&b_ptr->lock);
 405}
 406
 407/*
 408 * Schedule link for sending of messages after the bearer
 409 * has been deblocked by 'continue()'. This method is called
 410 * when somebody tries to send a message via this link while
 411 * the bearer is congested. 'tipc_net_lock' is in read_lock here
 412 * bearer.lock is busy
 413 */
 414
 415static void tipc_bearer_schedule_unlocked(struct tipc_bearer *b_ptr, struct link *l_ptr)
 416{
 417        list_move_tail(&l_ptr->link_list, &b_ptr->cong_links);
 418}
 419
 420/*
 421 * Schedule link for sending of messages after the bearer
 422 * has been deblocked by 'continue()'. This method is called
 423 * when somebody tries to send a message via this link while
 424 * the bearer is congested. 'tipc_net_lock' is in read_lock here,
 425 * bearer.lock is free
 426 */
 427
 428void tipc_bearer_schedule(struct tipc_bearer *b_ptr, struct link *l_ptr)
 429{
 430        spin_lock_bh(&b_ptr->lock);
 431        tipc_bearer_schedule_unlocked(b_ptr, l_ptr);
 432        spin_unlock_bh(&b_ptr->lock);
 433}
 434
 435
 436/*
 437 * tipc_bearer_resolve_congestion(): Check if there is bearer congestion,
 438 * and if there is, try to resolve it before returning.
 439 * 'tipc_net_lock' is read_locked when this function is called
 440 */
 441int tipc_bearer_resolve_congestion(struct tipc_bearer *b_ptr, struct link *l_ptr)
 442{
 443        int res = 1;
 444
 445        if (list_empty(&b_ptr->cong_links))
 446                return 1;
 447        spin_lock_bh(&b_ptr->lock);
 448        if (!bearer_push(b_ptr)) {
 449                tipc_bearer_schedule_unlocked(b_ptr, l_ptr);
 450                res = 0;
 451        }
 452        spin_unlock_bh(&b_ptr->lock);
 453        return res;
 454}
 455
 456/**
 457 * tipc_bearer_congested - determines if bearer is currently congested
 458 */
 459
 460int tipc_bearer_congested(struct tipc_bearer *b_ptr, struct link *l_ptr)
 461{
 462        if (unlikely(b_ptr->blocked))
 463                return 1;
 464        if (likely(list_empty(&b_ptr->cong_links)))
 465                return 0;
 466        return !tipc_bearer_resolve_congestion(b_ptr, l_ptr);
 467}
 468
 469/**
 470 * tipc_enable_bearer - enable bearer with the given name
 471 */
 472
 473int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority)
 474{
 475        struct tipc_bearer *b_ptr;
 476        struct media *m_ptr;
 477        struct bearer_name b_name;
 478        char addr_string[16];
 479        u32 bearer_id;
 480        u32 with_this_prio;
 481        u32 i;
 482        int res = -EINVAL;
 483
 484        if (tipc_mode != TIPC_NET_MODE) {
 485                warn("Bearer <%s> rejected, not supported in standalone mode\n",
 486                     name);
 487                return -ENOPROTOOPT;
 488        }
 489        if (!bearer_name_validate(name, &b_name)) {
 490                warn("Bearer <%s> rejected, illegal name\n", name);
 491                return -EINVAL;
 492        }
 493        if (tipc_addr_domain_valid(disc_domain) &&
 494            (disc_domain != tipc_own_addr)) {
 495                if (tipc_in_scope(disc_domain, tipc_own_addr)) {
 496                        disc_domain = tipc_own_addr & TIPC_CLUSTER_MASK;
 497                        res = 0;   /* accept any node in own cluster */
 498                } else if (in_own_cluster(disc_domain))
 499                        res = 0;   /* accept specified node in own cluster */
 500        }
 501        if (res) {
 502                warn("Bearer <%s> rejected, illegal discovery domain\n", name);
 503                return -EINVAL;
 504        }
 505        if ((priority < TIPC_MIN_LINK_PRI ||
 506             priority > TIPC_MAX_LINK_PRI) &&
 507            (priority != TIPC_MEDIA_LINK_PRI)) {
 508                warn("Bearer <%s> rejected, illegal priority\n", name);
 509                return -EINVAL;
 510        }
 511
 512        write_lock_bh(&tipc_net_lock);
 513
 514        m_ptr = media_find(b_name.media_name);
 515        if (!m_ptr) {
 516                warn("Bearer <%s> rejected, media <%s> not registered\n", name,
 517                     b_name.media_name);
 518                goto exit;
 519        }
 520
 521        if (priority == TIPC_MEDIA_LINK_PRI)
 522                priority = m_ptr->priority;
 523
 524restart:
 525        bearer_id = MAX_BEARERS;
 526        with_this_prio = 1;
 527        for (i = MAX_BEARERS; i-- != 0; ) {
 528                if (!tipc_bearers[i].active) {
 529                        bearer_id = i;
 530                        continue;
 531                }
 532                if (!strcmp(name, tipc_bearers[i].name)) {
 533                        warn("Bearer <%s> rejected, already enabled\n", name);
 534                        goto exit;
 535                }
 536                if ((tipc_bearers[i].priority == priority) &&
 537                    (++with_this_prio > 2)) {
 538                        if (priority-- == 0) {
 539                                warn("Bearer <%s> rejected, duplicate priority\n",
 540                                     name);
 541                                goto exit;
 542                        }
 543                        warn("Bearer <%s> priority adjustment required %u->%u\n",
 544                             name, priority + 1, priority);
 545                        goto restart;
 546                }
 547        }
 548        if (bearer_id >= MAX_BEARERS) {
 549                warn("Bearer <%s> rejected, bearer limit reached (%u)\n",
 550                     name, MAX_BEARERS);
 551                goto exit;
 552        }
 553
 554        b_ptr = &tipc_bearers[bearer_id];
 555        strcpy(b_ptr->name, name);
 556        res = m_ptr->enable_bearer(b_ptr);
 557        if (res) {
 558                warn("Bearer <%s> rejected, enable failure (%d)\n", name, -res);
 559                goto exit;
 560        }
 561
 562        b_ptr->identity = bearer_id;
 563        b_ptr->media = m_ptr;
 564        b_ptr->net_plane = bearer_id + 'A';
 565        b_ptr->active = 1;
 566        b_ptr->priority = priority;
 567        INIT_LIST_HEAD(&b_ptr->cong_links);
 568        INIT_LIST_HEAD(&b_ptr->links);
 569        spin_lock_init(&b_ptr->lock);
 570
 571        res = tipc_disc_create(b_ptr, &m_ptr->bcast_addr, disc_domain);
 572        if (res) {
 573                bearer_disable(b_ptr);
 574                warn("Bearer <%s> rejected, discovery object creation failed\n",
 575                     name);
 576                goto exit;
 577        }
 578        info("Enabled bearer <%s>, discovery domain %s, priority %u\n",
 579             name, tipc_addr_string_fill(addr_string, disc_domain), priority);
 580exit:
 581        write_unlock_bh(&tipc_net_lock);
 582        return res;
 583}
 584
 585/**
 586 * tipc_block_bearer(): Block the bearer with the given name,
 587 *                      and reset all its links
 588 */
 589
 590int tipc_block_bearer(const char *name)
 591{
 592        struct tipc_bearer *b_ptr = NULL;
 593        struct link *l_ptr;
 594        struct link *temp_l_ptr;
 595
 596        read_lock_bh(&tipc_net_lock);
 597        b_ptr = bearer_find(name);
 598        if (!b_ptr) {
 599                warn("Attempt to block unknown bearer <%s>\n", name);
 600                read_unlock_bh(&tipc_net_lock);
 601                return -EINVAL;
 602        }
 603
 604        info("Blocking bearer <%s>\n", name);
 605        spin_lock_bh(&b_ptr->lock);
 606        b_ptr->blocked = 1;
 607        list_splice_init(&b_ptr->cong_links, &b_ptr->links);
 608        list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) {
 609                struct tipc_node *n_ptr = l_ptr->owner;
 610
 611                spin_lock_bh(&n_ptr->lock);
 612                tipc_link_reset(l_ptr);
 613                spin_unlock_bh(&n_ptr->lock);
 614        }
 615        spin_unlock_bh(&b_ptr->lock);
 616        read_unlock_bh(&tipc_net_lock);
 617        return 0;
 618}
 619
 620/**
 621 * bearer_disable -
 622 *
 623 * Note: This routine assumes caller holds tipc_net_lock.
 624 */
 625
 626static void bearer_disable(struct tipc_bearer *b_ptr)
 627{
 628        struct link *l_ptr;
 629        struct link *temp_l_ptr;
 630
 631        info("Disabling bearer <%s>\n", b_ptr->name);
 632        spin_lock_bh(&b_ptr->lock);
 633        b_ptr->blocked = 1;
 634        b_ptr->media->disable_bearer(b_ptr);
 635        list_splice_init(&b_ptr->cong_links, &b_ptr->links);
 636        list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) {
 637                tipc_link_delete(l_ptr);
 638        }
 639        if (b_ptr->link_req)
 640                tipc_disc_delete(b_ptr->link_req);
 641        spin_unlock_bh(&b_ptr->lock);
 642        memset(b_ptr, 0, sizeof(struct tipc_bearer));
 643}
 644
 645int tipc_disable_bearer(const char *name)
 646{
 647        struct tipc_bearer *b_ptr;
 648        int res;
 649
 650        write_lock_bh(&tipc_net_lock);
 651        b_ptr = bearer_find(name);
 652        if (b_ptr == NULL) {
 653                warn("Attempt to disable unknown bearer <%s>\n", name);
 654                res = -EINVAL;
 655        } else {
 656                bearer_disable(b_ptr);
 657                res = 0;
 658        }
 659        write_unlock_bh(&tipc_net_lock);
 660        return res;
 661}
 662
 663
 664
 665void tipc_bearer_stop(void)
 666{
 667        u32 i;
 668
 669        for (i = 0; i < MAX_BEARERS; i++) {
 670                if (tipc_bearers[i].active)
 671                        bearer_disable(&tipc_bearers[i]);
 672        }
 673        media_count = 0;
 674}
 675
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.