/**
 * Check the version number of all route paths hanging off a route entry.
 * If a route does not match the current routing tree number, remove it
 * from the global originator tree for that rt_entry.
 * Reset the best route pointer.
 */
static void
olsr_delete_outdated_routes(struct rt_entry *rt)
{
  struct rt_path *rtp;
  struct avl_node *rtp_tree_node, *next_rtp_tree_node;

  for (rtp_tree_node = avl_walk_first(&rt->rt_path_tree); rtp_tree_node != NULL; rtp_tree_node = next_rtp_tree_node) {
    /*
     * pre-fetch the next node before loosing context.
     */
    next_rtp_tree_node = avl_walk_next(rtp_tree_node);

    rtp = rtp_tree2rtp(rtp_tree_node);

    /*
     * check the version number which gets incremented on every SPF run.
     * comparing for unequalness avoids handling version number wraps.
     */
    if (routingtree_version != rtp->rtp_version) {
      /* remove from the originator tree */
      avl_delete(&rt->rt_path_tree, rtp_tree_node);
      rtp->rtp_rt = NULL;

      if (rt->rt_best == rtp) {
        rt->rt_best = NULL;
      }
    }
  }
}
示例#2
0
/**
 * Grab the next topology entry.
 *
 * @param adr the address to look for
 * @return the entry found or NULL
 */
static struct tc_entry *
tas_getnext_tc_entry(struct tc_entry *tc)
{
  struct avl_node *node = avl_walk_next(&tc->vertex_node);

  return (node ? vertex_tree2tc(node) : NULL);
}
示例#3
0
/**
 * Print the routingtree to STDOUT
 *
 */
void
olsr_print_routing_table(struct avl_tree *tree)
{
#ifndef NODEBUG
  /* The whole function makes no sense without it. */
  struct avl_node *rt_tree_node;
  struct lqtextbuffer lqbuffer;

  OLSR_PRINTF(6, "ROUTING TABLE\n");

  for (rt_tree_node = avl_walk_first(tree); rt_tree_node != NULL; rt_tree_node = avl_walk_next(rt_tree_node)) {
    struct avl_node *rtp_tree_node;
    struct ipaddr_str prefixstr, origstr, gwstr;
    struct rt_entry *rt = rt_tree2rt(rt_tree_node);

    /* first the route entry */
    OLSR_PRINTF(6, "%s/%u, via %s, best-originator %s\n", olsr_ip_to_string(&prefixstr, &rt->rt_dst.prefix), rt->rt_dst.prefix_len,
                olsr_ip_to_string(&origstr, &rt->rt_nexthop.gateway), olsr_ip_to_string(&gwstr, &rt->rt_best->rtp_originator));

    /* walk the per-originator path tree of routes */
    for (rtp_tree_node = avl_walk_first(&rt->rt_path_tree); rtp_tree_node != NULL; rtp_tree_node = avl_walk_next(rtp_tree_node)) {
      struct rt_path *rtp = rtp_tree2rtp(rtp_tree_node);
      OLSR_PRINTF(6, "\tfrom %s, cost %s, metric %u, via %s, %s, v %u\n", olsr_ip_to_string(&origstr, &rtp->rtp_originator),
                  get_linkcost_text(rtp->rtp_metric.cost, true, &lqbuffer), rtp->rtp_metric.hops, olsr_ip_to_string(&gwstr,
                                                                                                                    &rtp->
                                                                                                                    rtp_nexthop.
                                                                                                                    gateway),
                  if_ifwithindex_name(rt->rt_nexthop.iif_index), rtp->rtp_version);
    }
  }
#endif /* NODEBUG */
  tree = NULL;                  /* squelch compiler warnings */
}
void
olsr_delete_interface_routes(int if_index) {
  struct rt_entry *rt;
  bool triggerUpdate = false;

  OLSR_FOR_ALL_RT_ENTRIES(rt) {
    bool mightTrigger = false;
    struct rt_path *rtp;
    struct avl_node *rtp_tree_node, *next_rtp_tree_node;

    /* run through all routing paths of route */
    for (rtp_tree_node = avl_walk_first(&rt->rt_path_tree); rtp_tree_node != NULL; rtp_tree_node = next_rtp_tree_node) {
      /*
       * pre-fetch the next node before loosing context.
       */
      next_rtp_tree_node = avl_walk_next(rtp_tree_node);

      rtp = rtp_tree2rtp(rtp_tree_node);

      /* nexthop use lost interface ? */
      if (rtp->rtp_nexthop.iif_index == if_index) {
        /* remove from the originator tree */
        avl_delete(&rt->rt_path_tree, rtp_tree_node);
        rtp->rtp_rt = NULL;

        if (rt->rt_best == rtp) {
          rt->rt_best = NULL;
          mightTrigger = true;
        }
      }
    }

    if (mightTrigger) {
      if (!rt->rt_path_tree.count) {
        /* oops, all routes are gone - flush the route head */
        avl_delete(&routingtree, rt_tree_node);

        /* do not dequeue route because they are already gone */
      }
      triggerUpdate = true;
    }
  } OLSR_FOR_ALL_RT_ENTRIES_END(rt)

  /* trigger route update if necessary */
  if (triggerUpdate) {
    olsr_update_rib_routes();
    olsr_update_kernel_routes();
  }
}
示例#5
0
int iterRouteTabNext(char *buff, int len)
{
  struct avl_node *rt_tree_node;

  if (iterRouteTab == NULL)
    return -1;

  snprintf(buff, len, "destination~%s~gateway~%s~interface~%s~metric~%d~",
           rawIpAddrToString(&iterRouteTab->rt_dst.prefix, ipAddrLen),
           rawIpAddrToString(&iterRouteTab->rt_best->rtp_nexthop.gateway, ipAddrLen),
           if_ifwithindex_name(iterRouteTab->rt_best->rtp_nexthop.iif_index),
           iterRouteTab->rt_best->rtp_metric.hops);

  rt_tree_node = avl_walk_next(&iterRouteTab->rt_tree_node);
  if (rt_tree_node) {
      iterRouteTab = rt_tree2rt(rt_tree_node);
  } else {
      iterRouteTab = NULL;
  }

  return 0;
}
示例#6
0
/**
 * run best route selection among a
 * set of identical prefixes.
 */
