TCP Fast Open by Google 浅析

Google 将在今年 12 月的 ACM CoNEXT 会议上发表他们在改善 Web 应用响应时延方面的一个工作,通过修改 TCP 协议利用三次握手时进行数据交换的“TCP Fast Open”。虽然 paper 是两天前才释出,但相关的 RFC 草案则早在 2011 年 3 月份就提交到了 IETF,并且在两周前进行了一次 UPDATE,这里是 DIFF

对于 TCP Fast Open 方案的内容,淘宝的一个朋友已经根据 RFC 草案进行了解读。我就不再赘述,感兴趣的朋友可以去看 paper 或者 RFC。我这里只是想讨论一下这个东西的应用前景。

由于对背景并没有做深入了解,我相信已经有很多人尝试去做过类似的工作,但我想类似的工作应该没有得到过大规模的应用。对于已经成型很久很久的 TCP 协议,让人很难有修改它的欲望,因为改那么底层的东西意味着很多很多的麻烦。

但是是否愿意付出代价,有一个前提是有没有足够的好处。TFO 给出的好处是:在 RTT (Round Trip Time) 比较低时,客户端页面加载时间优化大约在 4%~5%;RTT 越长,好处越大,平均大约在 25%。

Google TCP Fast Open Evaluation
Google TCP Fast Open Evaluation

除了页面加载变快改善了用户体验之外,TFO 给服务器端也带来了一些好处。由于每个请求都节省了一个 RTT,相应地也减少了服务器端的 CPU 消耗。paper 中给出的数据是每秒事务数由 2876.4 上升到 3548.7。

虽然 paper 中大部分时间在强调 TFO 对 web 页面加载的显著加速作用,但我认为即使 TFO 能成为互联网标准,它目前的状态离成为标准还有很长一段距离,因而在短期内它是无法影响到主流互联网世界的。但这并不意味着它没有机会,依小弟的愚见,目前它的推广应用可能有两个方向:

1. 移动互联网。移动互联网的 RTT 目前远大于传统互联网(常理推测,需数据支撑),因而一个 RTT 节省的效果无法被忽视;另外移动互联网终端操作系统多样化,不像桌面终端系统那么单一。 Google 自己就掌握着其中一个很重要的 android,百度也计划推出自己的“易平台”。这些互联网公司有动力去改善移动用户访问自身网站的用户体验。

2. 互联网企业数据中心。虽然数据中心内部访问时延很低,但对于典型的请求/响应的服务而言,减少一次 RTT 带来的好处还是有吸引力的,最起码能减少计算能力浪费和增加吞吐吧。再加上很多企业内部使用的都是定制的开源操作系统和定制的网络库,升级的代价并不是那么高。如果我是企业基础设施的负责人,我想我会很慎重地考虑这个方案的。

epoll 事件之 EPOLLRDHUP

在对系统问题进行排查时,我发现了一个奇怪的现象:明明是对方断开请求,系统却报告一个查询失败的错误,但从用户角度来看请求的结果正常返回,没有任何问题。

对这个现象深入分析后发现,这是一个基于 epoll 的连接池实现上的问题,或者说是特性 :)

首先解释一下导致这个现象的原因。

在使用 epoll 时,对端正常断开连接(调用 close()),在服务器端会触发一个 epoll 事件。在低于 2.6.17 版本的内核中,这个 epoll 事件一般是 EPOLLIN,即 0x1,代表连接可读。

连接池检测到某个连接发生 EPOLLIN 事件且没有错误后,会认为有请求到来,将连接交给上层进行处理。这样一来,上层尝试在对端已经 close() 的连接上读取请求,只能读到 EOF,会认为发生异常,报告一个错误。

因此在使用 2.6.17 之前版本内核的系统中,我们无法依赖封装 epoll 的底层连接库来实现对对端关闭连接事件的检测,只能通过上层读取数据时进行区分处理。

不过,2.6.17 版本内核中增加了 EPOLLRDHUP 事件,代表对端断开连接,关于添加这个事件的理由可以参见 “[Patch][RFC] epoll and half closed TCP connections”。

在使用 2.6.17 之后版本内核的服务器系统中,对端连接断开触发的 epoll 事件会包含 EPOLLIN | EPOLLRDHUP,即 0x2001。有了这个事件,对端断开连接的异常就可以在底层进行处理了,不用再移交到上层。

