⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lq_route.c

📁 wifi 无线网络路由协议OLSR linux下C代码
💻 C
字号:
/* * The olsr.org Optimized Link-State Routing daemon(olsrd) * Copyright (c) 2004, Thomas Lopatic (thomas@lopatic.de) * IPv4 performance optimization (c) 2006, sven-ola(gmx.de) * SPF implementation (c) 2007, Hannes Gredler (hannes@gredler.at) * All rights reserved. * * Redistribution and use in source and binary forms, with or without  * modification, are permitted provided that the following conditions  * are met: * * * Redistributions of source code must retain the above copyright  *   notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright  *   notice, this list of conditions and the following disclaimer in  *   the documentation and/or other materials provided with the  *   distribution. * * Neither the name of olsr.org, olsrd nor the names of its  *   contributors may be used to endorse or promote products derived  *   from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE  * POSSIBILITY OF SUCH DAMAGE. * * Visit http://www.olsr.org for more information. * * If you find this software useful feel free to make a donation * to the project. For more information see the website or contact * the copyright holders. * * $Id: lq_route.c,v 1.53 2007/10/16 09:54:43 bernd67 Exp $ */#include "defs.h"#include "olsr.h"#include "tc_set.h"#include "neighbor_table.h"#include "two_hop_neighbor_table.h"#include "link_set.h"#include "routing_table.h"#include "mid_set.h"#include "hna_set.h"#include "lq_list.h"#include "lq_avl.h"#include "lq_route.h"/* * avl_comp_etx * * compare two etx metrics. * return 0 if there is an exact match and * -1 / +1 depending on being smaller or bigger. * note that this results in the most optimal code * after compiler optimization. */static intavl_comp_etx (void *etx1, void *etx2){         if (*(float *)etx1 < *(float *)etx2) {    return -1;  }  if (*(float *)etx1 > *(float *)etx2) {    return +1;  }  return 0;}/* * olsr_spf_add_cand_tree * * Key an existing vertex to a candidate tree. */static voidolsr_spf_add_cand_tree (struct avl_tree *tree,                        struct tc_entry *vert){  vert->cand_tree_node.key = &vert->path_etx;  vert->cand_tree_node.data = vert;#ifdef DEBUG  OLSR_PRINTF(1, "SPF: insert candidate %s, cost %f\n",              olsr_ip_to_string(&(vert->addr)),              vert->path_etx);#endif  avl_insert(tree, &vert->cand_tree_node, AVL_DUP);}/* * olsr_spf_del_cand_tree * * Unkey an existing vertex from a candidate tree. */static voidolsr_spf_del_cand_tree (struct avl_tree *tree,                        struct tc_entry *vert){#ifdef DEBUG  OLSR_PRINTF(1, "SPF: delete candidate %s, cost %f\n",              olsr_ip_to_string(&(vert->addr)),              vert->path_etx);#endif  avl_delete(tree, &vert->cand_tree_node);}/* * olsr_spf_add_path_list * * Insert an SPF result at the end of the path list. */static voidolsr_spf_add_path_list (struct list_node *head,                        int *path_count,                        struct tc_entry *vert){  vert->path_list_node.data = vert;#ifdef DEBUG  OLSR_PRINTF(1, "SPF: append path %s, cost %f, via %s\n",              olsr_ip_to_string(&(vert->addr)),              vert->path_etx,              olsr_ip_to_string(vert->next_hop ? &vert->next_hop->neighbor_iface_addr : NULL));#endif  list_add_before(head, &vert->path_list_node);  *path_count = *path_count + 1;}/* * olsr_spf_extract_best * * return the node with the minimum pathcost. */static struct tc_entry *olsr_spf_extract_best (struct avl_tree *tree){  struct avl_node *node;  node = avl_walk_first(tree);  return (node ? node->data :  NULL);}char *olsr_etx_to_string(float etx){  static char buff[20];  if (etx == INFINITE_ETX)    return "INF";  snprintf(buff, 20, "%.6f", etx);  return buff;}/* * 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 voidolsr_spf_relax (struct avl_tree *cand_tree, struct tc_entry *vert){  struct tc_entry *new_vert;  struct tc_edge_entry *tc_edge;  struct avl_node *edge_node;  float new_etx;#ifdef DEBUG  OLSR_PRINTF(1, "SPF: exploring node %s, cost %f\n",              olsr_ip_to_string(&(vert->addr)),              vert->path_etx);#endif  /*   * loop through all edges of this vertex.   */  for (edge_node = avl_walk_first(&vert->edge_tree);       edge_node;       edge_node = avl_walk_next(edge_node)) {    tc_edge = edge_node->data;    /*     * We are not interested in dead-end or dying edges.     */    if (!tc_edge->edge_inv || (tc_edge->flags & OLSR_TC_EDGE_DOWN)) {#ifdef DEBUG      OLSR_PRINTF(1, "SPF:   ignoring edge %s\n",                  olsr_ip_to_string(&tc_edge->T_dest_addr));      if (tc_edge->flags & OLSR_TC_EDGE_DOWN) {        OLSR_PRINTF(1, "SPF:     edge down\n");      }      if (!tc_edge->edge_inv) {        OLSR_PRINTF(1, "SPF:     no inverse edge\n");      }#endif      continue;    }    /*     * total quality of the path through this vertex     * to the destination of this edge     */    new_etx = vert->path_etx + tc_edge->etx;#ifdef DEBUG      OLSR_PRINTF(1, "SPF:   exploring edge %s, cost %s\n",                  olsr_ip_to_string(&(tc_edge->T_dest_addr)),                  olsr_etx_to_string(new_vert->path_etx));#endif      /*        * 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_vert = tc_edge->edge_inv->tc;    if (new_etx < new_vert->path_etx) {      /* if this node has been on the candidate tree delete it */      if (new_vert->path_etx != INFINITE_ETX) {        olsr_spf_del_cand_tree(cand_tree, new_vert);      }      /* re-insert on candidate tree with the better metric */      new_vert->path_etx = new_etx;      olsr_spf_add_cand_tree(cand_tree, new_vert);      /* pull-up the next-hop and bump the hop count */      if (vert->next_hop) {        new_vert->next_hop = vert->next_hop;      }      new_vert->hops = vert->hops + 1;#ifdef DEBUG      OLSR_PRINTF(1, "SPF:   better path to %s, cost %s -> %s, via %s, hops %u\n",                  olsr_ip_to_string(&new_vert->addr),                  olsr_etx_to_string(new_vert->path_etx),                  olsr_etx_to_string(new_etx),                  olsr_ip_to_string(vert->next_hop ?                                    &vert->next_hop->neighbor_iface_addr : NULL),                  new_vert->->hops);#endif    }  }}/* * olsr_spf_run_full * * Run the Dijkstra algorithm. *  * A node gets added to the candidate tree when one of its edges has * an overall better root path cost than the node itself. * The node with the shortest metric gets moved from the candidate to * the path list every pass. * The SPF computation is completed when there are no more nodes * on the candidate tree.  */ static voidolsr_spf_run_full (struct avl_tree *cand_tree, struct list_node *path_list,                   int *path_count){  struct tc_entry *vert;  *path_count = 0;  while ((vert = olsr_spf_extract_best(cand_tree))) {    olsr_spf_relax(cand_tree, vert);    /*     * move the best path from the candidate tree     * to the path list.     */    olsr_spf_del_cand_tree(cand_tree, vert);    olsr_spf_add_path_list(path_list, path_count, vert);  }}voidolsr_calculate_routing_table (void){  struct avl_tree cand_tree;  struct list_node path_list;  int i, plen, path_count = 0;  struct tc_entry *tc;  struct tc_edge_entry *tc_edge;  struct tc_entry *vert;  struct neighbor_entry *neigh;  struct mid_address *mid_walker;  struct hna_entry *hna_gw;  struct hna_net *hna;  struct interface *inter;  struct link_entry *link;#ifdef SPF_PROFILING  struct timeval t1, t2, t3, t4, t5, spf_init, spf_run, route, kernel, total;  gettimeofday(&t1, NULL);#endif  /*   * Prepare the candidate tree and result list.   */  avl_init(&cand_tree, avl_comp_etx);  list_head_init(&path_list);  olsr_bump_routingtree_version();  /*   * Initialize vertices in the lsdb.   */  OLSR_FOR_ALL_TC_ENTRIES(tc) {    tc->next_hop = NULL;    tc->path_etx = INFINITE_ETX;    tc->hops = 0;  } OLSR_FOR_ALL_TC_ENTRIES_END(tc);  /*   * zero ourselves and add us to the candidate tree.   */  olsr_change_myself_tc();  tc_myself->path_etx = ZERO_ETX;  olsr_spf_add_cand_tree(&cand_tree, tc_myself);  /*   * add edges to and from our neighbours.   */  for (i = 0; i < HASHSIZE; i++)    for (neigh = neighbortable[i].next; neigh != &neighbortable[i];         neigh = neigh->next) {      if (neigh->status == SYM) {        tc_edge = olsr_lookup_tc_edge(tc_myself, &neigh->neighbor_main_addr);        link = get_best_link_to_neighbor(&neigh->neighbor_main_addr);	if (!link) {          /*           * If there is no best link to this neighbor           * and we had an edge before then flush the edge.           */          if (tc_edge) {            olsr_delete_tc_edge_entry(tc_edge);          }	  continue;        }        /*         * Set the next-hops of our neighbors.          */        if (!tc_edge) {          tc_edge = olsr_add_tc_edge_entry(tc_myself, &neigh->neighbor_main_addr,                                           0, link->last_htime,                                           link->loss_link_quality2,                                           link->neigh_link_quality2);        } else {          tc_edge->link_quality = link->loss_link_quality2;          tc_edge->inverse_link_quality = link->neigh_link_quality2;          olsr_calc_tc_edge_entry_etx(tc_edge);        }        if (tc_edge->edge_inv) {          tc_edge->edge_inv->tc->next_hop = link;        }      }    }#ifdef SPF_PROFILING  gettimeofday(&t2, NULL);#endif  /*   * Run the SPF calculation.   */  olsr_spf_run_full(&cand_tree, &path_list, &path_count);  OLSR_PRINTF(2, "\n--- %02d:%02d:%02d.%02d ------------------------------------------------- DIJKSTRA\n\n",              nowtm->tm_hour,              nowtm->tm_min,              nowtm->tm_sec,              (int)now.tv_usec/10000);#ifdef SPF_PROFILING  gettimeofday(&t3, NULL);#endif  /*   * In the path tree we have all the reachable nodes in our topology.   */  for (; !list_is_empty(&path_list); list_remove(path_list.next)) {    vert = path_list.next->data;    link = vert->next_hop;    if (!link) {      OLSR_PRINTF(2, "%s no next-hop\n", olsr_ip_to_string(&vert->addr));      continue;    }    /* find the interface for the found link */    inter = link->if_name ? if_ifwithname(link->if_name)      : if_ifwithaddr(&link->local_iface_addr);    /* interface is up ? */    if (inter) {      /* add a route to the main address of the destination node */      olsr_insert_routing_table(&vert->addr, olsr_cnf->maxplen, &vert->addr,                                &link->neighbor_iface_addr, inter->if_index,                                vert->hops, vert->path_etx);      /* add routes to the remaining interfaces of the destination node */      for (mid_walker = mid_lookup_aliases(&vert->addr);           mid_walker != NULL;           mid_walker = mid_walker->next_alias) {        olsr_insert_routing_table(&mid_walker->alias, olsr_cnf->maxplen, &vert->addr,                                  &link->neighbor_iface_addr, inter->if_index,                                  vert->hops, vert->path_etx);      }      /* find the node's HNAs */      hna_gw = olsr_lookup_hna_gw(&vert->addr);      /* node doesn't announce any HNAs */      if (!hna_gw) {        continue;      }      /* loop through the node's HNAs */      for (hna = hna_gw->networks.next;           hna != &hna_gw->networks;           hna = hna->next) {        plen = olsr_get_hna_prefix_len(hna);        if (vert->path_etx != INFINITE_ETX)        olsr_insert_routing_table(&hna->A_network_addr, plen, &vert->addr,                                  &link->neighbor_iface_addr, inter->if_index,                                  vert->hops, vert->path_etx);      }    }  }#ifdef SPF_PROFILING  gettimeofday(&t4, NULL);#endif  /* move the route changes into the kernel */  olsr_update_kernel_routes();#ifdef SPF_PROFILING  gettimeofday(&t5, NULL);#endif#ifdef SPF_PROFILING  timersub(&t2, &t1, &spf_init);  timersub(&t3, &t2, &spf_run);  timersub(&t4, &t3, &route);  timersub(&t5, &t4, &kernel);  timersub(&t5, &t1, &total);  olsr_printf(1, "\n--- SPF-stats for %d nodes, %d routes (total/init/run/route/kern): "              "%d, %d, %d, %d, %d\n",              path_count, routingtree.count,              (int)total.tv_usec, (int)spf_init.tv_usec, (int)spf_run.tv_usec,              (int)route.tv_usec, (int)kernel.tv_usec);#endif}/* * Local Variables: * c-basic-offset: 2 * End: */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -