]> git.ipfire.org Git - thirdparty/bird.git/blob - nest/proto.c
Merge commit 'origin/master' into socket
[thirdparty/bird.git] / nest / proto.c
1 /*
2 * BIRD -- Protocols
3 *
4 * (c) 1998--2000 Martin Mares <mj@ucw.cz>
5 *
6 * Can be freely distributed and used under the terms of the GNU GPL.
7 */
8
9 #undef LOCAL_DEBUG
10
11 #include "nest/bird.h"
12 #include "nest/protocol.h"
13 #include "lib/resource.h"
14 #include "lib/lists.h"
15 #include "lib/event.h"
16 #include "lib/string.h"
17 #include "conf/conf.h"
18 #include "nest/route.h"
19 #include "nest/iface.h"
20 #include "nest/cli.h"
21 #include "filter/filter.h"
22
23 pool *proto_pool;
24
25 static list protocol_list;
26 static list proto_list;
27
28 #define PD(pr, msg, args...) do { if (pr->debug & D_STATES) { log(L_TRACE "%s: " msg, pr->name , ## args); } } while(0)
29
30 list active_proto_list;
31 static list inactive_proto_list;
32 static list initial_proto_list;
33 static list flush_proto_list;
34 static struct proto *initial_device_proto;
35
36 static event *proto_flush_event;
37 static timer *proto_shutdown_timer;
38
39 static char *p_states[] = { "DOWN", "START", "UP", "STOP" };
40 static char *c_states[] = { "HUNGRY", "FEEDING", "HAPPY", "FLUSHING" };
41
42 static void proto_flush_loop(void *);
43 static void proto_shutdown_loop(struct timer *);
44 static void proto_rethink_goal(struct proto *p);
45 static char *proto_state_name(struct proto *p);
46
47 static void
48 proto_enqueue(list *l, struct proto *p)
49 {
50 add_tail(l, &p->n);
51 }
52
53 static void
54 proto_relink(struct proto *p)
55 {
56 list *l = NULL;
57
58 if (p->debug & D_STATES)
59 {
60 char *name = proto_state_name(p);
61 if (name != p->last_state_name_announced)
62 {
63 p->last_state_name_announced = name;
64 PD(p, "State changed to %s", proto_state_name(p));
65 }
66 }
67 else
68 p->last_state_name_announced = NULL;
69 rem_node(&p->n);
70 switch (p->core_state)
71 {
72 case FS_HUNGRY:
73 l = &inactive_proto_list;
74 break;
75 case FS_FEEDING:
76 case FS_HAPPY:
77 l = &active_proto_list;
78 break;
79 case FS_FLUSHING:
80 l = &flush_proto_list;
81 break;
82 default:
83 ASSERT(0);
84 }
85 proto_enqueue(l, p);
86 }
87
88 /**
89 * proto_new - create a new protocol instance
90 * @c: protocol configuration
91 * @size: size of protocol data structure (each protocol instance is represented by
92 * a structure starting with generic part [struct &proto] and continued
93 * with data specific to the protocol)
94 *
95 * When a new configuration has been read in, the core code starts
96 * initializing all the protocol instances configured by calling their
97 * init() hooks with the corresponding instance configuration. The initialization
98 * code of the protocol is expected to create a new instance according to the
99 * configuration by calling this function and then modifying the default settings
100 * to values wanted by the protocol.
101 */
102 void *
103 proto_new(struct proto_config *c, unsigned size)
104 {
105 struct protocol *pr = c->protocol;
106 struct proto *p = mb_allocz(proto_pool, size);
107
108 p->cf = c;
109 p->debug = c->debug;
110 p->mrtdump = c->mrtdump;
111 p->name = c->name;
112 p->preference = c->preference;
113 p->disabled = c->disabled;
114 p->proto = pr;
115 p->table = c->table->table;
116 p->hash_key = random_u32();
117 c->proto = p;
118 return p;
119 }
120
121 static void
122 proto_init_instance(struct proto *p)
123 {
124 /* Here we cannot use p->cf->name since it won't survive reconfiguration */
125 p->pool = rp_new(proto_pool, p->proto->name);
126 p->attn = ev_new(p->pool);
127 p->attn->data = p;
128
129 if (! p->proto->multitable)
130 rt_lock_table(p->table);
131 }
132
133 extern pool *rt_table_pool;
134 /**
135 * proto_add_announce_hook - connect protocol to a routing table
136 * @p: protocol instance
137 * @t: routing table to connect to
138 * @stats: per-table protocol statistics
139 *
140 * This function creates a connection between the protocol instance @p
141 * and the routing table @t, making the protocol hear all changes in
142 * the table.
143 *
144 * The announce hook is linked in the protocol ahook list and, if the
145 * protocol accepts routes, also in the table ahook list. Announce
146 * hooks are allocated from the routing table resource pool, they are
147 * unlinked from the table ahook list after the protocol went down,
148 * (in proto_schedule_flush()) and they are automatically freed after the
149 * protocol is flushed (in proto_fell_down()).
150 *
151 * Unless you want to listen to multiple routing tables (as the Pipe
152 * protocol does), you needn't to worry about this function since the
153 * connection to the protocol's primary routing table is initialized
154 * automatically by the core code.
155 */
156 struct announce_hook *
157 proto_add_announce_hook(struct proto *p, struct rtable *t, struct proto_stats *stats)
158 {
159 struct announce_hook *h;
160
161 DBG("Connecting protocol %s to table %s\n", p->name, t->name);
162 PD(p, "Connected to table %s", t->name);
163
164 h = mb_allocz(rt_table_pool, sizeof(struct announce_hook));
165 h->table = t;
166 h->proto = p;
167 h->stats = stats;
168
169 h->next = p->ahooks;
170 p->ahooks = h;
171
172 if (p->rt_notify)
173 add_tail(&t->hooks, &h->n);
174 return h;
175 }
176
177 /**
178 * proto_find_announce_hook - find announce hooks
179 * @p: protocol instance
180 * @t: routing table
181 *
182 * Returns pointer to announce hook or NULL
183 */
184 struct announce_hook *
185 proto_find_announce_hook(struct proto *p, struct rtable *t)
186 {
187 struct announce_hook *a;
188
189 for (a = p->ahooks; a; a = a->next)
190 if (a->table == t)
191 return a;
192
193 return NULL;
194 }
195
196 static void
197 proto_unlink_ahooks(struct proto *p)
198 {
199 struct announce_hook *h;
200
201 if (p->rt_notify)
202 for(h=p->ahooks; h; h=h->next)
203 rem_node(&h->n);
204 }
205
206 static void
207 proto_free_ahooks(struct proto *p)
208 {
209 struct announce_hook *h, *hn;
210
211 for(h = p->ahooks; h; h = hn)
212 {
213 hn = h->next;
214 mb_free(h);
215 }
216
217 p->ahooks = NULL;
218 p->main_ahook = NULL;
219 }
220
221
222 /**
223 * proto_config_new - create a new protocol configuration
224 * @pr: protocol the configuration will belong to
225 * @size: size of the structure including generic data
226 * @class: SYM_PROTO or SYM_TEMPLATE
227 *
228 * Whenever the configuration file says that a new instance
229 * of a routing protocol should be created, the parser calls
230 * proto_config_new() to create a configuration entry for this
231 * instance (a structure staring with the &proto_config header
232 * containing all the generic items followed by protocol-specific
233 * ones). Also, the configuration entry gets added to the list
234 * of protocol instances kept in the configuration.
235 *
236 * The function is also used to create protocol templates (when class
237 * SYM_TEMPLATE is specified), the only difference is that templates
238 * are not added to the list of protocol instances and therefore not
239 * initialized during protos_commit()).
240 */
241 void *
242 proto_config_new(struct protocol *pr, unsigned size, int class)
243 {
244 struct proto_config *c = cfg_allocz(size);
245
246 if (class == SYM_PROTO)
247 add_tail(&new_config->protos, &c->n);
248 c->global = new_config;
249 c->protocol = pr;
250 c->name = pr->name;
251 c->preference = pr->preference;
252 c->class = class;
253 c->out_filter = FILTER_REJECT;
254 c->table = c->global->master_rtc;
255 c->debug = new_config->proto_default_debug;
256 c->mrtdump = new_config->proto_default_mrtdump;
257 return c;
258 }
259
260 /**
261 * proto_copy_config - copy a protocol configuration
262 * @dest: destination protocol configuration
263 * @src: source protocol configuration
264 *
265 * Whenever a new instance of a routing protocol is created from the
266 * template, proto_copy_config() is called to copy a content of
267 * the source protocol configuration to the new protocol configuration.
268 * Name, class and a node in protos list of @dest are kept intact.
269 * copy_config() protocol hook is used to copy protocol-specific data.
270 */
271 void
272 proto_copy_config(struct proto_config *dest, struct proto_config *src)
273 {
274 node old_node;
275 int old_class;
276 char *old_name;
277
278 if (dest->protocol != src->protocol)
279 cf_error("Can't copy configuration from a different protocol type");
280
281 if (dest->protocol->copy_config == NULL)
282 cf_error("Inheriting configuration for %s is not supported", src->protocol->name);
283
284 DBG("Copying configuration from %s to %s\n", src->name, dest->name);
285
286 /*
287 * Copy struct proto_config here. Keep original node, class and name.
288 * protocol-specific config copy is handled by protocol copy_config() hook
289 */
290
291 old_node = dest->n;
292 old_class = dest->class;
293 old_name = dest->name;
294
295 memcpy(dest, src, sizeof(struct proto_config));
296
297 dest->n = old_node;
298 dest->class = old_class;
299 dest->name = old_name;
300
301 dest->protocol->copy_config(dest, src);
302 }
303
304 /**
305 * protos_preconfig - pre-configuration processing
306 * @c: new configuration
307 *
308 * This function calls the preconfig() hooks of all routing
309 * protocols available to prepare them for reading of the new
310 * configuration.
311 */
312 void
313 protos_preconfig(struct config *c)
314 {
315 struct protocol *p;
316
317 init_list(&c->protos);
318 DBG("Protocol preconfig:");
319 WALK_LIST(p, protocol_list)
320 {
321 DBG(" %s", p->name);
322 p->name_counter = 0;
323 if (p->preconfig)
324 p->preconfig(p, c);
325 }
326 DBG("\n");
327 }
328
329 /**
330 * protos_postconfig - post-configuration processing
331 * @c: new configuration
332 *
333 * This function calls the postconfig() hooks of all protocol
334 * instances specified in configuration @c. The hooks are not
335 * called for protocol templates.
336 */
337 void
338 protos_postconfig(struct config *c)
339 {
340 struct proto_config *x;
341 struct protocol *p;
342
343 DBG("Protocol postconfig:");
344 WALK_LIST(x, c->protos)
345 {
346 DBG(" %s", x->name);
347
348 p = x->protocol;
349 if (p->postconfig)
350 p->postconfig(x);
351 }
352 DBG("\n");
353 }
354
355 extern struct protocol proto_unix_iface;
356
357 static struct proto *
358 proto_init(struct proto_config *c)
359 {
360 struct protocol *p = c->protocol;
361 struct proto *q = p->init(c);
362
363 q->proto_state = PS_DOWN;
364 q->core_state = FS_HUNGRY;
365 q->last_state_change = now;
366
367 proto_enqueue(&initial_proto_list, q);
368 if (p == &proto_unix_iface)
369 initial_device_proto = q;
370
371 add_tail(&proto_list, &q->glob_node);
372 PD(q, "Initializing%s", q->disabled ? " [disabled]" : "");
373 return q;
374 }
375
376 int proto_reconfig_type; /* Hack to propagate type info to pipe reconfigure hook */
377
378 static int
379 proto_reconfigure(struct proto *p, struct proto_config *oc, struct proto_config *nc, int type)
380 {
381 struct announce_hook *ah = p->main_ahook;
382 /* If the protocol is DOWN, we just restart it */
383 if (p->proto_state == PS_DOWN)
384 return 0;
385
386 /* If there is a too big change in core attributes, ... */
387 if ((nc->protocol != oc->protocol) ||
388 (nc->disabled != p->disabled) ||
389 (nc->table->table != oc->table->table))
390 return 0;
391
392 p->debug = nc->debug;
393 p->mrtdump = nc->mrtdump;
394 proto_reconfig_type = type;
395
396 /* Execute protocol specific reconfigure hook */
397 if (! (p->proto->reconfigure && p->proto->reconfigure(p, nc)))
398 return 0;
399
400 DBG("\t%s: same\n", oc->name);
401 PD(p, "Reconfigured");
402 p->cf = nc;
403 p->name = nc->name;
404 p->preference = nc->preference;
405
406
407 /* Multitable protocols handle rest in their reconfigure hooks */
408 if (p->proto->multitable)
409 return 1;
410
411 /* Update filters and limits in the main announce hook
412 Note that this also resets limit state */
413 if (ah)
414 {
415 ah->in_filter = nc->in_filter;
416 ah->out_filter = nc->out_filter;
417 ah->rx_limit = nc->rx_limit;
418 ah->in_limit = nc->in_limit;
419 ah->out_limit = nc->out_limit;
420 ah->in_keep_filtered = nc->in_keep_filtered;
421
422 if (p->proto_state == PS_UP) /* Recheck export/import/receive limit */
423 {
424 struct proto_stats *stats = ah->stats;
425 struct proto_limit *l = ah->in_limit;
426 u32 all_routes = stats->imp_routes + stats->filt_routes;
427
428 if (l && (stats->imp_routes >= l->limit)) proto_notify_limit(ah, l, PLD_IN, stats->imp_routes);
429
430 l = ah->rx_limit;
431
432 if (l && ( all_routes >= l->limit)) proto_notify_limit(ah, l, PLD_RX, all_routes );
433
434 l = ah->out_limit;
435
436 if (l && ( stats->exp_routes >= l->limit)) proto_notify_limit(ah, l, PLD_OUT, stats->exp_routes);
437 }
438 }
439
440 /* Update routes when filters changed. If the protocol in not UP,
441 it has no routes and we can ignore such changes */
442 if ((p->proto_state != PS_UP) || (type == RECONFIG_SOFT))
443 return 1;
444
445 int import_changed = ! filter_same(nc->in_filter, oc->in_filter);
446 int export_changed = ! filter_same(nc->out_filter, oc->out_filter);
447
448 /* We treat a change in preferences by reimporting routes */
449 if (nc->preference != oc->preference)
450 import_changed = 1;
451
452 if (import_changed || export_changed)
453 log(L_INFO "Reloading protocol %s", p->name);
454
455 /* If import filter changed, call reload hook */
456 if (import_changed && ! (p->reload_routes && p->reload_routes(p)))
457 {
458 /* Now, the protocol is reconfigured. But route reload failed
459 and we have to do regular protocol restart. */
460 log(L_INFO "Restarting protocol %s", p->name);
461 p->disabled = 1;
462 p->down_code = PDC_CF_RESTART;
463 proto_rethink_goal(p);
464 p->disabled = 0;
465 proto_rethink_goal(p);
466 return 1;
467 }
468
469 if (export_changed)
470 proto_request_feeding(p);
471
472 return 1;
473 }
474
475 /**
476 * protos_commit - commit new protocol configuration
477 * @new: new configuration
478 * @old: old configuration or %NULL if it's boot time config
479 * @force_reconfig: force restart of all protocols (used for example
480 * when the router ID changes)
481 * @type: type of reconfiguration (RECONFIG_SOFT or RECONFIG_HARD)
482 *
483 * Scan differences between @old and @new configuration and adjust all
484 * protocol instances to conform to the new configuration.
485 *
486 * When a protocol exists in the new configuration, but it doesn't in the
487 * original one, it's immediately started. When a collision with the other
488 * running protocol would arise, the new protocol will be temporarily stopped
489 * by the locking mechanism.
490 *
491 * When a protocol exists in the old configuration, but it doesn't in the
492 * new one, it's shut down and deleted after the shutdown completes.
493 *
494 * When a protocol exists in both configurations, the core decides
495 * whether it's possible to reconfigure it dynamically - it checks all
496 * the core properties of the protocol (changes in filters are ignored
497 * if type is RECONFIG_SOFT) and if they match, it asks the
498 * reconfigure() hook of the protocol to see if the protocol is able
499 * to switch to the new configuration. If it isn't possible, the
500 * protocol is shut down and a new instance is started with the new
501 * configuration after the shutdown is completed.
502 */
503 void
504 protos_commit(struct config *new, struct config *old, int force_reconfig, int type)
505 {
506 struct proto_config *oc, *nc;
507 struct proto *p, *n;
508 struct symbol *sym;
509
510 DBG("protos_commit:\n");
511 if (old)
512 {
513 WALK_LIST(oc, old->protos)
514 {
515 p = oc->proto;
516 sym = cf_find_symbol(oc->name);
517 if (sym && sym->class == SYM_PROTO && !new->shutdown)
518 {
519 /* Found match, let's check if we can smoothly switch to new configuration */
520 /* No need to check description */
521 nc = sym->def;
522 nc->proto = p;
523
524 /* We will try to reconfigure protocol p */
525 if (! force_reconfig && proto_reconfigure(p, oc, nc, type))
526 continue;
527
528 /* Unsuccessful, we will restart it */
529 if (!p->disabled && !nc->disabled)
530 log(L_INFO "Restarting protocol %s", p->name);
531 else if (p->disabled && !nc->disabled)
532 log(L_INFO "Enabling protocol %s", p->name);
533 else if (!p->disabled && nc->disabled)
534 log(L_INFO "Disabling protocol %s", p->name);
535
536 p->down_code = nc->disabled ? PDC_CF_DISABLE : PDC_CF_RESTART;
537 p->cf_new = nc;
538 }
539 else if (!new->shutdown)
540 {
541 log(L_INFO "Removing protocol %s", p->name);
542 p->down_code = PDC_CF_REMOVE;
543 p->cf_new = NULL;
544 }
545 else /* global shutdown */
546 {
547 p->down_code = PDC_CMD_SHUTDOWN;
548 p->cf_new = NULL;
549 }
550
551 p->reconfiguring = 1;
552 config_add_obstacle(old);
553 proto_rethink_goal(p);
554 }
555 }
556
557 WALK_LIST(nc, new->protos)
558 if (!nc->proto)
559 {
560 if (old) /* Not a first-time configuration */
561 log(L_INFO "Adding protocol %s", nc->name);
562 proto_init(nc);
563 }
564 DBG("\tdone\n");
565
566 DBG("Protocol start\n");
567
568 /* Start device protocol first */
569 if (initial_device_proto)
570 {
571 proto_rethink_goal(initial_device_proto);
572 initial_device_proto = NULL;
573 }
574
575 /* Determine router ID for the first time - it has to be here and not in
576 global_commit() because it is postponed after start of device protocol */
577 if (!config->router_id)
578 {
579 config->router_id = if_choose_router_id(config->router_id_from, 0);
580 if (!config->router_id)
581 die("Cannot determine router ID, please configure it manually");
582 }
583
584 /* Start all other protocols */
585 WALK_LIST_DELSAFE(p, n, initial_proto_list)
586 proto_rethink_goal(p);
587 }
588
589 static void
590 proto_rethink_goal(struct proto *p)
591 {
592 struct protocol *q;
593
594 if (p->reconfiguring && p->core_state == FS_HUNGRY && p->proto_state == PS_DOWN)
595 {
596 struct proto_config *nc = p->cf_new;
597 DBG("%s has shut down for reconfiguration\n", p->name);
598 config_del_obstacle(p->cf->global);
599 rem_node(&p->n);
600 rem_node(&p->glob_node);
601 mb_free(p);
602 if (!nc)
603 return;
604 p = proto_init(nc);
605 }
606
607 /* Determine what state we want to reach */
608 if (p->disabled || p->reconfiguring)
609 {
610 p->core_goal = FS_HUNGRY;
611 if (p->core_state == FS_HUNGRY && p->proto_state == PS_DOWN)
612 return;
613 }
614 else
615 {
616 p->core_goal = FS_HAPPY;
617 if (p->core_state == FS_HAPPY && p->proto_state == PS_UP)
618 return;
619 }
620
621 q = p->proto;
622 if (p->core_goal == FS_HAPPY) /* Going up */
623 {
624 if (p->core_state == FS_HUNGRY && p->proto_state == PS_DOWN)
625 {
626 DBG("Kicking %s up\n", p->name);
627 PD(p, "Starting");
628 proto_init_instance(p);
629 proto_notify_state(p, (q->start ? q->start(p) : PS_UP));
630 }
631 }
632 else /* Going down */
633 {
634 if (p->proto_state == PS_START || p->proto_state == PS_UP)
635 {
636 DBG("Kicking %s down\n", p->name);
637 PD(p, "Shutting down");
638 proto_notify_state(p, (q->shutdown ? q->shutdown(p) : PS_DOWN));
639 }
640 }
641 }
642
643 /**
644 * protos_dump_all - dump status of all protocols
645 *
646 * This function dumps status of all existing protocol instances to the
647 * debug output. It involves printing of general status information
648 * such as protocol states, its position on the protocol lists
649 * and also calling of a dump() hook of the protocol to print
650 * the internals.
651 */
652 void
653 protos_dump_all(void)
654 {
655 struct proto *p;
656 struct announce_hook *a;
657
658 debug("Protocols:\n");
659
660 WALK_LIST(p, active_proto_list)
661 {
662 debug(" protocol %s state %s/%s\n", p->name,
663 p_states[p->proto_state], c_states[p->core_state]);
664 for (a = p->ahooks; a; a = a->next)
665 {
666 debug("\tTABLE %s\n", a->table->name);
667 if (a->in_filter)
668 debug("\tInput filter: %s\n", filter_name(a->in_filter));
669 if (a->out_filter != FILTER_REJECT)
670 debug("\tOutput filter: %s\n", filter_name(a->out_filter));
671 }
672 if (p->disabled)
673 debug("\tDISABLED\n");
674 else if (p->proto->dump)
675 p->proto->dump(p);
676 }
677 WALK_LIST(p, inactive_proto_list)
678 debug(" inactive %s: state %s/%s\n", p->name, p_states[p->proto_state], c_states[p->core_state]);
679 WALK_LIST(p, initial_proto_list)
680 debug(" initial %s\n", p->name);
681 WALK_LIST(p, flush_proto_list)
682 debug(" flushing %s\n", p->name);
683 }
684
685 /**
686 * proto_build - make a single protocol available
687 * @p: the protocol
688 *
689 * After the platform specific initialization code uses protos_build()
690 * to add all the standard protocols, it should call proto_build() for
691 * all platform specific protocols to inform the core that they exist.
692 */
693 void
694 proto_build(struct protocol *p)
695 {
696 add_tail(&protocol_list, &p->n);
697 if (p->attr_class)
698 {
699 ASSERT(!attr_class_to_protocol[p->attr_class]);
700 attr_class_to_protocol[p->attr_class] = p;
701 }
702 }
703
704 /* FIXME: convert this call to some protocol hook */
705 extern void bfd_init_all(void);
706
707 /**
708 * protos_build - build a protocol list
709 *
710 * This function is called during BIRD startup to insert
711 * all standard protocols to the global protocol list. Insertion
712 * of platform specific protocols (such as the kernel syncer)
713 * is in the domain of competence of the platform dependent
714 * startup code.
715 */
716 void
717 protos_build(void)
718 {
719 init_list(&protocol_list);
720 init_list(&proto_list);
721 init_list(&active_proto_list);
722 init_list(&inactive_proto_list);
723 init_list(&initial_proto_list);
724 init_list(&flush_proto_list);
725 proto_build(&proto_device);
726 #ifdef CONFIG_RADV
727 proto_build(&proto_radv);
728 #endif
729 #ifdef CONFIG_RIP
730 proto_build(&proto_rip);
731 #endif
732 #ifdef CONFIG_STATIC
733 proto_build(&proto_static);
734 #endif
735 #ifdef CONFIG_OSPF
736 proto_build(&proto_ospf);
737 #endif
738 #ifdef CONFIG_PIPE
739 proto_build(&proto_pipe);
740 #endif
741 #ifdef CONFIG_BGP
742 proto_build(&proto_bgp);
743 #endif
744 #ifdef CONFIG_BFD
745 proto_build(&proto_bfd);
746 bfd_init_all();
747 #endif
748
749 proto_pool = rp_new(&root_pool, "Protocols");
750 proto_flush_event = ev_new(proto_pool);
751 proto_flush_event->hook = proto_flush_loop;
752 proto_shutdown_timer = tm_new(proto_pool);
753 proto_shutdown_timer->hook = proto_shutdown_loop;
754 }
755
756 static void
757 proto_fell_down(struct proto *p)
758 {
759 DBG("Protocol %s down\n", p->name);
760
761 u32 all_routes = p->stats.imp_routes + p->stats.filt_routes;
762 if (all_routes != 0)
763 log(L_ERR "Protocol %s is down but still has %d routes", p->name, all_routes);
764
765 bzero(&p->stats, sizeof(struct proto_stats));
766 proto_free_ahooks(p);
767
768 if (! p->proto->multitable)
769 rt_unlock_table(p->table);
770
771 if (p->proto->cleanup)
772 p->proto->cleanup(p);
773
774 proto_rethink_goal(p);
775 }
776
777 static void
778 proto_feed_more(void *P)
779 {
780 struct proto *p = P;
781
782 if (p->core_state != FS_FEEDING)
783 return;
784
785 DBG("Feeding protocol %s continued\n", p->name);
786 if (rt_feed_baby(p))
787 {
788 p->core_state = FS_HAPPY;
789 proto_relink(p);
790 DBG("Protocol %s up and running\n", p->name);
791 }
792 else
793 {
794 p->attn->hook = proto_feed_more;
795 ev_schedule(p->attn); /* Will continue later... */
796 }
797 }
798
799 static void
800 proto_feed_initial(void *P)
801 {
802 struct proto *p = P;
803
804 if (p->core_state != FS_FEEDING)
805 return;
806
807 DBG("Feeding protocol %s\n", p->name);
808
809 if_feed_baby(p);
810 proto_feed_more(P);
811 }
812
813 static void
814 proto_schedule_feed(struct proto *p, int initial)
815 {
816 DBG("%s: Scheduling meal\n", p->name);
817 p->core_state = FS_FEEDING;
818 p->refeeding = !initial;
819
820 /* FIXME: This should be changed for better support of multitable protos */
821 if (!initial)
822 {
823 struct announce_hook *ah;
824 for (ah = p->ahooks; ah; ah = ah->next)
825 proto_reset_limit(ah->out_limit);
826
827 /* Hack: reset exp_routes during refeed, and do not decrease it later */
828 p->stats.exp_routes = 0;
829 }
830
831 /* Connect protocol to routing table */
832 if (initial && !p->proto->multitable)
833 {
834 p->main_source = rt_get_source(p, 0);
835 rt_lock_source(p->main_source);
836
837 p->main_ahook = proto_add_announce_hook(p, p->table, &p->stats);
838 p->main_ahook->in_filter = p->cf->in_filter;
839 p->main_ahook->out_filter = p->cf->out_filter;
840 p->main_ahook->rx_limit = p->cf->rx_limit;
841 p->main_ahook->in_limit = p->cf->in_limit;
842 p->main_ahook->out_limit = p->cf->out_limit;
843 p->main_ahook->in_keep_filtered = p->cf->in_keep_filtered;
844
845 proto_reset_limit(p->main_ahook->rx_limit);
846 proto_reset_limit(p->main_ahook->in_limit);
847 proto_reset_limit(p->main_ahook->out_limit);
848 }
849
850 proto_relink(p);
851 p->attn->hook = initial ? proto_feed_initial : proto_feed_more;
852 ev_schedule(p->attn);
853 }
854
855 /*
856 * Flushing loop is responsible for flushing routes and protocols
857 * after they went down. It runs in proto_flush_event. At the start of
858 * one round, protocols waiting to flush are marked in
859 * proto_schedule_flush_loop(). At the end of the round (when routing
860 * table flush is complete), marked protocols are flushed and a next
861 * round may start.
862 */
863
864 static int flush_loop_state; /* 1 -> running */
865
866 static void
867 proto_schedule_flush_loop(void)
868 {
869 struct proto *p;
870 struct announce_hook *h;
871
872 if (flush_loop_state)
873 return;
874 flush_loop_state = 1;
875
876 WALK_LIST(p, flush_proto_list)
877 {
878 p->flushing = 1;
879 for (h=p->ahooks; h; h=h->next)
880 h->table->prune_state = 1;
881 }
882
883 ev_schedule(proto_flush_event);
884 }
885
886 static void
887 proto_flush_loop(void *unused UNUSED)
888 {
889 struct proto *p;
890
891 if (! rt_prune_loop())
892 {
893 /* Rtable pruning is not finished */
894 ev_schedule(proto_flush_event);
895 return;
896 }
897
898 rt_prune_sources();
899
900 again:
901 WALK_LIST(p, flush_proto_list)
902 if (p->flushing)
903 {
904 /* This will flush interfaces in the same manner
905 like rt_prune_all() flushes routes */
906 if (p->proto == &proto_unix_iface)
907 if_flush_ifaces(p);
908
909 DBG("Flushing protocol %s\n", p->name);
910 p->flushing = 0;
911 p->core_state = FS_HUNGRY;
912 proto_relink(p);
913 if (p->proto_state == PS_DOWN)
914 proto_fell_down(p);
915 goto again;
916 }
917
918 /* This round finished, perhaps there will be another one */
919 flush_loop_state = 0;
920 if (!EMPTY_LIST(flush_proto_list))
921 proto_schedule_flush_loop();
922 }
923
924 static void
925 proto_schedule_flush(struct proto *p)
926 {
927 /* Need to abort feeding */
928 if (p->core_state == FS_FEEDING)
929 rt_feed_baby_abort(p);
930
931 DBG("%s: Scheduling flush\n", p->name);
932 p->core_state = FS_FLUSHING;
933 proto_relink(p);
934 proto_unlink_ahooks(p);
935 proto_schedule_flush_loop();
936 }
937
938 /* Temporary hack to propagate restart to BGP */
939 int proto_restart;
940
941 static void
942 proto_shutdown_loop(struct timer *t UNUSED)
943 {
944 struct proto *p, *p_next;
945
946 WALK_LIST_DELSAFE(p, p_next, active_proto_list)
947 if (p->down_sched)
948 {
949 proto_restart = (p->down_sched == PDS_RESTART);
950
951 p->disabled = 1;
952 proto_rethink_goal(p);
953 if (proto_restart)
954 {
955 p->disabled = 0;
956 proto_rethink_goal(p);
957 }
958 }
959 }
960
961 static inline void
962 proto_schedule_down(struct proto *p, byte restart, byte code)
963 {
964 /* Does not work for other states (even PS_START) */
965 ASSERT(p->proto_state == PS_UP);
966
967 /* Scheduled restart may change to shutdown, but not otherwise */
968 if (p->down_sched == PDS_DISABLE)
969 return;
970
971 p->down_sched = restart ? PDS_RESTART : PDS_DISABLE;
972 p->down_code = code;
973 tm_start_max(proto_shutdown_timer, restart ? 2 : 0);
974 }
975
976
977 /**
978 * proto_request_feeding - request feeding routes to the protocol
979 * @p: given protocol
980 *
981 * Sometimes it is needed to send again all routes to the
982 * protocol. This is called feeding and can be requested by this
983 * function. This would cause protocol core state transition
984 * to FS_FEEDING (during feeding) and when completed, it will
985 * switch back to FS_HAPPY. This function can be called even
986 * when feeding is already running, in that case it is restarted.
987 */
988 void
989 proto_request_feeding(struct proto *p)
990 {
991 ASSERT(p->proto_state == PS_UP);
992
993 /* If we are already feeding, we want to restart it */
994 if (p->core_state == FS_FEEDING)
995 {
996 /* Unless feeding is in initial state */
997 if (p->attn->hook == proto_feed_initial)
998 return;
999
1000 rt_feed_baby_abort(p);
1001 }
1002
1003 proto_schedule_feed(p, 0);
1004 }
1005
1006 static const char *
1007 proto_limit_name(struct proto_limit *l)
1008 {
1009 const char *actions[] = {
1010 [PLA_WARN] = "warn",
1011 [PLA_BLOCK] = "block",
1012 [PLA_RESTART] = "restart",
1013 [PLA_DISABLE] = "disable",
1014 };
1015
1016 return actions[l->action];
1017 }
1018
1019 /**
1020 * proto_notify_limit: notify about limit hit and take appropriate action
1021 * @ah: announce hook
1022 * @l: limit being hit
1023 * @dir: limit direction (PLD_*)
1024 * @rt_count: the number of routes
1025 *
1026 * The function is called by the route processing core when limit @l
1027 * is breached. It activates the limit and tooks appropriate action
1028 * according to @l->action.
1029 */
1030 void
1031 proto_notify_limit(struct announce_hook *ah, struct proto_limit *l, int dir, u32 rt_count)
1032 {
1033 const char *dir_name[PLD_MAX] = { "receive", "import" , "export" };
1034 const byte dir_down[PLD_MAX] = { PDC_RX_LIMIT_HIT, PDC_IN_LIMIT_HIT, PDC_OUT_LIMIT_HIT };
1035 struct proto *p = ah->proto;
1036
1037 if (l->state == PLS_BLOCKED)
1038 return;
1039
1040 /* For warning action, we want the log message every time we hit the limit */
1041 if (!l->state || ((l->action == PLA_WARN) && (rt_count == l->limit)))
1042 log(L_WARN "Protocol %s hits route %s limit (%d), action: %s",
1043 p->name, dir_name[dir], l->limit, proto_limit_name(l));
1044
1045 switch (l->action)
1046 {
1047 case PLA_WARN:
1048 l->state = PLS_ACTIVE;
1049 break;
1050
1051 case PLA_BLOCK:
1052 l->state = PLS_BLOCKED;
1053 break;
1054
1055 case PLA_RESTART:
1056 case PLA_DISABLE:
1057 l->state = PLS_BLOCKED;
1058 proto_schedule_down(p, l->action == PLA_RESTART, dir_down[dir]);
1059 break;
1060 }
1061 }
1062
1063 /**
1064 * proto_notify_state - notify core about protocol state change
1065 * @p: protocol the state of which has changed
1066 * @ps: the new status
1067 *
1068 * Whenever a state of a protocol changes due to some event internal
1069 * to the protocol (i.e., not inside a start() or shutdown() hook),
1070 * it should immediately notify the core about the change by calling
1071 * proto_notify_state() which will write the new state to the &proto
1072 * structure and take all the actions necessary to adapt to the new
1073 * state. State change to PS_DOWN immediately frees resources of protocol
1074 * and might execute start callback of protocol; therefore,
1075 * it should be used at tail positions of protocol callbacks.
1076 */
1077 void
1078 proto_notify_state(struct proto *p, unsigned ps)
1079 {
1080 unsigned ops = p->proto_state;
1081 unsigned cs = p->core_state;
1082
1083 DBG("%s reporting state transition %s/%s -> */%s\n", p->name, c_states[cs], p_states[ops], p_states[ps]);
1084 if (ops == ps)
1085 return;
1086
1087 p->proto_state = ps;
1088 p->last_state_change = now;
1089
1090 switch (ps)
1091 {
1092 case PS_DOWN:
1093 p->down_code = 0;
1094 p->down_sched = 0;
1095 if ((cs == FS_FEEDING) || (cs == FS_HAPPY))
1096 proto_schedule_flush(p);
1097
1098 if (p->proto->multitable)
1099 {
1100 rt_unlock_source(p->main_source);
1101 p->main_source = NULL;
1102 }
1103
1104 neigh_prune(); // FIXME convert neighbors to resource?
1105 rfree(p->pool);
1106 p->pool = NULL;
1107
1108 if (cs == FS_HUNGRY) /* Shutdown finished */
1109 {
1110 proto_fell_down(p);
1111 return; /* The protocol might have ceased to exist */
1112 }
1113 break;
1114 case PS_START:
1115 ASSERT(ops == PS_DOWN);
1116 ASSERT(cs == FS_HUNGRY);
1117 break;
1118 case PS_UP:
1119 ASSERT(ops == PS_DOWN || ops == PS_START);
1120 ASSERT(cs == FS_HUNGRY);
1121 proto_schedule_feed(p, 1);
1122 break;
1123 case PS_STOP:
1124 p->down_sched = 0;
1125 if ((cs == FS_FEEDING) || (cs == FS_HAPPY))
1126 proto_schedule_flush(p);
1127 break;
1128 default:
1129 bug("Invalid state transition for %s from %s/%s to */%s", p->name, c_states[cs], p_states[ops], p_states[ps]);
1130 }
1131 }
1132
1133 /*
1134 * CLI Commands
1135 */
1136
1137 static char *
1138 proto_state_name(struct proto *p)
1139 {
1140 #define P(x,y) ((x << 4) | y)
1141 switch (P(p->proto_state, p->core_state))
1142 {
1143 case P(PS_DOWN, FS_HUNGRY): return "down";
1144 case P(PS_START, FS_HUNGRY): return "start";
1145 case P(PS_UP, FS_HUNGRY):
1146 case P(PS_UP, FS_FEEDING): return "feed";
1147 case P(PS_STOP, FS_HUNGRY): return "stop";
1148 case P(PS_UP, FS_HAPPY): return "up";
1149 case P(PS_STOP, FS_FLUSHING):
1150 case P(PS_DOWN, FS_FLUSHING): return "flush";
1151 default: return "???";
1152 }
1153 #undef P
1154 }
1155
1156 static void
1157 proto_show_stats(struct proto_stats *s, int in_keep_filtered)
1158 {
1159 if (in_keep_filtered)
1160 cli_msg(-1006, " Routes: %u imported, %u filtered, %u exported, %u preferred",
1161 s->imp_routes, s->filt_routes, s->exp_routes, s->pref_routes);
1162 else
1163 cli_msg(-1006, " Routes: %u imported, %u exported, %u preferred",
1164 s->imp_routes, s->exp_routes, s->pref_routes);
1165
1166 cli_msg(-1006, " Route change stats: received rejected filtered ignored accepted");
1167 cli_msg(-1006, " Import updates: %10u %10u %10u %10u %10u",
1168 s->imp_updates_received, s->imp_updates_invalid,
1169 s->imp_updates_filtered, s->imp_updates_ignored,
1170 s->imp_updates_accepted);
1171 cli_msg(-1006, " Import withdraws: %10u %10u --- %10u %10u",
1172 s->imp_withdraws_received, s->imp_withdraws_invalid,
1173 s->imp_withdraws_ignored, s->imp_withdraws_accepted);
1174 cli_msg(-1006, " Export updates: %10u %10u %10u --- %10u",
1175 s->exp_updates_received, s->exp_updates_rejected,
1176 s->exp_updates_filtered, s->exp_updates_accepted);
1177 cli_msg(-1006, " Export withdraws: %10u --- --- --- %10u",
1178 s->exp_withdraws_received, s->exp_withdraws_accepted);
1179 }
1180
1181 void
1182 proto_show_limit(struct proto_limit *l, const char *dsc)
1183 {
1184 if (!l)
1185 return;
1186
1187 cli_msg(-1006, " %-16s%d%s", dsc, l->limit, l->state ? " [HIT]" : "");
1188 cli_msg(-1006, " Action: %s", proto_limit_name(l));
1189 }
1190
1191 void
1192 proto_show_basic_info(struct proto *p)
1193 {
1194 // cli_msg(-1006, " Table: %s", p->table->name);
1195 cli_msg(-1006, " Preference: %d", p->preference);
1196 cli_msg(-1006, " Input filter: %s", filter_name(p->cf->in_filter));
1197 cli_msg(-1006, " Output filter: %s", filter_name(p->cf->out_filter));
1198
1199 proto_show_limit(p->cf->rx_limit, "Receive limit:");
1200 proto_show_limit(p->cf->in_limit, "Import limit:");
1201 proto_show_limit(p->cf->out_limit, "Export limit:");
1202
1203 if (p->proto_state != PS_DOWN)
1204 proto_show_stats(&p->stats, p->cf->in_keep_filtered);
1205 }
1206
1207 void
1208 proto_cmd_show(struct proto *p, unsigned int verbose, int cnt)
1209 {
1210 byte buf[256], tbuf[TM_DATETIME_BUFFER_SIZE];
1211
1212 /* First protocol - show header */
1213 if (!cnt)
1214 cli_msg(-2002, "name proto table state since info");
1215
1216 buf[0] = 0;
1217 if (p->proto->get_status)
1218 p->proto->get_status(p, buf);
1219 tm_format_datetime(tbuf, &config->tf_proto, p->last_state_change);
1220 cli_msg(-1002, "%-8s %-8s %-8s %-5s %-10s %s",
1221 p->name,
1222 p->proto->name,
1223 p->table->name,
1224 proto_state_name(p),
1225 tbuf,
1226 buf);
1227 if (verbose)
1228 {
1229 if (p->cf->dsc)
1230 cli_msg(-1006, " Description: %s", p->cf->dsc);
1231 if (p->cf->router_id)
1232 cli_msg(-1006, " Router ID: %R", p->cf->router_id);
1233
1234 if (p->proto->show_proto_info)
1235 p->proto->show_proto_info(p);
1236 else
1237 proto_show_basic_info(p);
1238
1239 cli_msg(-1006, "");
1240 }
1241 }
1242
1243 void
1244 proto_cmd_disable(struct proto *p, unsigned int arg UNUSED, int cnt UNUSED)
1245 {
1246 if (p->disabled)
1247 {
1248 cli_msg(-8, "%s: already disabled", p->name);
1249 return;
1250 }
1251
1252 log(L_INFO "Disabling protocol %s", p->name);
1253 p->disabled = 1;
1254 p->down_code = PDC_CMD_DISABLE;
1255 proto_rethink_goal(p);
1256 cli_msg(-9, "%s: disabled", p->name);
1257 }
1258
1259 void
1260 proto_cmd_enable(struct proto *p, unsigned int arg UNUSED, int cnt UNUSED)
1261 {
1262 if (!p->disabled)
1263 {
1264 cli_msg(-10, "%s: already enabled", p->name);
1265 return;
1266 }
1267
1268 log(L_INFO "Enabling protocol %s", p->name);
1269 p->disabled = 0;
1270 proto_rethink_goal(p);
1271 cli_msg(-11, "%s: enabled", p->name);
1272 }
1273
1274 void
1275 proto_cmd_restart(struct proto *p, unsigned int arg UNUSED, int cnt UNUSED)
1276 {
1277 if (p->disabled)
1278 {
1279 cli_msg(-8, "%s: already disabled", p->name);
1280 return;
1281 }
1282
1283 log(L_INFO "Restarting protocol %s", p->name);
1284 p->disabled = 1;
1285 p->down_code = PDC_CMD_RESTART;
1286 proto_rethink_goal(p);
1287 p->disabled = 0;
1288 proto_rethink_goal(p);
1289 cli_msg(-12, "%s: restarted", p->name);
1290 }
1291
1292 void
1293 proto_cmd_reload(struct proto *p, unsigned int dir, int cnt UNUSED)
1294 {
1295 if (p->disabled)
1296 {
1297 cli_msg(-8, "%s: already disabled", p->name);
1298 return;
1299 }
1300
1301 /* If the protocol in not UP, it has no routes */
1302 if (p->proto_state != PS_UP)
1303 return;
1304
1305 log(L_INFO "Reloading protocol %s", p->name);
1306
1307 /* re-importing routes */
1308 if (dir != CMD_RELOAD_OUT)
1309 {
1310 if (! (p->reload_routes && p->reload_routes(p)))
1311 {
1312 cli_msg(-8006, "%s: reload failed", p->name);
1313 return;
1314 }
1315
1316 /*
1317 * Should be done before reload_routes() hook?
1318 * Perhaps, but these hooks work asynchronously.
1319 */
1320 if (!p->proto->multitable)
1321 {
1322 proto_reset_limit(p->main_ahook->rx_limit);
1323 proto_reset_limit(p->main_ahook->in_limit);
1324 }
1325 }
1326
1327 /* re-exporting routes */
1328 if (dir != CMD_RELOAD_IN)
1329 proto_request_feeding(p);
1330
1331 cli_msg(-15, "%s: reloading", p->name);
1332 }
1333
1334 void
1335 proto_cmd_debug(struct proto *p, unsigned int mask, int cnt UNUSED)
1336 {
1337 p->debug = mask;
1338 }
1339
1340 void
1341 proto_cmd_mrtdump(struct proto *p, unsigned int mask, int cnt UNUSED)
1342 {
1343 p->mrtdump = mask;
1344 }
1345
1346 static void
1347 proto_apply_cmd_symbol(struct symbol *s, void (* cmd)(struct proto *, unsigned int, int), unsigned int arg)
1348 {
1349 if (s->class != SYM_PROTO)
1350 {
1351 cli_msg(9002, "%s is not a protocol", s->name);
1352 return;
1353 }
1354
1355 cmd(((struct proto_config *)s->def)->proto, arg, 0);
1356 cli_msg(0, "");
1357 }
1358
1359 static void
1360 proto_apply_cmd_patt(char *patt, void (* cmd)(struct proto *, unsigned int, int), unsigned int arg)
1361 {
1362 int cnt = 0;
1363
1364 node *nn;
1365 WALK_LIST(nn, proto_list)
1366 {
1367 struct proto *p = SKIP_BACK(struct proto, glob_node, nn);
1368
1369 if (!patt || patmatch(patt, p->name))
1370 cmd(p, arg, cnt++);
1371 }
1372
1373 if (!cnt)
1374 cli_msg(8003, "No protocols match");
1375 else
1376 cli_msg(0, "");
1377 }
1378
1379 void
1380 proto_apply_cmd(struct proto_spec ps, void (* cmd)(struct proto *, unsigned int, int),
1381 int restricted, unsigned int arg)
1382 {
1383 if (restricted && cli_access_restricted())
1384 return;
1385
1386 if (ps.patt)
1387 proto_apply_cmd_patt(ps.ptr, cmd, arg);
1388 else
1389 proto_apply_cmd_symbol(ps.ptr, cmd, arg);
1390 }
1391
1392 struct proto *
1393 proto_get_named(struct symbol *sym, struct protocol *pr)
1394 {
1395 struct proto *p, *q;
1396
1397 if (sym)
1398 {
1399 if (sym->class != SYM_PROTO)
1400 cf_error("%s: Not a protocol", sym->name);
1401 p = ((struct proto_config *)sym->def)->proto;
1402 if (!p || p->proto != pr)
1403 cf_error("%s: Not a %s protocol", sym->name, pr->name);
1404 }
1405 else
1406 {
1407 p = NULL;
1408 WALK_LIST(q, active_proto_list)
1409 if (q->proto == pr)
1410 {
1411 if (p)
1412 cf_error("There are multiple %s protocols running", pr->name);
1413 p = q;
1414 }
1415 if (!p)
1416 cf_error("There is no %s protocol running", pr->name);
1417 }
1418 return p;
1419 }