blob: e152d6dddfab7c13bf4ecd8586d9901f288910f4 [file] [log] [blame]
Per Lidenb97bf3f2006-01-02 19:04:38 +01001/*
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 *
Per Liden9ea1fd32006-01-11 13:30:43 +01009 * Redistribution and use in source and binary forms, with or without
Per Lidenb97bf3f2006-01-02 19:04:38 +010010 * modification, are permitted provided that the following conditions are met:
11 *
Per Liden9ea1fd32006-01-11 13:30:43 +010012 * 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.
Per Lidenb97bf3f2006-01-02 19:04:38 +010020 *
Per Liden9ea1fd32006-01-11 13:30:43 +010021 * 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
Per Lidenb97bf3f2006-01-02 19:04:38 +010035 * 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
50int 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
61struct 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
81struct 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
98struct name_table {
99 struct hlist_head *types;
100 u32 local_publ_count;
101};
102
103struct name_table table = { NULL } ;
104static atomic_t rsv_publ_ok = ATOMIC_INIT(0);
105rwlock_t nametbl_lock = RW_LOCK_UNLOCKED;
106
107
108static 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
117static 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
146struct 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
162struct 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
194static 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
224static 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
247struct 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
373struct 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
491void 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
522static 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
542struct 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
567struct 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
595u32 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;
619found:
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);
659not_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
678int 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);
712exit:
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
721int 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
736struct 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
767int 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
791void
792nametbl_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
817void
818nametbl_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
842static 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
887static 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
913static 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
940static 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
987void 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
997struct 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
1027void nametbl_dump(void)
1028{
1029 nametbl_list(CONS, 0, 0, 0, 0);
1030}
1031
1032int 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
1047void 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}