• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
    • 軟件測試技術
    • 軟件測試博客
    • 軟件測試視頻
    • 開源軟件測試技術
    • 軟件測試論壇
    • 軟件測試沙龍
    • 軟件測試資料下載
    • 軟件測試雜志
    • 軟件測試人才招聘
      暫時沒有公告

    字號: | 推薦給好友 上一篇 | 下一篇

    Linux策略性路由應用

    發布: 2007-7-13 21:16 | 作者: 佚名    | 來源: 網絡轉載     | 查看: 12次 | 進入軟件測試論壇討論

    領測軟件測試網

        策略性路由

      策略性是指對于IP包的路由是以網絡管理員根據需要定下的一些策略為主要依據進行路由的。例如我們可以有這樣的策略:“所有來直自網A的包,選擇X路徑;其他選擇Y路徑”,或者是“所有TOS為A的包選擇路徑F;其他選者路徑K”。

      Cisco 的網絡操作系統 (Cisco IOS) 從11.0開始就采用新的策略性路由機制。而Linux是在內核2.1開始采用策略性路由機制的。策略性路由機制與傳統的路由算法相比主要是引入了多路由表以及規則的概念。

      多路由表(multiple Routing Tables)

      傳統的路由算法是僅使用一張路由表的。但是在有些情形底下,我們是需要使用多路由表的。例如一個子網通過一個路由器與外界相連,路由器與外界有兩條線路相連,其中一條的速度比較快,一條的速度比較慢。對于子網內的大多數用戶來說對速度并沒有特殊的要求,所以可以讓他們用比較慢的路由;但是子網內有一些特殊的用戶卻是對速度的要求比較苛刻,所以他們需要使用速度比較快的路由。如果使用一張路由表上述要求是無法實現的,而如果根據源地址或其它參數,對不同的用戶使用不同的路由表,這樣就可以大大提高路由器的性能。

      規則(rule)

      規則是策略性的關鍵性的新的概念。我們可以用自然語言這樣描述規則,例如我門可以指定這樣的規則:

      規則一:“所有來自192.16.152.24的IP包,使用路由表10, 本規則的優先級別是1500”

      規則二:“所有的包,使用路由表253,本規則的優先級別是32767”

      我們可以看到,規則包含3個要素:

      什么樣的包,將應用本規則(所謂的SELECTOR,可能是filter更能反映其作用);

      符合本規則的包將對其采取什么動作(ACTION),例如用那個表;

      本規則的優先級別。優先級別越高的規則越先匹配(數值越小優先級別越高)。

      策略性路由的配置方法

      傳統的linux下配置路由的工具是route,而實現策略性路由配置的工具是iproute2工具包。這個軟件包是由Alexey Kuznetsov開發的。
    這里簡單介紹策略性路由的配置方法,以便能更好理解第二部分的內容。詳細的使用方法請參考Alexey Kuznetsov寫的 ip-cfref文檔。策略性路由的配置主要包括接口地址的配置、路由的配置、規則的配置。

      接口地址的配置IP Addr

      對于接口的配置可以用下面的命令進行:

    Usage: ip addr [ add | del ] IFADDR dev STRING

      例如:

    router># ip addr add 192.168.0.1/24 broadcast 192.168.0.255 label eth0 dev eth0

      上面表示,給接口eth0賦予地址192.168.0.1 掩碼是255.255.255.0(24代表掩碼中1的個數),廣播地址是192.168.0.255

      路由的配置IP Route

      Linux最多可以支持255張路由表,其中有3張表是內置的:

      表255 本地路由表(Local table) 本地接口地址,廣播地址,已及NAT地址都放在這個表。該路由表由系統自動維護,管理員不能直接修改。

      表254 主路由表(Main table) 如果沒有指明路由所屬的表,所有的路由都默認都放在這個表里,一般來說,舊的路由工具(如route)所添加的路由都會加到這個表。一般是普通的路由。

      表253 默認路由表 (Default table) 一般來說默認的路由都放在這張表,但是如果特別指明放的也可以是所有的網關路由。

      表 0 保留

      路由配置命令的格式如下:
    Usage: ip route list SELECTOR
    ip route { change | del | add | append | replace | monitor } ROUTE


      如果想查看路由表的內容,可以通過命令:

      ip route list table table_number

      對于路由的操作包括change、del、add 、append 、replace 、 monitor這些。例如添加路由可以用:


    router># ip route add 0/0 via 192.168.0.4 table main
    router># ip route add 192.168.3.0/24 via 192.168.0.3 table 1


      第一條命令是向主路由表(main table)即表254添加一條路由,路由的內容是設置192.168.0.4成為網關。

      第二條命令代表向路由表1添加一條路由,子網192.168.3.0(子網掩碼是255.255.255.0)的網關是192.168.0.3。

      在多路由表的路由體系里,所有的路由的操作,例如網路由表添加路由,或者在路由表里尋找特定的路由,需要指明要操作的路由表,所有沒有指明路由表,默認是對主路由表(表254)進行操作。而在單表體系里,路由的操作是不用指明路由表的。

      規則的配置IP Rule

      在Linux里,總共可以定義 個優先級的規則,一個優先級別只能有一條規則,即理論上總共可以有 條規則。其中有3個規則是默認的。命令用法如下:


    Usage: ip rule [ list | add | del ] SELECTOR ACTION
    SELECTOR := [ from PREFIX ] [ to PREFIX ] [ tos TOS ]
    [ dev STRING ] [ pref NUMBER ]
    ACTION := [ table TABLE_ID ] [ nat ADDRESS ]
    [ prohibit | reject | unreachable ]
    [ flowid CLASSID ]
    TABLE_ID := [ local | main | default | new | NUMBER


      首先我們可以看看路由表默認的所有規則:


    0: from all lookup local
    32766: from all lookup main
    32767: from all lookup default


      規則0,它是優先級別最高的規則,規則規定,所有的包,都必須首先使用local表(254)進行路由。本規則不能被更改和刪除。

      規則32766,規定所有的包,使用表main進行路由。本規則可以被更改和刪除。

      規則32767,規定所有的包,使用表default進行路由。本規則可以被更改和刪除。

      在默認情況下進行路由時,首先會根據規則0在本地路由表里尋找路由,如果目的地址是本網絡,或是廣播地址的話,在這里就可以找到合適的路由;如果路由失敗,就會匹配下一個不空的規則,在這里只有32766規則,在這里將會在主路由表里尋找路由;如果失敗,就會匹配32767規則,即尋找默認路由表。如果失敗,路由將失敗。重這里可以看出,策略性路由是往前兼容的。

      還可以添加規則:


    router># ip rule add [from 0/0] table 1 pref 32800
    router >#ip rule add from 192.168.3.112/32 [tos 0x10] table 2 pref 1500 prohibit


      第一條命令將向規則鏈增加一條規則,規則匹配的對象是所有的數據包,動作是選用路由表1的路由,這條規則的優先級是32800。

      第二條命令將向規則鏈增加一條規則,規則匹配的對象是IP為192.168.3.112,tos等于0x10的包,使用路由表2,這條規則的優先級是1500,動作是。添加以后,我們可以看看系統規則的變化。


    router># ip rule
    0: from all lookup local
    1500 from 192.168.3.112/32 [tos 0x10] lookup 2
    32766: from all lookup main
    32767: from all lookup default
    32800: from all lookup 1


      上面的規則是以源地址為關鍵字,作為是否匹配的依據的。除了源地址外,還可以用以下的信息:

      From -- 源地址

      To -- 目的地址(這里是選擇規則時使用,查找路由表時也使用)

      Tos -- IP包頭的TOS(type of sevice)域

      Dev -- 物理接口

      Fwmark -- 防火墻參數

      采取的動作除了指定表,還可以指定下面的動作:

       Table 指明所使用的表

       Nat 透明網關

       Action prohibit 丟棄該包,并發送 COMM.ADM.PROHIITED的ICMP信息

       Reject 單純丟棄該包

       Unreachable丟棄該包, 并發送 NET UNREACHABLE的ICMP信息

        策略性路由的應用

      基于源地址選路( Source-Sensitive Routing)

      如果一個網絡通過兩條線路接入互聯網,一條是比較快的ADSL,另外一條是比較慢的普通的調制解調器。這樣的話,網絡管理員既可以提供無差別的路由服務,也可以根據源地址的不同,使一些特定的地址使用較快的線路,而普通用戶則使用較慢的線路,即基于源址的選路。

      根據服務級別選路(Quality of Service)

      網絡管理員可以根據IP報頭的服務級別域,對于不同的服務要求可以分別對待對于傳送速率、吞吐量以及可靠性的有不同要求的數據報根據網絡的狀況進行不同的路由。

      節省費用的應用

      網絡管理員可以根據通信的狀況,讓一些比較大的陣發性通信使用一些帶寬比較高但是比較貴的路徑一段短的時間,然后讓基本的通信繼續使用原來比較便宜的基本線路。例如,管理員知道,某一臺主機與一個特定的地址通信通常是伴隨著大量的陣發性通信的,那么網絡管理員可以安排一些策略,使得這些主機使用特別的路由,這些路由是按需撥號,帶寬比較高的線路,通信完成以后就停止使用,而普通的通信則不受影響。這樣既提高網絡的性能,又能節省費用。

      負載平衡(Load Sharing)

      根據網絡交通的特征,網絡管理員可以在不同的路徑之間分配負荷實現負載平衡。

      Linux下策略性路由的實現--RPDB(Routing Policy DataBase)

      在Linux下,策略性路由是由RPDB實現的。對于RPDB的內部機制的理解,可以加深對于策略性路由使用的理解。這里分析的是linux 2.4.18的RPDB實現的細節。主要的實現文件包括:

    fib_hash.c
    fib_rules.c
    fib_sematic
    fib_frontend.c
    route.c


      RDPB主要由多路由表和規則組成。路由表以及對其的操作和其對外的接口是整個RPDB的核心部分。路由表主要由table,zone,node這些主要的數據結構構成。對路由表的操作主要包含物理的操作以及語義的操作。路由表除了向IP層提供路由尋找的接口以外還必須與幾個元素提供接口:與用戶的接口(即更改路由)、proc的接口、IP層控制接口、以及和硬件的接口(網絡接口的改變會導致路由表內容的改變)。處在RDPB的中心的規則,由規則選取表。IP層并不直接使用路由表,而是通過一個路由適配層,路由適配層提供為IP層提供高性能的路由服務。

     路由表(Fib Table)

      數據結構:

      在整個策略性路由的框架里,路由表是最重要的的數據結構,我們在上面以及對路由表的概念和結構進行了清楚的說明。Linux里通過下面這些主要的數據結構進行實現的。

     

    主要的數據結構 作用 位置
    struct fib_table 路由表 ip_fib.h 116
    struct fn_hash 路由表的哈希數據 fib_hash.c 104
    struct fn_zone zone域 fib_hash.c 85
    struct fib_node 路由節點 fib_hash.c 68
    struct fib_info 路由信息 ip_fib.h 57
    struct fib_result 路由結果 ip_fib.h 86


      數據結構之間的主要關系如下。路由表由路由表號以及路由表的操作函數指針還有表數據組成。這里需要注意的是,路由表結構里并不直接定義zone域,而是通過一個數據指針指向fn_hash。只有當zone里有數據才會連接到fn_zone_list里。


      系統的所有的路由表由數組變量*fib_tables[RT_TABLE_MAX+1]維護,其中系統定義RT_TABLE_MAX為254,也就是說系統最大的路由表為255張,所有的路由表的操作都是對這個數組進行的。。同時系統還定義了三長路由表*local_table; *main_table。

      路由表的操作:

      Linux策略路由代碼的主要部分是對路由表的操作。對于路由表的操作,物理操作是直觀的和易于理解的。對于表的操作不外乎就是添加、刪除、更新等的操作。還有一種操作,是所謂的語義操作,語義操作主要是指諸如計算下一條的地址,把節點轉換為路由項,尋找指定信息的路由等。

      1、物理操作(operation):

      路由表的物理操作主要包括如下這些函數:


    路由標操作 實現函數 位置
    新建路由表    
    刪除路由表    
    搜索路由 fn_hash_lookup fib_hash.c 269
    插入路由到路由表 fn_hash_insert fib_hash.c 341
    刪除路由表的路由 fn_hash_delete
    fn_hash_dump
     fib_hash.c 433
    fib_hash.c 614
    更新路由表的路由 fn_hash_flush fib_hash.c 729
    顯示路由表的路由信息 fn_hash_get_info fib_hash.c 750
    選擇默認路由  fn_hash_select_default fib_hash.c 842


      2、語義操作(semantics operation):

      語義操作并不涉及路由表整體框架的理解,而且,函數名也是不言自明的,所以請大家參考fib_semantics.c。

      3、接口(front end)

      對于路由表接口的理解,關鍵在于理解那里有

       IP

       首先是路由表于IP層的接口。路由在目前linux的意義上來說,最主要的還是IP層的路由,所以和IP層的的接口是最主要的接口。和ip層的銜接主要是向IP層提供尋找路由、路由控制、尋找指定ip的接口。


    Fil_lookup
    ip_rt_ioctl fib_frontend.c 286;" f
    ip_dev_find 145


       Inet

      路由表還必須提供配置接口,即用戶直接操作路由的接口,例如增加和刪除一條路由。當然在策略性路由里,還有規則的添加和刪除。


    inet_rtm_delroute 351
    inet_rtm_newroute 366
    inet_check_attr 335


       proc

       在/proc/net/route里顯示路由信息。
       fib_get_procinfo

      4、網絡設備(net dev event)

      路由是和硬件關聯的,當網絡設備啟動或關閉的時候,必須通知路由表的管理程序,更新路由表的信息。


    fib_disable_ip 567
    fib_inetaddr_event 575
    fib_netdev_event


      5、內部維護( magic)

      上面我們提到,本地路由表(local table)的維護是由系統自動進行的。也就是說當用戶為硬件設置IP地址等的時候,系統自動在本地路由表里添加本地接口地址以及廣播地址。


    fib_magic 417
    fib_add_ifaddr 459
    fib_del_ifaddr 498


      Rule

      1、數據結構

      規則在fib_rules.c的52行里定義為 struct fib_rule。而RPDB里所有的路由是保存在101行的變量fib_rules里的,注意這個變量很關鍵,它掌管著所有的規則,規則的添加和刪除都是對這個變量進行的。

      2、系統定義規則:

      fib_rules被定義以后被賦予了三條默認的規則:默認規則,本地規則以及主規則。


    u 本地規則local_rule
    94 static struct fib_rule local_rule = {
    r_next: &main_rule, /*下一條規則是主規則*/
    r_clntref: ATOMIC_INIT(2),
    r_table: RT_TABLE_LOCAL, /*指向本地路由表*/
    r_action: RTN_UNICAST, /*動作是返回路由*/
    };

    u 主規則main_rule
    86 static struct fib_rule main_rule = {
    r_next: &default_rule,/*下一條規則是默認規則*/
    r_clntref: ATOMIC_INIT(2),
    r_preference: 0x7FFE, /*默認規則的優先級32766*/
    r_table: RT_TABLE_MAIN, /*指向主路由表*/
    r_action: RTN_UNICAST, /*動作是返回路由*/
    };
    u 默認規則default rule
    79 static struct fib_rule default_rule = {
    r_clntref: ATOMIC_INIT(2),
    r_preference: 0x7FFF,/*默認規則的優先級32767*/
    r_table: RT_TABLE_DEFAULT,/*指默認路由表*/
    r_action: RTN_UNICAST,/*動作是返回路由*/
    }; 


      規則鏈的鏈頭指向本地規則。

      RPDB的中心函數fib_lookup

      現在到了討論RPDB的實現的的中心函數fib_lookup了。RPDB通過提供接口函數fib_lookup,作為尋找路由的入口點,在這里有必要詳細討論這個函數,下面是源代碼:,


    310 int fib_lookup(const struct rt_key *key, struct fib_result *res)
    311 {
    312 int err;
    313 struct fib_rule *r, *policy;
    314 struct fib_table *tb;
    315
    316 u32 daddr = key->dst;
    317 u32 saddr = key->src;
    318
    321 read_lock(&fib_rules_lock);
    322 for (r = fib_rules; r; r=r->r_next) {/*掃描規則鏈fib_rules里的每一條規則直到匹配為止*/
    323 if (((saddr^r->r_src) & r->r_srcmask) ||
    324 ((daddr^r->r_dst) & r->r_dstmask) ||
    325 #ifdef CONFIG_IP_ROUTE_TOS
    326 (r->r_tos && r->r_tos != key->tos) ||
    327 #endif
    328 #ifdef CONFIG_IP_ROUTE_FWMARK
    329 (r->r_fwmark && r->r_fwmark != key->fwmark) ||
    330 #endif
    331 (r->r_ifindex && r->r_ifindex != key->iif))
    332 continue;/*以上為判斷規則是否匹配,如果不匹配則掃描下一條規則,否則繼續*/

    335 switch (r->r_action) {/*好了,開始處理動作了*/
    336 case RTN_UNICAST:/*沒有設置動作*/
    337 case RTN_NAT: /*動作nat ADDRESS*/
    338 policy = r;
    339 break;
    340 case RTN_UNREACHABLE: /*動作unreachable*/
    341 read_unlock(&fib_rules_lock);
    342 return -ENETUNREACH;
    343 default:
    344 case RTN_BLACKHOLE:/* 動作reject */
    345 read_unlock(&fib_rules_lock);
    346 return -EINVAL;
    347 case RTN_PROHIBIT:/* 動作prohibit */
    348 read_unlock(&fib_rules_lock);
    349 return -EACCES;
    350 }
    351 /*選擇路由表*/
    352 if ((tb = fib_get_table(r->r_table)) == NULL)
    353 continue;
    /*在路由表里尋找指定的路由*/
    354 err = tb->tb_lookup(tb, key, res);
    355 if (err == 0) {/*命中目標*/
    356 res->r = policy;
    357 if (policy)
    358 atomic_inc(&policy->r_clntref);
    359 read_unlock(&fib_rules_lock);
    360 return 0;
    361 }
    362 if (err < 0 && err != -EAGAIN) {/*路由失敗*/
    363 read_unlock(&fib_rules_lock);
    364 return err;
    365 }
    366 }
    368 read_unlock(&fib_rules_lock);
    369 return -ENETUNREACH;
    370 }


      上面的這段代碼的思路是非常的清晰的。首先程序從優先級高到低掃描所有的規則,如果規則匹配,處理該規則的動作。如果是普通的路由尋址或者是nat地址轉換的換,首先從規則得到路由表,然后對該路由表進行操作。這樣RPDB終于清晰的顯現出來了。

        IP層路由適配(IP route)

      路由表以及規則組成的系統,可以完成路由的管理以及查找的工作,但是為了使得IP層的路由工作更加的高效,linux的路由體系里,route.c里完成大多數IP層與RPDB的適配工作,以及路由緩沖(route cache)的功能。

      調用接口

      IP層的路由接口分為發送路由接口以及接收路由接口:

      發送路由接口

      IP層在發送數據時如果需要進行路由工作的時候,就會調用ip_route_out函數。這個函數在完成一些鍵值的簡單轉換以后,就會調用ip_route_output_key函數,這個函數首先在緩存里尋找路由,如果失敗就會調用ip_route_output_slow,ip_route_output_slow里調用fib_lookup在路由表里尋找路由,如果命中,首先在緩存里添加這個路由,然后返回結果。

     

    ip_route_out route.h
    ip_route_output_key route.c 1984;
    ip_route_output_slow route.c 1690;" 


      接收路由接口

      IP層接到一個數據包以后,如果需要進行路由,就調用函數ip_route_input,ip_route_input現在緩存里尋找,如果失敗則ip_route_inpu調用ip_route_input_slow, ip_route_input_slow里調用fib_lookup在路由表里尋找路由,如果命中,首先在緩存里添加這個路由,然后返回結果。


    ip_route_input_slow route.c 1312;" f
    ip_route_input route.c 1622;" f


      cache

      路由緩存保存的是最近使用的路由。當IP在路由表進行路由以后,如果命中就會在路由緩存里增加該路由。同時系統還會定時檢查路由緩存里的項目是否失效,如果失效則清除。


     

    文章來源于領測軟件測試網 http://www.kjueaiud.com/


    關于領測軟件測試網 | 領測軟件測試網合作伙伴 | 廣告服務 | 投稿指南 | 聯系我們 | 網站地圖 | 友情鏈接
    版權所有(C) 2003-2010 TestAge(領測軟件測試網)|領測國際科技(北京)有限公司|軟件測試工程師培訓網 All Rights Reserved
    北京市海淀區中關村南大街9號北京理工科技大廈1402室 京ICP備10010545號-5
    技術支持和業務聯系:info@testage.com.cn 電話:010-51297073

    軟件測試 | 領測國際ISTQBISTQB官網TMMiTMMi認證國際軟件測試工程師認證領測軟件測試網

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>