837
技術社區[雲棲]
網絡子係統61_路由子係統初始化
// 路由緩存內存量指定辦法: // 1.通過啟動參數rhash_entries指定hash表bucket個數 // 2.根據物理內存頁數確定使用的內存量 // 根據物理頁數分配緩存內存: // 1.goal目標內存頁數=總頁數/(2**(26-PAGE_SHIFT)) // 2.最接近goal內存頁數的order,用於從夥伴係統中分配 // 3.rt_hash_mask=order頁可容納的bucket數 // 4.對齊rt_hash_mask到2的冪次 // 5.從夥伴係統中分配order頁物理內存 // 路由緩存閾值: // 1.gc_thresh=bucket個數,當路由緩存數超過此閾值時,rt_garbage_collect同步回收內存 // 2.ip_rt_max_size=16*(bucket個數),當路由緩存超過此閾值時,dst_alloc會失敗 // 路由子係統初始化 // 調用路徑:ip_init->ip_rt_init // 函數主要任務: // 1.分配dst緩存的slab緩存 // 2.分配路由緩存表 // 3.向netdev_chain注冊監聽塊 // 4.初始化默認路由表 // 5.初始化路由緩存使用的定時器 // 5.1 垃圾回收定時器 // 5.2 緩存刷新定時器 // 5.3 緩存周期性刷新定時器 // 6.初始化IPSec與路由子係統交互的銜接點 1.1 int __init ip_rt_init(void) { int i, order, goal, rc = 0; // rt_hash_rnd = (int) ((num_physpages ^ (num_physpages>>8)) ^ (jiffies ^ (jiffies >> 7))); //dst緩存 ipv4_dst_ops.kmem_cachep = kmem_cache_create("ip_dst_cache", sizeof(struct rtable), 0, SLAB_HWCACHE_ALIGN, NULL, NULL); //根據物理內存數計算路由緩存使用的內存頁數 goal = num_physpages >> (26 - PAGE_SHIFT); if (rhash_entries)//rhash_entries為啟動參數, goal = (rhash_entries * sizeof(struct rt_hash_bucket)) >> PAGE_SHIFT; //計算緩存使用內存頁個數以2為底的order for (order = 0; (1UL << order) < goal; order++); //rt_hash_mask為bucket的個數 do { rt_hash_mask = (1UL << order) * PAGE_SIZE / sizeof(struct rt_hash_bucket); //使rt_hash_mask 對齊到2的冪次 while (rt_hash_mask & (rt_hash_mask - 1)) rt_hash_mask--; //分配路由緩存 rt_hash_table = (struct rt_hash_bucket *) __get_free_pages(GFP_ATOMIC, order); } while (rt_hash_table == NULL && --order > 0); for (rt_hash_log = 0; (1 << rt_hash_log) != rt_hash_mask; rt_hash_log++); //初始化每個bucket使用的自選鎖 rt_hash_mask--; for (i = 0; i <= rt_hash_mask; i++) { spin_lock_init(&rt_hash_table[i].lock); rt_hash_table[i].chain = NULL; } //垃圾回收的域值 ipv4_dst_ops.gc_thresh = (rt_hash_mask + 1); //路由緩存最多保存的緩存個數 ip_rt_max_size = (rt_hash_mask + 1) * 16; //per-cpu統計變量 rt_cache_stat = alloc_percpu(struct rt_cache_stat); //向netdev_chain注冊監聽塊,用netlink為地址和路由命令注冊處理函數 devinet_init(); //初始化默認路由表 ip_fib_init(); //緩存刷新定時器 init_timer(&rt_flush_timer); rt_flush_timer.function = rt_run_flush; //垃圾回收定時器 init_timer(&rt_periodic_timer); rt_periodic_timer.function = rt_check_expire; //緩存刷新周期定時器 init_timer(&rt_secret_timer); rt_secret_timer.function = rt_secret_rebuild; rt_periodic_timer.expires = jiffies + net_random() % ip_rt_gc_interval + ip_rt_gc_interval; add_timer(&rt_periodic_timer); rt_secret_timer.expires = jiffies + net_random() % ip_rt_secret_interval + ip_rt_secret_interval; add_timer(&rt_secret_timer); //處理路由子係統與IPSec的銜接 #ifdef CONFIG_XFRM xfrm_init(); xfrm4_init(); #endif return rc; } // 監聽外部事件 // 調用路徑:ip_rt_init->devinet_init 1.2 void __init devinet_init(void) { //netdev_chian監聽塊 register_netdevice_notifier(&ip_netdev_notifier); //通過netlink為路由命令注冊處理程序 rtnetlink_links[PF_INET] = inet_rtnetlink_table; }
最後更新:2017-04-03 14:53:48