重现这个现象的方法很简单,首先 telnet 到 server,然后什么都不做直接退出,查看在不同系统中触发的事件码。

注意,在使用 2.6.17 之前版本内核的系统中,sys/epoll.h 的 EPOLL_EVENTS 枚举类型中是没有 EPOLLRDHUP 事件的,所以带 EPOLLRDHUP 的程序无法编译通过。

使用无线自组网共享互联网接入

在这个互联网已经渗透入每个角落的时代,GUCAS 的网络接入收费显得非常不合时宜:(二年级以上同学)每个月 25 元套餐,其中包括5G国内流量、2G 国际流量,国内流量超出部分按 10元/G 收费,国际超出部分按 1元/M 收费。幸好有了 IPv6 BT(IPv6 流量不计入收费流量),不然 GUCAS 的网络就是一个悲剧。

对于高年级同学来说稍微好一点的是,某些实验室会有免费的网络,还可稍解流量窘迫。但如果不下 BT、不看视频、不视频聊天的话,5G 每月也是用不完的,而且 25 元的价钱也并不便宜,所以很多高年级同学都是宿舍共用一个上网帐号。

共用上网帐号有几种方式:1> 使用路由器,这是比较简洁的方式,但是这样就无法使用 IPv6——目前的路由器一般不支持 IPv6 路由功能,因此需要使用特别的配置才能同时支持 IPv6;2> 使用代理,一台电脑作为主机,为另一台电脑开一个代理,这种方式可以使用 IPv6,但缺点是主机分配的 IP 可能变化,需要手动更新代理地址,而且部分软件并不能完美支持代理。

我这里尝试了另外一种方式,使用无线自组网共享互联网接入,只适用于两台都带无线网卡的电脑共享上网。简单点儿来说,就是让两台电脑无线网卡相连,其中一台(主机)将有线的互联网接入通过无线链路共享给另外一台(从机)。这种方案同样适用于那些家里有两台笔记本却只有一个网口的家庭,省了买路由器的钱。

注:下文使用操作系统平台为 Windows XP SP3。

首先,需要将主机的有线连接即“本地连接”设为可共享。具体方法是,在主机上右击“本地连接”,选择“属性”,进入“高级”选项卡,“选中 Internet 连接共享”中的两个复选框,即“允许其他网络用户通过此计算机的 Internet 连接来连接”和“允许其他网络用户控制或禁用共享的 Internet 连接”。

其次,将两台电脑进行无线自组网。无线自组网的建立方式根据网卡管理软件的不同可能有不同的方法,简单的来说就是建立一个两台笔记本之间的一个点到点的(不需要接入点的)无线连接。一个典型的配置是:

主机:
Ethernet adapter 无线网络连接:

        Connection-specific DNS Suffix  . :
        IP Address. . . . . . . . . . . . : 192.168.0.1
        Subnet Mask . . . . . . . . . . . : 255.255.255.0
        Default Gateway . . . . . . . . . :
从机:
Ethernet adapter 无线网络连接:

        Connection-specific DNS Suffix  . : mshome.net
        IP Address. . . . . . . . . . . . : 192.168.0.27
        Subnet Mask . . . . . . . . . . . : 255.255.255.0
        Default Gateway . . . . . . . . . : 192.168.0.1

需要注意的一点是,两台电脑需要在同一个 Windows 工作组中,这里两台电脑的工作组都是 MSHOME。

如果对无线自组网不是很了解,以上两步可以通过软件来进行设定。联想有一款叫做“闪联任意通”的软件,配置起来相对简单好用,用它的“共享网络”功能即可做到以上两步。但是闪联任意通有一些BUG,会造成服务占用 CPU 过高。一旦配置成功之后,记住建立的点到点网络 SSID(一般以 PAN_ 开头),以后每次两台电脑都连接至该网络即可。不再需要闪联任意通的运行。

最后,将从机有线接口的 IPv4 功能禁用,将从机无线接口的 IPv6 功能禁用。具体方法是,在从机上右击“本地连接”,选择“属性”,在“常规”选项卡中的“此连接使用下列项目”选择框中的“Internet 协议 (TCP/IP)”前的复选框去掉,确定退出;在从机上右击“无线网络连接”(也可能是其它名称),在类似于上面的位置找到“Microsoft TCP/IP 版本 6”,去掉前面的复选框。

