Statistics
| Branch: | Revision:

iof-bird-daemon / nest / proto.c @ cf98be7b

History | View | Annotate | Download (34.9 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
      p->main_ahook->in_keep_rejected = nc->in_keep_rejected;
418
    }
419

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

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

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

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

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

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

    
452
  return 1;
453
}
454

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
727
  bzero(&p->stats, sizeof(struct proto_stats));
728
  proto_free_ahooks(p);
729

    
730
  if (! p->proto->multitable)
731
    rt_unlock_table(p->table);
732

    
733
  if (p->proto->cleanup)
734
    p->proto->cleanup(p);
735

    
736
  proto_rethink_goal(p);
737
}
738

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

    
744
  if (p->core_state != FS_FEEDING)
745
    return;
746

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

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

    
766
  if (p->core_state != FS_FEEDING)
767
    return;
768

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

    
771
  if_feed_baby(p);
772
  proto_feed_more(P);
773
}
774

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

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

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

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

    
806
  proto_relink(p);
807
  p->attn->hook = initial ? proto_feed_initial : proto_feed_more;
808
  ev_schedule(p->attn);
809
}
810

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

    
820
static int flush_loop_state;        /* 1 -> running */
821

    
822
static void
823
proto_schedule_flush_loop(void)
824
{
825
  struct proto *p;
826

    
827
  if (flush_loop_state)
828
    return;
829
  flush_loop_state = 1;
830

    
831
  rt_schedule_prune_all();
832
  WALK_LIST(p, flush_proto_list)
833
    p->flushing = 1;
834

    
835
  ev_schedule(proto_flush_event);
836
}
837

    
838
static void
839
proto_flush_loop(void *unused UNUSED)
840
{
841
  struct proto *p;
842

    
843
  if (! rt_prune_loop())
844
    {
845
      /* Rtable pruning is not finished */
846
      ev_schedule(proto_flush_event);
847
      return;
848
    }
849

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

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

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

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

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

    
888
/* Temporary hack to propagate restart to BGP */
889
int proto_restart;
890

    
891
static void
892
proto_shutdown_loop(struct timer *t UNUSED)
893
{
894
  struct proto *p, *p_next;
895

    
896
  WALK_LIST_DELSAFE(p, p_next, active_proto_list)
897
    if (p->down_sched)
898
      {
899
        proto_restart = (p->down_sched == PDS_RESTART);
900

    
901
        p->disabled = 1;
902
        proto_rethink_goal(p);
903
        if (proto_restart)
904
          {
905
            p->disabled = 0;
906
            proto_rethink_goal(p);
907
          }
908
      }
909
}
910

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

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

    
921
  p->down_sched = restart ? PDS_RESTART : PDS_DISABLE;
922
  p->down_code = code;
923
  tm_start_max(proto_shutdown_timer, restart ? 2 : 0);
924
}
925

    
926

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

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

    
950
      rt_feed_baby_abort(p);
951
    }
952

    
953
  proto_schedule_feed(p, 0);
954
}
955

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

    
966
  return actions[l->action];
967
}
968

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

    
985
  if (l->state == PLS_BLOCKED)
986
    return;
987

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

    
993
  switch (l->action)
