Statistics
| Branch: | Revision:

iof-bird-daemon / nest / proto.c @ 06edbb67

History | View | Annotate | Download (43.6 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
 *
722
 * When there are no locks on graceful restart, the functions finalizes the
723
 * graceful restart recovery. Protocols postponing route export until the end of
724
 * the recovery are awakened and the export to them is enabled. All other
725
 * related state is cleared. The function is also called when the graceful
726
 * restart wait timer fires (but there are still some locks).
727
 */
728
static void
729
graceful_restart_done(struct timer *t UNUSED)
730
{
731
  struct proto *p;
732
  node *n;
733

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

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

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

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

    
755
  graceful_restart_locks = 0;
756
}
757

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

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

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

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

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

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

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

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

    
815

    
816

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

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

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

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

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

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

    
923
  proto_pool = rp_new(&root_pool, "Protocols");
924
  proto_flush_event = ev_new(proto_pool);
925
  proto_flush_event->hook = proto_flush_loop;
926
  proto_shutdown_timer = tm_new(proto_pool);
927
  proto_shutdown_timer->hook = proto_shutdown_loop;
928
}
929

    
930
static void
931
proto_feed_more(void *P)
932
{
933
  struct proto *p = P;
934

    
935
  if (p->export_state != ES_FEEDING)
936
    return;
937

    
938
  DBG("Feeding protocol %s continued\n", p->name);
939
  if (rt_feed_baby(p))
940
    {
941
      DBG("Feeding protocol %s finished\n", p->name);
942
      p->export_state = ES_READY;
943
      proto_log_state_change(p);
944

    
945
      if (p->feed_end)
946
        p->feed_end(p);
947
    }
948
  else
949
    {
950
      p->attn->hook = proto_feed_more;
951
      ev_schedule(p->attn);                /* Will continue later... */
952
    }
953
}
954

    
955
static void
956
proto_feed_initial(void *P)
957
{
958
  struct proto *p = P;
959

    
960
  if (p->export_state != ES_FEEDING)
961
    return;
962

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

    
965
  if_feed_baby(p);
966
  proto_feed_more(P);
967
}
968

    
969
static void
970
proto_schedule_feed(struct proto *p, int initial)
971
{
972
  DBG("%s: Scheduling meal\n", p->name);
973

    
974
  p->export_state = ES_FEEDING;
975
  p->refeeding = !initial;
976

    
977
  p->attn->hook = initial ? proto_feed_initial : proto_feed_more;
978
  ev_schedule(p->attn);
979

    
980
  if (p->feed_begin)
981
    p->feed_begin(p, initial);
982
}
983

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

    
993
static int flush_loop_state;        /* 1 -> running */
994

    
995
static void
996
proto_schedule_flush_loop(void)
997
{
998
  struct proto *p;
999
  struct announce_hook *h;
1000

    
1001
  if (flush_loop_state)
1002
    return;
1003
  flush_loop_state = 1;
1004

    
1005
  WALK_LIST(p, flush_proto_list)
1006
  {
1007
    p->flushing = 1;
1008
    for (h=p->ahooks; h; h=h->next)
1009
      rt_mark_for_prune(h->table);
1010
  }
1011

    
1012
  ev_schedule(proto_flush_event);
1013
}
1014

    
1015
static void
1016
proto_flush_loop(void *unused UNUSED)
1017
{
1018
  struct proto *p;
1019

    
1020
  if (! rt_prune_loop())
1021
    {
1022
      /* Rtable pruning is not finished */
1023
      ev_schedule(proto_flush_event);
1024
      return;
1025
    }
1026

    
1027
  rt_prune_sources();
1028

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

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

    
1048
  /* This round finished, perhaps there will be another one */
1049
  flush_loop_state = 0;
1050
  if (!EMPTY_LIST(flush_proto_list))
1051
    proto_schedule_flush_loop();
1052
}
1053

    
1054

    
1055
/* Temporary hack to propagate restart to BGP */
1056
int proto_restart;
1057

    
1058
static void
1059
proto_shutdown_loop(struct timer *t UNUSED)
1060
{
1061
  struct proto *p, *p_next;
1062

    
1063
  WALK_LIST_DELSAFE(p, p_next, active_proto_list)
1064
    if (p->down_sched)
1065
      {
1066
        proto_restart = (p->down_sched == PDS_RESTART);
1067

    
1068
        p->disabled = 1;
1069
        proto_rethink_goal(p);
1070
        if (proto_restart)
1071
          {
1072
            p->disabled = 0;
1073
            proto_rethink_goal(p);
1074
          }
1075
      }
1076
}
1077

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

    
1084
  /* Scheduled restart may change to shutdown, but not otherwise */