经过上面三步之后,就可以保证从机的 IPv4 的流量会走无线接口,使用主机共享的 IPv4 互联网接入;而 IPv6 的流量会走有线接口,使用本地交换机提供的 IPv6 互联网接入。第二步建立的点到点网络会保存到无线网络配置中,两台电脑开机只要打开无线,一般就会自动连接到该点到点网络,无需再进行额外的手动修改。(即便是使用代理的同学,由于无线的 IP 不会变化,这样做也能带来不用修改代理地址的好处。)

综上,这种方式可以完美地实现共享 IPv4 接入而又不影响 IPv6 连接。

几种不得已时的上网办法

由于小弟最近上网受到诸多限制,在校时帐号爆掉,回家又没有网络可上,所以尝试了各种上网方法,也许对大家有用呢,所以下面分享及记录一下:

1. 手机作为 modem,使用 GPRS 拨号上网

这个一般受到手机版本影响,三星这方面做得非常不错。将手机使用数据线连接到电脑,打开 Samsung PC studio,选择 Network Wizard(网络向导?),创建连接,连接名称随便写,比如“中国移动”,下一步调制解调器选择“Samsun Mobile USB Modem”,下一步国家选择中国,网络供应商选择“China Mobile(Beijing)”(其实选择哪个好像无所谓),用户ID选择“cmnet”,密码也是“cmnet”,创建完成后就可以拨号了。因网络状况或者 GPRS 版本不同,连接速度可能是 153.5 kbps,或者 460 kbps。

GPRS 资费是非常贵的,不在不得已或者包月流量用不完时,最好不要用 GPRS 上网;即使用 GPRS 拨号上网时,也要切记关掉所有自动联网的软件,比如禁用杀毒软件和操作系统的自动更新,禁用浏览器插件等等,这样才能将有限的网速使用在优先的程序上。

2. 使用 201 卡进行古老的 modem 拨号上网

使用 201 卡拨号上网可能会受到运营商的限制。经过我多次咨询 10010 和动手尝试,北京网通(联通)的“阳光心语普通快捷卡”拨号上网方式是这样的:首先将电话线插到笔记本的 modem 口(一般台式机已经没有这个口了)。创建一个新的连接,“连接到 Internet”->“手动设置我的连接”->“用拨号调制解调器连接”->选择笔记本电脑自带的调制解调器(我从来没想过我会有使用它的一天...)->ISP 名称,随便填,比如“201”->电话号码:“2012,语言种类,卡号#,密码#,16911#”,语言种类为打201电话时选择的数字->用户名:169,密码:169。设置完后就可以拨号了,刚开始会听到愉悦的 201 拨号机器回复,最后就要忍受一会儿嘈杂的拨号音了。201 拨号上网的速度大概为 46.6 kpbs...

使用 16911 拨号上网资费大概是 0.07 元一分钟,所以也是相当贵的,只是在 201 卡快过期或者不得已时才能为之。

3. 借用 IPv6 上的 Google App Engine 上网

这个大概只适用于高校使用教育网的学生了。Google,作为一间牛逼闪闪的公司,当其他互联网公司还在 IPv4 上晃悠时,Google 已经将其几乎所有服务部署在 IPv6 互联网上了。作为 IPv6 网络用户,您只需要将所有 Google 相关的域名在 hosts 文件(C:\WINDOWS\system32\drivers\etc, /etc/hosts)中映射到 2001:4860:c004::68 这个 IPv6 地址即可,格式例如:

2001:4860:c004::68 www.google.com mail.google.com clients1.google.com talk.google.com ssl.goo飞gle-analytics.com

就可以使用浏览器访问 IPv6 上的 Google 服务了。目前中国的 IPv6 网络上是没有审查制度的,所以在 Google 搜索时,您可以放心地搜索任意关键词,以及查看网页快照了。

但是目前只解决了访问 Google 的问题,如何访问其它网站呢?就不得不提到我前段时间发布的 Tohr 项目了。Tohr router 可以运行在 Google App Engine 上,所以您只需要将您的 Google App Engine 的域名,比如 example.appspot.com 照上面格式添加到 hosts 文件中,就可以利用 Tohr 结合 GAE 作为一个 IPv4 over IPv6 通道来上网了。当然,GAE 有很多限制,所以有些网站是铁定上不了的。为了实现浏览器自动选择直连 IPv6 的 Google 服务和使用 Tohr 代理访问其他网站,强烈推荐您阅读一下我的这篇博客文章《浏览器自动选择 Proxy 配置案例》。

