http://www.cs.ccu.edu.tw/~cwr87u/Project_undergraduate/linux_firewall/www/net/ipv4/route.c.html
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)
static int
rt_cache_stat_get_info(char *buffer, char **start, off_t offset, int length)
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()
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;