在 openvswitch 上配置 GRE tunnel

如果你是用 openvswitch 内置的 GRE tunnel,那么配置很简单,基本上就一条命令:

ovs-vsctl add-port br0 gre0 -- set interface gre0 type=gre options:remote_ip=192.168.1.10

本文想谈的显然不是这个。因为 upstream 内核(指 Linus tree)中的 openvswitch 是不支持 GRE tunnel 的,那我们如何在 upstream 内核中上使用 GRE tunnel 呢?

其实也不难,我们可以创建一个普通的 GRE tunnel,然后把它添加到 openvswitch bridge 中去就可以了。至少这在理论上是可行的,而实际操作中却有一些问题,你可以动手试一试。我们假设网络环境如下图所示:

我们的目标是让 HOST1 上面的两个 VM 和 HOST2 上面的两个 VM 通过 GRE tunnel 实现通信。因为两边的配置是对称的,所以下面只说明 HOST2 上是如何配置的,HOST1 上以此类推即可。

在这个环境中,一个很可能的错误是把 HOST2 上的 uplink,即 eth0 也加入到 openvswitch 的 bridge 中,这是不对的,需要加入仅仅的是 GRE tunnel 设备,即 gre1 (你当然也可以把它命名为其它名字)。

剩下的一个最重要的问题是,GRE tunnel 是无法回应 ARP 的,因为它是一个 point to point 的设备(ip addr add 192.168.2.1/24 peer 192.168.1.1/24 dev gre1),所以很明显设置了 NOARP。这个问题是这里的关键。因为这个的缘故,即使你在 VM1 上也无法 ping HOST2 上的 gre1。所以这里需要一个技巧,就是要给 bridge 本身配置一个 IP 地址,然后让 bridge 做一个 ARP proxy

所以最后在 HOST2 上面的配置如下:

[root@host2 ~]# ip tunnel show
gre0: gre/ip  remote any  local any  ttl inherit  nopmtudisc
gre1: gre/ip  remote 10.16.43.214  local 10.16.43.215  ttl inherit
[root@host2 ~]# ip r s
192.168.2.0/24 dev ovsbr0  proto kernel  scope link  src 192.168.2.4
192.168.1.0/24 dev gre1  scope link
192.168.122.0/24 dev virbr0  proto kernel  scope link  src 192.168.122.1
10.16.40.0/21 dev eth0  proto kernel  scope link  src 10.16.43.215
169.254.0.0/16 dev eth0  scope link  metric 1005
default via 10.16.47.254 dev eth0
[root@host2 ~]# ovs-vsctl show
71f0f455-ccc8-4781-88b2-4b663dd48c5f
    Bridge "ovsbr0"
        Port "vnet0"
            Interface "vnet0"
        Port "ovsbr0"
            Interface "ovsbr0"
                type: internal
        Port "vnet1"
            Interface "vnet1"
        Port "gre1"
            Interface "gre1"
    ovs_version: "1.7.0"

[root@host2 ~]# ip addr ls gre1 && ip addr ls ovsbr0
17: gre1:  mtu 1476 qdisc noqueue state UNKNOWN
    link/gre 10.16.43.215 peer 10.16.43.214
    inet 192.168.2.1/24 scope global gre1
    inet 192.168.2.1 peer 192.168.1.1/24 scope global gre1
13: ovsbr0:  mtu 1500 qdisc noqueue state UNKNOWN
    link/ether 66:d7:ae:42:db:44 brd ff:ff:ff:ff:ff:ff
    inet 192.168.2.4/24 brd 192.168.2.255 scope global ovsbr0
    inet6 fe80::64d7:aeff:fe42:db44/64 scope link
       valid_lft forever preferred_lft forever

[root@host2 ~]# cat /proc/sys/net/ipv4/conf/ovsbr0/proxy_arp
1

HOST2 上面的 VM1 只需添加一个路由即可,配置如下:
[root@localhost ~]# ip r s
192.168.2.0/24 dev eth1  proto kernel  scope link  src 192.168.2.2
192.168.1.0/24 dev eth1  scope link  src 192.168.2.2
[root@localhost ~]# ping 192.168.1.2
PING 192.168.1.2 (192.168.1.2) 56(84) bytes of data.
64 bytes from 192.168.1.2: icmp_seq=1 ttl=62 time=561 ms
64 bytes from 192.168.1.2: icmp_seq=2 ttl=62 time=0.731 ms
64 bytes from 192.168.1.2: icmp_seq=3 ttl=62 time=0.669 ms
64 bytes from 192.168.1.2: icmp_seq=4 ttl=62 time=0.765 ms

--- 192.168.1.2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3823ms
rtt min/avg/max/mdev = 0.669/140.860/561.275/242.726 ms