1085
  if (p->down_sched == PDS_DISABLE)
1086
    return;
1087

    
1088
  p->down_sched = restart ? PDS_RESTART : PDS_DISABLE;
1089
  p->down_code = code;
1090
  tm_start_max(proto_shutdown_timer, restart ? 2 : 0);
1091
}
1092

    
1093

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

    
1110
  /* Do nothing if we are still waiting for feeding */
1111
  if (p->export_state == ES_DOWN)
1112
    return;
1113

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

    
1121
      rt_feed_baby_abort(p);
1122
    }
1123

    
1124
  /* FIXME: This should be changed for better support of multitable protos */
1125
  struct announce_hook *ah;
1126
  for (ah = p->ahooks; ah; ah = ah->next)
1127
    proto_reset_limit(ah->out_limit);
1128

    
1129
  /* Hack: reset exp_routes during refeed, and do not decrease it later */
1130
  p->stats.exp_routes = 0;
1131

    
1132
  proto_schedule_feed(p, 0);
1133
  proto_log_state_change(p);
1134
}
1135

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

    
1146
  return actions[l->action];
1147
}
1148

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

    
1167
  if (l->state == PLS_BLOCKED)
1168
    return;
1169

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

    
1175
  switch (l->action)
1176
    {
1177
    case PLA_WARN:
1178
      l->state = PLS_ACTIVE;
1179
      break;
1180

    
1181
    case PLA_BLOCK:
1182
      l->state = PLS_BLOCKED;
1183
      break;
1184

    
1185
    case PLA_RESTART:
1186
    case PLA_DISABLE:
1187
      l->state = PLS_BLOCKED;
1188
      if (p->proto_state == PS_UP)
1189
        proto_schedule_down(p, l->action == PLA_RESTART, dir_down[dir]);
1190
      break;
1191
    }
1192
}
1193

    
1194
void
1195
proto_verify_limits(struct announce_hook *ah)
1196
{
1197
  struct proto_limit *l;
1198
  struct proto_stats *stats = ah->stats;
1199
  u32 all_routes = stats->imp_routes + stats->filt_routes;
1200

    
1201
  l = ah->rx_limit;
1202
  if (l && (all_routes > l->limit))
1203
    proto_notify_limit(ah, l, PLD_RX, all_routes);
1204

    
1205
  l = ah->in_limit;
1206
  if (l && (stats->imp_routes > l->limit))
1207
    proto_notify_limit(ah, l, PLD_IN, stats->imp_routes);
1208

    
1209
  l = ah->out_limit;
1210
  if (l && (stats->exp_routes > l->limit))
1211
    proto_notify_limit(ah, l, PLD_OUT, stats->exp_routes);
1212
}
1213

    
1214

    
1215
static void
1216
proto_want_core_up(struct proto *p)
1217
{
1218
  ASSERT(p->core_state == FS_HUNGRY);
1219

    
1220
  if (!p->proto->multitable)
1221
    {
1222
      p->main_source = rt_get_source(p, 0);
1223
      rt_lock_source(p->main_source);
1224

    
1225
      /* Connect protocol to routing table */
1226
      p->main_ahook = proto_add_announce_hook(p, p->table, &p->stats);
1227
      p->main_ahook->in_filter = p->cf->in_filter;
1228
      p->main_ahook->out_filter = p->cf->out_filter;
1229
      p->main_ahook->rx_limit = p->cf->rx_limit;
1230
      p->main_ahook->in_limit = p->cf->in_limit;
1231
      p->main_ahook->out_limit = p->cf->out_limit;
1232
      p->main_ahook->in_keep_filtered = p->cf->in_keep_filtered;
1233

    
1234
      proto_reset_limit(p->main_ahook->rx_limit);
1235
      proto_reset_limit(p->main_ahook->in_limit);
1236
      proto_reset_limit(p->main_ahook->out_limit);
1237
    }
1238

    
1239
  p->core_state = FS_HAPPY;
1240
  proto_relink(p);
1241
}
1242

    
1243
static void
1244
proto_want_export_up(struct proto *p)
1245
{
1246
  ASSERT(p->core_state == FS_HAPPY);
1247
  ASSERT(p->export_state == ES_DOWN);
1248

    
1249
  proto_link_ahooks(p);
1250
  proto_schedule_feed(p, 1); /* Sets ES_FEEDING */
1251
}
1252

    
1253
static void
1254
proto_want_export_down(struct proto *p)
1255
{
1256
  ASSERT(p->export_state != ES_DOWN);
1257

    
1258
  /* Need to abort feeding */
1259
  if (p->export_state == ES_FEEDING)
1260
    rt_feed_baby_abort(p);
1261

    
1262
  p->export_state = ES_DOWN;
1263
  p->stats.exp_routes = 0;
1264
  proto_unlink_ahooks(p);
1265
}
1266

    
1267
static void
1268
proto_want_core_down(struct proto *p)
1269
{
1270
  ASSERT(p->core_state == FS_HAPPY);
1271
  ASSERT(p->export_state == ES_DOWN);
1272

    
1273
  p->core_state = FS_FLUSHING;
1274
  proto_relink(p);
1275
  proto_schedule_flush_loop();
1276

    
1277
  if (!p->proto->multitable)
1278
    {
1279
      rt_unlock_source(p->main_source);
1280
      p->main_source = NULL;
1281
    }
1282
}
1283

    
1284
static void
1285
proto_falling_down(struct proto *p)
1286
{
1287
  p->gr_recovery = 0;
1288
  p->gr_wait = 0;
1289
  if (p->gr_lock)
1290
    proto_graceful_restart_unlock(p);
1291
}
1292

    
1293
static void
1294
proto_fell_down(struct proto *p)
1295
{
1296
  DBG("Protocol %s down\n", p->name);
1297

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

    
1302
  bzero(&p->stats, sizeof(struct proto_stats));
1303
  proto_free_ahooks(p);
1304

    
1305
  if (! p->proto->multitable)
1306
    rt_unlock_table(p->table);
1307

    
1308
  if (p->proto->cleanup)
1309
    p->proto->cleanup(p);
1310

    
1311
  proto_rethink_goal(p);
1312
}
1313

    
1314

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

    
1336
  DBG("%s reporting state transition %s/%s -> */%s\n", p->name, c_states[cs], p_states[ops], p_states[ps]);
