Annotation of embedaddon/bird2/proto/babel/babel.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  *     BIRD -- The Babel protocol
        !             3:  *
        !             4:  *     Copyright (c) 2015--2016 Toke Hoiland-Jorgensen
        !             5:  *     (c) 2016--2017 Ondrej Zajicek <santiago@crfreenet.org>
        !             6:  *     (c) 2016--2017 CZ.NIC z.s.p.o.
        !             7:  *
        !             8:  *     Can be freely distributed and used under the terms of the GNU GPL.
        !             9:  *
        !            10:  *     This file contains the main routines for handling and sending TLVs, as
        !            11:  *     well as timers and interaction with the nest.
        !            12:  */
        !            13: 
        !            14: /**
        !            15:  * DOC: The Babel protocol
        !            16:  *
        !            17:  * Babel (RFC6126) is a loop-avoiding distance-vector routing protocol that is
        !            18:  * robust and efficient both in ordinary wired networks and in wireless mesh
        !            19:  * networks.
        !            20:  *
        !            21:  * The Babel protocol keeps state for each neighbour in a &babel_neighbor
        !            22:  * struct, tracking received Hello and I Heard You (IHU) messages. A
        !            23:  * &babel_interface struct keeps hello and update times for each interface, and
        !            24:  * a separate hello seqno is maintained for each interface.
        !            25:  *
        !            26:  * For each prefix, Babel keeps track of both the possible routes (with next hop
        !            27:  * and router IDs), as well as the feasibility distance for each prefix and
        !            28:  * router id. The prefix itself is tracked in a &babel_entry struct, while the
        !            29:  * possible routes for the prefix are tracked as &babel_route entries and the
        !            30:  * feasibility distance is maintained through &babel_source structures.
        !            31:  *
        !            32:  * The main route selection is done in babel_select_route(). This is called when
        !            33:  * an entry is updated by receiving updates from the network or when modified by
        !            34:  * internal timers. The function selects from feasible and reachable routes the
        !            35:  * one with the lowest metric to be announced to the core.
        !            36:  */
        !            37: 
        !            38: #include <stdlib.h>
        !            39: #include "babel.h"
        !            40: 
        !            41: 
        !            42: /*
        !            43:  * Is one number greater or equal than another mod 2^16? This is based on the
        !            44:  * definition of serial number space in RFC 1982. Note that arguments are of
        !            45:  * uint type to avoid integer promotion to signed integer.
        !            46:  */
        !            47: static inline int ge_mod64k(uint a, uint b)
        !            48: { return (u16)(a - b) < 0x8000; }
        !            49: 
        !            50: static void babel_expire_requests(struct babel_proto *p, struct babel_entry *e);
        !            51: static void babel_select_route(struct babel_proto *p, struct babel_entry *e, struct babel_route *mod);
        !            52: static inline void babel_announce_retraction(struct babel_proto *p, struct babel_entry *e);
        !            53: static void babel_send_route_request(struct babel_proto *p, struct babel_entry *e, struct babel_neighbor *n);
        !            54: static void babel_send_seqno_request(struct babel_proto *p, struct babel_entry *e, struct babel_seqno_request *sr);
        !            55: static void babel_update_cost(struct babel_neighbor *n);
        !            56: static inline void babel_kick_timer(struct babel_proto *p);
        !            57: static inline void babel_iface_kick_timer(struct babel_iface *ifa);
        !            58: 
        !            59: static inline void babel_lock_neighbor(struct babel_neighbor *nbr)
        !            60: { if (nbr) nbr->uc++; }
        !            61: 
        !            62: static inline void babel_unlock_neighbor(struct babel_neighbor *nbr)
        !            63: { if (nbr && !--nbr->uc) mb_free(nbr); }
        !            64: 
        !            65: 
        !            66: /*
        !            67:  *     Functions to maintain data structures
        !            68:  */
        !            69: 
        !            70: static void
        !            71: babel_init_entry(void *E)
        !            72: {
        !            73:   struct babel_entry *e = E;
        !            74: 
        !            75:   e->updated = current_time();
        !            76:   init_list(&e->requests);
        !            77:   init_list(&e->sources);
        !            78:   init_list(&e->routes);
        !            79: }
        !            80: 
        !            81: static inline struct babel_entry *
        !            82: babel_find_entry(struct babel_proto *p, const net_addr *n)
        !            83: {
        !            84:   struct fib *rtable = (n->type == NET_IP4) ? &p->ip4_rtable : &p->ip6_rtable;
        !            85:   return fib_find(rtable, n);
        !            86: }
        !            87: 
        !            88: static struct babel_entry *
        !            89: babel_get_entry(struct babel_proto *p, const net_addr *n)
        !            90: {
        !            91:   struct fib *rtable = (n->type == NET_IP4) ? &p->ip4_rtable : &p->ip6_rtable;
        !            92:   struct babel_entry *e = fib_get(rtable, n);
        !            93:   return e;
        !            94: }
        !            95: 
        !            96: static struct babel_source *
        !            97: babel_find_source(struct babel_entry *e, u64 router_id)
        !            98: {
        !            99:   struct babel_source *s;
        !           100: 
        !           101:   WALK_LIST(s, e->sources)
        !           102:     if (s->router_id == router_id)
        !           103:       return s;
        !           104: 
        !           105:   return NULL;
        !           106: }
        !           107: 
        !           108: static struct babel_source *
        !           109: babel_get_source(struct babel_proto *p, struct babel_entry *e, u64 router_id)
        !           110: {
        !           111:   struct babel_source *s = babel_find_source(e, router_id);
        !           112: 
        !           113:   if (s)
        !           114:     return s;
        !           115: 
        !           116:   s = sl_alloc(p->source_slab);
        !           117:   s->router_id = router_id;
        !           118:   s->expires = current_time() + BABEL_GARBAGE_INTERVAL;
        !           119:   s->seqno = 0;
        !           120:   s->metric = BABEL_INFINITY;
        !           121:   add_tail(&e->sources, NODE s);
        !           122: 
        !           123:   return s;
        !           124: }
        !           125: 
        !           126: static void
        !           127: babel_expire_sources(struct babel_proto *p, struct babel_entry *e)
        !           128: {
        !           129:   struct babel_source *n, *nx;
        !           130:   btime now_ = current_time();
        !           131: 
        !           132:   WALK_LIST_DELSAFE(n, nx, e->sources)
        !           133:   {
        !           134:     if (n->expires && n->expires <= now_)
        !           135:     {
        !           136:       rem_node(NODE n);
        !           137:       sl_free(p->source_slab, n);
        !           138:     }
        !           139:   }
        !           140: }
        !           141: 
        !           142: static struct babel_route *
        !           143: babel_find_route(struct babel_entry *e, struct babel_neighbor *n)
        !           144: {
        !           145:   struct babel_route *r;
        !           146: 
        !           147:   WALK_LIST(r, e->routes)
        !           148:     if (r->neigh == n)
        !           149:       return r;
        !           150: 
        !           151:   return NULL;
        !           152: }
        !           153: 
        !           154: static struct babel_route *
        !           155: babel_get_route(struct babel_proto *p, struct babel_entry *e, struct babel_neighbor *nbr)
        !           156: {
        !           157:   struct babel_route *r = babel_find_route(e, nbr);
        !           158: 
        !           159:   if (r)
        !           160:     return r;
        !           161: 
        !           162:   r = sl_alloc(p->route_slab);
        !           163:   memset(r, 0, sizeof(*r));
        !           164: 
        !           165:   r->e = e;
        !           166:   r->neigh = nbr;
        !           167:   add_tail(&e->routes, NODE r);
        !           168:   add_tail(&nbr->routes, NODE &r->neigh_route);
        !           169: 
        !           170:   return r;
        !           171: }
        !           172: 
        !           173: static inline void
        !           174: babel_retract_route(struct babel_proto *p, struct babel_route *r)
        !           175: {
        !           176:   r->metric = r->advert_metric = BABEL_INFINITY;
        !           177: 
        !           178:   if (r == r->e->selected)
        !           179:     babel_select_route(p, r->e, r);
        !           180: }
        !           181: 
        !           182: static void
        !           183: babel_flush_route(struct babel_proto *p, struct babel_route *r)
        !           184: {
        !           185:   DBG("Babel: Flush route %N router_id %lR neigh %I\n",
        !           186:       r->e->n.addr, r->router_id, r->neigh->addr);
        !           187: 
        !           188:   rem_node(NODE r);
        !           189:   rem_node(&r->neigh_route);
        !           190: 
        !           191:   if (r->e->selected == r)
        !           192:     r->e->selected = NULL;
        !           193: 
        !           194:   sl_free(p->route_slab, r);
        !           195: }
        !           196: 
        !           197: static void
        !           198: babel_expire_route(struct babel_proto *p, struct babel_route *r)
        !           199: {
        !           200:   struct babel_config *cf = (void *) p->p.cf;
        !           201: 
        !           202:   TRACE(D_EVENTS, "Route expiry timer for %N router-id %lR fired",
        !           203:        r->e->n.addr, r->router_id);
        !           204: 
        !           205:   if (r->metric < BABEL_INFINITY)
        !           206:   {
        !           207:     r->metric = r->advert_metric = BABEL_INFINITY;
        !           208:     r->expires = current_time() + cf->hold_time;
        !           209:   }
        !           210:   else
        !           211:   {
        !           212:     babel_flush_route(p, r);
        !           213:   }
        !           214: }
        !           215: 
        !           216: static void
        !           217: babel_refresh_route(struct babel_proto *p, struct babel_route *r)
        !           218: {
        !           219:   if (r == r->e->selected)
        !           220:     babel_send_route_request(p, r->e, r->neigh);
        !           221: 
        !           222:   r->refresh_time = 0;
        !           223: }
        !           224: 
        !           225: static void
        !           226: babel_expire_routes_(struct babel_proto *p, struct fib *rtable)
        !           227: {
        !           228:   struct babel_config *cf = (void *) p->p.cf;
        !           229:   struct babel_route *r, *rx;
        !           230:   struct fib_iterator fit;
        !           231:   btime now_ = current_time();
        !           232: 
        !           233:   FIB_ITERATE_INIT(&fit, rtable);
        !           234: 
        !           235: loop:
        !           236:   FIB_ITERATE_START(rtable, &fit, struct babel_entry, e)
        !           237:   {
        !           238:     int changed = 0;
        !           239: 
        !           240:     WALK_LIST_DELSAFE(r, rx, e->routes)
        !           241:     {
        !           242:       if (r->refresh_time && r->refresh_time <= now_)
        !           243:        babel_refresh_route(p, r);
        !           244: 
        !           245:       if (r->expires && r->expires <= now_)
        !           246:       {
        !           247:        changed = changed || (r == e->selected);
        !           248:        babel_expire_route(p, r);
        !           249:       }
        !           250:     }
        !           251: 
        !           252:     if (changed)
        !           253:     {
        !           254:       /*
        !           255:        * We have to restart the iteration because there may be a cascade of
        !           256:        * synchronous events babel_select_route() -> nest table change ->
        !           257:        * babel_rt_notify() -> rtable change, invalidating hidden variables.
        !           258:        */
        !           259:       FIB_ITERATE_PUT(&fit);
        !           260:       babel_select_route(p, e, NULL);
        !           261:       goto loop;
        !           262:     }
        !           263: 
        !           264:     /* Clean up stale entries */
        !           265:     if ((e->valid == BABEL_ENTRY_STALE) && ((e->updated + cf->hold_time) <= now_))
        !           266:       e->valid = BABEL_ENTRY_DUMMY;
        !           267: 
        !           268:     /* Clean up unreachable route */
        !           269:     if (e->unreachable && (!e->valid || (e->router_id == p->router_id)))
        !           270:     {
        !           271:       FIB_ITERATE_PUT(&fit);
        !           272:       babel_announce_retraction(p, e);
        !           273:       goto loop;
        !           274:     }
        !           275: 
        !           276:     babel_expire_sources(p, e);
        !           277:     babel_expire_requests(p, e);
        !           278: 
        !           279:     /* Remove empty entries */
        !           280:     if (!e->valid && EMPTY_LIST(e->routes) && EMPTY_LIST(e->sources) && EMPTY_LIST(e->requests))
        !           281:     {
        !           282:       FIB_ITERATE_PUT(&fit);
        !           283:       fib_delete(rtable, e);
        !           284:       goto loop;
        !           285:     }
        !           286:   }
        !           287:   FIB_ITERATE_END;
        !           288: }
        !           289: 
        !           290: static void
        !           291: babel_expire_routes(struct babel_proto *p)
        !           292: {
        !           293:   babel_expire_routes_(p, &p->ip4_rtable);
        !           294:   babel_expire_routes_(p, &p->ip6_rtable);
        !           295: }
        !           296: 
        !           297: static inline int seqno_request_valid(struct babel_seqno_request *sr)
        !           298: { return !sr->nbr || sr->nbr->ifa; }
        !           299: 
        !           300: /*
        !           301:  * Add seqno request to the table of pending requests (RFC 6216 3.2.6) and send
        !           302:  * it to network. Do nothing if it is already in the table.
        !           303:  */
        !           304: 
        !           305: static void
        !           306: babel_add_seqno_request(struct babel_proto *p, struct babel_entry *e,
        !           307:                        u64 router_id, u16 seqno, u8 hop_count,
        !           308:                        struct babel_neighbor *nbr)
        !           309: {
        !           310:   struct babel_seqno_request *sr;
        !           311: 
        !           312:   WALK_LIST(sr, e->requests)
        !           313:     if (sr->router_id == router_id)
        !           314:     {
        !           315:       /* Found matching or newer */
        !           316:       if (ge_mod64k(sr->seqno, seqno) && seqno_request_valid(sr))
        !           317:        return;
        !           318: 
        !           319:       /* Found older */
        !           320:       babel_unlock_neighbor(sr->nbr);
        !           321:       rem_node(NODE sr);
        !           322:       goto found;
        !           323:     }
        !           324: 
        !           325:   /* No entries found */
        !           326:   sr = sl_alloc(p->seqno_slab);
        !           327: 
        !           328: found:
        !           329:   sr->router_id = router_id;
        !           330:   sr->seqno = seqno;
        !           331:   sr->hop_count = hop_count;
        !           332:   sr->count = 0;
        !           333:   sr->expires = current_time() + BABEL_SEQNO_REQUEST_EXPIRY;
        !           334:   babel_lock_neighbor(sr->nbr = nbr);
        !           335:   add_tail(&e->requests, NODE sr);
        !           336: 
        !           337:   babel_send_seqno_request(p, e, sr);
        !           338: }
        !           339: 
        !           340: static void
        !           341: babel_remove_seqno_request(struct babel_proto *p, struct babel_seqno_request *sr)
        !           342: {
        !           343:   babel_unlock_neighbor(sr->nbr);
        !           344:   rem_node(NODE sr);
        !           345:   sl_free(p->seqno_slab, sr);
        !           346: }
        !           347: 
        !           348: static int
        !           349: babel_satisfy_seqno_request(struct babel_proto *p, struct babel_entry *e,
        !           350:                           u64 router_id, u16 seqno)
        !           351: {
        !           352:   struct babel_seqno_request *sr;
        !           353: 
        !           354:   WALK_LIST(sr, e->requests)
        !           355:     if ((sr->router_id == router_id) && ge_mod64k(seqno, sr->seqno))
        !           356:     {
        !           357:       /* Found the request, remove it */
        !           358:       babel_remove_seqno_request(p, sr);
        !           359:       return 1;
        !           360:     }
        !           361: 
        !           362:   return 0;
        !           363: }
        !           364: 
        !           365: static void
        !           366: babel_expire_requests(struct babel_proto *p, struct babel_entry *e)
        !           367: {
        !           368:   struct babel_seqno_request *sr, *srx;
        !           369:   btime now_ = current_time();
        !           370: 
        !           371:   WALK_LIST_DELSAFE(sr, srx, e->requests)
        !           372:   {
        !           373:     /* Remove seqno requests sent to dead neighbors */
        !           374:     if (!seqno_request_valid(sr))
        !           375:     {
        !           376:       babel_remove_seqno_request(p, sr);
        !           377:       continue;
        !           378:     }
        !           379: 
        !           380:     /* Handle expired requests - resend or remove */
        !           381:     if (sr->expires && sr->expires <= now_)
        !           382:     {
        !           383:       if (sr->count < BABEL_SEQNO_REQUEST_RETRY)
        !           384:       {
        !           385:        sr->count++;
        !           386:        sr->expires += (BABEL_SEQNO_REQUEST_EXPIRY << sr->count);
        !           387:        babel_send_seqno_request(p, e, sr);
        !           388:       }
        !           389:       else
        !           390:       {
        !           391:        TRACE(D_EVENTS, "Seqno request for %N router-id %lR expired",
        !           392:              e->n.addr, sr->router_id);
        !           393: 
        !           394:        babel_remove_seqno_request(p, sr);
        !           395:        continue;
        !           396:       }
        !           397:     }
        !           398:   }
        !           399: }
        !           400: 
        !           401: static struct babel_neighbor *
        !           402: babel_find_neighbor(struct babel_iface *ifa, ip_addr addr)
        !           403: {
        !           404:   struct babel_neighbor *nbr;
        !           405: 
        !           406:   WALK_LIST(nbr, ifa->neigh_list)
        !           407:     if (ipa_equal(nbr->addr, addr))
        !           408:       return nbr;
        !           409: 
        !           410:   return NULL;
        !           411: }
        !           412: 
        !           413: static struct babel_neighbor *
        !           414: babel_get_neighbor(struct babel_iface *ifa, ip_addr addr)
        !           415: {
        !           416:   struct babel_proto *p = ifa->proto;
        !           417:   struct babel_neighbor *nbr = babel_find_neighbor(ifa, addr);
        !           418: 
        !           419:   if (nbr)
        !           420:     return nbr;
        !           421: 
        !           422:   TRACE(D_EVENTS, "New neighbor %I on %s", addr, ifa->iface->name);
        !           423: 
        !           424:   nbr = mb_allocz(ifa->pool, sizeof(struct babel_neighbor));
        !           425:   nbr->ifa = ifa;
        !           426:   nbr->addr = addr;
        !           427:   nbr->rxcost = BABEL_INFINITY;
        !           428:   nbr->txcost = BABEL_INFINITY;
        !           429:   nbr->cost = BABEL_INFINITY;
        !           430:   init_list(&nbr->routes);
        !           431:   babel_lock_neighbor(nbr);
        !           432:   add_tail(&ifa->neigh_list, NODE nbr);
        !           433: 
        !           434:   return nbr;
        !           435: }
        !           436: 
        !           437: static void
        !           438: babel_flush_neighbor(struct babel_proto *p, struct babel_neighbor *nbr)
        !           439: {
        !           440:   struct babel_route *r;
        !           441:   node *n;
        !           442: 
        !           443:   TRACE(D_EVENTS, "Removing neighbor %I on %s", nbr->addr, nbr->ifa->iface->name);
        !           444: 
        !           445:   WALK_LIST_FIRST(n, nbr->routes)
        !           446:   {
        !           447:     r = SKIP_BACK(struct babel_route, neigh_route, n);
        !           448:     babel_retract_route(p, r);
        !           449:     babel_flush_route(p, r);
        !           450:   }
        !           451: 
        !           452:   nbr->ifa = NULL;
        !           453:   rem_node(NODE nbr);
        !           454:   babel_unlock_neighbor(nbr);
        !           455: }
        !           456: 
        !           457: static void
        !           458: babel_expire_ihu(struct babel_proto *p, struct babel_neighbor *nbr)
        !           459: {
        !           460:   TRACE(D_EVENTS, "IHU from nbr %I on %s expired", nbr->addr, nbr->ifa->iface->name);
        !           461: 
        !           462:   nbr->txcost = BABEL_INFINITY;
        !           463:   nbr->ihu_expiry = 0;
        !           464:   babel_update_cost(nbr);
        !           465: }
        !           466: 
        !           467: static void
        !           468: babel_expire_hello(struct babel_proto *p, struct babel_neighbor *nbr, btime now_)
        !           469: {
        !           470: again:
        !           471:   nbr->hello_map <<= 1;
        !           472: 
        !           473:   if (nbr->hello_cnt < 16)
        !           474:     nbr->hello_cnt++;
        !           475: 
        !           476:   nbr->hello_expiry += nbr->last_hello_int;
        !           477: 
        !           478:   /* We may expire multiple hellos if last_hello_int is too short */
        !           479:   if (nbr->hello_map && nbr->hello_expiry <= now_)
        !           480:     goto again;
        !           481: 
        !           482:   TRACE(D_EVENTS, "Hello from nbr %I on %s expired, %d left",
        !           483:        nbr->addr, nbr->ifa->iface->name, u32_popcount(nbr->hello_map));
        !           484: 
        !           485:   if (nbr->hello_map)
        !           486:     babel_update_cost(nbr);
        !           487:   else
        !           488:     babel_flush_neighbor(p, nbr);
        !           489: }
        !           490: 
        !           491: static void
        !           492: babel_expire_neighbors(struct babel_proto *p)
        !           493: {
        !           494:   struct babel_iface *ifa;
        !           495:   struct babel_neighbor *nbr, *nbx;
        !           496:   btime now_ = current_time();
        !           497: 
        !           498:   WALK_LIST(ifa, p->interfaces)
        !           499:   {
        !           500:     WALK_LIST_DELSAFE(nbr, nbx, ifa->neigh_list)
        !           501:     {
        !           502:       if (nbr->ihu_expiry && nbr->ihu_expiry <= now_)
        !           503:         babel_expire_ihu(p, nbr);
        !           504: 
        !           505:       if (nbr->hello_expiry && nbr->hello_expiry <= now_)
        !           506:         babel_expire_hello(p, nbr, now_);
        !           507:     }
        !           508:   }
        !           509: }
        !           510: 
        !           511: 
        !           512: /*
        !           513:  *     Best route selection
        !           514:  */
        !           515: 
        !           516: /*
        !           517:  * From the RFC (section 3.5.1):
        !           518:  *
        !           519:  * a route advertisement carrying the quintuple (prefix, plen, router-id, seqno,
        !           520:  * metric) is feasible if one of the following conditions holds:
        !           521:  *
        !           522:  * - metric is infinite; or
        !           523:  *
        !           524:  * - no entry exists in the source table indexed by (id, prefix, plen); or
        !           525:  *
        !           526:  * - an entry (prefix, plen, router-id, seqno', metric') exists in the source
        !           527:  *   table, and either
        !           528:  *   - seqno' < seqno or
        !           529:  *   - seqno = seqno' and metric < metric'.
        !           530:  */
        !           531: static inline int
        !           532: babel_is_feasible(struct babel_source *s, u16 seqno, u16 metric)
        !           533: {
        !           534:   return !s ||
        !           535:     (metric == BABEL_INFINITY) ||
        !           536:     (seqno > s->seqno) ||
        !           537:     ((seqno == s->seqno) && (metric < s->metric));
        !           538: }
        !           539: 
        !           540: /* Simple additive metric - Appendix 3.1 in the RFC */
        !           541: static inline u16
        !           542: babel_compute_metric(struct babel_neighbor *n, uint metric)
        !           543: {
        !           544:   return MIN(metric + n->cost, BABEL_INFINITY);
        !           545: }
        !           546: 
        !           547: static void
        !           548: babel_update_cost(struct babel_neighbor *nbr)
        !           549: {
        !           550:   struct babel_proto *p = nbr->ifa->proto;
        !           551:   struct babel_iface_config *cf = nbr->ifa->cf;
        !           552:   uint rcv = u32_popcount(nbr->hello_map); // number of bits set
        !           553:   uint max = nbr->hello_cnt;
        !           554:   uint rxcost = BABEL_INFINITY;        /* Cost to announce in IHU */
        !           555:   uint txcost = BABEL_INFINITY;        /* Effective cost for route selection */
        !           556: 
        !           557:   if (!rcv || !nbr->ifa->up)
        !           558:     goto done;
        !           559: 
        !           560:   switch (cf->type)
        !           561:   {
        !           562:   case BABEL_IFACE_TYPE_WIRED:
        !           563:     /* k-out-of-j selection - Appendix 2.1 in the RFC. */
        !           564: 
        !           565:     /* Link is bad if less than cf->limit/16 of expected hellos were received */
        !           566:     if (rcv * 16 < cf->limit * max)
        !           567:       break;
        !           568: 
        !           569:     rxcost =  cf->rxcost;
        !           570:     txcost = nbr->txcost;
        !           571:     break;
        !           572: 
        !           573:   case BABEL_IFACE_TYPE_WIRELESS:
        !           574:     /*
        !           575:      * ETX - Appendix 2.2 in the RFC.
        !           576:      *
        !           577:      * alpha  = prob. of successful transmission estimated by the neighbor
        !           578:      * beta   = prob. of successful transmission estimated by the router
        !           579:      * rxcost = nominal rxcost of the router / beta
        !           580:      * txcost = nominal rxcost of the neighbor / (alpha * beta)
        !           581:      *        = received txcost / beta
        !           582:      *
        !           583:      * Note that received txcost is just neighbor's rxcost. Beta is rcv/max,
        !           584:      * we use inverse values of beta (i.e. max/rcv) to stay in integers.
        !           585:      */
        !           586:     rxcost = MIN( cf->rxcost * max / rcv, BABEL_INFINITY);
        !           587:     txcost = MIN(nbr->txcost * max / rcv, BABEL_INFINITY);
        !           588:     break;
        !           589:   }
        !           590: 
        !           591: done:
        !           592:   /* If RX cost changed, send IHU with next Hello */
        !           593:   if (rxcost != nbr->rxcost)
        !           594:   {
        !           595:     nbr->rxcost = rxcost;
        !           596:     nbr->ihu_cnt = 0;
        !           597:   }
        !           598: 
        !           599:   /* If link cost changed, run route selection */
        !           600:   if (txcost != nbr->cost)
        !           601:   {
        !           602:     TRACE(D_EVENTS, "Cost of nbr %I on %s changed from %u to %u",
        !           603:          nbr->addr, nbr->ifa->iface->name, nbr->cost, txcost);
        !           604: 
        !           605:     nbr->cost = txcost;
        !           606: 
        !           607:     struct babel_route *r; node *n;
        !           608:     WALK_LIST2(r, n, nbr->routes, neigh_route)
        !           609:     {
        !           610:       r->metric = babel_compute_metric(nbr, r->advert_metric);
        !           611:       babel_select_route(p, r->e, r);
        !           612:     }
        !           613:   }
        !           614: }
        !           615: 
        !           616: /**
        !           617:  * babel_announce_rte - announce selected route to the core
        !           618:  * @p: Babel protocol instance
        !           619:  * @e: Babel route entry to announce
        !           620:  *
        !           621:  * This function announces a Babel entry to the core if it has a selected
        !           622:  * incoming path, and retracts it otherwise. If there is no selected route but
        !           623:  * the entry is valid and ours, the unreachable route is announced instead.
        !           624:  */
        !           625: static void
        !           626: babel_announce_rte(struct babel_proto *p, struct babel_entry *e)
        !           627: {
        !           628:   struct babel_route *r = e->selected;
        !           629:   struct channel *c = (e->n.addr->type == NET_IP4) ? p->ip4_channel : p->ip6_channel;
        !           630: 
        !           631:   if (r)
        !           632:   {
        !           633:     rta a0 = {
        !           634:       .src = p->p.main_source,
        !           635:       .source = RTS_BABEL,
        !           636:       .scope = SCOPE_UNIVERSE,
        !           637:       .dest = RTD_UNICAST,
        !           638:       .from = r->neigh->addr,
        !           639:       .nh.gw = r->next_hop,
        !           640:       .nh.iface = r->neigh->ifa->iface,
        !           641:     };
        !           642: 
        !           643:     rta *a = rta_lookup(&a0);
        !           644:     rte *rte = rte_get_temp(a);
        !           645:     rte->u.babel.seqno = r->seqno;
        !           646:     rte->u.babel.metric = r->metric;
        !           647:     rte->u.babel.router_id = r->router_id;
        !           648:     rte->pflags = EA_ID_FLAG(EA_BABEL_METRIC) | EA_ID_FLAG(EA_BABEL_ROUTER_ID);
        !           649: 
        !           650:     e->unreachable = 0;
        !           651:     rte_update2(c, e->n.addr, rte, p->p.main_source);
        !           652:   }
        !           653:   else if (e->valid && (e->router_id != p->router_id))
        !           654:   {
        !           655:     /* Unreachable */
        !           656:     rta a0 = {
        !           657:       .src = p->p.main_source,
        !           658:       .source = RTS_BABEL,
        !           659:       .scope = SCOPE_UNIVERSE,
        !           660:       .dest = RTD_UNREACHABLE,
        !           661:     };
        !           662: 
        !           663:     rta *a = rta_lookup(&a0);
        !           664:     rte *rte = rte_get_temp(a);
        !           665:     memset(&rte->u.babel, 0, sizeof(rte->u.babel));
        !           666:     rte->pflags = 0;
        !           667:     rte->pref = 1;
        !           668: 
        !           669:     e->unreachable = 1;
        !           670:     rte_update2(c, e->n.addr, rte, p->p.main_source);
        !           671:   }
        !           672:   else
        !           673:   {
        !           674:     /* Retraction */
        !           675:     e->unreachable = 0;
        !           676:     rte_update2(c, e->n.addr, NULL, p->p.main_source);
        !           677:   }
        !           678: }
        !           679: 
        !           680: /* Special case of babel_announce_rte() just for retraction */
        !           681: static inline void
        !           682: babel_announce_retraction(struct babel_proto *p, struct babel_entry *e)
        !           683: {
        !           684:   struct channel *c = (e->n.addr->type == NET_IP4) ? p->ip4_channel : p->ip6_channel;
        !           685:   e->unreachable = 0;
        !           686:   rte_update2(c, e->n.addr, NULL, p->p.main_source);
        !           687: }
        !           688: 
        !           689: 
        !           690: /**
        !           691:  * babel_select_route - select best route for given route entry
        !           692:  * @p: Babel protocol instance
        !           693:  * @e: Babel entry to select the best route for
        !           694:  * @mod: Babel route that was modified or NULL if unspecified
        !           695:  *
        !           696:  * Select the best reachable and feasible route for a given prefix among the
        !           697:  * routes received from peers, and propagate it to the nest. This just selects
        !           698:  * the reachable and feasible route with the lowest metric, but keeps selected
        !           699:  * the old one in case of tie.
        !           700:  *
        !           701:  * If no feasible route is available for a prefix that previously had a route
        !           702:  * selected, a seqno request is sent to try to get a valid route. If the entry
        !           703:  * is valid and not owned by us, the unreachable route is announced to the nest
        !           704:  * (to blackhole packets going to it, as per section 2.8). It is later removed
        !           705:  * by babel_expire_routes(). Otherwise, the route is just removed from the nest.
        !           706:  *
        !           707:  * Argument @mod is used to optimize best route calculation. When specified, the
        !           708:  * function can assume that only the @mod route was modified to avoid full best
        !           709:  * route selection and announcement when non-best route was modified in minor
        !           710:  * way. The caller is advised to not call babel_select_route() when no change is
        !           711:  * done (e.g. periodic route updates) to avoid unnecessary announcements of the
        !           712:  * same best route. The caller is not required to call the function in case of a
        !           713:  * retraction of a non-best route.
        !           714:  *
        !           715:  * Note that the function does not active triggered updates. That is done by
        !           716:  * babel_rt_notify() when the change is propagated back to Babel.
        !           717:  */
        !           718: static void
        !           719: babel_select_route(struct babel_proto *p, struct babel_entry *e, struct babel_route *mod)
        !           720: {
        !           721:   struct babel_route *r, *best = e->selected;
        !           722: 
        !           723:   /* Shortcut if only non-best was modified */
        !           724:   if (mod && (mod != best))
        !           725:   {
        !           726:     /* Either select modified route, or keep old best route */
        !           727:     if ((mod->metric < (best ? best->metric : BABEL_INFINITY)) && mod->feasible)
        !           728:       best = mod;
        !           729:     else
        !           730:       return;
        !           731:   }
        !           732:   else
        !           733:   {
        !           734:     /* Selected route may be modified and no longer admissible */
        !           735:     if (!best || (best->metric == BABEL_INFINITY) || !best->feasible)
        !           736:       best = NULL;
        !           737: 
        !           738:     /* Find the best feasible route from all routes */
        !           739:     WALK_LIST(r, e->routes)
        !           740:       if ((r->metric < (best ? best->metric : BABEL_INFINITY)) && r->feasible)
        !           741:        best = r;
        !           742:   }
        !           743: 
        !           744:   if (best)
        !           745:   {
        !           746:     if (best != e->selected)
        !           747:       TRACE(D_EVENTS, "Picked new route for prefix %N: router-id %lR metric %d",
        !           748:            e->n.addr, best->router_id, best->metric);
        !           749:   }
        !           750:   else if (e->selected)
        !           751:   {
        !           752:     /*
        !           753:      * We have lost all feasible routes. We have to broadcast seqno request
        !           754:      * (Section 3.8.2.1) and keep unreachable route for a while (section 2.8).
        !           755:      * The later is done automatically by babel_announce_rte().
        !           756:      */
        !           757: 
        !           758:     TRACE(D_EVENTS, "Lost feasible route for prefix %N", e->n.addr);
        !           759:     if (e->valid && (e->selected->router_id == e->router_id))
        !           760:       babel_add_seqno_request(p, e, e->selected->router_id, e->selected->seqno + 1, 0, NULL);
        !           761:   }
        !           762:   else
        !           763:     return;
        !           764: 
        !           765:   e->selected = best;
        !           766:   babel_announce_rte(p, e);
        !           767: }
        !           768: 
        !           769: /*
        !           770:  *     Functions to send replies
        !           771:  */
        !           772: 
        !           773: static void
        !           774: babel_send_ack(struct babel_iface *ifa, ip_addr dest, u16 nonce)
        !           775: {
        !           776:   struct babel_proto *p = ifa->proto;
        !           777:   union babel_msg msg = {};
        !           778: 
        !           779:   TRACE(D_PACKETS, "Sending ACK to %I with nonce %d", dest, nonce);
        !           780: 
        !           781:   msg.type = BABEL_TLV_ACK;
        !           782:   msg.ack.nonce = nonce;
        !           783: 
        !           784:   babel_send_unicast(&msg, ifa, dest);
        !           785: }
        !           786: 
        !           787: static void
        !           788: babel_build_ihu(union babel_msg *msg, struct babel_iface *ifa, struct babel_neighbor *n)
        !           789: {
        !           790:   struct babel_proto *p = ifa->proto;
        !           791: 
        !           792:   msg->type = BABEL_TLV_IHU;
        !           793:   msg->ihu.addr = n->addr;
        !           794:   msg->ihu.rxcost = n->rxcost;
        !           795:   msg->ihu.interval = ifa->cf->ihu_interval;
        !           796: 
        !           797:   TRACE(D_PACKETS, "Sending IHU for %I with rxcost %d interval %t",
        !           798:         msg->ihu.addr, msg->ihu.rxcost, (btime) msg->ihu.interval);
        !           799: }
        !           800: 
        !           801: static void
        !           802: babel_send_ihu(struct babel_iface *ifa, struct babel_neighbor *n)
        !           803: {
        !           804:   union babel_msg msg = {};
        !           805:   babel_build_ihu(&msg, ifa, n);
        !           806:   babel_send_unicast(&msg, ifa, n->addr);
        !           807:   n->ihu_cnt = BABEL_IHU_INTERVAL_FACTOR;
        !           808: }
        !           809: 
        !           810: static void
        !           811: babel_send_ihus(struct babel_iface *ifa)
        !           812: {
        !           813:   struct babel_neighbor *n;
        !           814:   WALK_LIST(n, ifa->neigh_list)
        !           815:   {
        !           816:     if (n->hello_cnt && (--n->ihu_cnt <= 0))
        !           817:     {
        !           818:       union babel_msg msg = {};
        !           819:       babel_build_ihu(&msg, ifa, n);
        !           820:       babel_enqueue(&msg, ifa);
        !           821:       n->ihu_cnt = BABEL_IHU_INTERVAL_FACTOR;
        !           822:     }
        !           823:   }
        !           824: }
        !           825: 
        !           826: static void
        !           827: babel_send_hello(struct babel_iface *ifa)
        !           828: {
        !           829:   struct babel_proto *p = ifa->proto;
        !           830:   union babel_msg msg = {};
        !           831: 
        !           832:   msg.type = BABEL_TLV_HELLO;
        !           833:   msg.hello.seqno = ifa->hello_seqno++;
        !           834:   msg.hello.interval = ifa->cf->hello_interval;
        !           835: 
        !           836:   TRACE(D_PACKETS, "Sending hello on %s with seqno %d interval %t",
        !           837:        ifa->ifname, msg.hello.seqno, (btime) msg.hello.interval);
        !           838: 
        !           839:   babel_enqueue(&msg, ifa);
        !           840: 
        !           841:   babel_send_ihus(ifa);
        !           842: }
        !           843: 
        !           844: static void
        !           845: babel_send_route_request(struct babel_proto *p, struct babel_entry *e, struct babel_neighbor *n)
        !           846: {
        !           847:   union babel_msg msg = {};
        !           848: 
        !           849:   TRACE(D_PACKETS, "Sending route request for %N to %I", e->n.addr, n->addr);
        !           850: 
        !           851:   msg.type = BABEL_TLV_ROUTE_REQUEST;
        !           852:   net_copy(&msg.route_request.net, e->n.addr);
        !           853: 
        !           854:   babel_send_unicast(&msg, n->ifa, n->addr);
        !           855: }
        !           856: 
        !           857: static void
        !           858: babel_send_wildcard_request(struct babel_iface *ifa)
        !           859: {
        !           860:   struct babel_proto *p = ifa->proto;
        !           861:   union babel_msg msg = {};
        !           862: 
        !           863:   TRACE(D_PACKETS, "Sending wildcard route request on %s", ifa->ifname);
        !           864: 
        !           865:   msg.type = BABEL_TLV_ROUTE_REQUEST;
        !           866:   msg.route_request.full = 1;
        !           867: 
        !           868:   babel_enqueue(&msg, ifa);
        !           869: }
        !           870: 
        !           871: static void
        !           872: babel_send_seqno_request(struct babel_proto *p, struct babel_entry *e, struct babel_seqno_request *sr)
        !           873: {
        !           874:   union babel_msg msg = {};
        !           875: 
        !           876:   msg.type = BABEL_TLV_SEQNO_REQUEST;
        !           877:   msg.seqno_request.hop_count = sr->hop_count ?: BABEL_INITIAL_HOP_COUNT;
        !           878:   msg.seqno_request.seqno = sr->seqno;
        !           879:   msg.seqno_request.router_id = sr->router_id;
        !           880:   net_copy(&msg.seqno_request.net, e->n.addr);
        !           881: 
        !           882:   if (sr->nbr)
        !           883:   {
        !           884:     TRACE(D_PACKETS, "Sending seqno request for %N router-id %lR seqno %d to %I on %s",
        !           885:          e->n.addr, sr->router_id, sr->seqno, sr->nbr->addr, sr->nbr->ifa->ifname);
        !           886: 
        !           887:     babel_send_unicast(&msg, sr->nbr->ifa, sr->nbr->addr);
        !           888:   }
        !           889:   else
        !           890:   {
        !           891:     TRACE(D_PACKETS, "Sending broadcast seqno request for %N router-id %lR seqno %d",
        !           892:          e->n.addr, sr->router_id, sr->seqno);
        !           893: 
        !           894:     struct babel_iface *ifa;
        !           895:     WALK_LIST(ifa, p->interfaces)
        !           896:       babel_enqueue(&msg, ifa);
        !           897:   }
        !           898: }
        !           899: 
        !           900: /**
        !           901:  * babel_send_update - send route table updates
        !           902:  * @ifa: Interface to transmit on
        !           903:  * @changed: Only send entries changed since this time
        !           904:  *
        !           905:  * This function produces update TLVs for all entries changed since the time
        !           906:  * indicated by the &changed parameter and queues them for transmission on the
        !           907:  * selected interface. During the process, the feasibility distance for each
        !           908:  * transmitted entry is updated.
        !           909:  */
        !           910: static void
        !           911: babel_send_update_(struct babel_iface *ifa, btime changed, struct fib *rtable)
        !           912: {
        !           913:   struct babel_proto *p = ifa->proto;
        !           914: 
        !           915:   /* Update increase was requested */
        !           916:   if (p->update_seqno_inc)
        !           917:   {
        !           918:     p->update_seqno++;
        !           919:     p->update_seqno_inc = 0;
        !           920:   }
        !           921: 
        !           922:   FIB_WALK(rtable, struct babel_entry, e)
        !           923:   {
        !           924:     if (!e->valid)
        !           925:       continue;
        !           926: 
        !           927:     /* Our own seqno might have changed, in which case we update the routes we
        !           928:        originate. */
        !           929:     if ((e->router_id == p->router_id) && (e->seqno < p->update_seqno))
        !           930:     {
        !           931:       e->seqno = p->update_seqno;
        !           932:       e->updated = current_time();
        !           933:     }
        !           934: 
        !           935:     /* Skip routes that weren't updated since 'changed' time */
        !           936:     if (e->updated < changed)
        !           937:       continue;
        !           938: 
        !           939:     TRACE(D_PACKETS, "Sending update for %N router-id %lR seqno %d metric %d",
        !           940:          e->n.addr, e->router_id, e->seqno, e->metric);
        !           941: 
        !           942:     union babel_msg msg = {};
        !           943:     msg.type = BABEL_TLV_UPDATE;
        !           944:     msg.update.interval = ifa->cf->update_interval;
        !           945:     msg.update.seqno = e->seqno;
        !           946:     msg.update.metric = e->metric;
        !           947:     msg.update.router_id = e->router_id;
        !           948:     net_copy(&msg.update.net, e->n.addr);
        !           949: 
        !           950:     msg.update.next_hop = ((e->n.addr->type == NET_IP4) ?
        !           951:                           ifa->next_hop_ip4 : ifa->next_hop_ip6);
        !           952: 
        !           953:     /* Do not send route if next hop is unknown, e.g. no configured IPv4 address */
        !           954:     if (ipa_zero(msg.update.next_hop))
        !           955:       continue;
        !           956: 
        !           957:     babel_enqueue(&msg, ifa);
        !           958: 
        !           959:     /* Update feasibility distance for redistributed routes */
        !           960:     if (e->router_id != p->router_id)
        !           961:     {
        !           962:       struct babel_source *s = babel_get_source(p, e, e->router_id);
        !           963:       s->expires = current_time() + BABEL_GARBAGE_INTERVAL;
        !           964: 
        !           965:       if ((msg.update.seqno > s->seqno) ||
        !           966:          ((msg.update.seqno == s->seqno) && (msg.update.metric < s->metric)))
        !           967:       {
        !           968:        s->seqno = msg.update.seqno;
        !           969:        s->metric = msg.update.metric;
        !           970:       }
        !           971:     }
        !           972:   }
        !           973:   FIB_WALK_END;
        !           974: }
        !           975: 
        !           976: static void
        !           977: babel_send_update(struct babel_iface *ifa, btime changed)
        !           978: {
        !           979:   struct babel_proto *p = ifa->proto;
        !           980: 
        !           981:   babel_send_update_(ifa, changed, &p->ip4_rtable);
        !           982:   babel_send_update_(ifa, changed, &p->ip6_rtable);
        !           983: }
        !           984: 
        !           985: static void
        !           986: babel_trigger_iface_update(struct babel_iface *ifa)
        !           987: {
        !           988:   struct babel_proto *p = ifa->proto;
        !           989: 
        !           990:   /* Interface not active or already scheduled */
        !           991:   if (!ifa->up || ifa->want_triggered)
        !           992:     return;
        !           993: 
        !           994:   TRACE(D_EVENTS, "Scheduling triggered updates for %s seqno %d",
        !           995:        ifa->iface->name, p->update_seqno);
        !           996: 
        !           997:   ifa->want_triggered = current_time();
        !           998:   babel_iface_kick_timer(ifa);
        !           999: }
        !          1000: 
        !          1001: /* Sends and update on all interfaces. */
        !          1002: static void
        !          1003: babel_trigger_update(struct babel_proto *p)
        !          1004: {
        !          1005:   if (p->triggered)
        !          1006:     return;
        !          1007: 
        !          1008:   struct babel_iface *ifa;
        !          1009:   WALK_LIST(ifa, p->interfaces)
        !          1010:     babel_trigger_iface_update(ifa);
        !          1011: 
        !          1012:   p->triggered = 1;
        !          1013: }
        !          1014: 
        !          1015: /* A retraction is an update with an infinite metric */
        !          1016: static void
        !          1017: babel_send_retraction(struct babel_iface *ifa, net_addr *n)
        !          1018: {
        !          1019:   struct babel_proto *p = ifa->proto;
        !          1020:   union babel_msg msg = {};
        !          1021: 
        !          1022:   TRACE(D_PACKETS, "Sending retraction for %N seqno %d", n, p->update_seqno);
        !          1023: 
        !          1024:   msg.type = BABEL_TLV_UPDATE;
        !          1025:   msg.update.interval = ifa->cf->update_interval;
        !          1026:   msg.update.seqno = p->update_seqno;
        !          1027:   msg.update.metric = BABEL_INFINITY;
        !          1028:   msg.update.net = *n;
        !          1029: 
        !          1030:   babel_enqueue(&msg, ifa);
        !          1031: }
        !          1032: 
        !          1033: static void
        !          1034: babel_send_wildcard_retraction(struct babel_iface *ifa)
        !          1035: {
        !          1036:   struct babel_proto *p = ifa->proto;
        !          1037:   union babel_msg msg = {};
        !          1038: 
        !          1039:   TRACE(D_PACKETS, "Sending wildcard retraction on %s", ifa->ifname);
        !          1040: 
        !          1041:   msg.type = BABEL_TLV_UPDATE;
        !          1042:   msg.update.wildcard = 1;
        !          1043:   msg.update.interval = ifa->cf->update_interval;
        !          1044:   msg.update.seqno = p->update_seqno;
        !          1045:   msg.update.metric = BABEL_INFINITY;
        !          1046: 
        !          1047:   babel_enqueue(&msg, ifa);
        !          1048: }
        !          1049: 
        !          1050: 
        !          1051: /*
        !          1052:  *     TLV handler helpers
        !          1053:  */
        !          1054: 
        !          1055: /* Update hello history according to Appendix A1 of the RFC */
        !          1056: static void
        !          1057: babel_update_hello_history(struct babel_neighbor *n, u16 seqno, uint interval)
        !          1058: {
        !          1059:   /*
        !          1060:    * Compute the difference between expected and received seqno (modulo 2^16).
        !          1061:    * If the expected and received seqnos are within 16 of each other, the modular
        !          1062:    * difference is going to be less than 16 for one of the directions. Otherwise,
        !          1063:    * the values differ too much, so just reset the state.
        !          1064:    */
        !          1065: 
        !          1066:   u16 delta = ((uint) seqno - (uint) n->next_hello_seqno);
        !          1067: 
        !          1068:   if ((delta == 0) || (n->hello_cnt == 0))
        !          1069:   {
        !          1070:     /* Do nothing */
        !          1071:   }
        !          1072:   else if (delta <= 16)
        !          1073:   {
        !          1074:     /* Sending node decreased interval; fast-forward */
        !          1075:     n->hello_map <<= delta;
        !          1076:     n->hello_cnt = MIN(n->hello_cnt + delta, 16);
        !          1077:   }
        !          1078:   else if (delta >= 0xfff0)
        !          1079:   {
        !          1080:     u8 diff = (0xffff - delta);
        !          1081:     /* Sending node increased interval; undo history */
        !          1082:     n->hello_map >>= diff;
        !          1083:     n->hello_cnt = (diff < n->hello_cnt) ? n->hello_cnt - diff : 0;
        !          1084:   }
        !          1085:   else
        !          1086:   {
        !          1087:     /* Note state reset - flush entries */
        !          1088:     n->hello_map = n->hello_cnt = 0;
        !          1089:   }
        !          1090: 
        !          1091:   /* Current entry */
        !          1092:   n->hello_map = (n->hello_map << 1) | 1;
        !          1093:   n->next_hello_seqno = seqno+1;
        !          1094:   if (n->hello_cnt < 16) n->hello_cnt++;
        !          1095: 
        !          1096:   /* Update expiration */
        !          1097:   n->hello_expiry = current_time() + BABEL_HELLO_EXPIRY_FACTOR(interval);
        !          1098:   n->last_hello_int = interval;
        !          1099: }
        !          1100: 
        !          1101: 
        !          1102: /*
        !          1103:  *     TLV handlers
        !          1104:  */
        !          1105: 
        !          1106: void
        !          1107: babel_handle_ack_req(union babel_msg *m, struct babel_iface *ifa)
        !          1108: {
        !          1109:   struct babel_proto *p = ifa->proto;
        !          1110:   struct babel_msg_ack_req *msg = &m->ack_req;
        !          1111: 
        !          1112:   TRACE(D_PACKETS, "Handling ACK request nonce %d interval %t",
        !          1113:        msg->nonce, (btime) msg->interval);
        !          1114: 
        !          1115:   babel_send_ack(ifa, msg->sender, msg->nonce);
        !          1116: }
        !          1117: 
        !          1118: void
        !          1119: babel_handle_hello(union babel_msg *m, struct babel_iface *ifa)
        !          1120: {
        !          1121:   struct babel_proto *p = ifa->proto;
        !          1122:   struct babel_msg_hello *msg = &m->hello;
        !          1123: 
        !          1124:   TRACE(D_PACKETS, "Handling hello seqno %d interval %t",
        !          1125:        msg->seqno, (btime) msg->interval);
        !          1126: 
        !          1127:   struct babel_neighbor *n = babel_get_neighbor(ifa, msg->sender);
        !          1128:   int first_hello = !n->hello_cnt;
        !          1129: 
        !          1130:   babel_update_hello_history(n, msg->seqno, msg->interval);
        !          1131:   babel_update_cost(n);
        !          1132: 
        !          1133:   /* Speed up session establishment by sending IHU immediately */
        !          1134:   if (first_hello)
        !          1135:     babel_send_ihu(ifa, n);
        !          1136: }
        !          1137: 
        !          1138: void
        !          1139: babel_handle_ihu(union babel_msg *m, struct babel_iface *ifa)
        !          1140: {
        !          1141:   struct babel_proto *p = ifa->proto;
        !          1142:   struct babel_msg_ihu *msg = &m->ihu;
        !          1143: 
        !          1144:   /* Ignore IHUs that are not about us */
        !          1145:   if ((msg->ae != BABEL_AE_WILDCARD) && !ipa_equal(msg->addr, ifa->addr))
        !          1146:     return;
        !          1147: 
        !          1148:   TRACE(D_PACKETS, "Handling IHU rxcost %d interval %t",
        !          1149:        msg->rxcost, (btime) msg->interval);
        !          1150: 
        !          1151:   struct babel_neighbor *n = babel_get_neighbor(ifa, msg->sender);
        !          1152:   n->txcost = msg->rxcost;
        !          1153:   n->ihu_expiry = current_time() + BABEL_IHU_EXPIRY_FACTOR(msg->interval);
        !          1154:   babel_update_cost(n);
        !          1155: }
        !          1156: 
        !          1157: /**
        !          1158:  * babel_handle_update - handle incoming route updates
        !          1159:  * @m: Incoming update TLV
        !          1160:  * @ifa: Interface the update was received on
        !          1161:  *
        !          1162:  * This function is called as a handler for update TLVs and handles the updating
        !          1163:  * and maintenance of route entries in Babel's internal routing cache. The
        !          1164:  * handling follows the actions described in the Babel RFC, and at the end of
        !          1165:  * each update handling, babel_select_route() is called on the affected entry to
        !          1166:  * optionally update the selected routes and propagate them to the core.
        !          1167:  */
        !          1168: void
        !          1169: babel_handle_update(union babel_msg *m, struct babel_iface *ifa)
        !          1170: {
        !          1171:   struct babel_proto *p = ifa->proto;
        !          1172:   struct babel_msg_update *msg = &m->update;
        !          1173: 
        !          1174:   struct babel_neighbor *nbr;
        !          1175:   struct babel_entry *e;
        !          1176:   struct babel_source *s;
        !          1177:   struct babel_route *r, *best;
        !          1178:   node *n;
        !          1179:   int feasible, metric;
        !          1180: 
        !          1181:   if (msg->wildcard)
        !          1182:     TRACE(D_PACKETS, "Handling wildcard retraction", msg->seqno);
        !          1183:   else
        !          1184:     TRACE(D_PACKETS, "Handling update for %N with seqno %d metric %d",
        !          1185:          &msg->net, msg->seqno, msg->metric);
        !          1186: 
        !          1187:   nbr = babel_find_neighbor(ifa, msg->sender);
        !          1188:   if (!nbr)
        !          1189:   {
        !          1190:     DBG("Babel: Haven't heard from neighbor %I; ignoring update.\n", msg->sender);
        !          1191:     return;
        !          1192:   }
        !          1193: 
        !          1194:   if (msg->router_id == p->router_id)
        !          1195:   {
        !          1196:     DBG("Babel: Ignoring update for our own router ID.\n");
        !          1197:     return;
        !          1198:   }
        !          1199: 
        !          1200:   struct channel *c = (msg->net.type == NET_IP4) ? p->ip4_channel : p->ip6_channel;
        !          1201:   if (!c || (c->channel_state != CS_UP))
        !          1202:   {
        !          1203:     DBG("Babel: Ignoring update for inactive address family.\n");
        !          1204:     return;
        !          1205:   }
        !          1206: 
        !          1207:   /* Retraction */
        !          1208:   if (msg->metric == BABEL_INFINITY)
        !          1209:   {
        !          1210:     if (msg->wildcard)
        !          1211:     {
        !          1212:       /*
        !          1213:        * Special case: This is a retraction of all prefixes announced by this
        !          1214:        * neighbour (see second-to-last paragraph of section 4.4.9 in the RFC).
        !          1215:        */
        !          1216:       WALK_LIST(n, nbr->routes)
        !          1217:       {
        !          1218:        r = SKIP_BACK(struct babel_route, neigh_route, n);
        !          1219:        babel_retract_route(p, r);
        !          1220:       }
        !          1221:     }
        !          1222:     else
        !          1223:     {
        !          1224:       e = babel_find_entry(p, &msg->net);
        !          1225: 
        !          1226:       if (!e)
        !          1227:        return;
        !          1228: 
        !          1229:       /* The route entry indexed by neighbour */
        !          1230:       r = babel_find_route(e, nbr);
        !          1231: 
        !          1232:       if (!r)
        !          1233:        return;
        !          1234: 
        !          1235:       /* Router-id, next-hop and seqno are ignored for retractions */
        !          1236:       babel_retract_route(p, r);
        !          1237:     }
        !          1238: 
        !          1239:     /* Done with retractions */
        !          1240:     return;
        !          1241:   }
        !          1242: 
        !          1243:   /* Regular update */
        !          1244:   e = babel_get_entry(p, &msg->net);
        !          1245:   r = babel_get_route(p, e, nbr); /* the route entry indexed by neighbour */
        !          1246:   s = babel_find_source(e, msg->router_id); /* for feasibility */
        !          1247:   feasible = babel_is_feasible(s, msg->seqno, msg->metric);
        !          1248:   metric = babel_compute_metric(nbr, msg->metric);
        !          1249:   best = e->selected;
        !          1250: 
        !          1251:   /* RFC section 3.8.2.2 - Dealing with unfeasible updates */
        !          1252:   if (!feasible && (metric != BABEL_INFINITY) &&
        !          1253:       (!best || (r == best) || (metric < best->metric)))
        !          1254:     babel_add_seqno_request(p, e, s->router_id, s->seqno + 1, 0, nbr);
        !          1255: 
        !          1256:   /* Special case - ignore unfeasible update to best route */
        !          1257:   if (r == best && !feasible && (msg->router_id == r->router_id))
        !          1258:     return;
        !          1259: 
        !          1260:   r->expires = current_time() + BABEL_ROUTE_EXPIRY_FACTOR(msg->interval);
        !          1261:   r->refresh_time = current_time() + BABEL_ROUTE_REFRESH_FACTOR(msg->interval);
        !          1262: 
        !          1263:   /* No further processing if there is no change */
        !          1264:   if ((r->feasible == feasible) && (r->seqno == msg->seqno) &&
        !          1265:       (r->metric == metric) && (r->advert_metric == msg->metric) &&
        !          1266:       (r->router_id == msg->router_id) && ipa_equal(r->next_hop, msg->next_hop))
        !          1267:     return;
        !          1268: 
        !          1269:   /* Last paragraph above - update the entry */
        !          1270:   r->feasible = feasible;
        !          1271:   r->seqno = msg->seqno;
        !          1272:   r->metric = metric;
        !          1273:   r->advert_metric = msg->metric;
        !          1274:   r->router_id = msg->router_id;
        !          1275:   r->next_hop = msg->next_hop;
        !          1276: 
        !          1277:   /* If received update satisfies seqno request, we send triggered updates */
        !          1278:   if (babel_satisfy_seqno_request(p, e, msg->router_id, msg->seqno))
        !          1279:   {
        !          1280:     babel_trigger_update(p);
        !          1281:     e->updated = current_time();
        !          1282:   }
        !          1283: 
        !          1284:   babel_select_route(p, e, r);
        !          1285: }
        !          1286: 
        !          1287: void
        !          1288: babel_handle_route_request(union babel_msg *m, struct babel_iface *ifa)
        !          1289: {
        !          1290:   struct babel_proto *p = ifa->proto;
        !          1291:   struct babel_msg_route_request *msg = &m->route_request;
        !          1292: 
        !          1293:   /* RFC 6126 3.8.1.1 */
        !          1294: 
        !          1295:   /* Wildcard request - full update on the interface */
        !          1296:   if (msg->full)
        !          1297:   {
        !          1298:     TRACE(D_PACKETS, "Handling wildcard route request");
        !          1299:     ifa->want_triggered = 1;
        !          1300:     return;
        !          1301:   }
        !          1302: 
        !          1303:   TRACE(D_PACKETS, "Handling route request for %N", &msg->net);
        !          1304: 
        !          1305:   /* Non-wildcard request - see if we have an entry for the route.
        !          1306:      If not, send a retraction, otherwise send an update. */
        !          1307:   struct babel_entry *e = babel_find_entry(p, &msg->net);
        !          1308:   if (!e)
        !          1309:   {
        !          1310:     babel_send_retraction(ifa, &msg->net);
        !          1311:   }
        !          1312:   else
        !          1313:   {
        !          1314:     babel_trigger_iface_update(ifa);
        !          1315:     e->updated = current_time();
        !          1316:   }
        !          1317: }
        !          1318: 
        !          1319: void
        !          1320: babel_handle_seqno_request(union babel_msg *m, struct babel_iface *ifa)
        !          1321: {
        !          1322:   struct babel_proto *p = ifa->proto;
        !          1323:   struct babel_msg_seqno_request *msg = &m->seqno_request;
        !          1324: 
        !          1325:   /* RFC 6126 3.8.1.2 */
        !          1326: 
        !          1327:   TRACE(D_PACKETS, "Handling seqno request for %N router-id %lR seqno %d hop count %d",
        !          1328:        &msg->net, msg->router_id, msg->seqno, msg->hop_count);
        !          1329: 
        !          1330:   /* Ignore if we have no such entry or entry has infinite metric */
        !          1331:   struct babel_entry *e = babel_find_entry(p, &msg->net);
        !          1332:   if (!e || !e->valid || (e->metric == BABEL_INFINITY))
        !          1333:     return;
        !          1334: 
        !          1335:   /* Trigger update on incoming interface if we have a selected route with
        !          1336:      different router id or seqno no smaller than requested */
        !          1337:   if ((e->router_id != msg->router_id) || ge_mod64k(e->seqno, msg->seqno))
        !          1338:   {
        !          1339:     babel_trigger_iface_update(ifa);
        !          1340:     e->updated = current_time();
        !          1341:     return;
        !          1342:   }
        !          1343: 
        !          1344:   /* Seqno is larger; check if we own the router id */
        !          1345:   if (msg->router_id == p->router_id)
        !          1346:   {
        !          1347:     /* Ours; seqno increase and trigger global update */
        !          1348:     p->update_seqno_inc = 1;
        !          1349:     babel_trigger_update(p);
        !          1350:   }
        !          1351:   else if (msg->hop_count > 1)
        !          1352:   {
        !          1353:     /* Not ours; forward if TTL allows it */
        !          1354: 
        !          1355:     /* Find best admissible route */
        !          1356:     struct babel_route *r, *best1 = NULL, *best2 = NULL;
        !          1357:     WALK_LIST(r, e->routes)
        !          1358:       if ((r->router_id == msg->router_id) && !ipa_equal(r->neigh->addr, msg->sender))
        !          1359:       {
        !          1360:        /* Find best feasible route */
        !          1361:        if ((!best1 || r->metric < best1->metric) && r->feasible)
        !          1362:          best1 = r;
        !          1363: 
        !          1364:        /* Find best not necessary feasible route */
        !          1365:        if (!best2 || r->metric < best2->metric)
        !          1366:          best2 = r;
        !          1367:       }
        !          1368: 
        !          1369:     /* If no route is found, do nothing */
        !          1370:     r = best1 ?: best2;
        !          1371:     if (!r)
        !          1372:       return;
        !          1373: 
        !          1374:     babel_add_seqno_request(p, e, msg->router_id, msg->seqno, msg->hop_count-1, r->neigh);
        !          1375:   }
        !          1376: }
        !          1377: 
        !          1378: 
        !          1379: /*
        !          1380:  *     Babel interfaces
        !          1381:  */
        !          1382: 
        !          1383: /**
        !          1384:  * babel_iface_timer - Babel interface timer handler
        !          1385:  * @t: Timer
        !          1386:  *
        !          1387:  * This function is called by the per-interface timer and triggers sending of
        !          1388:  * periodic Hello's and both triggered and periodic updates. Periodic Hello's
        !          1389:  * and updates are simply handled by setting the next_{hello,regular} variables
        !          1390:  * on the interface, and triggering an update (and resetting the variable)
        !          1391:  * whenever 'now' exceeds that value.
        !          1392:  *
        !          1393:  * For triggered updates, babel_trigger_iface_update() will set the
        !          1394:  * want_triggered field on the interface to a timestamp value. If this is set
        !          1395:  * (and the next_triggered time has passed; this is a rate limiting mechanism),
        !          1396:  * babel_send_update() will be called with this timestamp as the second
        !          1397:  * parameter. This causes updates to be send consisting of only the routes that
        !          1398:  * have changed since the time saved in want_triggered.
        !          1399:  *
        !          1400:  * Mostly when an update is triggered, the route being modified will be set to
        !          1401:  * the value of 'now' at the time of the trigger; the >= comparison for
        !          1402:  * selecting which routes to send in the update will make sure this is included.
        !          1403:  */
        !          1404: static void
        !          1405: babel_iface_timer(timer *t)
        !          1406: {
        !          1407:   struct babel_iface *ifa = t->data;
        !          1408:   struct babel_proto *p = ifa->proto;
        !          1409:   btime hello_period = ifa->cf->hello_interval;
        !          1410:   btime update_period = ifa->cf->update_interval;
        !          1411:   btime now_ = current_time();
        !          1412: 
        !          1413:   if (now_ >= ifa->next_hello)
        !          1414:   {
        !          1415:     babel_send_hello(ifa);
        !          1416:     ifa->next_hello += hello_period * (1 + (now_ - ifa->next_hello) / hello_period);
        !          1417:   }
        !          1418: 
        !          1419:   if (now_ >= ifa->next_regular)
        !          1420:   {
        !          1421:     TRACE(D_EVENTS, "Sending regular updates on %s", ifa->ifname);
        !          1422:     babel_send_update(ifa, 0);
        !          1423:     ifa->next_regular += update_period * (1 + (now_ - ifa->next_regular) / update_period);
        !          1424:     ifa->want_triggered = 0;
        !          1425:     p->triggered = 0;
        !          1426:   }
        !          1427:   else if (ifa->want_triggered && (now_ >= ifa->next_triggered))
        !          1428:   {
        !          1429:     TRACE(D_EVENTS, "Sending triggered updates on %s", ifa->ifname);
        !          1430:     babel_send_update(ifa, ifa->want_triggered);
        !          1431:     ifa->next_triggered = now_ + MIN(1 S, update_period / 2);
        !          1432:     ifa->want_triggered = 0;
        !          1433:     p->triggered = 0;
        !          1434:   }
        !          1435: 
        !          1436:   btime next_event = MIN(ifa->next_hello, ifa->next_regular);
        !          1437:   if (ifa->want_triggered) next_event = MIN(next_event, ifa->next_triggered);
        !          1438:   tm_set(ifa->timer, next_event);
        !          1439: }
        !          1440: 
        !          1441: static inline void
        !          1442: babel_iface_kick_timer(struct babel_iface *ifa)
        !          1443: {
        !          1444:   if (ifa->timer->expires > (current_time() + 100 MS))
        !          1445:     tm_start(ifa->timer, 100 MS);
        !          1446: }
        !          1447: 
        !          1448: static void
        !          1449: babel_iface_start(struct babel_iface *ifa)
        !          1450: {
        !          1451:   struct babel_proto *p = ifa->proto;
        !          1452: 
        !          1453:   TRACE(D_EVENTS, "Starting interface %s", ifa->ifname);
        !          1454: 
        !          1455:   ifa->next_hello = current_time() + (random() % ifa->cf->hello_interval);
        !          1456:   ifa->next_regular = current_time() + (random() % ifa->cf->update_interval);
        !          1457:   ifa->next_triggered = current_time() + MIN(1 S, ifa->cf->update_interval / 2);
        !          1458:   ifa->want_triggered = 0;     /* We send an immediate update (below) */
        !          1459:   tm_start(ifa->timer, 100 MS);
        !          1460:   ifa->up = 1;
        !          1461: 
        !          1462:   babel_send_hello(ifa);
        !          1463:   babel_send_wildcard_retraction(ifa);
        !          1464:   babel_send_wildcard_request(ifa);
        !          1465:   babel_send_update(ifa, 0);   /* Full update */
        !          1466: }
        !          1467: 
        !          1468: static void
        !          1469: babel_iface_stop(struct babel_iface *ifa)
        !          1470: {
        !          1471:   struct babel_proto *p = ifa->proto;
        !          1472:   struct babel_neighbor *nbr;
        !          1473:   struct babel_route *r;
        !          1474:   node *n;
        !          1475: 
        !          1476:   TRACE(D_EVENTS, "Stopping interface %s", ifa->ifname);
        !          1477: 
        !          1478:   /*
        !          1479:    * Rather than just flushing the neighbours, we set the metric of their routes
        !          1480:    * to infinity. This allows us to keep the neighbour hello state for when the
        !          1481:    * interface comes back up. The routes will also be kept until they expire.
        !          1482:    */
        !          1483:   WALK_LIST(nbr, ifa->neigh_list)
        !          1484:   {
        !          1485:     WALK_LIST(n, nbr->routes)
        !          1486:     {
        !          1487:       r = SKIP_BACK(struct babel_route, neigh_route, n);
        !          1488:       babel_retract_route(p, r);
        !          1489:     }
        !          1490:   }
        !          1491: 
        !          1492:   tm_stop(ifa->timer);
        !          1493:   ifa->up = 0;
        !          1494: }
        !          1495: 
        !          1496: static inline int
        !          1497: babel_iface_link_up(struct babel_iface *ifa)
        !          1498: {
        !          1499:   return !ifa->cf->check_link || (ifa->iface->flags & IF_LINK_UP);
        !          1500: }
        !          1501: 
        !          1502: static void
        !          1503: babel_iface_update_state(struct babel_iface *ifa)
        !          1504: {
        !          1505:   int up = ifa->sk && babel_iface_link_up(ifa);
        !          1506: 
        !          1507:   if (up == ifa->up)
        !          1508:     return;
        !          1509: 
        !          1510:   if (up)
        !          1511:     babel_iface_start(ifa);
        !          1512:   else
        !          1513:     babel_iface_stop(ifa);
        !          1514: }
        !          1515: 
        !          1516: static void
        !          1517: babel_iface_update_addr4(struct babel_iface *ifa)
        !          1518: {
        !          1519:   struct babel_proto *p = ifa->proto;
        !          1520: 
        !          1521:   ip_addr addr4 = ifa->iface->addr4 ? ifa->iface->addr4->ip : IPA_NONE;
        !          1522:   ifa->next_hop_ip4 = ipa_nonzero(ifa->cf->next_hop_ip4) ? ifa->cf->next_hop_ip4 : addr4;
        !          1523: 
        !          1524:   if (ipa_zero(ifa->next_hop_ip4) && p->ip4_channel)
        !          1525:     log(L_WARN "%s: Missing IPv4 next hop address for %s", p->p.name, ifa->ifname);
        !          1526: 
        !          1527:   if (ifa->up)
        !          1528:     babel_iface_kick_timer(ifa);
        !          1529: }
        !          1530: 
        !          1531: static void
        !          1532: babel_iface_update_buffers(struct babel_iface *ifa)
        !          1533: {
        !          1534:   if (!ifa->sk)
        !          1535:     return;
        !          1536: 
        !          1537:   uint mtu = MAX(BABEL_MIN_MTU, ifa->iface->mtu);
        !          1538:   uint rbsize = ifa->cf->rx_buffer ?: mtu;
        !          1539:   uint tbsize = ifa->cf->tx_length ?: mtu;
        !          1540:   rbsize = MAX(rbsize, tbsize);
        !          1541: 
        !          1542:   sk_set_rbsize(ifa->sk, rbsize);
        !          1543:   sk_set_tbsize(ifa->sk, tbsize);
        !          1544: 
        !          1545:   ifa->tx_length = tbsize - BABEL_OVERHEAD;
        !          1546: }
        !          1547: 
        !          1548: static struct babel_iface*
        !          1549: babel_find_iface(struct babel_proto *p, struct iface *what)
        !          1550: {
        !          1551:   struct babel_iface *ifa;
        !          1552: 
        !          1553:   WALK_LIST (ifa, p->interfaces)
        !          1554:     if (ifa->iface == what)
        !          1555:       return ifa;
        !          1556: 
        !          1557:   return NULL;
        !          1558: }
        !          1559: 
        !          1560: static void
        !          1561: babel_iface_locked(struct object_lock *lock)
        !          1562: {
        !          1563:   struct babel_iface *ifa = lock->data;
        !          1564:   struct babel_proto *p = ifa->proto;
        !          1565: 
        !          1566:   if (!babel_open_socket(ifa))
        !          1567:   {
        !          1568:     log(L_ERR "%s: Cannot open socket for %s", p->p.name, ifa->iface->name);
        !          1569:     return;
        !          1570:   }
        !          1571: 
        !          1572:   babel_iface_update_buffers(ifa);
        !          1573:   babel_iface_update_state(ifa);
        !          1574: }
        !          1575: 
        !          1576: static void
        !          1577: babel_add_iface(struct babel_proto *p, struct iface *new, struct babel_iface_config *ic)
        !          1578: {
        !          1579:   struct babel_iface *ifa;
        !          1580: 
        !          1581:   TRACE(D_EVENTS, "Adding interface %s", new->name);
        !          1582: 
        !          1583:   pool *pool = rp_new(p->p.pool, new->name);
        !          1584: 
        !          1585:   ifa = mb_allocz(pool, sizeof(struct babel_iface));
        !          1586:   ifa->proto = p;
        !          1587:   ifa->iface = new;
        !          1588:   ifa->cf = ic;
        !          1589:   ifa->pool = pool;
        !          1590:   ifa->ifname = new->name;
        !          1591:   ifa->addr = new->llv6->ip;
        !          1592: 
        !          1593:   add_tail(&p->interfaces, NODE ifa);
        !          1594: 
        !          1595:   ip_addr addr4 = new->addr4 ? new->addr4->ip : IPA_NONE;
        !          1596:   ifa->next_hop_ip4 = ipa_nonzero(ic->next_hop_ip4) ? ic->next_hop_ip4 : addr4;
        !          1597:   ifa->next_hop_ip6 = ipa_nonzero(ic->next_hop_ip6) ? ic->next_hop_ip6 : ifa->addr;
        !          1598: 
        !          1599:   if (ipa_zero(ifa->next_hop_ip4) && p->ip4_channel)
        !          1600:     log(L_WARN "%s: Missing IPv4 next hop address for %s", p->p.name, new->name);
        !          1601: 
        !          1602:   init_list(&ifa->neigh_list);
        !          1603:   ifa->hello_seqno = 1;
        !          1604: 
        !          1605:   ifa->timer = tm_new_init(ifa->pool, babel_iface_timer, ifa, 0, 0);
        !          1606: 
        !          1607:   init_list(&ifa->msg_queue);
        !          1608:   ifa->send_event = ev_new_init(ifa->pool, babel_send_queue, ifa);
        !          1609: 
        !          1610:   struct object_lock *lock = olock_new(ifa->pool);
        !          1611:   lock->type = OBJLOCK_UDP;
        !          1612:   lock->addr = IP6_BABEL_ROUTERS;
        !          1613:   lock->port = ifa->cf->port;
        !          1614:   lock->iface = ifa->iface;
        !          1615:   lock->hook = babel_iface_locked;
        !          1616:   lock->data = ifa;
        !          1617: 
        !          1618:   olock_acquire(lock);
        !          1619: }
        !          1620: 
        !          1621: static void
        !          1622: babel_remove_iface(struct babel_proto *p, struct babel_iface *ifa)
        !          1623: {
        !          1624:   TRACE(D_EVENTS, "Removing interface %s", ifa->iface->name);
        !          1625: 
        !          1626:   struct babel_neighbor *n;
        !          1627:   WALK_LIST_FIRST(n, ifa->neigh_list)
        !          1628:     babel_flush_neighbor(p, n);
        !          1629: 
        !          1630:   rem_node(NODE ifa);
        !          1631: 
        !          1632:   rfree(ifa->pool); /* contains ifa itself, locks, socket, etc */
        !          1633: }
        !          1634: 
        !          1635: static void
        !          1636: babel_if_notify(struct proto *P, unsigned flags, struct iface *iface)
        !          1637: {
        !          1638:   struct babel_proto *p = (void *) P;
        !          1639:   struct babel_config *cf = (void *) P->cf;
        !          1640:   struct babel_iface *ifa = babel_find_iface(p, iface);
        !          1641: 
        !          1642:   if (iface->flags & IF_IGNORE)
        !          1643:     return;
        !          1644: 
        !          1645:   /* Add, remove or restart interface */
        !          1646:   if (flags & (IF_CHANGE_UPDOWN | IF_CHANGE_LLV6))
        !          1647:   {
        !          1648:     if (ifa)
        !          1649:       babel_remove_iface(p, ifa);
        !          1650: 
        !          1651:     if (!(iface->flags & IF_UP))
        !          1652:       return;
        !          1653: 
        !          1654:     /* We only speak multicast */
        !          1655:     if (!(iface->flags & IF_MULTICAST))
        !          1656:       return;
        !          1657: 
        !          1658:     /* Ignore ifaces without link-local address */
        !          1659:     if (!iface->llv6)
        !          1660:       return;
        !          1661: 
        !          1662:     struct babel_iface_config *ic = (void *) iface_patt_find(&cf->iface_list, iface, NULL);
        !          1663:     if (ic)
        !          1664:       babel_add_iface(p, iface, ic);
        !          1665: 
        !          1666:     return;
        !          1667:   }
        !          1668: 
        !          1669:   if (!ifa)
        !          1670:     return;
        !          1671: 
        !          1672:   if (flags & IF_CHANGE_ADDR4)
        !          1673:     babel_iface_update_addr4(ifa);
        !          1674: 
        !          1675:   if (flags & IF_CHANGE_MTU)
        !          1676:     babel_iface_update_buffers(ifa);
        !          1677: 
        !          1678:   if (flags & IF_CHANGE_LINK)
        !          1679:     babel_iface_update_state(ifa);
        !          1680: }
        !          1681: 
        !          1682: static int
        !          1683: babel_reconfigure_iface(struct babel_proto *p, struct babel_iface *ifa, struct babel_iface_config *new)
        !          1684: {
        !          1685:   struct babel_iface_config *old = ifa->cf;
        !          1686: 
        !          1687:   /* Change of these options would require to reset the iface socket */
        !          1688:   if ((new->port != old->port) ||
        !          1689:       (new->tx_tos != old->tx_tos) ||
        !          1690:       (new->tx_priority != old->tx_priority))
        !          1691:     return 0;
        !          1692: 
        !          1693:   TRACE(D_EVENTS, "Reconfiguring interface %s", ifa->iface->name);
        !          1694: 
        !          1695:   ifa->cf = new;
        !          1696: 
        !          1697:   ip_addr addr4 = ifa->iface->addr4 ? ifa->iface->addr4->ip : IPA_NONE;
        !          1698:   ifa->next_hop_ip4 = ipa_nonzero(new->next_hop_ip4) ? new->next_hop_ip4 : addr4;
        !          1699:   ifa->next_hop_ip6 = ipa_nonzero(new->next_hop_ip6) ? new->next_hop_ip6 : ifa->addr;
        !          1700: 
        !          1701:   if (ipa_zero(ifa->next_hop_ip4) && p->ip4_channel)
        !          1702:     log(L_WARN "%s: Missing IPv4 next hop address for %s", p->p.name, ifa->ifname);
        !          1703: 
        !          1704:   if (ifa->next_hello > (current_time() + new->hello_interval))
        !          1705:     ifa->next_hello = current_time() + (random() % new->hello_interval);
        !          1706: 
        !          1707:   if (ifa->next_regular > (current_time() + new->update_interval))
        !          1708:     ifa->next_regular = current_time() + (random() % new->update_interval);
        !          1709: 
        !          1710:   if ((new->tx_length != old->tx_length) || (new->rx_buffer != old->rx_buffer))
        !          1711:     babel_iface_update_buffers(ifa);
        !          1712: 
        !          1713:   if (new->check_link != old->check_link)
        !          1714:     babel_iface_update_state(ifa);
        !          1715: 
        !          1716:   if (ifa->up)
        !          1717:     babel_iface_kick_timer(ifa);
        !          1718: 
        !          1719:   return 1;
        !          1720: }
        !          1721: 
        !          1722: static void
        !          1723: babel_reconfigure_ifaces(struct babel_proto *p, struct babel_config *cf)
        !          1724: {
        !          1725:   struct iface *iface;
        !          1726: 
        !          1727:   WALK_LIST(iface, iface_list)
        !          1728:   {
        !          1729:     if (!(iface->flags & IF_UP))
        !          1730:       continue;
        !          1731: 
        !          1732:     /* Ignore non-multicast ifaces */
        !          1733:     if (!(iface->flags & IF_MULTICAST))
        !          1734:       continue;
        !          1735: 
        !          1736:     /* Ignore ifaces without link-local address */
        !          1737:     if (!iface->llv6)
        !          1738:       continue;
        !          1739: 
        !          1740:     struct babel_iface *ifa = babel_find_iface(p, iface);
        !          1741:     struct babel_iface_config *ic = (void *) iface_patt_find(&cf->iface_list, iface, NULL);
        !          1742: 
        !          1743:     if (ifa && ic)
        !          1744:     {
        !          1745:       if (babel_reconfigure_iface(p, ifa, ic))
        !          1746:        continue;
        !          1747: 
        !          1748:       /* Hard restart */
        !          1749:       log(L_INFO "%s: Restarting interface %s", p->p.name, ifa->iface->name);
        !          1750:       babel_remove_iface(p, ifa);
        !          1751:       babel_add_iface(p, iface, ic);
        !          1752:     }
        !          1753: 
        !          1754:     if (ifa && !ic)
        !          1755:       babel_remove_iface(p, ifa);
        !          1756: 
        !          1757:     if (!ifa && ic)
        !          1758:       babel_add_iface(p, iface, ic);
        !          1759:   }
        !          1760: }
        !          1761: 
        !          1762: 
        !          1763: /*
        !          1764:  *     Debugging and info output functions
        !          1765:  */
        !          1766: 
        !          1767: static void
        !          1768: babel_dump_source(struct babel_source *s)
        !          1769: {
        !          1770:   debug("Source router_id %lR seqno %d metric %d expires %t\n",
        !          1771:        s->router_id, s->seqno, s->metric,
        !          1772:        s->expires ? s->expires - current_time() : 0);
        !          1773: }
        !          1774: 
        !          1775: static void
        !          1776: babel_dump_route(struct babel_route *r)
        !          1777: {
        !          1778:   debug("Route neigh %I if %s seqno %d metric %d/%d router_id %lR expires %t\n",
        !          1779:        r->neigh->addr, r->neigh->ifa->ifname, r->seqno, r->advert_metric, r->metric,
        !          1780:        r->router_id, r->expires ? r->expires - current_time() : 0);
        !          1781: }
        !          1782: 
        !          1783: static void
        !          1784: babel_dump_entry(struct babel_entry *e)
        !          1785: {
        !          1786:   struct babel_source *s;
        !          1787:   struct babel_route *r;
        !          1788: 
        !          1789:   debug("Babel: Entry %N:\n", e->n.addr);
        !          1790: 
        !          1791:   WALK_LIST(s,e->sources)
        !          1792:   { debug(" "); babel_dump_source(s); }
        !          1793: 
        !          1794:   WALK_LIST(r,e->routes)
        !          1795:   {
        !          1796:     debug(" ");
        !          1797:     if (r == e->selected) debug("*");
        !          1798:     babel_dump_route(r);
        !          1799:   }
        !          1800: }
        !          1801: 
        !          1802: static void
        !          1803: babel_dump_neighbor(struct babel_neighbor *n)
        !          1804: {
        !          1805:   debug("Neighbor %I txcost %d hello_map %x next seqno %d expires %t/%t\n",
        !          1806:        n->addr, n->txcost, n->hello_map, n->next_hello_seqno,
        !          1807:        n->hello_expiry ? n->hello_expiry - current_time() : 0,
        !          1808:         n->ihu_expiry ? n->ihu_expiry - current_time() : 0);
        !          1809: }
        !          1810: 
        !          1811: static void
        !          1812: babel_dump_iface(struct babel_iface *ifa)
        !          1813: {
        !          1814:   struct babel_neighbor *n;
        !          1815: 
        !          1816:   debug("Babel: Interface %s addr %I rxcost %d type %d hello seqno %d intervals %t %t",
        !          1817:        ifa->ifname, ifa->addr, ifa->cf->rxcost, ifa->cf->type, ifa->hello_seqno,
        !          1818:        ifa->cf->hello_interval, ifa->cf->update_interval);
        !          1819:   debug(" next hop v4 %I next hop v6 %I\n", ifa->next_hop_ip4, ifa->next_hop_ip6);
        !          1820: 
        !          1821:   WALK_LIST(n, ifa->neigh_list)
        !          1822:   { debug(" "); babel_dump_neighbor(n); }
        !          1823: }
        !          1824: 
        !          1825: static void
        !          1826: babel_dump(struct proto *P)
        !          1827: {
        !          1828:   struct babel_proto *p = (struct babel_proto *) P;
        !          1829:   struct babel_iface *ifa;
        !          1830: 
        !          1831:   debug("Babel: router id %lR update seqno %d\n", p->router_id, p->update_seqno);
        !          1832: 
        !          1833:   WALK_LIST(ifa, p->interfaces)
        !          1834:     babel_dump_iface(ifa);
        !          1835: 
        !          1836:   FIB_WALK(&p->ip4_rtable, struct babel_entry, e)
        !          1837:   {
        !          1838:     babel_dump_entry(e);
        !          1839:   }
        !          1840:   FIB_WALK_END;
        !          1841:   FIB_WALK(&p->ip6_rtable, struct babel_entry, e)
        !          1842:   {
        !          1843:     babel_dump_entry(e);
        !          1844:   }
        !          1845:   FIB_WALK_END;
        !          1846: }
        !          1847: 
        !          1848: static void
        !          1849: babel_get_route_info(rte *rte, byte *buf)
        !          1850: {
        !          1851:   buf += bsprintf(buf, " (%d/%d) [%lR]", rte->pref, rte->u.babel.metric, rte->u.babel.router_id);
        !          1852: }
        !          1853: 
        !          1854: static int
        !          1855: babel_get_attr(eattr *a, byte *buf, int buflen UNUSED)
        !          1856: {
        !          1857:   switch (a->id)
        !          1858:   {
        !          1859:   case EA_BABEL_METRIC:
        !          1860:     bsprintf(buf, "metric: %d", a->u.data);
        !          1861:     return GA_FULL;
        !          1862: 
        !          1863:   case EA_BABEL_ROUTER_ID:
        !          1864:   {
        !          1865:     u64 rid = 0;
        !          1866:     memcpy(&rid, a->u.ptr->data, sizeof(u64));
        !          1867:     bsprintf(buf, "router_id: %lR", rid);
        !          1868:     return GA_FULL;
        !          1869:   }
        !          1870: 
        !          1871:   default:
        !          1872:     return GA_UNKNOWN;
        !          1873:   }
        !          1874: }
        !          1875: 
        !          1876: void
        !          1877: babel_show_interfaces(struct proto *P, char *iff)
        !          1878: {
        !          1879:   struct babel_proto *p = (void *) P;
        !          1880:   struct babel_iface *ifa = NULL;
        !          1881:   struct babel_neighbor *nbr = NULL;
        !          1882: 
        !          1883:   if (p->p.proto_state != PS_UP)
        !          1884:   {
        !          1885:     cli_msg(-1023, "%s: is not up", p->p.name);
        !          1886:     cli_msg(0, "");
        !          1887:     return;
        !          1888:   }
        !          1889: 
        !          1890:   cli_msg(-1023, "%s:", p->p.name);
        !          1891:   cli_msg(-1023, "%-10s %-6s %7s %6s %7s %-15s %s",
        !          1892:          "Interface", "State", "RX cost", "Nbrs", "Timer",
        !          1893:          "Next hop (v4)", "Next hop (v6)");
        !          1894: 
        !          1895:   WALK_LIST(ifa, p->interfaces)
        !          1896:   {
        !          1897:     if (iff && !patmatch(iff, ifa->iface->name))
        !          1898:       continue;
        !          1899: 
        !          1900:     int nbrs = 0;
        !          1901:     WALK_LIST(nbr, ifa->neigh_list)
        !          1902:        nbrs++;
        !          1903: 
        !          1904:     btime timer = MIN(ifa->next_regular, ifa->next_hello) - current_time();
        !          1905:     cli_msg(-1023, "%-10s %-6s %7u %6u %7t %-15I %I",
        !          1906:            ifa->iface->name, (ifa->up ? "Up" : "Down"),
        !          1907:            ifa->cf->rxcost, nbrs, MAX(timer, 0),
        !          1908:            ifa->next_hop_ip4, ifa->next_hop_ip6);
        !          1909:   }
        !          1910: 
        !          1911:   cli_msg(0, "");
        !          1912: }
        !          1913: 
        !          1914: void
        !          1915: babel_show_neighbors(struct proto *P, char *iff)
        !          1916: {
        !          1917:   struct babel_proto *p = (void *) P;
        !          1918:   struct babel_iface *ifa = NULL;
        !          1919:   struct babel_neighbor *n = NULL;
        !          1920:   struct babel_route *r = NULL;
        !          1921: 
        !          1922:   if (p->p.proto_state != PS_UP)
        !          1923:   {
        !          1924:     cli_msg(-1024, "%s: is not up", p->p.name);
        !          1925:     cli_msg(0, "");
        !          1926:     return;
        !          1927:   }
        !          1928: 
        !          1929:   cli_msg(-1024, "%s:", p->p.name);
        !          1930:   cli_msg(-1024, "%-25s %-10s %6s %6s %6s %7s",
        !          1931:          "IP address", "Interface", "Metric", "Routes", "Hellos", "Expires");
        !          1932: 
        !          1933:   WALK_LIST(ifa, p->interfaces)
        !          1934:   {
        !          1935:     if (iff && !patmatch(iff, ifa->iface->name))
        !          1936:       continue;
        !          1937: 
        !          1938:     WALK_LIST(n, ifa->neigh_list)
        !          1939:     {
        !          1940:       int rts = 0;
        !          1941:       WALK_LIST(r, n->routes)
        !          1942:         rts++;
        !          1943: 
        !          1944:       uint hellos = u32_popcount(n->hello_map);
        !          1945:       btime timer = n->hello_expiry - current_time();
        !          1946:       cli_msg(-1024, "%-25I %-10s %6u %6u %6u %7t",
        !          1947:              n->addr, ifa->iface->name, n->cost, rts, hellos, MAX(timer, 0));
        !          1948:     }
        !          1949:   }
        !          1950: 
        !          1951:   cli_msg(0, "");
        !          1952: }
        !          1953: 
        !          1954: static void
        !          1955: babel_show_entries_(struct babel_proto *p, struct fib *rtable)
        !          1956: {
        !          1957:   int width = babel_sadr_enabled(p) ? -54 : -24;
        !          1958: 
        !          1959:   FIB_WALK(rtable, struct babel_entry, e)
        !          1960:   {
        !          1961:     struct babel_route *r = NULL;
        !          1962:     uint rts = 0, srcs = 0;
        !          1963:     node *n;
        !          1964: 
        !          1965:     WALK_LIST(n, e->routes)
        !          1966:       rts++;
        !          1967: 
        !          1968:     WALK_LIST(n, e->sources)
        !          1969:       srcs++;
        !          1970: 
        !          1971:     if (e->valid)
        !          1972:       cli_msg(-1025, "%-*N %-23lR %6u %5u %7u %7u", width,
        !          1973:              e->n.addr, e->router_id, e->metric, e->seqno, rts, srcs);
        !          1974:     else if (r = e->selected)
        !          1975:       cli_msg(-1025, "%-*N %-23lR %6u %5u %7u %7u", width,
        !          1976:              e->n.addr, r->router_id, r->metric, r->seqno, rts, srcs);
        !          1977:     else
        !          1978:       cli_msg(-1025, "%-*N %-23s %6s %5s %7u %7u", width,
        !          1979:              e->n.addr, "<none>", "-", "-", rts, srcs);
        !          1980:   }
        !          1981:   FIB_WALK_END;
        !          1982: }
        !          1983: 
        !          1984: void
        !          1985: babel_show_entries(struct proto *P)
        !          1986: {
        !          1987:   struct babel_proto *p = (void *) P;
        !          1988:   int width = babel_sadr_enabled(p) ? -54 : -24;
        !          1989: 
        !          1990:   if (p->p.proto_state != PS_UP)
        !          1991:   {
        !          1992:     cli_msg(-1025, "%s: is not up", p->p.name);
        !          1993:     cli_msg(0, "");
        !          1994:     return;
        !          1995:   }
        !          1996: 
        !          1997:   cli_msg(-1025, "%s:", p->p.name);
        !          1998:   cli_msg(-1025, "%-*s %-23s %6s %5s %7s %7s", width,
        !          1999:          "Prefix", "Router ID", "Metric", "Seqno", "Routes", "Sources");
        !          2000: 
        !          2001:   babel_show_entries_(p, &p->ip4_rtable);
        !          2002:   babel_show_entries_(p, &p->ip6_rtable);
        !          2003: 
        !          2004:   cli_msg(0, "");
        !          2005: }
        !          2006: 
        !          2007: static void
        !          2008: babel_show_routes_(struct babel_proto *p, struct fib *rtable)
        !          2009: {
        !          2010:   int width = babel_sadr_enabled(p) ? -54 : -24;
        !          2011: 
        !          2012:   FIB_WALK(rtable, struct babel_entry, e)
        !          2013:   {
        !          2014:     struct babel_route *r;
        !          2015:     WALK_LIST(r, e->routes)
        !          2016:     {
        !          2017:       char c = (r == e->selected) ? '*' : (r->feasible ? '+' : ' ');
        !          2018:       btime time = r->expires ? r->expires - current_time() : 0;
        !          2019:       cli_msg(-1025, "%-*N %-25I %-10s %5u %c %5u %7t", width,
        !          2020:              e->n.addr, r->next_hop, r->neigh->ifa->ifname,
        !          2021:              r->metric, c, r->seqno, MAX(time, 0));
        !          2022:     }
        !          2023:   }
        !          2024:   FIB_WALK_END;
        !          2025: }
        !          2026: 
        !          2027: void
        !          2028: babel_show_routes(struct proto *P)
        !          2029: {
        !          2030:   struct babel_proto *p = (void *) P;
        !          2031:   int width = babel_sadr_enabled(p) ? -54 : -24;
        !          2032: 
        !          2033:   if (p->p.proto_state != PS_UP)
        !          2034:   {
        !          2035:     cli_msg(-1025, "%s: is not up", p->p.name);
        !          2036:     cli_msg(0, "");
        !          2037:     return;
        !          2038:   }
        !          2039: 
        !          2040:   cli_msg(-1025, "%s:", p->p.name);
        !          2041:   cli_msg(-1025, "%-*s %-25s %-9s %6s F %5s %7s", width,
        !          2042:          "Prefix", "Nexthop", "Interface", "Metric", "Seqno", "Expires");
        !          2043: 
        !          2044:   babel_show_routes_(p, &p->ip4_rtable);
        !          2045:   babel_show_routes_(p, &p->ip6_rtable);
        !          2046: 
        !          2047:   cli_msg(0, "");
        !          2048: }
        !          2049: 
        !          2050: 
        !          2051: /*
        !          2052:  *     Babel protocol glue
        !          2053:  */
        !          2054: 
        !          2055: /**
        !          2056:  * babel_timer - global timer hook
        !          2057:  * @t: Timer
        !          2058:  *
        !          2059:  * This function is called by the global protocol instance timer and handles
        !          2060:  * expiration of routes and neighbours as well as pruning of the seqno request
        !          2061:  * cache.
        !          2062:  */
        !          2063: static void
        !          2064: babel_timer(timer *t)
        !          2065: {
        !          2066:   struct babel_proto *p = t->data;
        !          2067: 
        !          2068:   babel_expire_routes(p);
        !          2069:   babel_expire_neighbors(p);
        !          2070: }
        !          2071: 
        !          2072: static inline void
        !          2073: babel_kick_timer(struct babel_proto *p)
        !          2074: {
        !          2075:   if (p->timer->expires > (current_time() + 100 MS))
        !          2076:     tm_start(p->timer, 100 MS);
        !          2077: }
        !          2078: 
        !          2079: 
        !          2080: static int
        !          2081: babel_preexport(struct proto *P, struct rte **new, struct linpool *pool UNUSED)
        !          2082: {
        !          2083:   struct rta *a = (*new)->attrs;
        !          2084: 
        !          2085:   /* Reject our own unreachable routes */
        !          2086:   if ((a->dest == RTD_UNREACHABLE) && (a->src->proto == P))
        !          2087:     return -1;
        !          2088: 
        !          2089:   return 0;
        !          2090: }
        !          2091: 
        !          2092: static void
        !          2093: babel_make_tmp_attrs(struct rte *rt, struct linpool *pool)
        !          2094: {
        !          2095:   struct adata *id = lp_alloc_adata(pool, sizeof(u64));
        !          2096:   memcpy(id->data, &rt->u.babel.router_id, sizeof(u64));
        !          2097: 
        !          2098:   rte_init_tmp_attrs(rt, pool, 2);
        !          2099:   rte_make_tmp_attr(rt, EA_BABEL_METRIC, EAF_TYPE_INT, rt->u.babel.metric);
        !          2100:   rte_make_tmp_attr(rt, EA_BABEL_ROUTER_ID, EAF_TYPE_OPAQUE, (uintptr_t) id);
        !          2101: }
        !          2102: 
        !          2103: static void
        !          2104: babel_store_tmp_attrs(struct rte *rt, struct linpool *pool)
        !          2105: {
        !          2106:   rte_init_tmp_attrs(rt, pool, 2);
        !          2107:   rt->u.babel.metric = rte_store_tmp_attr(rt, EA_BABEL_METRIC);
        !          2108: 
        !          2109:   /* EA_BABEL_ROUTER_ID is read-only, we do not really save the value */
        !          2110:   rte_store_tmp_attr(rt, EA_BABEL_ROUTER_ID);
        !          2111: }
        !          2112: 
        !          2113: /*
        !          2114:  * babel_rt_notify - core tells us about new route (possibly our own),
        !          2115:  * so store it into our data structures.
        !          2116:  */
        !          2117: static void
        !          2118: babel_rt_notify(struct proto *P, struct channel *c UNUSED, struct network *net,
        !          2119:                struct rte *new, struct rte *old UNUSED)
        !          2120: {
        !          2121:   struct babel_proto *p = (void *) P;
        !          2122:   struct babel_entry *e;
        !          2123: 
        !          2124:   if (new)
        !          2125:   {
        !          2126:     /* Update */
        !          2127:     uint internal = (new->attrs->src->proto == P);
        !          2128:     uint rt_seqno = internal ? new->u.babel.seqno : p->update_seqno;
        !          2129:     uint rt_metric = ea_get_int(new->attrs->eattrs, EA_BABEL_METRIC, 0);
        !          2130:     u64 rt_router_id = internal ? new->u.babel.router_id : p->router_id;
        !          2131: 
        !          2132:     if (rt_metric > BABEL_INFINITY)
        !          2133:     {
        !          2134:       log(L_WARN "%s: Invalid babel_metric value %u for route %N",
        !          2135:          p->p.name, rt_metric, net->n.addr);
        !          2136:       rt_metric = BABEL_INFINITY;
        !          2137:     }
        !          2138: 
        !          2139:     e = babel_get_entry(p, net->n.addr);
        !          2140: 
        !          2141:     /* Activate triggered updates */
        !          2142:     if ((e->valid != BABEL_ENTRY_VALID) ||
        !          2143:        (e->router_id != rt_router_id))
        !          2144:     {
        !          2145:       babel_trigger_update(p);
        !          2146:       e->updated = current_time();
        !          2147:     }
        !          2148: 
        !          2149:     e->valid = BABEL_ENTRY_VALID;
        !          2150:     e->seqno = rt_seqno;
        !          2151:     e->metric = rt_metric;
        !          2152:     e->router_id = rt_router_id;
        !          2153:   }
        !          2154:   else
        !          2155:   {
        !          2156:     /* Withdraw */
        !          2157:     e = babel_find_entry(p, net->n.addr);
        !          2158: 
        !          2159:     if (!e || e->valid != BABEL_ENTRY_VALID)
        !          2160:       return;
        !          2161: 
        !          2162:     e->valid = BABEL_ENTRY_STALE;
        !          2163:     e->metric = BABEL_INFINITY;
        !          2164: 
        !          2165:     babel_trigger_update(p);
        !          2166:     e->updated = current_time();
        !          2167:   }
        !          2168: }
        !          2169: 
        !          2170: static int
        !          2171: babel_rte_better(struct rte *new, struct rte *old)
        !          2172: {
        !          2173:   return new->u.babel.metric < old->u.babel.metric;
        !          2174: }
        !          2175: 
        !          2176: static int
        !          2177: babel_rte_same(struct rte *new, struct rte *old)
        !          2178: {
        !          2179:   return ((new->u.babel.seqno == old->u.babel.seqno) &&
        !          2180:          (new->u.babel.metric == old->u.babel.metric) &&
        !          2181:          (new->u.babel.router_id == old->u.babel.router_id));
        !          2182: }
        !          2183: 
        !          2184: 
        !          2185: static void
        !          2186: babel_postconfig(struct proto_config *CF)
        !          2187: {
        !          2188:   struct babel_config *cf = (void *) CF;
        !          2189:   struct channel_config *ip4, *ip6, *ip6_sadr;
        !          2190: 
        !          2191:   ip4 = proto_cf_find_channel(CF, NET_IP4);
        !          2192:   ip6 = proto_cf_find_channel(CF, NET_IP6);
        !          2193:   ip6_sadr = proto_cf_find_channel(CF, NET_IP6_SADR);
        !          2194: 
        !          2195:   if (ip6 && ip6_sadr)
        !          2196:     cf_error("Both ipv6 and ipv6-sadr channels");
        !          2197: 
        !          2198:   cf->ip4_channel = ip4;
        !          2199:   cf->ip6_channel = ip6 ?: ip6_sadr;
        !          2200: }
        !          2201: 
        !          2202: static struct proto *
        !          2203: babel_init(struct proto_config *CF)
        !          2204: {
        !          2205:   struct proto *P = proto_new(CF);
        !          2206:   struct babel_proto *p = (void *) P;
        !          2207:   struct babel_config *cf = (void *) CF;
        !          2208: 
        !          2209:   proto_configure_channel(P, &p->ip4_channel, cf->ip4_channel);
        !          2210:   proto_configure_channel(P, &p->ip6_channel, cf->ip6_channel);
        !          2211: 
        !          2212:   P->if_notify = babel_if_notify;
        !          2213:   P->rt_notify = babel_rt_notify;
        !          2214:   P->preexport = babel_preexport;
        !          2215:   P->make_tmp_attrs = babel_make_tmp_attrs;
        !          2216:   P->store_tmp_attrs = babel_store_tmp_attrs;
        !          2217:   P->rte_better = babel_rte_better;
        !          2218:   P->rte_same = babel_rte_same;
        !          2219: 
        !          2220:   return P;
        !          2221: }
        !          2222: 
        !          2223: static inline void
        !          2224: babel_randomize_router_id(struct babel_proto *p)
        !          2225: {
        !          2226:   p->router_id &= (u64) 0xffffffff;
        !          2227:   p->router_id |= ((u64) random()) << 32;
        !          2228:   TRACE(D_EVENTS, "Randomized router ID to %lR", p->router_id);
        !          2229: }
        !          2230: 
        !          2231: static int
        !          2232: babel_start(struct proto *P)
        !          2233: {
        !          2234:   struct babel_proto *p = (void *) P;
        !          2235:   struct babel_config *cf = (void *) P->cf;
        !          2236:   u8 ip6_type = cf->ip6_channel ? cf->ip6_channel->net_type : NET_IP6;
        !          2237: 
        !          2238:   fib_init(&p->ip4_rtable, P->pool, NET_IP4, sizeof(struct babel_entry),
        !          2239:           OFFSETOF(struct babel_entry, n), 0, babel_init_entry);
        !          2240:   fib_init(&p->ip6_rtable, P->pool, ip6_type, sizeof(struct babel_entry),
        !          2241:           OFFSETOF(struct babel_entry, n), 0, babel_init_entry);
        !          2242: 
        !          2243:   init_list(&p->interfaces);
        !          2244:   p->timer = tm_new_init(P->pool, babel_timer, p, 1 S, 0);
        !          2245:   tm_start(p->timer, 1 S);
        !          2246:   p->update_seqno = 1;
        !          2247:   p->router_id = proto_get_router_id(&cf->c);
        !          2248: 
        !          2249:   if (cf->randomize_router_id)
        !          2250:     babel_randomize_router_id(p);
        !          2251: 
        !          2252:   p->route_slab = sl_new(P->pool, sizeof(struct babel_route));
        !          2253:   p->source_slab = sl_new(P->pool, sizeof(struct babel_source));
        !          2254:   p->msg_slab = sl_new(P->pool, sizeof(struct babel_msg_node));
        !          2255:   p->seqno_slab = sl_new(P->pool, sizeof(struct babel_seqno_request));
        !          2256: 
        !          2257:   p->log_pkt_tbf = (struct tbf){ .rate = 1, .burst = 5 };
        !          2258: 
        !          2259:   return PS_UP;
        !          2260: }
        !          2261: 
        !          2262: static inline void
        !          2263: babel_iface_shutdown(struct babel_iface *ifa)
        !          2264: {
        !          2265:   if (ifa->sk)
        !          2266:   {
        !          2267:     babel_send_wildcard_retraction(ifa);
        !          2268:     babel_send_queue(ifa);
        !          2269:   }
        !          2270: }
        !          2271: 
        !          2272: static int
        !          2273: babel_shutdown(struct proto *P)
        !          2274: {
        !          2275:   struct babel_proto *p = (void *) P;
        !          2276:   struct babel_iface *ifa;
        !          2277: 
        !          2278:   TRACE(D_EVENTS, "Shutdown requested");
        !          2279: 
        !          2280:   WALK_LIST(ifa, p->interfaces)
        !          2281:     babel_iface_shutdown(ifa);
        !          2282: 
        !          2283:   return PS_DOWN;
        !          2284: }
        !          2285: 
        !          2286: static int
        !          2287: babel_reconfigure(struct proto *P, struct proto_config *CF)
        !          2288: {
        !          2289:   struct babel_proto *p = (void *) P;
        !          2290:   struct babel_config *new = (void *) CF;
        !          2291:   u8 ip6_type = new->ip6_channel ? new->ip6_channel->net_type : NET_IP6;
        !          2292: 
        !          2293:   TRACE(D_EVENTS, "Reconfiguring");
        !          2294: 
        !          2295:   if (p->ip6_rtable.addr_type != ip6_type)
        !          2296:     return 0;
        !          2297: 
        !          2298:   if (!proto_configure_channel(P, &p->ip4_channel, new->ip4_channel) ||
        !          2299:       !proto_configure_channel(P, &p->ip6_channel, new->ip6_channel))
        !          2300:     return 0;
        !          2301: 
        !          2302:   p->p.cf = CF;
        !          2303:   babel_reconfigure_ifaces(p, new);
        !          2304: 
        !          2305:   babel_trigger_update(p);
        !          2306:   babel_kick_timer(p);
        !          2307: 
        !          2308:   return 1;
        !          2309: }
        !          2310: 
        !          2311: 
        !          2312: struct protocol proto_babel = {
        !          2313:   .name =              "Babel",
        !          2314:   .template =          "babel%d",
        !          2315:   .class =             PROTOCOL_BABEL,
        !          2316:   .preference =                DEF_PREF_BABEL,
        !          2317:   .channel_mask =      NB_IP | NB_IP6_SADR,
        !          2318:   .proto_size =                sizeof(struct babel_proto),
        !          2319:   .config_size =       sizeof(struct babel_config),
        !          2320:   .postconfig =                babel_postconfig,
        !          2321:   .init =              babel_init,
        !          2322:   .dump =              babel_dump,
        !          2323:   .start =             babel_start,
        !          2324:   .shutdown =          babel_shutdown,
        !          2325:   .reconfigure =       babel_reconfigure,
        !          2326:   .get_route_info =    babel_get_route_info,
        !          2327:   .get_attr =          babel_get_attr
        !          2328: };

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