注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

itoedr的it学苑

记录从IT文盲学到专家的历程

 
 
 

日志

 
 

在 openvswitch 上配置 GRE tunnel(转集)  

2014-07-12 18:19:16|  分类: 虚拟化技术 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

在 korg 内核的 openvswitch 支持 GRE 之前,我们都是用内核原生的 GRE tunnel 来配置,而现在, korg 内核中的 openvswitch 也已经支持 GRE tunnel 了。有兴趣的可以看 openvswitch: Add tunneling interface. 和   openvswitch: Add gre tunnel support. 这两个 commit。

其实在 OVS 中添加 GRE 很简单,它无非就是把对 GRE 头和外部 IP 头的一些操作从原来的代码中抽象出来,做成内核“库函数”的形式,然后 OVS 中就可以直接调用它们了。难的是要从旧的 ip_gre 模块代码中抽象出这些“库函数”。详见 GRE: Refactor GRE tunneling code.

值得注意的是,OVS GRE tunnel 没有注册网络设备,也就是说你无法通过 `ip link` 看到它,它只是一个 vport 而已,所以能通过 ovs-vsctl show 可以看到。这是故意这么设计的,虽然这简化了用户的操作,但刚注意到时难免会感觉有些奇怪。

网上最流行的一篇讲解 OVS GRE tunnel 配置的教程是这篇文章,根据它我做了如下配置:

ovs-vsctl add-br grebr0
ovs-vsctl add-br phybr0
ovs-vsctl add-port phybr0 p1p1
ovs-vsctl add-port phybr0 tep0 -- set Interface tep0 type=internal
ifconfig tep0 192.168.88.1/24
ifconfig p1p1 0.0.0.0
ovs-vsctl add-port grebr0 vnet0
ovs-vsctl add-port grebr0 gre1 -- set Interface gre1 type=gre options:remote_ip=192.168.88.2

但是仔细分析一下,其实完全没有必要使用两个 bridge,通过 gre1 的包其实可以直接进入 p1p1,即最后的物理网卡。所以优化后的配置如下:

ovs-vsctl add-br grebr0
ifconfig p1p1 192.168.88.1/24
ovs-vsctl add-port grebr0 vnet0
ovs-vsctl add-port grebr0 gre1 -- set Interface gre1 type=gre options:remote_ip=192.168.88.2

通过 GRE tunnel 的包是重新注入网络栈中的,所以它们会直接流向 p1p1,最终流向物理层。

注意,这并没有结束。虽然通过这个配置你已经可以 ping 通对方 host 上的 VM 了,但是,如果你运行 netperf 测试的话,你会发现吞吐量非常低。这也是网络上的教程没有提到的地方。

这里的原因是从 vnet0 里出来数据包很多是 MTU 的大小,我这里是1500。而经过 GRE tunnel 后外面又添加了 GRE 头和外层的 IP 头,所以包就会大于 1500。而物理网卡的 MTU 也是 1500!并且,这些包本身并不是 GSO 的,所以这些包最终会被 IP 层分片(fragment),所以性能非常差!

这里有两种解决方法:

1) 把 VM 里的网卡 MTU 调小,比如 1400,这样 host 上的 GRE 加上额外的头也不会超过 1500;

2) 让 VM 里发出来的包依旧维持 GSO,这样 host 上收到的包也是 GSO,它们最终会被分段(segment),而不是分片(fragment)。这个可以通过给 qemu 传递 vnet_hdr=on 来完成(我没有试过,仅分析了源代码)。



如果你是用 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
  评论这张
 
阅读(211)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017