994
    {
995
    case PLA_WARN:
996
      l->state = PLS_ACTIVE;
997
      break;
998

    
999
    case PLA_BLOCK:
1000
      l->state = PLS_BLOCKED;
1001
      break;
1002

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

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

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

    
1036
  p->proto_state = ps;
1037

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

    
1046
      neigh_prune(); // FIXME convert neighbors to resource?
1047
      rfree(p->pool);
1048
      p->pool = NULL;
1049

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

    
1075
/*
1076
 *  CLI Commands
1077
 */
1078

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

    
1098
static void
1099
proto_show_stats(struct proto_stats *s, int in_keep_rejected)
1100
{
1101
  if (in_keep_rejected)
1102
    cli_msg(-1006, "  Routes:         %u imported, %u rejected, %u exported, %u preferred", 
1103
            s->imp_routes, s->rej_routes, s->exp_routes, s->pref_routes);
1104
  else
1105
    cli_msg(-1006, "  Routes:         %u imported, %u exported, %u preferred", 
1106
            s->imp_routes, s->exp_routes, s->pref_routes);
1107

    
1108
  cli_msg(-1006, "  Route change stats:     received   rejected   filtered    ignored   accepted");
1109
  cli_msg(-1006, "    Import updates:     %10u %10u %10u %10u %10u",
1110
          s->imp_updates_received, s->imp_updates_invalid,
1111
          s->imp_updates_filtered, s->imp_updates_ignored,
1112
          s->imp_updates_accepted);
1113
  cli_msg(-1006, "    Import withdraws:   %10u %10u        --- %10u %10u",
1114
          s->imp_withdraws_received, s->imp_withdraws_invalid,
1115
          s->imp_withdraws_ignored, s->imp_withdraws_accepted);
1116
  cli_msg(-1006, "    Export updates:     %10u %10u %10u        --- %10u",
1117
          s->exp_updates_received, s->exp_updates_rejected,
1118
          s->exp_updates_filtered, s->exp_updates_accepted);
1119
  cli_msg(-1006, "    Export withdraws:   %10u        ---        ---        --- %10u",
1120
          s->exp_withdraws_received, s->exp_withdraws_accepted);
1121
}
1122

    
1123
void
1124
proto_show_limit(struct proto_limit *l, const char *dsc)
1125
{
1126
  if (!l)
1127
    return;
1128

    
1129
  cli_msg(-1006, "  %-16s%d%s", dsc, l->limit, l->state ? " [HIT]" : "");
1130
  cli_msg(-1006, "    Action:       %s", proto_limit_name(l));
1131
}
1132

    
1133
void
1134
proto_show_basic_info(struct proto *p)
1135
{
1136
  // cli_msg(-1006, "  Table:          %s", p->table->name);
1137
  cli_msg(-1006, "  Preference:     %d", p->preference);
1138
  cli_msg(-1006, "  Input filter:   %s", filter_name(p->cf->in_filter));
1139
  cli_msg(-1006, "  Output filter:  %s", filter_name(p->cf->out_filter));
1140

    
1141
  proto_show_limit(p->cf->in_limit, "Import limit:");
1142
  proto_show_limit(p->cf->out_limit, "Export limit:");
1143

    
1144
  if (p->proto_state != PS_DOWN)
1145
    proto_show_stats(&p->stats, p->cf->in_keep_rejected);
1146
}
1147

    
1148
void
1149
proto_cmd_show(struct proto *p, unsigned int verbose, int cnt)
1150
{
1151
  byte buf[256], tbuf[TM_DATETIME_BUFFER_SIZE];
1152

    
1153
  /* First protocol - show header */
1154
  if (!cnt)
1155
    cli_msg(-2002, "name     proto    table    state  since       info");
1156

    
1157
  buf[0] = 0;
1158
  if (p->proto->get_status)
1159
    p->proto->get_status(p, buf);
1160
  tm_format_datetime(tbuf, &config->tf_proto, p->last_state_change);
1161
  cli_msg(-1002, "%-8s %-8s %-8s %-5s  %-10s  %s",
1162
          p->name,
1163
          p->proto->name,
1164
          p->table->name,
1165
          proto_state_name(p),
1166
          tbuf,
1167
          buf);
1168
  if (verbose)
1169
    {
1170
      if (p->cf->dsc)
1171
        cli_msg(-1006, "  Description:    %s", p->cf->dsc);
1172
      if (p->cf->router_id)
1173
        cli_msg(-1006, "  Router ID:      %R", p->cf->router_id);
1174

    
1175
      if (p->proto->show_proto_info)
1176
        p->proto->show_proto_info(p);
1177
      else
1178
        proto_show_basic_info(p);
1179

    
1180
      cli_msg(-1006, "");
1181
    }
1182
}
1183

    
1184
void
1185
proto_cmd_disable(struct proto *p, unsigned int arg UNUSED, int cnt UNUSED)
1186
{
1187
  if (p->disabled)
1188
    {
1189
      cli_msg(-8, "%s: already disabled", p->name);
1190
      return;
1191
    }
1192

    
1193
  log(L_INFO "Disabling protocol %s", p->name);
1194
  p->disabled = 1;
1195
  p->down_code = PDC_CMD_DISABLE;
1196
  proto_rethink_goal(p);
1197
  cli_msg(-9, "%s: disabled", p->name);
1198
}
1199

    
1200
void
1201
proto_cmd_enable(struct proto *p, unsigned int arg UNUSED, int cnt UNUSED)
1202
{
1203
  if (!p->disabled)
1204
    {
1205
      cli_msg(-10, "%s: already enabled", p->name);
1206
      return;
1207
    }
1208

    
1209
  log(L_INFO "Enabling protocol %s", p->name);
1210
  p->disabled = 0;
1211
  proto_rethink_goal(p);
1212
  cli_msg(-11, "%s: enabled", p->name);
1213
}
1214

    
1215
void
1216
proto_cmd_restart(struct proto *p, unsigned int arg UNUSED, int cnt UNUSED)
1217
{
1218
  if (p->disabled)
1219
    {
1220
      cli_msg(-8, "%s: already disabled", p->name);
1221
      return;
1222
    }
1223

    
1224
  log(L_INFO "Restarting protocol %s", p->name);
1225
  p->disabled = 1;
1226
  p->down_code = PDC_CMD_RESTART;
1227
  proto_rethink_goal(p);
1228
  p->disabled = 0;
1229
  proto_rethink_goal(p);
1230
  cli_msg(-12, "%s: restarted", p->name);
1231
}
1232

    
1233
void
1234
proto_cmd_reload(struct proto *p, unsigned int dir, int cnt UNUSED)
1235
{
1236
  if (p->disabled)
1237
    {
1238
      cli_msg(-8, "%s: already disabled", p->name);
1239
      return;
1240
    }
1241

    
1242
  /* If the protocol in not UP, it has no routes */
1243
  if (p->proto_state != PS_UP)
1244
    return;
1245

    
1246
  log(L_INFO "Reloading protocol %s", p->name);
1247

    
1248
  /* re-importing routes */
1249
  if (dir != CMD_RELOAD_OUT)
1250
    {
1251
      if (! (p->reload_routes && p->reload_routes(p)))
1252
        {
1253
          cli_msg(-8006, "%s: reload failed", p->name);
1254
          return;
1255
        }
1256

    
1257
      /*
1258
       * Should be done before reload_routes() hook?
1259
       * Perhaps, but these hooks work asynchronously.
1260
       */
1261
      if (!p->proto->multitable)
1262
        proto_reset_limit(p->main_ahook->in_limit);
1263
    }
1264

    
1265
  /* re-exporting routes */
1266
  if (dir != CMD_RELOAD_IN)
1267
    proto_request_feeding(p);
1268

    
1269
  cli_msg(-15, "%s: reloading", p->name);
1270
}
1271

    
1272
void
1273
proto_cmd_debug(struct proto *p, unsigned int mask, int cnt UNUSED)
1274
{
1275
  p->debug = mask;
1276
}
1277

    
1278
void
1279
proto_cmd_mrtdump(struct proto *p, unsigned int mask, int cnt UNUSED)
1280
{
1281
  p->mrtdump = mask;
1282
}
1283

    
1284
static void
1285
proto_apply_cmd_symbol(struct symbol *s, void (* cmd)(struct proto *, unsigned int, int), unsigned int arg)
1286
{
1287
  if (s->class != SYM_PROTO)
1288
    {
1289
      cli_msg(9002, "%s is not a protocol", s->name);
1290
      return;
1291
    }
1292

    
1293
  cmd(((struct proto_config *)s->def)->proto, arg, 0);
1294
  cli_msg(0, "");
1295
}
1296

    
1297
static void
1298
proto_apply_cmd_patt(char *patt, void (* cmd)(struct proto *, unsigned int, int), unsigned int arg)
1299
{
1300
  int cnt = 0;
1301

    
1302
  node *nn;
1303
  WALK_LIST(nn, proto_list)
1304
    {
1305
      struct proto *p = SKIP_BACK(struct proto, glob_node, nn);
1306

    
1307
      if (!patt || patmatch(patt, p->name))
1308
        cmd(p, arg, cnt++);
1309
    }
1310

    
1311
  if (!cnt)
1312
    cli_msg(8003, "No protocols match");
1313
  else
1314
    cli_msg(0, "");
1315
}
1316

    
1317
void
1318
proto_apply_cmd(struct proto_spec ps, void (* cmd)(struct proto *, unsigned int, int),
1319
                int restricted, unsigned int arg)
1320
{
1321
  if (restricted && cli_access_restricted())
1322
    return;
1323

    
1324
  if (ps.patt)
1325
    proto_apply_cmd_patt(ps.ptr, cmd, arg);
1326
  else
1327
    proto_apply_cmd_symbol(ps.ptr, cmd, arg);
1328
}
1329

    
1330
struct proto *
1331
proto_get_named(struct symbol *sym, struct protocol *pr)
1332
{
1333
  struct proto *p, *q;
1334

    
1335
  if (sym)
1336
    {
1337
      if (sym->class != SYM_PROTO)
1338
        cf_error("%s: Not a protocol", sym->name);
1339
      p = ((struct proto_config *)sym->def)->proto;
1340
      if (!p || p->proto != pr)
1341
        cf_error("%s: Not a %s protocol", sym->name, pr->name);
1342
    }
1343
  else
1344
    {
1345
      p = NULL;
1346
      WALK_LIST(q, active_proto_list)
1347
        if (q->proto == pr)
1348
          {
1349
            if (p)
1350
              cf_error("There are multiple %s protocols running", pr->name);
1351
            p = q;
1352
          }
1353
      if (!p)
1354
        cf_error("There is no %s protocol running", pr->name);
1355
    }
1356
  return p;
1357
}