Statistics
| Branch: | Revision:

iof-bird-daemon / nest / proto.c @ 8e433d6a

History | View | Annotate | Download (43.7 KB)

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
static timer *gr_wait_timer;
39

    
40
#define GRS_NONE        0
41
#define GRS_INIT        1
42
#define GRS_ACTIVE        2
43
#define GRS_DONE        3
44

    
45
static int graceful_restart_state;
46
static u32 graceful_restart_locks;
47

    
48
static char *p_states[] = { "DOWN", "START", "UP", "STOP" };
49
static char *c_states[] = { "HUNGRY", "???", "HAPPY", "FLUSHING" };
50

    
51
static void proto_flush_loop(void *);
52
static void proto_shutdown_loop(struct timer *);
53
static void proto_rethink_goal(struct proto *p);
54
static void proto_want_export_up(struct proto *p);
55
static void proto_fell_down(struct proto *p);
56
static char *proto_state_name(struct proto *p);
57

    
58
static void
59
proto_relink(struct proto *p)
60
{
61
  list *l = NULL;
62

    
63
  switch (p->core_state)
64
    {
65
    case FS_HUNGRY:
66
      l = &inactive_proto_list;
67
      break;
68
    case FS_HAPPY:
69
      l = &active_proto_list;
70
      break;
71
    case FS_FLUSHING:
72
      l = &flush_proto_list;
73
      break;
74
    default:
75
      ASSERT(0);
76
    }
77

    
78
  rem_node(&p->n);
79
  add_tail(l, &p->n);
80
}
81

    
82
static void
83
proto_log_state_change(struct proto *p)
84
{
85
  if (p->debug & D_STATES)
86
    {
87
      char *name = proto_state_name(p);
88
      if (name != p->last_state_name_announced)
89
        {
90
          p->last_state_name_announced = name;
91
          PD(p, "State changed to %s", proto_state_name(p));
92
        }
93
    }
94
  else
95
    p->last_state_name_announced = NULL;
96
}
97

    
98

    
99
/**
100
 * proto_new - create a new protocol instance
101
 * @c: protocol configuration
102
 * @size: size of protocol data structure (each protocol instance is represented by
103
 * a structure starting with generic part [struct &proto] and continued
104
 * with data specific to the protocol)
105
 *
106
 * When a new configuration has been read in, the core code starts
107
 * initializing all the protocol instances configured by calling their
108
 * init() hooks with the corresponding instance configuration. The initialization
109
 * code of the protocol is expected to create a new instance according to the
110
 * configuration by calling this function and then modifying the default settings
111
 * to values wanted by the protocol.
112
 */
113
void *
114
proto_new(struct proto_config *c, unsigned size)
115
{
116
  struct protocol *pr = c->protocol;
117
  struct proto *p = mb_allocz(proto_pool, size);
118

    
119
  p->cf = c;
120
  p->debug = c->debug;
121
  p->mrtdump = c->mrtdump;
122
  p->name = c->name;
123
  p->preference = c->preference;
124
  p->disabled = c->disabled;
125
  p->proto = pr;
126
  p->table = c->table->table;
127
  p->hash_key = random_u32();
128
  c->proto = p;
129
  return p;
130
}
131

    
132
static void
133
proto_init_instance(struct proto *p)
134
{
135
  /* Here we cannot use p->cf->name since it won't survive reconfiguration */
136
  p->pool = rp_new(proto_pool, p->proto->name);
137
  p->attn = ev_new(p->pool);
138
  p->attn->data = p;
139

    
140
  if (graceful_restart_state == GRS_INIT)
141
    p->gr_recovery = 1;
142

    
143
  if (! p->proto->multitable)
144
    rt_lock_table(p->table);
145
}
146

    
147
extern pool *rt_table_pool;
148
/**
149
 * proto_add_announce_hook - connect protocol to a routing table
150
 * @p: protocol instance
151
 * @t: routing table to connect to
152
 * @stats: per-table protocol statistics
153
 *
154
 * This function creates a connection between the protocol instance @p and the
155
 * routing table @t, making the protocol hear all changes in the table.
156
 *
157
 * The announce hook is linked in the protocol ahook list. Announce hooks are
158
 * allocated from the routing table resource pool and when protocol accepts
159
 * routes also in the table ahook list. The are linked to the table ahook list
160
 * and unlinked from it depending on export_state (in proto_want_export_up() and
161
 * proto_want_export_down()) and they are automatically freed after the protocol
162
 * is flushed (in proto_fell_down()).
163
 *
164
 * Unless you want to listen to multiple routing tables (as the Pipe protocol
165
 * does), you needn't to worry about this function since the connection to the
166
 * protocol's primary routing table is initialized automatically by the core
167
 * code.
168
 */
169
struct announce_hook *
170
proto_add_announce_hook(struct proto *p, struct rtable *t, struct proto_stats *stats)
171
{
172
  struct announce_hook *h;
173

    
174
  DBG("Connecting protocol %s to table %s\n", p->name, t->name);
175
  PD(p, "Connected to table %s", t->name);
176

    
177
  h = mb_allocz(rt_table_pool, sizeof(struct announce_hook));
178
  h->table = t;
179
  h->proto = p;
180
  h->stats = stats;
181

    
182
  h->next = p->ahooks;
183
  p->ahooks = h;
184

    
185
  if (p->rt_notify && (p->export_state != ES_DOWN))
186
    add_tail(&t->hooks, &h->n);
187
  return h;
188
}
189

    
190
/**
191
 * proto_find_announce_hook - find announce hooks
192
 * @p: protocol instance
193
 * @t: routing table
194
 *
195
 * Returns pointer to announce hook or NULL
196
 */
197
struct announce_hook *
198
proto_find_announce_hook(struct proto *p, struct rtable *t)
199
{
200
  struct announce_hook *a;
201

    
202
  for (a = p->ahooks; a; a = a->next)
203
    if (a->table == t)
204
      return a;
205

    
206
  return NULL;
207
}
208

    
209
static void
210
proto_link_ahooks(struct proto *p)
211
{
212
  struct announce_hook *h;
213

    
214
  if (p->rt_notify)
215
    for(h=p->ahooks; h; h=h->next)
216
      add_tail(&h->table->hooks, &h->n);
217
}
218

    
219
static void
220
proto_unlink_ahooks(struct proto *p)
221
{
222
  struct announce_hook *h;
223

    
224
  if (p->rt_notify)
225
    for(h=p->ahooks; h; h=h->next)
226
      rem_node(&h->n);
227
}
228

    
229
static void
230
proto_free_ahooks(struct proto *p)
231
{
232
  struct announce_hook *h, *hn;
233

    
234
  for(h = p->ahooks; h; h = hn)
235
  {
236
    hn = h->next;
237
    mb_free(h);
238
  }
239

    
240
  p->ahooks = NULL;
241
  p->main_ahook = NULL;
242
}
243

    
244

    
245
/**
246
 * proto_config_new - create a new protocol configuration
247
 * @pr: protocol the configuration will belong to
248
 * @class: SYM_PROTO or SYM_TEMPLATE
249
 *
250
 * Whenever the configuration file says that a new instance
251
 * of a routing protocol should be created, the parser calls
252
 * proto_config_new() to create a configuration entry for this
253
 * instance (a structure staring with the &proto_config header
254
 * containing all the generic items followed by protocol-specific
255
 * ones). Also, the configuration entry gets added to the list
256
 * of protocol instances kept in the configuration.
257
 *
258
 * The function is also used to create protocol templates (when class
259
 * SYM_TEMPLATE is specified), the only difference is that templates
260
 * are not added to the list of protocol instances and therefore not
261
 * initialized during protos_commit()).
262
 */
