/* Insert a route into the table. If successful, retains the route. On failure, caller must free the route. */ static struct babel_route * insert_route(struct babel_route *route) { int i, n; assert(!route->installed); i = find_route_slot(route->src->prefix, route->src->plen, route->src->src_prefix, route->src->src_plen, &n); if(i < 0) { if(route_slots >= max_route_slots) resize_route_table(max_route_slots < 1 ? 8 : 2 * max_route_slots); if(route_slots >= max_route_slots) return NULL; route->next = NULL; if(n < route_slots) memmove(routes + n + 1, routes + n, (route_slots - n) * sizeof(struct babel_route*)); route_slots++; routes[n] = route; } else { struct babel_route *r; r = routes[i]; while(r->next) r = r->next; r->next = route; route->next = NULL; } return route; }
void install_route(struct babel_route *route) { int i, rc; if(route->installed) return; if(!route_feasible(route)) fprintf(stderr, "WARNING: installing unfeasible route " "(this shouldn't happen)."); i = find_route_slot(route->src->prefix, route->src->plen, route->src->src_prefix, route->src->src_plen, NULL); assert(i >= 0 && i < route_slots); if(routes[i] != route && routes[i]->installed) { fprintf(stderr, "WARNING: attempting to install duplicate route " "(this shouldn't happen)."); return; } rc = kinstall_route(route); if(rc < 0 && errno != EEXIST) return; route->installed = 1; move_installed_route(route, i); local_notify_route(route, LOCAL_CHANGE); }
struct babel_route * find_installed_route(const unsigned char *prefix, unsigned char plen) { int i = find_route_slot(prefix, plen, NULL); if(i >= 0 && routes[i]->installed) return routes[i]; return NULL; }
void flush_route(struct babel_route *route) { int i; struct source *src; unsigned oldmetric; int lost = 0; oldmetric = route_metric(route); src = route->src; if(route->installed) { uninstall_route(route); lost = 1; } i = find_route_slot(route->src->prefix, route->src->plen, route->src->src_prefix, route->src->src_plen, NULL); assert(i >= 0 && i < route_slots); local_notify_route(route, LOCAL_FLUSH); if(route == routes[i]) { routes[i] = route->next; route->next = NULL; destroy_route(route); if(routes[i] == NULL) { if(i < route_slots - 1) memmove(routes + i, routes + i + 1, (route_slots - i - 1) * sizeof(struct babel_route*)); routes[route_slots - 1] = NULL; route_slots--; VALGRIND_MAKE_MEM_UNDEFINED(routes + route_slots, sizeof(struct route *)); } if(route_slots == 0) resize_route_table(0); else if(max_route_slots > 8 && route_slots < max_route_slots / 4) resize_route_table(max_route_slots / 2); } else { struct babel_route *r = routes[i]; while(r->next != route) r = r->next; r->next = route->next; route->next = NULL; destroy_route(route); } if(lost) route_lost(src, oldmetric); release_source(src); }
struct babel_route * find_route(const unsigned char *prefix, unsigned char plen, struct neighbour *neigh, const unsigned char *nexthop) { struct babel_route *route; int i = find_route_slot(prefix, plen, NULL); if(i < 0) return NULL; route = routes[i]; while(route) { if(route->neigh == neigh && memcmp(route->nexthop, nexthop, 16) == 0) return route; route = route->next; } return NULL; }
void install_route(struct babel_route *route) { int i, rc; if(route->installed) return; if(!route_feasible(route)) flog_err(EC_BABEL_ROUTE, "WARNING: installing unfeasible route " "(this shouldn't happen)."); i = find_route_slot(route->src->prefix, route->src->plen, NULL); assert(i >= 0 && i < route_slots); if(routes[i] != route && routes[i]->installed) { flog_err(EC_BABEL_ROUTE, "WARNING: attempting to install duplicate route " "(this shouldn't happen)."); return; } rc = kernel_route(ROUTE_ADD, route->src->prefix, route->src->plen, route->nexthop, route->neigh->ifp->ifindex, metric_to_kernel(route_metric(route)), NULL, 0, 0); if(rc < 0) { int save = errno; flog_err(EC_BABEL_ROUTE, "kernel_route(ADD): %s", safe_strerror(errno)); if(save != EEXIST) return; } route->installed = 1; move_installed_route(route, i); }
void install_route(struct route *route) { int i, rc; if(route->installed) return; if(!route_feasible(route)) fprintf(stderr, "WARNING: installing unfeasible route " "(this shouldn't happen)."); i = find_route_slot(route->src->prefix, route->src->plen, NULL); assert(i >= 0 && i < route_slots); if(routes[i] != route && routes[i]->installed) { fprintf(stderr, "WARNING: attempting to install duplicate route " "(this shouldn't happen)."); return; } rc = kernel_route(ROUTE_ADD, route->src->prefix, route->src->plen, route->nexthop, route->neigh->ifp->ifindex, metric_to_kernel(route_metric(route)), NULL, 0, 0); if(rc < 0) { int save = errno; perror("kernel_route(ADD)"); if(save != EEXIST) return; } route->installed = 1; move_installed_route(route, i); local_notify_route(route, LOCAL_CHANGE); }