void
olsr_rt_best(struct rt_entry *rt)
{
  /* grab the first entry */
  struct avl_node *node = avl_walk_first(&rt->rt_path_tree);

  assert(node != 0);            /* should not happen */

  rt->rt_best = rtp_tree2rtp(node);

  /* walk all remaining originator entries */
  while ((node = avl_walk_next(node))) {
    struct rt_path *rtp = rtp_tree2rtp(node);

    if (olsr_cmp_rtp(rtp, rt->rt_best, current_inetgw)) {
      rt->rt_best = rtp;
    }
  }

  if (0 == rt->rt_dst.prefix_len) {
    current_inetgw = rt->rt_best;
  }
}
示例#7
0
/*
 * olsr_spf_relax
 *
 * Explore all edges of a node and add the node
 * to the candidate tree if the if the aggregate
 * path cost is better.
 */
static void
olsr_spf_relax(struct avl_tree *cand_tree, struct tc_entry *tc)
{
  struct avl_node *edge_node;
  olsr_linkcost new_cost;

#ifdef DEBUG
#ifndef NODEBUG
  struct ipaddr_str buf, nbuf;
  struct lqtextbuffer lqbuffer;
#endif /* NODEBUG */
  OLSR_PRINTF(2, "SPF: exploring node %s, cost %s\n", olsr_ip_to_string(&buf, &tc->addr),
              get_linkcost_text(tc->path_cost, false, &lqbuffer));
#endif /* DEBUG */

  /*
   * loop through all edges of this vertex.
   */
  for (edge_node = avl_walk_first(&tc->edge_tree); edge_node; edge_node = avl_walk_next(edge_node)) {

    struct tc_entry *new_tc;
    struct tc_edge_entry *tc_edge = edge_tree2tc_edge(edge_node);

    /*
     * We are not interested in dead-end edges.
     */
    if (!tc_edge->edge_inv) {
#ifdef DEBUG
      OLSR_PRINTF(2, "SPF:   ignoring edge %s\n", olsr_ip_to_string(&buf, &tc_edge->T_dest_addr));
      if (!tc_edge->edge_inv) {
        OLSR_PRINTF(2, "SPF:     no inverse edge\n");
      }
#endif /* DEBUG */
      continue;
    }

    if (tc_edge->cost == LINK_COST_BROKEN) {
#ifdef DEBUG
      OLSR_PRINTF(2, "SPF:   ignore edge %s (broken)\n", olsr_ip_to_string(&buf, &tc_edge->T_dest_addr));
#endif /* DEBUG */
      continue;
    }
    /*
     * total quality of the path through this vertex
     * to the destination of this edge
     */
    new_cost = tc->path_cost + tc_edge->cost;

#ifdef DEBUG
    OLSR_PRINTF(2, "SPF:   exploring edge %s, cost %s\n", olsr_ip_to_string(&buf, &tc_edge->T_dest_addr),
                get_linkcost_text(new_cost, true, &lqbuffer));
#endif /* DEBUG */

    /*
     * if it's better than the current path quality of this edge's
     * destination node, then we've found a better path to this node.
     */
    new_tc = tc_edge->edge_inv->tc;

    if (new_cost < new_tc->path_cost) {

      /* if this node has been on the candidate tree delete it */
      if (new_tc->path_cost < ROUTE_COST_BROKEN) {
        olsr_spf_del_cand_tree(cand_tree, new_tc);
      }

      /* re-insert on candidate tree with the better metric */
      new_tc->path_cost = new_cost;
      olsr_spf_add_cand_tree(cand_tree, new_tc);

      /* pull-up the next-hop and bump the hop count */
      if (tc->next_hop) {
        new_tc->next_hop = tc->next_hop;
      }
      new_tc->hops = tc->hops + 1;

#ifdef DEBUG
      OLSR_PRINTF(2, "SPF:   better path to %s, cost %s, via %s, hops %u\n", olsr_ip_to_string(&buf, &new_tc->addr),
                  get_linkcost_text(new_cost, true, &lqbuffer), tc->next_hop ? olsr_ip_to_string(&nbuf,
                                                                                                 &tc->next_hop->neighbor_iface_addr)
                  : "<none>", new_tc->hops);
#endif /* DEBUG */

    }
  }
}