263
void *
264
proto_config_new(struct protocol *pr, int class)
265
{
266
  struct proto_config *c = cfg_allocz(pr->config_size);
267

    
268
  if (class == SYM_PROTO)
269
    add_tail(&new_config->protos, &c->n);
270
  c->global = new_config;
271
  c->protocol = pr;
272
  c->name = pr->name;
273
  c->preference = pr->preference;
274
  c->class = class;
275
  c->out_filter = FILTER_REJECT;
276
  c->table = c->global->master_rtc;
277
  c->debug = new_config->proto_default_debug;
278
  c->mrtdump = new_config->proto_default_mrtdump;
279
  return c;
280
}
281

    
282
/**
283
 * proto_copy_config - copy a protocol configuration
284
 * @dest: destination protocol configuration
285
 * @src: source protocol configuration
286
 *
287
 * Whenever a new instance of a routing protocol is created from the
288
 * template, proto_copy_config() is called to copy a content of
289
 * the source protocol configuration to the new protocol configuration.
290
 * Name, class and a node in protos list of @dest are kept intact.
291
 * copy_config() protocol hook is used to copy protocol-specific data.
292
 */
293
void
294
proto_copy_config(struct proto_config *dest, struct proto_config *src)
295
{
296
  node old_node;
297
  int old_class;
298
  char *old_name;
299

    
300
  if (dest->protocol != src->protocol)
301
    cf_error("Can't copy configuration from a different protocol type");
302

    
303
  if (dest->protocol->copy_config == NULL)
304
    cf_error("Inheriting configuration for %s is not supported", src->protocol->name);
305

    
306
  DBG("Copying configuration from %s to %s\n", src->name, dest->name);
307

    
308
  /* 
309
   * Copy struct proto_config here. Keep original node, class and name.
310
   * protocol-specific config copy is handled by protocol copy_config() hook
311
   */
312

    
313
  old_node = dest->n;
314
  old_class = dest->class;
315
  old_name = dest->name;
316

    
317
  memcpy(dest, src, sizeof(struct proto_config));
318

    
319
  dest->n = old_node;
320
  dest->class = old_class;
321
  dest->name = old_name;
322

    
323
  dest->protocol->copy_config(dest, src);
324
}
325

    
326
/**
327
 * protos_preconfig - pre-configuration processing
328
 * @c: new configuration
329
 *
330
 * This function calls the preconfig() hooks of all routing
331
 * protocols available to prepare them for reading of the new
332
 * configuration.
333
 */
334
void
335
protos_preconfig(struct config *c)
336
{
337
  struct protocol *p;
338

    
339
  init_list(&c->protos);
340
  DBG("Protocol preconfig:");
341
  WALK_LIST(p, protocol_list)
342
    {
343
      DBG(" %s", p->name);
344
      p->name_counter = 0;
345
      if (p->preconfig)
346
        p->preconfig(p, c);
347
    }
348
  DBG("\n");
349
}
350

    
351
/**
352
 * protos_postconfig - post-configuration processing
353
 * @c: new configuration
354
 *
355
 * This function calls the postconfig() hooks of all protocol
356
 * instances specified in configuration @c. The hooks are not
357
 * called for protocol templates.
358
 */
359
void
360
protos_postconfig(struct config *c)
361
{
362
  struct proto_config *x;
363
  struct protocol *p;
364

    
365
  DBG("Protocol postconfig:");
366
  WALK_LIST(x, c->protos)
367
    {
368
      DBG(" %s", x->name);
369

    
370
      p = x->protocol;
371
      if (p->postconfig)
372
        p->postconfig(x);
373
    }
374
  DBG("\n");
375
}
376

    
377
extern struct protocol proto_unix_iface;
378

    
379
static struct proto *
380
proto_init(struct proto_config *c)
381
{
382
  struct protocol *p = c->protocol;
383
  struct proto *q = p->init(c);
384

    
385
  q->proto_state = PS_DOWN;
386
  q->core_state = FS_HUNGRY;
387
  q->export_state = ES_DOWN;
388
  q->last_state_change = now;
389

    
390
  add_tail(&initial_proto_list, &q->n);
391

    
392
  if (p == &proto_unix_iface)
393
    initial_device_proto = q;
394

    
395
  add_tail(&proto_list, &q->glob_node);
396
  PD(q, "Initializing%s", q->disabled ? " [disabled]" : "");
397
  return q;
398
}
399

    
400
int proto_reconfig_type;  /* Hack to propagate type info to pipe reconfigure hook */
401

    
402
static int
403
proto_reconfigure(struct proto *p, struct proto_config *oc, struct proto_config *nc, int type)
404
{
405
  /* If the protocol is DOWN, we just restart it */
406
  if (p->proto_state == PS_DOWN)
407
    return 0;
408

    
409
  /* If there is a too big change in core attributes, ... */
410
  if ((nc->protocol != oc->protocol) ||
411
      (nc->disabled != p->disabled) ||
412
      (nc->table->table != oc->table->table))
413
    return 0;
414

    
415
  p->debug = nc->debug;
416
  p->mrtdump = nc->mrtdump;
417
  proto_reconfig_type = type;
418

    
419
  /* Execute protocol specific reconfigure hook */
420
  if (! (p->proto->reconfigure && p->proto->reconfigure(p, nc)))
421
    return 0;
422

    
423
  DBG("\t%s: same\n", oc->name);
424
  PD(p, "Reconfigured");
425
  p->cf = nc;
426
  p->name = nc->name;
427
  p->preference = nc->preference;
428

    
429

    
430
  /* Multitable protocols handle rest in their reconfigure hooks */
431
  if (p->proto->multitable)
432
    return 1;
433

    
434
  /* Update filters and limits in the main announce hook
435
     Note that this also resets limit state */
436
  if (p->main_ahook)
437
    {  
438
      struct announce_hook *ah = p->main_ahook;
439
      ah->in_filter = nc->in_filter;
440
      ah->out_filter = nc->out_filter;
441
      ah->rx_limit = nc->rx_limit;
442
      ah->in_limit = nc->in_limit;
443
      ah->out_limit = nc->out_limit;
444
      ah->in_keep_filtered = nc->in_keep_filtered;
445
      proto_verify_limits(ah);
446
    }
447

    
448
  /* Update routes when filters changed. If the protocol in not UP,
449
     it has no routes and we can ignore such changes */
450
  if ((p->proto_state != PS_UP) || (type == RECONFIG_SOFT))
451
    return 1;
452

    
453
  int import_changed = ! filter_same(nc->in_filter, oc->in_filter);
454
  int export_changed = ! filter_same(nc->out_filter, oc->out_filter);
455

    
456
  /* We treat a change in preferences by reimporting routes */
457
  if (nc->preference != oc->preference)
458
    import_changed = 1;
459

    
460
  if (import_changed || export_changed)
461
    log(L_INFO "Reloading protocol %s", p->name);
462

    
463
  /* If import filter changed, call reload hook */
464
  if (import_changed && ! (p->reload_routes && p->reload_routes(p)))
465
    {
466
      /* Now, the protocol is reconfigured. But route reload failed
467
         and we have to do regular protocol restart. */
468
      log(L_INFO "Restarting protocol %s", p->name);
469
      p->disabled = 1;
470
      p->down_code = PDC_CF_RESTART;
471
      proto_rethink_goal(p);
472
      p->disabled = 0;
473
      proto_rethink_goal(p);
474
      return 1;
475
    }
476

    
477
  if (export_changed)
478
    proto_request_feeding(p);
479

    
480
  return 1;
481
}
482

    
483
/**
484
 * protos_commit - commit new protocol configuration
485
 * @new: new configuration
486
 * @old: old configuration or %NULL if it's boot time config
487
 * @force_reconfig: force restart of all protocols (used for example
488
 * when the router ID changes)
489
 * @type: type of reconfiguration (RECONFIG_SOFT or RECONFIG_HARD)
490
 *
491
 * Scan differences between @old and @new configuration and adjust all
492
 * protocol instances to conform to the new configuration.
493
 *
494
 * When a protocol exists in the new configuration, but it doesn't in the
495
 * original one, it's immediately started. When a collision with the other
496
 * running protocol would arise, the new protocol will be temporarily stopped
497
 * by the locking mechanism.
498
 *
499
 * When a protocol exists in the old configuration, but it doesn't in the
500
 * new one, it's shut down and deleted after the shutdown completes.
501
 *
502
 * When a protocol exists in both configurations, the core decides
503
 * whether it's possible to reconfigure it dynamically - it checks all
504
 * the core properties of the protocol (changes in filters are ignored
505
 * if type is RECONFIG_SOFT) and if they match, it asks the
506
 * reconfigure() hook of the protocol to see if the protocol is able
507
 * to switch to the new configuration.  If it isn't possible, the
508
 * protocol is shut down and a new instance is started with the new
509
 * configuration after the shutdown is completed.
510
 */
