Statistics
| Branch: | Revision:

iof-bird-daemon / nest / proto.c @ 5400c0e7

History | View | Annotate | Download (34.5 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

    
39
static char *p_states[] = { "DOWN", "START", "UP", "STOP" };
40
static char *c_states[] = { "HUNGRY", "FEEDING", "HAPPY", "FLUSHING" };
41

    
42
static void proto_flush_loop(void *);
43
static void proto_shutdown_loop(struct timer *);
44
static void proto_rethink_goal(struct proto *p);
45
static char *proto_state_name(struct proto *p);
46

    
47
static void
48
proto_enqueue(list *l, struct proto *p)
49
{
50
  add_tail(l, &p->n);
51
  p->last_state_change = now;
52
}
53

    
54
static void
55
proto_relink(struct proto *p)
56
{
57
  list *l = NULL;
58

    
59
  if (p->debug & D_STATES)
60
    {
61
      char *name = proto_state_name(p);
62
      if (name != p->last_state_name_announced)
63
        {
64
          p->last_state_name_announced = name;
65
          PD(p, "State changed to %s", proto_state_name(p));
66
        }
67
    }
68
  else
69
    p->last_state_name_announced = NULL;
70
  rem_node(&p->n);
71
  switch (p->core_state)
72
    {
73
    case FS_HUNGRY:
74
      l = &inactive_proto_list;
75
      break;
76
    case FS_FEEDING:
77
    case FS_HAPPY:
78
      l = &active_proto_list;
79
      break;
80
    case FS_FLUSHING:
81
      l = &flush_proto_list;
82
      break;
83
    default:
84
      ASSERT(0);
85
    }
86
  proto_enqueue(l, p);
87
}
88

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

    
109
  p->cf = c;
110
  p->debug = c->debug;
111
  p->mrtdump = c->mrtdump;
112
  p->name = c->name;
113
  p->preference = c->preference;
114
  p->disabled = c->disabled;
115
  p->proto = pr;
116
  p->table = c->table->table;
117
  p->hash_key = random_u32();
118
  c->proto = p;
119
  return p;
120
}
121

    
122
static void
123
proto_init_instance(struct proto *p)
124
{
125
  /* Here we cannot use p->cf->name since it won't survive reconfiguration */
126
  p->pool = rp_new(proto_pool, p->proto->name);
127
  p->attn = ev_new(p->pool);
128
  p->attn->data = p;
129

    
130
  if (! p->proto->multitable)
131
    rt_lock_table(p->table);
132
}
133

    
134
extern pool *rt_table_pool;
135
/**
136
 * proto_add_announce_hook - connect protocol to a routing table
137
 * @p: protocol instance
138
 * @t: routing table to connect to
139
 * @stats: per-table protocol statistics
140
 *
141
 * This function creates a connection between the protocol instance @p
142
 * and the routing table @t, making the protocol hear all changes in
143
 * the table.
144
 *
145
 * The announce hook is linked in the protocol ahook list and, if the
146
 * protocol accepts routes, also in the table ahook list. Announce
147
 * hooks are allocated from the routing table resource pool, they are
148
 * unlinked from the table ahook list after the protocol went down,
149
 * (in proto_schedule_flush()) and they are automatically freed after the
150
 * protocol is flushed (in proto_fell_down()).
151
 *
152
 * Unless you want to listen to multiple routing tables (as the Pipe
153
 * protocol does), you needn't to worry about this function since the
154
 * connection to the protocol's primary routing table is initialized
155
 * automatically by the core code.
156
 */
157
struct announce_hook *
158
proto_add_announce_hook(struct proto *p, struct rtable *t, struct proto_stats *stats)
159
{
160
  struct announce_hook *h;
161

    
162
  DBG("Connecting protocol %s to table %s\n", p->name, t->name);
163
  PD(p, "Connected to table %s", t->name);
164

    
165
  h = mb_allocz(rt_table_pool, sizeof(struct announce_hook));
166
  h->table = t;
167
  h->proto = p;
168
  h->stats = stats;
169

    
170
  h->next = p->ahooks;
171
  p->ahooks = h;
172

    
173
  if (p->rt_notify)
174
    add_tail(&t->hooks, &h->n);
175
  return h;
176
}
177

    
178
/**
179
 * proto_find_announce_hook - find announce hooks
180
 * @p: protocol instance
181
 * @t: routing table
182
 *
183
 * Returns pointer to announce hook or NULL
184
 */
185
struct announce_hook *
186
proto_find_announce_hook(struct proto *p, struct rtable *t)
187
{
188
  struct announce_hook *a;
189

    
190
  for (a = p->ahooks; a; a = a->next)
191
    if (a->table == t)
192
      return a;
193

    
194
  return NULL;
195
}
196

    
197
static void
198
proto_unlink_ahooks(struct proto *p)
199
{
200
  struct announce_hook *h;
201

    
202
  if (p->rt_notify)
203
    for(h=p->ahooks; h; h=h->next)
204
      rem_node(&h->n);
205
}
206

    
207
static void
208
proto_free_ahooks(struct proto *p)
209
{
210
  struct announce_hook *h, *hn;
211

    
212
  for(h = p->ahooks; h; h = hn)
213
  {
214
    hn = h->next;
215
    mb_free(h);
216
  }
217

    
218
  p->ahooks = NULL;
219
  p->main_ahook = NULL;
220
}
221

    
222
/**
223
 * proto_config_new - create a new protocol configuration
224
 * @pr: protocol the configuration will belong to
225
 * @size: size of the structure including generic data
226
 * @class: SYM_PROTO or SYM_TEMPLATE
227
 *
228
 * Whenever the configuration file says that a new instance
229
 * of a routing protocol should be created, the parser calls
230
 * proto_config_new() to create a configuration entry for this
231
 * instance (a structure staring with the &proto_config header
232
 * containing all the generic items followed by protocol-specific
233
 * ones). Also, the configuration entry gets added to the list
234
 * of protocol instances kept in the configuration.
235
 *
236
 * The function is also used to create protocol templates (when class
237
 * SYM_TEMPLATE is specified), the only difference is that templates
238
 * are not added to the list of protocol instances and therefore not
239
 * initialized during protos_commit()).
240
 */
