1 /* 2 * net/tipc/name_table.c: TIPC name table code 3 * 4 * Copyright (c) 2003-2005, Ericsson Research Canada 5 * Copyright (c) 2004-2005, Wind River Systems 6 * Copyright (c) 2005-2006, Ericsson AB 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. Neither the names of the copyright holders nor the names of its 18 * contributors may be used to endorse or promote products derived from 19 * this software without specific prior written permission. 20 * 21 * Alternatively, this software may be distributed under the terms of the 22 * GNU General Public License ("GPL") version 2 as published by the Free 23 * Software Foundation. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 26 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 29 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38 #include "core.h" 39 #include "config.h" 40 #include "dbg.h" 41 #include "name_table.h" 42 #include "name_distr.h" 43 #include "addr.h" 44 #include "node_subscr.h" 45 #include "subscr.h" 46 #include "port.h" 47 #include "cluster.h" 48 #include "bcast.h" 49 50 int tipc_nametbl_size = 1024; /* must be a power of 2 */ 51 52 /** 53 * struct sub_seq - container for all published instances of a name sequence 54 * @lower: name sequence lower bound 55 * @upper: name sequence upper bound 56 * @node_list: circular list of matching publications with >= node scope 57 * @cluster_list: circular list of matching publications with >= cluster scope 58 * @zone_list: circular list of matching publications with >= zone scope 59 */ 60 61 struct sub_seq { 62 u32 lower; 63 u32 upper; 64 struct publication *node_list; 65 struct publication *cluster_list; 66 struct publication *zone_list; 67 }; 68 69 /** 70 * struct name_seq - container for all published instances of a name type 71 * @type: 32 bit 'type' value for name sequence 72 * @sseq: pointer to dynamically-sized array of sub-sequences of this 'type'; 73 * sub-sequences are sorted in ascending order 74 * @alloc: number of sub-sequences currently in array 75 * @first_free: upper bound of highest sub-sequence + 1 76 * @ns_list: links to adjacent name sequences in hash chain 77 * @subscriptions: list of subscriptions for this 'type' 78 * @lock: spinlock controlling access to name sequence structure 79 */ 80 81 struct name_seq { 82 u32 type; 83 struct sub_seq *sseqs; 84 u32 alloc; 85 u32 first_free; 86 struct hlist_node ns_list; 87 struct list_head subscriptions; 88 spinlock_t lock; 89 }; 90 91 /** 92 * struct name_table - table containing all existing port name publications 93 * @types: pointer to fixed-sized array of name sequence lists, 94 * accessed via hashing on 'type'; name sequence lists are *not* sorted 95 * @local_publ_count: number of publications issued by this node 96 */ 97 98 struct name_table { 99 struct hlist_head *types; 100 u32 local_publ_count; 101 }; 102 103 struct name_table table = { NULL } ; 104 static atomic_t rsv_publ_ok = ATOMIC_INIT(0); 105 rwlock_t nametbl_lock = RW_LOCK_UNLOCKED; 106 107 108 static inline int hash(int x) 109 { 110 return(x & (tipc_nametbl_size - 1)); 111 } 112 113 /** 114 * publ_create - create a publication structure 115 */ 116 117 static struct publication *publ_create(u32 type, u32 lower, u32 upper, 118 u32 scope, u32 node, u32 port_ref, 119 u32 key) 120 { 121 struct publication *publ = 122 (struct publication *)kmalloc(sizeof(*publ), GFP_ATOMIC); 123 if (publ == NULL) { 124 warn("Memory squeeze; failed to create publication\n"); 125 return 0; 126 } 127 128 memset(publ, 0, sizeof(*publ)); 129 publ->type = type; 130 publ->lower = lower; 131 publ->upper = upper; 132 publ->scope = scope; 133 publ->node = node; 134 publ->ref = port_ref; 135 publ->key = key; 136 INIT_LIST_HEAD(&publ->local_list); 137 INIT_LIST_HEAD(&publ->pport_list); 138 INIT_LIST_HEAD(&publ->subscr.nodesub_list); 139 return publ; 140 } 141 142 /** 143 * subseq_alloc - allocate a specified number of sub-sequence structures 144 */ 145 146 struct sub_seq *subseq_alloc(u32 cnt) 147 { 148 u32 sz = cnt * sizeof(struct sub_seq); 149 struct sub_seq *sseq = (struct sub_seq *)kmalloc(sz, GFP_ATOMIC); 150 151 if (sseq) 152 memset(sseq, 0, sz); 153 return sseq; 154 } 155 156 /** 157 * nameseq_create - create a name sequence structure for the specified 'type' 158 * 159 * Allocates a single sub-sequence structure and sets it to all 0's. 160 */ 161 162 struct name_seq *nameseq_create(u32 type, struct hlist_head *seq_head) 163 { 164 struct name_seq *nseq = 165 (struct name_seq *)kmalloc(sizeof(*nseq), GFP_ATOMIC); 166 struct sub_seq *sseq = subseq_alloc(1); 167 168 if (!nseq || !sseq) { 169 warn("Memory squeeze; failed to create name sequence\n"); 170 kfree(nseq); 171 kfree(sseq); 172 return 0; 173 } 174 175 memset(nseq, 0, sizeof(*nseq)); 176 nseq->lock = SPIN_LOCK_UNLOCKED; 177 nseq->type = type; 178 nseq->sseqs = sseq; 179 dbg("nameseq_create() nseq = %x type %u, ssseqs %x, ff: %u\n", 180 nseq, type, nseq->sseqs, nseq->first_free); 181 nseq->alloc = 1; 182 INIT_HLIST_NODE(&nseq->ns_list); 183 INIT_LIST_HEAD(&nseq->subscriptions); 184 hlist_add_head(&nseq->ns_list, seq_head); 185 return nseq; 186 } 187 188 /** 189 * nameseq_find_subseq - find sub-sequence (if any) matching a name instance 190 * 191 * Very time-critical, so binary searches through sub-sequence array. 192 */ 193 194 static inline struct sub_seq *nameseq_find_subseq(struct name_seq *nseq, 195 u32 instance) 196 { 197 struct sub_seq *sseqs = nseq->sseqs; 198 int low = 0; 199 int high = nseq->first_free - 1; 200 int mid; 201 202 while (low <= high) { 203 mid = (low + high) / 2; 204 if (instance < sseqs[mid].lower) 205 high = mid - 1; 206 else if (instance > sseqs[mid].upper) 207 low = mid + 1; 208 else 209 return &sseqs[mid]; 210 } 211 return 0; 212 } 213 214 /** 215 * nameseq_locate_subseq - determine position of name instance in sub-sequence 216 * 217 * Returns index in sub-sequence array of the entry that contains the specified 218 * instance value; if no entry contains that value, returns the position 219 * where a new entry for it would be inserted in the array. 220 * 221 * Note: Similar to binary search code for locating a sub-sequence. 222 */ 223 224 static u32 nameseq_locate_subseq(struct name_seq *nseq, u32 instance) 225 { 226 struct sub_seq *sseqs = nseq->sseqs; 227 int low = 0; 228 int high = nseq->first_free - 1; 229 int mid; 230 231 while (low <= high) { 232 mid = (low + high) / 2; 233 if (instance < sseqs[mid].lower) 234 high = mid - 1; 235 else if (instance > sseqs[mid].upper) 236 low = mid + 1; 237 else 238 return mid; 239 } 240 return low; 241 } 242 243 /** 244 * nameseq_insert_publ - 245 */ 246 247 struct publication *nameseq_insert_publ(struct name_seq *nseq, 248 u32 type, u32 lower, u32 upper, 249 u32 scope, u32 node, u32 port, u32 key) 250 { 251 struct subscription *s; 252 struct subscription *st; 253 struct publication *publ; 254 struct sub_seq *sseq; 255 int created_subseq = 0; 256 257 assert(nseq->first_free <= nseq->alloc); 258 sseq = nameseq_find_subseq(nseq, lower); 259 dbg("nameseq_ins: for seq %x,<%u,%u>, found sseq %x\n", 260 nseq, type, lower, sseq); 261 if (sseq) { 262 263 /* Lower end overlaps existing entry => need an exact match */ 264 265 if ((sseq->lower != lower) || (sseq->upper != upper)) { 266 warn("Overlapping publ <%u,%u,%u>\n", type, lower, upper); 267 return 0; 268 } 269 } else { 270 u32 inspos; 271 struct sub_seq *freesseq; 272 273 /* Find where lower end should be inserted */ 274 275 inspos = nameseq_locate_subseq(nseq, lower); 276 277 /* Fail if upper end overlaps into an existing entry */ 278 279 if ((inspos < nseq->first_free) && 280 (upper >= nseq->sseqs[inspos].lower)) { 281 warn("Overlapping publ <%u,%u,%u>\n", type, lower, upper); 282 return 0; 283 } 284 285 /* Ensure there is space for new sub-sequence */ 286 287 if (nseq->first_free == nseq->alloc) { 288 struct sub_seq *sseqs = nseq->sseqs; 289 nseq->sseqs = subseq_alloc(nseq->alloc * 2); 290 if (nseq->sseqs != NULL) { 291 memcpy(nseq->sseqs, sseqs, 292 nseq->alloc * sizeof (struct sub_seq)); 293 kfree(sseqs); 294 dbg("Allocated %u sseqs\n", nseq->alloc); 295 nseq->alloc *= 2; 296 } else { 297 warn("Memory squeeze; failed to create sub-sequence\n"); 298 return 0; 299 } 300 } 301 dbg("Have %u sseqs for type %u\n", nseq->alloc, type); 302 303 /* Insert new sub-sequence */ 304 305 dbg("ins in pos %u, ff = %u\n", inspos, nseq->first_free); 306 sseq = &nseq->sseqs[inspos]; 307 freesseq = &nseq->sseqs[nseq->first_free]; 308 memmove(sseq + 1, sseq, (freesseq - sseq) * sizeof (*sseq)); 309 memset(sseq, 0, sizeof (*sseq)); 310 nseq->first_free++; 311 sseq->lower = lower; 312 sseq->upper = upper; 313 created_subseq = 1; 314 } 315 dbg("inserting (%u %u %u) from %x:%u into sseq %x(%u,%u) of seq %x\n", 316 type, lower, upper, node, port, sseq, 317 sseq->lower, sseq->upper, nseq); 318 319 /* Insert a publication: */ 320 321 publ = publ_create(type, lower, upper, scope, node, port, key); 322 if (!publ) 323 return 0; 324 dbg("inserting publ %x, node=%x publ->node=%x, subscr->node=%x\n", 325 publ, node, publ->node, publ->subscr.node); 326 327 if (!sseq->zone_list) 328 sseq->zone_list = publ->zone_list_next = publ; 329 else { 330 publ->zone_list_next = sseq->zone_list->zone_list_next; 331 sseq->zone_list->zone_list_next = publ; 332 } 333 334 if (in_own_cluster(node)) { 335 if (!sseq->cluster_list) 336 sseq->cluster_list = publ->cluster_list_next = publ; 337 else { 338 publ->cluster_list_next = 339 sseq->cluster_list->cluster_list_next; 340 sseq->cluster_list->cluster_list_next = publ; 341 } 342 } 343 344 if (node == tipc_own_addr) { 345 if (!sseq->node_list) 346 sseq->node_list = publ->node_list_next = publ; 347 else { 348 publ->node_list_next = sseq->node_list->node_list_next; 349 sseq->node_list->node_list_next = publ; 350 } 351 } 352 353 /* 354 * Any subscriptions waiting for notification? 355 */ 356 list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) { 357 dbg("calling report_overlap()\n"); 358 subscr_report_overlap(s, 359 publ->lower, 360 publ->upper, 361 TIPC_PUBLISHED, 362 publ->ref, 363 publ->node, 364 created_subseq); 365 } 366 return publ; 367 } 368 369 /** 370 * nameseq_remove_publ - 371 */ 372 373 struct publication *nameseq_remove_publ(struct name_seq *nseq, u32 inst, 374 u32 node, u32 ref, u32 key) 375 { 376 struct publication *publ; 377 struct publication *prev; 378 struct sub_seq *sseq = nameseq_find_subseq(nseq, inst); 379 struct sub_seq *free; 380 struct subscription *s, *st; 381 int removed_subseq = 0; 382 383 assert(nseq); 384 385 if (!sseq) { 386 int i; 387 388 warn("Withdraw unknown <%u,%u>?\n", nseq->type, inst); 389 assert(nseq->sseqs); 390 dbg("Dumping subseqs %x for %x, alloc = %u,ff=%u\n", 391 nseq->sseqs, nseq, nseq->alloc, 392 nseq->first_free); 393 for (i = 0; i < nseq->first_free; i++) { 394 dbg("Subseq %u(%x): lower = %u,upper = %u\n", 395 i, &nseq->sseqs[i], nseq->sseqs[i].lower, 396 nseq->sseqs[i].upper); 397 } 398 return 0; 399 } 400 dbg("nameseq_remove: seq: %x, sseq %x, <%u,%u> key %u\n", 401 nseq, sseq, nseq->type, inst, key); 402 403 prev = sseq->zone_list; 404 publ = sseq->zone_list->zone_list_next; 405 while ((publ->key != key) || (publ->ref != ref) || 406 (publ->node && (publ->node != node))) { 407 prev = publ; 408 publ = publ->zone_list_next; 409 assert(prev != sseq->zone_list); 410 } 411 if (publ != sseq->zone_list) 412 prev->zone_list_next = publ->zone_list_next; 413 else if (publ->zone_list_next != publ) { 414 prev->zone_list_next = publ->zone_list_next; 415 sseq->zone_list = publ->zone_list_next; 416 } else { 417 sseq->zone_list = 0; 418 } 419 420 if (in_own_cluster(node)) { 421 prev = sseq->cluster_list; 422 publ = sseq->cluster_list->cluster_list_next; 423 while ((publ->key != key) || (publ->ref != ref) || 424 (publ->node && (publ->node != node))) { 425 prev = publ; 426 publ = publ->cluster_list_next; 427 assert(prev != sseq->cluster_list); 428 } 429 if (publ != sseq->cluster_list) 430 prev->cluster_list_next = publ->cluster_list_next; 431 else if (publ->cluster_list_next != publ) { 432 prev->cluster_list_next = publ->cluster_list_next; 433 sseq->cluster_list = publ->cluster_list_next; 434 } else { 435 sseq->cluster_list = 0; 436 } 437 } 438 439 if (node == tipc_own_addr) { 440 prev = sseq->node_list; 441 publ = sseq->node_list->node_list_next; 442 while ((publ->key != key) || (publ->ref != ref) || 443 (publ->node && (publ->node != node))) { 444 prev = publ; 445 publ = publ->node_list_next; 446 assert(prev != sseq->node_list); 447 } 448 if (publ != sseq->node_list) 449 prev->node_list_next = publ->node_list_next; 450 else if (publ->node_list_next != publ) { 451 prev->node_list_next = publ->node_list_next; 452 sseq->node_list = publ->node_list_next; 453 } else { 454 sseq->node_list = 0; 455 } 456 } 457 assert(!publ->node || (publ->node == node)); 458 assert(publ->ref == ref); 459 assert(publ->key == key); 460 461 /* 462 * Contract subseq list if no more publications: 463 */ 464 if (!sseq->node_list && !sseq->cluster_list && !sseq->zone_list) { 465 free = &nseq->sseqs[nseq->first_free--]; 466 memmove(sseq, sseq + 1, (free - (sseq + 1)) * sizeof (*sseq)); 467 removed_subseq = 1; 468 } 469 470 /* 471 * Any subscriptions waiting ? 472 */ 473 list_for_each_entry_safe(s, st, &nseq->subscriptions, nameseq_list) { 474 subscr_report_overlap(s, 475 publ->lower, 476 publ->upper, 477 TIPC_WITHDRAWN, 478 publ->ref, 479 publ->node, 480 removed_subseq); 481 } 482 return publ; 483 } 484 485 /** 486 * nameseq_subscribe: attach a subscription, and issue 487 * the prescribed number of events if there is any sub- 488 * sequence overlapping with the requested sequence 489 */ 490 491 void nameseq_subscribe(struct name_seq *nseq, struct subscription *s) 492 { 493 struct sub_seq *sseq = nseq->sseqs; 494 495 list_add(&s->nameseq_list, &nseq->subscriptions); 496 497 if (!sseq) 498 return; 499 500 while (sseq != &nseq->sseqs[nseq->first_free]) { 501 struct publication *zl = sseq->zone_list; 502 if (zl && subscr_overlap(s,sseq->lower,sseq->upper)) { 503 struct publication *crs = zl; 504 int must_report = 1; 505 506 do { 507 subscr_report_overlap(s, 508 sseq->lower, 509 sseq->upper, 510 TIPC_PUBLISHED, 511 crs->ref, 512 crs->node, 513 must_report); 514 must_report = 0; 515 crs = crs->zone_list_next; 516 } while (crs != zl); 517 } 518 sseq++; 519 } 520 } 521 522 static struct name_seq *nametbl_find_seq(u32 type) 523 { 524 struct hlist_head *seq_head; 525 struct hlist_node *seq_node; 526 struct name_seq *ns; 527 528 dbg("find_seq %u,(%u,0x%x) table = %p, hash[type] = %u\n", 529 type, ntohl(type), type, table.types, hash(type)); 530 531 seq_head = &table.types[hash(type)]; 532 hlist_for_each_entry(ns, seq_node, seq_head, ns_list) { 533 if (ns->type == type) { 534 dbg("found %x\n", ns); 535 return ns; 536 } 537 } 538 539 return 0; 540 }; 541 542 struct publication *nametbl_insert_publ(u32 type, u32 lower, u32 upper, 543 u32 scope, u32 node, u32 port, u32 key) 544 { 545 struct name_seq *seq = nametbl_find_seq(type); 546 547 dbg("ins_publ: <%u,%x,%x> found %x\n", type, lower, upper, seq); 548 if (lower > upper) { 549 warn("Failed to publish illegal <%u,%u,%u>\n", 550 type, lower, upper); 551 return 0; 552 } 553 554 dbg("Publishing <%u,%u,%u> from %x\n", type, lower, upper, node); 555 if (!seq) { 556 seq = nameseq_create(type, &table.types[hash(type)]); 557 dbg("nametbl_insert_publ: created %x\n", seq); 558 } 559 if (!seq) 560 return 0; 561 562 assert(seq->type == type); 563 return nameseq_insert_publ(seq, type, lower, upper, 564 scope, node, port, key); 565 } 566 567 struct publication *nametbl_remove_publ(u32 type, u32 lower, 568 u32 node, u32 ref, u32 key) 569 { 570 struct publication *publ; 571 struct name_seq *seq = nametbl_find_seq(type); 572 573 if (!seq) 574 return 0; 575 576 dbg("Withdrawing <%u,%u> from %x\n", type, lower, node); 577 publ = nameseq_remove_publ(seq, lower, node, ref, key); 578 579 if (!seq->first_free && list_empty(&seq->subscriptions)) { 580 hlist_del_init(&seq->ns_list); 581 kfree(seq->sseqs); 582 kfree(seq); 583 } 584 return publ; 585 } 586 587 /* 588 * nametbl_translate(): Translate tipc_name -> tipc_portid. 589 * Very time-critical. 590 * 591 * Note: on entry 'destnode' is the search domain used during translation; 592 * on exit it passes back the node address of the matching port (if any) 593 */ 594 595 u32 nametbl_translate(u32 type, u32 instance, u32 *destnode) 596 { 597 struct sub_seq *sseq; 598 struct publication *publ = 0; 599 struct name_seq *seq; 600 u32 ref; 601 602 if (!in_scope(*destnode, tipc_own_addr)) 603 return 0; 604 605 read_lock_bh(&nametbl_lock); 606 seq = nametbl_find_seq(type); 607 if (unlikely(!seq)) 608 goto not_found; 609 sseq = nameseq_find_subseq(seq, instance); 610 if (unlikely(!sseq)) 611 goto not_found; 612 spin_lock_bh(&seq->lock); 613 614 /* Closest-First Algorithm: */ 615 if (likely(!*destnode)) { 616 publ = sseq->node_list; 617 if (publ) { 618 sseq->node_list = publ->node_list_next; 619 found: 620 ref = publ->ref; 621 *destnode = publ->node; 622 spin_unlock_bh(&seq->lock); 623 read_unlock_bh(&nametbl_lock); 624 return ref; 625 } 626 publ = sseq->cluster_list; 627 if (publ) { 628 sseq->cluster_list = publ->cluster_list_next; 629 goto found; 630 } 631 publ = sseq->zone_list; 632 if (publ) { 633 sseq->zone_list = publ->zone_list_next; 634 goto found; 635 } 636 } 637 638 /* Round-Robin Algorithm: */ 639 else if (*destnode == tipc_own_addr) { 640 publ = sseq->node_list; 641 if (publ) { 642 sseq->node_list = publ->node_list_next; 643 goto found; 644 } 645 } else if (in_own_cluster(*destnode)) { 646 publ = sseq->cluster_list; 647 if (publ) { 648 sseq->cluster_list = publ->cluster_list_next; 649 goto found; 650 } 651 } else { 652 publ = sseq->zone_list; 653 if (publ) { 654 sseq->zone_list = publ->zone_list_next; 655 goto found; 656 } 657 } 658 spin_unlock_bh(&seq->lock); 659 not_found: 660 *destnode = 0; 661 read_unlock_bh(&nametbl_lock); 662 return 0; 663 } 664 665 /** 666 * nametbl_mc_translate - find multicast destinations 667 * 668 * Creates list of all local ports that overlap the given multicast address; 669 * also determines if any off-node ports overlap. 670 * 671 * Note: Publications with a scope narrower than 'limit' are ignored. 672 * (i.e. local node-scope publications mustn't receive messages arriving 673 * from another node, even if the multcast link brought it here) 674 * 675 * Returns non-zero if any off-node ports overlap 676 */ 677 678 int nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit, 679 struct port_list *dports) 680 { 681 struct name_seq *seq; 682 struct sub_seq *sseq; 683 struct sub_seq *sseq_stop; 684 int res = 0; 685 686 read_lock_bh(&nametbl_lock); 687 seq = nametbl_find_seq(type); 688 if (!seq) 689 goto exit; 690 691 spin_lock_bh(&seq->lock); 692 693 sseq = seq->sseqs + nameseq_locate_subseq(seq, lower); 694 sseq_stop = seq->sseqs + seq->first_free; 695 for (; sseq != sseq_stop; sseq++) { 696 struct publication *publ; 697 698 if (sseq->lower > upper) 699 break; 700 publ = sseq->cluster_list; 701 if (publ && (publ->scope <= limit)) 702 do { 703 if (publ->node == tipc_own_addr) 704 port_list_add(dports, publ->ref); 705 else 706 res = 1; 707 publ = publ->cluster_list_next; 708 } while (publ != sseq->cluster_list); 709 } 710 711 spin_unlock_bh(&seq->lock); 712 exit: 713 read_unlock_bh(&nametbl_lock); 714 return res; 715 } 716 717 /** 718 * nametbl_publish_rsv - publish port name using a reserved name type 719 */ 720 721 int nametbl_publish_rsv(u32 ref, unsigned int scope, 722 struct tipc_name_seq const *seq) 723 { 724 int res; 725 726 atomic_inc(&rsv_publ_ok); 727 res = tipc_publish(ref, scope, seq); 728 atomic_dec(&rsv_publ_ok); 729 return res; 730 } 731 732 /** 733 * nametbl_publish - add name publication to network name tables 734 */ 735 736 struct publication *nametbl_publish(u32 type, u32 lower, u32 upper, 737 u32 scope, u32 port_ref, u32 key) 738 { 739 struct publication *publ; 740 741 if (table.local_publ_count >= tipc_max_publications) { 742 warn("Failed publish: max %u local publication\n", 743 tipc_max_publications); 744 return 0; 745 } 746 if ((type < TIPC_RESERVED_TYPES) && !atomic_read(&rsv_publ_ok)) { 747 warn("Failed to publish reserved name <%u,%u,%u>\n", 748 type, lower, upper); 749 return 0; 750 } 751 752 write_lock_bh(&nametbl_lock); 753 table.local_publ_count++; 754 publ = nametbl_insert_publ(type, lower, upper, scope, 755 tipc_own_addr, port_ref, key); 756 if (publ && (scope != TIPC_NODE_SCOPE)) { 757 named_publish(publ); 758 } 759 write_unlock_bh(&nametbl_lock); 760 return publ; 761 } 762 763 /** 764 * nametbl_withdraw - withdraw name publication from network name tables 765 */ 766 767 int nametbl_withdraw(u32 type, u32 lower, u32 ref, u32 key) 768 { 769 struct publication *publ; 770 771 dbg("nametbl_withdraw:<%d,%d,%d>\n", type, lower, key); 772 write_lock_bh(&nametbl_lock); 773 publ = nametbl_remove_publ(type, lower, tipc_own_addr, ref, key); 774 if (publ) { 775 table.local_publ_count--; 776 if (publ->scope != TIPC_NODE_SCOPE) 777 named_withdraw(publ); 778 write_unlock_bh(&nametbl_lock); 779 list_del_init(&publ->pport_list); 780 kfree(publ); 781 return 1; 782 } 783 write_unlock_bh(&nametbl_lock); 784 return 0; 785 } 786 787 /** 788 * nametbl_subscribe - add a subscription object to the name table 789 */ 790 791 void 792 nametbl_subscribe(struct subscription *s) 793 { 794 u32 type = s->seq.type; 795 struct name_seq *seq; 796 797 write_lock_bh(&nametbl_lock); 798 seq = nametbl_find_seq(type); 799 if (!seq) { 800 seq = nameseq_create(type, &table.types[hash(type)]); 801 } 802 if (seq){ 803 spin_lock_bh(&seq->lock); 804 dbg("nametbl_subscribe:found %x for <%u,%u,%u>\n", 805 seq, type, s->seq.lower, s->seq.upper); 806 assert(seq->type == type); 807 nameseq_subscribe(seq, s); 808 spin_unlock_bh(&seq->lock); 809 } 810 write_unlock_bh(&nametbl_lock); 811 } 812 813 /** 814 * nametbl_unsubscribe - remove a subscription object from name table 815 */ 816 817 void 818 nametbl_unsubscribe(struct subscription *s) 819 { 820 struct name_seq *seq; 821 822 write_lock_bh(&nametbl_lock); 823 seq = nametbl_find_seq(s->seq.type); 824 if (seq != NULL){ 825 spin_lock_bh(&seq->lock); 826 list_del_init(&s->nameseq_list); 827 spin_unlock_bh(&seq->lock); 828 if ((seq->first_free == 0) && list_empty(&seq->subscriptions)) { 829 hlist_del_init(&seq->ns_list); 830 kfree(seq->sseqs); 831 kfree(seq); 832 } 833 } 834 write_unlock_bh(&nametbl_lock); 835 } 836 837 838 /** 839 * subseq_list: print specified sub-sequence contents into the given buffer 840 */ 841 842 static void subseq_list(struct sub_seq *sseq, struct print_buf *buf, u32 depth, 843 u32 index) 844 { 845 char portIdStr[27]; 846 char *scopeStr; 847 struct publication *publ = sseq->zone_list; 848 849 tipc_printf(buf, "%-10u %-10u ", sseq->lower, sseq->upper); 850 851 if (depth == 2 || !publ) { 852 tipc_printf(buf, "\n"); 853 return; 854 } 855 856 do { 857 sprintf (portIdStr, "<%u.%u.%u:%u>", 858 tipc_zone(publ->node), tipc_cluster(publ->node), 859 tipc_node(publ->node), publ->ref); 860 tipc_printf(buf, "%-26s ", portIdStr); 861 if (depth > 3) { 862 if (publ->node != tipc_own_addr) 863 scopeStr = ""; 864 else if (publ->scope == TIPC_NODE_SCOPE) 865 scopeStr = "node"; 866 else if (publ->scope == TIPC_CLUSTER_SCOPE) 867 scopeStr = "cluster"; 868 else 869 scopeStr = "zone"; 870 tipc_printf(buf, "%-10u %s", publ->key, scopeStr); 871 } 872 873 publ = publ->zone_list_next; 874 if (publ == sseq->zone_list) 875 break; 876 877 tipc_printf(buf, "\n%33s", " "); 878 } while (1); 879 880 tipc_printf(buf, "\n"); 881 } 882 883 /** 884 * nameseq_list: print specified name sequence contents into the given buffer 885 */ 886 887 static void nameseq_list(struct name_seq *seq, struct print_buf *buf, u32 depth, 888 u32 type, u32 lowbound, u32 upbound, u32 index) 889 { 890 struct sub_seq *sseq; 891 char typearea[11]; 892 893 sprintf(typearea, "%-10u", seq->type); 894 895 if (depth == 1) { 896 tipc_printf(buf, "%s\n", typearea); 897 return; 898 } 899 900 for (sseq = seq->sseqs; sseq != &seq->sseqs[seq->first_free]; sseq++) { 901 if ((lowbound <= sseq->upper) && (upbound >= sseq->lower)) { 902 tipc_printf(buf, "%s ", typearea); 903 subseq_list(sseq, buf, depth, index); 904 sprintf(typearea, "%10s", " "); 905 } 906 } 907 } 908 909 /** 910 * nametbl_header - print name table header into the given buffer 911 */ 912 913 static void nametbl_header(struct print_buf *buf, u32 depth) 914 { 915 tipc_printf(buf, "Type "); 916 917 if (depth > 1) 918 tipc_printf(buf, "Lower Upper "); 919 if (depth > 2) 920 tipc_printf(buf, "Port Identity "); 921 if (depth > 3) 922 tipc_printf(buf, "Publication"); 923 924 tipc_printf(buf, "\n-----------"); 925 926 if (depth > 1) 927 tipc_printf(buf, "--------------------- "); 928 if (depth > 2) 929 tipc_printf(buf, "-------------------------- "); 930 if (depth > 3) 931 tipc_printf(buf, "------------------"); 932 933 tipc_printf(buf, "\n"); 934 } 935 936 /** 937 * nametbl_list - print specified name table contents into the given buffer 938 */ 939 940 static void nametbl_list(struct print_buf *buf, u32 depth_info, 941 u32 type, u32 lowbound, u32 upbound) 942 { 943 struct hlist_head *seq_head; 944 struct hlist_node *seq_node; 945 struct name_seq *seq; 946 int all_types; 947 u32 depth; 948 u32 i; 949 950 all_types = (depth_info & TIPC_NTQ_ALLTYPES); 951 depth = (depth_info & ~TIPC_NTQ_ALLTYPES); 952 953 if (depth == 0) 954 return; 955 956 if (all_types) { 957 /* display all entries in name table to specified depth */ 958 nametbl_header(buf, depth); 959 lowbound = 0; 960 upbound = ~0; 961 for (i = 0; i < tipc_nametbl_size; i++) { 962 seq_head = &table.types[i]; 963 hlist_for_each_entry(seq, seq_node, seq_head, ns_list) { 964 nameseq_list(seq, buf, depth, seq->type, 965 lowbound, upbound, i); 966 } 967 } 968 } else { 969 /* display only the sequence that matches the specified type */ 970 if (upbound < lowbound) { 971 tipc_printf(buf, "invalid name sequence specified\n"); 972 return; 973 } 974 nametbl_header(buf, depth); 975 i = hash(type); 976 seq_head = &table.types[i]; 977 hlist_for_each_entry(seq, seq_node, seq_head, ns_list) { 978 if (seq->type == type) { 979 nameseq_list(seq, buf, depth, type, 980 lowbound, upbound, i); 981 break; 982 } 983 } 984 } 985 } 986 987 void nametbl_print(struct print_buf *buf, const char *str) 988 { 989 tipc_printf(buf, str); 990 read_lock_bh(&nametbl_lock); 991 nametbl_list(buf, 0, 0, 0, 0); 992 read_unlock_bh(&nametbl_lock); 993 } 994 995 #define MAX_NAME_TBL_QUERY 32768 996 997 struct sk_buff *nametbl_get(const void *req_tlv_area, int req_tlv_space) 998 { 999 struct sk_buff *buf; 1000 struct tipc_name_table_query *argv; 1001 struct tlv_desc *rep_tlv; 1002 struct print_buf b; 1003 int str_len; 1004 1005 if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_NAME_TBL_QUERY)) 1006 return cfg_reply_error_string(TIPC_CFG_TLV_ERROR); 1007 1008 buf = cfg_reply_alloc(TLV_SPACE(MAX_NAME_TBL_QUERY)); 1009 if (!buf) 1010 return NULL; 1011 1012 rep_tlv = (struct tlv_desc *)buf->data; 1013 printbuf_init(&b, TLV_DATA(rep_tlv), MAX_NAME_TBL_QUERY); 1014 argv = (struct tipc_name_table_query *)TLV_DATA(req_tlv_area); 1015 read_lock_bh(&nametbl_lock); 1016 nametbl_list(&b, ntohl(argv->depth), ntohl(argv->type), 1017 ntohl(argv->lowbound), ntohl(argv->upbound)); 1018 read_unlock_bh(&nametbl_lock); 1019 str_len = printbuf_validate(&b); 1020 1021 skb_put(buf, TLV_SPACE(str_len)); 1022 TLV_SET(rep_tlv, TIPC_TLV_ULTRA_STRING, NULL, str_len); 1023 1024 return buf; 1025 } 1026 1027 void nametbl_dump(void) 1028 { 1029 nametbl_list(CONS, 0, 0, 0, 0); 1030 } 1031 1032 int nametbl_init(void) 1033 { 1034 int array_size = sizeof(struct hlist_head) * tipc_nametbl_size; 1035 1036 table.types = (struct hlist_head *)kmalloc(array_size, GFP_ATOMIC); 1037 if (!table.types) 1038 return -ENOMEM; 1039 1040 write_lock_bh(&nametbl_lock); 1041 memset(table.types, 0, array_size); 1042 table.local_publ_count = 0; 1043 write_unlock_bh(&nametbl_lock); 1044 return 0; 1045 } 1046 1047 void nametbl_stop(void) 1048 { 1049 struct hlist_head *seq_head; 1050 struct hlist_node *seq_node; 1051 struct hlist_node *tmp; 1052 struct name_seq *seq; 1053 u32 i; 1054 1055 if (!table.types) 1056 return; 1057 1058 write_lock_bh(&nametbl_lock); 1059 for (i = 0; i < tipc_nametbl_size; i++) { 1060 seq_head = &table.types[i]; 1061 hlist_for_each_entry_safe(seq, seq_node, tmp, seq_head, ns_list) { 1062 struct sub_seq *sseq = seq->sseqs; 1063 1064 for (; sseq != &seq->sseqs[seq->first_free]; sseq++) { 1065 struct publication *publ = sseq->zone_list; 1066 assert(publ); 1067 do { 1068 struct publication *next = 1069 publ->zone_list_next; 1070 kfree(publ); 1071 publ = next; 1072 } 1073 while (publ != sseq->zone_list); 1074 } 1075 } 1076 } 1077 kfree(table.types); 1078 table.types = NULL; 1079 write_unlock_bh(&nametbl_lock); 1080 } 1081