511
void
512
protos_commit(struct config *new, struct config *old, int force_reconfig, int type)
513
{
514
  struct proto_config *oc, *nc;
515
  struct proto *p, *n;
516
  struct symbol *sym;
517

    
518
  DBG("protos_commit:\n");
519
  if (old)
520
    {
521
      WALK_LIST(oc, old->protos)
522
        {
523
          p = oc->proto;
524
          sym = cf_find_symbol(new, oc->name);
525
          if (sym && sym->class == SYM_PROTO && !new->shutdown)
526
            {
527
              /* Found match, let's check if we can smoothly switch to new configuration */
528
              /* No need to check description */
529
              nc = sym->def;
530
              nc->proto = p;
531

    
532
              /* We will try to reconfigure protocol p */
533
              if (! force_reconfig && proto_reconfigure(p, oc, nc, type))
534
                continue;
535

    
536
              /* Unsuccessful, we will restart it */
537
              if (!p->disabled && !nc->disabled)
538
                log(L_INFO "Restarting protocol %s", p->name);
539
              else if (p->disabled && !nc->disabled)
540
                log(L_INFO "Enabling protocol %s", p->name);
541
              else if (!p->disabled && nc->disabled)
542
                log(L_INFO "Disabling protocol %s", p->name);
543

    
544
              p->down_code = nc->disabled ? PDC_CF_DISABLE : PDC_CF_RESTART;
545
              p->cf_new = nc;
546
            }
547
          else if (!new->shutdown)
548
            {
549
              log(L_INFO "Removing protocol %s", p->name);
550
              p->down_code = PDC_CF_REMOVE;
551
              p->cf_new = NULL;
552
            }
553
          else /* global shutdown */
554
            {
555
              p->down_code = PDC_CMD_SHUTDOWN;
556
              p->cf_new = NULL;
557
            }
558

    
559
          p->reconfiguring = 1;
560
          config_add_obstacle(old);
561
          proto_rethink_goal(p);
562
        }
563
    }
564

    
565
  WALK_LIST(nc, new->protos)
566
    if (!nc->proto)
567
      {
568
        if (old)                /* Not a first-time configuration */
569
          log(L_INFO "Adding protocol %s", nc->name);
570
        proto_init(nc);
571
      }
572
  DBG("\tdone\n");
573

    
574
  DBG("Protocol start\n");
575

    
576
  /* Start device protocol first */
577
  if (initial_device_proto)
578
  {
579
    proto_rethink_goal(initial_device_proto);
580
    initial_device_proto = NULL;
581
  }
582

    
583
  /* Determine router ID for the first time - it has to be here and not in
584
     global_commit() because it is postponed after start of device protocol */
585
  if (!config->router_id)
586
    {
587
      config->router_id = if_choose_router_id(config->router_id_from, 0);
588
      if (!config->router_id)
589
        die("Cannot determine router ID, please configure it manually");
590
    }
591

    
592
  /* Start all other protocols */
593
  WALK_LIST_DELSAFE(p, n, initial_proto_list)
594
    proto_rethink_goal(p);
595
}
596

    
597
static void
598
proto_rethink_goal(struct proto *p)
599
{
600
  struct protocol *q;
601
  byte goal;
602

    
603
  if (p->reconfiguring && p->core_state == FS_HUNGRY && p->proto_state == PS_DOWN)
604
    {
605
      struct proto_config *nc = p->cf_new;
606
      DBG("%s has shut down for reconfiguration\n", p->name);
607
      p->cf->proto = NULL;
608
      config_del_obstacle(p->cf->global);
609
      rem_node(&p->n);
610
      rem_node(&p->glob_node);
611
      mb_free(p);
612
      if (!nc)
613
        return;
614
      p = proto_init(nc);
615
    }
616

    
617
  /* Determine what state we want to reach */
618
  if (p->disabled || p->reconfiguring)
619
    goal = PS_DOWN;
620
  else
621
    goal = PS_UP;
622

    
623
  q = p->proto;
624
  if (goal == PS_UP)                         /* Going up */
625
    {
626
      if (p->proto_state == PS_DOWN && p->core_state == FS_HUNGRY)
627
        {
628
          DBG("Kicking %s up\n", p->name);
629
          PD(p, "Starting");
630
          proto_init_instance(p);
631
          proto_notify_state(p, (q->start ? q->start(p) : PS_UP));
632
        }
633
    }
634
  else                                         /* Going down */
635
    {
636
      if (p->proto_state == PS_START || p->proto_state == PS_UP)
637
        {
638
          DBG("Kicking %s down\n", p->name);
639
          PD(p, "Shutting down");
640
          proto_notify_state(p, (q->shutdown ? q->shutdown(p) : PS_DOWN));
641
        }
642
    }
643
}
644

    
645

    
646
/**
647
 * DOC: Graceful restart recovery
648
 *
649
 * Graceful restart of a router is a process when the routing plane (e.g. BIRD)
650
 * restarts but both the forwarding plane (e.g kernel routing table) and routing
651
 * neighbors keep proper routes, and therefore uninterrupted packet forwarding
652
 * is maintained.
653
 *
654
 * BIRD implements graceful restart recovery by deferring export of routes to
655
 * protocols until routing tables are refilled with the expected content. After
656
 * start, protocols generate routes as usual, but routes are not propagated to
657
 * them, until protocols report that they generated all routes. After that,
658
 * graceful restart recovery is finished and the export (and the initial feed)
659
 * to protocols is enabled.
660
 *
661
 * When graceful restart recovery need is detected during initialization, then
662
 * enabled protocols are marked with @gr_recovery flag before start. Such
663
 * protocols then decide how to proceed with graceful restart, participation is
664
 * voluntary. Protocols could lock the recovery by proto_graceful_restart_lock()
665
 * (stored in @gr_lock flag), which means that they want to postpone the end of
666
 * the recovery until they converge and then unlock it. They also could set
667
 * @gr_wait before advancing to %PS_UP, which means that the core should defer
668
 * route export to that protocol until the end of the recovery. This should be
669
 * done by protocols that expect their neigbors to keep the proper routes
670
 * (kernel table, BGP sessions with BGP graceful restart capability).
671
 *
672
 * The graceful restart recovery is finished when either all graceful restart
673
 * locks are unlocked or when graceful restart wait timer fires.
674
 *
675
 */