241
void *
242
proto_config_new(struct protocol *pr, unsigned size, int class)
243
{
244
  struct proto_config *c = cfg_allocz(size);
245

    
246
  if (class == SYM_PROTO)
247
    add_tail(&new_config->protos, &c->n);
248
  c->global = new_config;
249
  c->protocol = pr;
250
  c->name = pr->name;
251
  c->preference = pr->preference;
252
  c->class = class;
253
  c->out_filter = FILTER_REJECT;
254
  c->table = c->global->master_rtc;
255
  c->debug = new_config->proto_default_debug;
256
  c->mrtdump = new_config->proto_default_mrtdump;
257
  return c;
258
}
259

    
260
/**
261
 * proto_copy_config - copy a protocol configuration
262
 * @dest: destination protocol configuration
263
 * @src: source protocol configuration
264
 *
265
 * Whenever a new instance of a routing protocol is created from the
266
 * template, proto_copy_config() is called to copy a content of
267
 * the source protocol configuration to the new protocol configuration.
268
 * Name, class and a node in protos list of @dest are kept intact.
269
 * copy_config() protocol hook is used to copy protocol-specific data.
270
 */
271
void
272
proto_copy_config(struct proto_config *dest, struct proto_config *src)
273
{
274
  node old_node;
275
  int old_class;
276
  char *old_name;
277

    
278
  if (dest->protocol != src->protocol)
279
    cf_error("Can't copy configuration from a different protocol type");
280

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

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

    
286
  /* 
287
   * Copy struct proto_config here. Keep original node, class and name.
288
   * protocol-specific config copy is handled by protocol copy_config() hook
289
   */
290

    
291
  old_node = dest->n;
292
  old_class = dest->class;
293
  old_name = dest->name;
294

    
295
  memcpy(dest, src, sizeof(struct proto_config));
296

    
297
  dest->n = old_node;
298
  dest->class = old_class;
299
  dest->name = old_name;
300

    
301
  dest->protocol->copy_config(dest, src);
302
}
303

    
304
/**
305
 * protos_preconfig - pre-configuration processing
306
 * @c: new configuration
307
 *
308
 * This function calls the preconfig() hooks of all routing
309
 * protocols available to prepare them for reading of the new
310
 * configuration.
311
 */
312
void
313
protos_preconfig(struct config *c)
314
{
315
  struct protocol *p;
316

    
317
  init_list(&c->protos);
318
  DBG("Protocol preconfig:");
319
  WALK_LIST(p, protocol_list)
320
    {
321
      DBG(" %s", p->name);
322
      p->name_counter = 0;
323
      if (p->preconfig)
324
        p->preconfig(p, c);
325
    }
326
  DBG("\n");
327
}
328

    
329
/**
330
 * protos_postconfig - post-configuration processing
331
 * @c: new configuration
332
 *
333
 * This function calls the postconfig() hooks of all protocol
334
 * instances specified in configuration @c. The hooks are not
335
 * called for protocol templates.
336
 */
