zoukankan      html  css  js  c++  java
  • quagga源码分析--路由信息处理zebra-rib

    对于各个协议生成的路由信息的处理属于quagga中非常重要的一个功能,如何在内核进行路由增加,更新,删除是一个复杂的过程。

    quagga在thread任务调度中加入了一种工作队列,work_queue,与内核的工作队列类似,是一种相对而言,低优先级的任务,这里的任务看成类似的系统进程。

    1、队列初始化:

     1 /* initialise zebra rib work queue */
     2 static void
     3 rib_queue_init(struct zebra_t *zebra)
     4 {
     5     assert(zebra);
     6 
     7     if (!(zebra->ribq = work_queue_new(zebra->master,
     8                                        "route_node processing")))
     9     {
    10         zlog_err("%s: could not initialise work queue!", __func__);
    11         return;
    12     }
    13 
    14     /* fill in the work queue spec */
    15     zebra->ribq->spec.workfunc = &meta_queue_process;
    16     zebra->ribq->spec.errorfunc = NULL;
    17     /* XXX: TODO: These should be runtime configurable via vty */
    18     zebra->ribq->spec.max_retries = 3;
    19     zebra->ribq->spec.hold = rib_process_hold_time;
    20 
    21     if (!(zebra->mq = meta_queue_new()))
    22     {
    23         zlog_err("%s: could not initialise meta queue!", __func__);
    24         return;
    25     }
    26     return;
    27 }

    第19行,zebra->ribq->spec.hold = rib_process_hold_time; 指定了rib工作队列在thread_fetch的时候会等待10毫秒

    1 /* Hold time for RIB process, should be very minimal.
    2  * it is useful to able to set it otherwise for testing, hence exported
    3  * as global here for test-rig code.
    4  */
    5 int rib_process_hold_time = 10;

    在添加thread任务的时候进行了时间单位换算:

     1 /* Add a background thread, with an optional millisec delay */
     2 struct thread*
     3 funcname_thread_add_background(struct thread_master *m,
     4                                int (*func)(struct thread *),
     5                                void *arg, long delay,
     6                                debugargdef) {
     7     struct timeval trel;
     8 
     9     assert(m != NULL);
    10 
    11     if (delay) {
    12         trel.tv_sec = delay / 1000;
    13         trel.tv_usec = 1000 * (delay % 1000);
    14     } else {
    15         trel.tv_sec = 0;
    16         trel.tv_usec = 0;
    17     }
    18 
    19     return funcname_thread_add_timer_timeval(m, func, THREAD_BACKGROUND,
    20                                              arg, &trel, debugargpass);
    21 }

    OK,meta_queue_process,就指定了工作队列在调度执行的处理函数,由此guagga就会一直同步更新路由了。

    2、每个子网的下一跳路由表项的描述:

    quagga使用了双向链表来管理表项,定义了路由表现的详细信息,但比如 status 这个字段是用来在更新路由时来做比较的关键字段。如下宏定义了3种状态:

    #define RIB_ENTRY_REMOVED    (1 << 0)
    #define RIB_ENTRY_CHANGED    (1 << 1)
    #define RIB_ENTRY_SELECTED_FIB    (1 << 2)

     1 struct rib { 
     2   struct rib *next;         /* Link list. */
     3   struct rib *prev;
     4   struct nexthop *nexthop; /* Nexthop structure */
     5   unsigned long refcnt;    /* Refrence count. */
     6   time_t uptime;           /* Uptime. */
     7   int type;                /* Type fo this route. */
     8   vrf_id_t vrf_id;         /* VRF identifier. */
     9   int table;               /* Which routing table */
    10   u_int32_t metric;        /* Metric */
    11   u_int32_t mtu;           /* MTU */
    12   u_int32_t nexthop_mtu;
    13   u_char distance;         /* Distance. */
    14   u_char flags;             /* Flags of this route. in lib/zebra.h ZEBRA_FLAG_* */
    15   u_char status;            /* RIB internal status */
    16 #define RIB_ENTRY_REMOVED    (1 << 0)
    17 #define RIB_ENTRY_CHANGED    (1 << 1)
    18 #define RIB_ENTRY_SELECTED_FIB    (1 << 2)
    19   u_char nexthop_num;        /* Nexthop information. */
    20   u_char nexthop_active_num;
    21   u_char nexthop_fib_num;
    22 };

     3、整个路由表的描述:

    /* Routing table top structure. */
    struct route_table {
      struct route_node *top;
      /*
       * Delegate that performs certain functions for this table.
       */
      route_table_delegate_t *delegate;
      unsigned long count;
      void *info;     /* User data. */
    };

    route_table包含了一个二叉树结构来保存所有的路由前缀和下一跳路由表项,prefix结构保持了路由前缀的长度和值,用来做最长前缀匹配:

     1 /* Each routing entry. */
     2 struct route_node {
     3   struct prefix p;   /* Actual prefix of this radix. */
     4   struct route_table *table;   /* Tree link. */
     5   struct route_node *parent;
     6   struct route_node *link[2];
     7   unsigned int lock; /* Lock of this radix */
     8   void *info;        /* Each node of route. */
     9   void *aggregate;   /* Aggregation. */
    10 
    11 #define l_left   link[0]
    12 #define l_right  link[1]
    13 };

    呃,说好的mtire树呢? 好吧,我们不太可能把成千上万的路由表项塞给linux内核,够用就行。



  • 相关阅读:
    echo和重定向
    grep命令
    重温JSP学习笔记--JSP动作标签
    重温JSP学习笔记--El表达式
    重温JSP学习笔记--El函数库
    重温JSP学习笔记--JSTL标签库
    重温JSP学习笔记
    Android 用 camera2 API 自定义相机
    从零开始用 Flask 搭建一个网站(一)
    从零开始用 Flask 搭建一个网站(二)
  • 原文地址:https://www.cnblogs.com/danxi/p/6285545.html
Copyright © 2011-2022 走看看