676

    
677
static void graceful_restart_done(struct timer *t);
678

    
679
/**
680
 * graceful_restart_recovery - request initial graceful restart recovery
681
 *
682
 * Called by the platform initialization code if the need for recovery
683
 * after graceful restart is detected during boot. Have to be called
684
 * before protos_commit().
685
 */
686
void
687
graceful_restart_recovery(void)
688
{
689
  graceful_restart_state = GRS_INIT;
690
}
691

    
692
/**
693
 * graceful_restart_init - initialize graceful restart
694
 *
695
 * When graceful restart recovery was requested, the function starts an active
696
 * phase of the recovery and initializes graceful restart wait timer. The
697
 * function have to be called after protos_commit().
698
 */
699
void
700
graceful_restart_init(void)
701
{
702
  if (!graceful_restart_state)
703
    return;
704

    
705
  log(L_INFO "Graceful restart started");
706

    
707
  if (!graceful_restart_locks)
708
    {
709
      graceful_restart_done(NULL);
710
      return;
711
    }
712

    
713
  graceful_restart_state = GRS_ACTIVE;
714
  gr_wait_timer = tm_new(proto_pool);
715
  gr_wait_timer->hook = graceful_restart_done;
716
  tm_start(gr_wait_timer, config->gr_wait);
717
}
718

    
719
/**
720
 * graceful_restart_done - finalize graceful restart
721
 * @t: unused
722
 *
723
 * When there are no locks on graceful restart, the functions finalizes the
724
 * graceful restart recovery. Protocols postponing route export until the end of
725
 * the recovery are awakened and the export to them is enabled. All other
726
 * related state is cleared. The function is also called when the graceful
727
 * restart wait timer fires (but there are still some locks).
728
 */
729
static void
730
graceful_restart_done(struct timer *t UNUSED)
731
{
732
  struct proto *p;
733
  node *n;
734

    
735
  log(L_INFO "Graceful restart done");
736
  graceful_restart_state = GRS_DONE;
737

    
738
  WALK_LIST2(p, n, proto_list, glob_node)
739
    {
740
      if (!p->gr_recovery)
741
        continue;
742

    
743
      /* Resume postponed export of routes */
744
      if ((p->proto_state == PS_UP) && p->gr_wait)
745
      {
746
        proto_want_export_up(p);
747
        proto_log_state_change(p);
748
      }
749

    
750
      /* Cleanup */
751
      p->gr_recovery = 0;
752
      p->gr_wait = 0;
753
      p->gr_lock = 0;
754
    }
755

    
756
  graceful_restart_locks = 0;
757
}
758

    
759
void
760
graceful_restart_show_status(void)
761
{
762
  if (graceful_restart_state != GRS_ACTIVE)
763
    return;
764

    
765
  cli_msg(-24, "Graceful restart recovery in progress");
766
  cli_msg(-24, "  Waiting for %d protocols to recover", graceful_restart_locks);
767
  cli_msg(-24, "  Wait timer is %d/%d", tm_remains(gr_wait_timer), config->gr_wait);
768
}
769

    
770
/**
771
 * proto_graceful_restart_lock - lock graceful restart by protocol
772
 * @p: protocol instance
773
 *
774
 * This function allows a protocol to postpone the end of graceful restart
775
 * recovery until it converges. The lock is removed when the protocol calls
776
 * proto_graceful_restart_unlock() or when the protocol is stopped.
777
 *
778
 * The function have to be called during the initial phase of graceful restart
779
 * recovery and only for protocols that are part of graceful restart (i.e. their
780
 * @gr_recovery is set), which means it should be called from protocol start
781
 * hooks.
782
 */
783
void
784
proto_graceful_restart_lock(struct proto *p)
785
{
786
  ASSERT(graceful_restart_state == GRS_INIT);
787
  ASSERT(p->gr_recovery);
788

    
789
  if (p->gr_lock)
790
    return;
791

    
792
  p->gr_lock = 1;
793
  graceful_restart_locks++;
794
}
795

    
796
/**
797
 * proto_graceful_restart_unlock - unlock graceful restart by protocol
798
 * @p: protocol instance
799
 *
800
 * This function unlocks a lock from proto_graceful_restart_lock(). It is also
801
 * automatically called when the lock holding protocol went down.
802
 */
803
void
804
proto_graceful_restart_unlock(struct proto *p)
805
{
806
  if (!p->gr_lock)
807
    return;
808

    
809
  p->gr_lock = 0;
810
  graceful_restart_locks--;
811

    
812
  if ((graceful_restart_state == GRS_ACTIVE) && !graceful_restart_locks)
813
    tm_start(gr_wait_timer, 0);
814
}
815

    
816

    
817

    
818
/**
819
 * protos_dump_all - dump status of all protocols
820
 *
821
 * This function dumps status of all existing protocol instances to the
822
 * debug output. It involves printing of general status information
823
 * such as protocol states, its position on the protocol lists
824
 * and also calling of a dump() hook of the protocol to print
825
 * the internals.
826
 */
827
void
828
protos_dump_all(void)
829
{
830
  struct proto *p;
831
  struct announce_hook *a;
832

    
833
  debug("Protocols:\n");
834

    
835
  WALK_LIST(p, active_proto_list)
836
    {
837
      debug("  protocol %s state %s/%s\n", p->name,
838
            p_states[p->proto_state], c_states[p->core_state]);
839
      for (a = p->ahooks; a; a = a->next)
840
        {
841
          debug("\tTABLE %s\n", a->table->name);
842
          if (a->in_filter)
843
            debug("\tInput filter: %s\n", filter_name(a->in_filter));
844
          if (a->out_filter != FILTER_REJECT)
845
            debug("\tOutput filter: %s\n", filter_name(a->out_filter));
846
        }
847
      if (p->disabled)
848
        debug("\tDISABLED\n");
849
      else if (p->proto->dump)
850
        p->proto->dump(p);
851
    }
852
  WALK_LIST(p, inactive_proto_list)
853
    debug("  inactive %s: state %s/%s\n", p->name, p_states[p->proto_state], c_states[p->core_state]);
854
  WALK_LIST(p, initial_proto_list)
855
    debug("  initial %s\n", p->name);
856
  WALK_LIST(p, flush_proto_list)
857
    debug("  flushing %s\n", p->name);
858
}
859

    
860
/**
861
 * proto_build - make a single protocol available
862
 * @p: the protocol
863
 *
864
 * After the platform specific initialization code uses protos_build()
865
 * to add all the standard protocols, it should call proto_build() for
866
 * all platform specific protocols to inform the core that they exist.
867
 */
868
void
869
proto_build(struct protocol *p)
870
{
871
  add_tail(&protocol_list, &p->n);
872
  if (p->attr_class)
873
    {
874
      ASSERT(!attr_class_to_protocol[p->attr_class]);
875
      attr_class_to_protocol[p->attr_class] = p;
876
    }
877
}
878

    
879
/* FIXME: convert this call to some protocol hook */
880
extern void bfd_init_all(void);
881

    
882
/**
883
 * protos_build - build a protocol list
884
 *
885
 * This function is called during BIRD startup to insert
886
 * all standard protocols to the global protocol list. Insertion
887
 * of platform specific protocols (such as the kernel syncer)
888
 * is in the domain of competence of the platform dependent
889
 * startup code.
890
 */