337
void
338
protos_postconfig(struct config *c)
339
{
340
  struct proto_config *x;
341
  struct protocol *p;
342

    
343
  DBG("Protocol postconfig:");
344
  WALK_LIST(x, c->protos)
345
    {
346
      DBG(" %s", x->name);
347
      p = x->protocol;
348
      if (p->postconfig)
349
        p->postconfig(x);
350
    }
351
  DBG("\n");
352
}
353

    
354
extern struct protocol proto_unix_iface;
355

    
356
static struct proto *
357
proto_init(struct proto_config *c)
358
{
359
  struct protocol *p = c->protocol;
360
  struct proto *q = p->init(c);
361

    
362
  q->proto_state = PS_DOWN;
363
  q->core_state = FS_HUNGRY;
364
  proto_enqueue(&initial_proto_list, q);
365
  if (p == &proto_unix_iface)
366
    initial_device_proto = q;
367

    
368
  add_tail(&proto_list, &q->glob_node);
369
  PD(q, "Initializing%s", q->disabled ? " [disabled]" : "");
370
  return q;
371
}
372

    
373
int proto_reconfig_type;  /* Hack to propagate type info to pipe reconfigure hook */
374

    
375
static int
376
proto_reconfigure(struct proto *p, struct proto_config *oc, struct proto_config *nc, int type)
377
{
378
  /* If the protocol is DOWN, we just restart it */
379
  if (p->proto_state == PS_DOWN)
380
    return 0;
381

    
382
  /* If there is a too big change in core attributes, ... */
383
  if ((nc->protocol != oc->protocol) ||
384
      (nc->disabled != p->disabled) ||
385
      (nc->table->table != oc->table->table) ||
386
      (proto_get_router_id(nc) != proto_get_router_id(oc)))
387
    return 0;
388

    
389

    
390
  p->debug = nc->debug;
391
  p->mrtdump = nc->mrtdump;
392
  proto_reconfig_type = type;
393

    
394
  /* Execute protocol specific reconfigure hook */
395
  if (! (p->proto->reconfigure && p->proto->reconfigure(p, nc)))
396
    return 0;
397

    
398
  DBG("\t%s: same\n", oc->name);
399
  PD(p, "Reconfigured");
400
  p->cf = nc;
401
  p->name = nc->name;
402
  p->preference = nc->preference;
403

    
404

    
405
  /* Multitable protocols handle rest in their reconfigure hooks */
406
  if (p->proto->multitable)
407
    return 1;
408

    
409
  /* Update filters and limits in the main announce hook
410
     Note that this also resets limit state */
411
  if (p->main_ahook)
412
    {
413
      p->main_ahook->in_filter = nc->in_filter;
414
      p->main_ahook->out_filter = nc->out_filter;
415
      p->main_ahook->in_limit = nc->in_limit;
416
      p->main_ahook->out_limit = nc->out_limit;
417
    }
418

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

    
424
  int import_changed = ! filter_same(nc->in_filter, oc->in_filter);
425
  int export_changed = ! filter_same(nc->out_filter, oc->out_filter);
426

    
427
  /* We treat a change in preferences by reimporting routes */
428
  if (nc->preference != oc->preference)
429
    import_changed = 1;
430

    
431
  if (import_changed || export_changed)
432
    log(L_INFO "Reloading protocol %s", p->name);
433

    
434
  /* If import filter changed, call reload hook */
435
  if (import_changed && ! (p->reload_routes && p->reload_routes(p)))
436
    {
437
      /* Now, the protocol is reconfigured. But route reload failed
438
         and we have to do regular protocol restart. */
439
      log(L_INFO "Restarting protocol %s", p->name);
440
      p->disabled = 1;
441
      p->down_code = PDC_CF_RESTART;
442
      proto_rethink_goal(p);
443
      p->disabled = 0;
444
      proto_rethink_goal(p);
445
      return 1;
446
    }
447

    
448
  if (export_changed)
449
    proto_request_feeding(p);
450

    
451
  return 1;
452
}
453

    
454
/**
455
 * protos_commit - commit new protocol configuration
456
 * @new: new configuration
457
 * @old: old configuration or %NULL if it's boot time config
458
 * @force_reconfig: force restart of all protocols (used for example
459
 * when the router ID changes)
460
 * @type: type of reconfiguration (RECONFIG_SOFT or RECONFIG_HARD)
461
 *
462
 * Scan differences between @old and @new configuration and adjust all
463
 * protocol instances to conform to the new configuration.
464
 *
465
 * When a protocol exists in the new configuration, but it doesn't in the
466
 * original one, it's immediately started. When a collision with the other
467
 * running protocol would arise, the new protocol will be temporarily stopped
468
 * by the locking mechanism.
469
 *
470
 * When a protocol exists in the old configuration, but it doesn't in the
471
 * new one, it's shut down and deleted after the shutdown completes.
472
 *
473
 * When a protocol exists in both configurations, the core decides
474
 * whether it's possible to reconfigure it dynamically - it checks all
475
 * the core properties of the protocol (changes in filters are ignored
476
 * if type is RECONFIG_SOFT) and if they match, it asks the
477
 * reconfigure() hook of the protocol to see if the protocol is able
478
 * to switch to the new configuration.  If it isn't possible, the
479
 * protocol is shut down and a new instance is started with the new
480
 * configuration after the shutdown is completed.
481
 */
482
void
483
protos_commit(struct config *new, struct config *old, int force_reconfig, int type)
484
{
485
  struct proto_config *oc, *nc;
486
  struct proto *p, *n;
487
  struct symbol *sym;
488

    
489
  DBG("protos_commit:\n");
490
  if (old)
491
    {
492
      WALK_LIST(oc, old->protos)
493
        {
494
          p = oc->proto;
495
          sym = cf_find_symbol(oc->name);
496
          if (sym && sym->class == SYM_PROTO && !new->shutdown)
497
            {
498
              /* Found match, let's check if we can smoothly switch to new configuration */
499
              /* No need to check description */
500
              nc = sym->def;
501
              nc->proto = p;
502

    
503
              /* We will try to reconfigure protocol p */
504
              if (! force_reconfig && proto_reconfigure(p, oc, nc, type))
505
                continue;
506

    
507
              /* Unsuccessful, we will restart it */
508
              if (!p->disabled && !nc->disabled)
509
                log(L_INFO "Restarting protocol %s", p->name);
510
              else if (p->disabled && !nc->disabled)
511
                log(L_INFO "Enabling protocol %s", p->name);
512
              else if (!p->disabled && nc->disabled)
513
                log(L_INFO "Disabling protocol %s", p->name);
514

    
515
              p->down_code = nc->disabled ? PDC_CF_DISABLE : PDC_CF_RESTART;
516
              p->cf_new = nc;
517
            }
518
          else if (!shutting_down)
519
            {
520
              log(L_INFO "Removing protocol %s", p->name);
521
              p->down_code = PDC_CF_REMOVE;
522
              p->cf_new = NULL;
523
            }
524
          else /* global shutdown */
525
            {
526
              p->down_code = PDC_CMD_SHUTDOWN;
527
              p->cf_new = NULL;
528
            }
529

    
530
          p->reconfiguring = 1;
531
          config_add_obstacle(old);
532
          proto_rethink_goal(p);
533
        }
534
    }
535

    
536
  WALK_LIST(nc, new->protos)
537
    if (!nc->proto)
538
      {
539
        if (old_config)                /* Not a first-time configuration */
540
          log(L_INFO "Adding protocol %s", nc->name);
541
        proto_init(nc);
542
      }
543
  DBG("\tdone\n");
544

    
545
  DBG("Protocol start\n");
546

    
547
  /* Start device protocol first */
548
  if (initial_device_proto)
549
  {
550
    proto_rethink_goal(initial_device_proto);
551
    initial_device_proto = NULL;
552
  }
553

    
554
  WALK_LIST_DELSAFE(p, n, initial_proto_list)
555
    proto_rethink_goal(p);
556
}
557

    
558
static void
559
proto_rethink_goal(struct proto *p)
560
{
561
  struct protocol *q;
562

    
563
  if (p->reconfiguring && p->core_state == FS_HUNGRY && p->proto_state == PS_DOWN)
564
    {
565
      struct proto_config *nc = p->cf_new;
566
      DBG("%s has shut down for reconfiguration\n", p->name);
567
      config_del_obstacle(p->cf->global);
568
      rem_node(&p->n);
569
      rem_node(&p->glob_node);
570
      mb_free(p);
571
      if (!nc)
572
        return;
573
      p = proto_init(nc);
574
    }
575

    
576
  /* Determine what state we want to reach */
577
  if (p->disabled || p->reconfiguring)
578
    {
579
      p->core_goal = FS_HUNGRY;
580
      if (p->core_state == FS_HUNGRY && p->proto_state == PS_DOWN)
581
        return;
582
    }
583
  else
584
    {
585
      p->core_goal = FS_HAPPY;
586
      if (p->core_state == FS_HAPPY && p->proto_state == PS_UP)
587
        return;
588
    }
589

    
590
  q = p->proto;
591
  if (p->core_goal == FS_HAPPY)                /* Going up */
592
    {
593
      if (p->core_state == FS_HUNGRY && p->proto_state == PS_DOWN)
594
        {
595
          DBG("Kicking %s up\n", p->name);
596
          PD(p, "Starting");
597
          proto_init_instance(p);
598
          proto_notify_state(p, (q->start ? q->start(p) : PS_UP));
599
        }
600
    }
601
  else                                         /* Going down */
602
    {
603
      if (p->proto_state == PS_START || p->proto_state == PS_UP)
604
        {
605
          DBG("Kicking %s down\n", p->name);
606
          PD(p, "Shutting down");
607
          proto_notify_state(p, (q->shutdown ? q->shutdown(p) : PS_DOWN));
608
        }
609
    }
610
}
611

    
612
/**
613
 * protos_dump_all - dump status of all protocols
614
 *
615
 * This function dumps status of all existing protocol instances to the
616
 * debug output. It involves printing of general status information
617
 * such as protocol states, its position on the protocol lists
618
 * and also calling of a dump() hook of the protocol to print
619
 * the internals.
620
 */
