]> git.ipfire.org Git - thirdparty/bird.git/blame - nest/proto.c
Merge commit 'origin/master'
[thirdparty/bird.git] / nest / proto.c
CommitLineData
2326b001
MM
1/*
2 * BIRD -- Protocols
3 *
50fe90ed 4 * (c) 1998--2000 Martin Mares <mj@ucw.cz>
2326b001
MM
5 *
6 * Can be freely distributed and used under the terms of the GNU GPL.
7 */
8
6b9fa320 9#undef LOCAL_DEBUG
7f4a3988 10
2326b001
MM
11#include "nest/bird.h"
12#include "nest/protocol.h"
13#include "lib/resource.h"
14#include "lib/lists.h"
67bd949a 15#include "lib/event.h"
f14a4bec 16#include "lib/string.h"
fe7cec12 17#include "conf/conf.h"
47b79306
MM
18#include "nest/route.h"
19#include "nest/iface.h"
ae97b946 20#include "nest/cli.h"
529c4149 21#include "filter/filter.h"
2326b001 22
acb60628 23pool *proto_pool;
67bd949a 24
3991d84e 25static list protocol_list;
f14a4bec 26static list proto_list;
67bd949a 27
839380d7
MM
28#define PD(pr, msg, args...) do { if (pr->debug & D_STATES) { log(L_TRACE "%s: " msg, pr->name , ## args); } } while(0)
29
f14a4bec 30list active_proto_list;
67bd949a
MM
31static list inactive_proto_list;
32static list initial_proto_list;
1a54b1c6 33static list flush_proto_list;
4ef09506 34static struct proto *initial_device_proto;
1a54b1c6
MM
35
36static event *proto_flush_event;
67bd949a
MM
37
38static char *p_states[] = { "DOWN", "START", "UP", "STOP" };
39static char *c_states[] = { "HUNGRY", "FEEDING", "HAPPY", "FLUSHING" };
40
8f6accb5 41static void proto_flush_all(void *);
50fe90ed 42static void proto_rethink_goal(struct proto *p);
839380d7 43static char *proto_state_name(struct proto *p);
1a54b1c6 44
b2280748
MM
45static void
46proto_enqueue(list *l, struct proto *p)
47{
3ea1ba63 48 add_tail(l, &p->n);
9685deb9 49 p->last_state_change = now;
b2280748
MM
50}
51
67bd949a
MM
52static void
53proto_relink(struct proto *p)
54{
e81b440f 55 list *l = NULL;
1a54b1c6 56
df9f0fb3
MM
57 if (p->debug & D_STATES)
58 {
59 char *name = proto_state_name(p);
60 if (name != p->last_state_name_announced)
61 {
62 p->last_state_name_announced = name;
63 PD(p, "State changed to %s", proto_state_name(p));
64 }
65 }
66 else
67 p->last_state_name_announced = NULL;
67bd949a 68 rem_node(&p->n);
1a54b1c6
MM
69 switch (p->core_state)
70 {
bf47fe4b
OZ
71 case FS_HUNGRY:
72 l = &inactive_proto_list;
73 break;
74 case FS_FEEDING:
1a54b1c6 75 case FS_HAPPY:
f14a4bec 76 l = &active_proto_list;
1a54b1c6
MM
77 break;
78 case FS_FLUSHING:
79 l = &flush_proto_list;
80 break;
81 default:
bf47fe4b 82 ASSERT(0);
1a54b1c6 83 }
b2280748 84 proto_enqueue(l, p);
67bd949a 85}
2326b001 86
3c6269b8
MM
87/**
88 * proto_new - create a new protocol instance
89 * @c: protocol configuration
90 * @size: size of protocol data structure (each protocol instance is represented by
91 * a structure starting with generic part [struct &proto] and continued
92 * with data specific to the protocol)
93 *
94 * When a new configuration has been read in, the core code starts
2e9b2421 95 * initializing all the protocol instances configured by calling their
3c6269b8
MM
96 * init() hooks with the corresponding instance configuration. The initialization
97 * code of the protocol is expected to create a new instance according to the
98 * configuration by calling this function and then modifying the default settings
99 * to values wanted by the protocol.
100 */
7f4a3988 101void *
31b3e1bb 102proto_new(struct proto_config *c, unsigned size)
7f4a3988 103{
1d2664a4 104 struct protocol *pr = c->protocol;
8fe48f13 105 struct proto *p = mb_allocz(proto_pool, size);
7f4a3988 106
31b3e1bb
MM
107 p->cf = c;
108 p->debug = c->debug;
cf31112f 109 p->mrtdump = c->mrtdump;
67bd949a 110 p->name = c->name;
31b3e1bb
MM
111 p->preference = c->preference;
112 p->disabled = c->disabled;
7f4a3988 113 p->proto = pr;
9d885689 114 p->table = c->table->table;
529c4149
MM
115 p->in_filter = c->in_filter;
116 p->out_filter = c->out_filter;
7293c5dd 117 p->hash_key = random_u32();
1d2664a4 118 c->proto = p;
7f4a3988
MM
119 return p;
120}
121
1a54b1c6
MM
122static void
123proto_init_instance(struct proto *p)
124{
5bc512aa
MM
125 /* Here we cannot use p->cf->name since it won't survive reconfiguration */
126 p->pool = rp_new(proto_pool, p->proto->name);
1a54b1c6
MM
127 p->attn = ev_new(p->pool);
128 p->attn->data = p;
50fe90ed 129 rt_lock_table(p->table);
1a54b1c6
MM
130}
131
3c6269b8
MM
132/**
133 * proto_add_announce_hook - connect protocol to a routing table
134 * @p: protocol instance
135 * @t: routing table to connect to
136 *
137 * This function creates a connection between the protocol instance @p
138 * and the routing table @t, making the protocol hear all changes in
139 * the table.
140 *
141 * Unless you want to listen to multiple routing tables (as the Pipe
142 * protocol does), you needn't to worry about this function since the
143 * connection to the protocol's primary routing table is initialized
144 * automatically by the core code.
145 */
0e02abfd
MM
146struct announce_hook *
147proto_add_announce_hook(struct proto *p, struct rtable *t)
148{
149 struct announce_hook *h;
150
151 if (!p->rt_notify)
152 return NULL;
153 DBG("Connecting protocol %s to table %s\n", p->name, t->name);
839380d7 154 PD(p, "Connected to table %s", t->name);
0e02abfd
MM
155 h = mb_alloc(p->pool, sizeof(struct announce_hook));
156 h->table = t;
157 h->proto = p;
158 h->next = p->ahooks;
159 p->ahooks = h;
160 add_tail(&t->hooks, &h->n);
161 return h;
162}
163
164static void
165proto_flush_hooks(struct proto *p)
166{
167 struct announce_hook *h;
168
169 for(h=p->ahooks; h; h=h->next)
170 rem_node(&h->n);
171 p->ahooks = NULL;
172}
173
3c6269b8
MM
174/**
175 * proto_config_new - create a new protocol configuration
176 * @pr: protocol the configuration will belong to
177 * @size: size of the structure including generic data
a7f23f58 178 * @class: SYM_PROTO or SYM_TEMPLATE
3c6269b8
MM
179 *
180 * Whenever the configuration file says that a new instance
181 * of a routing protocol should be created, the parser calls
182 * proto_config_new() to create a configuration entry for this
183 * instance (a structure staring with the &proto_config header
184 * containing all the generic items followed by protocol-specific
185 * ones). Also, the configuration entry gets added to the list
186 * of protocol instances kept in the configuration.
a7f23f58
OZ
187 *
188 * The function is also used to create protocol templates (when class
189 * SYM_TEMPLATE is specified), the only difference is that templates
190 * are not added to the list of protocol instances and therefore not
191 * initialized during protos_commit()).
3c6269b8 192 */
31b3e1bb 193void *
a7f23f58 194proto_config_new(struct protocol *pr, unsigned size, int class)
31b3e1bb
MM
195{
196 struct proto_config *c = cfg_allocz(size);
197
a7f23f58
OZ
198 if (class == SYM_PROTO)
199 add_tail(&new_config->protos, &c->n);
31b3e1bb 200 c->global = new_config;
1d2664a4 201 c->protocol = pr;
31b3e1bb 202 c->name = pr->name;
39c028e9 203 c->preference = pr->preference;
a7f23f58 204 c->class = class;
5056c559 205 c->out_filter = FILTER_REJECT;
9d885689 206 c->table = c->global->master_rtc;
839380d7 207 c->debug = new_config->proto_default_debug;
cf31112f 208 c->mrtdump = new_config->proto_default_mrtdump;
31b3e1bb
MM
209 return c;
210}
211
a7f23f58
OZ
212/**
213 * proto_copy_config - copy a protocol configuration
214 * @dest: destination protocol configuration
215 * @src: source protocol configuration
216 *
217 * Whenever a new instance of a routing protocol is created from the
218 * template, proto_copy_config() is called to copy a content of
219 * the source protocol configuration to the new protocol configuration.
220 * Name, class and a node in protos list of @dest are kept intact.
221 * copy_config() protocol hook is used to copy protocol-specific data.
222 */
223void
224proto_copy_config(struct proto_config *dest, struct proto_config *src)
225{
226 node old_node;
227 int old_class;
228 char *old_name;
229
230 if (dest->protocol != src->protocol)
231 cf_error("Can't copy configuration from a different protocol type");
232
233 if (dest->protocol->copy_config == NULL)
234 cf_error("Inheriting configuration for %s is not supported", src->protocol->name);
235
236 DBG("Copying configuration from %s to %s\n", src->name, dest->name);
237
238 /*
239 * Copy struct proto_config here. Keep original node, class and name.
240 * protocol-specific config copy is handled by protocol copy_config() hook
241 */
242
243 old_node = dest->n;
244 old_class = dest->class;
245 old_name = dest->name;
246
247 memcpy(dest, src, sizeof(struct proto_config));
248
249 dest->n = old_node;
250 dest->class = old_class;
251 dest->name = old_name;
252
253 dest->protocol->copy_config(dest, src);
254}
255
3c6269b8
MM
256/**
257 * protos_preconfig - pre-configuration processing
258 * @c: new configuration
259 *
260 * This function calls the preconfig() hooks of all routing
261 * protocols available to prepare them for reading of the new
262 * configuration.
263 */
2326b001 264void
31b3e1bb 265protos_preconfig(struct config *c)
2326b001 266{
7f4a3988
MM
267 struct protocol *p;
268
7c0cc76e 269 init_list(&c->protos);
6b9fa320 270 DBG("Protocol preconfig:");
7f4a3988
MM
271 WALK_LIST(p, protocol_list)
272 {
6b9fa320 273 DBG(" %s", p->name);
4ba84ebc 274 p->name_counter = 0;
3629bcf0 275 if (p->preconfig)
31b3e1bb 276 p->preconfig(p, c);
7f4a3988 277 }
6b9fa320 278 DBG("\n");
7f4a3988
MM
279}
280
3c6269b8
MM
281/**
282 * protos_postconfig - post-configuration processing
283 * @c: new configuration
284 *
285 * This function calls the postconfig() hooks of all protocol
a7f23f58
OZ
286 * instances specified in configuration @c. The hooks are not
287 * called for protocol templates.
3c6269b8 288 */
7f4a3988 289void
31b3e1bb 290protos_postconfig(struct config *c)
7f4a3988 291{
31b3e1bb 292 struct proto_config *x;
7f4a3988
MM
293 struct protocol *p;
294
6b9fa320 295 DBG("Protocol postconfig:");
31b3e1bb 296 WALK_LIST(x, c->protos)
7f4a3988 297 {
6b9fa320 298 DBG(" %s", x->name);
1d2664a4 299 p = x->protocol;
3629bcf0 300 if (p->postconfig)
31b3e1bb
MM
301 p->postconfig(x);
302 }
6b9fa320 303 DBG("\n");
31b3e1bb
MM
304}
305
4ef09506
OZ
306extern struct protocol proto_unix_iface;
307
50fe90ed
MM
308static struct proto *
309proto_init(struct proto_config *c)
310{
311 struct protocol *p = c->protocol;
312 struct proto *q = p->init(c);
313
314 q->proto_state = PS_DOWN;
315 q->core_state = FS_HUNGRY;
316 proto_enqueue(&initial_proto_list, q);
4ef09506
OZ
317 if (p == &proto_unix_iface)
318 initial_device_proto = q;
319
f14a4bec 320 add_tail(&proto_list, &q->glob_node);
498c3339 321 PD(q, "Initializing%s", q->disabled ? " [disabled]" : "");
50fe90ed
MM
322 return q;
323}
324
ebae4770
OZ
325static int
326proto_reconfigure(struct proto *p, struct proto_config *oc, struct proto_config *nc, int type)
327{
328 /* If the protocol is DOWN, we just restart it */
329 if (p->proto_state == PS_DOWN)
330 return 0;
331
332 /* If there is a too big change in core attributes, ... */
333 if ((nc->protocol != oc->protocol) ||
23fd4644 334 (nc->disabled != p->disabled) ||
ebae4770 335 (nc->table->table != oc->table->table) ||
76b53a4e 336 (proto_get_router_id(nc) != proto_get_router_id(oc)))
ebae4770
OZ
337 return 0;
338
339 int import_changed = (type != RECONFIG_SOFT) && ! filter_same(nc->in_filter, oc->in_filter);
340 int export_changed = (type != RECONFIG_SOFT) && ! filter_same(nc->out_filter, oc->out_filter);
341
342 /* We treat a change in preferences by reimporting routes */
343 if (nc->preference != oc->preference)
344 import_changed = 1;
345
346 /* If the protocol in not UP, it has no routes and we can ignore such changes */
347 if (p->proto_state != PS_UP)
348 import_changed = export_changed = 0;
349
350 /* Without this hook we cannot reload routes and have to restart the protocol */
351 if (import_changed && ! p->reload_routes)
352 return 0;
353
354 p->debug = nc->debug;
355 p->mrtdump = nc->mrtdump;
356
357 /* Execute protocol specific reconfigure hook */
358 if (! (p->proto->reconfigure && p->proto->reconfigure(p, nc)))
359 return 0;
360
361 DBG("\t%s: same\n", oc->name);
362 PD(p, "Reconfigured");
363 p->cf = nc;
364 p->name = nc->name;
365 p->in_filter = nc->in_filter;
366 p->out_filter = nc->out_filter;
5a56f27c 367 p->preference = nc->preference;
ebae4770 368
76b53a4e
OZ
369 if (import_changed || export_changed)
370 log(L_INFO "Reloading protocol %s", p->name);
371
ebae4770
OZ
372 if (import_changed && ! p->reload_routes(p))
373 {
374 /* Now, the protocol is reconfigured. But route reload failed
375 and we have to do regular protocol restart. */
76b53a4e 376 log(L_INFO "Restarting protocol %s", p->name);
ebae4770
OZ
377 p->disabled = 1;
378 proto_rethink_goal(p);
379 p->disabled = 0;
380 proto_rethink_goal(p);
381 return 1;
382 }
383
384 if (export_changed)
385 proto_request_feeding(p);
386
387 return 1;
388}
389
3c6269b8
MM
390/**
391 * protos_commit - commit new protocol configuration
392 * @new: new configuration
393 * @old: old configuration or %NULL if it's boot time config
394 * @force_reconfig: force restart of all protocols (used for example
395 * when the router ID changes)
bf1aec97 396 * @type: type of reconfiguration (RECONFIG_SOFT or RECONFIG_HARD)
3c6269b8
MM
397 *
398 * Scan differences between @old and @new configuration and adjust all
399 * protocol instances to conform to the new configuration.
400 *
401 * When a protocol exists in the new configuration, but it doesn't in the
402 * original one, it's immediately started. When a collision with the other
403 * running protocol would arise, the new protocol will be temporarily stopped
404 * by the locking mechanism.
405 *
406 * When a protocol exists in the old configuration, but it doesn't in the
407 * new one, it's shut down and deleted after the shutdown completes.
408 *
bf1aec97
OZ
409 * When a protocol exists in both configurations, the core decides
410 * whether it's possible to reconfigure it dynamically - it checks all
411 * the core properties of the protocol (changes in filters are ignored
412 * if type is RECONFIG_SOFT) and if they match, it asks the
413 * reconfigure() hook of the protocol to see if the protocol is able
414 * to switch to the new configuration. If it isn't possible, the
415 * protocol is shut down and a new instance is started with the new
416 * configuration after the shutdown is completed.
3c6269b8 417 */
31b3e1bb 418void
bf1aec97 419protos_commit(struct config *new, struct config *old, int force_reconfig, int type)
31b3e1bb 420{
50fe90ed
MM
421 struct proto_config *oc, *nc;
422 struct proto *p, *n;
a7f23f58 423 struct symbol *sym;
31b3e1bb 424
50fe90ed
MM
425 DBG("protos_commit:\n");
426 if (old)
31b3e1bb 427 {
50fe90ed
MM
428 WALK_LIST(oc, old->protos)
429 {
a7f23f58
OZ
430 p = oc->proto;
431 sym = cf_find_symbol(oc->name);
bf8558bc 432 if (sym && sym->class == SYM_PROTO && !new->shutdown)
50fe90ed
MM
433 {
434 /* Found match, let's check if we can smoothly switch to new configuration */
e04555c0 435 /* No need to check description */
50fe90ed 436 nc = sym->def;
ebae4770
OZ
437 nc->proto = p;
438
439 /* We will try to reconfigure protocol p */
440 if (! force_reconfig && proto_reconfigure(p, oc, nc, type))
441 continue;
442
443 /* Unsuccessful, we will restart it */
76b53a4e
OZ
444 if (!p->disabled && !nc->disabled)
445 log(L_INFO "Restarting protocol %s", p->name);
446 else if (p->disabled && !nc->disabled)
447 log(L_INFO "Enabling protocol %s", p->name);
448 else if (!p->disabled && nc->disabled)
449 log(L_INFO "Disabling protocol %s", p->name);
450
ebae4770 451 PD(p, "Restarting");
50fe90ed
MM
452 p->cf_new = nc;
453 }
454 else
455 {
76b53a4e
OZ
456 if (!shutting_down)
457 log(L_INFO "Removing protocol %s", p->name);
839380d7 458 PD(p, "Unconfigured");
50fe90ed
MM
459 p->cf_new = NULL;
460 }
461 p->reconfiguring = 1;
462 config_add_obstacle(old);
463 proto_rethink_goal(p);
464 }
7f4a3988 465 }
50fe90ed
MM
466
467 WALK_LIST(nc, new->protos)
468 if (!nc->proto)
469 {
76b53a4e
OZ
470 if (old_config) /* Not a first-time configuration */
471 log(L_INFO "Adding protocol %s", nc->name);
50fe90ed
MM
472 proto_init(nc);
473 }
474 DBG("\tdone\n");
475
476 DBG("Protocol start\n");
4ef09506
OZ
477
478 /* Start device protocol first */
479 if (initial_device_proto)
480 {
481 proto_rethink_goal(initial_device_proto);
482 initial_device_proto = NULL;
483 }
484
50fe90ed
MM
485 WALK_LIST_DELSAFE(p, n, initial_proto_list)
486 proto_rethink_goal(p);
7f4a3988
MM
487}
488
47b79306 489static void
67bd949a 490proto_rethink_goal(struct proto *p)
47b79306 491{
50fe90ed
MM
492 struct protocol *q;
493
494 if (p->reconfiguring && p->core_state == FS_HUNGRY && p->proto_state == PS_DOWN)
495 {
496 struct proto_config *nc = p->cf_new;
497 DBG("%s has shut down for reconfiguration\n", p->name);
498 config_del_obstacle(p->cf->global);
499 rem_node(&p->n);
f14a4bec 500 rem_node(&p->glob_node);
50fe90ed
MM
501 mb_free(p);
502 if (!nc)
503 return;
f098e072 504 p = proto_init(nc);
50fe90ed
MM
505 }
506
507 /* Determine what state we want to reach */
bf8558bc 508 if (p->disabled || p->reconfiguring)
ebd3720f
MM
509 {
510 p->core_goal = FS_HUNGRY;
511 if (p->core_state == FS_HUNGRY && p->proto_state == PS_DOWN)
512 return;
513 }
50fe90ed 514 else
ebd3720f
MM
515 {
516 p->core_goal = FS_HAPPY;
517 if (p->core_state == FS_HAPPY && p->proto_state == PS_UP)
518 return;
519 }
50fe90ed
MM
520
521 q = p->proto;
67bd949a
MM
522 if (p->core_goal == FS_HAPPY) /* Going up */
523 {
524 if (p->core_state == FS_HUNGRY && p->proto_state == PS_DOWN)
525 {
526 DBG("Kicking %s up\n", p->name);
839380d7 527 PD(p, "Starting");
1a54b1c6 528 proto_init_instance(p);
67bd949a
MM
529 proto_notify_state(p, (q->start ? q->start(p) : PS_UP));
530 }
531 }
532 else /* Going down */
533 {
534 if (p->proto_state == PS_START || p->proto_state == PS_UP)
535 {
536 DBG("Kicking %s down\n", p->name);
839380d7 537 PD(p, "Shutting down");
67bd949a
MM
538 proto_notify_state(p, (q->shutdown ? q->shutdown(p) : PS_DOWN));
539 }
540 }
541}
542
3c6269b8
MM
543/**
544 * protos_dump_all - dump status of all protocols
545 *
546 * This function dumps status of all existing protocol instances to the
547 * debug output. It involves printing of general status information
548 * such as protocol states, its position on the protocol lists
549 * and also calling of a dump() hook of the protocol to print
550 * the internals.
551 */
87d2be86
PM
552void
553protos_dump_all(void)
554{
555 struct proto *p;
556
557 debug("Protocols:\n");
558
f14a4bec 559 WALK_LIST(p, active_proto_list)
87d2be86 560 {
3ea1ba63 561 debug(" protocol %s state %s/%s\n", p->name,
b2280748 562 p_states[p->proto_state], c_states[p->core_state]);
529c4149 563 if (p->in_filter)
5056c559
MM
564 debug("\tInput filter: %s\n", filter_name(p->in_filter));
565 if (p->out_filter != FILTER_REJECT)
566 debug("\tOutput filter: %s\n", filter_name(p->out_filter));
66efdf96
MM
567 if (p->disabled)
568 debug("\tDISABLED\n");
31b3e1bb
MM
569 else if (p->proto->dump)
570 p->proto->dump(p);
87d2be86 571 }
47b79306 572 WALK_LIST(p, inactive_proto_list)
67bd949a
MM
573 debug(" inactive %s: state %s/%s\n", p->name, p_states[p->proto_state], c_states[p->core_state]);
574 WALK_LIST(p, initial_proto_list)
575 debug(" initial %s\n", p->name);
f14a4bec
MM
576 WALK_LIST(p, flush_proto_list)
577 debug(" flushing %s\n", p->name);
87d2be86
PM
578}
579
3c6269b8
MM
580/**
581 * proto_build - make a single protocol available
582 * @p: the protocol
583 *
584 * After the platform specific initialization code uses protos_build()
585 * to add all the standard protocols, it should call proto_build() for
2e9b2421 586 * all platform specific protocols to inform the core that they exist.
3c6269b8 587 */
3991d84e
MM
588void
589proto_build(struct protocol *p)
590{
591 add_tail(&protocol_list, &p->n);
592 if (p->attr_class)
593 {
594 ASSERT(!attr_class_to_protocol[p->attr_class]);
595 attr_class_to_protocol[p->attr_class] = p;
596 }
597}
598
3c6269b8
MM
599/**
600 * protos_build - build a protocol list
601 *
602 * This function is called during BIRD startup to insert
603 * all standard protocols to the global protocol list. Insertion
604 * of platform specific protocols (such as the kernel syncer)
605 * is in the domain of competence of the platform dependent
606 * startup code.
607 */
0432c017
MM
608void
609protos_build(void)
610{
611 init_list(&protocol_list);
471cc0be
MM
612 init_list(&proto_list);
613 init_list(&active_proto_list);
614 init_list(&inactive_proto_list);
615 init_list(&initial_proto_list);
616 init_list(&flush_proto_list);
3991d84e 617 proto_build(&proto_device);
93e868c7
OZ
618#ifdef CONFIG_RADV
619 proto_build(&proto_radv);
620#endif
18fff6a1 621#ifdef CONFIG_RIP
3991d84e 622 proto_build(&proto_rip);
18fff6a1
MM
623#endif
624#ifdef CONFIG_STATIC
3991d84e 625 proto_build(&proto_static);
c1f8dc91
OF
626#endif
627#ifdef CONFIG_OSPF
3991d84e 628 proto_build(&proto_ospf);
26368f65
MM
629#endif
630#ifdef CONFIG_PIPE
3991d84e 631 proto_build(&proto_pipe);
2638249d
MM
632#endif
633#ifdef CONFIG_BGP
3991d84e 634 proto_build(&proto_bgp);
18fff6a1 635#endif
67bd949a 636 proto_pool = rp_new(&root_pool, "Protocols");
1a54b1c6
MM
637 proto_flush_event = ev_new(proto_pool);
638 proto_flush_event->hook = proto_flush_all;
67bd949a
MM
639}
640
641static void
642proto_fell_down(struct proto *p)
643{
644 DBG("Protocol %s down\n", p->name);
ac07aacd
OZ
645
646 if (p->stats.imp_routes != 0)
647 log(L_ERR "Protocol %s is down but still has %d routes", p->name, p->stats.imp_routes);
925fe2d3
OZ
648
649 bzero(&p->stats, sizeof(struct proto_stats));
50fe90ed 650 rt_unlock_table(p->table);
c8387626 651
cfe34a31
OZ
652 if (p->proto->cleanup)
653 p->proto->cleanup(p);
c8387626 654
67bd949a
MM
655 proto_rethink_goal(p);
656}
657
ac5d8012
MM
658static void
659proto_feed_more(void *P)
660{
661 struct proto *p = P;
662
075898de
MM
663 if (p->core_state != FS_FEEDING)
664 return;
fbde6c39
OZ
665
666 DBG("Feeding protocol %s continued\n", p->name);
ac5d8012
MM
667 if (rt_feed_baby(p))
668 {
669 p->core_state = FS_HAPPY;
670 proto_relink(p);
671 DBG("Protocol %s up and running\n", p->name);
672 }
673 else
674 {
675 p->attn->hook = proto_feed_more;
676 ev_schedule(p->attn); /* Will continue later... */
677 }
678}
679
8f6accb5 680static void
bf47fe4b 681proto_feed_initial(void *P)
67bd949a
MM
682{
683 struct proto *p = P;
684
fbde6c39
OZ
685 if (p->core_state != FS_FEEDING)
686 return;
687
67bd949a 688 DBG("Feeding protocol %s\n", p->name);
0e02abfd 689 proto_add_announce_hook(p, p->table);
67bd949a 690 if_feed_baby(p);
ac5d8012 691 proto_feed_more(P);
67bd949a
MM
692}
693
d6a836f8
OZ
694static void
695proto_schedule_flush(struct proto *p)
696{
697 /* Need to abort feeding */
698 if (p->core_state == FS_FEEDING)
699 rt_feed_baby_abort(p);
700
701 DBG("%s: Scheduling flush\n", p->name);
702 p->core_state = FS_FLUSHING;
703 proto_relink(p);
704 proto_flush_hooks(p);
705 ev_schedule(proto_flush_event);
706}
707
708static void
bf47fe4b 709proto_schedule_feed(struct proto *p, int initial)
d6a836f8
OZ
710{
711 DBG("%s: Scheduling meal\n", p->name);
712 p->core_state = FS_FEEDING;
11361a10 713 p->refeeding = !initial;
8a7fb885
OZ
714
715 /* Hack: reset exp_routes during refeed, and do not decrease it later */
716 if (!initial)
717 p->stats.exp_routes = 0;
718
d6a836f8 719 proto_relink(p);
bf47fe4b 720 p->attn->hook = initial ? proto_feed_initial : proto_feed_more;
d6a836f8
OZ
721 ev_schedule(p->attn);
722}
723
bf47fe4b
OZ
724/**
725 * proto_request_feeding - request feeding routes to the protocol
726 * @p: given protocol
727 *
728 * Sometimes it is needed to send again all routes to the
729 * protocol. This is called feeding and can be requested by this
730 * function. This would cause protocol core state transition
731 * to FS_FEEDING (during feeding) and when completed, it will
732 * switch back to FS_HAPPY. This function can be called even
733 * when feeding is already running, in that case it is restarted.
734 */
735void
736proto_request_feeding(struct proto *p)
737{
738 ASSERT(p->proto_state == PS_UP);
739
740 /* If we are already feeding, we want to restart it */
741 if (p->core_state == FS_FEEDING)
742 {
743 /* Unless feeding is in initial state */
744 if (p->attn->hook == proto_feed_initial)
745 return;
746
747 rt_feed_baby_abort(p);
748 }
749
750 proto_schedule_feed(p, 0);
751}
752
3c6269b8
MM
753/**
754 * proto_notify_state - notify core about protocol state change
755 * @p: protocol the state of which has changed
756 * @ps: the new status
757 *
758 * Whenever a state of a protocol changes due to some event internal
759 * to the protocol (i.e., not inside a start() or shutdown() hook),
760 * it should immediately notify the core about the change by calling
761 * proto_notify_state() which will write the new state to the &proto
762 * structure and take all the actions necessary to adapt to the new
d6a836f8
OZ
763 * state. State change to PS_DOWN immediately frees resources of protocol
764 * and might execute start callback of protocol; therefore,
765 * it should be used at tail positions of protocol callbacks.
3c6269b8 766 */
67bd949a
MM
767void
768proto_notify_state(struct proto *p, unsigned ps)
769{
770 unsigned ops = p->proto_state;
771 unsigned cs = p->core_state;
772
773 DBG("%s reporting state transition %s/%s -> */%s\n", p->name, c_states[cs], p_states[ops], p_states[ps]);
774 if (ops == ps)
775 return;
776
d6a836f8
OZ
777 p->proto_state = ps;
778
67bd949a
MM
779 switch (ps)
780 {
781 case PS_DOWN:
a421ec33 782 if ((cs == FS_FEEDING) || (cs == FS_HAPPY))
b807ef9a
OZ
783 proto_schedule_flush(p);
784
d6a836f8
OZ
785 neigh_prune(); // FIXME convert neighbors to resource?
786 rfree(p->pool);
787 p->pool = NULL;
788
67bd949a 789 if (cs == FS_HUNGRY) /* Shutdown finished */
50fe90ed
MM
790 {
791 proto_fell_down(p);
792 return; /* The protocol might have ceased to exist */
793 }
67bd949a
MM
794 break;
795 case PS_START:
796 ASSERT(ops == PS_DOWN);
797 ASSERT(cs == FS_HUNGRY);
798 break;
799 case PS_UP:
800 ASSERT(ops == PS_DOWN || ops == PS_START);
801 ASSERT(cs == FS_HUNGRY);
bf47fe4b 802 proto_schedule_feed(p, 1);
67bd949a
MM
803 break;
804 case PS_STOP:
a421ec33 805 if ((cs == FS_FEEDING) || (cs == FS_HAPPY))
d6a836f8 806 proto_schedule_flush(p);
f4aabcee 807 break;
67bd949a 808 default:
67bd949a
MM
809 bug("Invalid state transition for %s from %s/%s to */%s", p->name, c_states[cs], p_states[ops], p_states[ps]);
810 }
0432c017 811}
1a54b1c6 812
8f6accb5 813static void
7c103b1e 814proto_flush_all(void *unused UNUSED)
1a54b1c6
MM
815{
816 struct proto *p;
817
0e02abfd 818 rt_prune_all();
1a54b1c6
MM
819 while ((p = HEAD(flush_proto_list))->n.next)
820 {
53434e44
OZ
821 /* This will flush interfaces in the same manner
822 like rt_prune_all() flushes routes */
823 if (p->proto == &proto_unix_iface)
824 if_flush_ifaces(p);
825
1a54b1c6 826 DBG("Flushing protocol %s\n", p->name);
1a54b1c6
MM
827 p->core_state = FS_HUNGRY;
828 proto_relink(p);
d6a836f8
OZ
829 if (p->proto_state == PS_DOWN)
830 proto_fell_down(p);
1a54b1c6
MM
831 }
832}
ae97b946 833
0d3e6bce
MM
834/*
835 * CLI Commands
836 */
837
838static char *
839proto_state_name(struct proto *p)
840{
841#define P(x,y) ((x << 4) | y)
842 switch (P(p->proto_state, p->core_state))
843 {
844 case P(PS_DOWN, FS_HUNGRY): return "down";
845 case P(PS_START, FS_HUNGRY): return "start";
846 case P(PS_UP, FS_HUNGRY):
847 case P(PS_UP, FS_FEEDING): return "feed";
848 case P(PS_STOP, FS_HUNGRY): return "stop";
849 case P(PS_UP, FS_HAPPY): return "up";
850 case P(PS_STOP, FS_FLUSHING):
851 case P(PS_DOWN, FS_FLUSHING): return "flush";
852 default: return "???";
853 }
854#undef P
855}
856
9db74169
OZ
857static void
858proto_do_show_stats(struct proto *p)
859{
860 struct proto_stats *s = &p->stats;
861 cli_msg(-1006, " Routes: %u imported, %u exported, %u preferred",
862 s->imp_routes, s->exp_routes, s->pref_routes);
863 cli_msg(-1006, " Route change stats: received rejected filtered ignored accepted");
864 cli_msg(-1006, " Import updates: %10u %10u %10u %10u %10u",
865 s->imp_updates_received, s->imp_updates_invalid,
866 s->imp_updates_filtered, s->imp_updates_ignored,
867 s->imp_updates_accepted);
868 cli_msg(-1006, " Import withdraws: %10u %10u --- %10u %10u",
869 s->imp_withdraws_received, s->imp_withdraws_invalid,
870 s->imp_withdraws_ignored, s->imp_withdraws_accepted);
871 cli_msg(-1006, " Export updates: %10u %10u %10u --- %10u",
872 s->exp_updates_received, s->exp_updates_rejected,
873 s->exp_updates_filtered, s->exp_updates_accepted);
874 cli_msg(-1006, " Export withdraws: %10u --- --- --- %10u",
875 s->exp_withdraws_received, s->exp_withdraws_accepted);
876}
877
ba130172 878#ifdef CONFIG_PIPE
9db74169
OZ
879static void
880proto_do_show_pipe_stats(struct proto *p)
881{
882 struct proto_stats *s1 = &p->stats;
883 struct proto_stats *s2 = pipe_get_peer_stats(p);
884
885 /*
886 * Pipe stats (as anything related to pipes) are a bit tricky. There
887 * are two sets of stats - s1 for routes going from the primary
888 * routing table to the secondary routing table ('exported' from the
889 * user point of view) and s2 for routes going in the other
890 * direction ('imported' from the user point of view).
891 *
892 * Each route going through a pipe is, technically, first exported
893 * to the pipe and then imported from that pipe and such operations
894 * are counted in one set of stats according to the direction of the
895 * route propagation. Filtering is done just in the first part
896 * (export). Therefore, we compose stats for one directon for one
897 * user direction from both import and export stats, skipping
898 * immediate and irrelevant steps (exp_updates_accepted,
899 * imp_updates_received, imp_updates_filtered, ...)
900 */
901
902 cli_msg(-1006, " Routes: %u imported, %u exported",
903 s2->imp_routes, s1->imp_routes);
904 cli_msg(-1006, " Route change stats: received rejected filtered ignored accepted");
905 cli_msg(-1006, " Import updates: %10u %10u %10u %10u %10u",
906 s2->exp_updates_received, s2->exp_updates_rejected + s2->imp_updates_invalid,
907 s2->exp_updates_filtered, s2->imp_updates_ignored, s2->imp_updates_accepted);
908 cli_msg(-1006, " Import withdraws: %10u %10u --- %10u %10u",
909 s2->exp_withdraws_received, s2->imp_withdraws_invalid,
910 s2->imp_withdraws_ignored, s2->imp_withdraws_accepted);
911 cli_msg(-1006, " Export updates: %10u %10u %10u %10u %10u",
912 s1->exp_updates_received, s1->exp_updates_rejected + s1->imp_updates_invalid,
913 s1->exp_updates_filtered, s1->imp_updates_ignored, s1->imp_updates_accepted);
914 cli_msg(-1006, " Export withdraws: %10u %10u --- %10u %10u",
915 s1->exp_withdraws_received, s1->imp_withdraws_invalid,
916 s1->imp_withdraws_ignored, s1->imp_withdraws_accepted);
917}
ba130172 918#endif
9db74169 919
e304fd4b
OZ
920void
921proto_cmd_show(struct proto *p, unsigned int verbose, int cnt)
1d2664a4 922{
c37e7851 923 byte buf[256], tbuf[TM_DATETIME_BUFFER_SIZE];
9685deb9 924
e304fd4b
OZ
925 /* First protocol - show header */
926 if (!cnt)
927 cli_msg(-2002, "name proto table state since info");
928
9685deb9
MM
929 buf[0] = 0;
930 if (p->proto->get_status)
931 p->proto->get_status(p, buf);
c37e7851
OZ
932 tm_format_datetime(tbuf, &config->tf_proto, p->last_state_change);
933 cli_msg(-1002, "%-8s %-8s %-8s %-5s %-10s %s",
1d2664a4
MM
934 p->name,
935 p->proto->name,
936 p->table->name,
937 proto_state_name(p),
c37e7851 938 tbuf,
9685deb9 939 buf);
1d2664a4
MM
940 if (verbose)
941 {
e04555c0
OZ
942 if (p->cf->dsc)
943 cli_msg(-1006, " Description: %s", p->cf->dsc);
b8113a5e
OZ
944 if (p->cf->router_id)
945 cli_msg(-1006, " Router ID: %R", p->cf->router_id);
925fe2d3
OZ
946 cli_msg(-1006, " Preference: %d", p->preference);
947 cli_msg(-1006, " Input filter: %s", filter_name(p->in_filter));
948 cli_msg(-1006, " Output filter: %s", filter_name(p->out_filter));
949
950 if (p->proto_state != PS_DOWN)
951 {
9db74169
OZ
952#ifdef CONFIG_PIPE
953 if (proto_is_pipe(p))
954 proto_do_show_pipe_stats(p);
955 else
956#endif
957 proto_do_show_stats(p);
925fe2d3
OZ
958 }
959
b8113a5e
OZ
960 if (p->proto->show_proto_info)
961 p->proto->show_proto_info(p);
962
925fe2d3 963 cli_msg(-1006, "");
1d2664a4
MM
964 }
965}
966
ae97b946 967void
e304fd4b 968proto_cmd_disable(struct proto *p, unsigned int arg UNUSED, int cnt UNUSED)
ae97b946 969{
e304fd4b 970 if (p->disabled)
1d2664a4 971 {
e304fd4b 972 cli_msg(-8, "%s: already disabled", p->name);
1d2664a4
MM
973 return;
974 }
e304fd4b
OZ
975
976 log(L_INFO "Disabling protocol %s", p->name);
977 p->disabled = 1;
978 proto_rethink_goal(p);
979 cli_msg(-9, "%s: disabled", p->name);
980}
981
982void
983proto_cmd_enable(struct proto *p, unsigned int arg UNUSED, int cnt UNUSED)
984{
985 if (!p->disabled)
986 {
987 cli_msg(-10, "%s: already enabled", p->name);
988 return;
989 }
990
991 log(L_INFO "Enabling protocol %s", p->name);
992 p->disabled = 0;
993 proto_rethink_goal(p);
994 cli_msg(-11, "%s: enabled", p->name);
995}
996
997void
998proto_cmd_restart(struct proto *p, unsigned int arg UNUSED, int cnt UNUSED)
999{
1000 if (p->disabled)
1001 {
1002 cli_msg(-8, "%s: already disabled", p->name);
1003 return;
1004 }
1005
1006 log(L_INFO "Restarting protocol %s", p->name);
1007 p->disabled = 1;
1008 proto_rethink_goal(p);
1009 p->disabled = 0;
1010 proto_rethink_goal(p);
1011 cli_msg(-12, "%s: restarted", p->name);
1012}
1013
1014void
1015proto_cmd_reload(struct proto *p, unsigned int dir, int cnt UNUSED)
1016{
1017 if (p->disabled)
1018 {
1019 cli_msg(-8, "%s: already disabled", p->name);
1020 return;
1021 }
1022
1023 /* If the protocol in not UP, it has no routes */
1024 if (p->proto_state != PS_UP)
1025 return;
1026
1027 log(L_INFO "Reloading protocol %s", p->name);
1028
1029 /* re-importing routes */
1030 if (dir != CMD_RELOAD_OUT)
1031 if (! (p->reload_routes && p->reload_routes(p)))
1032 {
1033 cli_msg(-8006, "%s: reload failed", p->name);
1034 return;
1035 }
1036
1037 /* re-exporting routes */
1038 if (dir != CMD_RELOAD_IN)
1039 proto_request_feeding(p);
1040
1041 cli_msg(-15, "%s: reloading", p->name);
1042}
1043
1044void
1045proto_cmd_debug(struct proto *p, unsigned int mask, int cnt UNUSED)
1046{
1047 p->debug = mask;
1048}
1049
1050void
1051proto_cmd_mrtdump(struct proto *p, unsigned int mask, int cnt UNUSED)
1052{
1053 p->mrtdump = mask;
1054}
1055
1056static void
1057proto_apply_cmd_symbol(struct symbol *s, void (* cmd)(struct proto *, unsigned int, int), unsigned int arg)
1058{
1059 if (s->class != SYM_PROTO)
1d2664a4 1060 {
e304fd4b
OZ
1061 cli_msg(9002, "%s is not a protocol", s->name);
1062 return;
1d2664a4 1063 }
e304fd4b
OZ
1064
1065 cmd(((struct proto_config *)s->def)->proto, arg, 0);
ae97b946
MM
1066 cli_msg(0, "");
1067}
02c1fbdd 1068
e304fd4b
OZ
1069static void
1070proto_apply_cmd_patt(char *patt, void (* cmd)(struct proto *, unsigned int, int), unsigned int arg)
1071{
1072 int cnt = 0;
1073
1074 node *nn;
1075 WALK_LIST(nn, proto_list)
1076 {
1077 struct proto *p = SKIP_BACK(struct proto, glob_node, nn);
1078
1079 if (!patt || patmatch(patt, p->name))
1080 cmd(p, arg, cnt++);
1081 }
1082
1083 if (!cnt)
1084 cli_msg(8003, "No protocols match");
1085 else
1086 cli_msg(0, "");
1087}
1088
1089void
e0a45fb4
OZ
1090proto_apply_cmd(struct proto_spec ps, void (* cmd)(struct proto *, unsigned int, int),
1091 int restricted, unsigned int arg)
e304fd4b 1092{
e0a45fb4
OZ
1093 if (restricted && cli_access_restricted())
1094 return;
1095
e304fd4b
OZ
1096 if (ps.patt)
1097 proto_apply_cmd_patt(ps.ptr, cmd, arg);
1098 else
1099 proto_apply_cmd_symbol(ps.ptr, cmd, arg);
1100}
1101
02c1fbdd
MM
1102struct proto *
1103proto_get_named(struct symbol *sym, struct protocol *pr)
1104{
1105 struct proto *p, *q;
1106
1107 if (sym)
1108 {
1109 if (sym->class != SYM_PROTO)
1110 cf_error("%s: Not a protocol", sym->name);
1111 p = ((struct proto_config *)sym->def)->proto;
1112 if (!p || p->proto != pr)
1113 cf_error("%s: Not a %s protocol", sym->name, pr->name);
1114 }
1115 else
1116 {
1117 p = NULL;
f14a4bec 1118 WALK_LIST(q, active_proto_list)
02c1fbdd
MM
1119 if (q->proto == pr)
1120 {
1121 if (p)
1122 cf_error("There are multiple %s protocols running", pr->name);
1123 p = q;
1124 }
1125 if (!p)
1126 cf_error("There is no %s protocol running", pr->name);
1127 }
1128 return p;
1129}