891
void
892
protos_build(void)
893
{
894
  init_list(&protocol_list);
895
  init_list(&proto_list);
896
  init_list(&active_proto_list);
897
  init_list(&inactive_proto_list);
898
  init_list(&initial_proto_list);
899
  init_list(&flush_proto_list);
900
  proto_build(&proto_device);
901
#ifdef CONFIG_RADV
902
  proto_build(&proto_radv);
903
#endif
904
#ifdef CONFIG_RIP
905
  proto_build(&proto_rip);
906
#endif
907
#ifdef CONFIG_STATIC
908
  proto_build(&proto_static);
909
#endif
910
#ifdef CONFIG_OSPF
911
  proto_build(&proto_ospf);
912
#endif
913
#ifdef CONFIG_PIPE
914
  proto_build(&proto_pipe);
915
#endif
916
#ifdef CONFIG_BGP
917
  proto_build(&proto_bgp);
918
#endif
919
#ifdef CONFIG_BFD
920
  proto_build(&proto_bfd);
921
  bfd_init_all();
922
#endif
923
#ifdef CONFIG_BABEL
924
  proto_build(&proto_babel);
925
#endif
926

    
927
  proto_pool = rp_new(&root_pool, "Protocols");
928
  proto_flush_event = ev_new(proto_pool);
929
  proto_flush_event->hook = proto_flush_loop;
930
  proto_shutdown_timer = tm_new(proto_pool);
931
  proto_shutdown_timer->hook = proto_shutdown_loop;
932
}
933

    
934
static void
935
proto_feed_more(void *P)
936
{
937
  struct proto *p = P;
938

    
939
  if (p->export_state != ES_FEEDING)
940
    return;
941

    
942
  DBG("Feeding protocol %s continued\n", p->name);
943
  if (rt_feed_baby(p))
944
    {
945
      DBG("Feeding protocol %s finished\n", p->name);
946
      p->export_state = ES_READY;
947
      proto_log_state_change(p);
948

    
949
      if (p->feed_end)
950
        p->feed_end(p);
951
    }
952
  else
953
    {
954
      p->attn->hook = proto_feed_more;
955
      ev_schedule(p->attn);                /* Will continue later... */
956
    }
957
}
958

    
959
static void
960
proto_feed_initial(void *P)
961
{
962
  struct proto *p = P;
963

    
964
  if (p->export_state != ES_FEEDING)
965
    return;
966

    
967
  DBG("Feeding protocol %s\n", p->name);
968

    
969
  if_feed_baby(p);
970
  proto_feed_more(P);
971
}
972

    
973
static void
974
proto_schedule_feed(struct proto *p, int initial)
975
{
976
  DBG("%s: Scheduling meal\n", p->name);
977

    
978
  p->export_state = ES_FEEDING;
979
  p->refeeding = !initial;
980

    
981
  p->attn->hook = initial ? proto_feed_initial : proto_feed_more;
982
  ev_schedule(p->attn);
983

    
984
  if (p->feed_begin)
985
    p->feed_begin(p, initial);
986
}
987

    
988
/*
989
 * Flushing loop is responsible for flushing routes and protocols
990
 * after they went down. It runs in proto_flush_event. At the start of
991
 * one round, protocols waiting to flush are marked in
992
 * proto_schedule_flush_loop(). At the end of the round (when routing
993
 * table flush is complete), marked protocols are flushed and a next
994
 * round may start.
995
 */
996

    
997
static int flush_loop_state;        /* 1 -> running */
998

    
999
static void
1000
proto_schedule_flush_loop(void)
1001
{
1002
  struct proto *p;
1003
  struct announce_hook *h;
1004

    
1005
  if (flush_loop_state)
1006
    return;
1007
  flush_loop_state = 1;
1008

    
1009
  WALK_LIST(p, flush_proto_list)
1010
  {
1011
    p->flushing = 1;
1012
    for (h=p->ahooks; h; h=h->next)
1013
      rt_mark_for_prune(h->table);
1014
  }
1015

    
1016
  ev_schedule(proto_flush_event);
1017
}
1018

    
1019
static void
1020
proto_flush_loop(void *unused UNUSED)
1021
{
1022
  struct proto *p;
1023

    
1024
  if (! rt_prune_loop())
1025
    {
1026
      /* Rtable pruning is not finished */
1027
      ev_schedule(proto_flush_event);
1028
      return;
1029
    }
1030

    
1031
  rt_prune_sources();
1032

    
1033
 again:
1034
  WALK_LIST(p, flush_proto_list)
1035
    if (p->flushing)
1036
      {
1037
        /* This will flush interfaces in the same manner
1038
           like rt_prune_all() flushes routes */
1039
        if (p->proto == &proto_unix_iface)
1040
          if_flush_ifaces(p);
1041

    
1042
        DBG("Flushing protocol %s\n", p->name);
1043
        p->flushing = 0;
1044
        p->core_state = FS_HUNGRY;
1045
        proto_relink(p);
1046
        proto_log_state_change(p);
1047
        if (p->proto_state == PS_DOWN)
1048
          proto_fell_down(p);
1049
        goto again;
1050
      }
1051

    
1052
  /* This round finished, perhaps there will be another one */
1053
  flush_loop_state = 0;
1054
  if (!EMPTY_LIST(flush_proto_list))
1055
    proto_schedule_flush_loop();
1056
}
1057

    
1058

    
1059
/* Temporary hack to propagate restart to BGP */
1060
int proto_restart;
1061

    
1062
static void
1063
proto_shutdown_loop(struct timer *t UNUSED)
1064
{
1065
  struct proto *p, *p_next;
1066

    
1067
  WALK_LIST_DELSAFE(p, p_next, active_proto_list)
1068
    if (p->down_sched)
1069
      {
1070
        proto_restart = (p->down_sched == PDS_RESTART);
1071

    
1072
        p->disabled = 1;
1073
        proto_rethink_goal(p);
1074
        if (proto_restart)
1075
          {
1076
            p->disabled = 0;
1077
            proto_rethink_goal(p);
1078
          }
1079
      }
1080
}
1081

    
1082
static inline void
1083
proto_schedule_down(struct proto *p, byte restart, byte code)
1084
{
1085
  /* Does not work for other states (even PS_START) */
1086
  ASSERT(p->proto_state == PS_UP);
1087

    
1088
  /* Scheduled restart may change to shutdown, but not otherwise */
1089
  if (p->down_sched == PDS_DISABLE)
1090
    return;
1091

    
1092
  p->down_sched = restart ? PDS_RESTART : PDS_DISABLE;
1093
  p->down_code = code;
1094
  tm_start_max(proto_shutdown_timer, restart ? 2 : 0);
1095
}
1096

    
1097

    
1098
/**
1099
 * proto_request_feeding - request feeding routes to the protocol
1100
 * @p: given protocol 
1101
 *
1102
 * Sometimes it is needed to send again all routes to the
1103
 * protocol. This is called feeding and can be requested by this
1104
 * function. This would cause protocol export state transition
1105
 * to ES_FEEDING (during feeding) and when completed, it will
1106
 * switch back to ES_READY. This function can be called even
1107
 * when feeding is already running, in that case it is restarted.
1108
 */
