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