当前位置: 代码迷 >> 综合 >> net/ipv4/route.c文件分析
  详细解决方案

net/ipv4/route.c文件分析

热度:24   发布时间:2024-01-06 09:50:36.0

net/ipv4/route.c

author: elvis


目錄 介紹 route.c 的背景 routing 流程 相關資料結構 route.c 相關函數詳解

介紹 route.c 的背景

linux 在設定 route 有兩個機制,一個是 fib,一個是 dynamic 產生的 routing
fib 是利用 route (man 8 route) 指定來靜態 route table
而 net/ipv4/route.c 所做的則是動能產生 routing hash,以加快 route decision 的速度
範例:
  • 靜態 route table
    # route -F
    Kernel IP routing table
    Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
    192.168.1.3     *               255.255.255.255 UH    0      0        0 eth0
    140.123.103.156 *               255.255.255.255 UH    0      0        0 eth1
    192.168.1.0     *               255.255.255.0   U     0      0        0 eth0
    140.123.0.0     *               255.255.0.0     U     0      0        0 eth1
    127.0.0.0       *               255.0.0.0       U     0      0        0 lo
    default         CSIE-C5505      0.0.0.0         UG    0      0        0 eth1	
    
  • 動態 route table
    # route -C
    Kernel IP routing cache
    Source          Destination     Gateway         Flags Metric Ref    Use Iface
    infomedia.cs.cc 140.123.103.255 140.123.103.255 ri    0      6        0 eth1
    CSIE-C5505      not-a-legal-add not-a-legal-add ibl   0      796989       0 lo
    fish.cs.ccu.edu 140.123.103.255 140.123.103.255 ri    0      2        0 eth1
    didi.cs.ccu.edu 140.123.103.255 140.123.103.255 ri    0      31       0 eth1
    lena.cs.ccu.edu 140.123.103.255 140.123.103.255 ri    0      2438       0 eth1
    filter.cs.ccu.e 140.123.103.255 140.123.103.255 ri    0      265       0 eth1
    CSIE-C5505      ALL-SYSTEMS.MCA ALL-SYSTEMS.MCA ml    0      7273       0 lo
    vivi.cs.ccu.edu 140.123.103.255 140.123.103.255 ri    0      7        0 eth1
    gigi.cs.ccu.edu 140.123.103.255 140.123.103.255 ri    0      3        0 eth1
    scoap.cs.ccu.ed 140.123.103.255 140.123.103.255 ri    0      12       0 eth1
    bist.cs.ccu.edu 140.123.103.255 140.123.103.255 ri    0      86       0 eth1
    macgyver.cs.ccu 140.123.103.255 140.123.103.255 ri    0      11       0 eth1		
    
參考資料:
  • RFC 1122 有關 IP 層 routing 的說明 這裡
table

routing 流程

	一個 skb 要決定行走的路徑(input) 時
會呼叫如 ip_route_input(skb,...); 來決定他的 rtable
流程大概是
1.ip_route_input 查看是否有存在的 rtable
2.呼叫 ip_route_input_slow 產生 rtable
3.ip_route_input_slow 呼叫 fib_lookup
4.fib_lookup 從 fib_rules 找出 fib_rule
5.fib_lookup 呼叫 fib_get_table 來取得 fib_table
6.fib_lookup 使用 fib_table 呼叫 tb->tb_lookup 取得 fib_result
7.fib_lookup 將 fib_rule 設定給 fib_result
8.ip_route_input_slow 利用 rt_intern_hash 設定 rtable
9.返回 ip_route_input 此時 skb 已有設定好的 rtable還有 input/output 方法
10.返回原呼叫者
11.原呼叫者呼叫 dst->input() 處理
  • route 初始化
  • route 流程圖
  • 收進 skb 流程
  • 送出 skb 流程
table

相關資料結構