使用这种方法起码在访问只需要阅读的网站还是 OK 的,Twitter 也可以直接登陆。部分在登录时检查 HTTP 请求 Referer 的网站是无法登录的,比如豆瓣、开心网、Facebook 等,这些时候不要责怪我,因为这是 GAE 的限制,不许用户自定义 Referer;或者 gmail, google reader 等,这也可能是 GAE 限制访问的网站。

但比较遗憾的是,除了第3种方法在 Linux 一样好用以外,前两种方法我都不知道如何在 Linux 上使用。

用 Wireshark 分析 RTP 流

Wireshark 是一个强大的抓包及网络分析软件,可以用来嗅探和分析多种网络协议的数据包和流,RTP 和 RTCP 也是其中的两种。

对 RTP 流的分析过程,在 Wireshark 的 Wiki 上讲得很清楚,下面我只是记录一下我在使用过程中的一些经验:

1. 要想分析 RTP 流,首先要把抓到的 UDP 包用 RTP 协议而不是默认的 UDP 协议 decode; Wireshark 默认只对选中的流(由端口区分)进行 decode,所以对 audio 和 video 流要分别 decode。

2. 直接从菜单中选择 RTP 的 Stream Analysis... 才是对双向的流进行分析,从 Show All Streams 中再分析只是单向的 RTP 流。

3. 不要过度相信 Wireshark 的能力,尤其是在无线网络或者网卡驱动不是很合适的情况下,Wireshark 也会有丢包,所以说 Wireshark 对 RTP 流的分析也是“仅供参考”——除非经过严格测试 Wireshark 不会错过任何包。

4. 这个页面上提到的 Sun 的 JMF JMstudio 的 Linux 版本状况很糟糕。首先其安装文件中使用的 tail 参数和 bash 中的 tail 参数不一样,导致执行安装文件不仅不会安装,反而会清除安装文件的内容。由于其将安装脚本和二进制文件写入到同一个文件中,所以最好是在外部手工用 tail 提取二进制文件的内容;其次无论如何配置,该程序运行时会去监听 IPv6 地址的端口而不是 v4 的端口——我一直想不通是什么原因,所以该程序可以说是基本不可用。

5. rtptools 是个好东西。我们可以先用 Wireshark 录制一段 RTP 流,保存成 rtpdump 格式,就可以用 rtpplay 不断地重放它,用来测试网络状况很方便。原本应该用 JMStudio 收听的,既然它不可用,只有用 rtpdump 在另一端收听了。

回复选登:

james:

博主请问有没有办法能够使wireshark能够在ubuntu下捕捉到所有的rtp包?

由于要做老板的项目,所以需要测量一系列delay,jitter等等数据。所以我用vlc做server向外multicast一个rtp stream (拓扑上用的全部是有线)。若传输的stream质量不高(比如dvdrip,大概速度也就1.5mbps),wireshark能够完全捕获所有的包。但是若是使用较高质量的stream(比如1080p,1080i的,大概在20mbps)就会出现wireshark丢包的情况。

所以我想知道wireshark丢包的原因是不是来自于cpu利用率太高?有没有办法在仍然使用wireshark的情况下捕捉到所有的包?如果有其他抓包、分析软件,博主可否给我推荐一下?

非常感谢!

Solrex Yang:

@james
非常抱歉,我所了解的知识无法解决您遇到的问题。如果您找到了解决方法,非常欢迎您回来再次留下您的评论。

james:

博主你好,这个问题已经解决了。

由于wireshark实时捕捉packet会非常消耗cpu资源,所以我使用tcpdump来抓包,并且加大了libpcap的缓冲区,问题就解决了。

当然,若是要在Gbps的网络环境中抓包,linux下的tcpdump的精度完全不够(尤其在包长度小的时候很明显),这个就是跟libpcap函数相关的。有个意大利大牛写了一个PF_RING的类似“zero copy”的应用,可以在很大程度上解决这个问题,如果大家有兴趣可以尝试。google上有相关介绍。

JPerf Single Jar with UDP BW Unit Fixed

JPerf is the GUI frond-end of IPerf, a TCP and UDP bandwidth performance measurement tool which allows the tuning of various parameters and UDP characteristics.

The official JPerf release (2.0.2 version) has some flaws. First, it mistakenly uses bytes/sec as the unit of UDP bandwidth, which should be bits/sec according to IPerf man-page:

