704
技術社區[雲棲]
網絡子係統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