neigh_sysctl_register函数中最复杂的部分是如何将四个参数gc_xxx参数从neigh_table结构中提取出来。实现过程巧妙地利用了neigh_table结构在内存中的安排:与垃圾回收相关的四个参数保存在neigh_table结构中,且位于neigh_parms结构之后,具体代码如下(在函数neigh_sysctl_register中):
2056 if (dev) {
2057 t->neigh_dev[0].procname = dev->name;
2058 t->neigh_dev[0].ctl_name = dev->ifindex;
2059 memset(&t->neigh_vars[12], 0, sizeof(ctl_table));
2060 } else {
2061 t->neigh_vars[12].data = (int*)(p+1);
2062 t->neigh_vars[13].data = (int*)(p+1) + 1;
2063 t->neigh_vars[14].data = (int*)(p+1) + 2;
2064 t->neigh_vars[15].data = (int*)(p+1) + 3;
2065 }
其中p为入参struct neigh_parms *p。
每个neigh_table表中,也就是每个协议,都有自己的neigh_parms 实例,这个实例保存着协议提供的默认参数。每个设备的net_device结构可以配置多个L3协议。对每个配置在该设备上的L3协议,net_device都有个指针,指向保存该L3协议配置信息的数据结构(例如,IPv4协议的是in_device)。这个协议指定的结构中也包含一个指针,指向neigh_params实例,这个实例中保存着该L3协议所用的邻居协议的配置参数。
当在一个设备上第一次配置IPv4信息时,IPv4的相关函数就会调用inetdev_init函数,来分配ARP协议所使用的neigh_params实例。这个新的neigh_params实例的内容就是拷贝自neigh_table->parms。而ARP下neigh_table实例就是arp_tbl。当创建一个neighbour实例时,neigh->parms就被初始化为相关联设备的neigh_params实例。注:全局默认配置取自neigh_table->parms。