1109
void
1110
proto_request_feeding(struct proto *p)
1111
{
1112
  ASSERT(p->proto_state == PS_UP);
1113

    
1114
  /* Do nothing if we are still waiting for feeding */
1115
  if (p->export_state == ES_DOWN)
1116
    return;
1117

    
1118
  /* If we are already feeding, we want to restart it */
1119
  if (p->export_state == ES_FEEDING)
1120
    {
1121
      /* Unless feeding is in initial state */
1122
      if (p->attn->hook == proto_feed_initial)
1123
        return;
1124

    
1125
      rt_feed_baby_abort(p);
1126
    }
1127

    
1128
  /* FIXME: This should be changed for better support of multitable protos */
1129
  struct announce_hook *ah;
1130
  for (ah = p->ahooks; ah; ah = ah->next)
1131
    proto_reset_limit(ah->out_limit);
1132

    
1133
  /* Hack: reset exp_routes during refeed, and do not decrease it later */
1134
  p->stats.exp_routes = 0;
1135

    
1136
  proto_schedule_feed(p, 0);
1137
  proto_log_state_change(p);
1138
}
1139

    
1140
static const char *
1141
proto_limit_name(struct proto_limit *l)
1142
{
1143
  const char *actions[] = {
1144
    [PLA_WARN] = "warn",
1145
    [PLA_BLOCK] = "block",
1146
    [PLA_RESTART] = "restart",
1147
    [PLA_DISABLE] = "disable",
1148
  };
1149

    
1150
  return actions[l->action];
1151
}
1152

    
1153
/**
1154
 * proto_notify_limit: notify about limit hit and take appropriate action
1155
 * @ah: announce hook
1156
 * @l: limit being hit
1157
 * @dir: limit direction (PLD_*)
1158
 * @rt_count: the number of routes 
1159
 *
1160
 * The function is called by the route processing core when limit @l
1161
 * is breached. It activates the limit and tooks appropriate action
1162
 * according to @l->action.
1163
 */
1164
void
1165
proto_notify_limit(struct announce_hook *ah, struct proto_limit *l, int dir, u32 rt_count)
1166
{
1167
  const char *dir_name[PLD_MAX] = { "receive", "import" , "export" };
1168
  const byte dir_down[PLD_MAX] = { PDC_RX_LIMIT_HIT, PDC_IN_LIMIT_HIT, PDC_OUT_LIMIT_HIT };
1169
  struct proto *p = ah->proto;
1170

    
1171
  if (l->state == PLS_BLOCKED)
1172
    return;
1173

    
1174
  /* For warning action, we want the log message every time we hit the limit */
1175
  if (!l->state || ((l->action == PLA_WARN) && (rt_count == l->limit)))
1176
    log(L_WARN "Protocol %s hits route %s limit (%d), action: %s",
1177
        p->name, dir_name[dir], l->limit, proto_limit_name(l));
1178

    
1179
  switch (l->action)
1180
    {
1181
    case PLA_WARN:
1182
      l->state = PLS_ACTIVE;
1183
      break;
1184

    
1185
    case PLA_BLOCK:
1186
      l->state = PLS_BLOCKED;
1187
      break;
1188

    
1189
    case PLA_RESTART:
1190
    case PLA_DISABLE:
1191
      l->state = PLS_BLOCKED;
1192
      if (p->proto_state == PS_UP)
1193
        proto_schedule_down(p, l->action == PLA_RESTART, dir_down[dir]);
1194
      break;
1195
    }
1196
}
1197

    
1198
void
1199
proto_verify_limits(struct announce_hook *ah)
1200
{
1201
  struct proto_limit *l;
1202
  struct proto_stats *stats = ah->stats;
1203
  u32 all_routes = stats->imp_routes + stats->filt_routes;
1204

    
1205
  l = ah->rx_limit;
1206
  if (l && (all_routes > l->limit))
1207
    proto_notify_limit(ah, l, PLD_RX, all_routes);
1208

    
1209
  l = ah->in_limit;
1210
  if (l && (stats->imp_routes > l->limit))
1211
    proto_notify_limit(ah, l, PLD_IN, stats->imp_routes);
1212

    
1213
  l = ah->out_limit;
1214
  if (l && (stats->exp_routes > l->limit))
1215
    proto_notify_limit(ah, l, PLD_OUT, stats->exp_routes);
1216
}
1217

    
1218

    
1219
static void
1220
proto_want_core_up(struct proto *p)
1221
{
1222
  ASSERT(p->core_state == FS_HUNGRY);
1223

    
1224
  if (!p->proto->multitable)
1225
    {
1226
      p->main_source = rt_get_source(p, 0);
1227
      rt_lock_source(p->main_source);
1228

    
1229
      /* Connect protocol to routing table */
1230
      p->main_ahook = proto_add_announce_hook(p, p->table, &p->stats);
1231
      p->main_ahook->in_filter = p->cf->in_filter;
1232
      p->main_ahook->out_filter = p->cf->out_filter;
1233
      p->main_ahook->rx_limit = p->cf->rx_limit;
1234
      p->main_ahook->in_limit = p->cf->in_limit;
1235
      p->main_ahook->out_limit = p->cf->out_limit;
1236
      p->main_ahook->in_keep_filtered = p->cf->in_keep_filtered;
1237

    
1238
      proto_reset_limit(p->main_ahook->rx_limit);
1239
      proto_reset_limit(p->main_ahook->in_limit);
1240
      proto_reset_limit(p->main_ahook->out_limit);
1241
    }
1242

    
1243
  p->core_state = FS_HAPPY;
1244
  proto_relink(p);
1245
}
1246

    
1247
static void
1248
proto_want_export_up(struct proto *p)
1249
{
1250
  ASSERT(p->core_state == FS_HAPPY);
1251
  ASSERT(p->export_state == ES_DOWN);
1252

    
1253
  proto_link_ahooks(p);
1254
  proto_schedule_feed(p, 1); /* Sets ES_FEEDING */
1255
}
1256

    
1257
static void
1258
proto_want_export_down(struct proto *p)
1259
{
1260
  ASSERT(p->export_state != ES_DOWN);
1261

    
1262
  /* Need to abort feeding */
1263
  if (p->export_state == ES_FEEDING)
1264
    rt_feed_baby_abort(p);
1265

    
1266
  p->export_state = ES_DOWN;
1267
  p->stats.exp_routes = 0;
1268
  proto_unlink_ahooks(p);
1269
}
1270

    
1271
static void
1272
proto_want_core_down(struct proto *p)
1273
{
1274
  ASSERT(p->core_state == FS_HAPPY);
1275
  ASSERT(p->export_state == ES_DOWN);
1276

    
1277
  p->core_state = FS_FLUSHING;
1278
  proto_relink(p);
1279
  proto_schedule_flush_loop();
1280

    
1281
  if (!p->proto->multitable)
1282
    {
1283
      rt_unlock_source(p->main_source);
1284
      p->main_source = NULL;
1285
    }
1286
}
1287

    
1288
static void
1289
proto_falling_down(struct proto *p)
1290
{
1291
  p->gr_recovery = 0;
1292
  p->gr_wait = 0;
1293
  if (p->gr_lock)
1294
    proto_graceful_restart_unlock(p);
1295
}
1296

    
1297
static void
1298
proto_fell_down(struct proto *p)
1299
{
1300
  DBG("Protocol %s down\n", p->name);
1301

    
1302
  u32 all_routes = p->stats.imp_routes + p->stats.filt_routes;
1303
  if (all_routes != 0)
1304
    log(L_ERR "Protocol %s is down but still has %d routes", p->name, all_routes);
1305

    
1306
  bzero(&p->stats, sizeof(struct proto_stats));
1307
  proto_free_ahooks(p);
1308

    
1309
  if (! p->proto->multitable)
1310
    rt_unlock_table(p->table);
1311

    
1312
  if (p->proto->cleanup)
1313
    p->proto->cleanup(p);
1314

    
1315
  proto_rethink_goal(p);
1316
}
1317

    
1318

    
1319
/**
1320
 * proto_notify_state - notify core about protocol state change
1321
 * @p: protocol the state of which has changed
1322
 * @ps: the new status
1323
 *
1324
 * Whenever a state of a protocol changes due to some event internal
1325
 * to the protocol (i.e., not inside a start() or shutdown() hook),
1326
 * it should immediately notify the core about the change by calling
1327
 * proto_notify_state() which will write the new state to the &proto
1328
 * structure and take all the actions necessary to adapt to the new
1329
 * state. State change to PS_DOWN immediately frees resources of protocol
1330
 * and might execute start callback of protocol; therefore,
1331
 * it should be used at tail positions of protocol callbacks.
1332
 */
