閱讀837 返回首頁    go 技術社區[雲棲]


網絡子係統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

  上一篇:go 導入Excel出錯引出兩類異常——數據庫異常和業務異常處理方式
  下一篇:go 2013-10-18