邻居子系统 之 邻居表的初始化neigh_table_init
概述
邻居子系统支持多种实现,例如ARP,ND等,这些实现需要在其初始化的时候,调用neigh_table_init将邻居表项添加到全局邻居子系统数组中,并对实例中的字段(如hash,定时器等)进行相关初始化;
源码分析
分析过程以ARP为例,引出邻居表的初始化,在arp_init初始化中,调用neigh_table_init来进行邻居表的初始化;其中NEIGH_ARP_TABLE为ARP在全局邻居表数组中的索引值,arp_table则是邻居表的一个实例,里面包含了部分字段的初始化;
void __init arp_init(void)
{
neigh_table_init(NEIGH_ARP_TABLE, &arp_tbl); dev_add_pack(&arp_packet_type);
arp_proc_init();
#ifdef CONFIG_SYSCTL
neigh_sysctl_register(NULL, &arp_tbl.parms, NULL);
#endif
register_netdevice_notifier(&arp_netdev_notifier);
}
索引值是一个枚举类型,从中可见现在已经实现的邻居表项有哪些,其中NEIGH_ARP_TABLE排在第一位;
enum {
NEIGH_ARP_TABLE = ,
NEIGH_ND_TABLE = ,
NEIGH_DN_TABLE = ,
NEIGH_NR_TABLES,
NEIGH_LINK_TABLE = NEIGH_NR_TABLES /* Pseudo table for neigh_xmit */
};
下面为ARP表项实例;
struct neigh_table arp_tbl = {
.family = AF_INET,
.key_len = ,
.protocol = cpu_to_be16(ETH_P_IP),
.hash = arp_hash,
.key_eq = arp_key_eq,
.constructor = arp_constructor,
.proxy_redo = parp_redo,
.id = "arp_cache",
.parms = {
.tbl = &arp_tbl,
.reachable_time = * HZ,
.data = {
[NEIGH_VAR_MCAST_PROBES] = ,
[NEIGH_VAR_UCAST_PROBES] = ,
[NEIGH_VAR_RETRANS_TIME] = * HZ,
[NEIGH_VAR_BASE_REACHABLE_TIME] = * HZ,
[NEIGH_VAR_DELAY_PROBE_TIME] = * HZ,
[NEIGH_VAR_GC_STALETIME] = * HZ,
[NEIGH_VAR_QUEUE_LEN_BYTES] = * ,
[NEIGH_VAR_PROXY_QLEN] = ,
[NEIGH_VAR_ANYCAST_DELAY] = * HZ,
[NEIGH_VAR_PROXY_DELAY] = ( * HZ) / ,
[NEIGH_VAR_LOCKTIME] = * HZ,
},
},
.gc_interval = * HZ,
.gc_thresh1 = ,
.gc_thresh2 = ,
.gc_thresh3 = ,
};
每个邻居表实例都需要通过调用neigh_table_init进行初始化,并将其加入到全局邻居表数组中;函数首先对邻居表项中的参数进行初始化,其中包括了初始化邻居项hash和代理项hash,初始化垃圾回收GC任务和代理处理定时器任务,以及一些其他必要字段,最后将该邻居表项实例加入到全局数组neigh_tables中;
void neigh_table_init(int index, struct neigh_table *tbl)
{
unsigned long now = jiffies;
unsigned long phsize; /* 初始化参数列表 */
INIT_LIST_HEAD(&tbl->parms_list);
/* 将参数添加到参数列表 */
list_add(&tbl->parms.list, &tbl->parms_list);
/* 设置net */
write_pnet(&tbl->parms.net, &init_net);
/* 设置引用计数 */
atomic_set(&tbl->parms.refcnt, );
/* 设置可达状态的超时时间 */
tbl->parms.reachable_time =
neigh_rand_reach_time(NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME));
/* 统计信息 */
tbl->stats = alloc_percpu(struct neigh_statistics);
if (!tbl->stats)
panic("cannot create neighbour cache statistics"); /* 初始化proc */
#ifdef CONFIG_PROC_FS
if (!proc_create_data(tbl->id, , init_net.proc_net_stat,
&neigh_stat_seq_fops, tbl))
panic("cannot create neighbour proc dir entry");
#endif /* 初始化邻居项hash */
RCU_INIT_POINTER(tbl->nht, neigh_hash_alloc()); /* 初始化代理项hash */
phsize = (PNEIGH_HASHMASK + ) * sizeof(struct pneigh_entry *);
tbl->phash_buckets = kzalloc(phsize, GFP_KERNEL); if (!tbl->nht || !tbl->phash_buckets)
panic("cannot allocate neighbour cache hashes"); /* 邻居项的结构大小 */
if (!tbl->entry_size)
tbl->entry_size = ALIGN(offsetof(struct neighbour, primary_key) +
tbl->key_len, NEIGH_PRIV_ALIGN);
else
WARN_ON(tbl->entry_size % NEIGH_PRIV_ALIGN); rwlock_init(&tbl->lock);
/* gc任务初始化 */
INIT_DEFERRABLE_WORK(&tbl->gc_work, neigh_periodic_work);
queue_delayed_work(system_power_efficient_wq, &tbl->gc_work,
tbl->parms.reachable_time); /* 代理定时器处理初始化 */
setup_timer(&tbl->proxy_timer, neigh_proxy_process, (unsigned long)tbl);
skb_queue_head_init_class(&tbl->proxy_queue,
&neigh_table_proxy_queue_class); /* 初始化最近一次gc的时间 */
tbl->last_flush = now;
/* 初始化最近一次可达状态reachable_time的更新时间 */
tbl->last_rand = now + tbl->parms.reachable_time * ; /* 加入全局邻居项数组 */
neigh_tables[index] = tbl;
}
邻居子系统 之 邻居表的初始化neigh_table_init的更多相关文章
- 邻居子系统 之 邻居项创建__neigh_create
概述 IP层输出数据包会根据路由的下一跳查询邻居项,如果不存在则会调用__neigh_create创建邻居项,然后调用邻居项的output函数进行输出: __neigh_create完成邻居项的创建, ...
- 邻居子系统 之 邻居项查找neigh_lookup、___neigh_lookup_noref
概述 邻居项查找是通过neigh_lookup相关函数来进行的: ___neigh_lookup_noref,该函数根据输出设备和主键值(IPv4为下一跳ip地址)在邻居项hash表中查找,找到则返回 ...
- 邻居子系统 之 状态定时器回调neigh_timer_handler
概述 在分配邻居子系统之后,会设置定时器来处理那些需要定时器处理的状态,定时器回调函数为neigh_timer_handler:函数会根据状态机变换规则对状态进行切换,切换状态后,如果需要更新输出函数 ...
- 邻居子系统 之 更新neigh_update
概述 neigh_update函数用来更新指定的邻居项,更新内容是硬件地址和状态,更新之后,会根据新状态设置其输出函数,CONNECTED状态则使用快速输出,否则使用慢速输出:如果是由原来的无效状态变 ...
- 邻居子系统输出 之 neigh_output、neigh_hh_output
概述 ip层在构造好ip头,检查完分片之后,会调用邻居子系统的输出函数neigh_output进行输出,输出分为有二层头缓存和没有两种情况,有缓存时调用neigh_hh_output进行快速输出,没有 ...
- 《扩展和嵌入python解释器》1.4 模块方法表和初始化函数
<扩展和嵌入python解释器>1.4 模块方法表和初始化函数 1.4 模块方法表和初始化函数 下面,我演示如何从Python程序调用spam_system().首先,我们需要在’方法 ...
- [fw]IDT表的初始化
IDT表的初始化 linux内核的中断描述符表IDT是一个全局的数据,在i386平台上被定义为: struct desc_struct idt_table[256] __attribute__((_ ...
- 邻居子系统1.5 neigh output
1.5.1 当邻居项不处于NUD_CONNECTD状态时,不允许快速路径发送报文,函数neigh_resolve_output 用于慢而安全的输出,通常用初始化neigh_ops结构 来实例outpu ...
- 《深入理解Linux网络技术内幕》阅读笔记 --- 邻居子系统
1.封包从L3至L2的传送过程如下所示: 本地主机的路由子系统选择L3目的地址(下一个跃点). 根据路由表,如果下一个跃点在同一个网络中,邻居层就把目的L3地址解析为跃点的L2地址.这个关联会被放入缓 ...
随机推荐
- UE中正则表达式
UltraEdit(后简称UE),是我经常使用的文本编辑软件,其功能的强大,令我由衷地爱上了它.每天不用就全身不爽.从最开始的9.0到现在的 12.10a(本人只用到这个版本),UE都是系统重装后必安 ...
- Hacklab WebIDE在线调试ESP32笔记
目录 1.什么是Hacklab WebIDE 1.1 优势 1.2 趋势 2. 使用方法 2.1 功能介绍 2.2 编译第一个程序 2.3 搭建esp32的开发环境 2.4 建立开发板与云平台的连接 ...
- Web开发的分层结构与MVC模式
1.分层结构 所谓分层结构.把不同的功能代码封装成类,把相同功能的类封装在一个个的包中,也叫层.功能归类如下: 实体类: 封装数据,是数据的载体,在层与层之间进行传递,数据也就传递了.比如说要传递学生 ...
- arm交叉编译sudo-1.8.6p7
1.交叉编译 # tar -xvf sudo-1.8.6p7.tar.gz # cd sudo-1.8.6p7/ # mkdir build # ./configure --prefix=/home/ ...
- 微信小程序开发(三)点击事件
接着上篇博客继续. 如下修改: // index.wxml <view>Hello World!</view> <button bindtap="but&quo ...
- 解决PHP中json_encode()不支持中文的替代函数
json_encode()是PHP中将数组转换成JSON格式的函数,因为各种原因只要是中文就会乱码= = 找到了这么一个函数替代了原有的json_encode(),能很好地输出中文~ function ...
- Java 工具类 IpUtil - 获取本机所有 IP 地址,LocalHost 对应地址 IP
Java 工具类 IpUtil - 获取本机所有 IP 地址,LocalHost 对应地址 IP IP 工具类 源代码: /** * <p> * * @author XiaoPengwei ...
- JavaScript16进制颜色值和rgb的转换
//十六进制颜色值域RGB格式颜色值之间的相互转换//十六进制颜色值的正则表达式 var reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/; /*RGB颜色转换为1 ...
- router-link
<router-link> 组件支持用户在具有路由功能的应用中 (点击) 导航. 通过 to 属性指定目标地址,默认渲染成带有正确链接的 <a> 标签,可以通过配置 tag 属 ...
- ESP8266—“ICACHE_FLASH_ATTR”宏
问:ESP8266_NONOS_SDK中ICACHE_FLASH_ATTR宏的用途是什么?我看到它取决于ICACHE_FLASH,但我不知道何时应该定义该符号.什么时候需要包括它?答:对于ESP826 ...