621
void
622
protos_dump_all(void)
623
{
624
  struct proto *p;
625
  struct announce_hook *a;
626

    
627
  debug("Protocols:\n");
628

    
629
  WALK_LIST(p, active_proto_list)
630
    {
631
      debug("  protocol %s state %s/%s\n", p->name,
632
            p_states[p->proto_state], c_states[p->core_state]);
633
      for (a = p->ahooks; a; a = a->next)
634
        {
635
          debug("\tTABLE %s\n", a->table->name);
636
          if (a->in_filter)
637
            debug("\tInput filter: %s\n", filter_name(a->in_filter));
638
          if (a->out_filter != FILTER_REJECT)
639
            debug("\tOutput filter: %s\n", filter_name(a->out_filter));
640
        }
641
      if (p->disabled)
642
        debug("\tDISABLED\n");
643
      else if (p->proto->dump)
644
        p->proto->dump(p);
645
    }
646
  WALK_LIST(p, inactive_proto_list)
647
    debug("  inactive %s: state %s/%s\n", p->name, p_states[p->proto_state], c_states[p->core_state]);
648
  WALK_LIST(p, initial_proto_list)
649
    debug("  initial %s\n", p->name);
650
  WALK_LIST(p, flush_proto_list)
651
    debug("  flushing %s\n", p->name);
652
}
653

    
654
/**
655
 * proto_build - make a single protocol available
656
 * @p: the protocol
657
 *
658
 * After the platform specific initialization code uses protos_build()
659
 * to add all the standard protocols, it should call proto_build() for
660
 * all platform specific protocols to inform the core that they exist.
661
 */
662
void
663
proto_build(struct protocol *p)
664
{
665
  add_tail(&protocol_list, &p->n);
666
  if (p->attr_class)
667
    {
668
      ASSERT(!attr_class_to_protocol[p->attr_class]);
669
      attr_class_to_protocol[p->attr_class] = p;
670
    }
671
}
672

    
673
/**
674
 * protos_build - build a protocol list
675
 *
676
 * This function is called during BIRD startup to insert
677
 * all standard protocols to the global protocol list. Insertion
678
 * of platform specific protocols (such as the kernel syncer)
679
 * is in the domain of competence of the platform dependent
680
 * startup code.
681
 */
