File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / bird / nest / proto.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 19:50:23 2021 UTC (3 years, 3 months ago) by misho
Branches: bird, MAIN
CVS tags: v1_6_8p3, HEAD
bird 1.6.8

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

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