網絡子係統69_路由表輔助程序
// 關閉設備上的ip協議
// 函數主要任務:
// 1.刪除與設備相關的路由信息
// 2.刷新路由緩存
// 3.通知鄰居子係統,與該設備有關的鄰居項失效
1.1 static void fib_disable_ip(struct net_device *dev, int force)
{
if (fib_sync_down(0, dev, force))
fib_flush();
rt_cache_flush(0);
arp_ifdown(dev);
}
// 設備狀態改變/刪除ip,標記失效路由信息
// 參數:
// local,被刪除的ip地址
// dev,被關閉的設備
// force:
// 0, local有效,表示ip地址被刪除
// 1, dev有效,表示dev被關閉
// 2, dev有效,表示dev被注銷
// 返回值:返回標記為dead的fib_info的數量
// 函數主要任務:
// 1.ip地址被刪除
// 1.1 遍曆fib_info_laddrhash,標記所有使用該地址作為首選源地址的fib_info->fib_flags|=RTNH_F_DEAD
// 2.設備狀態發生改變
// 2.1 遍曆fib_info_devhash,標記所有使用該設備的fib_nh->nh_flags|=RTNF_F_DEAD,如果fib_info的所有下一跳均失效,
// 或者設備注銷,則標記fib_info->fib_flags|=RTNH_F_DEAD
// 3.返回失效fib_info個數
// 注:
// 1.
// fib_info_hash 所有fib_info結構被插入到這個hash表
// fib_info_laddrhash 路由表項有一個首選源地址時,插入到這個表
// 2.
// fib_create_info 添加新fib_info到fib_info_hash, fib_info_laddrhash,fib_info_cnt統計實例個數,當超過
// fib_hash_size時,fib_info_hash, fib_info_laddrhash容量同時增加一倍。
// 3.
// fib_info_devhash 索引與設備相關的所有下一跳的hash表
// 4.
// fib_info_devhash 靜態分配256個bucket
2.1 int fib_sync_down(u32 local, struct net_device *dev, int force)
{
int ret = 0;
int scope = RT_SCOPE_NOWHERE;
//表示設備狀態發生改變
if (force)
scope = -1;
//1.處理ip地址被刪除
if (local && fib_info_laddrhash) {
unsigned int hash = fib_laddr_hashfn(local);
struct hlist_head *head = &fib_info_laddrhash[hash];
struct hlist_node *node;
struct fib_info *fi;
//遍曆fib_info_laddr的bucket
hlist_for_each_entry(fi, node, head, fib_lhash) {
//凡是與該首選源地址相關的路由信息,均標識為失效
if (fi->fib_prefsrc == local) {
fi->fib_flags |= RTNH_F_DEAD;
ret++;//統計標識為失效的節點個數
}
}
}
//2.處理設備狀態改變
if (dev) {
struct fib_info *prev_fi = NULL;
//對設備index hash
unsigned int hash = fib_devindex_hashfn(dev->ifindex);
struct hlist_head *head = &fib_info_devhash[hash];
struct hlist_node *node;
struct fib_nh *nh;
//遍曆使用該設備的下一跳
hlist_for_each_entry(nh, node, head, nh_hash) {
struct fib_info *fi = nh->nh_parent;
int dead;
if (nh->nh_dev != dev || fi == prev_fi)
continue;
prev_fi = fi;
dead = 0;
//遍曆路由信息的所有下一跳
change_nexthops(fi) {
//統計失效的下一跳個數
if (nh->nh_flags&RTNH_F_DEAD)
dead++;
else if (nh->nh_dev == dev &&
nh->nh_scope != scope) {
nh->nh_flags |= RTNH_F_DEAD;
//多路徑路由
#ifdef CONFIG_IP_ROUTE_MULTIPATH
//下一跳失效,調整路由權重
spin_lock_bh(&fib_multipath_lock);
fi->fib_power -= nh->nh_power;
nh->nh_power = 0;
spin_unlock_bh(&fib_multipath_lock);
#endif
dead++;
}
#ifdef CONFIG_IP_ROUTE_MULTIPATH
//設備注銷,與該設備相關的路由信息均失效
if (force > 1 && nh->nh_dev == dev) {
dead = fi->fib_nhs;
break;
}
#endif
} endfor_nexthops(fi)
//所有下一跳均失效,則標記該路由信息失效
if (dead == fi->fib_nhs) {
fi->fib_flags |= RTNH_F_DEAD;
ret++;
}
}
}
return ret;
}
// 刪除失效路由信息
// 函數主要任務:
// 1.由路由表刷新路由表
// 2.刷新路由緩存
3.1 static void fib_flush(void)
{
int flushed = 0;
// 編譯支持多路由表
#ifdef CONFIG_IP_MULTIPLE_TABLES
struct fib_table *tb;
int id;
//遍曆255個路由表
for (id = RT_TABLE_MAX; id>0; id--) {
if ((tb = fib_get_table(id))==NULL)
continue;
//特定於路由表的刷新操作
flushed += tb->tb_flush(tb);
}
#else /* CONFIG_IP_MULTIPLE_TABLES */
flushed += ip_fib_main_table->tb_flush(ip_fib_main_table);
flushed += ip_fib_local_table->tb_flush(ip_fib_local_table);
#endif /* CONFIG_IP_MULTIPLE_TABLES */
//刪除的路由個數>0,刷新路由緩存
if (flushed)
rt_cache_flush(-1);
}
// 設備開啟,激活使用該設備的下一跳
// 在路由的某些下一跳為alive時,更新fib_info結構內該路由的一些參數。
// 返回值:RTNH_F_DEAD標識被清除的fib_info結構的個數
// 函數主要任務:
// 1.1 遍曆與設備相關的下一跳信息
// 1.2 清除下一跳的RTNH_F_DEAD標誌
// 1.3 清除該下一跳相關的路由信息的RTNH_F_DEAD標誌
// 1.4 返回清除RTNH_F_DEAD標誌的fib_info個數
// 注:隻有內核支持多路徑路由時才使用該函數
4.1 int fib_sync_up(struct net_device *dev)
{
struct fib_info *prev_fi;
unsigned int hash;
struct hlist_head *head;
struct hlist_node *node;
struct fib_nh *nh;
int ret;
//設備需要開啟狀態
if (!(dev->flags&IFF_UP))
return 0;
prev_fi = NULL;
hash = fib_devindex_hashfn(dev->ifindex);
head = &fib_info_devhash[hash];
ret = 0;
//與設備相關的所有下一跳
hlist_for_each_entry(nh, node, head, nh_hash) {
struct fib_info *fi = nh->nh_parent;
int alive;
if (nh->nh_dev != dev || fi == prev_fi)
continue;
prev_fi = fi;
alive = 0;
//遍曆路由信息的下一跳,統計有效下一跳的個數
change_nexthops(fi) {
if (!(nh->nh_flags&RTNH_F_DEAD)) {
alive++;
continue;
}
if (nh->nh_dev == NULL || !(nh->nh_dev->flags&IFF_UP))
continue;
if (nh->nh_dev != dev || __in_dev_get(dev) == NULL)
continue;
alive++;
//設備開啟,清除之前由於設備關閉而設置的RTNH_F_DEAD標誌
spin_lock_bh(&fib_multipath_lock);
nh->nh_power = 0;
nh->nh_flags &= ~RTNH_F_DEAD;
spin_unlock_bh(&fib_multipath_lock);
} endfor_nexthops(fi)
//隻要路由信息有一個有效的下一跳,則該路由信息有效
if (alive > 0) {
fi->fib_flags &= ~RTNH_F_DEAD;
ret++;
}
}
return ret;
}
// 綁定路由緩存到鄰居子係統
5.1 int arp_bind_neighbour(struct dst_entry *dst)
{
struct net_device *dev = dst->dev;
struct neighbour *n = dst->neighbour;
if (dev == NULL)
return -EINVAL;
//此路由緩存還沒有綁定鄰居項
if (n == NULL) {
u32 nexthop = ((struct rtable*)dst)->rt_gateway;
//回環設備,點到點設備不需要綁定到鄰居子係統
if (dev->flags&(IFF_LOOPBACK|IFF_POINTOPOINT))
nexthop = 0;
//根據出口設備,下一跳地址,尋找鄰居項
n = __neigh_lookup_errno(
&arp_tbl, &nexthop, dev);
//綁定到路由緩存
dst->neighbour = n;
}
return 0;
}
最後更新:2017-04-03 14:53:48