682
void
683
protos_build(void)
684
{
685
  init_list(&protocol_list);
686
  init_list(&proto_list);
687
  init_list(&active_proto_list);
688
  init_list(&inactive_proto_list);
689
  init_list(&initial_proto_list);
690
  init_list(&flush_proto_list);
691
  proto_build(&proto_device);
692
#ifdef CONFIG_RADV
693
  proto_build(&proto_radv);
694
#endif
695
#ifdef CONFIG_RIP
696
  proto_build(&proto_rip);
697
#endif
698
#ifdef CONFIG_STATIC
699
  proto_build(&proto_static);
700
#endif
701
#ifdef CONFIG_OSPF
702
  proto_build(&proto_ospf);
703
#endif
704
#ifdef CONFIG_PIPE
705
  proto_build(&proto_pipe);
706
#endif
707
#ifdef CONFIG_BGP
708
  proto_build(&proto_bgp);
709
#endif
710
  proto_pool = rp_new(&root_pool, "Protocols");
711
  proto_flush_event = ev_new(proto_pool);
712
  proto_flush_event->hook = proto_flush_loop;
713
  proto_shutdown_timer = tm_new(proto_pool);
714
  proto_shutdown_timer->hook = proto_shutdown_loop;
715
}
716

    
717
static void
718
proto_fell_down(struct proto *p)
719
{
720
  DBG("Protocol %s down\n", p->name);
721

    
722
  if (p->stats.imp_routes != 0)
723
    log(L_ERR "Protocol %s is down but still has %d routes", p->name, p->stats.imp_routes);
724

    
725
  bzero(&p->stats, sizeof(struct proto_stats));
726
  proto_free_ahooks(p);
727

    
728
  if (! p->proto->multitable)
729
    rt_unlock_table(p->table);
730

    
731
  if (p->proto->cleanup)
732
    p->proto->cleanup(p);
733

    
734
  proto_rethink_goal(p);
735
}
736

    
737
static void
738
proto_feed_more(void *P)
739
{
740
  struct proto *p = P;
741

    
742
  if (p->core_state != FS_FEEDING)
743
    return;
744

    
745
  DBG("Feeding protocol %s continued\n", p->name);
746
  if (rt_feed_baby(p))
747
    {
748
      p->core_state = FS_HAPPY;
749
      proto_relink(p);
750
      DBG("Protocol %s up and running\n", p->name);
751
    }
752
  else
753
    {
754
      p->attn->hook = proto_feed_more;
755
      ev_schedule(p->attn);                /* Will continue later... */
756
    }
757
}
758

    
759
static void
760
proto_feed_initial(void *P)
761
{
762
  struct proto *p = P;
763

    
764
  if (p->core_state != FS_FEEDING)
765
    return;
766

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

    
769
  if_feed_baby(p);
770
  proto_feed_more(P);
771
}
772

    
773
static void
774
proto_schedule_feed(struct proto *p, int initial)
775
{
776
  DBG("%s: Scheduling meal\n", p->name);
777
  p->core_state = FS_FEEDING;
778
  p->refeeding = !initial;
779

    
780
  /* FIXME: This should be changed for better support of multitable protos */
781
  if (!initial)
782
    {
783
      struct announce_hook *ah;
784
      for (ah = p->ahooks; ah; ah = ah->next)
785
        proto_reset_limit(ah->out_limit);
786

    
787
      /* Hack: reset exp_routes during refeed, and do not decrease it later */
788
      p->stats.exp_routes = 0;
789
    }
790

    
791
  /* Connect protocol to routing table */
792
  if (initial && !p->proto->multitable)
793
    {
794
      p->main_ahook = proto_add_announce_hook(p, p->table, &p->stats);
795
      p->main_ahook->in_filter = p->cf->in_filter;
796
      p->main_ahook->out_filter = p->cf->out_filter;
797
      p->main_ahook->in_limit = p->cf->in_limit;
798
      p->main_ahook->out_limit = p->cf->out_limit;
799
      proto_reset_limit(p->main_ahook->in_limit);
800
      proto_reset_limit(p->main_ahook->out_limit);
801
    }
802

    
803
  proto_relink(p);
804
  p->attn->hook = initial ? proto_feed_initial : proto_feed_more;
805
  ev_schedule(p->attn);
806
}
807

    
808
/*
809
 * Flushing loop is responsible for flushing routes and protocols
810
 * after they went down. It runs in proto_flush_event. At the start of
811
 * one round, protocols waiting to flush are marked in
812
 * proto_schedule_flush_loop(). At the end of the round (when routing
813
 * table flush is complete), marked protocols are flushed and a next
814
 * round may start.
815
 */
816

    
817
static int flush_loop_state;        /* 1 -> running */
818

    
819
static void
820
proto_schedule_flush_loop(void)
821
{
822
  struct proto *p;
823

    
824
  if (flush_loop_state)
825
    return;
826
  flush_loop_state = 1;
827

    
828
  rt_schedule_prune_all();
829
  WALK_LIST(p, flush_proto_list)
830
    p->flushing = 1;
831

    
832
  ev_schedule(proto_flush_event);
833
}
834

    
835
static void
836
proto_flush_loop(void *unused UNUSED)
837
{
838
  struct proto *p;
839

    
840
  if (! rt_prune_loop())
841
    {
842
      /* Rtable pruning is not finished */
843
      ev_schedule(proto_flush_event);
844
      return;
845
    }
846

    
847
 again:
848
  WALK_LIST(p, flush_proto_list)
849
    if (p->flushing)
850
      {
851
        /* This will flush interfaces in the same manner
852
           like rt_prune_all() flushes routes */
853
        if (p->proto == &proto_unix_iface)
854
          if_flush_ifaces(p);
855

    
856
        DBG("Flushing protocol %s\n", p->name);
857
        p->flushing = 0;
858
        p->core_state = FS_HUNGRY;
859
        proto_relink(p);
860
        if (p->proto_state == PS_DOWN)
861
          proto_fell_down(p);
862
        goto again;
863
      }
864

    
865
  /* This round finished, perhaps there will be another one */
866
  flush_loop_state = 0;
867
  if (!EMPTY_LIST(flush_proto_list))
868
    proto_schedule_flush_loop();
869
}
870

    
871
static void
872
proto_schedule_flush(struct proto *p)
873
{
874
  /* Need to abort feeding */
875
  if (p->core_state == FS_FEEDING)
876
    rt_feed_baby_abort(p);
877

    
878
  DBG("%s: Scheduling flush\n", p->name);
879
  p->core_state = FS_FLUSHING;
880
  proto_relink(p);
881
  proto_unlink_ahooks(p);
882
  proto_schedule_flush_loop();
883
}
884

    
885
/* Temporary hack to propagate restart to BGP */
886
int proto_restart;
887

    
888
static void
889
proto_shutdown_loop(struct timer *t UNUSED)
890
{
891
  struct proto *p, *p_next;
892

    
893
  WALK_LIST_DELSAFE(p, p_next, active_proto_list)
894
    if (p->down_sched)
895
      {
896
        proto_restart = (p->down_sched == PDS_RESTART);
897

    
898
        p->disabled = 1;
899
        proto_rethink_goal(p);
900
        if (proto_restart)
901
          {
902
            p->disabled = 0;
903
            proto_rethink_goal(p);
904
          }
905
      }
906
}
907

    
908
static inline void
909
proto_schedule_down(struct proto *p, byte restart, byte code)
910
{
911
  /* Does not work for other states (even PS_START) */
912
  ASSERT(p->proto_state == PS_UP);
913

    
914
  /* Scheduled restart may change to shutdown, but not otherwise */
915
  if (p->down_sched == PDS_DISABLE)
916
    return;
917

    
918
  p->down_sched = restart ? PDS_RESTART : PDS_DISABLE;
919
  p->down_code = code;
920
  tm_start_max(proto_shutdown_timer, restart ? 2 : 0);
921
}
922

    
923

    
924
/**
925
 * proto_request_feeding - request feeding routes to the protocol
926
 * @p: given protocol 
927
 *
928
 * Sometimes it is needed to send again all routes to the
929
 * protocol. This is called feeding and can be requested by this
930
 * function. This would cause protocol core state transition
931
 * to FS_FEEDING (during feeding) and when completed, it will
932
 * switch back to FS_HAPPY. This function can be called even
933
 * when feeding is already running, in that case it is restarted.
934
 */