-b, --bandwidth #[KM]
       for  UDP,  bandwidth  to  send  at  in  bits/sec (default 1 Mbit/sec,
       implies -u)

Second, starting it from command line is error prone. The command to start it (jperf.sh) is:

java -classpath jperf.jar:lib/forms-1.1.0.jar:lib/jcommon-1.0.10.jar:lib/jfreechart-1.0.6.jar:lib/swingx-0.9.6.jar net.nlanr.jperf.JPerf

We can see that all jar paths in classpath are relative paths. So if we create a symbol link to the jperf.sh script, e.g. /usr/bin/jperf -> /opt/jperf-2.0.2/jperf.sh. Then calling /usr/bin/jperf will result in some errors like:

Exception in thread "main" java.lang.NoClassDefFoundError: net/nlanr/jperf/JPerf
Caused by: java.lang.ClassNotFoundException: net.nlanr.jperf.JPerf
at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:252)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)
Could not find the main class: net.nlanr.jperf.JPerf. Program will exit.

This error can be fixed by resolving the real path of the symbol link, as I reported.

However, a better way to solve this problem is to pack all libs JPerf needed(i.e. forms*.jar, jcommon*.jar, jfreechart*.jar, swingx*.jar) to a single jar, and add a proper "Manifest". Then we will be able to start JPerf with a much simpler command:

java -jar jperf.jar

And finally, I gave a try to solve the above 2 flaws and put my work (deb/jar/src packets) on my site. You can find them here .

NetworkManager 任重而道远

Ubuntu 8.04 以前的 NetworkManager(nm-applet) 还差强人意,好歹还能通过它来配置一下网络。中间跳过了 Ubuntu 8.10,而新的 Ubuntu 9.04 的 NetworkManger 则让我不知道该如何使用。

我依稀记得原来使用 nm-applet 对网络进行配置后,设置会被保存在它应该在的配置文件中,比如 /etc/network/interfaces, /etc/resolv.conf。但是我完全不知道目前的 nm-applet 会将网络配置保存在什么地方。无论是有线网络还是无线网络,无论是 DHCP 还是固定 IP,我一次都没有使用 nm-applet 配置成功过。有线网络还好,我很熟悉,直接写到配置文件中不费什么事情。最近忽然遇到要配置无线网络,一懒,就试试 nm-applet。用 nm-applet 可以扫描到无线网络,但是填入密钥就是无法完成验证,没办法只好转而用 iwconfig 命令配置。按说直接敲命令应该是最靠谱的事情,依然无法凑效,最后才发现原因——在使用 iwconfig 配置时,一定要 disable nm-applet 对无线网络的管理!

我觉得目前 nm-applet 可能在做一些革新性的改变,大概是想简化网络的配置方法增强易用性吧。但是一些不愉快的经历让我觉得现在的 nm-applet 是一个相当不靠谱的东西,所以我只好在所有的 Ubuntu 里禁用了 nm-applet,还是直接修改配置文件靠谱呀!

用 Firefox 插件控制网络沉迷

最近好几个朋友都加入了一个叫做“你为什么不关掉电脑去做爱做的事”的豆瓣小组,当然,我也加入了。

也许是大学时候养成的毛病,也许是因为现在网络是免费的,我虽然不会沉迷于游戏,但却经常在该工作的时候沉迷于网络,其中典型的包括小百合 BBS、Google Reader 等。最近我想控制一下这些浪费时间的行为,就把 bbs.nju.edu.cn, reader.google.com 等这些域名在 /etc/hosts(或 c:\windows\system32\drivers\etc\hosts)文件中写成回环地址 127.0.0.1,这样我一旦访问这些网站,就会转到我本机的服务器。

但直接写系统 hosts 文件会产生一个问题,它不仅影响浏览器,还会影响所有其它软件。某些情况下我是不希望这种事情发生的,而且每次都要手动修改策略,于是我找到了 Firefox 插件 LeechBlock。它的介绍是这样的:

LeechBlock is a simple productivity tool designed to block those time-wasting sites that can suck the life out of your working day. All you need to do is specify which sites to block and when to block them.

LeechBlock 可以设置六个策略集,策略集组成主要包括要屏蔽的网站、屏蔽策略和屏蔽时间。最狠+幽默的是可以设置 LeechBlock 为修改设置时要求输入一串随机产生的 64 位验证码,直接搞到你不想随便修改自己定下的策略集,比密码还有效。要是再长点儿,恐怕你就永远不想修改你的设置了。

