最近学习路由子系统,进行了一些总结。因为个人喜欢比较喜欢ubuntu的哲学精神,因此想将自己在技术上的一些总结进行记录,一是做为一种记录方便以后查阅,二是做为一种分享吧。有什么不对的地方,请不吝赐教,本人将感激不尽!
内核版本是linux-2.6.31.8
介绍路由子系统的初始化流程
inet_init() @net/ipv4/Af_inet.c
--- >ip_init() @net/ipv4/ip_output.c
//路由子系统初始化函数
--->ip_rt_init() @net/ipv4/route.c
//使用通知链注册一个处理函数,用Netlink套接字为地址和路由命令注册处理函数
--->devinet_init() @net/ipv4/devinet.c
//初始化默认路由表,用两个通知链注册两个处理函数
注册了对ipv4路由表进行操作的接口
--->ip_fib_init() @net/ipv4/fib_frontend.c
- <span style="color:#FF0000;">//路由子系统相关的初始化工作在这个函数里完成</span>
- int __init ip_rt_init(void)
- {
-
- intrc = 0;
-
- #ifdef CONFIG_NET_CLS_ROUTE
-
- ip_rt_acct= __alloc_percpu(256 * sizeof(struct ip_rt_acct), __alignof__(structip_rt_acct));
-
- if(!ip_rt_acct)
-
- panic("IP:failed to allocate ip_rt_acct\n");
-
- #endif
-
- <span style="color:#FF0000;">//ipv4_dst_ops提供了一组虚函数,这些函数能使更高层的协议调用具体协议中操作缓存表项的函数;分配新的缓存表项时会用到dst_alloc(&ipv4_dst_ops)dst_alloc(&ip6_dst_ops)</span>
- ipv4_dst_ops.kmem_cachep = kmem_cache_create("ip_dst_cache",sizeof(struct rtable), 0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);
-
- ipv4_dst_blackhole_ops.kmem_cachep= ipv4_dst_ops.kmem_cachep;
-
- <span style="color:#FF0000;">//用hash表定义的路由缓存,这里为路由缓存分配内存</span>
- rt_hash_table = (struct rt_hash_bucket *)
-
- alloc_large_system_hash("IProute cache",
-
- sizeof(structrt_hash_bucket),
-
- rhash_entries ,<span style="color:#FF0000;">//内核默认的缓存容量可以被用户启动选项rhash_entries所覆盖,该选项保存的hash表的容量
- </span>
- (num_physpages>= 128 * 1024) ?
-
- 15: 17,
-
- 0,
-
- &rt_hash_log,<span style="color:#FF0000;">//rt_hash_mask以2为对数所得的值,也是表示hash表的容量
- </span>
- &rt_hash_mask,<span style="color:#FF0000;">//表示hash表rt_hash_table的容量,即bucket的数目</span>
-
- rhash_entries? 0 : 512 * 1024);
-
- memset(rt_hash_table,0, (rt_hash_mask + 1) * sizeof(struct rt_hash_bucket));
-
- rt_hash_lock_init() ;<span style="color:#FF0000;">//初始化rt_hash_table表,各个桶的锁</span>
-
- ipv4_dst_ops.gc_thresh = (rt_hash_mask + 1);<span style="color:#FF0000;">//路由缓存垃圾回收的峰值,在后面删除路由缓存项时会涉及</span>
-
- ip_rt_max_size= (rt_hash_mask + 1) * 16; <span style="color:#FF0000;">//路由缓存表最大能容纳的路由缓存项目数</span>
-
-
- devinet_init() ;<span style="color:#FF0000;">//注册与设备状态相关的处理函数</span>
-
- ip_fib_init();<span style="color:#FF0000;">//注册与设备IP配置相关的处理函数
- </span>
-
-
- /*All the timers, started at system startup tend
-
- to synchronize. Perturb it a bit.
-
- */
-
- INIT_DELAYED_WORK_DEFERRABLE(&expires_work,rt_worker_func); //垃圾回收定时器,在rt_worker_func里面会调用rt_check_expire清除过期的缓存项
-
- expires_ljiffies= jiffies;
-
- schedule_delayed_work(&expires_work,
-
- net_random()% ip_rt_gc_interval + ip_rt_gc_interval);
-
-
-
- if(register_pernet_subsys(&rt_secret_timer_ops))
-
- printk(KERN_ERR"Unable to setup rt_secret_timer\n");
-
-
-
- if(ip_rt_proc_init())
-
- printk(KERN_ERR"Unable to create route proc files\n");
-
- #ifdef CONFIG_XFRM <span style="color:#FF0000;">//IPSEC相关的初始化</span>
-
- xfrm_init();
-
- xfrm4_init();
-
- #endif
-
- rtnl_register(PF_INET,RTM_GETROUTE, inet_rtm_getroute, NULL);
-
-
- #ifdef CONFIG_SYSCTL
-
- register_pernet_subsys(&sysctl_route_ops);
-
- #endif
-
-
-
- #ifdef CONFIG_MV_ETH_NFP
-
- fp_rule_db_init(rt_hash_mask+ 1);
-
- fp_arp_db_init(rt_hash_mask+ 1);
-
- #endif /* CONFIG_MV_ETH_NFP */
-
-
-
- returnrc;
-
- }
路由子系统对两类事件特别感兴趣:
1. 网络设备状态的变化
a) NETDEV_UNREGISTER //注销设备原因可能是用户从内核中删除该设备的驱动程序或拔出一块热插拔设备,比如PCMCIA以太网卡
b) NETDEV_UP //启动设备
c) NETDEV_DOWN //关闭设备原因可能是用户拔出网线或发出一条管理命令关闭设备
d) NETDEV_CHANGEMTU //改变了设备的MTU
e) NETDEV_CHANGE //
因此在初始化路由子系统的时候,路由子系统在通知链netdev_chain与inetaddr_chain上注册了处理函数进行处理网络设备状态变化和网络设备上IP配置的变化。注册的处理函数如下:
static struct notifier_block fib_inetaddr_notifier = {
.notifier_call = fib_inetaddr_event, //处理网络设备IP地址变化的情况
};
static struct notifier_block fib_netdev_notifier = {
.notifier_call = fib_netdev_event, //处理网络设备状态变化的情况
};
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请
点击举报。