935
void
936
proto_request_feeding(struct proto *p)
937
{
938
  ASSERT(p->proto_state == PS_UP);
939

    
940
  /* If we are already feeding, we want to restart it */
941
  if (p->core_state == FS_FEEDING)
942
    {
943
      /* Unless feeding is in initial state */
944
      if (p->attn->hook == proto_feed_initial)
945
        return;
946

    
947
      rt_feed_baby_abort(p);
948
    }
949

    
950
  proto_schedule_feed(p, 0);
951
}
952

    
953
static const char *
954
proto_limit_name(struct proto_limit *l)
955
{
956
  const char *actions[] = {
957
    [PLA_WARN] = "warn",
958
    [PLA_BLOCK] = "block",
959
    [PLA_RESTART] = "restart",
960
    [PLA_DISABLE] = "disable",
961
  };
962

    
963
  return actions[l->action];
964
}
965

    
966
/**
967
 * proto_notify_limit: notify about limit hit and take appropriate action
968
 * @ah: announce hook
969
 * @l: limit being hit
970
 * @rt_count: the number of routes 
971
 *
972
 * The function is called by the route processing core when limit @l
973
 * is breached. It activates the limit and tooks appropriate action
974
 * according to @l->action.
975
 */
976
void
977
proto_notify_limit(struct announce_hook *ah, struct proto_limit *l, u32 rt_count)
978
{
979
  struct proto *p = ah->proto;
980
  int dir = (ah->in_limit == l);
981

    
982
  if (l->state == PLS_BLOCKED)
983
    return;
984

    
985
  /* For warning action, we want the log message every time we hit the limit */
986
  if (!l->state || ((l->action == PLA_WARN) && (rt_count == l->limit)))
987
    log(L_WARN "Protocol %s hits route %s limit (%d), action: %s",
988
        p->name, dir ? "import" : "export", l->limit, proto_limit_name(l));
989

    
990
  switch (l->action)
991
    {
992
    case PLA_WARN:
993
      l->state = PLS_ACTIVE;
994
      break;
995

    
996
    case PLA_BLOCK:
997
      l->state = PLS_BLOCKED;
998
      break;
999

    
1000
    case PLA_RESTART:
1001
    case PLA_DISABLE:
1002
      l->state = PLS_BLOCKED;
1003
      proto_schedule_down(p, l->action == PLA_RESTART,
1004
                          dir ? PDC_IN_LIMIT_HIT : PDC_OUT_LIMIT_HIT);
1005
      break;
1006
    }
1007
}
1008

    
1009
/**
1010
 * proto_notify_state - notify core about protocol state change
1011
 * @p: protocol the state of which has changed
1012
 * @ps: the new status
1013
 *
1014
 * Whenever a state of a protocol changes due to some event internal
1015
 * to the protocol (i.e., not inside a start() or shutdown() hook),
1016
 * it should immediately notify the core about the change by calling
1017
 * proto_notify_state() which will write the new state to the &proto
1018
 * structure and take all the actions necessary to adapt to the new
1019
 * state. State change to PS_DOWN immediately frees resources of protocol
1020
 * and might execute start callback of protocol; therefore,
1021
 * it should be used at tail positions of protocol callbacks.
1022
 */
1023
void
1024
proto_notify_state(struct proto *p, unsigned ps)
1025
{
1026
  unsigned ops = p->proto_state;
1027
  unsigned cs = p->core_state;
1028

    
1029
  DBG("%s reporting state transition %s/%s -> */%s\n", p->name, c_states[cs], p_states[ops], p_states[ps]);
1030
  if (ops == ps)
1031
    return;
1032

    
1033
  p->proto_state = ps;
1034

    
1035
  switch (ps)
1036
    {
1037
    case PS_DOWN:
1038
      p->down_code = 0;
1039
      p->down_sched = 0;
1040
      if ((cs == FS_FEEDING) || (cs == FS_HAPPY))
1041
        proto_schedule_flush(p);
1042

    
1043
      neigh_prune(); // FIXME convert neighbors to resource?
1044
      rfree(p->pool);
1045
      p->pool = NULL;
1046

    
1047
      if (cs == FS_HUNGRY)                /* Shutdown finished */
1048
        {
1049
          proto_fell_down(p);
1050
          return;                        /* The protocol might have ceased to exist */
1051
        }
1052
      break;
1053
    case PS_START:
1054
      ASSERT(ops == PS_DOWN);
1055
      ASSERT(cs == FS_HUNGRY);
1056
      break;
1057
    case PS_UP:
1058
      ASSERT(ops == PS_DOWN || ops == PS_START);
1059
      ASSERT(cs == FS_HUNGRY);
1060
      proto_schedule_feed(p, 1);
1061
      break;
1062
    case PS_STOP:
1063
      p->down_sched = 0;
1064
      if ((cs == FS_FEEDING) || (cs == FS_HAPPY))
1065
        proto_schedule_flush(p);
1066
      break;
1067
    default:
1068
      bug("Invalid state transition for %s from %s/%s to */%s", p->name, c_states[cs], p_states[ops], p_states[ps]);
1069
    }
1070
}
1071

    
1072
/*
1073
 *  CLI Commands
1074
 */
