1 : /*
2 : * TIPC Linux kernel implementation
3 : * Copyright (c) 2001-2003 Ericsson Research Canada
4 : * Copyright (c) 2003 OSDL, Inc.
5 : *
6 : * This file is based on the original source code done by Jon Maloy
7 : * (jon.maloy@ericsson.com) for TIPC version 0.96, available from
8 : * http://tipc.sourceforge.net
9 : ***************************************************************************
10 : * This program is free software; you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License as published by
12 : * the Free Software Foundation; either version 2 of the License, or
13 : * (at your option) any later version.
14 : *
15 : * This program is distributed in the hope that it will be useful,
16 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : * GNU General Public License for more details.
19 : *
20 : * You should have received a copy of the GNU General Public License
21 : * along with this program; if not, write to the Free Software
22 : * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 : ***************************************************************************
24 : * Alphabetical list of people who have worked on this file:
25 : * - Mark Haverkamp (markh@osdl.org)
26 : * - Mika Kukkonen (mika@osdl.org)
27 : * - Rusty Lynch (rusty@linux.intel.com)
28 : */
29 :
30 : #include "debug.h"
31 : #include "msg_buf.h"
32 : #include "name_table.h"
33 : #include "named.h"
34 : #include "net_event.h"
35 : #include "name_subscription.h"
36 : #include "port.h"
37 : #include "link.h"
38 : #include <net/tipc.h>
39 :
40 : #ifdef CONFIG_TIPC_DBG_BUF
41 : void nametbl_print(tipc_dbg_buf_t * buf, const char *str);
42 : void nametbl_dump(void);
43 : #endif
44 : uint published_reserved = 0;
45 :
46 : Publication *publ_pool = 0;
47 :
48 : void
49 : publ_handleUnavailable(Publication * this, tipc_net_addr_t a)
50 0 : {
51 : dbg_msg("publ_handleUnavailable: %x\n", a);
52 0 : nametbl_remove(this->type, this->lower, this->node, this->key);
53 : }
54 :
55 : Publication *
56 : publ_new(uint type,
57 : uint lower,
58 : uint upper, uint port, tipc_net_addr_t node, uint scope, uint key)
59 24 : {
60 24 : Publication *this;
61 :
62 25 : mem_cnew(this, publ_pool, 32500);
63 24 : netwsub_init(&this->subscription,
64 : this, (NS_Virtual) 0, (NS_Virtual) publ_handleUnavailable);
65 : assert(this->prev == 0);
66 24 : this->next = this;
67 24 : this->prev = this;
68 24 : this->type = type;
69 24 : this->lower = lower;
70 24 : this->upper = upper;
71 24 : this->port = port;
72 24 : this->node = node;
73 24 : this->scope = scope;
74 24 : this->key = key;
75 24 : this->nextInPortChain = 0;
76 24 : if (node != tipc_my_addr) {
77 5 : tipc_net_register(&this->subscription, node);
78 : }
79 24 : return this;
80 : }
81 :
82 : void
83 : publ_delete(Publication * this)
84 18 : {
85 : dbg_msg("publ_delete called, node = %x\n", this->node);
86 : assert(this->prev);
87 : assert(this->next);
88 18 : this->prev->next = this->next;
89 18 : this->next->prev = this->prev;
90 18 : this->prev = 0;
91 18 : this->next = publ_pool;
92 18 : publ_pool = this;
93 18 : if (this->node != tipc_my_addr) {
94 1 : netwsub_unsubscribe(&this->subscription);
95 : }
96 : }
97 :
98 : /* //////////////////////////////////////////////////////////////
99 : //
100 : // SubSequence: A contiguous sub-sequence within a name sequence.
101 : // A subsequence refers to 'Publication' objects representing
102 : // the ports from which the publications are issued.
103 : // A big independent area of subsequences is maintained here
104 : // because of the need for efficient memory usage, while
105 : // allocation/deallocation speed is less critical.
106 : //
107 : ////////////////////////////////////////////////////////////// */
108 :
109 : typedef struct SubSequence {
110 : uint lower;
111 : uint upper;
112 : Publication *preferred;
113 : Publication *loadshared;
114 : } SubSequence;
115 :
116 : #define SS_SIZE (sizeof(SubSequence))
117 :
118 : #define subseq_busy(X) (*((int *)&((X)->preferred)) != ~0)
119 : #define subseq_setFree(X) {(X)->preferred = (Publication*)~0;};
120 :
121 : #define subseq_get(X,Y) (pools[(X)]?&pools[(X)]->subsequences[(Y)]:0)
122 :
123 : typedef struct SubSequencePool {
124 : uint size;
125 : uint occupied;
126 : SubSequence subsequences[1];
127 : } SubSequencePool;
128 :
129 : SubSequencePool *pools[20] =
130 : { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
131 :
132 : SubSequence *
133 : subseq_allocate(uint sz, uint * poolno, uint * i)
134 11 : {
135 11 : struct SubSequencePool *pool;
136 11 : uint chunk_size = *poolno = 1;
137 :
138 : dbg_msg("Subseq: allocating %u items\n", sz);
139 11 : while (chunk_size < sz) {
140 13 : chunk_size = chunk_size << 1;
141 13 : (*poolno)++;
142 : }
143 : dbg_msg("Subseq: found pool no %u, is %p \n", *poolno, pools[*poolno]);
144 : assert(*poolno < 20);
145 11 : pool = pools[*poolno];
146 :
147 : /* Make sure that there is free space: */
148 11 : if (!pool) {
149 5 : uint oc =
150 : 2 * sizeof (int) +
151 5 : ((4000 < (chunk_size * SS_SIZE)) ? (chunk_size * SS_SIZE) : 4000);
152 : dbg_msg("Subseq: allocating new pool of sz %u/%u \n", oc,
153 : (oc / SS_SIZE));
154 5 : pool = pools[*poolno] = (SubSequencePool *) mem_alloc(oc);
155 5 : memset(pool, 0xff, oc);
156 5 : pool->size = oc / SS_SIZE / chunk_size;
157 5 : pool->occupied = 0;
158 6 : } else if (pool->occupied >= pool->size) {
159 0 : uint oc = pool->size * SS_SIZE * chunk_size + 2 * sizeof (int);
160 :
161 : assert(pool->occupied == pool->size);
162 0 : pool =
163 : (struct SubSequencePool *) mem_alloc((oc * 2) -
164 : 2 * sizeof (int));
165 0 : memset(((char *) pool) + oc, 0xff, oc - 2 * sizeof (int));
166 0 : memcpy(pool, pools[*poolno], oc);
167 0 : pool->size *= 2;
168 0 : mem_free((char *) pools[*poolno]);
169 0 : pools[*poolno] = pool;
170 : dbg_msg("Subseq: extended pool no: %u->%u \n", oc / SS_SIZE,
171 : pool->size);
172 : }
173 : dbg_msg("Subseq: pool no %u is %p\n", *poolno, pool);
174 : dbg_msg(".. has sz %u, %u busy\n", pool ? pool->size : 0,
175 : pool ? pool->occupied : 0);
176 :
177 : /* Find first free space: */
178 11 : for (*i = 0; subseq_busy(&(pool->subsequences[*i])); (*i) += chunk_size) {
179 : assert(*i < (pool->size * chunk_size));
180 : }
181 11 : pool->occupied++;
182 11 : memset(&(pool->subsequences[*i]), 0, sizeof (SubSequence));
183 : dbg_msg("Subseq: found space at pos %u, in pool %u\n", *i, *poolno);
184 11 : return &pool->subsequences[*i];
185 : }
186 :
187 : void
188 : subseq_deallocate(uint poolno, uint index)
189 9 : {
190 : assert(pools[poolno]);
191 : dbg_msg("Subseq: deallocating at pos %u, in pool %u\n", index, poolno);
192 9 : subseq_setFree(&pools[poolno]->subsequences[index]);
193 9 : pools[poolno]->occupied--;
194 : }
195 :
196 : /* //////////////////////////////////////////////////////////////
197 : //
198 : // NameSequence: A container of more or less contiguous sub-
199 : // sequences of name individuals. All individuals represent
200 : // a name of the same 'type'.
201 : //
202 : ////////////////////////////////////////////////////////////// */
203 :
204 : typedef struct NameSequence {
205 : uint type;
206 : uint subseqPool;
207 : uint subseqIndex;
208 : uint allocated;
209 : uint firstFree;
210 : struct NameSequence *prev;
211 : struct NameSequence *next;
212 : NameSubscription *subscriptions;
213 : } NameSequence;
214 :
215 : NameSequence *nameseq_pool = 0;
216 :
217 : NameSequence *
218 : nameseq_new(uint type, NameSequence * next)
219 5 : {
220 5 : NameSequence *this;
221 :
222 6 : mem_cnew(this, nameseq_pool, 16000);
223 : dbg_msg("nameseq_new called() for type %u, next =%p\n", type, next);
224 5 : this->allocated = 0;
225 5 : this->firstFree = 0;
226 5 : this->subseqPool = 0;
227 5 : this->subseqIndex = 0;
228 5 : this->type = type;
229 5 : this->prev = 0;
230 5 : this->next = next;
231 5 : this->subscriptions = 0;
232 5 : if (next)
233 0 : next->prev = this;
234 5 : return this;
235 : }
236 :
237 : void
238 : nameseq_delete(NameSequence * this)
239 3 : {
240 : dbg_msg("nameseq_delete called() %p: firstFree = %u,alloc = %u\n",
241 : this, this->firstFree, this->allocated);
242 : assert(this->firstFree == 0);
243 : assert(this->subscriptions == 0);
244 3 : subseq_deallocate(this->subseqPool, this->subseqIndex);
245 3 : this->next = nameseq_pool;
246 3 : nameseq_pool = this;
247 : }
248 :
249 : #define nameseq_findSubsequence(this,subsequences,instance,res)\
250 : {\
251 : uint mid = 0;\
252 : int low = 0;\
253 : int high = (this)->firstFree - 1;\
254 : res = ~0;\
255 : while (low <= high)\
256 : {\
257 : mid = (low + high) / 2;\
258 : if (((instance) >= subsequences[mid].lower) &&\
259 : ((instance) <= subsequences[mid].upper))\
260 : {\
261 : res = mid;\
262 : break;\
263 : }\
264 : else\
265 : {\
266 : if ((instance) < subsequences[mid].lower)\
267 : {\
268 : high = mid - 1;\
269 : }\
270 : else\
271 : {\
272 : low = mid + 1;\
273 : }\
274 : }\
275 : }\
276 : \
277 : if (res < 0)\
278 : /* No match, return inverse of position where insertion can be done */\
279 : {\
280 : if ((this)->firstFree)\
281 : {\
282 : assert(mid <= (this)->firstFree);\
283 : res = ((subsequences[mid].upper<(instance))?mid+1:mid);\
284 : assert(res <= (int)(this)->firstFree);\
285 : if (res < (int)(this)->firstFree)\
286 : { \
287 : assert(subsequences[res].lower > (instance));\
288 : }\
289 : else assert(subsequences[res-1].upper < (instance));\
290 : res=~res; \
291 : }\
292 : else {assert(res == ~0);};\
293 : }\
294 : }
295 :
296 : Publication *
297 : nameseq_insert(NameSequence * this,
298 : uint type,
299 : uint lower,
300 : uint upper,
301 : uint port,
302 : tipc_net_addr_t node, uint scope, uint preferred, uint key)
303 24 : {
304 24 : int i = ~0;
305 24 : Publication *publ = 0;
306 24 : SubSequence *sseqs = subseq_get(this->subseqPool, this->subseqIndex);
307 24 : uint new_subsequence = 0;
308 :
309 24 : if (!sseqs) {
310 5 : subseq_allocate(1, &this->subseqPool, &this->subseqIndex);
311 5 : this->allocated = 1;
312 5 : sseqs = subseq_get(this->subseqPool, this->subseqIndex);
313 : } else {
314 19 : int u;
315 :
316 19 : nameseq_findSubsequence(this, sseqs, lower, i);
317 19 : nameseq_findSubsequence(this, sseqs, upper, u);
318 19 : if (u != i)
319 0 : return 0;
320 : }
321 :
322 24 : if (i < 0) { /* No match found, insert new subsequence */
323 : /* Make sure there is enough space: */
324 22 : if (this->firstFree >= this->allocated) {
325 6 : uint oldpool = this->subseqPool;
326 6 : uint oldindex = this->subseqIndex;
327 6 : SubSequence *oldss = sseqs;
328 6 : uint newsize = this->allocated * 2;
329 :
330 : dbg_msg("nameseq_insert:expanding %u->%u\n",
331 : this->allocated, newsize);
332 : assert(this->firstFree == this->allocated);
333 6 : subseq_allocate(newsize, &this->subseqPool,
334 : &this->subseqIndex);
335 6 : sseqs = subseq_get(this->subseqPool, this->subseqIndex);
336 6 : memcpy(sseqs, oldss, this->allocated * SS_SIZE);
337 6 : subseq_deallocate(oldpool, oldindex);
338 6 : this->allocated = newsize;
339 : }
340 :
341 22 : i = ~i; /* Gives insert position */
342 : dbg_msg("nameseq_insert:inserting into pos %u <%u,%u,%u>\n",
343 : i, type, lower, upper);
344 :
345 22 : if (i < (int) this->firstFree) { /* Insert new */
346 13 : char *from = ((char *) &sseqs[i]);
347 13 : uint sz = ((char *) &sseqs[this->firstFree]) - from;
348 :
349 13 : if (i && !(sseqs[i - 1].upper < lower))
350 0 : return 0;
351 13 : memmove(&sseqs[i + 1], from, sz);
352 : }
353 22 : this->firstFree++;
354 22 : sseqs[i].preferred = 0;
355 22 : sseqs[i].loadshared = 0;
356 22 : sseqs[i].lower = lower;
357 22 : sseqs[i].upper = upper;
358 22 : new_subsequence = 1;
359 : } else { /* Subsequences must match exactly */
360 :
361 2 : if ((sseqs[i].lower != lower) || (sseqs[i].upper != upper)) {
362 0 : Publication *p =
363 : sseqs[i].preferred ? sseqs[i].preferred : sseqs[i].
364 0 : loadshared;
365 0 : tipc_net_addr_t a = p ? p->node : 0;
366 :
367 0 : warn("TIPC: Attempted publication <%u,%u,%u> from port <%u.%u.%u:%u>\n" "overlaps with existing one <%u,%u,%u> from port <%u.%u.%u:%u>\n", type, lower, upper, tipc_zone_id(node), tipc_cluster_id(node), tipc_node_id(node), port, type, sseqs[i].lower, sseqs[i].upper, tipc_zone_id(a), tipc_cluster_id(a), tipc_node_id(a), p ? p->port : 0);
368 0 : return 0;
369 : }
370 : }
371 :
372 : /* Insert a port reference: */
373 :
374 24 : publ = publ_new(type, lower, upper, port, node, scope, key);
375 24 : if ((node == tipc_my_addr) && (preferred)) {
376 2 : if (sseqs[i].preferred) {
377 :
378 0 : err("TIPC: User Error: Preferred local publication <%u,%u,%u> from port" " %u\n clashes with existing one from port %u\n", type, lower, upper, port, sseqs[i].preferred->port);
379 0 : publ_delete(publ);
380 0 : return 0;
381 : }
382 2 : sseqs[i].preferred = publ;
383 : } else {
384 22 : Publication *crs = sseqs[i].loadshared;
385 :
386 22 : if (!crs)
387 22 : crs = publ;
388 22 : publ->next = crs;
389 22 : publ->prev = crs->prev;
390 22 : publ->prev->next = publ;
391 22 : publ->next->prev = publ;
392 22 : sseqs[i].loadshared = publ;
393 : }
394 :
395 : /* Any subscriptions waiting ? */
396 24 : if (new_subsequence) {
397 22 : NameSubscription *s = this->subscriptions;
398 :
399 22 : while (s) {
400 12 : NameSubscription *next = s->next;
401 :
402 : /* If any overlap, report it */
403 12 : uint low = (s->lower < lower) ? lower : s->lower;
404 12 : uint up = (s->upper > upper) ? upper : s->upper;
405 :
406 : dbg_msg("nameseq_insert; subsc = %p\n", s);
407 12 : if (low <= up) { /* Found match */
408 : dbg_msg
409 : ("nameseq_insert(%u,%u,%u, calling subscriber\n",
410 : type, low, up);
411 12 : namesub_handleEvent(s, low, up, tipc_name_published, port, node);
412 : }
413 12 : s = next;
414 : }
415 : }
416 24 : return publ;
417 : }
418 :
419 : uint
420 : nameseq_remove(NameSequence * this, uint instance, tipc_net_addr_t node,
421 : uint key)
422 18 : {
423 18 : int i;
424 18 : Publication *publ = 0;
425 18 : uint result = ~0u;
426 18 : uint port;
427 18 : SubSequence *sseqs = subseq_get(this->subseqPool, this->subseqIndex);
428 :
429 : dbg_msg("nameseq_remove: got subseqs %p, looking for instance %u\n",
430 : sseqs, instance);
431 18 : nameseq_findSubsequence(this, sseqs, instance, i);
432 0 : if ((i < 0) || (i >= (int)this->firstFree))
433 : {
434 0 : warn("TIPC: Failed to withdraw unknown <%u,%u>\n",this->type,instance);
435 0 : return result;
436 : }
437 :
438 : /* Find corresponding publications: */
439 :
440 18 : if ((node == tipc_my_addr) && sseqs[i].preferred) {
441 0 : if (sseqs[i].preferred->key == key) {
442 0 : publ = sseqs[i].preferred;
443 0 : sseqs[i].preferred = 0;
444 : }
445 : }
446 :
447 18 : if (!publ) {
448 18 : publ = sseqs[i].loadshared;
449 : assert(publ);
450 18 : do {
451 18 : if ((key == publ->key)
452 : && (node == publ->node)) {
453 18 : if (publ == publ->next) { /* The only one in list ? */
454 : assert(publ == publ->prev);
455 18 : sseqs[i].loadshared = 0;
456 0 : } else if (publ == sseqs[i].loadshared) {
457 0 : sseqs[i].loadshared = publ->next;
458 : }
459 0 : break;
460 : }
461 0 : publ = publ->next;
462 0 : }
463 : while (publ != sseqs[i].loadshared);
464 : }
465 :
466 : /* There must be one: */
467 : assert(publ->node == node);
468 : assert(publ->key == key);
469 18 : result = publ->scope;
470 18 : port = publ->port;
471 18 : publ_delete(publ);
472 :
473 : /* Contract subsequence list if necessary: */
474 18 : if ((sseqs[i].preferred == 0) && (sseqs[i].loadshared == 0)) {
475 18 : uint lower = sseqs[i].lower;
476 18 : uint upper = sseqs[i].upper;
477 18 : char *from = (char *) &sseqs[i + 1];
478 18 : uint sz = (char *) &sseqs[this->firstFree--] - from;
479 :
480 : dbg_msg("nameseq_remove() firstFree = %u, moving %u bytes\n",
481 : this->firstFree, sz);
482 : assert(sz <= (1u << 31));
483 18 : memmove(&sseqs[i], from, sz);
484 :
485 : /* Any subscriptions waiting ? */
486 : {
487 18 : NameSubscription *s = this->subscriptions;
488 :
489 18 : while (s) {
490 : /* If any overlap, report it */
491 0 : uint low =
492 0 : (s->lower < lower) ? lower : s->lower;
493 0 : uint up = (s->upper > upper) ? upper : s->upper;
494 :
495 : dbg_msg("nameseq_remove; subsc = %p\n", s);
496 0 : if (low <= up) {
497 : dbg_msg
498 : ("nameseq_remove; sending signal\n");
499 0 : namesub_handleEvent(s, low, up,
500 : tipc_name_withdrawn,
501 : port, node);
502 : }
503 0 : s = s->next;
504 : }
505 : }
506 : }
507 18 : return result;
508 : }
509 :
510 : void
511 : nameseq_subscribe(NameSequence * this, NameSubscription * s)
512 12 : {
513 12 : uint i;
514 12 : uint lower = s->lower;
515 12 : uint upper = s->upper;
516 12 : SubSequence *sseqs = subseq_get(this->subseqPool, this->subseqIndex);
517 :
518 12 : s->next = this->subscriptions;
519 12 : this->subscriptions = s;
520 : dbg_msg("NameSequencesubscribe; subsc = %p, for <%u,%u,%u>\n",
521 : s, this->type, lower, upper);
522 12 : for (i = 0; i < this->firstFree; i++) {
523 : /* If any overlap, report it */
524 0 : uint foundLower =
525 0 : (lower < sseqs[i].lower) ? sseqs[i].lower : lower;
526 0 : uint foundUpper =
527 0 : (upper > sseqs[i].upper) ? sseqs[i].upper : upper;
528 0 : if (foundLower <= foundUpper) {
529 0 : SubSequence* ss = &sseqs[i];
530 0 : Publication* p = ss->preferred;
531 0 : if (!p)
532 0 : p = ss->loadshared;
533 : assert(p);
534 : dbg_msg("NameSequencesubscribe: handleEvent(PUBLISHED)");
535 0 : namesub_handleEvent(s, foundLower, foundUpper,
536 : tipc_name_published, p->port, p->node);
537 : }
538 : }
539 : }
540 :
541 : /* //////////////////////////////////////////////////////////////
542 : //
543 : // Name Table: Translation table containing all existing
544 : // port name publications. Consists of 'NameSequence' objects
545 : // sorted on 'type'.
546 : //
547 : ////////////////////////////////////////////////////////////// */
548 :
549 : #define LOCAL_PUBLICATIONLIMIT 10000
550 : #define TABLE_SIZE (1<<14)
551 : #define HASH(X) ((X)&(TABLE_SIZE-1))
552 :
553 : typedef struct NameTable {
554 : NameSequence *types[TABLE_SIZE];
555 : uint key;
556 : unsigned long int timerRef;
557 : uint localPublicationCount;
558 : } NameTable;
559 :
560 : static NameTable table;
561 :
562 : #define nametbl_findNameSequence(TYPE,SEQ) \
563 : {\
564 : (SEQ) = table.types[HASH((TYPE))];\
565 : while ((SEQ) && ((SEQ)->type != (TYPE))) {(SEQ) = (SEQ)->next;}\
566 : };
567 :
568 : Publication *
569 : nametbl_insert(uint type,
570 : uint lower,
571 : uint upper,
572 : uint port,
573 : tipc_net_addr_t node, uint scope, uint preferred, uint key)
574 24 : {
575 24 : Publication *publ;
576 24 : NameSequence *item;
577 :
578 : assert(lower <= upper);
579 24 : nametbl_findNameSequence(type, item);
580 : dbg_msg("Publishing <%u,%u,%u> from %x\n", type, lower, upper, node);
581 24 : if (scope != ZONE_SCOPE) {
582 : dbg_msg(" with scope %u\n", scope);
583 : }
584 24 : if (!item) {
585 4 : NameSequence *head = table.types[HASH(type)];
586 :
587 4 : item = table.types[HASH(type)] = nameseq_new(type, head);
588 : dbg_msg("nametbl_insert: created %p\n", item);
589 : }
590 : assert(item->type == type);
591 24 : publ = nameseq_insert(item, type, lower, upper, port, node, scope,
592 : preferred, key);
593 24 : return publ;
594 : }
595 :
596 : uint
597 : nametbl_remove(uint type, uint lower, tipc_net_addr_t node, uint key)
598 18 : {
599 18 : uint result;
600 18 : NameSequence *seq;
601 :
602 18 : nametbl_findNameSequence(type, seq);
603 0 : if (!seq)
604 0 : return ~0u;
605 : dbg_msg("Withdrawing <%u,%u> from %x\n", type, lower, node);
606 18 : result = nameseq_remove(seq, lower, node, key);
607 18 : if ((result != ~0u) && (seq->firstFree == 0) && (seq->subscriptions == 0)) {
608 3 : if (seq->prev)
609 0 : seq->prev->next = seq->next;
610 : else
611 3 : table.types[HASH(seq->type)] = seq->next;
612 3 : if (seq->next)
613 0 : seq->next->prev = seq->prev;
614 3 : nameseq_delete(seq);
615 : }
616 18 : return result;
617 : }
618 :
619 : uint
620 : nametbl_translate(uint type, uint instance, tipc_net_addr_t * destnode)
621 80 : {
622 80 : NameSequence *seq;
623 80 : int i;
624 80 : Publication *publ;
625 80 : SubSequence *sseqs;
626 :
627 80 : nametbl_findNameSequence(type, seq);
628 : dbg_msg("NameSequence::translate: [%d, %d] \n", type, instance);
629 0 : if (!seq)
630 1 : return 0;
631 79 : sseqs = subseq_get(seq->subseqPool, seq->subseqIndex);
632 79 : if (!sseqs)
633 11 : return 0;
634 68 : nameseq_findSubsequence(seq, sseqs, instance, i);
635 1 : if (i < 0)
636 1 : return 0;
637 : assert(sseqs[i].upper >= instance);
638 : assert(sseqs[i].lower <= instance);
639 : dbg_msg("nameseq_translate: pos %u ok\n", i);
640 67 : publ = sseqs[i].preferred;
641 67 : if (!publ) {
642 43 : publ = sseqs[i].loadshared;
643 43 : sseqs[i].loadshared = publ->next;
644 : }
645 : assert(publ);
646 67 : *destnode = publ->node;
647 67 : return publ->port;
648 : }
649 :
650 : Publication *
651 : nametbl_publish(uint type,
652 : uint lower, uint upper, uint port, uint scope, uint preferred)
653 19 : {
654 19 : Publication *publ;
655 :
656 19 : if ((type <= 1) && (++published_reserved > 2)) {
657 : warn("TIPC: Failed to publish from port %u \n"
658 0 : "type %u is reserved\n", port, type);
659 0 : return 0;
660 : }
661 :
662 19 : if (lower > upper) {
663 : warn("TIPC: Failed to publish <%u,%u,%u> from port %u.\n"
664 : "Illegal suite: lower > upper\n", type, lower, upper,
665 0 : port);
666 0 : return 0;
667 : }
668 :
669 19 : if (table.localPublicationCount >= LOCAL_PUBLICATIONLIMIT) {
670 0 : warn("TIPC: Not possible to publish more port names, \nlimit of " " %u node local publications exceeded\n", LOCAL_PUBLICATIONLIMIT);
671 0 : return 0;
672 : }
673 19 : table.localPublicationCount++;
674 19 : publ = nametbl_insert(type, lower, upper, port, tipc_my_addr,
675 : scope, preferred, ++table.key);
676 19 : if (publ && (scope != NODE_SCOPE)) {
677 19 : tipc_named_publish(type, lower, upper, port, table.key);
678 : }
679 19 : return publ;
680 : }
681 :
682 : uint
683 : nametbl_withdraw(uint type, uint lower, uint key)
684 17 : {
685 17 : uint scope;
686 :
687 : dbg_msg("\nnametbl_withdraw:<%d,%d,%d>\n", type, lower, key);
688 17 : scope = nametbl_remove(type, lower, tipc_my_addr, key);
689 17 : if (scope == ~0u)
690 0 : return 0;
691 17 : table.localPublicationCount--;
692 17 : if (scope != NODE_SCOPE) {
693 17 : tipc_named_withdraw(type, lower, key);
694 : }
695 17 : return 1;
696 : }
697 :
698 : void
699 : nametbl_subscribe(NameSubscription * s, uint type)
700 12 : {
701 12 : NameSequence *item;
702 :
703 12 : nametbl_findNameSequence(type, item);
704 : dbg_msg("nametblsubscribe:found %p for <%u,%u,%u>\n",
705 : item, type, s->lower, s->upper);
706 0 : if (!item) {
707 1 : NameSequence *head = table.types[HASH(type)];
708 :
709 1 : item = table.types[HASH(type)] = nameseq_new(type, head);
710 : dbg_msg("nametblsubscribe: created %p\n", item);
711 : }
712 : assert(item->type == type);
713 12 : nameseq_subscribe(item, s);
714 : }
715 :
716 : void
717 : nametbl_unsubscribe(NameSubscription * s, uint type)
718 12 : {
719 12 : NameSubscription *prev;
720 12 : NameSubscription *item;
721 12 : NameSequence *seq;
722 :
723 12 : nametbl_findNameSequence(type, seq);
724 : dbg_msg("namtbl_unsubscribe:found %p for type %u\n", seq, type);
725 12 : if (!seq)
726 12 : return; /* No NameSequence (can't be valid) */
727 : assert(seq->type == type);
728 12 : prev = 0;
729 12 : item = seq->subscriptions;
730 12 : while ((item != 0) && (item != s)) {
731 40 : prev = item;
732 40 : item = item->next;
733 : }
734 12 : if (!item)
735 12 : return; /* No match found */
736 :
737 12 : if (!prev)
738 2 : seq->subscriptions = item->next;
739 : else
740 10 : prev->next = item->next;
741 : }
742 :
743 : void
744 : name_table_init(void)
745 1 : {
746 1 : memset(&table, 0, sizeof (table));
747 1 : table.key = tipc_my_addr;
748 : }
749 :
750 : /* //////////////////////////////////////////////////////////////////
751 : //
752 : // tipc_sendNamedMessage is called from user when a named message is
753 : // being sent.
754 : //
755 : /////////////////////////////////////////////////////////////////// */
756 :
757 : uint
758 : tipc_sendNamedMsg(TipcSendMsgArgv * argv)
759 0 : {
760 0 : tipc_net_addr_t destnode;
761 0 : NameSequence *seq;
762 0 : int i;
763 0 : Publication *publ;
764 0 : uint destport;
765 0 : tipc_msg_hdr_t *phdr;
766 0 : uint type;
767 0 : uint inst;
768 0 : uint dest;
769 :
770 : /* Get pre-built header and update */
771 0 : Port *oport = port_deref(argv->origport);
772 :
773 0 : if (!oport)
774 0 : return tipc_userError(tipc_invalid_args);
775 0 : if (port_connected(oport))
776 0 : return tipc_userError(tipc_illegal_operation);
777 0 : phdr = port_phdr(oport);
778 0 : type = argv->dest.name.type;
779 0 : inst = argv->dest.name.instance;
780 0 : dest = argv->dest.name.translationNode;
781 0 : if (dest < 512)
782 0 : dest = tipc_make_addr(dest, 0, 0); /* undocumented feature */
783 0 : set_name_type(phdr, type);
784 0 : set_name_inst(phdr, inst);
785 0 : set_hdr_size(phdr, LONG_HDR_SIZE);
786 0 : set_msg_type(phdr, TIPC_NAMED_MSG);
787 :
788 : /* Should first lookup be done somewhere else ? */
789 0 : if (!tipc_addr_match(dest, tipc_my_addr)) {
790 : dbg_msg("Sending <%u,%u> for translation on %x\n",
791 : type, inst, argv->dest.name.translationNode);
792 0 : set_dest_port(phdr, 0);
793 0 : set_dest_node(phdr, dest);
794 0 : return tipc_sendMsg(argv);
795 : }
796 : dbg_msg("Looking up <%u,%u> ", type, inst);
797 :
798 : /* Do the lookup: */
799 0 : nametbl_findNameSequence(type, seq);
800 0 : if (seq) {
801 0 : SubSequence *sseqs =
802 0 : subseq_get(seq->subseqPool, seq->subseqIndex);
803 0 : nameseq_findSubsequence(seq, sseqs, inst, i);
804 0 : if (i >= 0) { /* Found */
805 : assert(sseqs[i].upper >= inst);
806 : assert(sseqs[i].lower <= inst);
807 0 : publ = sseqs[i].preferred;
808 0 : if (!publ) {
809 0 : publ = sseqs[i].loadshared;
810 0 : sseqs[i].loadshared = publ->next;
811 : }
812 : assert(publ);
813 0 : destport = publ->port;
814 0 : destnode = publ->node;
815 :
816 : /* Update header as far as known now */
817 0 : set_dest_node(phdr, destnode);
818 0 : set_dest_port(phdr, destport);
819 :
820 0 : if (destport) {
821 : dbg_msg("found [%u,%x] \n", destport, destnode);
822 0 : if (destnode == tipc_my_addr) {
823 0 : return port_sendMsg(oport, (TipcSendMsgArgv *) argv);
824 : } else {
825 0 : return
826 : tipc_sendMsg((TipcSendMsgArgv *) argv);
827 : }
828 : }
829 : }
830 : }
831 : dbg_msg("failed... \n");
832 0 : return port_rejectReq(argv, phdr, tipc_no_portname);
833 : }
834 :
835 : /* //////////////////////////////////////////////////////////////////
836 : //
837 : // tipc_multicastNamedMessage is called from user when a named message is
838 : // being sent.
839 : //
840 : /////////////////////////////////////////////////////////////////// */
841 :
842 : uint
843 : tipc_multicastNamedMsg(TipcSendMsgArgv * argv)
844 0 : {
845 0 : return 0;
846 : }
847 :
848 : uint
849 : tipc_nameAvailable(const TipcNameAvailabilityArgv * argv)
850 17 : {
851 17 : tipc_net_addr_t addr;
852 17 : uint res = nametbl_translate(argv->type, argv->instance, &addr);
853 :
854 : dbg_msg(" tipc_nameAvailable <%u,%u> returns %s\n",
855 : argv->type, argv->instance, res ? "1" : "0");
856 17 : return res;
857 : }
858 :
859 : uint
860 : nametbl_nameSeqAvailable(uint type, uint lower, uint upper)
861 0 : {
862 0 : NameSequence *seq;
863 0 : uint i;
864 0 : SubSequence *sseqs;
865 :
866 0 : nametbl_findNameSequence(type, seq);
867 0 : if (!seq)
868 0 : return 0;
869 0 : sseqs = subseq_get(seq->subseqPool, seq->subseqIndex);
870 0 : if (!sseqs)
871 0 : return 0;
872 0 : for (i = 0; i < seq->firstFree; i++) {
873 0 : if ((sseqs[i].lower >= lower) && (sseqs[i].lower <= upper))
874 0 : return 1;
875 0 : if ((sseqs[i].upper >= lower) && (sseqs[i].upper <= upper))
876 0 : return 1;
877 : }
878 0 : return 0;
879 : }
880 :
881 : #ifdef CONFIG_TIPC_DBG_BUF
882 : void
883 : nametbl_list(tipc_dbg_buf_t * buf, uint type, uint depth)
884 : {
885 : NameSequence *seq = 0;
886 : Publication *publ = 0;
887 : uint i;
888 :
889 : for (i = 0; i < TABLE_SIZE; i++) {
890 : if (table.types[i] != 0) {
891 : seq = table.types[i];
892 : while (seq) {
893 : uint j;
894 : SubSequence *sseqs = subseq_get(seq->subseqPool,
895 : seq->
896 : subseqIndex);
897 : if (!type || (type == seq->type)) {
898 : debug_output(buf, "Index %u:\n", i);
899 : debug_output(buf, " Type: %u\n",
900 : seq->type);
901 : if (depth <= 1) { /* Print subsequences */
902 : for (j = 0; j < seq->firstFree;
903 : j++) {
904 : debug_output(buf,
905 : " Sub-sequence[%u]:[%u,%u]\n",
906 : j,
907 : sseqs[j].
908 : lower,
909 : sseqs[j].
910 : upper);
911 : if (depth == 0) { /* Print all */
912 : if (sseqs[j].
913 : preferred !=
914 : 0) {
915 : debug_output
916 : (buf,
917 : " Local port: %u key = %u\n",
918 : sseqs
919 : [j].
920 : preferred->
921 : port,
922 : sseqs
923 : [j].
924 : preferred->
925 : key);
926 : }
927 :
928 : if (sseqs[j].
929 : loadshared
930 : != 0) {
931 : publ =
932 : sseqs
933 : [j].
934 : loadshared;
935 : do {
936 : debug_output
937 : (buf,
938 : " Remote port: [%u,%x],key: %u\n",
939 : publ->
940 : port,
941 : publ->
942 : node,
943 : publ->
944 : key);
945 : publ = publ->next;
946 : }
947 : while
948 : (publ
949 : !=
950 : sseqs
951 : [j].
952 : loadshared);
953 : }
954 : }
955 : }
956 : }
957 : }
958 : seq = seq->next;
959 : }
960 : debug_output(buf, "\n");
961 : }
962 : }
963 : }
964 :
965 : void
966 : nametbl_print(tipc_dbg_buf_t * buf, const char *str)
967 : {
968 : debug_output(buf, str);
969 : nametbl_list(buf, 0, 0);
970 : }
971 :
972 : const char *
973 : tipc_getNameTable(const tipc_get_name_table_argv * argv)
974 : {
975 : tipc_dbg_buf_t db;
976 :
977 : dbg_buf_init(&db, 0, 0, 65408);
978 : nametbl_list(&db, argv->type, argv->depth);
979 : mem_delayed_free(db.buffer, 100);
980 : return db.buffer;
981 : }
982 :
983 : void
984 : nametbl_dump(void)
985 : {
986 : nametbl_list(C,0,0);
987 : }
988 : #endif
|