File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / bird / nest / proto.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Aug 22 12:33:54 2017 UTC (6 years, 10 months ago) by misho
Branches: bird, MAIN
CVS tags: v1_6_3p0, v1_6_3, HEAD
bird 1.6.3

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

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