1075

    
1076
static char *
1077
proto_state_name(struct proto *p)
1078
{
1079
#define P(x,y) ((x << 4) | y)
1080
  switch (P(p->proto_state, p->core_state))
1081
    {
1082
    case P(PS_DOWN, FS_HUNGRY):                return "down";
1083
    case P(PS_START, FS_HUNGRY):        return "start";
1084
    case P(PS_UP, FS_HUNGRY):
1085
    case P(PS_UP, FS_FEEDING):                return "feed";
1086
    case P(PS_STOP, FS_HUNGRY):                return "stop";
1087
    case P(PS_UP, FS_HAPPY):                return "up";
1088
    case P(PS_STOP, FS_FLUSHING):
1089
    case P(PS_DOWN, FS_FLUSHING):        return "flush";
1090
    default:                              return "???";
1091
    }
1092
#undef P
1093
}
1094

    
1095
static void
1096
proto_show_stats(struct proto_stats *s)
1097
{
1098
  cli_msg(-1006, "  Routes:         %u imported, %u exported, %u preferred", 
1099
          s->imp_routes, s->exp_routes, s->pref_routes);
1100
  cli_msg(-1006, "  Route change stats:     received   rejected   filtered    ignored   accepted");
1101
  cli_msg(-1006, "    Import updates:     %10u %10u %10u %10u %10u",
1102
          s->imp_updates_received, s->imp_updates_invalid,
1103
          s->imp_updates_filtered, s->imp_updates_ignored,
1104
          s->imp_updates_accepted);
1105
  cli_msg(-1006, "    Import withdraws:   %10u %10u        --- %10u %10u",
1106
          s->imp_withdraws_received, s->imp_withdraws_invalid,
1107
          s->imp_withdraws_ignored, s->imp_withdraws_accepted);
1108
  cli_msg(-1006, "    Export updates:     %10u %10u %10u        --- %10u",
1109
          s->exp_updates_received, s->exp_updates_rejected,
1110
          s->exp_updates_filtered, s->exp_updates_accepted);
1111
  cli_msg(-1006, "    Export withdraws:   %10u        ---        ---        --- %10u",
1112
          s->exp_withdraws_received, s->exp_withdraws_accepted);
1113
}
1114

    
1115
void
1116
proto_show_limit(struct proto_limit *l, const char *dsc)
1117
{
1118
  if (!l)
1119
    return;
1120

    
1121
  cli_msg(-1006, "  %-16s%d%s", dsc, l->limit, l->state ? " [HIT]" : "");
1122
  cli_msg(-1006, "    Action:       %s", proto_limit_name(l));
1123
}
1124

    
1125
void
1126
proto_show_basic_info(struct proto *p)
1127
{
1128
  // cli_msg(-1006, "  Table:          %s", p->table->name);
1129
  cli_msg(-1006, "  Preference:     %d", p->preference);
1130
  cli_msg(-1006, "  Input filter:   %s", filter_name(p->cf->in_filter));
1131
  cli_msg(-1006, "  Output filter:  %s", filter_name(p->cf->out_filter));
1132

    
1133
  proto_show_limit(p->cf->in_limit, "Import limit:");
1134
  proto_show_limit(p->cf->out_limit, "Export limit:");
1135

    
1136
  if (p->proto_state != PS_DOWN)
1137
    proto_show_stats(&p->stats);
1138
}
1139

    
1140
void
1141
proto_cmd_show(struct proto *p, unsigned int verbose, int cnt)
1142
{
1143
  byte buf[256], tbuf[TM_DATETIME_BUFFER_SIZE];
1144

    
1145
  /* First protocol - show header */
1146
  if (!cnt)
1147
    cli_msg(-2002, "name     proto    table    state  since       info");
1148

    
1149
  buf[0] = 0;
1150
  if (p->proto->get_status)
1151
    p->proto->get_status(p, buf);
1152
  tm_format_datetime(tbuf, &config->tf_proto, p->last_state_change);
1153
  cli_msg(-1002, "%-8s %-8s %-8s %-5s  %-10s  %s",
1154
          p->name,
1155
          p->proto->name,
1156
          p->table->name,
1157
          proto_state_name(p),
1158
          tbuf,
1159
          buf);
1160
  if (verbose)
1161
    {
1162
      if (p->cf->dsc)
1163
        cli_msg(-1006, "  Description:    %s", p->cf->dsc);
1164
      if (p->cf->router_id)
1165
        cli_msg(-1006, "  Router ID:      %R", p->cf->router_id);
1166

    
1167
      if (p->proto->show_proto_info)
1168
        p->proto->show_proto_info(p);
1169
      else
1170
        proto_show_basic_info(p);
1171

    
1172
      cli_msg(-1006, "");
1173
    }
1174
}
1175

    
1176
void
1177
proto_cmd_disable(struct proto *p, unsigned int arg UNUSED, int cnt UNUSED)
1178
{
1179
  if (p->disabled)
1180
    {
1181
      cli_msg(-8, "%s: already disabled", p->name);
1182
      return;
1183
    }
1184

    
1185
  log(L_INFO "Disabling protocol %s", p->name);
1186
  p->disabled = 1;
1187
  p->down_code = PDC_CMD_DISABLE;
1188
  proto_rethink_goal(p);
1189
  cli_msg(-9, "%s: disabled", p->name);
1190
}
1191

    
1192
void
1193
proto_cmd_enable(struct proto *p, unsigned int arg UNUSED, int cnt UNUSED)
1194
{
1195
  if (!p->disabled)
1196
    {
1197
      cli_msg(-10, "%s: already enabled", p->name);
1198
      return;
1199
    }
1200

    
1201
  log(L_INFO "Enabling protocol %s", p->name);
1202
  p->disabled = 0;
1203
  proto_rethink_goal(p);
1204
  cli_msg(-11, "%s: enabled", p->name);
1205
}
1206

    
1207
void
1208
proto_cmd_restart(struct proto *p, unsigned int arg UNUSED, int cnt UNUSED)
1209
{
1210
  if (p->disabled)
1211
    {
1212
      cli_msg(-8, "%s: already disabled", p->name);
1213
      return;
1214
    }
1215

    
1216
  log(L_INFO "Restarting protocol %s", p->name);
1217
  p->disabled = 1;
1218
  p->down_code = PDC_CMD_RESTART;
1219
  proto_rethink_goal(p);
1220
  p->disabled = 0;
1221
  proto_rethink_goal(p);
1222
  cli_msg(-12, "%s: restarted", p->name);
1223
}
1224

    
1225
void
1226
proto_cmd_reload(struct proto *p, unsigned int dir, int cnt UNUSED)
1227
{
1228
  if (p->disabled)
1229
    {
1230
      cli_msg(-8, "%s: already disabled", p->name);
1231
      return;
1232
    }
1233

    
1234
  /* If the protocol in not UP, it has no routes */
1235
  if (p->proto_state != PS_UP)
1236
    return;
1237

    
1238
  log(L_INFO "Reloading protocol %s", p->name);
1239

    
1240
  /* re-importing routes */
1241
  if (dir != CMD_RELOAD_OUT)
1242
    {
1243
      if (! (p->reload_routes && p->reload_routes(p)))
1244
        {
1245
          cli_msg(-8006, "%s: reload failed", p->name);
1246
          return;
1247
        }
1248

    
1249
      /*
1250
       * Should be done before reload_routes() hook?
1251
       * Perhaps, but these hooks work asynchronously.
1252
       */
1253
      if (!p->proto->multitable)
1254
        proto_reset_limit(p->main_ahook->in_limit);
1255
    }
1256

    
1257
  /* re-exporting routes */
1258
  if (dir != CMD_RELOAD_IN)
1259
    proto_request_feeding(p);
1260

    
1261
  cli_msg(-15, "%s: reloading", p->name);
1262
}
1263

    
1264
void
1265
proto_cmd_debug(struct proto *p, unsigned int mask, int cnt UNUSED)
1266
{
1267
  p->debug = mask;
1268
}
1269

    
1270
void
1271
proto_cmd_mrtdump(struct proto *p, unsigned int mask, int cnt UNUSED)
1272
{
1273
  p->mrtdump = mask;
1274
}
1275

    
1276
static void
1277
proto_apply_cmd_symbol(struct symbol *s, void (* cmd)(struct proto *, unsigned int, int), unsigned int arg)
1278
{
1279
  if (s->class != SYM_PROTO)
1280
    {
1281
      cli_msg(9002, "%s is not a protocol", s->name);
1282
      return;
1283
    }
1284

    
1285
  cmd(((struct proto_config *)s->def)->proto, arg, 0);
1286
  cli_msg(0, "");
1287
}
1288

    
1289
static void
1290
proto_apply_cmd_patt(char *patt, void (* cmd)(struct proto *, unsigned int, int), unsigned int arg)
1291
{
1292
  int cnt = 0;
1293

    
1294
  node *nn;
1295
  WALK_LIST(nn, proto_list)
1296
    {
1297
      struct proto *p = SKIP_BACK(struct proto, glob_node, nn);
1298

    
1299
      if (!patt || patmatch(patt, p->name))
1300
        cmd(p, arg, cnt++);
1301
    }
1302

    
1303
  if (!cnt)
1304
    cli_msg(8003, "No protocols match");
1305
  else
1306
    cli_msg(0, "");
1307
}
1308

    
1309
void
1310
proto_apply_cmd(struct proto_spec ps, void (* cmd)(struct proto *, unsigned int, int),
1311
                int restricted, unsigned int arg)
1312
{
1313
  if (restricted && cli_access_restricted())
1314
    return;
1315

    
1316
  if (ps.patt)
1317
    proto_apply_cmd_patt(ps.ptr, cmd, arg);
1318
  else
1319
    proto_apply_cmd_symbol(ps.ptr, cmd, arg);
1320
}
1321

    
1322
struct proto *
1323
proto_get_named(struct symbol *sym, struct protocol *pr)
1324
{
1325
  struct proto *p, *q;
1326

    
1327
  if (sym)
1328
    {
1329
      if (sym->class != SYM_PROTO)
1330
        cf_error("%s: Not a protocol", sym->name);
1331
      p = ((struct proto_config *)sym->def)->proto;
1332
      if (!p || p->proto != pr)
1333
        cf_error("%s: Not a %s protocol", sym->name, pr->name);
1334
    }
1335
  else
1336
    {
1337
      p = NULL;
1338
      WALK_LIST(q, active_proto_list)
1339
        if (q->proto == pr)
1340
          {
1341
            if (p)
1342
              cf_error("There are multiple %s protocols running", pr->name);
1343
            p = q;
1344
          }
1345
      if (!p)
1346
        cf_error("There is no %s protocol running", pr->name);
1347
    }
1348
  return p;
1349
}