/* IPv4 routing cache flags */
#define RTCF_DEAD	RTNH_F_DEAD
#define RTCF_ONLINK	RTNH_F_ONLINK
/* Obsolete flag. About to be deleted */
#define RTCF_NOPMTUDISC RTM_F_NOPMTUDISC
#define RTCF_NOTIFY	0x00010000
#define RTCF_DIRECTDST	0x00020000
#define RTCF_REDIRECTED	0x00040000
#define RTCF_TPROXY	0x00080000
#define RTCF_FAST	0x00200000
#define RTCF_MASQ	0x00400000
#define RTCF_SNAT	0x00800000
#define RTCF_DOREDIRECT 0x01000000
#define RTCF_DIRECTSRC	0x04000000
#define RTCF_DNAT	0x08000000
#define RTCF_BROADCAST	0x10000000
#define RTCF_MULTICAST	0x20000000
#define RTCF_REJECT	0x40000000
#define RTCF_LOCAL	0x80000000
#define RTCF_NAT	(RTCF_DNAT|RTCF_SNAT)
routing type
enum
{
RTN_UNSPEC,
RTN_UNICAST,		/* Gateway or direct route	*/
RTN_LOCAL,		/* Accept locally		*/
RTN_BROADCAST,		/* Accept locally as broadcast,
send as broadcast */
RTN_ANYCAST,		/* Accept locally as broadcast,
but send as unicast */
RTN_MULTICAST,		/* Multicast route		*/
RTN_BLACKHOLE,		/* Drop				*/
RTN_UNREACHABLE,		/* Destination is unreachable   */
RTN_PROHIBIT,		/* Administratively prohibited	*/
RTN_THROW,		/* Not in this table		*/
RTN_NAT,			/* Translate this address	*/
RTN_XRESOLVE,		/* Use external resolver	*/
};
scope 的值
enum rt_scope_t
{
RT_SCOPE_UNIVERSE=0,
/* User defined values  */
RT_SCOPE_SITE=200,
RT_SCOPE_LINK=253,
RT_SCOPE_HOST=254,
RT_SCOPE_NOWHERE=255
};
用來查詢 fib table 的鍵值
struct rt_key @include/net/route.h
{
__u32	dst; 目的 ip 位址
__u32	src; 來源 ip 位址
int	iif; input interface
int	oif; output interface
__u8	tos; type of service
__u8	scope; Unknown
};
●route table 最主要的結構
一些判斷位址的 macro
#define LOOPBACK(x) (((x) & htonl(0xff000000)) == htonl(0x7f000000))
127.0.0.0/255.0.0.0 loopback
#define MULTICAST(x)    (((x) & htonl(0xf0000000)) == htonl(0xe0000000))
class D
1110 開頭
#define BADCLASS(x) (((x) & htonl(0xf0000000)) == htonl(0xf0000000))
class E 保留的區段,不應該有人用到
11110 開頭
#define ZERONET(x)  (((x) & htonl(0xff000000)) == htonl(0x00000000))
class A 且 netid 為 0000000 (七個 0)
#define LOCAL_MCAST(x)  (((x) & htonl(0xFFFFFF00)) == htonl(0xE0000000))
class D multicast ip
且 只有最小的 8bit
struct rtable @include/net/route.h
{
union
{
struct dst_entry	dst;
struct rtable	*rt_next;
} u;
unsigned	rt_flags;  RTCF_MULTICAST 之類的 flag
unsigned	rt_type;  RTN_UNICAST 之類的型態,用來表示此 route rule 是哪種型態
__u32	rt_dst;	/* Path destination	*/
__u32	rt_src;	/* Path source		*/
int	rt_iif;  incoming interface
/* Info on neighbour */
__u32	rt_gateway;
/* Cache lookup keys */
struct rt_key	key;
/* Miscellaneous cached information */
__u32	rt_spec_dst; /* RFC1122 specific destination */
inet_peer 的結構是個 avl tree 用來紀錄各個 peer 的資訊
詳細 implement 在 inetpeer.h 與 inetpeer.c
struct inet_peer	*peer; /* long-living peer info */
};
●rt_hash_table 使用的結構
struct rt_hash_bucket { @net/ipv4/route.c
struct rtable	*chain;
rwlock_t	lock;	鎖定狀態
} __attribute__((__aligned__(8)))
●route table 最主要操作的結構, 在 ip_rt_init 中配置空間且初始化
route rules 依 hash 串起來,其中 rt_hash_table[hash] 為一串
static struct rt_hash_bucket 	*rt_hash_table;
table

route.c 相關函數詳解


