File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / bird2 / nest / proto.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Oct 21 16:03:56 2019 UTC (4 years, 8 months ago) by misho
Branches: bird2, MAIN
CVS tags: v2_0_7p0, HEAD
bird2 ver 2.0.7

    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/timer.h"
   17: #include "lib/string.h"
   18: #include "conf/conf.h"
   19: #include "nest/route.h"
   20: #include "nest/iface.h"
   21: #include "nest/cli.h"
   22: #include "filter/filter.h"
   23: 
   24: pool *proto_pool;
   25: list  proto_list;
   26: 
   27: static list protocol_list;
   28: struct protocol *class_to_protocol[PROTOCOL__MAX];
   29: 
   30: #define PD(pr, msg, args...) do { if (pr->debug & D_STATES) { log(L_TRACE "%s: " msg, pr->name , ## args); } } while(0)
   31: 
   32: static timer *proto_shutdown_timer;
   33: static timer *gr_wait_timer;
   34: 
   35: #define GRS_NONE	0
   36: #define GRS_INIT	1
   37: #define GRS_ACTIVE	2
   38: #define GRS_DONE	3
   39: 
   40: static int graceful_restart_state;
   41: static u32 graceful_restart_locks;
   42: 
   43: static char *p_states[] = { "DOWN", "START", "UP", "STOP" };
   44: static char *c_states[] = { "DOWN", "START", "UP", "FLUSHING" };
   45: 
   46: extern struct protocol proto_unix_iface;
   47: 
   48: static void proto_shutdown_loop(timer *);
   49: static void proto_rethink_goal(struct proto *p);
   50: static char *proto_state_name(struct proto *p);
   51: static void channel_verify_limits(struct channel *c);
   52: static inline void channel_reset_limit(struct channel_limit *l);
   53: 
   54: 
   55: static inline int proto_is_done(struct proto *p)
   56: { return (p->proto_state == PS_DOWN) && (p->active_channels == 0); }
   57: 
   58: static inline int channel_is_active(struct channel *c)
   59: { return (c->channel_state == CS_START) || (c->channel_state == CS_UP); }
   60: 
   61: static void
   62: proto_log_state_change(struct proto *p)
   63: {
   64:   if (p->debug & D_STATES)
   65:   {
   66:     char *name = proto_state_name(p);
   67:     if (name != p->last_state_name_announced)
   68:     {
   69:       p->last_state_name_announced = name;
   70:       PD(p, "State changed to %s", proto_state_name(p));
   71:     }
   72:   }
   73:   else
   74:     p->last_state_name_announced = NULL;
   75: }
   76: 
   77: 
   78: struct channel_config *
   79: proto_cf_find_channel(struct proto_config *pc, uint net_type)
   80: {
   81:   struct channel_config *cc;
   82: 
   83:   WALK_LIST(cc, pc->channels)
   84:     if (cc->net_type == net_type)
   85:       return cc;
   86: 
   87:   return NULL;
   88: }
   89: 
   90: /**
   91:  * proto_find_channel_by_table - find channel connected to a routing table
   92:  * @p: protocol instance
   93:  * @t: routing table
   94:  *
   95:  * Returns pointer to channel or NULL
   96:  */
   97: struct channel *
   98: proto_find_channel_by_table(struct proto *p, struct rtable *t)
   99: {
  100:   struct channel *c;
  101: 
  102:   WALK_LIST(c, p->channels)
  103:     if (c->table == t)
  104:       return c;
  105: 
  106:   return NULL;
  107: }
  108: 
  109: /**
  110:  * proto_find_channel_by_name - find channel by its name
  111:  * @p: protocol instance
  112:  * @n: channel name
  113:  *
  114:  * Returns pointer to channel or NULL
  115:  */
  116: struct channel *
  117: proto_find_channel_by_name(struct proto *p, const char *n)
  118: {
  119:   struct channel *c;
  120: 
  121:   WALK_LIST(c, p->channels)
  122:     if (!strcmp(c->name, n))
  123:       return c;
  124: 
  125:   return NULL;
  126: }
  127: 
  128: /**
  129:  * proto_add_channel - connect protocol to a routing table
  130:  * @p: protocol instance
  131:  * @cf: channel configuration
  132:  *
  133:  * This function creates a channel between the protocol instance @p and the
  134:  * routing table specified in the configuration @cf, making the protocol hear
  135:  * all changes in the table and allowing the protocol to update routes in the
  136:  * table.
  137:  *
  138:  * The channel is linked in the protocol channel list and when active also in
  139:  * the table channel list. Channels are allocated from the global resource pool
  140:  * (@proto_pool) and they are automatically freed when the protocol is removed.
  141:  */
  142: 
  143: struct channel *
  144: proto_add_channel(struct proto *p, struct channel_config *cf)
  145: {
  146:   struct channel *c = mb_allocz(proto_pool, cf->channel->channel_size);
  147: 
  148:   c->name = cf->name;
  149:   c->channel = cf->channel;
  150:   c->proto = p;
  151:   c->table = cf->table->table;
  152: 
  153:   c->in_filter = cf->in_filter;
  154:   c->out_filter = cf->out_filter;
  155:   c->rx_limit = cf->rx_limit;
  156:   c->in_limit = cf->in_limit;
  157:   c->out_limit = cf->out_limit;
  158: 
  159:   c->net_type = cf->net_type;
  160:   c->ra_mode = cf->ra_mode;
  161:   c->preference = cf->preference;
  162:   c->merge_limit = cf->merge_limit;
  163:   c->in_keep_filtered = cf->in_keep_filtered;
  164: 
  165:   c->channel_state = CS_DOWN;
  166:   c->export_state = ES_DOWN;
  167:   c->last_state_change = current_time();
  168:   c->last_tx_filter_change = current_time();
  169:   c->reloadable = 1;
  170: 
  171:   CALL(c->channel->init, c, cf);
  172: 
  173:   add_tail(&p->channels, &c->n);
  174: 
  175:   PD(p, "Channel %s connected to table %s", c->name, c->table->name);
  176: 
  177:   return c;
  178: }
  179: 
  180: void
  181: proto_remove_channel(struct proto *p, struct channel *c)
  182: {
  183:   ASSERT(c->channel_state == CS_DOWN);
  184: 
  185:   PD(p, "Channel %s removed", c->name);
  186: 
  187:   rem_node(&c->n);
  188:   mb_free(c);
  189: }
  190: 
  191: 
  192: static void
  193: proto_start_channels(struct proto *p)
  194: {
  195:   struct channel *c;
  196:   WALK_LIST(c, p->channels)
  197:     if (!c->disabled)
  198:       channel_set_state(c, CS_UP);
  199: }
  200: 
  201: static void
  202: proto_pause_channels(struct proto *p)
  203: {
  204:   struct channel *c;
  205:   WALK_LIST(c, p->channels)
  206:     if (!c->disabled && channel_is_active(c))
  207:       channel_set_state(c, CS_START);
  208: }
  209: 
  210: static void
  211: proto_stop_channels(struct proto *p)
  212: {
  213:   struct channel *c;
  214:   WALK_LIST(c, p->channels)
  215:     if (!c->disabled && channel_is_active(c))
  216:       channel_set_state(c, CS_FLUSHING);
  217: }
  218: 
  219: static void
  220: proto_remove_channels(struct proto *p)
  221: {
  222:   struct channel *c;
  223:   WALK_LIST_FIRST(c, p->channels)
  224:     proto_remove_channel(p, c);
  225: }
  226: 
  227: static void
  228: channel_schedule_feed(struct channel *c, int initial)
  229: {
  230:   // DBG("%s: Scheduling meal\n", p->name);
  231:   ASSERT(c->channel_state == CS_UP);
  232: 
  233:   c->export_state = ES_FEEDING;
  234:   c->refeeding = !initial;
  235: 
  236:   ev_schedule(c->feed_event);
  237: }
  238: 
  239: static void
  240: channel_feed_loop(void *ptr)
  241: {
  242:   struct channel *c = ptr;
  243: 
  244:   if (c->export_state != ES_FEEDING)
  245:     return;
  246: 
  247:   if (!c->feed_active)
  248:     if (c->proto->feed_begin)
  249:       c->proto->feed_begin(c, !c->refeeding);
  250: 
  251:   // DBG("Feeding protocol %s continued\n", p->name);
  252:   if (!rt_feed_channel(c))
  253:   {
  254:     ev_schedule(c->feed_event);
  255:     return;
  256:   }
  257: 
  258:   // DBG("Feeding protocol %s finished\n", p->name);
  259:   c->export_state = ES_READY;
  260:   // proto_log_state_change(p);
  261: 
  262:   if (c->proto->feed_end)
  263:     c->proto->feed_end(c);
  264: }
  265: 
  266: 
  267: static void
  268: channel_start_export(struct channel *c)
  269: {
  270:   ASSERT(c->channel_state == CS_UP);
  271:   ASSERT(c->export_state == ES_DOWN);
  272: 
  273:   channel_schedule_feed(c, 1);	/* Sets ES_FEEDING */
  274: }
  275: 
  276: static void
  277: channel_stop_export(struct channel *c)
  278: {
  279:   /* Need to abort feeding */
  280:   if (c->export_state == ES_FEEDING)
  281:     rt_feed_channel_abort(c);
  282: 
  283:   c->export_state = ES_DOWN;
  284:   c->stats.exp_routes = 0;
  285: }
  286: 
  287: 
  288: /* Called by protocol for reload from in_table */
  289: void
  290: channel_schedule_reload(struct channel *c)
  291: {
  292:   ASSERT(c->channel_state == CS_UP);
  293: 
  294:   rt_reload_channel_abort(c);
  295:   ev_schedule(c->reload_event);
  296: }
  297: 
  298: static void
  299: channel_reload_loop(void *ptr)
  300: {
  301:   struct channel *c = ptr;
  302: 
  303:   if (!rt_reload_channel(c))
  304:   {
  305:     ev_schedule(c->reload_event);
  306:     return;
  307:   }
  308: }
  309: 
  310: static void
  311: channel_reset_import(struct channel *c)
  312: {
  313:   /* Need to abort feeding */
  314:   ev_postpone(c->reload_event);
  315:   rt_reload_channel_abort(c);
  316: 
  317:   rt_prune_sync(c->in_table, 1);
  318: }
  319: 
  320: static void
  321: channel_reset_export(struct channel *c)
  322: {
  323:   /* Just free the routes */
  324:   rt_prune_sync(c->out_table, 1);
  325: }
  326: 
  327: /* Called by protocol to activate in_table */
  328: void
  329: channel_setup_in_table(struct channel *c)
  330: {
  331:   struct rtable_config *cf = mb_allocz(c->proto->pool, sizeof(struct rtable_config));
  332:   cf->name = "import";
  333:   cf->addr_type = c->net_type;
  334: 
  335:   c->in_table = mb_allocz(c->proto->pool, sizeof(struct rtable));
  336:   rt_setup(c->proto->pool, c->in_table, cf);
  337: 
  338:   c->reload_event = ev_new_init(c->proto->pool, channel_reload_loop, c);
  339: }
  340: 
  341: /* Called by protocol to activate out_table */
  342: void
  343: channel_setup_out_table(struct channel *c)
  344: {
  345:   struct rtable_config *cf = mb_allocz(c->proto->pool, sizeof(struct rtable_config));
  346:   cf->name = "export";
  347:   cf->addr_type = c->net_type;
  348: 
  349:   c->out_table = mb_allocz(c->proto->pool, sizeof(struct rtable));
  350:   rt_setup(c->proto->pool, c->out_table, cf);
  351: }
  352: 
  353: 
  354: static void
  355: channel_do_start(struct channel *c)
  356: {
  357:   rt_lock_table(c->table);
  358:   add_tail(&c->table->channels, &c->table_node);
  359:   c->proto->active_channels++;
  360: 
  361:   c->feed_event = ev_new_init(c->proto->pool, channel_feed_loop, c);
  362: 
  363:   channel_reset_limit(&c->rx_limit);
  364:   channel_reset_limit(&c->in_limit);
  365:   channel_reset_limit(&c->out_limit);
  366: 
  367:   CALL(c->channel->start, c);
  368: }
  369: 
  370: static void
  371: channel_do_flush(struct channel *c)
  372: {
  373:   rt_schedule_prune(c->table);
  374: 
  375:   c->gr_wait = 0;
  376:   if (c->gr_lock)
  377:     channel_graceful_restart_unlock(c);
  378: 
  379:   CALL(c->channel->shutdown, c);
  380: }
  381: 
  382: static void
  383: channel_do_down(struct channel *c)
  384: {
  385:   ASSERT(!c->feed_active && !c->reload_active);
  386: 
  387:   rem_node(&c->table_node);
  388:   rt_unlock_table(c->table);
  389:   c->proto->active_channels--;
  390: 
  391:   if ((c->stats.imp_routes + c->stats.filt_routes) != 0)
  392:     log(L_ERR "%s: Channel %s is down but still has some routes", c->proto->name, c->name);
  393: 
  394:   memset(&c->stats, 0, sizeof(struct proto_stats));
  395: 
  396:   c->in_table = NULL;
  397:   c->reload_event = NULL;
  398:   c->out_table = NULL;
  399: 
  400:   CALL(c->channel->cleanup, c);
  401: 
  402:   /* Schedule protocol shutddown */
  403:   if (proto_is_done(c->proto))
  404:     ev_schedule(c->proto->event);
  405: }
  406: 
  407: void
  408: channel_set_state(struct channel *c, uint state)
  409: {
  410:   uint cs = c->channel_state;
  411:   uint es = c->export_state;
  412: 
  413:   DBG("%s reporting channel %s state transition %s -> %s\n", c->proto->name, c->name, c_states[cs], c_states[state]);
  414:   if (state == cs)
  415:     return;
  416: 
  417:   c->channel_state = state;
  418:   c->last_state_change = current_time();
  419: 
  420:   switch (state)
  421:   {
  422:   case CS_START:
  423:     ASSERT(cs == CS_DOWN || cs == CS_UP);
  424: 
  425:     if (cs == CS_DOWN)
  426:       channel_do_start(c);
  427: 
  428:     if (es != ES_DOWN)
  429:       channel_stop_export(c);
  430: 
  431:     if (c->in_table && (cs == CS_UP))
  432:       channel_reset_import(c);
  433: 
  434:     if (c->out_table && (cs == CS_UP))
  435:       channel_reset_export(c);
  436: 
  437:     break;
  438: 
  439:   case CS_UP:
  440:     ASSERT(cs == CS_DOWN || cs == CS_START);
  441: 
  442:     if (cs == CS_DOWN)
  443:       channel_do_start(c);
  444: 
  445:     if (!c->gr_wait && c->proto->rt_notify)
  446:       channel_start_export(c);
  447: 
  448:     break;
  449: 
  450:   case CS_FLUSHING:
  451:     ASSERT(cs == CS_START || cs == CS_UP);
  452: 
  453:     if (es != ES_DOWN)
  454:       channel_stop_export(c);
  455: 
  456:     if (c->in_table && (cs == CS_UP))
  457:       channel_reset_import(c);
  458: 
  459:     if (c->out_table && (cs == CS_UP))
  460:       channel_reset_export(c);
  461: 
  462:     channel_do_flush(c);
  463:     break;
  464: 
  465:   case CS_DOWN:
  466:     ASSERT(cs == CS_FLUSHING);
  467: 
  468:     channel_do_down(c);
  469:     break;
  470: 
  471:   default:
  472:     ASSERT(0);
  473:   }
  474:   // XXXX proto_log_state_change(c);
  475: }
  476: 
  477: /**
  478:  * channel_request_feeding - request feeding routes to the channel
  479:  * @c: given channel
  480:  *
  481:  * Sometimes it is needed to send again all routes to the channel. This is
  482:  * called feeding and can be requested by this function. This would cause
  483:  * channel export state transition to ES_FEEDING (during feeding) and when
  484:  * completed, it will switch back to ES_READY. This function can be called
  485:  * even when feeding is already running, in that case it is restarted.
  486:  */
  487: void
  488: channel_request_feeding(struct channel *c)
  489: {
  490:   ASSERT(c->channel_state == CS_UP);
  491: 
  492:   /* Do nothing if we are still waiting for feeding */
  493:   if (c->export_state == ES_DOWN)
  494:     return;
  495: 
  496:   /* If we are already feeding, we want to restart it */
  497:   if (c->export_state == ES_FEEDING)
  498:   {
  499:     /* Unless feeding is in initial state */
  500:     if (!c->feed_active)
  501: 	return;
  502: 
  503:     rt_feed_channel_abort(c);
  504:   }
  505: 
  506:   channel_reset_limit(&c->out_limit);
  507: 
  508:   /* Hack: reset exp_routes during refeed, and do not decrease it later */
  509:   c->stats.exp_routes = 0;
  510: 
  511:   channel_schedule_feed(c, 0);	/* Sets ES_FEEDING */
  512:   // proto_log_state_change(c);
  513: }
  514: 
  515: static inline int
  516: channel_reloadable(struct channel *c)
  517: {
  518:   return c->proto->reload_routes && c->reloadable;
  519: }
  520: 
  521: static void
  522: channel_request_reload(struct channel *c)
  523: {
  524:   ASSERT(c->channel_state == CS_UP);
  525:   ASSERT(channel_reloadable(c));
  526: 
  527:   c->proto->reload_routes(c);
  528: 
  529:   /*
  530:    * Should this be done before reload_routes() hook?
  531:    * Perhaps, but routes are updated asynchronously.
  532:    */
  533:   channel_reset_limit(&c->rx_limit);
  534:   channel_reset_limit(&c->in_limit);
  535: }
  536: 
  537: const struct channel_class channel_basic = {
  538:   .channel_size = sizeof(struct channel),
  539:   .config_size = sizeof(struct channel_config)
  540: };
  541: 
  542: void *
  543: channel_config_new(const struct channel_class *cc, const char *name, uint net_type, struct proto_config *proto)
  544: {
  545:   struct channel_config *cf = NULL;
  546:   struct rtable_config *tab = NULL;
  547: 
  548:   if (net_type)
  549:   {
  550:     if (!net_val_match(net_type, proto->protocol->channel_mask))
  551:       cf_error("Unsupported channel type");
  552: 
  553:     if (proto->net_type && (net_type != proto->net_type))
  554:       cf_error("Different channel type");
  555: 
  556:     tab = new_config->def_tables[net_type];
  557:   }
  558: 
  559:   if (!cc)
  560:     cc = &channel_basic;
  561: 
  562:   cf = cfg_allocz(cc->config_size);
  563:   cf->name = name;
  564:   cf->channel = cc;
  565:   cf->parent = proto;
  566:   cf->table = tab;
  567:   cf->out_filter = FILTER_REJECT;
  568: 
  569:   cf->net_type = net_type;
  570:   cf->ra_mode = RA_OPTIMAL;
  571:   cf->preference = proto->protocol->preference;
  572: 
  573:   add_tail(&proto->channels, &cf->n);
  574: 
  575:   return cf;
  576: }
  577: 
  578: void *
  579: channel_config_get(const struct channel_class *cc, const char *name, uint net_type, struct proto_config *proto)
  580: {
  581:   struct channel_config *cf;
  582: 
  583:   /* We are using name as token, so no strcmp() */
  584:   WALK_LIST(cf, proto->channels)
  585:     if (cf->name == name)
  586:     {
  587:       /* Allow to redefine channel only if inherited from template */
  588:       if (cf->parent == proto)
  589: 	cf_error("Multiple %s channels", name);
  590: 
  591:       cf->parent = proto;
  592:       return cf;
  593:     }
  594: 
  595:   return channel_config_new(cc, name, net_type, proto);
  596: }
  597: 
  598: struct channel_config *
  599: channel_copy_config(struct channel_config *src, struct proto_config *proto)
  600: {
  601:   struct channel_config *dst = cfg_alloc(src->channel->config_size);
  602: 
  603:   memcpy(dst, src, src->channel->config_size);
  604:   add_tail(&proto->channels, &dst->n);
  605:   CALL(src->channel->copy_config, dst, src);
  606: 
  607:   return dst;
  608: }
  609: 
  610: 
  611: static int reconfigure_type;  /* Hack to propagate type info to channel_reconfigure() */
  612: 
  613: int
  614: channel_reconfigure(struct channel *c, struct channel_config *cf)
  615: {
  616:   /* FIXME: better handle these changes, also handle in_keep_filtered */
  617:   if ((c->table != cf->table->table) || (cf->ra_mode && (c->ra_mode != cf->ra_mode)))
  618:     return 0;
  619: 
  620:   /* Note that filter_same() requires arguments in (new, old) order */
  621:   int import_changed = !filter_same(cf->in_filter, c->in_filter);
  622:   int export_changed = !filter_same(cf->out_filter, c->out_filter);
  623: 
  624:   if (c->preference != cf->preference)
  625:     import_changed = 1;
  626: 
  627:   if (c->merge_limit != cf->merge_limit)
  628:     export_changed = 1;
  629: 
  630:   /* Reconfigure channel fields */
  631:   c->in_filter = cf->in_filter;
  632:   c->out_filter = cf->out_filter;
  633:   c->rx_limit = cf->rx_limit;
  634:   c->in_limit = cf->in_limit;
  635:   c->out_limit = cf->out_limit;
  636: 
  637:   // c->ra_mode = cf->ra_mode;
  638:   c->merge_limit = cf->merge_limit;
  639:   c->preference = cf->preference;
  640:   c->in_keep_filtered = cf->in_keep_filtered;
  641: 
  642:   channel_verify_limits(c);
  643: 
  644:   if (export_changed)
  645:     c->last_tx_filter_change = current_time();
  646: 
  647:   /* Execute channel-specific reconfigure hook */
  648:   if (c->channel->reconfigure && !c->channel->reconfigure(c, cf, &import_changed, &export_changed))
  649:     return 0;
  650: 
  651:   /* If the channel is not open, it has no routes and we cannot reload it anyways */
  652:   if (c->channel_state != CS_UP)
  653:     return 1;
  654: 
  655:   if (reconfigure_type == RECONFIG_SOFT)
  656:   {
  657:     if (import_changed)
  658:       log(L_INFO "Channel %s.%s changed import", c->proto->name, c->name);
  659: 
  660:     if (export_changed)
  661:       log(L_INFO "Channel %s.%s changed export", c->proto->name, c->name);
  662: 
  663:     return 1;
  664:   }
  665: 
  666:   /* Route reload may be not supported */
  667:   if (import_changed && !channel_reloadable(c))
  668:     return 0;
  669: 
  670:   if (import_changed || export_changed)
  671:     log(L_INFO "Reloading channel %s.%s", c->proto->name, c->name);
  672: 
  673:   if (import_changed)
  674:     channel_request_reload(c);
  675: 
  676:   if (export_changed)
  677:     channel_request_feeding(c);
  678: 
  679:   return 1;
  680: }
  681: 
  682: 
  683: int
  684: proto_configure_channel(struct proto *p, struct channel **pc, struct channel_config *cf)
  685: {
  686:   struct channel *c = *pc;
  687: 
  688:   if (!c && cf)
  689:   {
  690:     /* We could add the channel, but currently it would just stay in down state
  691:        until protocol is restarted, so it is better to force restart anyways. */
  692:     if (p->proto_state != PS_DOWN)
  693:     {
  694:       log(L_INFO "Cannot add channel %s.%s", p->name, cf->name);
  695:       return 0;
  696:     }
  697: 
  698:     *pc = proto_add_channel(p, cf);
  699:   }
  700:   else if (c && !cf)
  701:   {
  702:     if (c->channel_state != CS_DOWN)
  703:     {
  704:       log(L_INFO "Cannot remove channel %s.%s", c->proto->name, c->name);
  705:       return 0;
  706:     }
  707: 
  708:     proto_remove_channel(p, c);
  709:     *pc = NULL;
  710:   }
  711:   else if (c && cf)
  712:   {
  713:     if (!channel_reconfigure(c, cf))
  714:     {
  715:       log(L_INFO "Cannot reconfigure channel %s.%s", c->proto->name, c->name);
  716:       return 0;
  717:     }
  718:   }
  719: 
  720:   return 1;
  721: }
  722: 
  723: 
  724: static void
  725: proto_event(void *ptr)
  726: {
  727:   struct proto *p = ptr;
  728: 
  729:   if (p->do_start)
  730:   {
  731:     if_feed_baby(p);
  732:     p->do_start = 0;
  733:   }
  734: 
  735:   if (p->do_stop)
  736:   {
  737:     if (p->proto == &proto_unix_iface)
  738:       if_flush_ifaces(p);
  739:     p->do_stop = 0;
  740:   }
  741: 
  742:   if (proto_is_done(p))
  743:   {
  744:     if (p->proto->cleanup)
  745:       p->proto->cleanup(p);
  746: 
  747:     p->active = 0;
  748:     proto_log_state_change(p);
  749:     proto_rethink_goal(p);
  750:   }
  751: }
  752: 
  753: 
  754: /**
  755:  * proto_new - create a new protocol instance
  756:  * @c: protocol configuration
  757:  *
  758:  * When a new configuration has been read in, the core code starts
  759:  * initializing all the protocol instances configured by calling their
  760:  * init() hooks with the corresponding instance configuration. The initialization
  761:  * code of the protocol is expected to create a new instance according to the
  762:  * configuration by calling this function and then modifying the default settings
  763:  * to values wanted by the protocol.
  764:  */
  765: void *
  766: proto_new(struct proto_config *cf)
  767: {
  768:   struct proto *p = mb_allocz(proto_pool, cf->protocol->proto_size);
  769: 
  770:   p->cf = cf;
  771:   p->debug = cf->debug;
  772:   p->mrtdump = cf->mrtdump;
  773:   p->name = cf->name;
  774:   p->proto = cf->protocol;
  775:   p->net_type = cf->net_type;
  776:   p->disabled = cf->disabled;
  777:   p->hash_key = random_u32();
  778:   cf->proto = p;
  779: 
  780:   init_list(&p->channels);
  781: 
  782:   return p;
  783: }
  784: 
  785: static struct proto *
  786: proto_init(struct proto_config *c, node *n)
  787: {
  788:   struct protocol *pr = c->protocol;
  789:   struct proto *p = pr->init(c);
  790: 
  791:   p->proto_state = PS_DOWN;
  792:   p->last_state_change = current_time();
  793:   p->vrf = c->vrf;
  794:   p->vrf_set = c->vrf_set;
  795:   insert_node(&p->n, n);
  796: 
  797:   p->event = ev_new_init(proto_pool, proto_event, p);
  798: 
  799:   PD(p, "Initializing%s", p->disabled ? " [disabled]" : "");
  800: 
  801:   return p;
  802: }
  803: 
  804: static void
  805: proto_start(struct proto *p)
  806: {
  807:   /* Here we cannot use p->cf->name since it won't survive reconfiguration */
  808:   p->pool = rp_new(proto_pool, p->proto->name);
  809: 
  810:   if (graceful_restart_state == GRS_INIT)
  811:     p->gr_recovery = 1;
  812: }
  813: 
  814: 
  815: /**
  816:  * proto_config_new - create a new protocol configuration
  817:  * @pr: protocol the configuration will belong to
  818:  * @class: SYM_PROTO or SYM_TEMPLATE
  819:  *
  820:  * Whenever the configuration file says that a new instance
  821:  * of a routing protocol should be created, the parser calls
  822:  * proto_config_new() to create a configuration entry for this
  823:  * instance (a structure staring with the &proto_config header
  824:  * containing all the generic items followed by protocol-specific
  825:  * ones). Also, the configuration entry gets added to the list
  826:  * of protocol instances kept in the configuration.
  827:  *
  828:  * The function is also used to create protocol templates (when class
  829:  * SYM_TEMPLATE is specified), the only difference is that templates
  830:  * are not added to the list of protocol instances and therefore not
  831:  * initialized during protos_commit()).
  832:  */
  833: void *
  834: proto_config_new(struct protocol *pr, int class)
  835: {
  836:   struct proto_config *cf = cfg_allocz(pr->config_size);
  837: 
  838:   if (class == SYM_PROTO)
  839:     add_tail(&new_config->protos, &cf->n);
  840: 
  841:   cf->global = new_config;
  842:   cf->protocol = pr;
  843:   cf->name = pr->name;
  844:   cf->class = class;
  845:   cf->debug = new_config->proto_default_debug;
  846:   cf->mrtdump = new_config->proto_default_mrtdump;
  847: 
  848:   init_list(&cf->channels);
  849: 
  850:   return cf;
  851: }
  852: 
  853: 
  854: /**
  855:  * proto_copy_config - copy a protocol configuration
  856:  * @dest: destination protocol configuration
  857:  * @src: source protocol configuration
  858:  *
  859:  * Whenever a new instance of a routing protocol is created from the
  860:  * template, proto_copy_config() is called to copy a content of
  861:  * the source protocol configuration to the new protocol configuration.
  862:  * Name, class and a node in protos list of @dest are kept intact.
  863:  * copy_config() protocol hook is used to copy protocol-specific data.
  864:  */
  865: void
  866: proto_copy_config(struct proto_config *dest, struct proto_config *src)
  867: {
  868:   struct channel_config *cc;
  869:   node old_node;
  870:   int old_class;
  871:   char *old_name;
  872: 
  873:   if (dest->protocol != src->protocol)
  874:     cf_error("Can't copy configuration from a different protocol type");
  875: 
  876:   if (dest->protocol->copy_config == NULL)
  877:     cf_error("Inheriting configuration for %s is not supported", src->protocol->name);
  878: 
  879:   DBG("Copying configuration from %s to %s\n", src->name, dest->name);
  880: 
  881:   /*
  882:    * Copy struct proto_config here. Keep original node, class and name.
  883:    * protocol-specific config copy is handled by protocol copy_config() hook
  884:    */
  885: 
  886:   old_node = dest->n;
  887:   old_class = dest->class;
  888:   old_name = dest->name;
  889: 
  890:   memcpy(dest, src, src->protocol->config_size);
  891: 
  892:   dest->n = old_node;
  893:   dest->class = old_class;
  894:   dest->name = old_name;
  895:   init_list(&dest->channels);
  896: 
  897:   WALK_LIST(cc, src->channels)
  898:     channel_copy_config(cc, dest);
  899: 
  900:   /* FIXME: allow for undefined copy_config */
  901:   dest->protocol->copy_config(dest, src);
  902: }
  903: 
  904: void
  905: proto_clone_config(struct symbol *sym, struct proto_config *parent)
  906: {
  907:   struct proto_config *cf = proto_config_new(parent->protocol, SYM_PROTO);
  908:   proto_copy_config(cf, parent);
  909:   cf->name = sym->name;
  910:   cf->proto = NULL;
  911:   cf->parent = parent;
  912: 
  913:   sym->class = cf->class;
  914:   sym->proto = cf;
  915: }
  916: 
  917: static void
  918: proto_undef_clone(struct symbol *sym, struct proto_config *cf)
  919: {
  920:   rem_node(&cf->n);
  921: 
  922:   sym->class = SYM_VOID;
  923:   sym->proto = NULL;
  924: }
  925: 
  926: /**
  927:  * protos_preconfig - pre-configuration processing
  928:  * @c: new configuration
  929:  *
  930:  * This function calls the preconfig() hooks of all routing
  931:  * protocols available to prepare them for reading of the new
  932:  * configuration.
  933:  */
  934: void
  935: protos_preconfig(struct config *c)
  936: {
  937:   struct protocol *p;
  938: 
  939:   init_list(&c->protos);
  940:   DBG("Protocol preconfig:");
  941:   WALK_LIST(p, protocol_list)
  942:   {
  943:     DBG(" %s", p->name);
  944:     p->name_counter = 0;
  945:     if (p->preconfig)
  946:       p->preconfig(p, c);
  947:   }
  948:   DBG("\n");
  949: }
  950: 
  951: static int
  952: proto_reconfigure(struct proto *p, struct proto_config *oc, struct proto_config *nc, int type)
  953: {
  954:   /* If the protocol is DOWN, we just restart it */
  955:   if (p->proto_state == PS_DOWN)
  956:     return 0;
  957: 
  958:   /* If there is a too big change in core attributes, ... */
  959:   if ((nc->protocol != oc->protocol) ||
  960:       (nc->net_type != oc->net_type) ||
  961:       (nc->disabled != p->disabled) ||
  962:       (nc->vrf != oc->vrf) ||
  963:       (nc->vrf_set != oc->vrf_set))
  964:     return 0;
  965: 
  966:   p->name = nc->name;
  967:   p->debug = nc->debug;
  968:   p->mrtdump = nc->mrtdump;
  969:   reconfigure_type = type;
  970: 
  971:   /* Execute protocol specific reconfigure hook */
  972:   if (!p->proto->reconfigure || !p->proto->reconfigure(p, nc))
  973:     return 0;
  974: 
  975:   DBG("\t%s: same\n", oc->name);
  976:   PD(p, "Reconfigured");
  977:   p->cf = nc;
  978: 
  979:   return 1;
  980: }
  981: 
  982: /**
  983:  * protos_commit - commit new protocol configuration
  984:  * @new: new configuration
  985:  * @old: old configuration or %NULL if it's boot time config
  986:  * @force_reconfig: force restart of all protocols (used for example
  987:  * when the router ID changes)
  988:  * @type: type of reconfiguration (RECONFIG_SOFT or RECONFIG_HARD)
  989:  *
  990:  * Scan differences between @old and @new configuration and adjust all
  991:  * protocol instances to conform to the new configuration.
  992:  *
  993:  * When a protocol exists in the new configuration, but it doesn't in the
  994:  * original one, it's immediately started. When a collision with the other
  995:  * running protocol would arise, the new protocol will be temporarily stopped
  996:  * by the locking mechanism.
  997:  *
  998:  * When a protocol exists in the old configuration, but it doesn't in the
  999:  * new one, it's shut down and deleted after the shutdown completes.
 1000:  *
 1001:  * When a protocol exists in both configurations, the core decides
 1002:  * whether it's possible to reconfigure it dynamically - it checks all
 1003:  * the core properties of the protocol (changes in filters are ignored
 1004:  * if type is RECONFIG_SOFT) and if they match, it asks the
 1005:  * reconfigure() hook of the protocol to see if the protocol is able
 1006:  * to switch to the new configuration.  If it isn't possible, the
 1007:  * protocol is shut down and a new instance is started with the new
 1008:  * configuration after the shutdown is completed.
 1009:  */
 1010: void
 1011: protos_commit(struct config *new, struct config *old, int force_reconfig, int type)
 1012: {
 1013:   struct proto_config *oc, *nc;
 1014:   struct symbol *sym;
 1015:   struct proto *p;
 1016:   node *n;
 1017: 
 1018: 
 1019:   DBG("protos_commit:\n");
 1020:   if (old)
 1021:   {
 1022:     WALK_LIST(oc, old->protos)
 1023:     {
 1024:       p = oc->proto;
 1025:       sym = cf_find_symbol(new, oc->name);
 1026: 
 1027:       /* Handle dynamic protocols */
 1028:       if (!sym && oc->parent && !new->shutdown)
 1029:       {
 1030: 	struct symbol *parsym = cf_find_symbol(new, oc->parent->name);
 1031: 	if (parsym && parsym->class == SYM_PROTO)
 1032: 	{
 1033: 	  /* This is hack, we would like to share config, but we need to copy it now */
 1034: 	  new_config = new;
 1035: 	  cfg_mem = new->mem;
 1036: 	  conf_this_scope = new->root_scope;
 1037: 	  sym = cf_get_symbol(oc->name);
 1038: 	  proto_clone_config(sym, parsym->proto);
 1039: 	  new_config = NULL;
 1040: 	  cfg_mem = NULL;
 1041: 	}
 1042:       }
 1043: 
 1044:       if (sym && sym->class == SYM_PROTO && !new->shutdown)
 1045:       {
 1046: 	/* Found match, let's check if we can smoothly switch to new configuration */
 1047: 	/* No need to check description */
 1048: 	nc = sym->proto;
 1049: 	nc->proto = p;
 1050: 
 1051: 	/* We will try to reconfigure protocol p */
 1052: 	if (! force_reconfig && proto_reconfigure(p, oc, nc, type))
 1053: 	  continue;
 1054: 
 1055: 	if (nc->parent)
 1056: 	{
 1057: 	  proto_undef_clone(sym, nc);
 1058: 	  goto remove;
 1059: 	}
 1060: 
 1061: 	/* Unsuccessful, we will restart it */
 1062: 	if (!p->disabled && !nc->disabled)
 1063: 	  log(L_INFO "Restarting protocol %s", p->name);
 1064: 	else if (p->disabled && !nc->disabled)
 1065: 	  log(L_INFO "Enabling protocol %s", p->name);
 1066: 	else if (!p->disabled && nc->disabled)
 1067: 	  log(L_INFO "Disabling protocol %s", p->name);
 1068: 
 1069: 	p->down_code = nc->disabled ? PDC_CF_DISABLE : PDC_CF_RESTART;
 1070: 	p->cf_new = nc;
 1071:       }
 1072:       else if (!new->shutdown)
 1073:       {
 1074:       remove:
 1075: 	log(L_INFO "Removing protocol %s", p->name);
 1076: 	p->down_code = PDC_CF_REMOVE;
 1077: 	p->cf_new = NULL;
 1078:       }
 1079:       else if (new->gr_down)
 1080:       {
 1081: 	p->down_code = PDC_CMD_GR_DOWN;
 1082: 	p->cf_new = NULL;
 1083:       }
 1084:       else /* global shutdown */
 1085:       {
 1086: 	p->down_code = PDC_CMD_SHUTDOWN;
 1087: 	p->cf_new = NULL;
 1088:       }
 1089: 
 1090:       p->reconfiguring = 1;
 1091:       config_add_obstacle(old);
 1092:       proto_rethink_goal(p);
 1093:     }
 1094:   }
 1095: 
 1096:   struct proto *first_dev_proto = NULL;
 1097: 
 1098:   n = NODE &(proto_list.head);
 1099:   WALK_LIST(nc, new->protos)
 1100:     if (!nc->proto)
 1101:     {
 1102:       /* Not a first-time configuration */
 1103:       if (old)
 1104: 	log(L_INFO "Adding protocol %s", nc->name);
 1105: 
 1106:       p = proto_init(nc, n);
 1107:       n = NODE p;
 1108: 
 1109:       if (p->proto == &proto_unix_iface)
 1110: 	first_dev_proto = p;
 1111:     }
 1112:     else
 1113:       n = NODE nc->proto;
 1114: 
 1115:   DBG("Protocol start\n");
 1116: 
 1117:   /* Start device protocol first */
 1118:   if (first_dev_proto)
 1119:     proto_rethink_goal(first_dev_proto);
 1120: 
 1121:   /* Determine router ID for the first time - it has to be here and not in
 1122:      global_commit() because it is postponed after start of device protocol */
 1123:   if (!config->router_id)
 1124:   {
 1125:     config->router_id = if_choose_router_id(config->router_id_from, 0);
 1126:     if (!config->router_id)
 1127:       die("Cannot determine router ID, please configure it manually");
 1128:   }
 1129: 
 1130:   /* Start all new protocols */
 1131:   WALK_LIST_DELSAFE(p, n, proto_list)
 1132:     proto_rethink_goal(p);
 1133: }
 1134: 
 1135: static void
 1136: proto_rethink_goal(struct proto *p)
 1137: {
 1138:   struct protocol *q;
 1139:   byte goal;
 1140: 
 1141:   if (p->reconfiguring && !p->active)
 1142:   {
 1143:     struct proto_config *nc = p->cf_new;
 1144:     node *n = p->n.prev;
 1145:     DBG("%s has shut down for reconfiguration\n", p->name);
 1146:     p->cf->proto = NULL;
 1147:     config_del_obstacle(p->cf->global);
 1148:     proto_remove_channels(p);
 1149:     rem_node(&p->n);
 1150:     rfree(p->event);
 1151:     mb_free(p->message);
 1152:     mb_free(p);
 1153:     if (!nc)
 1154:       return;
 1155:     p = proto_init(nc, n);
 1156:   }
 1157: 
 1158:   /* Determine what state we want to reach */
 1159:   if (p->disabled || p->reconfiguring)
 1160:     goal = PS_DOWN;
 1161:   else
 1162:     goal = PS_UP;
 1163: 
 1164:   q = p->proto;
 1165:   if (goal == PS_UP)
 1166:   {
 1167:     if (!p->active)
 1168:     {
 1169:       /* Going up */
 1170:       DBG("Kicking %s up\n", p->name);
 1171:       PD(p, "Starting");
 1172:       proto_start(p);
 1173:       proto_notify_state(p, (q->start ? q->start(p) : PS_UP));
 1174:     }
 1175:   }
 1176:   else
 1177:   {
 1178:     if (p->proto_state == PS_START || p->proto_state == PS_UP)
 1179:     {
 1180:       /* Going down */
 1181:       DBG("Kicking %s down\n", p->name);
 1182:       PD(p, "Shutting down");
 1183:       proto_notify_state(p, (q->shutdown ? q->shutdown(p) : PS_DOWN));
 1184:     }
 1185:   }
 1186: }
 1187: 
 1188: struct proto *
 1189: proto_spawn(struct proto_config *cf, uint disabled)
 1190: {
 1191:   struct proto *p = proto_init(cf, TAIL(proto_list));
 1192:   p->disabled = disabled;
 1193:   proto_rethink_goal(p);
 1194:   return p;
 1195: }
 1196: 
 1197: 
 1198: /**
 1199:  * DOC: Graceful restart recovery
 1200:  *
 1201:  * Graceful restart of a router is a process when the routing plane (e.g. BIRD)
 1202:  * restarts but both the forwarding plane (e.g kernel routing table) and routing
 1203:  * neighbors keep proper routes, and therefore uninterrupted packet forwarding
 1204:  * is maintained.
 1205:  *
 1206:  * BIRD implements graceful restart recovery by deferring export of routes to
 1207:  * protocols until routing tables are refilled with the expected content. After
 1208:  * start, protocols generate routes as usual, but routes are not propagated to
 1209:  * them, until protocols report that they generated all routes. After that,
 1210:  * graceful restart recovery is finished and the export (and the initial feed)
 1211:  * to protocols is enabled.
 1212:  *
 1213:  * When graceful restart recovery need is detected during initialization, then
 1214:  * enabled protocols are marked with @gr_recovery flag before start. Such
 1215:  * protocols then decide how to proceed with graceful restart, participation is
 1216:  * voluntary. Protocols could lock the recovery for each channel by function
 1217:  * channel_graceful_restart_lock() (state stored in @gr_lock flag), which means
 1218:  * that they want to postpone the end of the recovery until they converge and
 1219:  * then unlock it. They also could set @gr_wait before advancing to %PS_UP,
 1220:  * which means that the core should defer route export to that channel until
 1221:  * the end of the recovery. This should be done by protocols that expect their
 1222:  * neigbors to keep the proper routes (kernel table, BGP sessions with BGP
 1223:  * graceful restart capability).
 1224:  *
 1225:  * The graceful restart recovery is finished when either all graceful restart
 1226:  * locks are unlocked or when graceful restart wait timer fires.
 1227:  *
 1228:  */
 1229: 
 1230: static void graceful_restart_done(timer *t);
 1231: 
 1232: /**
 1233:  * graceful_restart_recovery - request initial graceful restart recovery
 1234:  *
 1235:  * Called by the platform initialization code if the need for recovery
 1236:  * after graceful restart is detected during boot. Have to be called
 1237:  * before protos_commit().
 1238:  */
 1239: void
 1240: graceful_restart_recovery(void)
 1241: {
 1242:   graceful_restart_state = GRS_INIT;
 1243: }
 1244: 
 1245: /**
 1246:  * graceful_restart_init - initialize graceful restart
 1247:  *
 1248:  * When graceful restart recovery was requested, the function starts an active
 1249:  * phase of the recovery and initializes graceful restart wait timer. The
 1250:  * function have to be called after protos_commit().
 1251:  */
 1252: void
 1253: graceful_restart_init(void)
 1254: {
 1255:   if (!graceful_restart_state)
 1256:     return;
 1257: 
 1258:   log(L_INFO "Graceful restart started");
 1259: 
 1260:   if (!graceful_restart_locks)
 1261:   {
 1262:     graceful_restart_done(NULL);
 1263:     return;
 1264:   }
 1265: 
 1266:   graceful_restart_state = GRS_ACTIVE;
 1267:   gr_wait_timer = tm_new_init(proto_pool, graceful_restart_done, NULL, 0, 0);
 1268:   tm_start(gr_wait_timer, config->gr_wait S);
 1269: }
 1270: 
 1271: /**
 1272:  * graceful_restart_done - finalize graceful restart
 1273:  * @t: unused
 1274:  *
 1275:  * When there are no locks on graceful restart, the functions finalizes the
 1276:  * graceful restart recovery. Protocols postponing route export until the end of
 1277:  * the recovery are awakened and the export to them is enabled. All other
 1278:  * related state is cleared. The function is also called when the graceful
 1279:  * restart wait timer fires (but there are still some locks).
 1280:  */
 1281: static void
 1282: graceful_restart_done(timer *t UNUSED)
 1283: {
 1284:   log(L_INFO "Graceful restart done");
 1285:   graceful_restart_state = GRS_DONE;
 1286: 
 1287:   struct proto *p;
 1288:   WALK_LIST(p, proto_list)
 1289:   {
 1290:     if (!p->gr_recovery)
 1291:       continue;
 1292: 
 1293:     struct channel *c;
 1294:     WALK_LIST(c, p->channels)
 1295:     {
 1296:       /* Resume postponed export of routes */
 1297:       if ((c->channel_state == CS_UP) && c->gr_wait && c->proto->rt_notify)
 1298: 	channel_start_export(c);
 1299: 
 1300:       /* Cleanup */
 1301:       c->gr_wait = 0;
 1302:       c->gr_lock = 0;
 1303:     }
 1304: 
 1305:     p->gr_recovery = 0;
 1306:   }
 1307: 
 1308:   graceful_restart_locks = 0;
 1309: }
 1310: 
 1311: void
 1312: graceful_restart_show_status(void)
 1313: {
 1314:   if (graceful_restart_state != GRS_ACTIVE)
 1315:     return;
 1316: 
 1317:   cli_msg(-24, "Graceful restart recovery in progress");
 1318:   cli_msg(-24, "  Waiting for %d channels to recover", graceful_restart_locks);
 1319:   cli_msg(-24, "  Wait timer is %t/%u", tm_remains(gr_wait_timer), config->gr_wait);
 1320: }
 1321: 
 1322: /**
 1323:  * channel_graceful_restart_lock - lock graceful restart by channel
 1324:  * @p: channel instance
 1325:  *
 1326:  * This function allows a protocol to postpone the end of graceful restart
 1327:  * recovery until it converges. The lock is removed when the protocol calls
 1328:  * channel_graceful_restart_unlock() or when the channel is closed.
 1329:  *
 1330:  * The function have to be called during the initial phase of graceful restart
 1331:  * recovery and only for protocols that are part of graceful restart (i.e. their
 1332:  * @gr_recovery is set), which means it should be called from protocol start
 1333:  * hooks.
 1334:  */
 1335: void
 1336: channel_graceful_restart_lock(struct channel *c)
 1337: {
 1338:   ASSERT(graceful_restart_state == GRS_INIT);
 1339:   ASSERT(c->proto->gr_recovery);
 1340: 
 1341:   if (c->gr_lock)
 1342:     return;
 1343: 
 1344:   c->gr_lock = 1;
 1345:   graceful_restart_locks++;
 1346: }
 1347: 
 1348: /**
 1349:  * channel_graceful_restart_unlock - unlock graceful restart by channel
 1350:  * @p: channel instance
 1351:  *
 1352:  * This function unlocks a lock from channel_graceful_restart_lock(). It is also
 1353:  * automatically called when the lock holding protocol went down.
 1354:  */
 1355: void
 1356: channel_graceful_restart_unlock(struct channel *c)
 1357: {
 1358:   if (!c->gr_lock)
 1359:     return;
 1360: 
 1361:   c->gr_lock = 0;
 1362:   graceful_restart_locks--;
 1363: 
 1364:   if ((graceful_restart_state == GRS_ACTIVE) && !graceful_restart_locks)
 1365:     tm_start(gr_wait_timer, 0);
 1366: }
 1367: 
 1368: 
 1369: 
 1370: /**
 1371:  * protos_dump_all - dump status of all protocols
 1372:  *
 1373:  * This function dumps status of all existing protocol instances to the
 1374:  * debug output. It involves printing of general status information
 1375:  * such as protocol states, its position on the protocol lists
 1376:  * and also calling of a dump() hook of the protocol to print
 1377:  * the internals.
 1378:  */
 1379: void
 1380: protos_dump_all(void)
 1381: {
 1382:   debug("Protocols:\n");
 1383: 
 1384:   struct proto *p;
 1385:   WALK_LIST(p, proto_list)
 1386:   {
 1387:     debug("  protocol %s state %s\n", p->name, p_states[p->proto_state]);
 1388: 
 1389:     struct channel *c;
 1390:     WALK_LIST(c, p->channels)
 1391:     {
 1392:       debug("\tTABLE %s\n", c->table->name);
 1393:       if (c->in_filter)
 1394: 	debug("\tInput filter: %s\n", filter_name(c->in_filter));
 1395:       if (c->out_filter)
 1396: 	debug("\tOutput filter: %s\n", filter_name(c->out_filter));
 1397:     }
 1398: 
 1399:     if (p->proto->dump && (p->proto_state != PS_DOWN))
 1400:       p->proto->dump(p);
 1401:   }
 1402: }
 1403: 
 1404: /**
 1405:  * proto_build - make a single protocol available
 1406:  * @p: the protocol
 1407:  *
 1408:  * After the platform specific initialization code uses protos_build()
 1409:  * to add all the standard protocols, it should call proto_build() for
 1410:  * all platform specific protocols to inform the core that they exist.
 1411:  */
 1412: void
 1413: proto_build(struct protocol *p)
 1414: {
 1415:   add_tail(&protocol_list, &p->n);
 1416:   ASSERT(p->class);
 1417:   ASSERT(!class_to_protocol[p->class]);
 1418:   class_to_protocol[p->class] = p;
 1419: }
 1420: 
 1421: /* FIXME: convert this call to some protocol hook */
 1422: extern void bfd_init_all(void);
 1423: 
 1424: /**
 1425:  * protos_build - build a protocol list
 1426:  *
 1427:  * This function is called during BIRD startup to insert
 1428:  * all standard protocols to the global protocol list. Insertion
 1429:  * of platform specific protocols (such as the kernel syncer)
 1430:  * is in the domain of competence of the platform dependent
 1431:  * startup code.
 1432:  */
 1433: void
 1434: protos_build(void)
 1435: {
 1436:   init_list(&proto_list);
 1437:   init_list(&protocol_list);
 1438: 
 1439:   proto_build(&proto_device);
 1440: #ifdef CONFIG_RADV
 1441:   proto_build(&proto_radv);
 1442: #endif
 1443: #ifdef CONFIG_RIP
 1444:   proto_build(&proto_rip);
 1445: #endif
 1446: #ifdef CONFIG_STATIC
 1447:   proto_build(&proto_static);
 1448: #endif
 1449: #ifdef CONFIG_MRT
 1450:   proto_build(&proto_mrt);
 1451: #endif
 1452: #ifdef CONFIG_OSPF
 1453:   proto_build(&proto_ospf);
 1454: #endif
 1455: #ifdef CONFIG_PIPE
 1456:   proto_build(&proto_pipe);
 1457: #endif
 1458: #ifdef CONFIG_BGP
 1459:   proto_build(&proto_bgp);
 1460: #endif
 1461: #ifdef CONFIG_BFD
 1462:   proto_build(&proto_bfd);
 1463:   bfd_init_all();
 1464: #endif
 1465: #ifdef CONFIG_BABEL
 1466:   proto_build(&proto_babel);
 1467: #endif
 1468: #ifdef CONFIG_RPKI
 1469:   proto_build(&proto_rpki);
 1470: #endif
 1471: #ifdef CONFIG_PERF
 1472:   proto_build(&proto_perf);
 1473: #endif
 1474: 
 1475:   proto_pool = rp_new(&root_pool, "Protocols");
 1476:   proto_shutdown_timer = tm_new(proto_pool);
 1477:   proto_shutdown_timer->hook = proto_shutdown_loop;
 1478: }
 1479: 
 1480: 
 1481: /* Temporary hack to propagate restart to BGP */
 1482: int proto_restart;
 1483: 
 1484: static void
 1485: proto_shutdown_loop(timer *t UNUSED)
 1486: {
 1487:   struct proto *p, *p_next;
 1488: 
 1489:   WALK_LIST_DELSAFE(p, p_next, proto_list)
 1490:     if (p->down_sched)
 1491:     {
 1492:       proto_restart = (p->down_sched == PDS_RESTART);
 1493: 
 1494:       p->disabled = 1;
 1495:       proto_rethink_goal(p);
 1496:       if (proto_restart)
 1497:       {
 1498: 	p->disabled = 0;
 1499: 	proto_rethink_goal(p);
 1500:       }
 1501:     }
 1502: }
 1503: 
 1504: static inline void
 1505: proto_schedule_down(struct proto *p, byte restart, byte code)
 1506: {
 1507:   /* Does not work for other states (even PS_START) */
 1508:   ASSERT(p->proto_state == PS_UP);
 1509: 
 1510:   /* Scheduled restart may change to shutdown, but not otherwise */
 1511:   if (p->down_sched == PDS_DISABLE)
 1512:     return;
 1513: 
 1514:   p->down_sched = restart ? PDS_RESTART : PDS_DISABLE;
 1515:   p->down_code = code;
 1516:   tm_start_max(proto_shutdown_timer, restart ? 250 MS : 0);
 1517: }
 1518: 
 1519: /**
 1520:  * proto_set_message - set administrative message to protocol
 1521:  * @p: protocol
 1522:  * @msg: message
 1523:  * @len: message length (-1 for NULL-terminated string)
 1524:  *
 1525:  * The function sets administrative message (string) related to protocol state
 1526:  * change. It is called by the nest code for manual enable/disable/restart
 1527:  * commands all routes to the protocol, and by protocol-specific code when the
 1528:  * protocol state change is initiated by the protocol. Using NULL message clears
 1529:  * the last message. The message string may be either NULL-terminated or with an
 1530:  * explicit length.
 1531:  */
 1532: void
 1533: proto_set_message(struct proto *p, char *msg, int len)
 1534: {
 1535:   mb_free(p->message);
 1536:   p->message = NULL;
 1537: 
 1538:   if (!msg || !len)
 1539:     return;
 1540: 
 1541:   if (len < 0)
 1542:     len = strlen(msg);
 1543: 
 1544:   if (!len)
 1545:     return;
 1546: 
 1547:   p->message = mb_alloc(proto_pool, len + 1);
 1548:   memcpy(p->message, msg, len);
 1549:   p->message[len] = 0;
 1550: }
 1551: 
 1552: 
 1553: static const char *
 1554: channel_limit_name(struct channel_limit *l)
 1555: {
 1556:   const char *actions[] = {
 1557:     [PLA_WARN] = "warn",
 1558:     [PLA_BLOCK] = "block",
 1559:     [PLA_RESTART] = "restart",
 1560:     [PLA_DISABLE] = "disable",
 1561:   };
 1562: 
 1563:   return actions[l->action];
 1564: }
 1565: 
 1566: /**
 1567:  * channel_notify_limit: notify about limit hit and take appropriate action
 1568:  * @c: channel
 1569:  * @l: limit being hit
 1570:  * @dir: limit direction (PLD_*)
 1571:  * @rt_count: the number of routes
 1572:  *
 1573:  * The function is called by the route processing core when limit @l
 1574:  * is breached. It activates the limit and tooks appropriate action
 1575:  * according to @l->action.
 1576:  */
 1577: void
 1578: channel_notify_limit(struct channel *c, struct channel_limit *l, int dir, u32 rt_count)
 1579: {
 1580:   const char *dir_name[PLD_MAX] = { "receive", "import" , "export" };
 1581:   const byte dir_down[PLD_MAX] = { PDC_RX_LIMIT_HIT, PDC_IN_LIMIT_HIT, PDC_OUT_LIMIT_HIT };
 1582:   struct proto *p = c->proto;
 1583: 
 1584:   if (l->state == PLS_BLOCKED)
 1585:     return;
 1586: 
 1587:   /* For warning action, we want the log message every time we hit the limit */
 1588:   if (!l->state || ((l->action == PLA_WARN) && (rt_count == l->limit)))
 1589:     log(L_WARN "Protocol %s hits route %s limit (%d), action: %s",
 1590: 	p->name, dir_name[dir], l->limit, channel_limit_name(l));
 1591: 
 1592:   switch (l->action)
 1593:   {
 1594:   case PLA_WARN:
 1595:     l->state = PLS_ACTIVE;
 1596:     break;
 1597: 
 1598:   case PLA_BLOCK:
 1599:     l->state = PLS_BLOCKED;
 1600:     break;
 1601: 
 1602:   case PLA_RESTART:
 1603:   case PLA_DISABLE:
 1604:     l->state = PLS_BLOCKED;
 1605:     if (p->proto_state == PS_UP)
 1606:       proto_schedule_down(p, l->action == PLA_RESTART, dir_down[dir]);
 1607:     break;
 1608:   }
 1609: }
 1610: 
 1611: static void
 1612: channel_verify_limits(struct channel *c)
 1613: {
 1614:   struct channel_limit *l;
 1615:   u32 all_routes = c->stats.imp_routes + c->stats.filt_routes;
 1616: 
 1617:   l = &c->rx_limit;
 1618:   if (l->action && (all_routes > l->limit))
 1619:     channel_notify_limit(c, l, PLD_RX, all_routes);
 1620: 
 1621:   l = &c->in_limit;
 1622:   if (l->action && (c->stats.imp_routes > l->limit))
 1623:     channel_notify_limit(c, l, PLD_IN, c->stats.imp_routes);
 1624: 
 1625:   l = &c->out_limit;
 1626:   if (l->action && (c->stats.exp_routes > l->limit))
 1627:     channel_notify_limit(c, l, PLD_OUT, c->stats.exp_routes);
 1628: }
 1629: 
 1630: static inline void
 1631: channel_reset_limit(struct channel_limit *l)
 1632: {
 1633:   if (l->action)
 1634:     l->state = PLS_INITIAL;
 1635: }
 1636: 
 1637: static inline void
 1638: proto_do_start(struct proto *p)
 1639: {
 1640:   p->active = 1;
 1641:   p->do_start = 1;
 1642:   ev_schedule(p->event);
 1643: }
 1644: 
 1645: static void
 1646: proto_do_up(struct proto *p)
 1647: {
 1648:   if (!p->main_source)
 1649:   {
 1650:     p->main_source = rt_get_source(p, 0);
 1651:     rt_lock_source(p->main_source);
 1652:   }
 1653: 
 1654:   proto_start_channels(p);
 1655: }
 1656: 
 1657: static inline void
 1658: proto_do_pause(struct proto *p)
 1659: {
 1660:   proto_pause_channels(p);
 1661: }
 1662: 
 1663: static void
 1664: proto_do_stop(struct proto *p)
 1665: {
 1666:   p->down_sched = 0;
 1667:   p->gr_recovery = 0;
 1668: 
 1669:   p->do_stop = 1;
 1670:   ev_schedule(p->event);
 1671: 
 1672:   if (p->main_source)
 1673:   {
 1674:     rt_unlock_source(p->main_source);
 1675:     p->main_source = NULL;
 1676:   }
 1677: 
 1678:   proto_stop_channels(p);
 1679: }
 1680: 
 1681: static void
 1682: proto_do_down(struct proto *p)
 1683: {
 1684:   p->down_code = 0;
 1685:   neigh_prune();
 1686:   rfree(p->pool);
 1687:   p->pool = NULL;
 1688: 
 1689:   /* Shutdown is finished in the protocol event */
 1690:   if (proto_is_done(p))
 1691:     ev_schedule(p->event);
 1692: }
 1693: 
 1694: 
 1695: 
 1696: /**
 1697:  * proto_notify_state - notify core about protocol state change
 1698:  * @p: protocol the state of which has changed
 1699:  * @ps: the new status
 1700:  *
 1701:  * Whenever a state of a protocol changes due to some event internal
 1702:  * to the protocol (i.e., not inside a start() or shutdown() hook),
 1703:  * it should immediately notify the core about the change by calling
 1704:  * proto_notify_state() which will write the new state to the &proto
 1705:  * structure and take all the actions necessary to adapt to the new
 1706:  * state. State change to PS_DOWN immediately frees resources of protocol
 1707:  * and might execute start callback of protocol; therefore,
 1708:  * it should be used at tail positions of protocol callbacks.
 1709:  */
 1710: void
 1711: proto_notify_state(struct proto *p, uint state)
 1712: {
 1713:   uint ps = p->proto_state;
 1714: 
 1715:   DBG("%s reporting state transition %s -> %s\n", p->name, p_states[ps], p_states[state]);
 1716:   if (state == ps)
 1717:     return;
 1718: 
 1719:   p->proto_state = state;
 1720:   p->last_state_change = current_time();
 1721: 
 1722:   switch (state)
 1723:   {
 1724:   case PS_START:
 1725:     ASSERT(ps == PS_DOWN || ps == PS_UP);
 1726: 
 1727:     if (ps == PS_DOWN)
 1728:       proto_do_start(p);
 1729:     else
 1730:       proto_do_pause(p);
 1731:     break;
 1732: 
 1733:   case PS_UP:
 1734:     ASSERT(ps == PS_DOWN || ps == PS_START);
 1735: 
 1736:     if (ps == PS_DOWN)
 1737:       proto_do_start(p);
 1738: 
 1739:     proto_do_up(p);
 1740:     break;
 1741: 
 1742:   case PS_STOP:
 1743:     ASSERT(ps == PS_START || ps == PS_UP);
 1744: 
 1745:     proto_do_stop(p);
 1746:     break;
 1747: 
 1748:   case PS_DOWN:
 1749:     if (ps != PS_STOP)
 1750:       proto_do_stop(p);
 1751: 
 1752:     proto_do_down(p);
 1753:     break;
 1754: 
 1755:   default:
 1756:     bug("%s: Invalid state %d", p->name, ps);
 1757:   }
 1758: 
 1759:   proto_log_state_change(p);
 1760: }
 1761: 
 1762: /*
 1763:  *  CLI Commands
 1764:  */
 1765: 
 1766: static char *
 1767: proto_state_name(struct proto *p)
 1768: {
 1769:   switch (p->proto_state)
 1770:   {
 1771:   case PS_DOWN:		return p->active ? "flush" : "down";
 1772:   case PS_START:	return "start";
 1773:   case PS_UP:		return "up";
 1774:   case PS_STOP:		return "stop";
 1775:   default:		return "???";
 1776:   }
 1777: }
 1778: 
 1779: static void
 1780: channel_show_stats(struct channel *c)
 1781: {
 1782:   struct proto_stats *s = &c->stats;
 1783: 
 1784:   if (c->in_keep_filtered)
 1785:     cli_msg(-1006, "    Routes:         %u imported, %u filtered, %u exported, %u preferred",
 1786: 	    s->imp_routes, s->filt_routes, s->exp_routes, s->pref_routes);
 1787:   else
 1788:     cli_msg(-1006, "    Routes:         %u imported, %u exported, %u preferred",
 1789: 	    s->imp_routes, s->exp_routes, s->pref_routes);
 1790: 
 1791:   cli_msg(-1006, "    Route change stats:     received   rejected   filtered    ignored   accepted");
 1792:   cli_msg(-1006, "      Import updates:     %10u %10u %10u %10u %10u",
 1793: 	  s->imp_updates_received, s->imp_updates_invalid,
 1794: 	  s->imp_updates_filtered, s->imp_updates_ignored,
 1795: 	  s->imp_updates_accepted);
 1796:   cli_msg(-1006, "      Import withdraws:   %10u %10u        --- %10u %10u",
 1797: 	  s->imp_withdraws_received, s->imp_withdraws_invalid,
 1798: 	  s->imp_withdraws_ignored, s->imp_withdraws_accepted);
 1799:   cli_msg(-1006, "      Export updates:     %10u %10u %10u        --- %10u",
 1800: 	  s->exp_updates_received, s->exp_updates_rejected,
 1801: 	  s->exp_updates_filtered, s->exp_updates_accepted);
 1802:   cli_msg(-1006, "      Export withdraws:   %10u        ---        ---        --- %10u",
 1803: 	  s->exp_withdraws_received, s->exp_withdraws_accepted);
 1804: }
 1805: 
 1806: void
 1807: channel_show_limit(struct channel_limit *l, const char *dsc)
 1808: {
 1809:   if (!l->action)
 1810:     return;
 1811: 
 1812:   cli_msg(-1006, "    %-16s%d%s", dsc, l->limit, l->state ? " [HIT]" : "");
 1813:   cli_msg(-1006, "      Action:       %s", channel_limit_name(l));
 1814: }
 1815: 
 1816: void
 1817: channel_show_info(struct channel *c)
 1818: {
 1819:   cli_msg(-1006, "  Channel %s", c->name);
 1820:   cli_msg(-1006, "    State:          %s", c_states[c->channel_state]);
 1821:   cli_msg(-1006, "    Table:          %s", c->table->name);
 1822:   cli_msg(-1006, "    Preference:     %d", c->preference);
 1823:   cli_msg(-1006, "    Input filter:   %s", filter_name(c->in_filter));
 1824:   cli_msg(-1006, "    Output filter:  %s", filter_name(c->out_filter));
 1825: 
 1826:   if (graceful_restart_state == GRS_ACTIVE)
 1827:     cli_msg(-1006, "    GR recovery:   %s%s",
 1828: 	    c->gr_lock ? " pending" : "",
 1829: 	    c->gr_wait ? " waiting" : "");
 1830: 
 1831:   channel_show_limit(&c->rx_limit, "Receive limit:");
 1832:   channel_show_limit(&c->in_limit, "Import limit:");
 1833:   channel_show_limit(&c->out_limit, "Export limit:");
 1834: 
 1835:   if (c->channel_state != CS_DOWN)
 1836:     channel_show_stats(c);
 1837: }
 1838: 
 1839: void
 1840: proto_cmd_show(struct proto *p, uintptr_t verbose, int cnt)
 1841: {
 1842:   byte buf[256], tbuf[TM_DATETIME_BUFFER_SIZE];
 1843: 
 1844:   /* First protocol - show header */
 1845:   if (!cnt)
 1846:     cli_msg(-2002, "%-10s %-10s %-10s %-6s %-12s  %s",
 1847: 	    "Name", "Proto", "Table", "State", "Since", "Info");
 1848: 
 1849:   buf[0] = 0;
 1850:   if (p->proto->get_status)
 1851:     p->proto->get_status(p, buf);
 1852:   tm_format_time(tbuf, &config->tf_proto, p->last_state_change);
 1853:   cli_msg(-1002, "%-10s %-10s %-10s %-6s %-12s  %s",
 1854: 	  p->name,
 1855: 	  p->proto->name,
 1856: 	  p->main_channel ? p->main_channel->table->name : "---",
 1857: 	  proto_state_name(p),
 1858: 	  tbuf,
 1859: 	  buf);
 1860: 
 1861:   if (verbose)
 1862:   {
 1863:     if (p->cf->dsc)
 1864:       cli_msg(-1006, "  Description:    %s", p->cf->dsc);
 1865:     if (p->message)
 1866:       cli_msg(-1006, "  Message:        %s", p->message);
 1867:     if (p->cf->router_id)
 1868:       cli_msg(-1006, "  Router ID:      %R", p->cf->router_id);
 1869:     if (p->vrf_set)
 1870:       cli_msg(-1006, "  VRF:            %s", p->vrf ? p->vrf->name : "default");
 1871: 
 1872:     if (p->proto->show_proto_info)
 1873:       p->proto->show_proto_info(p);
 1874:     else
 1875:     {
 1876:       struct channel *c;
 1877:       WALK_LIST(c, p->channels)
 1878: 	channel_show_info(c);
 1879:     }
 1880: 
 1881:     cli_msg(-1006, "");
 1882:   }
 1883: }
 1884: 
 1885: void
 1886: proto_cmd_disable(struct proto *p, uintptr_t arg, int cnt UNUSED)
 1887: {
 1888:   if (p->disabled)
 1889:   {
 1890:     cli_msg(-8, "%s: already disabled", p->name);
 1891:     return;
 1892:   }
 1893: 
 1894:   log(L_INFO "Disabling protocol %s", p->name);
 1895:   p->disabled = 1;
 1896:   p->down_code = PDC_CMD_DISABLE;
 1897:   proto_set_message(p, (char *) arg, -1);
 1898:   proto_rethink_goal(p);
 1899:   cli_msg(-9, "%s: disabled", p->name);
 1900: }
 1901: 
 1902: void
 1903: proto_cmd_enable(struct proto *p, uintptr_t arg, int cnt UNUSED)
 1904: {
 1905:   if (!p->disabled)
 1906:   {
 1907:     cli_msg(-10, "%s: already enabled", p->name);
 1908:     return;
 1909:   }
 1910: 
 1911:   log(L_INFO "Enabling protocol %s", p->name);
 1912:   p->disabled = 0;
 1913:   proto_set_message(p, (char *) arg, -1);
 1914:   proto_rethink_goal(p);
 1915:   cli_msg(-11, "%s: enabled", p->name);
 1916: }
 1917: 
 1918: void
 1919: proto_cmd_restart(struct proto *p, uintptr_t arg, int cnt UNUSED)
 1920: {
 1921:   if (p->disabled)
 1922:   {
 1923:     cli_msg(-8, "%s: already disabled", p->name);
 1924:     return;
 1925:   }
 1926: 
 1927:   log(L_INFO "Restarting protocol %s", p->name);
 1928:   p->disabled = 1;
 1929:   p->down_code = PDC_CMD_RESTART;
 1930:   proto_set_message(p, (char *) arg, -1);
 1931:   proto_rethink_goal(p);
 1932:   p->disabled = 0;
 1933:   proto_rethink_goal(p);
 1934:   cli_msg(-12, "%s: restarted", p->name);
 1935: }
 1936: 
 1937: void
 1938: proto_cmd_reload(struct proto *p, uintptr_t dir, int cnt UNUSED)
 1939: {
 1940:   struct channel *c;
 1941: 
 1942:   if (p->disabled)
 1943:   {
 1944:     cli_msg(-8, "%s: already disabled", p->name);
 1945:     return;
 1946:   }
 1947: 
 1948:   /* If the protocol in not UP, it has no routes */
 1949:   if (p->proto_state != PS_UP)
 1950:     return;
 1951: 
 1952:   /* All channels must support reload */
 1953:   if (dir != CMD_RELOAD_OUT)
 1954:     WALK_LIST(c, p->channels)
 1955:       if ((c->channel_state == CS_UP) && !channel_reloadable(c))
 1956:       {
 1957: 	cli_msg(-8006, "%s: reload failed", p->name);
 1958: 	return;
 1959:       }
 1960: 
 1961:   log(L_INFO "Reloading protocol %s", p->name);
 1962: 
 1963:   /* re-importing routes */
 1964:   if (dir != CMD_RELOAD_OUT)
 1965:     WALK_LIST(c, p->channels)
 1966:       if (c->channel_state == CS_UP)
 1967: 	channel_request_reload(c);
 1968: 
 1969:   /* re-exporting routes */
 1970:   if (dir != CMD_RELOAD_IN)
 1971:     WALK_LIST(c, p->channels)
 1972:       if (c->channel_state == CS_UP)
 1973: 	channel_request_feeding(c);
 1974: 
 1975:   cli_msg(-15, "%s: reloading", p->name);
 1976: }
 1977: 
 1978: void
 1979: proto_cmd_debug(struct proto *p, uintptr_t mask, int cnt UNUSED)
 1980: {
 1981:   p->debug = mask;
 1982: }
 1983: 
 1984: void
 1985: proto_cmd_mrtdump(struct proto *p, uintptr_t mask, int cnt UNUSED)
 1986: {
 1987:   p->mrtdump = mask;
 1988: }
 1989: 
 1990: static void
 1991: proto_apply_cmd_symbol(struct symbol *s, void (* cmd)(struct proto *, uintptr_t, int), uintptr_t arg)
 1992: {
 1993:   if (s->class != SYM_PROTO)
 1994:   {
 1995:     cli_msg(9002, "%s is not a protocol", s->name);
 1996:     return;
 1997:   }
 1998: 
 1999:   cmd(s->proto->proto, arg, 0);
 2000:   cli_msg(0, "");
 2001: }
 2002: 
 2003: static void
 2004: proto_apply_cmd_patt(char *patt, void (* cmd)(struct proto *, uintptr_t, int), uintptr_t arg)
 2005: {
 2006:   struct proto *p;
 2007:   int cnt = 0;
 2008: 
 2009:   WALK_LIST(p, proto_list)
 2010:     if (!patt || patmatch(patt, p->name))
 2011:       cmd(p, arg, cnt++);
 2012: 
 2013:   if (!cnt)
 2014:     cli_msg(8003, "No protocols match");
 2015:   else
 2016:     cli_msg(0, "");
 2017: }
 2018: 
 2019: void
 2020: proto_apply_cmd(struct proto_spec ps, void (* cmd)(struct proto *, uintptr_t, int),
 2021: 		int restricted, uintptr_t arg)
 2022: {
 2023:   if (restricted && cli_access_restricted())
 2024:     return;
 2025: 
 2026:   if (ps.patt)
 2027:     proto_apply_cmd_patt(ps.ptr, cmd, arg);
 2028:   else
 2029:     proto_apply_cmd_symbol(ps.ptr, cmd, arg);
 2030: }
 2031: 
 2032: struct proto *
 2033: proto_get_named(struct symbol *sym, struct protocol *pr)
 2034: {
 2035:   struct proto *p, *q;
 2036: 
 2037:   if (sym)
 2038:   {
 2039:     if (sym->class != SYM_PROTO)
 2040:       cf_error("%s: Not a protocol", sym->name);
 2041: 
 2042:     p = sym->proto->proto;
 2043:     if (!p || p->proto != pr)
 2044:       cf_error("%s: Not a %s protocol", sym->name, pr->name);
 2045:   }
 2046:   else
 2047:   {
 2048:     p = NULL;
 2049:     WALK_LIST(q, proto_list)
 2050:       if ((q->proto == pr) && (q->proto_state != PS_DOWN))
 2051:       {
 2052: 	if (p)
 2053: 	  cf_error("There are multiple %s protocols running", pr->name);
 2054: 	p = q;
 2055:       }
 2056:     if (!p)
 2057:       cf_error("There is no %s protocol running", pr->name);
 2058:   }
 2059: 
 2060:   return p;
 2061: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>