linux/net/tipc/name_table.c
<<
>>
Prefs
   1/*
   2 * net/tipc/name_table.c: TIPC name table code
   3 *
   4 * Copyright (c) 2000-2006, Ericsson AB
   5 * Copyright (c) 2004-2008, 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 "name_table.h"
  40#include "name_distr.h"
  41#include "subscr.h"
  42#include "port.h"
  43
  44static int tipc_nametbl_size = 1024;            /* must be a power of 2 */
  45
  46/**
  47 * struct name_info - name sequence publication info
  48 * @node_list: circular list of publications made by own node
  49 * @cluster_list: circular list of publications made by own cluster
  50 * @zone_list: circular list of publications made by own zone
  51 * @node_list_size: number of entries in "node_list"
  52 * @cluster_list_size: number of entries in "cluster_list"
  53 * @zone_list_size: number of entries in "zone_list"
  54 *
  55 * Note: The zone list always contains at least one entry, since all
  56 *       publications of the associated name sequence belong to it.
  57 *       (The cluster and node lists may be empty.)
  58 */
  59
  60struct name_info {
  61        struct list_head node_list;
  62        struct list_head cluster_list;
  63        struct list_head zone_list;
  64        u32 node_list_size;
  65        u32 cluster_list_size;
  66        u32 zone_list_size;
  67};
  68
  69/**
  70 * struct sub_seq - container for all published instances of a name sequence
  71 * @lower: name sequence lower bound
  72 * @upper: name sequence upper bound
  73 * @info: pointer to name sequence publication info
  74 */
  75
  76struct sub_seq {
  77        u32 lower;
  78        u32 upper;
  79        struct name_info *info;
  80};
  81
  82/**
  83 * struct name_seq - container for all published instances of a name type
  84 * @type: 32 bit 'type' value for name sequence
  85 * @sseq: pointer to dynamically-sized array of sub-sequences of this 'type';
  86 *        sub-sequences are sorted in ascending order
  87 * @alloc: number of sub-sequences currently in array
  88 * @first_free: array index of first unused sub-sequence entry
  89 * @ns_list: links to adjacent name sequences in hash chain
  90 * @subscriptions: list of subscriptions for this 'type'
  91 * @lock: spinlock controlling access to publication lists of all sub-sequences
  92 */
  93
  94struct name_seq {
  95        u32 type;
  96        struct sub_seq *sseqs;
  97        u32 alloc;
  98        u32 first_free;
  99        struct hlist_node ns_list;
 100        struct list_head subscriptions;
 101        spinlock_t lock;
 102};
 103
 104/**
 105 * struct name_table - table containing all existing port name publications
 106 * @types: pointer to fixed-sized array of name sequence lists,
 107 *         accessed via hashing on 'type'; name sequence lists are *not* sorted
 108 * @local_publ_count: number of publications issued by this node
 109 */
 110
 111struct name_table {
 112        struct hlist_head *types;
 113        u32 local_publ_count;
 114};
 115
 116static struct name_table table;
 117static atomic_t rsv_publ_ok = ATOMIC_INIT(0);
 118DEFINE_RWLOCK(tipc_nametbl_lock);
 119
 120
 121static int hash(int x)
 122{
 123        return x & (tipc_nametbl_size - 1);
 124}
 125
 126/**
 127 * publ_create - create a publication structure
 128 */
 129
 130static struct publication *publ_create(u32 type, u32 lower, u32 upper,
 131                                       u32 scope, u32 node, u32 port_ref,
 132                                       u32 key)
 133{
 134        struct publication *publ = kzalloc(sizeof(*publ), GFP_ATOMIC);
 135        if (publ == NULL) {
 136                warn("Publication creation failure, no memory\n");
 137                return NULL;
 138        }
 139
 140        publ->type = type;
 141        publ->lower = lower;
 142        publ->upper = upper;
 143        publ->scope = scope;
 144        publ->node = node;
 145        publ->ref = port_ref;
 146        publ->key = key;
 147        INIT_LIST_HEAD(&publ->local_list);
 148        INIT_LIST_HEAD(&publ->pport_list);
 149        INIT_LIST_HEAD(&publ->subscr.nodesub_list);
 150        return publ;
 151}
 152
 153/**
 154 * tipc_subseq_alloc - allocate a specified number of sub-sequence structures
 155 */
 156
 157static struct sub_seq *tipc_subseq_alloc(u32 cnt)
 158{
 159        struct sub_seq *sseq = kcalloc(cnt, sizeof(struct sub_seq), GFP_ATOMIC);
 160        return sseq;
 161}
 162
 163/**
 164 * tipc_nameseq_create - create a name sequence structure for the specified 'type'
 165 *
 166 * Allocates a single sub-sequence structure and sets it to all 0's.
 167 */
 168
 169static struct name_seq *tipc_nameseq_create(u32 type, struct hlist_head *seq_head)
 170{
 171        struct name_seq *nseq = kzalloc(sizeof(*nseq), GFP_ATOMIC);
 172        struct sub_seq *sseq = tipc_subseq_alloc(1);
 173
 174        if (!nseq || !sseq) {
 175                warn("Name sequence creation failed, no memory\n");
 176                kfree(nseq);
 177                kfree(sseq);
 178                return NULL;
 179        }
 180
 181        spin_lock_init(&nseq->lock);
 182        nseq->type = type;
 183        nseq->sseqs = sseq;
 184        nseq->alloc = 1;
 185        INIT_HLIST_NODE(&nseq->ns_list);
 186        INIT_LIST_HEAD(&nseq->subscriptions);
 187        hlist_add_head(&nseq->ns_list, seq_head);
 188        return nseq;
 189}
 190
 191/**
 192 * nameseq_find_subseq - find sub-sequence (if any) matching a name instance
 193 *
 194 * Very time-critical, so binary searches through sub-sequence array.
 195 */
 196
 197static struct sub_seq *nameseq_find_subseq(struct name_seq *nseq,
 198                                           u32 instance)
 199{
 200        struct sub_seq *sseqs = nseq->sseqs;
 201        int low = 0;
 202        int high = nseq->first_free - 1;
 203        int mid;
 204
 205        while (low <= high) {
 206                mid = (low + high) / 2;
 207                if (instance < sseqs[mid].lower)
 208                        high = mid - 1;
 209                else if (instance > sseqs[mid].upper)
 210                        low = mid + 1;
 211                else
 212                        return &sseqs[mid];
 213        }
 214        return NULL;
 215}
 216
 217/**
 218 * nameseq_locate_subseq - determine position of name instance in sub-sequence
 219 *
 220 * Returns index in sub-sequence array of the entry that contains the specified
 221 * instance value; if no entry contains that value, returns the position
 222 * where a new entry for it would be inserted in the array.
 223 *
 224 * Note: Similar to binary search code for locating a sub-sequence.
 225 */
 226
 227static u32 nameseq_locate_subseq(struct name_seq *nseq, u32 instance)
 228{
 229        struct sub_seq *sseqs = nseq->sseqs;
 230        int low = 0;
 231        int high = nseq->first_free - 1;
 232        int mid;
 233
 234        while (low <= high) {
 235                mid = (low + high) / 2;
 236                if (instance < sseqs[mid].lower)
 237                        high = mid - 1;
 238                else if (instance > sseqs[mid].upper)
 239                        low = mid + 1;
 240                else
 241                        return mid;
 242        }
 243        return low;
 244}
 245
 246/**
 247 * tipc_nameseq_insert_publ -
 248 */
 249
 250static struct publication *tipc_nameseq_insert_publ(struct name_seq *nseq,
 251                                                    u32 type, u32 lower, u32 upper,
 252                                                    u32 scope, u32 node, u32 port, u32 key)
 253{
 254        struct tipc_subscription *s;
 255        struct tipc_subscription *st;
 256        struct publication *publ;
 257        struct sub_seq *sseq;
 258        struct name_info *info;
 259        int created_subseq = 0;
 260
 261        sseq = nameseq_find_subseq(nseq, lower);
 262        if (sseq) {
 263
 264                /* Lower end overlaps existing entry => need an exact match */
 265
 266                if ((sseq->lower != lower) || (sseq->upper != upper)) {
 267                        warn("Cannot publish {%u,%u,%u}, overlap error\n",
 268                             type, lower, upper);
 269                        return NULL;
 270                }
 271
 272                info = sseq->info;
 273        } else {
 274                u32 inspos;
 275                struct sub_seq *freesseq;
 276
 277                /* Find where lower end should be inserted */
 278
 279                inspos = nameseq_locate_subseq(nseq, lower);
 280
 281                /* Fail if upper end overlaps into an existing entry */
 282
 283                if ((inspos < nseq->first_free) &&
 284                    (upper >= nseq->sseqs[inspos].lower)) {
 285                        warn("Cannot publish {%u,%u,%u}, overlap error\n",
 286                             type, lower, upper);
 287                        return NULL;
 288                }
 289
 290                /* Ensure there is space for new sub-sequence */
 291
 292                if (nseq->first_free == nseq->alloc) {
 293                        struct sub_seq *sseqs = tipc_subseq_alloc(nseq->alloc * 2);
 294
 295                        if (!sseqs) {
 296                                warn("Cannot publish {%u,%u,%u}, no memory\n",
 297                                     type, lower, upper);
 298                                return NULL;
 299                        }
 300                        memcpy(sseqs, nseq->sseqs,
 301                               nseq->alloc * sizeof(struct sub_seq));
 302                        kfree(nseq->sseqs);
 303                        nseq->sseqs = sseqs;
 304                        nseq->alloc *= 2;
 305                }
 306
 307                info = kzalloc(sizeof(*info), GFP_ATOMIC);
 308                if (!info) {
 309                        warn("Cannot publish {%u,%u,%u}, no memory\n",
 310                             type, lower, upper);
 311                        return NULL;
 312                }
 313
 314                INIT_LIST_HEAD(&info->node_list);
 315                INIT_LIST_HEAD(&info->cluster_list);
 316                INIT_LIST_HEAD(&info->zone_list);
 317
 318                /* Insert new sub-sequence */
 319
 320                sseq = &nseq->sseqs[inspos];
 321                freesseq = &nseq->sseqs[nseq->first_free];
 322                memmove(sseq + 1, sseq, (freesseq - sseq) * sizeof(*sseq));
 323                memset(sseq, 0, sizeof(*sseq));
 324                nseq->first_free++;
 325                sseq->lower = lower;
 326                sseq->upper = upper;
 327                sseq->info = info;
 328                created_subseq = 1;
 329        }
 330
 331        /* Insert a publication: */
 332
 333        publ = publ_create(type, lower, upper, scope, node, port, key);
 334        if (!publ)
 335                return NULL;
 336
 337        list_add(&publ->zone_list, &info->zone_list);
 338        info->zone_list_size++;
 339
 340        if (in_own_cluster(node)) {
 341                list_add(&publ->cluster_list, &info->cluster_list);
 342                info->cluster_list_size++;
 343        }
 344
 345        if (node == tipc_own_addr) {
 346                list_add(&publ->node_list, &info->node_list);
 347                info->node_list_size++;
 348        }
 349
 350        /*
 351         * Any subscriptions waiting for notification?
 352         */
 353        list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) {
 354                tipc_subscr_report_overlap(s,
 355                                           publ->lower,
 356                                           publ->upper,
 357                                           TIPC_PUBLISHED,
 358                                           publ->ref,
 359                                           publ->node,
 360                                           created_subseq);
 361        }
 362        return publ;
 363}
 364
 365/**
 366 * tipc_nameseq_remove_publ -
 367 *
 368 * NOTE: There may be cases where TIPC is asked to remove a publication
 369 * that is not in the name table.  For example, if another node issues a
 370 * publication for a name sequence that overlaps an existing name sequence
 371 * the publication will not be recorded, which means the publication won't
 372 * be found when the name sequence is later withdrawn by that node.
 373 * A failed withdraw request simply returns a failure indication and lets the
 374 * caller issue any error or warning messages associated with such a problem.
 375 */
 376
 377static struct publication *tipc_nameseq_remove_publ(struct name_seq *nseq, u32 inst,
 378                                                    u32 node, u32 ref, u32 key)
 379{
 380        struct publication *publ;
 381        struct sub_seq *sseq = nameseq_find_subseq(nseq, inst);
 382        struct name_info *info;
 383        struct sub_seq *free;
 384        struct tipc_subscription *s, *st;
 385        int removed_subseq = 0;
 386
 387        if (!sseq)
 388                return NULL;
 389
 390        info = sseq->info;
 391
 392        /* Locate publication, if it exists */
 393
 394        list_for_each_entry(publ, &info->zone_list, zone_list) {
 395                if ((publ->key == key) && (publ->ref == ref) &&
 396                    (!publ->node || (publ->node == node)))
 397                        goto found;
 398        }
 399        return NULL;
 400
 401found:
 402        /* Remove publication from zone scope list */
 403
 404        list_del(&publ->zone_list);
 405        info->zone_list_size--;
 406
 407        /* Remove publication from cluster scope list, if present */
 408
 409        if (in_own_cluster(node)) {
 410                list_del(&publ->cluster_list);
 411                info->cluster_list_size--;
 412        }
 413
 414        /* Remove publication from node scope list, if present */
 415
 416        if (node == tipc_own_addr) {
 417                list_del(&publ->node_list);
 418                info->node_list_size--;
 419        }
 420
 421        /* Contract subseq list if no more publications for that subseq */
 422
 423        if (list_empty(&info->zone_list)) {
 424                kfree(info);
 425                free = &nseq->sseqs[nseq->first_free--];
 426                memmove(sseq, sseq + 1, (free - (sseq + 1)) * sizeof(*sseq));
 427                removed_subseq = 1;
 428        }
 429
 430        /* Notify any waiting subscriptions */
 431
 432        list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) {
 433                tipc_subscr_report_overlap(s,
 434                                           publ->lower,
 435                                           publ->upper,
 436                                           TIPC_WITHDRAWN,
 437                                           publ->ref,
 438                                           publ->node,
 439                                           removed_subseq);
 440        }
 441
 442        return publ;
 443}
 444
 445/**
 446 * tipc_nameseq_subscribe: attach a subscription, and issue
 447 * the prescribed number of events if there is any sub-
 448 * sequence overlapping with the requested sequence
 449 */
 450
 451static void tipc_nameseq_subscribe(struct name_seq *nseq,
 452                                        struct tipc_subscription *s)
 453{
 454        struct sub_seq *sseq = nseq->sseqs;
 455
 456        list_add(&s->nameseq_list, &nseq->subscriptions);
 457
 458        if (!sseq)
 459                return;
 460
 461        while (sseq != &nseq->sseqs[nseq->first_free]) {
 462                if (tipc_subscr_overlap(s, sseq->lower, sseq->upper)) {
 463                        struct publication *crs;
 464                        struct name_info *info = sseq->info;
 465                        int must_report = 1;
 466
 467                        list_for_each_entry(crs, &info->zone_list, zone_list) {
 468                                tipc_subscr_report_overlap(s,
 469                                                           sseq->lower,
 470                                                           sseq->upper,
 471                                                           TIPC_PUBLISHED,
 472                                                           crs->ref,
 473                                                           crs->node,
 474                                                           must_report);
 475                                must_report = 0;
 476                        }
 477                }
 478                sseq++;
 479        }
 480}
 481
 482static struct name_seq *nametbl_find_seq(u32 type)
 483{
 484        struct hlist_head *seq_head;
 485        struct hlist_node *seq_node;
 486        struct name_seq *ns;
 487
 488        seq_head = &table.types[hash(type)];
 489        hlist_for_each_entry(ns, seq_node, seq_head, ns_list) {
 490                if (ns->type == type)
 491                        return ns;
 492        }
 493
 494        return NULL;
 495};
 496
 497struct publication *tipc_nametbl_insert_publ(u32 type, u32 lower, u32 upper,
 498                                             u32 scope, u32 node, u32 port, u32 key)
 499{
 500        struct name_seq *seq = nametbl_find_seq(type);
 501
 502        if (lower > upper) {
 503                warn("Failed to publish illegal {%u,%u,%u}\n",
 504                     type, lower, upper);
 505                return NULL;
 506        }
 507
 508        if (!seq)
 509                seq = tipc_nameseq_create(type, &table.types[hash(type)]);
 510        if (!seq)
 511                return NULL;
 512
 513        return tipc_nameseq_insert_publ(seq, type, lower, upper,
 514                                        scope, node, port, key);
 515}
 516
 517struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower,
 518                                             u32 node, u32 ref, u32 key)
 519{
 520        struct publication *publ;
 521        struct name_seq *seq = nametbl_find_seq(type);
 522
 523        if (!seq)
 524                return NULL;
 525
 526        publ = tipc_nameseq_remove_publ(seq, lower, node, ref, key);
 527
 528        if (!seq->first_free && list_empty(&seq->subscriptions)) {
 529                hlist_del_init(&seq->ns_list);
 530                kfree(seq->sseqs);
 531                kfree(seq);
 532        }
 533        return publ;
 534}
 535
 536/*
 537 * tipc_nametbl_translate - translate name to port id
 538 *
 539 * Note: on entry 'destnode' is the search domain used during translation;
 540 *       on exit it passes back the node address of the matching port (if any)
 541 */
 542
 543u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *destnode)
 544{
 545        struct sub_seq *sseq;
 546        struct name_info *info;
 547        struct publication *publ;
 548        struct name_seq *seq;
 549        u32 ref = 0;
 550
 551        if (!tipc_in_scope(*destnode, tipc_own_addr))
 552                return 0;
 553
 554        read_lock_bh(&tipc_nametbl_lock);
 555        seq = nametbl_find_seq(type);
 556        if (unlikely(!seq))
 557                goto not_found;
 558        sseq = nameseq_find_subseq(seq, instance);
 559        if (unlikely(!sseq))
 560                goto not_found;
 561        spin_lock_bh(&seq->lock);
 562        info = sseq->info;
 563
 564        /* Closest-First Algorithm: */
 565        if (likely(!*destnode)) {
 566                if (!list_empty(&info->node_list)) {
 567                        publ = list_first_entry(&info->node_list,
 568                                                struct publication,
 569                                                node_list);
 570                        list_move_tail(&publ->node_list,
 571                                       &info->node_list);
 572                } else if (!list_empty(&info->cluster_list)) {
 573                        publ = list_first_entry(&info->cluster_list,
 574                                                struct publication,
 575                                                cluster_list);
 576                        list_move_tail(&publ->cluster_list,
 577                                       &info->cluster_list);
 578                } else {
 579                        publ = list_first_entry(&info->zone_list,
 580                                                struct publication,
 581                                                zone_list);
 582                        list_move_tail(&publ->zone_list,
 583                                       &info->zone_list);
 584                }
 585        }
 586
 587        /* Round-Robin Algorithm: */
 588        else if (*destnode == tipc_own_addr) {
 589                if (list_empty(&info->node_list))
 590                        goto no_match;
 591                publ = list_first_entry(&info->node_list, struct publication,
 592                                        node_list);
 593                list_move_tail(&publ->node_list, &info->node_list);
 594        } else if (in_own_cluster(*destnode)) {
 595                if (list_empty(&info->cluster_list))
 596                        goto no_match;
 597                publ = list_first_entry(&info->cluster_list, struct publication,
 598                                        cluster_list);
 599                list_move_tail(&publ->cluster_list, &info->cluster_list);
 600        } else {
 601                publ = list_first_entry(&info->zone_list, struct publication,
 602                                        zone_list);
 603                list_move_tail(&publ->zone_list, &info->zone_list);
 604        }
 605
 606        ref = publ->ref;
 607        *destnode = publ->node;
 608no_match:
 609        spin_unlock_bh(&seq->lock);
 610not_found:
 611        read_unlock_bh(&tipc_nametbl_lock);
 612        return ref;
 613}
 614
 615/**
 616 * tipc_nametbl_mc_translate - find multicast destinations
 617 *
 618 * Creates list of all local ports that overlap the given multicast address;
 619 * also determines if any off-node ports overlap.
 620 *
 621 * Note: Publications with a scope narrower than 'limit' are ignored.
 622 * (i.e. local node-scope publications mustn't receive messages arriving
 623 * from another node, even if the multcast link brought it here)
 624 *
 625 * Returns non-zero if any off-node ports overlap
 626 */
 627
 628int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit,
 629                              struct tipc_port_list *dports)
 630{
 631        struct name_seq *seq;
 632        struct sub_seq *sseq;
 633        struct sub_seq *sseq_stop;
 634        struct name_info *info;
 635        int res = 0;
 636
 637        read_lock_bh(&tipc_nametbl_lock);
 638        seq = nametbl_find_seq(type);
 639        if (!seq)
 640                goto exit;
 641
 642        spin_lock_bh(&seq->lock);
 643
 644        sseq = seq->sseqs + nameseq_locate_subseq(seq, lower);
 645        sseq_stop = seq->sseqs + seq->first_free;
 646        for (; sseq != sseq_stop; sseq++) {
 647                struct publication *publ;
 648
 649                if (sseq->lower > upper)
 650                        break;
 651
 652                info = sseq->info;
 653                list_for_each_entry(publ, &info->node_list, node_list) {
 654                        if (publ->scope <= limit)
 655                                tipc_port_list_add(dports, publ->ref);
 656                }
 657
 658                if (info->cluster_list_size != info->node_list_size)
 659                        res = 1;
 660        }
 661
 662        spin_unlock_bh(&seq->lock);
 663exit:
 664        read_unlock_bh(&tipc_nametbl_lock);
 665        return res;
 666}
 667
 668/**
 669 * tipc_nametbl_publish_rsv - publish port name using a reserved name type
 670 */
 671
 672int tipc_nametbl_publish_rsv(u32 ref, unsigned int scope,
 673                        struct tipc_name_seq const *seq)
 674{
 675        int res;
 676
 677        atomic_inc(&rsv_publ_ok);
 678        res = tipc_publish(ref, scope, seq);
 679        atomic_dec(&rsv_publ_ok);
 680        return res;
 681}
 682
 683/**
 684 * tipc_nametbl_publish - add name publication to network name tables
 685 */
 686
 687struct publication *tipc_nametbl_publish(u32 type, u32 lower, u32 upper,
 688                                    u32 scope, u32 port_ref, u32 key)
 689{
 690        struct publication *publ;
 691
 692        if (table.local_publ_count >= tipc_max_publications) {
 693                warn("Publication failed, local publication limit reached (%u)\n",
 694                     tipc_max_publications);
 695                return NULL;
 696        }
 697        if ((type < TIPC_RESERVED_TYPES) && !atomic_read(&rsv_publ_ok)) {
 698                warn("Publication failed, reserved name {%u,%u,%u}\n",
 699                     type, lower, upper);
 700                return NULL;
 701        }
 702
 703        write_lock_bh(&tipc_nametbl_lock);
 704        table.local_publ_count++;
 705        publ = tipc_nametbl_insert_publ(type, lower, upper, scope,
 706                                   tipc_own_addr, port_ref, key);
 707        if (publ && (scope != TIPC_NODE_SCOPE))
 708                tipc_named_publish(publ);
 709        write_unlock_bh(&tipc_nametbl_lock);
 710        return publ;
 711}
 712
 713/**
 714 * tipc_nametbl_withdraw - withdraw name publication from network name tables
 715 */
 716
 717int tipc_nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key)
 718{
 719        struct publication *publ;
 720
 721        write_lock_bh(&tipc_nametbl_lock);
 722        publ = tipc_nametbl_remove_publ(type, lower, tipc_own_addr, ref, key);
 723        if (likely(publ)) {
 724                table.local_publ_count--;
 725                if (publ->scope != TIPC_NODE_SCOPE)
 726                        tipc_named_withdraw(publ);
 727                write_unlock_bh(&tipc_nametbl_lock);
 728                list_del_init(&publ->pport_list);
 729                kfree(publ);
 730                return 1;
 731        }
 732        write_unlock_bh(&tipc_nametbl_lock);
 733        err("Unable to remove local publication\n"
 734            "(type=%u, lower=%u, ref=%u, key=%u)\n",
 735            type, lower, ref, key);
 736        return 0;
 737}
 738
 739/**
 740 * tipc_nametbl_subscribe - add a subscription object to the name table
 741 */
 742
 743void tipc_nametbl_subscribe(struct tipc_subscription *s)
 744{
 745        u32 type = s->seq.type;
 746        struct name_seq *seq;
 747
 748        write_lock_bh(&tipc_nametbl_lock);
 749        seq = nametbl_find_seq(type);
 750        if (!seq)
 751                seq = tipc_nameseq_create(type, &table.types[hash(type)]);
 752        if (seq) {
 753                spin_lock_bh(&seq->lock);
 754                tipc_nameseq_subscribe(seq, s);
 755                spin_unlock_bh(&seq->lock);
 756        } else {
 757                warn("Failed to create subscription for {%u,%u,%u}\n",
 758                     s->seq.type, s->seq.lower, s->seq.upper);
 759        }
 760        write_unlock_bh(&tipc_nametbl_lock);
 761}
 762
 763/**
 764 * tipc_nametbl_unsubscribe - remove a subscription object from name table
 765 */
 766
 767void tipc_nametbl_unsubscribe(struct tipc_subscription *s)
 768{
 769        struct name_seq *seq;
 770
 771        write_lock_bh(&tipc_nametbl_lock);
 772        seq = nametbl_find_seq(s->seq.type);
 773        if (seq != NULL) {
 774                spin_lock_bh(&seq->lock);
 775                list_del_init(&s->nameseq_list);
 776                spin_unlock_bh(&seq->lock);
 777                if ((seq->first_free == 0) && list_empty(&seq->subscriptions)) {
 778                        hlist_del_init(&seq->ns_list);
 779                        kfree(seq->sseqs);
 780                        kfree(seq);
 781                }
 782        }
 783        write_unlock_bh(&tipc_nametbl_lock);
 784}
 785
 786
 787/**
 788 * subseq_list: print specified sub-sequence contents into the given buffer
 789 */
 790
 791static void subseq_list(struct sub_seq *sseq, struct print_buf *buf, u32 depth,
 792                        u32 index)
 793{
 794        char portIdStr[27];
 795        const char *scope_str[] = {"", " zone", " cluster", " node"};
 796        struct publication *publ;
 797        struct name_info *info;
 798
 799        tipc_printf(buf, "%-10u %-10u ", sseq->lower, sseq->upper);
 800
 801        if (depth == 2) {
 802                tipc_printf(buf, "\n");
 803                return;
 804        }
 805
 806        info = sseq->info;
 807
 808        list_for_each_entry(publ, &info->zone_list, zone_list) {
 809                sprintf(portIdStr, "<%u.%u.%u:%u>",
 810                         tipc_zone(publ->node), tipc_cluster(publ->node),
 811                         tipc_node(publ->node), publ->ref);
 812                tipc_printf(buf, "%-26s ", portIdStr);
 813                if (depth > 3) {
 814                        tipc_printf(buf, "%-10u %s", publ->key,
 815                                    scope_str[publ->scope]);
 816                }
 817                if (!list_is_last(&publ->zone_list, &info->zone_list))
 818                        tipc_printf(buf, "\n%33s", " ");
 819        };
 820
 821        tipc_printf(buf, "\n");
 822}
 823
 824/**
 825 * nameseq_list: print specified name sequence contents into the given buffer
 826 */
 827
 828static void nameseq_list(struct name_seq *seq, struct print_buf *buf, u32 depth,
 829                         u32 type, u32 lowbound, u32 upbound, u32 index)
 830{
 831        struct sub_seq *sseq;
 832        char typearea[11];
 833
 834        if (seq->first_free == 0)
 835                return;
 836
 837        sprintf(typearea, "%-10u", seq->type);
 838
 839        if (depth == 1) {
 840                tipc_printf(buf, "%s\n", typearea);
 841                return;
 842        }
 843
 844        for (sseq = seq->sseqs; sseq != &seq->sseqs[seq->first_free]; sseq++) {
 845                if ((lowbound <= sseq->upper) && (upbound >= sseq->lower)) {
 846                        tipc_printf(buf, "%s ", typearea);
 847                        spin_lock_bh(&seq->lock);
 848                        subseq_list(sseq, buf, depth, index);
 849                        spin_unlock_bh(&seq->lock);
 850                        sprintf(typearea, "%10s", " ");
 851                }
 852        }
 853}
 854
 855/**
 856 * nametbl_header - print name table header into the given buffer
 857 */
 858
 859static void nametbl_header(struct print_buf *buf, u32 depth)
 860{
 861        const char *header[] = {
 862                "Type       ",
 863                "Lower      Upper      ",
 864                "Port Identity              ",
 865                "Publication Scope"
 866        };
 867
 868        int i;
 869
 870        if (depth > 4)
 871                depth = 4;
 872        for (i = 0; i < depth; i++)
 873                tipc_printf(buf, header[i]);
 874        tipc_printf(buf, "\n");
 875}
 876
 877/**
 878 * nametbl_list - print specified name table contents into the given buffer
 879 */
 880
 881static void nametbl_list(struct print_buf *buf, u32 depth_info,
 882                         u32 type, u32 lowbound, u32 upbound)
 883{
 884        struct hlist_head *seq_head;
 885        struct hlist_node *seq_node;
 886        struct name_seq *seq;
 887        int all_types;
 888        u32 depth;
 889        u32 i;
 890
 891        all_types = (depth_info & TIPC_NTQ_ALLTYPES);
 892        depth = (depth_info & ~TIPC_NTQ_ALLTYPES);
 893
 894        if (depth == 0)
 895                return;
 896
 897        if (all_types) {
 898                /* display all entries in name table to specified depth */
 899                nametbl_header(buf, depth);
 900                lowbound = 0;
 901                upbound = ~0;
 902                for (i = 0; i < tipc_nametbl_size; i++) {
 903                        seq_head = &table.types[i];
 904                        hlist_for_each_entry(seq, seq_node, seq_head, ns_list) {
 905                                nameseq_list(seq, buf, depth, seq->type,
 906                                             lowbound, upbound, i);
 907                        }
 908                }
 909        } else {
 910                /* display only the sequence that matches the specified type */
 911                if (upbound < lowbound) {
 912                        tipc_printf(buf, "invalid name sequence specified\n");
 913                        return;
 914                }
 915                nametbl_header(buf, depth);
 916                i = hash(type);
 917                seq_head = &table.types[i];
 918                hlist_for_each_entry(seq, seq_node, seq_head, ns_list) {
 919                        if (seq->type == type) {
 920                                nameseq_list(seq, buf, depth, type,
 921                                             lowbound, upbound, i);
 922                                break;
 923                        }
 924                }
 925        }
 926}
 927
 928#define MAX_NAME_TBL_QUERY 32768
 929
 930struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space)
 931{
 932        struct sk_buff *buf;
 933        struct tipc_name_table_query *argv;
 934        struct tlv_desc *rep_tlv;
 935        struct print_buf b;
 936        int str_len;
 937
 938        if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NAME_TBL_QUERY))
 939                return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR);
 940
 941        buf = tipc_cfg_reply_alloc(TLV_SPACE(MAX_NAME_TBL_QUERY));
 942        if (!buf)
 943                return NULL;
 944
 945        rep_tlv = (struct tlv_desc *)buf->data;
 946        tipc_printbuf_init(&b, TLV_DATA(rep_tlv), MAX_NAME_TBL_QUERY);
 947        argv = (struct tipc_name_table_query *)TLV_DATA(req_tlv_area);
 948        read_lock_bh(&tipc_nametbl_lock);
 949        nametbl_list(&b, ntohl(argv->depth), ntohl(argv->type),
 950                     ntohl(argv->lowbound), ntohl(argv->upbound));
 951        read_unlock_bh(&tipc_nametbl_lock);
 952        str_len = tipc_printbuf_validate(&b);
 953
 954        skb_put(buf, TLV_SPACE(str_len));
 955        TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len);
 956
 957        return buf;
 958}
 959
 960int tipc_nametbl_init(void)
 961{
 962        table.types = kcalloc(tipc_nametbl_size, sizeof(struct hlist_head),
 963                              GFP_ATOMIC);
 964        if (!table.types)
 965                return -ENOMEM;
 966
 967        table.local_publ_count = 0;
 968        return 0;
 969}
 970
 971void tipc_nametbl_stop(void)
 972{
 973        u32 i;
 974
 975        if (!table.types)
 976                return;
 977
 978        /* Verify name table is empty, then release it */
 979
 980        write_lock_bh(&tipc_nametbl_lock);
 981        for (i = 0; i < tipc_nametbl_size; i++) {
 982                if (!hlist_empty(&table.types[i]))
 983                        err("tipc_nametbl_stop(): hash chain %u is non-null\n", i);
 984        }
 985        kfree(table.types);
 986        table.types = NULL;
 987        write_unlock_bh(&tipc_nametbl_lock);
 988}
 989
 990