rt_hash_code rt_cache_get_info rt_cache_stat_get_info rt_free rt_drop
rt_fast_clean rt_valuable rt_may_expire rt_check_expire rt_run_flush
rt_cache_flush rt_garbage_collect rt_intern_hash rt_bind_peer ip_select_fb_ident
__ip_select_ident rt_del ip_rt_redirect ipv4_negative_advice ip_rt_send_redirect
ip_error guess_mtu ip_rt_frag_needed ip_rt_update_pmtu ipv4_dst_check
ipv4_dst_reroute ipv4_dst_destroy ipv4_link_failure ip_rt_bug ip_rt_get_source
rt_set_nexthop ip_route_input_mc ip_route_input_slow ip_route_input ip_route_output_slow
ip_route_output_key ip_rt_multicast_event ip_rt_init

static __inline__ unsigned rt_hash_code(u32 daddr, u32 saddr, u8 tos)
  • 功能:產生 hash 的值
  • 參數:位址和服務類型
  • 回傳:hash 值
  • 說明:rt_hash_table[hash]
static int rt_cache_get_info(char *buffer, char **start, off_t offset,int length)
  • 功能:給 proc fs 用的函式
static int rt_cache_stat_get_info(char *buffer, char **start, off_t offset, int length)
  • 功能:給 proc fs 用的函式