1333
void
1334
proto_notify_state(struct proto *p, unsigned ps)
1335
{
1336
  unsigned ops = p->proto_state;
1337
  unsigned cs = p->core_state;
1338
  unsigned es = p->export_state;
1339

    
1340
  DBG("%s reporting state transition %s/%s -> */%s\n", p->name, c_states[cs], p_states[ops], p_states[ps]);
1341
  if (ops == ps)
1342
    return;
1343

    
1344
  p->proto_state = ps;
1345
  p->last_state_change = now;
1346

    
1347
  switch (ps)
1348
    {
1349
    case PS_START:
1350
      ASSERT(ops == PS_DOWN || ops == PS_UP);
1351
      ASSERT(cs == FS_HUNGRY || cs == FS_HAPPY);
1352

    
1353
      if (es != ES_DOWN)
1354
        proto_want_export_down(p);
1355
      break;
1356

    
1357
    case PS_UP:
1358
      ASSERT(ops == PS_DOWN || ops == PS_START);
1359
      ASSERT(cs == FS_HUNGRY || cs == FS_HAPPY);
1360
      ASSERT(es == ES_DOWN);
1361

    
1362
      if (cs == FS_HUNGRY)
1363
        proto_want_core_up(p);
1364
      if (!p->gr_wait)
1365
        proto_want_export_up(p);
1366
      break;
1367

    
1368
    case PS_STOP:
1369
      ASSERT(ops == PS_START || ops == PS_UP);
1370

    
1371
      p->down_sched = 0;
1372

    
1373
      if (es != ES_DOWN)
1374
        proto_want_export_down(p);
1375
      if (cs == FS_HAPPY)
1376
        proto_want_core_down(p);
1377
      proto_falling_down(p);
1378
      break;
1379

    
1380
    case PS_DOWN:
1381
      p->down_code = 0;
1382
      p->down_sched = 0;
1383

    
1384
      if (es != ES_DOWN)
1385
        proto_want_export_down(p);
1386
      if (cs == FS_HAPPY)
1387
        proto_want_core_down(p);
1388
      if (ops != PS_STOP)
1389
        proto_falling_down(p);
1390

    
1391
      neigh_prune(); // FIXME convert neighbors to resource?
1392
      rfree(p->pool);
1393
      p->pool = NULL;
1394

    
1395
      if (cs == FS_HUNGRY)                /* Shutdown finished */
1396
        {
1397
          proto_log_state_change(p);
1398
          proto_fell_down(p);
1399
          return;                        /* The protocol might have ceased to exist */
1400
        }
1401
      break;
1402

    
1403
    default:
1404
      bug("%s: Invalid state %d", p->name, ps);
1405
    }
1406

    
1407
  proto_log_state_change(p);
1408
}
1409

    
1410
/*
1411
 *  CLI Commands
1412
 */