1337
  if (ops == ps)
1338
    return;
1339

    
1340
  p->proto_state = ps;
1341
  p->last_state_change = now;
1342

    
1343
  switch (ps)
1344
    {
1345
    case PS_START:
1346
      ASSERT(ops == PS_DOWN || ops == PS_UP);
1347
      ASSERT(cs == FS_HUNGRY || cs == FS_HAPPY);
1348

    
1349
      if (es != ES_DOWN)
1350
        proto_want_export_down(p);
1351
      break;
1352

    
1353
    case PS_UP:
1354
      ASSERT(ops == PS_DOWN || ops == PS_START);
1355
      ASSERT(cs == FS_HUNGRY || cs == FS_HAPPY);
1356
      ASSERT(es == ES_DOWN);
1357

    
1358
      if (cs == FS_HUNGRY)
1359
        proto_want_core_up(p);
1360
      if (!p->gr_wait)
1361
        proto_want_export_up(p);
1362
      break;
1363

    
1364
    case PS_STOP:
1365
      ASSERT(ops == PS_START || ops == PS_UP);
1366

    
1367
      p->down_sched = 0;
1368

    
1369
      if (es != ES_DOWN)
1370
        proto_want_export_down(p);
1371
      if (cs == FS_HAPPY)
1372
        proto_want_core_down(p);
1373
      proto_falling_down(p);
1374
      break;
1375

    
1376
    case PS_DOWN:
1377
      p->down_code = 0;
1378
      p->down_sched = 0;
1379

    
1380
      if (es != ES_DOWN)
1381
        proto_want_export_down(p);
1382
      if (cs == FS_HAPPY)
1383
        proto_want_core_down(p);
1384
      if (ops != PS_STOP)
1385
        proto_falling_down(p);
1386

    
1387
      neigh_prune(); // FIXME convert neighbors to resource?
1388
      rfree(p->pool);
1389
      p->pool = NULL;
1390

    
1391
      if (cs == FS_HUNGRY)                /* Shutdown finished */
1392
        {
1393
          proto_log_state_change(p);
1394
          proto_fell_down(p);
1395
          return;                        /* The protocol might have ceased to exist */
1396
        }
1397
      break;
1398

    
1399
    default:
1400
      bug("%s: Invalid state %d", p->name, ps);
1401
    }
1402

    
1403
  proto_log_state_change(p);
1404
}
1405

    
1406
/*
1407
 *  CLI Commands
1408
 */
