一、简介
GRE(Generic Routing Encapsulation)是一种通用路由封装协议,是隧道业务的一种。
GRE相关的RFC有很多,如rfc1701、rfc1702、rfc2784、rfc2890、rfc6245等。我们以此为顺序来介绍在RFC中规定的GRE报文结构和转发行为。
二、基本概念
在网络传输过程中,如果有报文需要进行封装然后转发,我们就称这个报文为负载报文(Payload packet);在GRE业务中,负载报文被封装在GRE报文头。只有GRE报文头的报文是无法直接在网络中传输的,需要将其封装在其他的协议中进行传输。我们称这个外层协议为传输头(Delivery Hearder)。因此GRE报文在网络中的传输格式就如下图所示:Delivery Header + GRE Header + Payload packet。
三、RFC1701
在RFC1701中规定了GRE Header的格式,如下图所示:
在报文首部的标记位有五个,分别如下:
注:如果C和R任意一个置位1,则表示Checksum和Offset都存在GRE报文中。
Protocol Type(2字节)
“协议类型”字段包含负载报文的协议类型。通常,该值将是数据包的以太网协议类型字段。下面列出了当前定义的协议类型。其他的值可以在其他文档中定义。
Offset(2字节)
offset字段表示要检测的主源路由表项从“Routing”字段开始到第一个字节的偏移量。当Routing present位或Checksum present位设置为1时,该字段才会出现。只有当Routing present位设置为1时,该字段才会包含有效的信息。
Checksum(2字节)
校验和字段包含GRE报文头以及负载。
Key(4字节)
Key字段长度为四个字节,是由封装者封装在报文中。可以被接收者用来验证报文的来源。
Sequence Number(4字节)
序列号字段长度为四个字节,是由封装者封装在报文中。接收者使用序列号来对接收的报文进行排序.
Routing(变长)
Routing的长度是可变的,是由一系列的SREs(Source Route Entries)组成的,其报文结构如下图所示:
四、RFC1702
RFC1701中定义了GRE的报文,在RFC1702中,主要是关于GRE over IPv4的说明。这里ipv4既可以作为传输协议也可以作为负载也可以二者都是。
五、RFC2784
RFC2784是2000.03修订的。这一版本的RFC简化了GRE头的定义,使其更加简单明了。其GRE报文格式如下:
可以看到,相比于RFC1701,RFC2784在GRE报文前两个字节的定义简单了许多,只有一个关键字C,其含义与RFC701一致,表明校验和存在位,置位1则表示Checksum存在且包含有效信息。
规范指出,对于那些没有实现RFC1701的设备,bit1-5必须为0,否则需要将报文丢弃。bit6-12供以后使用,必须设置为0,且接受者不需要不对其检验。
对于Ver(Version Number)、protocol type和Checksum字段,则与RFC1701一样。
Reserved1占两个字节,如果C置位1,Reserved1字段就必须存在,且为全0。
1、转发细则
当IPv4报文作为负载时,protocol type必须为0x0800。
隧道终结时,如果GRE报文中的负载是IPv4,ipv4报文的dip必须用来进行转发,且内层ipv4报文的TTL必须缩减。当IPv4作为外层报文时,其协议字段必须为47,在网络中的转发行为与IPv4的转发行为一致。
2、与RFC1701兼容性说明
RFC2784新增了对RFC1701的说明,将GRE报文前两个字节的标记位简化至只有C字段。并且指出,接收者如使用RFC1701需要明确指出执行RFC1701。
3、GRE Version Numbers
一般情况下,该字段默认置0,如果改字段置1,则表示为PPTP协议。
4、已知问题
PMTU问题:当用IPv4作为传送协议时,现有实现并不实现路径MTU发现和不设置禁止分片标志。当传送大包时,在隧道中会分片,在隧道端再重组。如果一个隧道端希望实现Path MTU发现,那么该隧道也需要实现把ICMP不可达错误信息报文(需要分片,设置DF位)回复给报文产生者。否则,假如报文产生者设置了不分片标志,那么报文在隧道中可能会被丢弃,但没有把该ICMP错误信息传回给产生者,那么后续的报文也将使用相同的PMTU,导致后续报文都被丢弃。
IPv6+GRE问题,此规范中并未给出IPv6+GRE的格式及转发行为。
六、RFC2890
可能是因为在RFC2784中,将GRE报文前两个字节简化的太严重,只剩下一个标记位,因此在同年九月份,RFC2890中对RFC2784进行了更新说明。更新之后的GRE报文格式如下:
Key(4字节)
Key字段占四个字节,在转发时由发送端进行封装。“Key”字段用于标识隧道内的单个流量流。例如,可能需要根据报文头中不存在的信息来对数据包进行转发。Key字段提供了这个功能,并定义了发送端和接收端之间的逻辑通信流。
Sequence Number(4字节)
Sequence Number字段占四个字节,在转发时由发送端进行封装。序列号字段是一个四个字节的字段,当序列号显示位被设置时由封装器插入。接收方必须使用序列号来确定数据包从封装器传输到接收方的顺序。Sequence Field的预期用途是提供不可靠但有序的交付。如果设置了Key present位(第2位),则序列号针对Key字段所标识的流量。请注意,没有序列位集的数据包可以与序列位集的数据包交叉。
参考文献:RFC1701、RFC1702、RFC2784、RFC2890