1413

    
1414
static char *
1415
proto_state_name(struct proto *p)
1416
{
1417
#define P(x,y) ((x << 4) | y)
1418
  switch (P(p->proto_state, p->core_state))
1419
    {
1420
    case P(PS_DOWN, FS_HUNGRY):                return "down";
1421
    case P(PS_START, FS_HUNGRY):
1422
    case P(PS_START, FS_HAPPY):                return "start";
1423
    case P(PS_UP, FS_HAPPY):
1424
      switch (p->export_state)
1425
        {
1426
        case ES_DOWN:                        return "wait";
1427
        case ES_FEEDING:                return "feed";
1428
        case ES_READY:                        return "up";
1429
        default:                              return "???";
1430
        }
1431
    case P(PS_STOP, FS_HUNGRY):
1432
    case P(PS_STOP, FS_FLUSHING):        return "stop";
1433
    case P(PS_DOWN, FS_FLUSHING):        return "flush";
1434
    default:                              return "???";
1435
    }
1436
#undef P
1437
}
1438

    
1439
static void
1440
proto_show_stats(struct proto_stats *s, int in_keep_filtered)
1441
{
1442
  if (in_keep_filtered)
1443
    cli_msg(-1006, "  Routes:         %u imported, %u filtered, %u exported, %u preferred", 
1444
            s->imp_routes, s->filt_routes, s->exp_routes, s->pref_routes);
1445
  else
1446
    cli_msg(-1006, "  Routes:         %u imported, %u exported, %u preferred", 
1447
            s->imp_routes, s->exp_routes, s->pref_routes);
1448

    
1449
  cli_msg(-1006, "  Route change stats:     received   rejected   filtered    ignored   accepted");
1450
  cli_msg(-1006, "    Import updates:     %10u %10u %10u %10u %10u",
1451
          s->imp_updates_received, s->imp_updates_invalid,
1452
          s->imp_updates_filtered, s->imp_updates_ignored,
1453
          s->imp_updates_accepted);
1454
  cli_msg(-1006, "    Import withdraws:   %10u %10u        --- %10u %10u",
1455
          s->imp_withdraws_received, s->imp_withdraws_invalid,
1456
          s->imp_withdraws_ignored, s->imp_withdraws_accepted);
1457
  cli_msg(-1006, "    Export updates:     %10u %10u %10u        --- %10u",
1458
          s->exp_updates_received, s->exp_updates_rejected,
1459
          s->exp_updates_filtered, s->exp_updates_accepted);
1460
  cli_msg(-1006, "    Export withdraws:   %10u        ---        ---        --- %10u",
1461
          s->exp_withdraws_received, s->exp_withdraws_accepted);
1462
}
1463

    
1464
void
1465
proto_show_limit(struct proto_limit *l, const char *dsc)
1466
{
1467
  if (!l)
1468
    return;
1469

    
1470
  cli_msg(-1006, "  %-16s%d%s", dsc, l->limit, l->state ? " [HIT]" : "");
1471
  cli_msg(-1006, "    Action:       %s", proto_limit_name(l));
1472
}
1473

    
1474
void
1475
proto_show_basic_info(struct proto *p)
1476
{
1477
  // cli_msg(-1006, "  Table:          %s", p->table->name);
1478
  cli_msg(-1006, "  Preference:     %d", p->preference);
1479
  cli_msg(-1006, "  Input filter:   %s", filter_name(p->cf->in_filter));
1480
  cli_msg(-1006, "  Output filter:  %s", filter_name(p->cf->out_filter));
1481

    
1482
  if (graceful_restart_state == GRS_ACTIVE)
1483
    cli_msg(-1006, "  GR recovery:   %s%s",
1484
            p->gr_lock ? " pending" : "",
1485
            p->gr_wait ? " waiting" : "");
1486

    
1487
  proto_show_limit(p->cf->rx_limit, "Receive limit:");
1488
  proto_show_limit(p->cf->in_limit, "Import limit:");
1489
  proto_show_limit(p->cf->out_limit, "Export limit:");
1490

    
1491
  if (p->proto_state != PS_DOWN)
1492
    proto_show_stats(&p->stats, p->cf->in_keep_filtered);
1493
}
1494

    
1495
void
1496
proto_cmd_show(struct proto *p, uint verbose, int cnt)
1497
{
1498
  byte buf[256], tbuf[TM_DATETIME_BUFFER_SIZE];
1499

    
1500
  /* First protocol - show header */
1501
  if (!cnt)
1502
    cli_msg(-2002, "name     proto    table    state  since       info");
1503

    
1504
  buf[0] = 0;
1505
  if (p->proto->get_status)
1506
    p->proto->get_status(p, buf);
1507
  tm_format_datetime(tbuf, &config->tf_proto, p->last_state_change);
1508
  cli_msg(-1002, "%-8s %-8s %-8s %-5s  %-10s  %s",
1509
          p->name,
1510
          p->proto->name,
1511
          p->table->name,
1512
          proto_state_name(p),
1513
          tbuf,
1514
          buf);
1515
  if (verbose)
1516
    {
1517
      if (p->cf->dsc)
1518
        cli_msg(-1006, "  Description:    %s", p->cf->dsc);
1519
      if (p->cf->router_id)
1520
        cli_msg(-1006, "  Router ID:      %R", p->cf->router_id);
1521

    
1522
      if (p->proto->show_proto_info)
1523
        p->proto->show_proto_info(p);
1524
      else
1525
        proto_show_basic_info(p);
1526

    
1527
      cli_msg(-1006, "");
1528
    }
1529
}
1530

    
1531
void
1532
proto_cmd_disable(struct proto *p, uint arg UNUSED, int cnt UNUSED)
1533
{
1534
  if (p->disabled)
1535
    {
1536
      cli_msg(-8, "%s: already disabled", p->name);
1537
      return;
1538
    }
1539

    
1540
  log(L_INFO "Disabling protocol %s", p->name);
1541
  p->disabled = 1;
1542
  p->down_code = PDC_CMD_DISABLE;
1543
  proto_rethink_goal(p);
1544
  cli_msg(-9, "%s: disabled", p->name);
1545
}
1546

    
1547
void
1548
proto_cmd_enable(struct proto *p, uint arg UNUSED, int cnt UNUSED)
1549
{
1550
  if (!p->disabled)
1551
    {
1552
      cli_msg(-10, "%s: already enabled", p->name);
1553
      return;
1554
    }
1555

    
1556
  log(L_INFO "Enabling protocol %s", p->name);
1557
  p->disabled = 0;
1558
  proto_rethink_goal(p);
1559
  cli_msg(-11, "%s: enabled", p->name);
1560
}
1561

    
1562
void
1563
proto_cmd_restart(struct proto *p, uint arg UNUSED, int cnt UNUSED)
1564
{
1565
  if (p->disabled)
1566
    {
1567
      cli_msg(-8, "%s: already disabled", p->name);
1568
      return;
1569
    }
1570

    
1571
  log(L_INFO "Restarting protocol %s", p->name);
1572
  p->disabled = 1;
1573
  p->down_code = PDC_CMD_RESTART;
1574
  proto_rethink_goal(p);
1575
  p->disabled = 0;
1576
  proto_rethink_goal(p);
1577
  cli_msg(-12, "%s: restarted", p->name);
1578
}
1579

    
1580
void
1581
proto_cmd_reload(struct proto *p, uint dir, int cnt UNUSED)
1582
{
1583
  if (p->disabled)
1584
    {
1585
      cli_msg(-8, "%s: already disabled", p->name);
1586
      return;
1587
    }
1588

    
1589
  /* If the protocol in not UP, it has no routes */
1590
  if (p->proto_state != PS_UP)
1591
    return;
1592

    
1593
  log(L_INFO "Reloading protocol %s", p->name);
1594

    
1595
  /* re-importing routes */
1596
  if (dir != CMD_RELOAD_OUT)
1597
    {
1598
      if (! (p->reload_routes && p->reload_routes(p)))
1599
        {
1600
          cli_msg(-8006, "%s: reload failed", p->name);
1601
          return;
1602
        }
1603

    
1604
      /*
1605
       * Should be done before reload_routes() hook?
1606
       * Perhaps, but these hooks work asynchronously.
1607
       */
1608
      if (!p->proto->multitable)
1609
        {
1610
          proto_reset_limit(p->main_ahook->rx_limit);
1611
          proto_reset_limit(p->main_ahook->in_limit);
1612
        }
1613
    }
1614

    
1615
  /* re-exporting routes */
1616
  if (dir != CMD_RELOAD_IN)
1617
    proto_request_feeding(p);
1618

    
1619
  cli_msg(-15, "%s: reloading", p->name);
1620
}
1621

    
1622
void
1623
proto_cmd_debug(struct proto *p, uint mask, int cnt UNUSED)
1624
{
1625
  p->debug = mask;
1626
}
1627

    
1628
void
1629
proto_cmd_mrtdump(struct proto *p, uint mask, int cnt UNUSED)
1630
{
1631
  p->mrtdump = mask;
1632
}
1633

    
1634
static void
1635
proto_apply_cmd_symbol(struct symbol *s, void (* cmd)(struct proto *, uint, int), uint arg)
1636
{
1637
  if (s->class != SYM_PROTO)
1638
    {
1639
      cli_msg(9002, "%s is not a protocol", s->name);
1640
      return;
1641
    }
1642

    
1643
  cmd(((struct proto_config *)s->def)->proto, arg, 0);
1644
  cli_msg(0, "");
1645
}
1646

    
1647
static void
1648
proto_apply_cmd_patt(char *patt, void (* cmd)(struct proto *, uint, int), uint arg)
1649
{
1650
  int cnt = 0;
1651

    
1652
  node *nn;
1653
  WALK_LIST(nn, proto_list)
1654
    {
1655
      struct proto *p = SKIP_BACK(struct proto, glob_node, nn);
1656

    
1657
      if (!patt || patmatch(patt, p->name))
1658
        cmd(p, arg, cnt++);
1659
    }
1660

    
1661
  if (!cnt)
1662
    cli_msg(8003, "No protocols match");
1663
  else
1664
    cli_msg(0, "");
1665
}
1666

    
1667
void
1668
proto_apply_cmd(struct proto_spec ps, void (* cmd)(struct proto *, uint, int),
1669
                int restricted, uint arg)
1670
{
1671
  if (restricted && cli_access_restricted())
1672
    return;
1673

    
1674
  if (ps.patt)
1675
    proto_apply_cmd_patt(ps.ptr, cmd, arg);
1676
  else
1677
    proto_apply_cmd_symbol(ps.ptr, cmd, arg);
1678
}
1679

    
1680
struct proto *
1681
proto_get_named(struct symbol *sym, struct protocol *pr)
1682
{
1683
  struct proto *p, *q;
1684

    
1685
  if (sym)
1686
    {
1687
      if (sym->class != SYM_PROTO)
1688
        cf_error("%s: Not a protocol", sym->name);
1689
      p = ((struct proto_config *)sym->def)->proto;
1690
      if (!p || p->proto != pr)
1691
        cf_error("%s: Not a %s protocol", sym->name, pr->name);
1692
    }
1693
  else
1694
    {
1695
      p = NULL;
1696
      WALK_LIST(q, active_proto_list)
1697
        if (q->proto == pr)
1698
          {
1699
            if (p)
1700
              cf_error("There are multiple %s protocols running", pr->name);
1701
            p = q;
1702
          }
1703
      if (!p)
1704
        cf_error("There is no %s protocol running", pr->name);
1705
    }
1706
  return p;
1707
}