1409

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

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

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

    
1460
void
1461
proto_show_limit(struct proto_limit *l, const char *dsc)
1462
{
1463
  if (!l)
1464
    return;
1465

    
1466
  cli_msg(-1006, "  %-16s%d%s", dsc, l->limit, l->state ? " [HIT]" : "");
1467
  cli_msg(-1006, "    Action:       %s", proto_limit_name(l));
1468
}
1469

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

    
1478
  if (graceful_restart_state == GRS_ACTIVE)
1479
    cli_msg(-1006, "  GR recovery:   %s%s",
1480
            p->gr_lock ? " pending" : "",
1481
            p->gr_wait ? " waiting" : "");
1482

    
1483
  proto_show_limit(p->cf->rx_limit, "Receive limit:");
1484
  proto_show_limit(p->cf->in_limit, "Import limit:");
1485
  proto_show_limit(p->cf->out_limit, "Export limit:");
1486

    
1487
  if (p->proto_state != PS_DOWN)
1488
    proto_show_stats(&p->stats, p->cf->in_keep_filtered);
1489
}
1490

    
1491
void
1492
proto_cmd_show(struct proto *p, uint verbose, int cnt)
1493
{
1494
  byte buf[256], tbuf[TM_DATETIME_BUFFER_SIZE];
1495

    
1496
  /* First protocol - show header */
1497
  if (!cnt)
1498
    cli_msg(-2002, "name     proto    table    state  since       info");
1499

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

    
1518
      if (p->proto->show_proto_info)
1519
        p->proto->show_proto_info(p);
1520
      else
1521
        proto_show_basic_info(p);
1522

    
1523
      cli_msg(-1006, "");
1524
    }
1525
}
1526

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

    
1536
  log(L_INFO "Disabling protocol %s", p->name);
1537
  p->disabled = 1;
1538
  p->down_code = PDC_CMD_DISABLE;
1539
  proto_rethink_goal(p);
1540
  cli_msg(-9, "%s: disabled", p->name);
1541
}
1542

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

    
1552
  log(L_INFO "Enabling protocol %s", p->name);
1553
  p->disabled = 0;
1554
  proto_rethink_goal(p);
1555
  cli_msg(-11, "%s: enabled", p->name);
1556
}
1557

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

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

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

    
1585
  /* If the protocol in not UP, it has no routes */
1586
  if (p->proto_state != PS_UP)
1587
    return;
1588

    
1589
  log(L_INFO "Reloading protocol %s", p->name);
1590

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

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

    
1611
  /* re-exporting routes */
1612
  if (dir != CMD_RELOAD_IN)
1613
    proto_request_feeding(p);
1614

    
1615
  cli_msg(-15, "%s: reloading", p->name);
1616
}
1617

    
1618
void
1619
proto_cmd_debug(struct proto *p, uint mask, int cnt UNUSED)
1620
{
1621
  p->debug = mask;
1622
}
1623

    
1624
void
1625
proto_cmd_mrtdump(struct proto *p, uint mask, int cnt UNUSED)
1626
{
1627
  p->mrtdump = mask;
1628
}
1629

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

    
1639
  cmd(((struct proto_config *)s->def)->proto, arg, 0);
1640
  cli_msg(0, "");
1641
}
1642

    
1643
static void
1644
proto_apply_cmd_patt(char *patt, void (* cmd)(struct proto *, uint, int), uint arg)
1645
{
1646
  int cnt = 0;
1647

    
1648
  node *nn;
1649
  WALK_LIST(nn, proto_list)
1650
    {
1651
      struct proto *p = SKIP_BACK(struct proto, glob_node, nn);
1652

    
1653
      if (!patt || patmatch(patt, p->name))
1654
        cmd(p, arg, cnt++);
1655
    }
1656

    
1657
  if (!cnt)
1658
    cli_msg(8003, "No protocols match");
1659
  else
1660
    cli_msg(0, "");
1661
}
1662

    
1663
void
1664
proto_apply_cmd(struct proto_spec ps, void (* cmd)(struct proto *, uint, int),
1665
                int restricted, uint arg)
1666
{
1667
  if (restricted && cli_access_restricted())
1668
    return;
1669

    
1670
  if (ps.patt)
1671
    proto_apply_cmd_patt(ps.ptr, cmd, arg);
1672
  else
1673
    proto_apply_cmd_symbol(ps.ptr, cmd, arg);
1674
}
1675

    
1676
struct proto *
1677
proto_get_named(struct symbol *sym, struct protocol *pr)
1678
{
1679
  struct proto *p, *q;
1680

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