ifconfig
我在脚本中使用了 IPv6 地址。然后立即使用该地址来侦听 TCP 端口。
当我这样编写脚本时,它会失败,因为服务无法侦听:
ifconfig igb0 inet6 2001:db8::10/64 add
service my_service start #fails
但是,当我这样做时它会成功:
ifconfig igb0 inet6 2001:db8::10/64 add
sleep 1
service my_service start
ifconfig
我尝试在运行 - 操作后直接写入输出add
。看来ifconfig
报告的 IP 地址是暂定的,这显然会阻止服务监听它。
当然,等待一秒钟并希望该地址已可用并不是处理此问题的好方法。我如何等待暂定地址可用,或ifconfig
稍后返回以便地址全部设置完毕?
答案1
一个地址可以处于多种状态,暂定就是其中之一。等待ifconfig
地址离开暂定状态根本不符合设计。
您可以配置为使用乐观 DAD,如中定义的RFC 4429。目的是即使 DAD 尚未完成,也可以为应用程序提供一个可用的地址。您可能需要重新配置内核才能使用此功能。
一旦内核被构建为提供乐观 DAD,那么您可以通过某些 sysctl 设置来启用它。从ip-sysctl.txt:
/proc/sys/net/ipv6/* Variables:
...
conf/interface/*:
Change special settings per interface.
The functional behaviour for certain settings is different
depending on whether local forwarding is enabled or not.
...
optimistic_dad - BOOLEAN
Whether to perform Optimistic Duplicate Address Detection (RFC 4429).
0: disabled (default)
1: enabled
use_optimistic - BOOLEAN
If enabled, do not classify optimistic addresses as deprecated during
source address selection. Preferred addresses will still be chosen
before optimistic addresses, subject to other ranking in the source
address selection algorithm.
0: disabled (default)
1: enabled
也就是说,做类似的事情
sysctl -w net.ipv6.conf.enp2s6.optimistic_dad=1
sysctl -w net.ipv6.conf.enp2s6.use_optimistic=1
在启动时。
答案2
在询问 NetBSD 开发人员并验证这同样适用于 FreeBSD 后,我找到了解决方案(适用于这两种操作系统):
重复地址检测 (DAD) 将花费一些时间来检测该地址是否已在使用中。为此使用的时间量在 sysctl(3) 值中以秒为单位定义net.inet6.ip6.dad_count。在 NetBSD 中/etc/rc.d/网络, 功能网络_启动_ipv6_autoconf,脚本会等待此时间加一秒。
当 DAD 发现该地址已在网络上使用时,ifconfig(8) 会将地址显示为duplicated
。在此状态下,无法绑定到该地址,类似于地址为 时tentative
。
因此,更完整、更正确的解决方案是:
ifconfig igb0 inet6 2001:db8::10/64 add
dadcount=$(/sbin/sysctl -n net.inet6.ip6.dad_count 2>/dev/null)
sleep $dadcount
sleep 1
ifconfig igb0 | grep 2001:db8::10/64 | egrep '(duplicated|tentative)$' >&2 && exit 1
service my_service start
我观察到 FreeBSD 和 NetBSD 在添加当前处于状态的地址时表现不同duplicated
:
- FreeBSD 11 将立即删除该
duplicated
状态,允许使用该地址,但可能会导致冲突。 - NetBSD 7 会将地址标记为
tentative
,并且不会从那里更改状态,至少在几分钟内不会。该地址必须删除并再次添加才能使用。