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