虽然是否会浪费时间主要取决于自己的毅力,但是有一个软件能稍微起点儿帮助作用也是不错的。我发表完就把 blog.solrex.cn 添加到屏蔽列表中去。

最后再提醒诸君一句,在设置完策略集之前千万不要选择 Require the user to enter a random 64-character access code,切记切记!

IPV6 获取地址却无法使用的解决方案

最近我的 WinXP 经常无法连接 IPV6 站点,但是 IPV6 地址的获取是正常的,同一台电脑上的 Ubuntu IPV6 工作也正常。经过一些摸索发现可能是以下两个原因造成的:

1. 分配到 2002 开头的 IPV6 地址并使用了它。2002::/16 格式的地址是 6to4 的地址,不是 native 的 IPV6 地址,所以在 IPV4+V6 双栈网络中不应该使用 2002::/16 格式的地址。执行 ping6 ipv6.google.com 可以看到自己使用的是什么 IPV6 地址。

之所以会产生 2002::/16 格式的地址,一个很可能的原因是网络中的 Windows Vista 操作系统默认会发送 IPV6 的路由器公告。使用

netsh interface ipv6 show interface "本地连接"

命令可以查看本地连接的参数,其中有一条:“发送路由器公告”,一定要设置为“否”。如果您的这个选项是“是”,那么您可以使用这个命令关闭它:

netsh interface ipv6 set interface “本地连接” advertise=disabled

如果获得的全部是 2002 开头的地址,可以使用下面命令进行重分配:

netsh interface ipv6 reset

2. IPV6 的路由表(网关)不对。tracert6 ipv6.google.com 就能看到本机是经过什么路由到 ipv6.google.com 的。如果从第一跳就显示连接超时,应该就是路由表出了问题。

两个问题的解决方案如下:

netsh interface ipv6 set prefixpolicy 2001::/16 1 1 persistent

上面这条命令的意思是设置 Windows 更偏好使用 2001 开头的 IPV6 地址,避免使用 2002 开头的地址。如果您 ping ipv6.google.com 使用的是 2001 开头的地址,那么您不必执行上面这条命令。

netsh interface ipv6 add route 2001::/16 "本地连接" fe80::21a:30ff:fe4f:7000 persistent

上面这条命令的意思是为 2001 开头的 IPV6 地址使用正确的网关 fe80::21a:30ff:fe4f:7000(中科院某公寓)。这个网关可能随着用户所在网络的不同而不同,简单点儿的方法可以去看正常用户的 ifconfig 网关地址。

之后执行 ping6 ipv6.google.com 看能否 ping 通,如果能 ping 通就说明 IPV6 工作正常了。

如果您经过以上两步之后仍然无法解决问题的话,您可以使用 netsh interface ipv6 reset 命令来重置所有修改。

PS:

1. 如何确定网络中哪些主机在发送路由器公告?

2002 后面的两个字段就是该主机的 IPV4 地址,比如 2002:3b41:177e:8:18fc:7649:9e1d:2880,其中 3b41:177e 从 16 进制显示换算成 IPV4 的 10 进制显示地址就是 59.65.23.126。一般来说,V4 地址的分配更有规律,您可以从 V4 地址大致确定该主机的位置。

2. 如何确定虚假的路由记录?

一般来说,IPV6 地址的最后 4 个域应该从网卡的物理地址中获得,假设网卡物理地址是:00-17-31-94-99-EA,在 3,4 字节之间插入 FFFE 换成 EUI-64 格式是:00-17-31-FF-FE-94-99-EA,再对第一个字节的第二位取反,就变成 02-17-31-FF-FE-94-99-EA,然后装载到 IPV6 的本地地址中,就变成本地地址 fe80::217:31ff:fe94:99ea。根据网段的不同,在前面加上 4 个网络域,就是主机的公网地址 2001:xxxx:xxxx:xxxx:217:31ff:fe94:99ea。

由于双栈路由器是使用同一个网卡提供 V4 和 V6 的路由,那么路由器的 V4 地址和 V6 地址的物理地址是一样的。通过 ping gateway_ipaddress_v4,然后 arp -a 看 V4 的网关地址对应的物理地址,与上面 V6 网关本地地址中获得的物理地址相对照,就可以确定某路由记录是否为可用的记录。