File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / babeld / route.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Oct 9 09:22:28 2012 UTC (12 years, 5 months ago) by misho
Branches: quagga, MAIN
CVS tags: v0_99_22p0, v0_99_22, v0_99_21, HEAD
quagga

    1: /*  
    2:  *  This file is free software: you may copy, redistribute and/or modify it  
    3:  *  under the terms of the GNU General Public License as published by the  
    4:  *  Free Software Foundation, either version 2 of the License, or (at your  
    5:  *  option) any later version.  
    6:  *  
    7:  *  This file is distributed in the hope that it will be useful, but  
    8:  *  WITHOUT ANY WARRANTY; without even the implied warranty of  
    9:  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  
   10:  *  General Public License for more details.  
   11:  *  
   12:  *  You should have received a copy of the GNU General Public License  
   13:  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.  
   14:  *  
   15:  * This file incorporates work covered by the following copyright and  
   16:  * permission notice:  
   17:  *  
   18: Copyright (c) 2007, 2008 by Juliusz Chroboczek
   19: Copyright 2011 by Matthieu Boutier and Juliusz Chroboczek
   20: 
   21: Permission is hereby granted, free of charge, to any person obtaining a copy
   22: of this software and associated documentation files (the "Software"), to deal
   23: in the Software without restriction, including without limitation the rights
   24: to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   25: copies of the Software, and to permit persons to whom the Software is
   26: furnished to do so, subject to the following conditions:
   27: 
   28: The above copyright notice and this permission notice shall be included in
   29: all copies or substantial portions of the Software.
   30: 
   31: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   32: IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   33: FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
   34: AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   35: LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   36: OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   37: THE SOFTWARE.
   38: */
   39: 
   40: #include <zebra.h>
   41: #include "if.h"
   42: 
   43: #include "babeld.h"
   44: #include "util.h"
   45: #include "kernel.h"
   46: #include "babel_interface.h"
   47: #include "source.h"
   48: #include "neighbour.h"
   49: #include "route.h"
   50: #include "xroute.h"
   51: #include "message.h"
   52: #include "resend.h"
   53: 
   54: static void consider_route(struct babel_route *route);
   55: 
   56: struct babel_route **routes = NULL;
   57: static int route_slots = 0, max_route_slots = 0;
   58: int kernel_metric = 0;
   59: int allow_duplicates = -1;
   60: int diversity_kind = DIVERSITY_NONE;
   61: int diversity_factor = 256;     /* in units of 1/256 */
   62: int keep_unfeasible = 0;
   63: 
   64: /* We maintain a list of "slots", ordered by prefix.  Every slot
   65:    contains a linked list of the routes to this prefix, with the
   66:    installed route, if any, at the head of the list. */
   67: 
   68: static int
   69: route_compare(const unsigned char *prefix, unsigned char plen,
   70:                struct babel_route *route)
   71: {
   72:     int i = memcmp(prefix, route->src->prefix, 16);
   73:     if(i != 0)
   74:         return i;
   75: 
   76:     if(plen < route->src->plen)
   77:         return -1;
   78:     else if(plen > route->src->plen)
   79:         return 1;
   80:     else
   81:         return 0;
   82: }
   83: 
   84: /* Performs binary search, returns -1 in case of failure.  In the latter
   85:    case, new_return is the place where to insert the new element. */
   86: 
   87: static int
   88: find_route_slot(const unsigned char *prefix, unsigned char plen,
   89:                 int *new_return)
   90: {
   91:     int p, m, g, c;
   92: 
   93:     if(route_slots < 1) {
   94:         if(new_return)
   95:             *new_return = 0;
   96:         return -1;
   97:     }
   98: 
   99:     p = 0; g = route_slots - 1;
  100: 
  101:     do {
  102:         m = (p + g) / 2;
  103:         c = route_compare(prefix, plen, routes[m]);
  104:         if(c == 0)
  105:             return m;
  106:         else if(c < 0)
  107:             g = m - 1;
  108:         else
  109:             p = m + 1;
  110:     } while(p <= g);
  111: 
  112:     if(new_return)
  113:         *new_return = p;
  114: 
  115:     return -1;
  116: }
  117: 
  118: struct babel_route *
  119: find_route(const unsigned char *prefix, unsigned char plen,
  120:            struct neighbour *neigh, const unsigned char *nexthop)
  121: {
  122:     struct babel_route *route;
  123:     int i = find_route_slot(prefix, plen, NULL);
  124: 
  125:     if(i < 0)
  126:         return NULL;
  127: 
  128:     route = routes[i];
  129: 
  130:     while(route) {
  131:         if(route->neigh == neigh && memcmp(route->nexthop, nexthop, 16) == 0)
  132:             return route;
  133:         route = route->next;
  134:     }
  135: 
  136:     return NULL;
  137: }
  138: 
  139: struct babel_route *
  140: find_installed_route(const unsigned char *prefix, unsigned char plen)
  141: {
  142:     int i = find_route_slot(prefix, plen, NULL);
  143: 
  144:     if(i >= 0 && routes[i]->installed)
  145:         return routes[i];
  146: 
  147:     return NULL;
  148: }
  149: 
  150: /* Returns an overestimate of the number of installed routes. */
  151: int
  152: installed_routes_estimate(void)
  153: {
  154:     return route_slots;
  155: }
  156: 
  157: static int
  158: resize_route_table(int new_slots)
  159: {
  160:     struct babel_route **new_routes;
  161:     assert(new_slots >= route_slots);
  162: 
  163:     if(new_slots == 0) {
  164:         new_routes = NULL;
  165:         free(routes);
  166:     } else {
  167:         new_routes = realloc(routes, new_slots * sizeof(struct babel_route*));
  168:         if(new_routes == NULL)
  169:             return -1;
  170:     }
  171: 
  172:     max_route_slots = new_slots;
  173:     routes = new_routes;
  174:     return 1;
  175: }
  176: 
  177: /* Insert a route into the table.  If successful, retains the route.
  178:    On failure, caller must free the route. */
  179: static struct babel_route *
  180: insert_route(struct babel_route *route)
  181: {
  182:     int i, n;
  183: 
  184:     assert(!route->installed);
  185: 
  186:     i = find_route_slot(route->src->prefix, route->src->plen, &n);
  187: 
  188:     if(i < 0) {
  189:         if(route_slots >= max_route_slots)
  190:             resize_route_table(max_route_slots < 1 ? 8 : 2 * max_route_slots);
  191:         if(route_slots >= max_route_slots)
  192:             return NULL;
  193:         route->next = NULL;
  194:         if(n < route_slots)
  195:             memmove(routes + n + 1, routes + n,
  196:                     (route_slots - n) * sizeof(struct babel_route*));
  197:         route_slots++;
  198:         routes[n] = route;
  199:     } else {
  200:         struct babel_route *r;
  201:         r = routes[i];
  202:         while(r->next)
  203:             r = r->next;
  204:         r->next = route;
  205:         route->next = NULL;
  206:     }
  207: 
  208:     return route;
  209: }
  210: 
  211: void
  212: flush_route(struct babel_route *route)
  213: {
  214:     int i;
  215:     struct source *src;
  216:     unsigned oldmetric;
  217:     int lost = 0;
  218: 
  219:     oldmetric = route_metric(route);
  220:     src = route->src;
  221: 
  222:     if(route->installed) {
  223:         uninstall_route(route);
  224:         lost = 1;
  225:     }
  226: 
  227:     i = find_route_slot(route->src->prefix, route->src->plen, NULL);
  228:     assert(i >= 0 && i < route_slots);
  229: 
  230:     if(route == routes[i]) {
  231:         routes[i] = route->next;
  232:         route->next = NULL;
  233:         free(route);
  234: 
  235:         if(routes[i] == NULL) {
  236:             if(i < route_slots - 1)
  237:                 memmove(routes + i, routes + i + 1,
  238:                         (route_slots - i - 1) * sizeof(struct babel_route*));
  239:             routes[route_slots - 1] = NULL;
  240:             route_slots--;
  241:         }
  242: 
  243:         if(route_slots == 0)
  244:             resize_route_table(0);
  245:         else if(max_route_slots > 8 && route_slots < max_route_slots / 4)
  246:             resize_route_table(max_route_slots / 2);
  247:     } else {
  248:         struct babel_route *r = routes[i];
  249:         while(r->next != route)
  250:             r = r->next;
  251:         r->next = route->next;
  252:         route->next = NULL;
  253:         free(route);
  254:     }
  255: 
  256:     if(lost)
  257:         route_lost(src, oldmetric);
  258: 
  259:     release_source(src);
  260: }
  261: 
  262: void
  263: flush_all_routes()
  264: {
  265:     int i;
  266: 
  267:     /* Start from the end, to avoid shifting the table. */
  268:     i = route_slots - 1;
  269:     while(i >= 0) {
  270:         while(i < route_slots) {
  271:         /* Uninstall first, to avoid calling route_lost. */
  272:             if(routes[i]->installed)
  273:                 uninstall_route(routes[0]);
  274:             flush_route(routes[i]);
  275:         }
  276:         i--;
  277:     }
  278: 
  279:     check_sources_released();
  280: }
  281: 
  282: void
  283: flush_neighbour_routes(struct neighbour *neigh)
  284: {
  285:     int i;
  286: 
  287:     i = 0;
  288:     while(i < route_slots) {
  289:         struct babel_route *r;
  290:         r = routes[i];
  291:         while(r) {
  292:             if(r->neigh == neigh) {
  293:                 flush_route(r);
  294:                 goto again;
  295:             }
  296:             r = r->next;
  297:         }
  298:         i++;
  299:     again:
  300:         ;
  301:     }
  302: }
  303: 
  304: void
  305: flush_interface_routes(struct interface *ifp, int v4only)
  306: {
  307:     int i;
  308: 
  309:     i = 0;
  310:     while(i < route_slots) {
  311:         struct babel_route *r;
  312:         r = routes[i];
  313:         while(r) {
  314:             if(r->neigh->ifp == ifp &&
  315:                (!v4only || v4mapped(r->nexthop))) {
  316:                 flush_route(r);
  317:                 goto again;
  318:             }
  319:             r = r->next;
  320:         }
  321:         i++;
  322:     again:
  323:         ;
  324:     }
  325: }
  326: 
  327: /* Iterate a function over all routes. */
  328: void
  329: for_all_routes(void (*f)(struct babel_route*, void*), void *closure)
  330: {
  331:     int i;
  332: 
  333:     for(i = 0; i < route_slots; i++) {
  334:         struct babel_route *r = routes[i];
  335:         while(r) {
  336:             (*f)(r, closure);
  337:             r = r->next;
  338:         }
  339:     }
  340: }
  341: 
  342: void
  343: for_all_installed_routes(void (*f)(struct babel_route*, void*), void *closure)
  344: {
  345:     int i;
  346: 
  347:     for(i = 0; i < route_slots; i++) {
  348:         if(routes[i]->installed)
  349:             (*f)(routes[i], closure);
  350:     }
  351: }
  352: 
  353: static int
  354: metric_to_kernel(int metric)
  355: {
  356:     return metric < INFINITY ? kernel_metric : KERNEL_INFINITY;
  357: }
  358: 
  359: /* This is used to maintain the invariant that the installed route is at
  360:    the head of the list. */
  361: static void
  362: move_installed_route(struct babel_route *route, int i)
  363: {
  364:     assert(i >= 0 && i < route_slots);
  365:     assert(route->installed);
  366: 
  367:     if(route != routes[i]) {
  368:         struct babel_route *r = routes[i];
  369:         while(r->next != route)
  370:             r = r->next;
  371:         r->next = route->next;
  372:         route->next = routes[i];
  373:         routes[i] = route;
  374:     }
  375: }
  376: 
  377: void
  378: install_route(struct babel_route *route)
  379: {
  380:     int i, rc;
  381: 
  382:     if(route->installed)
  383:         return;
  384: 
  385:     if(!route_feasible(route))
  386:         zlog_err("WARNING: installing unfeasible route "
  387:                  "(this shouldn't happen).");
  388: 
  389:     i = find_route_slot(route->src->prefix, route->src->plen, NULL);
  390:     assert(i >= 0 && i < route_slots);
  391: 
  392:     if(routes[i] != route && routes[i]->installed) {
  393:         fprintf(stderr, "WARNING: attempting to install duplicate route "
  394:                 "(this shouldn't happen).");
  395:         return;
  396:     }
  397: 
  398:     rc = kernel_route(ROUTE_ADD, route->src->prefix, route->src->plen,
  399:                       route->nexthop,
  400:                       route->neigh->ifp->ifindex,
  401:                       metric_to_kernel(route_metric(route)), NULL, 0, 0);
  402:     if(rc < 0) {
  403:         int save = errno;
  404:         zlog_err("kernel_route(ADD): %s", safe_strerror(errno));
  405:         if(save != EEXIST)
  406:             return;
  407:     }
  408:     route->installed = 1;
  409:     move_installed_route(route, i);
  410: 
  411: }
  412: 
  413: void
  414: uninstall_route(struct babel_route *route)
  415: {
  416:     int rc;
  417: 
  418:     if(!route->installed)
  419:         return;
  420: 
  421:     rc = kernel_route(ROUTE_FLUSH, route->src->prefix, route->src->plen,
  422:                       route->nexthop,
  423:                       route->neigh->ifp->ifindex,
  424:                       metric_to_kernel(route_metric(route)), NULL, 0, 0);
  425:     if(rc < 0)
  426:         zlog_err("kernel_route(FLUSH): %s", safe_strerror(errno));
  427: 
  428:     route->installed = 0;
  429: }
  430: 
  431: /* This is equivalent to uninstall_route followed with install_route,
  432:    but without the race condition.  The destination of both routes
  433:    must be the same. */
  434: 
  435: static void
  436: switch_routes(struct babel_route *old, struct babel_route *new)
  437: {
  438:     int rc;
  439: 
  440:     if(!old) {
  441:         install_route(new);
  442:         return;
  443:     }
  444: 
  445:     if(!old->installed)
  446:         return;
  447: 
  448:     if(!route_feasible(new))
  449:         zlog_err("WARNING: switching to unfeasible route "
  450:                  "(this shouldn't happen).");
  451: 
  452:     rc = kernel_route(ROUTE_MODIFY, old->src->prefix, old->src->plen,
  453:                       old->nexthop, old->neigh->ifp->ifindex,
  454:                       metric_to_kernel(route_metric(old)),
  455:                       new->nexthop, new->neigh->ifp->ifindex,
  456:                       metric_to_kernel(route_metric(new)));
  457:     if(rc < 0) {
  458:         zlog_err("kernel_route(MODIFY): %s", safe_strerror(errno));
  459:         return;
  460:     }
  461: 
  462:     old->installed = 0;
  463:     new->installed = 1;
  464:     move_installed_route(new, find_route_slot(new->src->prefix, new->src->plen,
  465:                                               NULL));
  466: }
  467: 
  468: static void
  469: change_route_metric(struct babel_route *route,
  470:                     unsigned refmetric, unsigned cost, unsigned add)
  471: {
  472:     int old, new;
  473:     int newmetric = MIN(refmetric + cost + add, INFINITY);
  474: 
  475:     old = metric_to_kernel(route_metric(route));
  476:     new = metric_to_kernel(newmetric);
  477: 
  478:     if(route->installed && old != new) {
  479:         int rc;
  480:         rc = kernel_route(ROUTE_MODIFY, route->src->prefix, route->src->plen,
  481:                           route->nexthop, route->neigh->ifp->ifindex,
  482:                           old,
  483:                           route->nexthop, route->neigh->ifp->ifindex,
  484:                           new);
  485:         if(rc < 0) {
  486:             zlog_err("kernel_route(MODIFY metric): %s", safe_strerror(errno));
  487:             return;
  488:         }
  489:     }
  490: 
  491:     route->refmetric = refmetric;
  492:     route->cost = cost;
  493:     route->add_metric = add;
  494: }
  495: 
  496: static void
  497: retract_route(struct babel_route *route)
  498: {
  499:     change_route_metric(route, INFINITY, INFINITY, 0);
  500: }
  501: 
  502: int
  503: route_feasible(struct babel_route *route)
  504: {
  505:     return update_feasible(route->src, route->seqno, route->refmetric);
  506: }
  507: 
  508: int
  509: route_old(struct babel_route *route)
  510: {
  511:     return route->time < babel_now.tv_sec - route->hold_time * 7 / 8;
  512: }
  513: 
  514: int
  515: route_expired(struct babel_route *route)
  516: {
  517:     return route->time < babel_now.tv_sec - route->hold_time;
  518: }
  519: 
  520: static int
  521: channels_interfere(int ch1, int ch2)
  522: {
  523:     if(ch1 == BABEL_IF_CHANNEL_NONINTERFERING
  524:        || ch2 == BABEL_IF_CHANNEL_NONINTERFERING)
  525:         return 0;
  526:     if(ch1 == BABEL_IF_CHANNEL_INTERFERING
  527:        || ch2 == BABEL_IF_CHANNEL_INTERFERING)
  528:         return 1;
  529:     return ch1 == ch2;
  530: }
  531: 
  532: int
  533: route_interferes(struct babel_route *route, struct interface *ifp)
  534: {
  535:     struct babel_interface *babel_ifp = NULL;
  536:     switch(diversity_kind) {
  537:     case DIVERSITY_NONE:
  538:         return 1;
  539:     case DIVERSITY_INTERFACE_1:
  540:         return route->neigh->ifp == ifp;
  541:     case DIVERSITY_CHANNEL_1:
  542:     case DIVERSITY_CHANNEL:
  543:         if(route->neigh->ifp == ifp)
  544:             return 1;
  545:         babel_ifp = babel_get_if_nfo(ifp);
  546:         if(channels_interfere(babel_ifp->channel,
  547:                               babel_get_if_nfo(route->neigh->ifp)->channel))
  548:             return 1;
  549:         if(diversity_kind == DIVERSITY_CHANNEL) {
  550:             int i;
  551:             for(i = 0; i < DIVERSITY_HOPS; i++) {
  552:                 if(route->channels[i] == 0)
  553:                     break;
  554:                 if(channels_interfere(babel_ifp->channel, route->channels[i]))
  555:                     return 1;
  556:             }
  557:         }
  558:         return 0;
  559:     default:
  560:         fprintf(stderr, "Unknown kind of diversity.\n");
  561:         return 1;
  562:     }
  563: }
  564: 
  565: int
  566: update_feasible(struct source *src,
  567:                 unsigned short seqno, unsigned short refmetric)
  568: {
  569:     if(src == NULL)
  570:         return 1;
  571: 
  572:     if(src->time < babel_now.tv_sec - SOURCE_GC_TIME)
  573:         /* Never mind what is probably stale data */
  574:         return 1;
  575: 
  576:     if(refmetric >= INFINITY)
  577:         /* Retractions are always feasible */
  578:         return 1;
  579: 
  580:     return (seqno_compare(seqno, src->seqno) > 0 ||
  581:             (src->seqno == seqno && refmetric < src->metric));
  582: }
  583: 
  584: /* This returns the feasible route with the smallest metric. */
  585: struct babel_route *
  586: find_best_route(const unsigned char *prefix, unsigned char plen, int feasible,
  587:                 struct neighbour *exclude)
  588: {
  589:     struct babel_route *route = NULL, *r = NULL;
  590:     int i = find_route_slot(prefix, plen, NULL);
  591: 
  592:     if(i < 0)
  593:         return NULL;
  594: 
  595:     route = routes[i];
  596: 
  597:     r = route->next;
  598:     while(r) {
  599:         if(!route_expired(r) &&
  600:            (!feasible || route_feasible(r)) &&
  601:            (!exclude || r->neigh != exclude) &&
  602:            (route_metric(r) < route_metric(route)))
  603:             route = r;
  604:         r = r->next;
  605:     }
  606:     return route;
  607: }
  608: 
  609: void
  610: update_route_metric(struct babel_route *route)
  611: {
  612:     int oldmetric = route_metric(route);
  613: 
  614:     if(route_expired(route)) {
  615:         if(route->refmetric < INFINITY) {
  616:             route->seqno = seqno_plus(route->src->seqno, 1);
  617:             retract_route(route);
  618:             if(oldmetric < INFINITY)
  619:                 route_changed(route, route->src, oldmetric);
  620:         }
  621:     } else {
  622:         struct neighbour *neigh = route->neigh;
  623:         int add_metric = input_filter(route->src->id,
  624:                                       route->src->prefix, route->src->plen,
  625:                                       neigh->address,
  626:                                       neigh->ifp->ifindex);
  627:         change_route_metric(route, route->refmetric,
  628:                             neighbour_cost(route->neigh), add_metric);
  629:         if(route_metric(route) != oldmetric)
  630:             route_changed(route, route->src, oldmetric);
  631:     }
  632: }
  633: 
  634: /* Called whenever a neighbour's cost changes, to update the metric of
  635:    all routes through that neighbour.  Calls local_notify_neighbour. */
  636: void
  637: update_neighbour_metric(struct neighbour *neigh, int changed)
  638: {
  639: 
  640:     if(changed) {
  641:         int i;
  642: 
  643:         for(i = 0; i < route_slots; i++) {
  644:             struct babel_route *r = routes[i];
  645:             while(r) {
  646:                 if(r->neigh == neigh)
  647:                     update_route_metric(r);
  648:                 r = r->next;
  649:             }
  650:         }
  651:     }
  652: }
  653: 
  654: void
  655: update_interface_metric(struct interface *ifp)
  656: {
  657:     int i;
  658: 
  659:     for(i = 0; i < route_slots; i++) {
  660:         struct babel_route *r = routes[i];
  661:         while(r) {
  662:             if(r->neigh->ifp == ifp)
  663:                 update_route_metric(r);
  664:             r = r->next;
  665:         }
  666:     }
  667: }
  668: 
  669: /* This is called whenever we receive an update. */
  670: struct babel_route *
  671: update_route(const unsigned char *router_id,
  672:              const unsigned char *prefix, unsigned char plen,
  673:              unsigned short seqno, unsigned short refmetric,
  674:              unsigned short interval,
  675:              struct neighbour *neigh, const unsigned char *nexthop,
  676:              const unsigned char *channels, int channels_len)
  677: {
  678:     struct babel_route *route;
  679:     struct source *src;
  680:     int metric, feasible;
  681:     int add_metric;
  682:     int hold_time = MAX((4 * interval) / 100 + interval / 50, 15);
  683: 
  684:     if(memcmp(router_id, myid, 8) == 0)
  685:         return NULL;
  686: 
  687:     if(martian_prefix(prefix, plen)) {
  688:         zlog_err("Rejecting martian route to %s through %s.",
  689:                  format_prefix(prefix, plen), format_address(router_id));
  690:         return NULL;
  691:     }
  692: 
  693:     add_metric = input_filter(router_id, prefix, plen,
  694:                               neigh->address, neigh->ifp->ifindex);
  695:     if(add_metric >= INFINITY)
  696:         return NULL;
  697: 
  698:     route = find_route(prefix, plen, neigh, nexthop);
  699: 
  700:     if(route && memcmp(route->src->id, router_id, 8) == 0)
  701:         /* Avoid scanning the source table. */
  702:         src = route->src;
  703:     else
  704:         src = find_source(router_id, prefix, plen, 1, seqno);
  705: 
  706:     if(src == NULL)
  707:         return NULL;
  708: 
  709:     feasible = update_feasible(src, seqno, refmetric);
  710:     metric = MIN((int)refmetric + neighbour_cost(neigh) + add_metric, INFINITY);
  711: 
  712:     if(route) {
  713:         struct source *oldsrc;
  714:         unsigned short oldmetric;
  715:         int lost = 0;
  716: 
  717:         oldsrc = route->src;
  718:         oldmetric = route_metric(route);
  719: 
  720:         /* If a successor switches sources, we must accept his update even
  721:            if it makes a route unfeasible in order to break any routing loops
  722:            in a timely manner.  If the source remains the same, we ignore
  723:            the update. */
  724:         if(!feasible && route->installed) {
  725:             debugf(BABEL_DEBUG_COMMON,"Unfeasible update for installed route to %s "
  726:                    "(%s %d %d -> %s %d %d).",
  727:                    format_prefix(src->prefix, src->plen),
  728:                    format_address(route->src->id),
  729:                    route->seqno, route->refmetric,
  730:                    format_address(src->id), seqno, refmetric);
  731:             if(src != route->src) {
  732:                 uninstall_route(route);
  733:                 lost = 1;
  734:             }
  735:         }
  736: 
  737:         route->src = retain_source(src);
  738:         if((feasible || keep_unfeasible) && refmetric < INFINITY)
  739:             route->time = babel_now.tv_sec;
  740:         route->seqno = seqno;
  741:         change_route_metric(route,
  742:                             refmetric, neighbour_cost(neigh), add_metric);
  743:         route->hold_time = hold_time;
  744: 
  745:         route_changed(route, oldsrc, oldmetric);
  746:         if(lost)
  747:             route_lost(oldsrc, oldmetric);
  748: 
  749:         if(!feasible)
  750:             send_unfeasible_request(neigh, route->installed && route_old(route),
  751:                                     seqno, metric, src);
  752:         release_source(oldsrc);
  753:     } else {
  754:         struct babel_route *new_route;
  755: 
  756:         if(refmetric >= INFINITY)
  757:             /* Somebody's retracting a route we never saw. */
  758:             return NULL;
  759:         if(!feasible) {
  760:             send_unfeasible_request(neigh, 0, seqno, metric, src);
  761:             if(!keep_unfeasible)
  762:                 return NULL;
  763:         }
  764: 
  765:         route = malloc(sizeof(struct babel_route));
  766:         if(route == NULL) {
  767:             perror("malloc(route)");
  768:             return NULL;
  769:         }
  770: 
  771:         route->src = retain_source(src);
  772:         route->refmetric = refmetric;
  773:         route->cost = neighbour_cost(neigh);
  774:         route->add_metric = add_metric;
  775:         route->seqno = seqno;
  776:         route->neigh = neigh;
  777:         memcpy(route->nexthop, nexthop, 16);
  778:         route->time = babel_now.tv_sec;
  779:         route->hold_time = hold_time;
  780:         route->installed = 0;
  781:         memset(&route->channels, 0, sizeof(route->channels));
  782:         if(channels_len > 0)
  783:             memcpy(&route->channels, channels,
  784:                    MIN(channels_len, DIVERSITY_HOPS));
  785:         route->next = NULL;
  786:         new_route = insert_route(route);
  787:         if(new_route == NULL) {
  788:             fprintf(stderr, "Couldn't insert route.\n");
  789:             free(route);
  790:             return NULL;
  791:         }
  792:         consider_route(route);
  793:     }
  794:     return route;
  795: }
  796: 
  797: /* We just received an unfeasible update.  If it's any good, send
  798:    a request for a new seqno. */
  799: void
  800: send_unfeasible_request(struct neighbour *neigh, int force,
  801:                         unsigned short seqno, unsigned short metric,
  802:                         struct source *src)
  803: {
  804:     struct babel_route *route = find_installed_route(src->prefix, src->plen);
  805: 
  806:     if(seqno_minus(src->seqno, seqno) > 100) {
  807:         /* Probably a source that lost its seqno.  Let it time-out. */
  808:         return;
  809:     }
  810: 
  811:     if(force || !route || route_metric(route) >= metric + 512) {
  812:         send_unicast_multihop_request(neigh, src->prefix, src->plen,
  813:                                       src->metric >= INFINITY ?
  814:                                       src->seqno :
  815:                                       seqno_plus(src->seqno, 1),
  816:                                       src->id, 127);
  817:     }
  818: }
  819: 
  820: /* This takes a feasible route and decides whether to install it. */
  821: static void
  822: consider_route(struct babel_route *route)
  823: {
  824:     struct babel_route *installed;
  825:     struct xroute *xroute;
  826: 
  827:     if(route->installed)
  828:         return;
  829: 
  830:     if(!route_feasible(route))
  831:         return;
  832: 
  833:     xroute = find_xroute(route->src->prefix, route->src->plen);
  834:     if(xroute && (allow_duplicates < 0 || xroute->metric >= allow_duplicates))
  835:         return;
  836: 
  837:     installed = find_installed_route(route->src->prefix, route->src->plen);
  838: 
  839:     if(installed == NULL)
  840:         goto install;
  841: 
  842:     if(route_metric(route) >= INFINITY)
  843:         return;
  844: 
  845:     if(route_metric(installed) >= INFINITY)
  846:         goto install;
  847: 
  848:     if(route_metric(installed) >= route_metric(route) + 64)
  849:         goto install;
  850: 
  851:     return;
  852: 
  853:  install:
  854:     switch_routes(installed, route);
  855:     if(installed && route->installed)
  856:         send_triggered_update(route, installed->src, route_metric(installed));
  857:     else
  858:         send_update(NULL, 1, route->src->prefix, route->src->plen);
  859:     return;
  860: }
  861: 
  862: void
  863: retract_neighbour_routes(struct neighbour *neigh)
  864: {
  865:     int i;
  866: 
  867:     for(i = 0; i < route_slots; i++) {
  868:         struct babel_route *r = routes[i];
  869:         while(r) {
  870:             if(r->neigh == neigh) {
  871:                 if(r->refmetric != INFINITY) {
  872:                     unsigned short oldmetric = route_metric(r);
  873:                     retract_route(r);
  874:                     if(oldmetric != INFINITY)
  875:                         route_changed(r, r->src, oldmetric);
  876:                 }
  877:             }
  878:             r = r->next;
  879:         }
  880:         i++;
  881:     }
  882: }
  883: 
  884: void
  885: send_triggered_update(struct babel_route *route, struct source *oldsrc,
  886:                       unsigned oldmetric)
  887: {
  888:     unsigned newmetric, diff;
  889:     /* 1 means send speedily, 2 means resend */
  890:     int urgent;
  891: 
  892:     if(!route->installed)
  893:         return;
  894: 
  895:     newmetric = route_metric(route);
  896:     diff =
  897:         newmetric >= oldmetric ? newmetric - oldmetric : oldmetric - newmetric;
  898: 
  899:     if(route->src != oldsrc || (oldmetric < INFINITY && newmetric >= INFINITY))
  900:         /* Switching sources can cause transient routing loops.
  901:            Retractions can cause blackholes. */
  902:         urgent = 2;
  903:     else if(newmetric > oldmetric && oldmetric < 6 * 256 && diff >= 512)
  904:         /* Route getting significantly worse */
  905:         urgent = 1;
  906:     else if(unsatisfied_request(route->src->prefix, route->src->plen,
  907:                                 route->seqno, route->src->id))
  908:         /* Make sure that requests are satisfied speedily */
  909:         urgent = 1;
  910:     else if(oldmetric >= INFINITY && newmetric < INFINITY)
  911:         /* New route */
  912:         urgent = 0;
  913:     else if(newmetric < oldmetric && diff < 1024)
  914:         /* Route getting better.  This may be a transient fluctuation, so
  915:            don't advertise it to avoid making routes unfeasible later on. */
  916:         return;
  917:     else if(diff < 384)
  918:         /* Don't fret about trivialities */
  919:         return;
  920:     else
  921:         urgent = 0;
  922: 
  923:     if(urgent >= 2)
  924:         send_update_resend(NULL, route->src->prefix, route->src->plen);
  925:     else
  926:         send_update(NULL, urgent, route->src->prefix, route->src->plen);
  927: 
  928:     if(oldmetric < INFINITY) {
  929:         if(newmetric >= oldmetric + 512) {
  930:             send_request_resend(NULL, route->src->prefix, route->src->plen,
  931:                                 route->src->metric >= INFINITY ?
  932:                                 route->src->seqno :
  933:                                 seqno_plus(route->src->seqno, 1),
  934:                                 route->src->id);
  935:         } else if(newmetric >= oldmetric + 288) {
  936:             send_request(NULL, route->src->prefix, route->src->plen);
  937:         }
  938:     }
  939: }
  940: 
  941: /* A route has just changed.  Decide whether to switch to a different route or
  942:    send an update. */
  943: void
  944: route_changed(struct babel_route *route,
  945:               struct source *oldsrc, unsigned short oldmetric)
  946: {
  947:     if(route->installed) {
  948:         if(route_metric(route) > oldmetric) {
  949:             struct babel_route *better_route;
  950:             better_route =
  951:                 find_best_route(route->src->prefix, route->src->plen, 1, NULL);
  952:             if(better_route &&
  953:                route_metric(better_route) <= route_metric(route) - 96)
  954:                 consider_route(better_route);
  955:         }
  956: 
  957:         if(route->installed)
  958:             /* We didn't change routes after all. */
  959:             send_triggered_update(route, oldsrc, oldmetric);
  960:     } else {
  961:         /* Reconsider routes even when their metric didn't decrease,
  962:            they may not have been feasible before. */
  963:         consider_route(route);
  964:     }
  965: }
  966: 
  967: /* We just lost the installed route to a given destination. */
  968: void
  969: route_lost(struct source *src, unsigned oldmetric)
  970: {
  971:     struct babel_route *new_route;
  972:     new_route = find_best_route(src->prefix, src->plen, 1, NULL);
  973:     if(new_route) {
  974:         consider_route(new_route);
  975:     } else if(oldmetric < INFINITY) {
  976:         /* Complain loudly. */
  977:         send_update_resend(NULL, src->prefix, src->plen);
  978:         send_request_resend(NULL, src->prefix, src->plen,
  979:                             src->metric >= INFINITY ?
  980:                             src->seqno : seqno_plus(src->seqno, 1),
  981:                             src->id);
  982:     }
  983: }
  984: 
  985: /* This is called periodically to flush old routes.  It will also send
  986:    requests for routes that are about to expire. */
  987: void
  988: expire_routes(void)
  989: {
  990:     struct babel_route *r;
  991:     int i;
  992: 
  993:     debugf(BABEL_DEBUG_COMMON,"Expiring old routes.");
  994: 
  995:     i = 0;
  996:     while(i < route_slots) {
  997:         r = routes[i];
  998:         while(r) {
  999:             /* Protect against clock being stepped. */
 1000:             if(r->time > babel_now.tv_sec || route_old(r)) {
 1001:                 flush_route(r);
 1002:                 goto again;
 1003:             }
 1004: 
 1005:             update_route_metric(r);
 1006: 
 1007:             if(r->installed && r->refmetric < INFINITY) {
 1008:                 if(route_old(r))
 1009:                     /* Route about to expire, send a request. */
 1010:                     send_unicast_request(r->neigh,
 1011:                                          r->src->prefix, r->src->plen);
 1012:             }
 1013:             r = r->next;
 1014:         }
 1015:         i++;
 1016:     again:
 1017:         ;
 1018:     }
 1019: }

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