1.IPV6报头格式
2.IPV6地址格式
2.1.单播地址
2.1.1 全球单播地址(对应IPV4公网地址)
前3bit固定为001,换算成16进制为2000::开头。提供商路由前缀一般为48bit,子网号为16bit(类似IPV4中的网络号),主机接口标识为64bit(类似IPV4中的主机号)。
2.1.2 ULA唯一本地地址(对应IPV4私有地址)
地址前缀固定为FC00::/7,还包括FC00::/8和FD00::/8,从理论规定上来讲 仅在本地网络中能使用,在IPV6的公网中不能被路由。如下:
即使私网地址的40bit的随机产生全局ID,(全局ID唯一性的保证:一般是使用md5/sha的哈希算法计算得出再填充到这里),企业的正式使用也是需要向IPV6官网申请的这段全局ID范围。这样一旦被路由通告到路由器上去,该地址段由于注册了归属企业,其他企业也不会使用,路由也是可达的。
2.1.3 Link-local本地链路地址(IPV6独有,接口和路由器之间获取地址必须通过该本地链路地址)
用于链路发现。地址为FE80::/10前缀,其中64位接口ID位(可以手动配置或eui命令自动生成),eui自动生成是使用网卡的mac地址前三字节和后三字节之间插入FFFE后拼成64位接口ID。
2.1.4 特殊未知地址(::/128等,类似于IPV4中的0.0.0.0,即DHCPV6时会出现,IPV6 DAD地址冲突检测时会出现)
2.1.5 环回地址(::1/128 类似IPV4的127.0.0.1系列)
2.1.6兼容IPV4地址(如::xx:xx:xx:xx /64 (xx表示IPV4的地址,将ipv4地址兼容到ipv6地址格式中))
2.1.7 单播地址的作用域如下图
2.2.组播地址
地址前缀为FF00::/8(IPV4为224-239前缀),如下图
链路本地范围的组播地址(FF02::开头)包括:
其中FF02::1:FFXX:XXXX地址极其重要,在接口下一旦配置/生成了单播地址,每个单播地址必然会生成对应的一个组播地址在该接口下。譬如配置2000::1111/64,便会生成一个对应的组播地址FF02::1:FF00:1111,譬如配置本地链路单播地址FE80::A3C4/64,便会同时生成对应组播地址FF02::1:FF00::A3C4。该组播地址被命名为“被请求节点组播地址”,该地址生成原则为FF02::1:FF+对应单播地址的后24位.如果接口下多个单播地址的后24位一致但前缀不同,对应生成的组播组地址是同一个组播地址,即不同前缀但后24位相同的接口下地址共用一个组播地址.
这个组播地址在直连接口学习MAC时使用到(类似IPV4 ARP学习),ICMPV6触发MAC学习时,目的为该组播地址
上面是ipv6的组播地址,v6对应的二层组播mac为3333开头的二层地址.即3333 XXXX XXXX,后面的xxxx系列直接从ipv6组播地址的后24位拷贝下来填充。
2.3.任播地址
3.IPV6的基础协议
3.1.ICMPV6
ICMP主要有2类报文,差错类和信息类,根据ICMPV6报头中的TYPE来区分。差错类(0-127),信息类(128-255)。报文类型如下图:
基于ICMPV6实现的几种重要机制,如下图:
3.1.1 地址解析(类似IPV4的ARP)
地址解析是基于ICMPV6的NS(请求135)和NA(应答136).环境如下:
地址配置完成后如上图,
从PC1 ping PC2地址2000::2/64,PC1发出NS报文,该NS报文IP层目的地址为PC2的组播地址(根据2000::2/64计算出该地址对应的被请求节点组播地址为FF02::1:FF00:0002),二层目的MAC地址为PC2的组播MAC地址(根据2000::2/64计算出该地址对应的组播MAC地址为3333:FF00:0002).ICMPV6报文头可选项中存放PC2地址2000::2/64,表示请求该地址对应的MAC地址。
PC2和ROUTE都会收到PC的NS请求报文,ROUTE收到PC1的NS报文时,通过报文中的目的MAC 3333:FF00:0002 匹配本地组播MAC地址(本地为3333:FF00:0003),目的MAC不匹配,ROUTE丢弃该NS报文。
PC2收到该NS报文,匹配NS报文中的目的MAC,和本地3333:FF00:0002匹配上,PC2通过源IPV6地址和源MAC地址学习到PC1的MAC地址和IPV6的地址表,PC2再回应NS报文,携带本地MAC地址给PC1.PC1收到NS报文后学习到PC2的MAC地址并形成本地表项.
NS/NA报文格式如下:
3.1.2 邻居状态跟踪(链路是否可达检测)
在1.1中PC1和PC2通过NA/NS互相学习到MAC后,在30秒内 MAC转发表项reachable可达状态,超过30秒后为stale状态(即老化状态)。若在stale状态下,有流量通过时PC1会触发NS请求报文给PC2(表项的目的MAC),NS报文目的mac和目的ip都是单播地址,但IP源地址为接口的本地链路接口地址(FF80开头的地址)。同样PC2回应报文NA中的地址是NS报文中的目的和源的相反填充,PC1本地mac表项进入reachable状态。同时PC2也主动向PC1触发NS报文,PC1回应NA,PC2本地mac表项进入reachable状态。
mac表的过程状态30s后到达stale状态,发送NS报文时,进入delay状态,等待收到NA报文时进入probe状态,收到NA报文时真正进入reachable状态。
即mac表的状态机变迁过程为 reachable---30s---->stale--->delay-->probe-->reachable
以上所说MAC表即为ipv6中所说的邻居表。邻居表状态如下:
3.1.3 DAD地址冲突检测(等同于IPV4的免费ARP)
接口下所有单播地址包括本地link地址都要进行DAD检测后才能正常通讯。
接口主动发送DAD检测报文,源地址为::,目的地址为该地址对应的被请求阶段组播地址,譬如配置2000::01/64,NS报文中的目的IP为FF02::1:FF00:0001,若无NA回应报文说明该地址在未被使用本,则本地2000::01为duplicate状态,可以正常使用;若有NA回应报文,说明该地址已被使用,本地2000::01为tentative状态,无法进行通讯,该NA回应报文目的地址为FF02::01(该地址所有节点都会接受到),源地址为2000::01/64。
简单理解下,接口配置IPV6后地址状态为试验状态(tentative); 接口up后即进行DAD检测。
3.1.4 无状态地址配置(使用RS/RA报文,R=router,type=133/134)
PE2触发RS请求报文(IP目的地址为FF02::02,基于链路的所有路由器的组播地址),PE1回应RA报文携带地址前缀(2000::/64)给PE2(IP目的地址为FF02::01,基于链路的所有节点的组播地址)。RA回应报文如下图:
PE1定期通告RA报文(思科200s/每次,华为200-600s/每次)。
RA中报文中的FLAG字段:
3.1.5 NUD,邻居不可达检测(NS/NA报文)
3.1.6路由器发现
3.1.7路由器重定向
3.1.8前缀重编址
3.1.9 总结
无状态地址配置(见1.4)
4.IPV6过渡技术
5.IPV6几个重要的表
IPV6栈里面有几个重要的表现,ndv6邻居缓存表(类似于V4的ARP表)、ndv6目的地址缓存表、ndv6地址前缀表、v6缺省路由表
5.1 ndv6邻居缓存表(类似于V4的ARP表)
协议栈在收到ICMPV6的ND/RD报文时更新该表现,NS报文学习源地址对应的MAC地址,ND回应报文学习对端V6地址(上图中的next_hop_address)对应的MAC地址(lladdr)。
协议栈在收到ICMPV6路由重定向报文时更新next_hop_address和lladdr。
struct nd6_q_entry *q,挂的是本地在发送V6报文时查询不到吓一跳地址对应的mac地址(lladdr),便将该数据报文入队列,并本地触发NS报文请求吓一跳地址对应的MAC地址。当成功收到NA报文并学习到lladdr地址时,继续发送struct nd6_q_entry中记录的数据报文.
state字段是记录该表项几种状态.见《3.1.2 邻居状态跟踪(链路是否可达检测》。
5.2 ndv6目的地址缓存表
该目的路由表的形成时机:
当报文下行时需要根据报文的目的地址查询该目的地址表,若查不到该目的地址对应的目的地址表,则新建一个目的地址表条目。若该目的地址为本地链路地址(本地连接地址FE80::的地址或和本地单播地址前缀相同),则该条目目的地址和吓一跳地址都设置成该目的地址,PMTU设置成netif的MTU。若该目的地址为非本地连路上地址, 则在netif接口下选择第一个可用的default路由条目(接口up && 邻居缓存表是reachable状态),将该deault路由条目的吓一跳地址赋值给目的地址表中的next_hop_addr,pmtu设置成netif-mtu。
收到ICMPV6重定向报文时,更新该目的地址对应的吓一跳地址;
收到ICMPV6的差错报文“packet too pig”时,更新对应的pmtu(pmtu会在差错报文中携带);
age路由表本地老化定时器超时++,age在阈值以下该表项有效。若 age没超过阈值之前 该表项发生查找,则age置0.若age达到阈值,该表项老化删除。
数据报文查表过程:用报文目的地址查找 5.2 ndv6目的地址缓存表 获取吓一跳next_hop_address,再用next_hop_address查询5.1 ndv6邻居缓存表(类似于V4的ARP表)获取对端MAC地址封装报文。
5.3 ndv6地址前缀表
在发送RS消息后,收到RA消息时,RA消息中可选项携带地址前缀时生成该表项。
该表项有什么作用?
作为本地出接口和地址前缀映射表(可理解为本地链路接口表,只找出接口netif),即报文转发(ip6_forward)时,先根据目的地址查询该本地链路接口表,查找到则返回出接口netif。若查不到时再去遍历5.4 v6缺省表下的5.1 ndv6邻居缓存表(类似于V4的ARP表),找一条状态为reachable的netif。
但随着报文下行后需要继续封装二层Mac头,在IPV6_OUTPUT中还需要继续使用目的地址再次查询 5.2 ndv6目的地址缓存表获取到next_hop_address后,使用next_hop_address继续查询5.1 ndv6邻居缓存表(类似于V4的ARP表)取得MAC地址,报文下行write网卡驱动。
(感觉LWIP的V6设计查询逻辑有点混乱)
5.4 v6缺省表(每个netif下都有一个ipv6缺省路由表)
每个netif结构下可以有多个ipv6地址,但缺省路由只有一条.
该表项和5.1 ndv6邻居缓存表(类似于V4的ARP表)同步创建。
对5.1 ndv6邻居缓存表(类似于V4的ARP表)外部增加了2个控制信息:
收到RA消息时生成该表项,并记录RA报文中的router_life为invalidation_timer和flags。
该表项的作用:用于router_life条目有效期的老化管理。
5.5 几张表总结
其中本质上就是三张表很重要,本地链路接口表(5.3 ndv6地址前缀表)、路由表(5.2 ndv6目的地址缓存表)、邻居表(5.1 ndv6邻居缓存表(类似于V4的ARP表))。
需要快速查找直连链路的出接口netif就查找5.3 ndv6地址前缀表,
需要根据目的地址查找路由表下一跳就查找5.2 ndv6目的地址缓存表
需要根据下一跳/目的地址查找MAC地址就查找5.1 ndv6邻居缓存表(类似于V4的ARP表),其实该表中也存在出接口netif,所以5.3 ndv6地址前缀表在报文查找转发过程中并不是必须的,他最大的意义应该在于记录邻居地址前缀.