]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - net/tipc/bearer.c
[TIPC] Initial merge
[linux-2.6-omap-h63xx.git] / net / tipc / bearer.c
1 /*
2  * net/tipc/bearer.c: TIPC bearer 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 "bearer.h"
38 #include "link.h"
39 #include "port.h"
40 #include "discover.h"
41 #include "bcast.h"
42
43 #define MAX_ADDR_STR 32
44
45 static struct media *media_list = 0;
46 static u32 media_count = 0;
47
48 struct bearer *bearers = 0;
49
50 /**
51  * media_name_valid - validate media name
52  * 
53  * Returns 1 if media name is valid, otherwise 0.
54  */
55
56 static int media_name_valid(const char *name)
57 {
58         u32 len;
59
60         len = strlen(name);
61         if ((len + 1) > TIPC_MAX_MEDIA_NAME)
62                 return 0;
63         return (strspn(name, tipc_alphabet) == len);
64 }
65
66 /**
67  * media_find - locates specified media object by name
68  */
69
70 static struct media *media_find(const char *name)
71 {
72         struct media *m_ptr;
73         u32 i;
74
75         for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) {
76                 if (!strcmp(m_ptr->name, name))
77                         return m_ptr;
78         }
79         return 0;
80 }
81
82 /**
83  * tipc_register_media - register a media type
84  * 
85  * Bearers for this media type must be activated separately at a later stage.
86  */
87
88 int  tipc_register_media(u32 media_type,
89                          char *name, 
90                          int (*enable)(struct tipc_bearer *), 
91                          void (*disable)(struct tipc_bearer *), 
92                          int (*send_msg)(struct sk_buff *, 
93                                          struct tipc_bearer *,
94                                          struct tipc_media_addr *), 
95                          char *(*addr2str)(struct tipc_media_addr *a,
96                                            char *str_buf, int str_size),
97                          struct tipc_media_addr *bcast_addr,
98                          const u32 bearer_priority,
99                          const u32 link_tolerance,  /* [ms] */
100                          const u32 send_window_limit)
101 {
102         struct media *m_ptr;
103         u32 media_id;
104         u32 i;
105         int res = -EINVAL;
106
107         write_lock_bh(&net_lock);
108         if (!media_list)
109                 goto exit;
110
111         if (!media_name_valid(name)) {
112                 warn("Media registration error: illegal name <%s>\n", name);
113                 goto exit;
114         }
115         if (!bcast_addr) {
116                 warn("Media registration error: no broadcast address supplied\n");
117                 goto exit;
118         }
119         if (bearer_priority >= TIPC_NUM_LINK_PRI) {
120                 warn("Media registration error: priority %u\n", bearer_priority);
121                 goto exit;
122         }
123         if ((link_tolerance < TIPC_MIN_LINK_TOL) || 
124             (link_tolerance > TIPC_MAX_LINK_TOL)) {
125                 warn("Media registration error: tolerance %u\n", link_tolerance);
126                 goto exit;
127         }
128
129         media_id = media_count++;
130         if (media_id >= MAX_MEDIA) {
131                 warn("Attempt to register more than %u media\n", MAX_MEDIA);
132                 media_count--;
133                 goto exit;
134         }
135         for (i = 0; i < media_id; i++) {
136                 if (media_list[i].type_id == media_type) {
137                         warn("Attempt to register second media with type %u\n", 
138                              media_type);
139                         media_count--;
140                         goto exit;
141                 }
142                 if (!strcmp(name, media_list[i].name)) {
143                         warn("Attempt to re-register media name <%s>\n", name);
144                         media_count--;
145                         goto exit;
146                 }
147         }
148
149         m_ptr = &media_list[media_id];
150         m_ptr->type_id = media_type;
151         m_ptr->send_msg = send_msg;
152         m_ptr->enable_bearer = enable;
153         m_ptr->disable_bearer = disable;
154         m_ptr->addr2str = addr2str;
155         memcpy(&m_ptr->bcast_addr, bcast_addr, sizeof(*bcast_addr));
156         m_ptr->bcast = 1;
157         strcpy(m_ptr->name, name);
158         m_ptr->priority = bearer_priority;
159         m_ptr->tolerance = link_tolerance;
160         m_ptr->window = send_window_limit;
161         dbg("Media <%s> registered\n", name);
162         res = 0;
163 exit:
164         write_unlock_bh(&net_lock);
165         return res;
166 }
167
168 /**
169  * media_addr_printf - record media address in print buffer
170  */
171
172 void media_addr_printf(struct print_buf *pb, struct tipc_media_addr *a)
173 {
174         struct media *m_ptr;
175         u32 media_type;
176         u32 i;
177
178         media_type = ntohl(a->type);
179         for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) {
180                 if (m_ptr->type_id == media_type)
181                         break;
182         }
183
184         if ((i < media_count) && (m_ptr->addr2str != NULL)) {
185                 char addr_str[MAX_ADDR_STR];
186
187                 tipc_printf(pb, "%s(%s) ", m_ptr->name, 
188                             m_ptr->addr2str(a, addr_str, sizeof(addr_str)));
189         } else {
190                 unchar *addr = (unchar *)&a->dev_addr;
191
192                 tipc_printf(pb, "UNKNOWN(%u):", media_type);
193                 for (i = 0; i < (sizeof(*a) - sizeof(a->type)); i++) {
194                         tipc_printf(pb, "%02x ", addr[i]);
195                 }
196         }
197 }
198
199 /**
200  * media_get_names - record names of registered media in buffer
201  */
202
203 struct sk_buff *media_get_names(void)
204 {
205         struct sk_buff *buf;
206         struct media *m_ptr;
207         int i;
208
209         buf = cfg_reply_alloc(MAX_MEDIA * TLV_SPACE(TIPC_MAX_MEDIA_NAME));
210         if (!buf)
211                 return NULL;
212
213         read_lock_bh(&net_lock);
214         for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) {
215                 cfg_append_tlv(buf, TIPC_TLV_MEDIA_NAME, m_ptr->name, 
216                                strlen(m_ptr->name) + 1);
217         }
218         read_unlock_bh(&net_lock);
219         return buf;
220 }
221
222 /**
223  * bearer_name_validate - validate & (optionally) deconstruct bearer name
224  * @name - ptr to bearer name string
225  * @name_parts - ptr to area for bearer name components (or NULL if not needed)
226  * 
227  * Returns 1 if bearer name is valid, otherwise 0.
228  */
229
230 static int bearer_name_validate(const char *name, 
231                                 struct bearer_name *name_parts)
232 {
233         char name_copy[TIPC_MAX_BEARER_NAME];
234         char *media_name;
235         char *if_name;
236         u32 media_len;
237         u32 if_len;
238
239         /* copy bearer name & ensure length is OK */
240
241         name_copy[TIPC_MAX_BEARER_NAME - 1] = 0;
242         /* need above in case non-Posix strncpy() doesn't pad with nulls */
243         strncpy(name_copy, name, TIPC_MAX_BEARER_NAME);
244         if (name_copy[TIPC_MAX_BEARER_NAME - 1] != 0)
245                 return 0;
246
247         /* ensure all component parts of bearer name are present */
248
249         media_name = name_copy;
250         if ((if_name = strchr(media_name, ':')) == NULL)
251                 return 0;
252         *(if_name++) = 0;
253         media_len = if_name - media_name;
254         if_len = strlen(if_name) + 1;
255
256         /* validate component parts of bearer name */
257
258         if ((media_len <= 1) || (media_len > TIPC_MAX_MEDIA_NAME) || 
259             (if_len <= 1) || (if_len > TIPC_MAX_IF_NAME) || 
260             (strspn(media_name, tipc_alphabet) != (media_len - 1)) ||
261             (strspn(if_name, tipc_alphabet) != (if_len - 1)))
262                 return 0;
263
264         /* return bearer name components, if necessary */
265
266         if (name_parts) {
267                 strcpy(name_parts->media_name, media_name);
268                 strcpy(name_parts->if_name, if_name);
269         }
270         return 1;
271 }
272
273 /**
274  * bearer_find - locates bearer object with matching bearer name
275  */
276
277 static struct bearer *bearer_find(const char *name)
278 {
279         struct bearer *b_ptr;
280         u32 i;
281
282         for (i = 0, b_ptr = bearers; i < MAX_BEARERS; i++, b_ptr++) {
283                 if (b_ptr->active && (!strcmp(b_ptr->publ.name, name)))
284                         return b_ptr;
285         }
286         return 0;
287 }
288
289 /**
290  * bearer_find - locates bearer object with matching interface name
291  */
292
293 struct bearer *bearer_find_interface(const char *if_name)
294 {
295         struct bearer *b_ptr;
296         char *b_if_name;
297         u32 i;
298
299         for (i = 0, b_ptr = bearers; i < MAX_BEARERS; i++, b_ptr++) {
300                 if (!b_ptr->active)
301                         continue;
302                 b_if_name = strchr(b_ptr->publ.name, ':') + 1;
303                 if (!strcmp(b_if_name, if_name))
304                         return b_ptr;
305         }
306         return 0;
307 }
308
309 /**
310  * bearer_get_names - record names of bearers in buffer
311  */
312
313 struct sk_buff *bearer_get_names(void)
314 {
315         struct sk_buff *buf;
316         struct media *m_ptr;
317         struct bearer *b_ptr;
318         int i, j;
319
320         buf = cfg_reply_alloc(MAX_BEARERS * TLV_SPACE(TIPC_MAX_BEARER_NAME));
321         if (!buf)
322                 return NULL;
323
324         read_lock_bh(&net_lock);
325         for (i = 0, m_ptr = media_list; i < media_count; i++, m_ptr++) {
326                 for (j = 0; j < MAX_BEARERS; j++) {
327                         b_ptr = &bearers[j];
328                         if (b_ptr->active && (b_ptr->media == m_ptr)) {
329                                 cfg_append_tlv(buf, TIPC_TLV_BEARER_NAME, 
330                                                b_ptr->publ.name, 
331                                                strlen(b_ptr->publ.name) + 1);
332                         }
333                 }
334         }
335         read_unlock_bh(&net_lock);
336         return buf;
337 }
338
339 void bearer_add_dest(struct bearer *b_ptr, u32 dest)
340 {
341         nmap_add(&b_ptr->nodes, dest);
342         disc_update_link_req(b_ptr->link_req);
343         bcbearer_sort();
344 }
345
346 void bearer_remove_dest(struct bearer *b_ptr, u32 dest)
347 {
348         nmap_remove(&b_ptr->nodes, dest);
349         disc_update_link_req(b_ptr->link_req);
350         bcbearer_sort();
351 }
352
353 /*
354  * bearer_push(): Resolve bearer congestion. Force the waiting
355  * links to push out their unsent packets, one packet per link
356  * per iteration, until all packets are gone or congestion reoccurs.
357  * 'net_lock' is read_locked when this function is called
358  * bearer.lock must be taken before calling
359  * Returns binary true(1) ore false(0)
360  */
361 static int bearer_push(struct bearer *b_ptr)
362 {
363         u32 res = TIPC_OK;
364         struct link *ln, *tln;
365
366         if (b_ptr->publ.blocked)
367                 return 0;
368
369         while (!list_empty(&b_ptr->cong_links) && (res != PUSH_FAILED)) {
370                 list_for_each_entry_safe(ln, tln, &b_ptr->cong_links, link_list) {
371                         res = link_push_packet(ln);
372                         if (res == PUSH_FAILED)
373                                 break;
374                         if (res == PUSH_FINISHED)
375                                 list_move_tail(&ln->link_list, &b_ptr->links);
376                 }
377         }
378         return list_empty(&b_ptr->cong_links);
379 }
380
381 void bearer_lock_push(struct bearer *b_ptr)
382 {
383         int res;
384
385         spin_lock_bh(&b_ptr->publ.lock);
386         res = bearer_push(b_ptr);
387         spin_unlock_bh(&b_ptr->publ.lock);
388         if (res)
389                 bcbearer_push();
390 }
391
392
393 /*
394  * Interrupt enabling new requests after bearer congestion or blocking:    
395  * See bearer_send().   
396  */
397 void tipc_continue(struct tipc_bearer *tb_ptr)
398 {
399         struct bearer *b_ptr = (struct bearer *)tb_ptr;
400
401         spin_lock_bh(&b_ptr->publ.lock);
402         b_ptr->continue_count++;
403         if (!list_empty(&b_ptr->cong_links))
404                 k_signal((Handler)bearer_lock_push, (unsigned long)b_ptr);
405         b_ptr->publ.blocked = 0;
406         spin_unlock_bh(&b_ptr->publ.lock);
407 }
408
409 /*
410  * Schedule link for sending of messages after the bearer 
411  * has been deblocked by 'continue()'. This method is called 
412  * when somebody tries to send a message via this link while 
413  * the bearer is congested. 'net_lock' is in read_lock here
414  * bearer.lock is busy
415  */
416
417 static void bearer_schedule_unlocked(struct bearer *b_ptr, struct link *l_ptr)
418 {
419         list_move_tail(&l_ptr->link_list, &b_ptr->cong_links);
420 }
421
422 /*
423  * Schedule link for sending of messages after the bearer 
424  * has been deblocked by 'continue()'. This method is called 
425  * when somebody tries to send a message via this link while 
426  * the bearer is congested. 'net_lock' is in read_lock here,
427  * bearer.lock is free
428  */
429
430 void bearer_schedule(struct bearer *b_ptr, struct link *l_ptr)
431 {
432         spin_lock_bh(&b_ptr->publ.lock);
433         bearer_schedule_unlocked(b_ptr, l_ptr);
434         spin_unlock_bh(&b_ptr->publ.lock);
435 }
436
437
438 /*
439  * bearer_resolve_congestion(): Check if there is bearer congestion,
440  * and if there is, try to resolve it before returning.
441  * 'net_lock' is read_locked when this function is called
442  */
443 int bearer_resolve_congestion(struct bearer *b_ptr, struct link *l_ptr)
444 {
445         int res = 1;
446
447         if (list_empty(&b_ptr->cong_links))
448                 return 1;
449         spin_lock_bh(&b_ptr->publ.lock);
450         if (!bearer_push(b_ptr)) {
451                 bearer_schedule_unlocked(b_ptr, l_ptr);
452                 res = 0;
453         }
454         spin_unlock_bh(&b_ptr->publ.lock);
455         return res;
456 }
457
458
459 /**
460  * tipc_enable_bearer - enable bearer with the given name
461  */              
462
463 int tipc_enable_bearer(const char *name, u32 bcast_scope, u32 priority)
464 {
465         struct bearer *b_ptr;
466         struct media *m_ptr;
467         struct bearer_name b_name;
468         char addr_string[16];
469         u32 bearer_id;
470         u32 with_this_prio;
471         u32 i;
472         int res = -EINVAL;
473
474         if (tipc_mode != TIPC_NET_MODE)
475                 return -ENOPROTOOPT;
476         if (!bearer_name_validate(name, &b_name) ||
477             !addr_domain_valid(bcast_scope) ||
478             !in_scope(bcast_scope, tipc_own_addr) ||
479             (priority > TIPC_NUM_LINK_PRI))
480                 return -EINVAL;
481
482         write_lock_bh(&net_lock);
483         if (!bearers)
484                 goto failed;
485
486         m_ptr = media_find(b_name.media_name);
487         if (!m_ptr) {
488                 warn("No media <%s>\n", b_name.media_name);
489                 goto failed;
490         }
491         if (priority == TIPC_NUM_LINK_PRI)
492                 priority = m_ptr->priority;
493
494 restart:
495         bearer_id = MAX_BEARERS;
496         with_this_prio = 1;
497         for (i = MAX_BEARERS; i-- != 0; ) {
498                 if (!bearers[i].active) {
499                         bearer_id = i;
500                         continue;
501                 }
502                 if (!strcmp(name, bearers[i].publ.name)) {
503                         warn("Bearer <%s> already enabled\n", name);
504                         goto failed;
505                 }
506                 if ((bearers[i].priority == priority) &&
507                     (++with_this_prio > 2)) {
508                         if (priority-- == 0) {
509                                 warn("Third bearer <%s> with priority %u, unable to lower to %u\n",
510                                      name, priority + 1, priority);
511                                 goto failed;
512                         }
513                         warn("Third bearer <%s> with priority %u, lowering to %u\n",
514                              name, priority + 1, priority);
515                         goto restart;
516                 }
517         }
518         if (bearer_id >= MAX_BEARERS) {
519                 warn("Attempt to enable more than %d bearers\n", MAX_BEARERS);
520                 goto failed;
521         }
522
523         b_ptr = &bearers[bearer_id];
524         memset(b_ptr, 0, sizeof(struct bearer));
525
526         strcpy(b_ptr->publ.name, name);
527         res = m_ptr->enable_bearer(&b_ptr->publ);
528         if (res) {
529                 warn("Failed to enable bearer <%s>\n", name);
530                 goto failed;
531         }
532
533         b_ptr->identity = bearer_id;
534         b_ptr->media = m_ptr;
535         b_ptr->net_plane = bearer_id + 'A';
536         b_ptr->active = 1;
537         b_ptr->detect_scope = bcast_scope;
538         b_ptr->priority = priority;
539         INIT_LIST_HEAD(&b_ptr->cong_links);
540         INIT_LIST_HEAD(&b_ptr->links);
541         if (m_ptr->bcast) {
542                 b_ptr->link_req = disc_init_link_req(b_ptr, &m_ptr->bcast_addr,
543                                                      bcast_scope, 2);
544         }
545         b_ptr->publ.lock = SPIN_LOCK_UNLOCKED;
546         write_unlock_bh(&net_lock);
547         info("Enabled bearer <%s>, discovery domain %s\n",
548              name, addr_string_fill(addr_string, bcast_scope));
549         return 0;
550 failed:
551         write_unlock_bh(&net_lock);
552         return res;
553 }
554
555 /**
556  * tipc_block_bearer(): Block the bearer with the given name,
557  *                      and reset all its links
558  */
559
560 int tipc_block_bearer(const char *name)
561 {
562         struct bearer *b_ptr = 0;
563         struct link *l_ptr;
564         struct link *temp_l_ptr;
565
566         if (tipc_mode != TIPC_NET_MODE)
567                 return -ENOPROTOOPT;
568
569         read_lock_bh(&net_lock);
570         b_ptr = bearer_find(name);
571         if (!b_ptr) {
572                 warn("Attempt to block unknown bearer <%s>\n", name);
573                 read_unlock_bh(&net_lock);
574                 return -EINVAL;
575         }
576
577         spin_lock_bh(&b_ptr->publ.lock);
578         b_ptr->publ.blocked = 1;
579         list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) {
580                 struct node *n_ptr = l_ptr->owner;
581
582                 spin_lock_bh(&n_ptr->lock);
583                 link_reset(l_ptr);
584                 spin_unlock_bh(&n_ptr->lock);
585         }
586         spin_unlock_bh(&b_ptr->publ.lock);
587         read_unlock_bh(&net_lock);
588         info("Blocked bearer <%s>\n", name);
589         return TIPC_OK;
590 }
591
592 /**
593  * bearer_disable -
594  * 
595  * Note: This routine assumes caller holds net_lock.
596  */
597
598 static int bearer_disable(const char *name)
599 {
600         struct bearer *b_ptr;
601         struct link *l_ptr;
602         struct link *temp_l_ptr;
603
604         if (tipc_mode != TIPC_NET_MODE)
605                 return -ENOPROTOOPT;
606
607         b_ptr = bearer_find(name);
608         if (!b_ptr) {
609                 warn("Attempt to disable unknown bearer <%s>\n", name);
610                 return -EINVAL;
611         }
612
613         disc_stop_link_req(b_ptr->link_req);
614         spin_lock_bh(&b_ptr->publ.lock);
615         b_ptr->link_req = NULL;
616         b_ptr->publ.blocked = 1;
617         if (b_ptr->media->disable_bearer) {
618                 spin_unlock_bh(&b_ptr->publ.lock);
619                 write_unlock_bh(&net_lock);
620                 b_ptr->media->disable_bearer(&b_ptr->publ);
621                 write_lock_bh(&net_lock);
622                 spin_lock_bh(&b_ptr->publ.lock);
623         }
624         list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) {
625                 link_delete(l_ptr);
626         }
627         spin_unlock_bh(&b_ptr->publ.lock);
628         info("Disabled bearer <%s>\n", name);
629         memset(b_ptr, 0, sizeof(struct bearer));
630         return TIPC_OK;
631 }
632
633 int tipc_disable_bearer(const char *name)
634 {
635         int res;
636
637         write_lock_bh(&net_lock);
638         res = bearer_disable(name);
639         write_unlock_bh(&net_lock);
640         return res;
641 }
642
643
644
645 int bearer_init(void)
646 {
647         int res;
648
649         write_lock_bh(&net_lock);
650         bearers = kmalloc(MAX_BEARERS * sizeof(struct bearer), GFP_ATOMIC);
651         media_list = kmalloc(MAX_MEDIA * sizeof(struct media), GFP_ATOMIC);
652         if (bearers && media_list) {
653                 memset(bearers, 0, MAX_BEARERS * sizeof(struct bearer));
654                 memset(media_list, 0, MAX_MEDIA * sizeof(struct media));
655                 res = TIPC_OK;
656         } else {
657                 kfree(bearers);
658                 kfree(media_list);
659                 bearers = 0;
660                 media_list = 0;
661                 res = -ENOMEM;
662         }
663         write_unlock_bh(&net_lock);
664         return res;
665 }
666
667 void bearer_stop(void)
668 {
669         u32 i;
670
671         if (!bearers)
672                 return;
673
674         for (i = 0; i < MAX_BEARERS; i++) {
675                 if (bearers[i].active)
676                         bearers[i].publ.blocked = 1;
677         }
678         for (i = 0; i < MAX_BEARERS; i++) {
679                 if (bearers[i].active)
680                         bearer_disable(bearers[i].publ.name);
681         }
682         kfree(bearers);
683         kfree(media_list);
684         bearers = 0;
685         media_list = 0;
686         media_count = 0;
687 }
688
689