本文主要是介绍邻居表项的locktime时长,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
如果内核在locktime时间内接收到多个ARP报文,仅首个报文生效。对于arp协议,内核默认的locktime时长为1秒钟,可通过PROC文件或者ip命令进行修改。
struct neigh_table arp_tbl = {.family = AF_INET,.key_len = 4,.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 = 30 * HZ,.data = {...[NEIGH_VAR_LOCKTIME] = 1 * HZ,
通过PROC文件locktime可查看和修改此值,如下,默认为100,对应于1秒钟。
$ cat /proc/sys/net/ipv4/neigh/eth0/locktime
100
内核中静态变量neigh_sysctl_table定义了locktime的PROC文件信息。
static struct neigh_sysctl_table {struct ctl_table_header *sysctl_header;struct ctl_table neigh_vars[NEIGH_VAR_MAX + 1];
} neigh_sysctl_template __read_mostly = {.neigh_vars = {...NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(LOCKTIME, "locktime"),
如下定义,locktime的处理有neigh_proc_dointvec_userhz_jiffies,其负责将内核使用的jiffies值转换为用户层面的HZ(值为100),即内核locktime初始化为1000,用户层面显示为100。
#define NEIGH_SYSCTL_USERHZ_JIFFIES_ENTRY(attr, name) \NEIGH_SYSCTL_ENTRY(attr, attr, name, 0644, neigh_proc_dointvec_userhz_jiffies)
netlink接口
除了以上的PROC文件外,还可使用ip ntable命令查看和修改设备的邻居表参数。
# ip ntable show dev eth0
inet arp_cache dev eth0refcnt 12 reachable 28884 base_reachable 30000 retrans 1000 gc_stale 60000 delay_probe 5000 queue 31 app_probes 0 ucast_probes 3 mcast_probes 3 anycast_delay 1000 proxy_delay 800 proxy_queue 64 locktime 1000
与PROC文件不同,这里显示的locktime单位为毫秒值。如下将设备eth0的邻居表参数locktime修改为2秒钟。
# ip ntable change name arp_cache dev eth0 base_reachable 2000
内核函数neigh_init初始化了以上ip ntable change命令的处理函数neightbl_set。
static int __init neigh_init(void)
{...rtnl_register(PF_UNSPEC, RTM_SETNEIGHTBL, neightbl_set, NULL, 0);
如下为neightbl_set的实现,函数nla_get_msecs读取IP命令行设置的locktime的毫秒值参数,转换为内核使用的jiffies值,设置到邻居表的参数中。对于arp协议,将设置到arp_tbl成员parms的子成员data数组中,索引位置为NEIGH_VAR_LOCKTIME。
static int neightbl_set(struct sk_buff *skb, struct nlmsghdr *nlh, struct netlink_ext_ack *extack)
{struct neigh_table *tbl;struct nlattr *tb[NDTA_MAX+1];if (tb[NDTA_PARMS]) {struct neigh_parms *p;p = lookup_neigh_parms(tbl, net, ifindex);...for (i = 1; i <= NDTPA_MAX; i++) {switch (i) {...case NDTPA_LOCKTIME:NEIGH_VAR_SET(p, LOCKTIME, nla_get_msecs(tbp[i]));
显示命令ip ntable show由内核中的函数neightbl_fill_parms填充值,对于locktime的值,由nla_put_msecs填充。
static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms)
{...if ((parms->dev &&...nla_put_msecs(skb, NDTPA_LOCKTIME,NEIGH_VAR(parms, LOCKTIME), NDTPA_PAD)
如下函数nla_put_msecs,其需要将内核使用locktime的jiffies值转换为ip ntable show显示时的毫秒值,通过jiffies_to_msecs实现。
static inline int nla_put_msecs(struct sk_buff *skb, int attrtype,unsigned long njiffies, int padattr)
{u64 tmp = jiffies_to_msecs(njiffies);return nla_put_64bit(skb, attrtype, sizeof(u64), &tmp, padattr);
}
locktime处理
在arp报文处理函数arp_process中,对于连续(back-to-back)接收到的ARP回复,内核选择使用首个回复报文,因为,如果链路上存在多个活动的ARP代理,这样就选择了其中速度较快的一个,也可屏蔽一些无用的ARP回复。
内核判断连续报文的依据为locktime时长,在此段时间内接收到的ARP报文,进行更新时不设置覆盖标志位NEIGH_UPDATE_F_OVERRIDE(garp的情况除外)。
static int arp_process(struct net *net, struct sock *sk, struct sk_buff *skb)
{.../* Update our ARP tables */n = __neigh_lookup(&arp_tbl, &sip, dev, 0);...if (n) {int state = NUD_REACHABLE;int override;/* If several different ARP replies follows back-to-back,use the FIRST one. It is possible, if several proxyagents are active. Taking the first reply preventsarp trashing and chooses the fastest router.*/override = time_after(jiffies,n->updated +NEIGH_VAR(n->parms, LOCKTIME)) || is_garp;/* Broadcast replies and request packetsdo not assert neighbour reachability.*/if (arp->ar_op != htons(ARPOP_REPLY) || skb->pkt_type != PACKET_HOST)state = NUD_STALE;neigh_update(n, sha, state,override ? NEIGH_UPDATE_F_OVERRIDE : 0, 0);
内核版本 5.0
这篇关于邻居表项的locktime时长的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!