static __inline__ void rt_free(struct rtable *rt)
  • 功能:釋放 rtable->dst
  • 參數:rtable
  • 回傳:無
  • 說明:dst_free((&rt->u.dst)
static __inline__ void rt_drop(struct rtable *rt)
  • 功能:丟棄 rtable
  • 參數:rtable
  • 回傳:無
  • 說明:
    • ip_rt_put(); //dst_release(rt) 減少 rt->u.dst.__refcnt dst 使用的次數
    • dst_free((&rt->u.dst)
static __inline__ int rt_fast_clean(struct rtable *rth)
  • 功能:檢查是不是 broadcast/multicast
  • 說明:broadcast/multicast 的 rtable 應該優先被捨棄
static __inline__ int rt_valuable(struct rtable *rth)
  • 功能:檢查是不是 redirect/notify rtable
static __inline__ int rt_may_expire(struct rtable *rth, int tmo1, int tmo2)
  • 功能:檢查 rtable 是否過期應該廢棄
  • 參數:tmo1,tmo2 (tmo2 > tmo1,tmo2 harder than tmo1)
  • 回傳:是否過期
  • 說明:
    • 349:還有在使用(__refcnt不會0) 則回傳否
    • 353:已達這個 rtable 的 expire time,回傳是
    • 359:age = 距最後一次使用的時間
      假如 age <= tmo1 且不是屬於 broadcast 或 multicast rtable 則回傳否
      都優先清除 broadcast/multicast 的 rtable
      (使用 rt_fast_clean)
      假如 age <= tmo2 且 rtable 是屬於 redirected 或 notify
      雖已經超過 tmo1 也回傳否(比較重要)
      (使用 rt_valuable)
    • 362:預設是 expire
static void SMP_TIMER_NAME( rt_check_expire)(unsigned long dummy)
  • 功能:強制 rt_free 掉 rt_hash_table[] chain 中的 expire entries
  • 說明:此函數為 timer 的 timer function
    每 ip_rt_gc_interval 呼叫一次
static void SMP_TIMER_NAME( rt_run_flush)(unsigned long dummy)
  • 功能:
    • 清除所有的 rtable
    • rt_flush_timer 的 timer function
    • also called by rt_cache_flush()
  • 說明:依序將 rt_hash_table[] 中的 rtable rt_free 掉
void rt_cache_flush(int delay)
  • 功能:delay 幾個 jiffies 後,call rt_flush_timer()
  • 說明:
    • 449:移除 rt_flush_timer,重算 delay
    • 472:重設 rt_deadline
    • 475:加上 rt_flush_timer
      第一次的 rt_flush_timer 在這裡被掛上
  • Note:delay 一開始不為 0,怎麼才會呼叫 rt_run_flush()
    不過似乎只會用 0,-1 來呼叫
static int rt_garbage_collect(void)
  • 功能:maintain routing cache
    動態調整routing cache 的有效時間,使其產生/過期的 rtable 速率相同
  • 說明:
    • 506:檢查上次的執行時間,garbage collection 不需要太常做(很費資源)
      (時間間格太小或要清掉的東西不夠多,不做)
    • 511-527:計算現在要清除過期 rtable的個數
    • 529:記錄這次 garbage collection 的時間
    • 537-585:開始做 garbage collection
      • 540-559:從上次做完的 hash chain 開始(rover)
        541:用 rt_may_expire檢查是否 expire
        把 tmo 減半增加來找 expire 的 entries的機率
        (因為有可能是因為 traffic 太高,需要做快速的 expire
      • 583:要清的 entries 小於 rtable 的最大值就不需要做了
      • 577:expire >>=1
        要是 traffic 過高,很可能一個 hash chain 做不完
        減小 expire 來限制 routing cache 的大小
    • 585:從 interrupt 呼叫這個 function 則只跑過一次
      就強制返回
    • 589:net_ratelimit()
      限制 garbage collection 的速率
    • 594:重設 expire
static int rt_intern_hash(unsigned hash, struct rtable *rt, struct rtable **rp)
  • 功能:將 rtable 加入 chain 中
  • 說明:
    • 616:從 rt_hash_table[hash] 中找相同 key 的 rtable
      使用次數 +1 並將傳入的 rt rt_drop 掉
    • 638:找不到現存的 rtable,若 rtable type 為 unicast forwarding path 或為 output route
      則產生一個 dst - arp_bind_neighbour()
      output route 或 unicast forward 時要 bind arp,因為是出去
    • 653: arp_bind_neighbour 失敗, 做 rt_garbage_collect 來縮小 route table
      然後重新再行執行一次
    • 670:將新產生的 rtable 掛上 rt_hash_table[hash].chain
void rt_bind_peer(struct rtable *rt, int create)
  • 功能:建立 rt->peer
  • 說明:
    • 692:inet_getpeer(); 定義在 net/ipv4/inetpeer.c
    • 700:假如已經存在 rt->peer,則把產生的 peer 拿掉(inet_putpeer())
  • Note:peer 是各點(每個ipv4 addess)資訊
static void ip_select_fb_ident(struct iphdr *iph)
  • 功能:強制產生 ip id
  • 說明:只有在 __ip_select_ident 中 rt_bind_peer 失敗才會執行這個函數來強生 random 的 ip id
  • 原註解:
    /*
    * Peer allocation may fail only in serious out-of-memory conditions. However
    * we still can generate some output.
    * Random ID selection looks a bit dangerous because we have no chances to
    * select ID being unique in a reasonable period of time.
    * But broken packet identifier may be better than no packet at all.
    */
void __ip_select_ident(struct iphdr *iph, struct dst_entry *dst)
  • 功能:
  • 說明:
    • 730:rt_bind_peer
    • 735:rt_bind_peer 成功或 rt->peer本來就存在
      inet_getid() 給予 ip id
    • 742:rt_bind_peer fail
      ip_select_fb_ident()
static void rt_del(unsigned hash, struct rtable *rt)
  • 功能:移除指定hash中的 rtable
  • 參數:hash,rtable
  • 回傳:
  • 說明:從 rt_hash_table[hash] 中找出 rt,rt_free() 掉它
void ip_rt_redirect(u32 old_gw, u32 daddr, u32 new_gw,u32 saddr, u8 tos, struct net_device *dev)
  • 功能:redirect,設定新的 rtable
  • 說明:找到原來的 rtable,將原來的資訊複制後
    修改 gateway,flags 等轉送要改的資訊,移除原來的 rtable
  • 使用:net/ipv4/icmp.c icmp_redirect()
static struct dst_entry * ipv4_negative_advice(struct dst_entry *dst)
  • 功能:處理毀損的 dst
  • 說明:
    • 891:obsolete,ip_rt_put() it
    • 894:redirect 的 dst 或 expire 掉的 rt_del掉
void ip_rt_send_redirect(struct sk_buff *skb)
  • 功能:轉送 skb
  • 說明: called by ip_forward()
    • 942:經過 ip_rt_redirect_silence 長的時間沒轉送過 skb 則 reset 狀態
    • 948:太多 redirect 封包,忽略(假定 host 不理我們的 redirect 封包,ip_forward() 就得幫他送 -_-")
      上次 rate_last設為現在時間
    • 956:check load
    • 958:傳送 icmp 封包
static int ip_error(struct sk_buff *skb)
  • 功能:檢查 rt->u.dst.error
    然後利用icmp_send() 送出對應的錯誤訊息
  • 說明:1001:上一個發生 ip_error() 的 時間太短也不送
static __inline__ unsigned short guess_mtu(unsigned short old_mtu)
  • 從 mtu_plateau[] 中找出小於且最接近 old_mut 的 mtu 值
    預設是 68
unsigned short ip_rt_frag_needed(struct iphdr *iph, unsigned short new_mtu)
  • 功能:拆開封包,需要重新計算 mtu
  • 說明:
    • 1045:找到這個 ip header 所用的 rtable
    • 1056-1079:計算新的 mtu
void ip_rt_update_pmtu(struct dst_entry *dst, unsigned mtu)
  • 功能:設定新的 mtu
  • 說明:
    • 1096:設定 dst 的有效時間
      dst_set_expires() 定義在 include/net/dst.h
static struct dst_entry * ipv4_dst_check(struct dst_entry *dst, u32 cookie)
  • 功能:用法 unknown
  • 說明:ipv4_dst_ops 的 check funtion
    release 傳進的 dst //dst_release();
static struct dst_entry * ipv4_dst_reroute(struct dst_entry *dst,struct sk_buff *skb)
  • 功能:用法 unknown
  • 說明:ipv4_dst_ops 的 reroute function
  • Note:Linux 在 2.2/2.4 kernel 皆未實作它
static void ipv4_dst_destroy(struct dst_entry *dst)
  • 功能:回收 dst peer
  • 說明:
    • 1118:rt->peer = NULL;
    • 1119:inet_putpeer(peer); 定義在 include/net/inetpeer.h 將 rt->peer 放到 unused list
static void ipv4_link_failure(struct sk_buff *skb)
  • 功能:利用 icmp 告知目的位址無法連結
  • 參數:skb
  • 說明:
    • 1127:送出 icmp 告知目的位址無法連結
    • 1130:設定此路徑立即失效(expire time == 0)
static int ip_rt_bug(struct sk_buff *skb)
  • 功能:輸出 skb 資訊,並 kfree_skb()
    ip_route_input_mc() 指定為 dst 的 output function (rth->u.dst.output= ip_rt_bug;)
void ip_rt_get_source(u8 *addr, struct rtable *rt)
  • 功能:取得 source address,從哪個 interface 出去的,ip address 就設為它
  • 說明:因為沒有 cache outgoing route 的 source address
    所以利用這個函數取得
    • 1157:iif==0,直接指定 rt->rt_src 給他
    • 1159:從 fib 找
    • 1169:用 inet_select_addr() 找
static void rt_set_nexthop(struct rtable *rt, struct fib_result *res, u32 itag)
  • 功能:依據 fib_result 的資訊來設定下一個 hop 的資訊
int ip_route_input(struct sk_buff *skb, u32 daddr, u32 saddr,u8 tos, struct net_device *dev)
  • 功能:利用 rt_key 找出 input 的 rtable
  • 說明:
    • 1633-1655:從 rt_hash_table[] 中找出相符 rt_key 的 rtable(且oif==0)
    • 1505:實際產生 rt_intern_hash() 不檢查 tos(因為 tos 不同..rt_hash_code() 出來的也不會一樣)
    • 1668-1686:假如是 multicast address,且在 dev 的 multicast list 中
      呼叫 ip_route_input_mc() 來產生 entry
    • 1687:不是 multicast 也沒找到已經產生的 entry
      利用 ip_route_input_slow() 新增 entry
  • Note:called by
    net/ipv4/arp.c arp_rcv()
    net/ipv4/ipip.c ipip_err()
    net/ipv4/ip_gre.c ipgre_err()
    net/ipv4/ip_input.c ip_rcv_finish()
    net/ipv4/ip_options.c ip_options_rcv_srr()
    net/ipv4/netfilter/ip_fw_compat.c fw_in()
int ip_route_input_slow(struct sk_buff *skb, u32 daddr, u32 saddr,u8 tos, struct net_device *dev)
  • 功能:判斷從外面收進的 skb 的去處
  • 說明:
    • 前置工作
      • 1336-1346:初始化 key,跟算出 hash
        key.dst daddr
        key.src saddr
        key.tos tos
        key.iif dev->ifindex
        key.oif 0 沒有 output dev
        key.scope RT_SCOPE_UNIVERSE
      • 1352:檢查 saddr,不可為 multicast(class D address), badclass(class E address),loopback address
      • 1355-1365:除了 0xffffffff 外的 zeronet saddr 皆為 bad source
        1355:若為 broadcast(daddr 為 0xffffffff 或 saddr/daddr 都為 0x0), 跳到 brd_input 處理,這些都是 broadcast
      • 1364:檢查 daddr,不可為 badclass(class E address), zeronet,loopback
      • 1370:fib_lookup 依據 key 值找出 res (result)
      • 1404:為 broadcast type brd_input
      • 1407:為 local type
    • 真正進行 route 產生
      • Ⅰ?ip_forward()
        一般的 route table(需轉送)
          • 1437:fib_validate_source 檢查來源是否正確,not broadcast or our local address 確定 spec_dst
          • 1445:flags 加上 RTCF_DOREDIRECT
            表示並不是最佳的路徑,redirect host
          • 1458:dst_alloc() 一個新的 route table
            1462-1491:填入 route table 資料
            out_dev in_dev_get(FIB_RES_DEV(res))
            spec_dst fib_validate_source()
            flags |= RTCF_DIRECTSRC if fib_validate_source err
            flags |= RTCF_DOREDIRECTSRC if 該通知轉送
            rth->u.dst.__refcnt 1
            rth->key.dst daddr
            rth->rt_dst daddr
            rth->key.tos tos
            rth->key.src saddr
            rth->rt_src saddr
            rth->rt_gateway daddr
            rth->rt_iif dev->ifindex
            rth->key.iif dev->ifindex
            rth->u.dst.dev out_dev->dev
            rth->u.dst.dev.refcnt ++
            rth->key.oif 0
            rth->rt_spec_dst spec_dst
            rth->u.dst.input ip_forward
            rth->u.dst.output ip_output
            rth->rt_flags flags
          • 1485:dst.input = ip_forward
          • 1505:實際產生 rt_intern_hash()
      • Ⅱ?ip_local_deliver()
        broadcast route table
        • 設定 type/flags 檢查 saddr,因為不需要 forward 出去
          spec_dst inet_select_addr(dev, 0, RT_SCOPE_LINK) if ZERONET
          spec_dst fib_validate_source(saddr, 0, tos, 0, dev, &spec_dst,&itag) if not ZERONET
          flags |= RTCF_DIRECTSRC if fib_validate_source err
          flags |= RTCF_BROADCAST
          res.type RTN_BROADCAST
          利用 local input route table部份 code 來產生 route table 資料
        local input route table
        • 1409:fib_valid_source()
        • 1414:if (result) flags 加上 RTCF_DIRECTSRC
        • 配置 route table 並填入資料
          rth->u.dst.output ip_rt_bug ip_rt_bug()
          rth->u.dst.__refcnt 1
          rth->key.dst daddr
          rth->rt_dst daddr
          rth->key.tos tos
          rth->key.src saddr
          rth->rt_src saddr
          rth->rt_iif dev->ifindex
          rth->key.iif dev->ifindex
          rth->u.dst.dev &loopback_dev
          rth->u.dst.dev->refcnf ++
          rth->key.oif 0
          rth->rt_gateway daddr
          rth->rt_spec_dst spec_dst = daddr
          rth->u.dst.input ip_local_deliver ip_local_deliver()
          rth->rt_flags |= RTCF_LOCAL
          rth->rt_rype res.type
          如果 res.type == RTN_UNREACHABLE
          rth->u.dst.input ip_error ip_error
          rth->u.dst.error -err
          rth->rt_flags &= ~RTCF_LOCAL 把剛設的拿掉
        • 1563:input 正常的話為 ip_local_deliver() 往上層丟
        • 1566:unreachable 則為 ip_error() 來處理
        • 1505:實際產生 rt_intern_hash()
      • Ⅲ?no route
        • route type = unreachable then do Ⅲ?local_input
static int ip_route_input_mc(struct sk_buff *skb, u32 daddr, u32 saddr,u8 tos, struct net_device *dev, int our)
  • 功能:產生 multicast address 的 input rtable
  • 說明:
    • 1238-1248:檢查 saddr/daddr 的正確性
    • 1250-1285:填入資訊, 如果在 device 的 multicast list,則 input function 為 ip_local_deliver()
    • 1294:rt_intern_hash()
int ip_route_output_key(struct rtable **rp, const struct rt_key *key)
    • 功能:利用 rt_key 找出 output 的 rtable
    • 參數:rtable
  • 說明:
    • 1993-2017:在 rt_hash_table[] 中找相符的 rtable
    • 2019:找不到,則利用
    ip_route_output_slow() 產生 entry
  • Note:2.2 版的相對應函數為 ip_route_output()
(struct rtable **rp, const struct rt_key *key)
  • 功能:利用 rt_key 找出 output 的 rtable
  • 參數:rtable
  • 說明:
    • 1993-2017:在 rt_hash_table[] 中找相符的 rtable
    • 2019:找不到,則利用 ip_route_output_slow() 產生 entry
  • Note:2.2 版的相對應函數為 ip_route_output()
int ip_route_output_slow(struct rtable **rp, const struct rt_key *oldkey)
  • 功能:產生 output routing cache/rtable
  • 說明:
    • 1722:if (oldkey-gtsrc)
      • 1724:檢查 oldkey->src 的位址型態(multicast/badclass/zeronet return error)
      • 1730:利用 src 找出去的第一個 device ip_dev_find() net/ipv4/fib_frontend.c
      • 1742-1761:oldkey->oif ==0 且 oldkey->dst 是 multicast 或 0xffffffff
        key.oif = dev_out->ifindex,直接 make route
      • 1762-1764:檢查完後 dev_out 不需要了
    • 1766-1790:if (oldkey->oif)
      依 oldkey->dst 型態找出 key.src
    • 1792-1804:沒有 key.dst,設成 loopback,make route
    • 1806:if (fib_lookup()) if(找得到 fib entry)
      • 存在 oldkey->oif,則 type = unicast ,不經 gateway make_route
        否則 error
    • 1843-1856:loopback, 設定 dev,oif make route
    • 1863-1873:以上皆不符合,預設資料設定
      • 1864:fib_select_default()
      • 1867:FIB_RES_PREFSRC()
        include/net/ip_fib.h
        #define FIB_RES_PREFSRC(res) ((res).fi->fib_prefsrc ? : __fib_res_prefsrc(&res))
      • 1869:取消先前找出的 dev_out
        dev_out = FIB_RES_DEV
        inlcude/net/ip_fib.h
        #define FIB_RES_DEV(res) (FIB_RES_NH(res).nh_dev)
      • 1872:dev_hold() dev_out->refcnt++
    • 1875:make_route:
      • 1876:no loopback src address error
      • 1879-1884:依 dst 位址型態設定 res.type
        no badclass/zeronet dst address error
      • 1889-1894:處理 broadcast
        fib_info_put() include/net/ip_fib.h fi 不使用了
        不知道為啥要 broadcast 就 dec fi
      • 1912-1965:配置 dst 並填 rth/rth->dst 資料
      • 1967:rt_set_nexthop
      • 1972:rt_intern_hash
void ip_rt_multicast_event(struct in_device *in_dev)
  • 功能:在 multicast 狀態改變時要清掉 cache
    called by net/ipv4/igmp.c#451 ip_mc_inc_group() #471 ip_mc_dec_group(0
    called by net/ipv4/ipmr.c#232 vif_delete() #775 ip_mroute_setsockopt()
  • 參數:in_device
  • 回傳:
  • 說明:
    • 2230:強制 rt_cache_flush(0);
      清掉 routing table cache no delay
void __init ip_rt_init(void)
  • 功能:kernel 一開始初始 route table 的初始函數
  • 參數:
  • 回傳:
  • 說明:初始化流程
    • 2474:kmem_cache_create() 建立 kernel cache for ip dst cache
    • 2482-2497:配置 rt_hash_table 的記憶體
    • 2506:rt_hash_table initial
    • 2512,2513:初始化 ipv4_dst_ops.gc_thresh ip_rt_max_size
    • 2515:devinet_init();
    • 2516:ip_fib_init();
    • 2517:rt_flush_timer 雖然被宣告,也指定 timer function
      但是從未被初始化過,只有在第一次呼叫完了 rt_cache_flush() 後
      才會真正被啟動
    • 2519-2526:add_timer(&rt_periodic_timer); timer function 為 rt_check_expire
    • 2528,2529:proc fs 相關的資訊
table 問題
 
  
  • RTCF_DIRECTSRC 不知道幹嘛的 唯一用到的地方 icmp.c icmp_address_reply() if (skb->len < 4 || !(rt->rt_flags&RTCF_DIRECTSRC)) return;
  相关解决方案