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