diff mbox series

[ovs-dev,PATCHv2] tunnel: add ip6gretap support.

Message ID 1561046127-102875-1-git-send-email-u9012063@gmail.com
State Superseded
Headers show
Series [ovs-dev,PATCHv2] tunnel: add ip6gretap support. | expand

Commit Message

William Tu June 20, 2019, 3:55 p.m. UTC
The patch adds ip6gretap support. Tunnel type ip6gretap is a layer 2 GRE
tunnel over IPv6, carrying inner ethernet packets and encap with GRE header
with outer IPv6 header.  I tested it by running:
  # make check-kernel
under kernel 5.2 and for userspace:
  # make check TESTSUITEFLAGS='-k ip6gretap'

Signed-off-by: William Tu <u9012063@gmail.com>
---
v1-v2: rebase to master

---
 Documentation/faq/configuration.rst | 12 +++++++
 NEWS                                |  1 +
 datapath/linux/compat/ip6_gre.c     |  2 +-
 lib/dpif-netlink-rtnl.c             |  2 +-
 lib/dpif-netlink.c                  |  4 ++-
 lib/netdev-vport.c                  |  4 +--
 lib/tnl-ports.c                     |  3 +-
 tests/system-traffic.at             | 40 ++++++++++++++++++++++
 tests/tunnel-push-pop-ipv6.at       | 68 +++++++++++++++++++++++++++++++++++++
 9 files changed, 130 insertions(+), 6 deletions(-)

Comments

Eli Britstein June 20, 2019, 5 p.m. UTC | #1
On 6/20/2019 6:55 PM, William Tu wrote:
> The patch adds ip6gretap support. Tunnel type ip6gretap is a layer 2 GRE
> tunnel over IPv6, carrying inner ethernet packets and encap with GRE header
> with outer IPv6 header.  I tested it by running:
>    # make check-kernel
> under kernel 5.2 and for userspace:
>    # make check TESTSUITEFLAGS='-k ip6gretap'
>
> Signed-off-by: William Tu <u9012063@gmail.com>
> ---
> v1-v2: rebase to master
>
> ---
>   Documentation/faq/configuration.rst | 12 +++++++
>   NEWS                                |  1 +
>   datapath/linux/compat/ip6_gre.c     |  2 +-
>   lib/dpif-netlink-rtnl.c             |  2 +-
>   lib/dpif-netlink.c                  |  4 ++-
>   lib/netdev-vport.c                  |  4 +--
>   lib/tnl-ports.c                     |  3 +-
>   tests/system-traffic.at             | 40 ++++++++++++++++++++++
>   tests/tunnel-push-pop-ipv6.at       | 68 +++++++++++++++++++++++++++++++++++++
>   9 files changed, 130 insertions(+), 6 deletions(-)
>
> diff --git a/Documentation/faq/configuration.rst b/Documentation/faq/configuration.rst
> index cb2c6b4eca98..c9bcfa8a790d 100644
> --- a/Documentation/faq/configuration.rst
> +++ b/Documentation/faq/configuration.rst
> @@ -212,6 +212,18 @@ Q: Does Open vSwitch support ERSPAN?
>                   options:erspan_ver=2 options:erspan_dir=1 \
>                   options:erspan_hwid=4
>   
> +Q: Does Open vSwitch support IPv6 GRE?
> +
> +    A: Yes. L2 tunnel interface GRE over IPv6 is supported.
> +    L3 GRE tunnel over IPv6 is not supported.
> +
> +    ::
> +
> +        $ ovs-vsctl add-br br0
> +        $ ovs-vsctl add-port br0 at_gretap0 -- \
> +                set int at_gretap0 type=ip6gretap \
> +                options:remote_ip=fc00:100::1
> +
>   Q: How do I connect two bridges?
>   
>       A: First, why do you want to do this?  Two connected bridges are not much
> diff --git a/NEWS b/NEWS
> index a38ab258fc6c..c7e84ed7931d 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -47,6 +47,7 @@ Post-v2.11.0
>      - Linux datapath:
>        * Support for the kernel versions 4.19.x and 4.20.x.
>        * Support for the kernel version 5.0.x.
> +   - Add L2 GRE tunnel over IPv6 support.
>   
>   
>   v2.11.0 - 19 Feb 2019
> diff --git a/datapath/linux/compat/ip6_gre.c b/datapath/linux/compat/ip6_gre.c
> index ca4e66133570..ab50c72d0753 100644
> --- a/datapath/linux/compat/ip6_gre.c
> +++ b/datapath/linux/compat/ip6_gre.c
> @@ -2550,7 +2550,7 @@ static struct rtnl_link_ops ip6gre_link_ops __read_mostly = {
>   };
>   
>   static struct rtnl_link_ops ip6gre_tap_ops __read_mostly = {
> -	.kind		= "ip6gre",
> +	.kind		= "ip6gretap",
>   	.maxtype	= RPL_IFLA_GRE_MAX,
>   	.policy		= ip6gre_policy,
>   	.priv_size	= sizeof(struct ip6_tnl),
> diff --git a/lib/dpif-netlink-rtnl.c b/lib/dpif-netlink-rtnl.c
> index 2e23a8c14fcf..d666f239aeed 100644
> --- a/lib/dpif-netlink-rtnl.c
> +++ b/lib/dpif-netlink-rtnl.c
> @@ -104,7 +104,7 @@ vport_type_to_kind(enum ovs_vport_type type,
>       case OVS_VPORT_TYPE_IP6ERSPAN:
>           return "ip6erspan";
>       case OVS_VPORT_TYPE_IP6GRE:
> -        return "ip6gre";
> +        return "ip6gretap";
>       case OVS_VPORT_TYPE_NETDEV:
>       case OVS_VPORT_TYPE_INTERNAL:
>       case OVS_VPORT_TYPE_LISP:
> diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c
> index ba80a0079181..fc1d1591975e 100644
> --- a/lib/dpif-netlink.c
> +++ b/lib/dpif-netlink.c
> @@ -699,7 +699,7 @@ get_vport_type(const struct dpif_netlink_vport *vport)
>           return "ip6erspan";
>   
>       case OVS_VPORT_TYPE_IP6GRE:
> -        return "ip6gre";
> +        return "ip6gretap";
>   
>       case OVS_VPORT_TYPE_UNSPEC:
>       case __OVS_VPORT_TYPE_MAX:
> @@ -730,6 +730,8 @@ netdev_to_ovs_vport_type(const char *type)
>           return OVS_VPORT_TYPE_ERSPAN;
>       } else if (!strcmp(type, "ip6erspan")) {
>           return OVS_VPORT_TYPE_IP6ERSPAN;
> +    } else if (!strcmp(type, "ip6gretap")) {
> +        return OVS_VPORT_TYPE_IP6GRE;
>       } else if (!strcmp(type, "ip6gre")) {
>           return OVS_VPORT_TYPE_IP6GRE;
>       } else if (!strcmp(type, "gre")) {
> diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
> index 92a256af16ed..5a20415529eb 100644
> --- a/lib/netdev-vport.c
> +++ b/lib/netdev-vport.c
> @@ -1212,10 +1212,10 @@ netdev_vport_tunnel_register(void)
>             },
>             {{NULL, NULL, 0, 0}}
>           },
> -        { "ip6gre_sys",
> +        { "ip6gretap_sys",
>             {
>                 TUNNEL_FUNCTIONS_COMMON,
> -              .type = "ip6gre",
> +              .type = "ip6gretap",
>                 .build_header = netdev_gre_build_header,
>                 .push_header = netdev_gre_push_header,
>                 .pop_header = netdev_gre_pop_header
> diff --git a/lib/tnl-ports.c b/lib/tnl-ports.c
> index 17353046cc6e..62065c0027cd 100644
> --- a/lib/tnl-ports.c
> +++ b/lib/tnl-ports.c
> @@ -172,7 +172,8 @@ tnl_type_to_nw_proto(const char type[])
>           return IPPROTO_TCP;
>       }
>       if (!strcmp(type, "gre") || !strcmp(type, "erspan") ||
> -        !strcmp(type, "ip6erspan") || !strcmp(type, "ip6gre")) {
> +        !strcmp(type, "ip6erspan") || !strcmp(type, "ip6gre") ||
> +        !strcmp(type, "ip6gretap")) {
>           return IPPROTO_GRE;
>       }
>       if (!strcmp(type, "vxlan")) {
> diff --git a/tests/system-traffic.at b/tests/system-traffic.at
> index d23ee897b0b2..43056733794a 100644
> --- a/tests/system-traffic.at
> +++ b/tests/system-traffic.at
> @@ -340,6 +340,46 @@ NS_CHECK_EXEC([at_ns0], [ping -s 3200 -q -c 3 -i 0.3 -w 2 10.1.1.100 | FORMAT_PI
>   OVS_TRAFFIC_VSWITCHD_STOP
>   AT_CLEANUP
>   
> +AT_SETUP([datapath - ping over ip6gretap tunnel])
> +OVS_CHECK_KERNEL_EXCL(3, 10, 4, 15)
> +OVS_CHECK_GRE()
> +OVS_CHECK_ERSPAN()
> +
> +OVS_TRAFFIC_VSWITCHD_START()
> +ADD_BR([br-underlay])
> +
> +AT_CHECK([ovs-ofctl add-flow br0 "actions=normal"])
> +AT_CHECK([ovs-ofctl add-flow br-underlay "actions=normal"])
> +
> +ADD_NAMESPACES(at_ns0)
> +
> +dnl Set up underlay link from host into the namespace using veth pair.
> +ADD_VETH(p0, at_ns0, br-underlay, "fc00:100::1/96", [], [], nodad)
> +AT_CHECK([ip addr add dev br-underlay "fc00:100::100/96" nodad])
> +AT_CHECK([ip link set dev br-underlay up])
> +
> +dnl Set up tunnel endpoints on OVS outside the namespace and with a native
> +dnl linux device inside the namespace.
> +ADD_OVS_TUNNEL6([ip6gretap], [br0], [at_gretap0], [fc00:100::1], [10.1.1.100/24],
> +                [])
> +ADD_NATIVE_TUNNEL6([ip6gretap], [ns_gretap0], [at_ns0], [fc00:100::100],
> +                   [10.1.1.1/24], [local fc00:100::1])
> +
> +OVS_WAIT_UNTIL([ip netns exec at_ns0 ping6 -c 2 fc00:100::100])
> +
> +dnl First, check the underlay
> +NS_CHECK_EXEC([at_ns0], [ping6 -q -c 3 -i 0.3 -w 2 fc00:100::100 | FORMAT_PING], [0], [dnl
> +3 packets transmitted, 3 received, 0% packet loss, time 0ms
> +])
> +
> +dnl Okay, now check the overlay with different packet sizes
> +NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -w 2 10.1.1.100 | FORMAT_PING], [0], [dnl
> +3 packets transmitted, 3 received, 0% packet loss, time 0ms
> +])
> +OVS_TRAFFIC_VSWITCHD_STOP
> +AT_CLEANUP
> +
> +
>   AT_SETUP([datapath - ping over erspan v1 tunnel])
>   OVS_CHECK_KERNEL_EXCL(3, 10, 4, 15)
>   OVS_CHECK_GRE()
> diff --git a/tests/tunnel-push-pop-ipv6.at b/tests/tunnel-push-pop-ipv6.at
> index cbdd5a32f719..07dd6ab504a0 100644
> --- a/tests/tunnel-push-pop-ipv6.at
> +++ b/tests/tunnel-push-pop-ipv6.at
> @@ -1,5 +1,73 @@
>   AT_BANNER([tunnel_push_pop_ipv6])
>   
> +AT_SETUP([tunnel_push_pop_ipv6 - ip6gretap])
> +
> +OVS_VSWITCHD_START([add-port br0 p0 -- set Interface p0 type=dummy ofport_request=1 other-config:hwaddr=aa:55:aa:55:00:00])
> +AT_CHECK([ovs-vsctl add-br int-br -- set bridge int-br datapath_type=dummy], [0])
> +AT_CHECK([ovs-vsctl add-port int-br t2 -- set Interface t2 type=ip6gretap \
> +                       options:remote_ip=2001:cafe::92 ofport_request=2\
> +                       ], [0])
> +
> +AT_CHECK([ovs-appctl dpif/show], [0], [dnl
> +dummy@ovs-dummy: hit:0 missed:0
> +  br0:
> +    br0 65534/100: (dummy-internal)
> +    p0 1/1: (dummy)
> +  int-br:
> +    int-br 65534/2: (dummy-internal)
> +    t2 2/6: (ip6gretap: remote_ip=2001:cafe::92)
> +])
> +
> +dnl First setup dummy interface IP address, then add the route
> +dnl so that tnl-port table can get valid IP address for the device.
> +AT_CHECK([ovs-appctl netdev-dummy/ip6addr br0 2001:cafe::88/24], [0], [OK
> +])
> +AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 1.1.2.88/24], [0], [OK
> +])
> +AT_CHECK([ovs-appctl ovs/route/add 2001:cafe::92/24 br0], [0], [OK
> +])
> +
> +AT_CHECK([ovs-ofctl add-flow br0 action=normal])
> +
> +dnl Check Neighbour discovery.
> +AT_CHECK([ovs-vsctl -- set Interface p0 options:pcap=p0.pcap])
> +
> +AT_CHECK([ovs-appctl netdev-dummy/receive int-br 'in_port(2),eth(src=aa:55:aa:55:00:00,dst=f8:bc:12:ff:ff:ff),eth_type(0x0800),ipv4(src=1.1.3.92,dst=1.1.3.88,proto=1,tos=0,ttl=64,frag=no),icmp(type=0,code=0)'])
> +AT_CHECK([ovs-pcap p0.pcap > p0.pcap.txt 2>&1])
> +
> +AT_CHECK([cat p0.pcap.txt | grep 92aa55aa55000086dd6000000000203aff2001cafe | uniq], [0], [dnl
> +3333ff000092aa55aa55000086dd6000000000203aff2001cafe000000000000000000000088ff0200000000000000000001ff00009287004d48000000002001cafe0000000000000000000000920101aa55aa550000
> +])
> +
> +dnl
> +AT_CHECK([ovs-appctl netdev-dummy/receive p0 'in_port(1),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x86dd),ipv6(src=2001:cafe::92,dst=2001:cafe::88,label=0,proto=58,tclass=0,hlimit=255,frag=no),icmpv6(type=136,code=0),nd(target=2001:cafe::92,sll=00:00:00:00:00:00,tll=f8:bc:12:44:34:b6)'])
> +
> +AT_CHECK([ovs-appctl tnl/arp/show | tail -n+3 | sort], [0], [dnl
> +2001:cafe::92                                 f8:bc:12:44:34:b6   br0
> +])
> +
> +AT_CHECK([ovs-appctl tnl/ports/show |sort], [0], [dnl
> +Listening ports:
> +ip6gretap_sys (6) ref_cnt=1
> +])
> +
> +dnl Check IPv6 GRE tunnel pop
> +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x86dd),ipv6(src=2001:cafe::92,dst=2001:cafe::88,label=0,proto=47,tclass=0x0,hlimit=64)'], [0], [stdout])
> +AT_CHECK([tail -1 stdout], [0],
> +  [Datapath actions: tnl_pop(6)
> +])
> +
> +dnl Check IPv6 GRE tunnel push
> +AT_CHECK([ovs-ofctl add-flow int-br action=2])
> +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:01),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout])
> +
> +AT_CHECK([tail -1 stdout], [0],
> +  [Datapath actions: clone(tnl_push(tnl_port(6),header(size=58,type=109,eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:00,dl_type=0x86dd),ipv6(src=2001:cafe::88,dst=2001:cafe::92,label=0,proto=47,tclass=0x0,hlimit=64),gre((flags=0x0,proto=0x6558))),out_port(100)),1)
> +])
> +
> +OVS_VSWITCHD_STOP
> +AT_CLEANUP
> +
>   AT_SETUP([tunnel_push_pop_ipv6 - ip6erspan])
>   
>   OVS_VSWITCHD_START([add-port br0 p0 -- set Interface p0 type=dummy ofport_request=1 other-config:hwaddr=aa:55:aa:55:00:00])

Works for me. Thanks!

However, do we want to keep a separate configuration for IPv6 GRE vs 
IPv4 GRE? if so, some more documentation should be adapted, for example 
vswitchd/vswitch.xml make "gre" for IPv4 and not IPv4/IPv6, and more 
places add ip6gretap as a legitimate tunnel.

Alternatively, we can maybe detect the options:remote_ip to be an 
IPv4/IPv6 address in type=gre and do the proper adjustments behind the 
scenes.

What do you think?
Gregory Rose June 20, 2019, 5:10 p.m. UTC | #2
On 6/20/2019 10:00 AM, Eli Britstein wrote:
> On 6/20/2019 6:55 PM, William Tu wrote:
>> The patch adds ip6gretap support. Tunnel type ip6gretap is a layer 2 GRE
>> tunnel over IPv6, carrying inner ethernet packets and encap with GRE header
>> with outer IPv6 header.  I tested it by running:
>>     # make check-kernel
>> under kernel 5.2 and for userspace:
>>     # make check TESTSUITEFLAGS='-k ip6gretap'
>>
>> Signed-off-by: William Tu <u9012063@gmail.com>
>> ---
>> v1-v2: rebase to master
>>
>> ---
>>    Documentation/faq/configuration.rst | 12 +++++++
>>    NEWS                                |  1 +
>>    datapath/linux/compat/ip6_gre.c     |  2 +-
>>    lib/dpif-netlink-rtnl.c             |  2 +-
>>    lib/dpif-netlink.c                  |  4 ++-
>>    lib/netdev-vport.c                  |  4 +--
>>    lib/tnl-ports.c                     |  3 +-
>>    tests/system-traffic.at             | 40 ++++++++++++++++++++++
>>    tests/tunnel-push-pop-ipv6.at       | 68 +++++++++++++++++++++++++++++++++++++
>>    9 files changed, 130 insertions(+), 6 deletions(-)
>>
>> diff --git a/Documentation/faq/configuration.rst b/Documentation/faq/configuration.rst
>> index cb2c6b4eca98..c9bcfa8a790d 100644
>> --- a/Documentation/faq/configuration.rst
>> +++ b/Documentation/faq/configuration.rst
>> @@ -212,6 +212,18 @@ Q: Does Open vSwitch support ERSPAN?
>>                    options:erspan_ver=2 options:erspan_dir=1 \
>>                    options:erspan_hwid=4
>>    
>> +Q: Does Open vSwitch support IPv6 GRE?
>> +
>> +    A: Yes. L2 tunnel interface GRE over IPv6 is supported.
>> +    L3 GRE tunnel over IPv6 is not supported.
>> +
>> +    ::
>> +
>> +        $ ovs-vsctl add-br br0
>> +        $ ovs-vsctl add-port br0 at_gretap0 -- \
>> +                set int at_gretap0 type=ip6gretap \
>> +                options:remote_ip=fc00:100::1
>> +
>>    Q: How do I connect two bridges?
>>    
>>        A: First, why do you want to do this?  Two connected bridges are not much
>> diff --git a/NEWS b/NEWS
>> index a38ab258fc6c..c7e84ed7931d 100644
>> --- a/NEWS
>> +++ b/NEWS
>> @@ -47,6 +47,7 @@ Post-v2.11.0
>>       - Linux datapath:
>>         * Support for the kernel versions 4.19.x and 4.20.x.
>>         * Support for the kernel version 5.0.x.
>> +   - Add L2 GRE tunnel over IPv6 support.
>>    
>>    
>>    v2.11.0 - 19 Feb 2019
>> diff --git a/datapath/linux/compat/ip6_gre.c b/datapath/linux/compat/ip6_gre.c
>> index ca4e66133570..ab50c72d0753 100644
>> --- a/datapath/linux/compat/ip6_gre.c
>> +++ b/datapath/linux/compat/ip6_gre.c
>> @@ -2550,7 +2550,7 @@ static struct rtnl_link_ops ip6gre_link_ops __read_mostly = {
>>    };
>>    
>>    static struct rtnl_link_ops ip6gre_tap_ops __read_mostly = {
>> -	.kind		= "ip6gre",
>> +	.kind		= "ip6gretap",
>>    	.maxtype	= RPL_IFLA_GRE_MAX,
>>    	.policy		= ip6gre_policy,
>>    	.priv_size	= sizeof(struct ip6_tnl),
>> diff --git a/lib/dpif-netlink-rtnl.c b/lib/dpif-netlink-rtnl.c
>> index 2e23a8c14fcf..d666f239aeed 100644
>> --- a/lib/dpif-netlink-rtnl.c
>> +++ b/lib/dpif-netlink-rtnl.c
>> @@ -104,7 +104,7 @@ vport_type_to_kind(enum ovs_vport_type type,
>>        case OVS_VPORT_TYPE_IP6ERSPAN:
>>            return "ip6erspan";
>>        case OVS_VPORT_TYPE_IP6GRE:
>> -        return "ip6gre";
>> +        return "ip6gretap";
>>        case OVS_VPORT_TYPE_NETDEV:
>>        case OVS_VPORT_TYPE_INTERNAL:
>>        case OVS_VPORT_TYPE_LISP:
>> diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c
>> index ba80a0079181..fc1d1591975e 100644
>> --- a/lib/dpif-netlink.c
>> +++ b/lib/dpif-netlink.c
>> @@ -699,7 +699,7 @@ get_vport_type(const struct dpif_netlink_vport *vport)
>>            return "ip6erspan";
>>    
>>        case OVS_VPORT_TYPE_IP6GRE:
>> -        return "ip6gre";
>> +        return "ip6gretap";
>>    
>>        case OVS_VPORT_TYPE_UNSPEC:
>>        case __OVS_VPORT_TYPE_MAX:
>> @@ -730,6 +730,8 @@ netdev_to_ovs_vport_type(const char *type)
>>            return OVS_VPORT_TYPE_ERSPAN;
>>        } else if (!strcmp(type, "ip6erspan")) {
>>            return OVS_VPORT_TYPE_IP6ERSPAN;
>> +    } else if (!strcmp(type, "ip6gretap")) {
>> +        return OVS_VPORT_TYPE_IP6GRE;
>>        } else if (!strcmp(type, "ip6gre")) {
>>            return OVS_VPORT_TYPE_IP6GRE;
>>        } else if (!strcmp(type, "gre")) {
>> diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
>> index 92a256af16ed..5a20415529eb 100644
>> --- a/lib/netdev-vport.c
>> +++ b/lib/netdev-vport.c
>> @@ -1212,10 +1212,10 @@ netdev_vport_tunnel_register(void)
>>              },
>>              {{NULL, NULL, 0, 0}}
>>            },
>> -        { "ip6gre_sys",
>> +        { "ip6gretap_sys",
>>              {
>>                  TUNNEL_FUNCTIONS_COMMON,
>> -              .type = "ip6gre",
>> +              .type = "ip6gretap",
>>                  .build_header = netdev_gre_build_header,
>>                  .push_header = netdev_gre_push_header,
>>                  .pop_header = netdev_gre_pop_header
>> diff --git a/lib/tnl-ports.c b/lib/tnl-ports.c
>> index 17353046cc6e..62065c0027cd 100644
>> --- a/lib/tnl-ports.c
>> +++ b/lib/tnl-ports.c
>> @@ -172,7 +172,8 @@ tnl_type_to_nw_proto(const char type[])
>>            return IPPROTO_TCP;
>>        }
>>        if (!strcmp(type, "gre") || !strcmp(type, "erspan") ||
>> -        !strcmp(type, "ip6erspan") || !strcmp(type, "ip6gre")) {
>> +        !strcmp(type, "ip6erspan") || !strcmp(type, "ip6gre") ||
>> +        !strcmp(type, "ip6gretap")) {
>>            return IPPROTO_GRE;
>>        }
>>        if (!strcmp(type, "vxlan")) {
>> diff --git a/tests/system-traffic.at b/tests/system-traffic.at
>> index d23ee897b0b2..43056733794a 100644
>> --- a/tests/system-traffic.at
>> +++ b/tests/system-traffic.at
>> @@ -340,6 +340,46 @@ NS_CHECK_EXEC([at_ns0], [ping -s 3200 -q -c 3 -i 0.3 -w 2 10.1.1.100 | FORMAT_PI
>>    OVS_TRAFFIC_VSWITCHD_STOP
>>    AT_CLEANUP
>>    
>> +AT_SETUP([datapath - ping over ip6gretap tunnel])
>> +OVS_CHECK_KERNEL_EXCL(3, 10, 4, 15)
>> +OVS_CHECK_GRE()
>> +OVS_CHECK_ERSPAN()
>> +
>> +OVS_TRAFFIC_VSWITCHD_START()
>> +ADD_BR([br-underlay])
>> +
>> +AT_CHECK([ovs-ofctl add-flow br0 "actions=normal"])
>> +AT_CHECK([ovs-ofctl add-flow br-underlay "actions=normal"])
>> +
>> +ADD_NAMESPACES(at_ns0)
>> +
>> +dnl Set up underlay link from host into the namespace using veth pair.
>> +ADD_VETH(p0, at_ns0, br-underlay, "fc00:100::1/96", [], [], nodad)
>> +AT_CHECK([ip addr add dev br-underlay "fc00:100::100/96" nodad])
>> +AT_CHECK([ip link set dev br-underlay up])
>> +
>> +dnl Set up tunnel endpoints on OVS outside the namespace and with a native
>> +dnl linux device inside the namespace.
>> +ADD_OVS_TUNNEL6([ip6gretap], [br0], [at_gretap0], [fc00:100::1], [10.1.1.100/24],
>> +                [])
>> +ADD_NATIVE_TUNNEL6([ip6gretap], [ns_gretap0], [at_ns0], [fc00:100::100],
>> +                   [10.1.1.1/24], [local fc00:100::1])
>> +
>> +OVS_WAIT_UNTIL([ip netns exec at_ns0 ping6 -c 2 fc00:100::100])
>> +
>> +dnl First, check the underlay
>> +NS_CHECK_EXEC([at_ns0], [ping6 -q -c 3 -i 0.3 -w 2 fc00:100::100 | FORMAT_PING], [0], [dnl
>> +3 packets transmitted, 3 received, 0% packet loss, time 0ms
>> +])
>> +
>> +dnl Okay, now check the overlay with different packet sizes
>> +NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -w 2 10.1.1.100 | FORMAT_PING], [0], [dnl
>> +3 packets transmitted, 3 received, 0% packet loss, time 0ms
>> +])
>> +OVS_TRAFFIC_VSWITCHD_STOP
>> +AT_CLEANUP
>> +
>> +
>>    AT_SETUP([datapath - ping over erspan v1 tunnel])
>>    OVS_CHECK_KERNEL_EXCL(3, 10, 4, 15)
>>    OVS_CHECK_GRE()
>> diff --git a/tests/tunnel-push-pop-ipv6.at b/tests/tunnel-push-pop-ipv6.at
>> index cbdd5a32f719..07dd6ab504a0 100644
>> --- a/tests/tunnel-push-pop-ipv6.at
>> +++ b/tests/tunnel-push-pop-ipv6.at
>> @@ -1,5 +1,73 @@
>>    AT_BANNER([tunnel_push_pop_ipv6])
>>    
>> +AT_SETUP([tunnel_push_pop_ipv6 - ip6gretap])
>> +
>> +OVS_VSWITCHD_START([add-port br0 p0 -- set Interface p0 type=dummy ofport_request=1 other-config:hwaddr=aa:55:aa:55:00:00])
>> +AT_CHECK([ovs-vsctl add-br int-br -- set bridge int-br datapath_type=dummy], [0])
>> +AT_CHECK([ovs-vsctl add-port int-br t2 -- set Interface t2 type=ip6gretap \
>> +                       options:remote_ip=2001:cafe::92 ofport_request=2\
>> +                       ], [0])
>> +
>> +AT_CHECK([ovs-appctl dpif/show], [0], [dnl
>> +dummy@ovs-dummy: hit:0 missed:0
>> +  br0:
>> +    br0 65534/100: (dummy-internal)
>> +    p0 1/1: (dummy)
>> +  int-br:
>> +    int-br 65534/2: (dummy-internal)
>> +    t2 2/6: (ip6gretap: remote_ip=2001:cafe::92)
>> +])
>> +
>> +dnl First setup dummy interface IP address, then add the route
>> +dnl so that tnl-port table can get valid IP address for the device.
>> +AT_CHECK([ovs-appctl netdev-dummy/ip6addr br0 2001:cafe::88/24], [0], [OK
>> +])
>> +AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 1.1.2.88/24], [0], [OK
>> +])
>> +AT_CHECK([ovs-appctl ovs/route/add 2001:cafe::92/24 br0], [0], [OK
>> +])
>> +
>> +AT_CHECK([ovs-ofctl add-flow br0 action=normal])
>> +
>> +dnl Check Neighbour discovery.
>> +AT_CHECK([ovs-vsctl -- set Interface p0 options:pcap=p0.pcap])
>> +
>> +AT_CHECK([ovs-appctl netdev-dummy/receive int-br 'in_port(2),eth(src=aa:55:aa:55:00:00,dst=f8:bc:12:ff:ff:ff),eth_type(0x0800),ipv4(src=1.1.3.92,dst=1.1.3.88,proto=1,tos=0,ttl=64,frag=no),icmp(type=0,code=0)'])
>> +AT_CHECK([ovs-pcap p0.pcap > p0.pcap.txt 2>&1])
>> +
>> +AT_CHECK([cat p0.pcap.txt | grep 92aa55aa55000086dd6000000000203aff2001cafe | uniq], [0], [dnl
>> +3333ff000092aa55aa55000086dd6000000000203aff2001cafe000000000000000000000088ff0200000000000000000001ff00009287004d48000000002001cafe0000000000000000000000920101aa55aa550000
>> +])
>> +
>> +dnl
>> +AT_CHECK([ovs-appctl netdev-dummy/receive p0 'in_port(1),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x86dd),ipv6(src=2001:cafe::92,dst=2001:cafe::88,label=0,proto=58,tclass=0,hlimit=255,frag=no),icmpv6(type=136,code=0),nd(target=2001:cafe::92,sll=00:00:00:00:00:00,tll=f8:bc:12:44:34:b6)'])
>> +
>> +AT_CHECK([ovs-appctl tnl/arp/show | tail -n+3 | sort], [0], [dnl
>> +2001:cafe::92                                 f8:bc:12:44:34:b6   br0
>> +])
>> +
>> +AT_CHECK([ovs-appctl tnl/ports/show |sort], [0], [dnl
>> +Listening ports:
>> +ip6gretap_sys (6) ref_cnt=1
>> +])
>> +
>> +dnl Check IPv6 GRE tunnel pop
>> +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x86dd),ipv6(src=2001:cafe::92,dst=2001:cafe::88,label=0,proto=47,tclass=0x0,hlimit=64)'], [0], [stdout])
>> +AT_CHECK([tail -1 stdout], [0],
>> +  [Datapath actions: tnl_pop(6)
>> +])
>> +
>> +dnl Check IPv6 GRE tunnel push
>> +AT_CHECK([ovs-ofctl add-flow int-br action=2])
>> +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:01),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout])
>> +
>> +AT_CHECK([tail -1 stdout], [0],
>> +  [Datapath actions: clone(tnl_push(tnl_port(6),header(size=58,type=109,eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:00,dl_type=0x86dd),ipv6(src=2001:cafe::88,dst=2001:cafe::92,label=0,proto=47,tclass=0x0,hlimit=64),gre((flags=0x0,proto=0x6558))),out_port(100)),1)
>> +])
>> +
>> +OVS_VSWITCHD_STOP
>> +AT_CLEANUP
>> +
>>    AT_SETUP([tunnel_push_pop_ipv6 - ip6erspan])
>>    
>>    OVS_VSWITCHD_START([add-port br0 p0 -- set Interface p0 type=dummy ofport_request=1 other-config:hwaddr=aa:55:aa:55:00:00])
> Works for me. Thanks!
>
> However, do we want to keep a separate configuration for IPv6 GRE vs
> IPv4 GRE? if so, some more documentation should be adapted, for example
> vswitchd/vswitch.xml make "gre" for IPv4 and not IPv4/IPv6, and more
> places add ip6gretap as a legitimate tunnel.

I'll be working on clarifying the documentation.  And we need to clarify 
that we will not be supporting ip6gre because it
requires ARPHRD_IP6GRE.  OVS only works with ARPHRD_ETHER so it can only 
support ip6gretap.

>
> Alternatively, we can maybe detect the options:remote_ip to be an
> IPv4/IPv6 address in type=gre and do the proper adjustments behind the
> scenes.
>
> What do you think?
>

Would take user space changes.  I'd be fine with it - I think it would 
work more like geneve and vxlan that way.

- Greg
William Tu June 20, 2019, 6:19 p.m. UTC | #3
> I'll be working on clarifying the documentation.  And we need to clarify
> that we will not be supporting ip6gre because it
> requires ARPHRD_IP6GRE.  OVS only works with ARPHRD_ETHER so it can only
> support ip6gretap.
>
> >
> > Alternatively, we can maybe detect the options:remote_ip to be an
> > IPv4/IPv6 address in type=gre and do the proper adjustments behind the
> > scenes.
> >
> > What do you think?

But when users set type=gre, and underneath we might created gre or ip6gretap.
I think it better makes it clear using ip6gretap or gre.
>
>
>
> Would take user space changes.  I'd be fine with it - I think it would
> work more like geneve and vxlan that way.
>
For geneve and vxlan (see drivers/net/geneve.c), it uses only one type
rtnl_link_ops.kind ="geneve" for handling both ipv6 and ipv4.

But for gre/erspan, there are separate rtnl_link_ops.kind in
net/ipv4/ip_gre.c and net/ipv6/ip6_gre.c
So I think we have to do separate type=ip6gre or type=gre.

Regards,
William


> - Greg
Eli Britstein June 20, 2019, 7:23 p.m. UTC | #4
On 6/20/2019 9:19 PM, William Tu wrote:
>> I'll be working on clarifying the documentation.  And we need to clarify
>> that we will not be supporting ip6gre because it
>> requires ARPHRD_IP6GRE.  OVS only works with ARPHRD_ETHER so it can only
>> support ip6gretap.
>>
>>> Alternatively, we can maybe detect the options:remote_ip to be an
>>> IPv4/IPv6 address in type=gre and do the proper adjustments behind the
>>> scenes.
>>>
>>> What do you think?
> But when users set type=gre, and underneath we might created gre or ip6gretap.
> I think it better makes it clear using ip6gretap or gre.

In gre we use "gre" for both "gre" or "gretap", so we should maybe use 
"ip6gre" and not "ip6gretap", though "ip6gre" is not supported but only 
"ip6gretap". BTW, can't OVS be updated to support it as well in the future?

In any case, I think documentation should be updated in the same commit.

>>
>>
>> Would take user space changes.  I'd be fine with it - I think it would
>> work more like geneve and vxlan that way.
>>
> For geneve and vxlan (see drivers/net/geneve.c), it uses only one type
> rtnl_link_ops.kind ="geneve" for handling both ipv6 and ipv4.
>
> But for gre/erspan, there are separate rtnl_link_ops.kind in
> net/ipv4/ip_gre.c and net/ipv6/ip6_gre.c
> So I think we have to do separate type=ip6gre or type=gre.
>
> Regards,
> William
>
>
>> - Greg
Gregory Rose June 21, 2019, 4:59 p.m. UTC | #5
On 6/20/2019 8:55 AM, William Tu wrote:
> The patch adds ip6gretap support. Tunnel type ip6gretap is a layer 2 GRE
> tunnel over IPv6, carrying inner ethernet packets and encap with GRE header
> with outer IPv6 header.  I tested it by running:
>    # make check-kernel
> under kernel 5.2 and for userspace:
>    # make check TESTSUITEFLAGS='-k ip6gretap'
>
> Signed-off-by: William Tu <u9012063@gmail.com>
> ---
> v1-v2: rebase to master

Thanks William, looks good for testing and documentation.

Tested-by: Greg Rose <gvrose8192@gmail.com>
Reviewed-by: Greg Rose <gvrose8192@gmail.com>

>
> ---
>   Documentation/faq/configuration.rst | 12 +++++++
>   NEWS                                |  1 +
>   datapath/linux/compat/ip6_gre.c     |  2 +-
>   lib/dpif-netlink-rtnl.c             |  2 +-
>   lib/dpif-netlink.c                  |  4 ++-
>   lib/netdev-vport.c                  |  4 +--
>   lib/tnl-ports.c                     |  3 +-
>   tests/system-traffic.at             | 40 ++++++++++++++++++++++
>   tests/tunnel-push-pop-ipv6.at       | 68 +++++++++++++++++++++++++++++++++++++
>   9 files changed, 130 insertions(+), 6 deletions(-)
>
> diff --git a/Documentation/faq/configuration.rst b/Documentation/faq/configuration.rst
> index cb2c6b4eca98..c9bcfa8a790d 100644
> --- a/Documentation/faq/configuration.rst
> +++ b/Documentation/faq/configuration.rst
> @@ -212,6 +212,18 @@ Q: Does Open vSwitch support ERSPAN?
>                   options:erspan_ver=2 options:erspan_dir=1 \
>                   options:erspan_hwid=4
>   
> +Q: Does Open vSwitch support IPv6 GRE?
> +
> +    A: Yes. L2 tunnel interface GRE over IPv6 is supported.
> +    L3 GRE tunnel over IPv6 is not supported.
> +
> +    ::
> +
> +        $ ovs-vsctl add-br br0
> +        $ ovs-vsctl add-port br0 at_gretap0 -- \
> +                set int at_gretap0 type=ip6gretap \
> +                options:remote_ip=fc00:100::1
> +
>   Q: How do I connect two bridges?
>   
>       A: First, why do you want to do this?  Two connected bridges are not much
> diff --git a/NEWS b/NEWS
> index a38ab258fc6c..c7e84ed7931d 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -47,6 +47,7 @@ Post-v2.11.0
>      - Linux datapath:
>        * Support for the kernel versions 4.19.x and 4.20.x.
>        * Support for the kernel version 5.0.x.
> +   - Add L2 GRE tunnel over IPv6 support.
>   
>   
>   v2.11.0 - 19 Feb 2019
> diff --git a/datapath/linux/compat/ip6_gre.c b/datapath/linux/compat/ip6_gre.c
> index ca4e66133570..ab50c72d0753 100644
> --- a/datapath/linux/compat/ip6_gre.c
> +++ b/datapath/linux/compat/ip6_gre.c
> @@ -2550,7 +2550,7 @@ static struct rtnl_link_ops ip6gre_link_ops __read_mostly = {
>   };
>   
>   static struct rtnl_link_ops ip6gre_tap_ops __read_mostly = {
> -	.kind		= "ip6gre",
> +	.kind		= "ip6gretap",
>   	.maxtype	= RPL_IFLA_GRE_MAX,
>   	.policy		= ip6gre_policy,
>   	.priv_size	= sizeof(struct ip6_tnl),
> diff --git a/lib/dpif-netlink-rtnl.c b/lib/dpif-netlink-rtnl.c
> index 2e23a8c14fcf..d666f239aeed 100644
> --- a/lib/dpif-netlink-rtnl.c
> +++ b/lib/dpif-netlink-rtnl.c
> @@ -104,7 +104,7 @@ vport_type_to_kind(enum ovs_vport_type type,
>       case OVS_VPORT_TYPE_IP6ERSPAN:
>           return "ip6erspan";
>       case OVS_VPORT_TYPE_IP6GRE:
> -        return "ip6gre";
> +        return "ip6gretap";
>       case OVS_VPORT_TYPE_NETDEV:
>       case OVS_VPORT_TYPE_INTERNAL:
>       case OVS_VPORT_TYPE_LISP:
> diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c
> index ba80a0079181..fc1d1591975e 100644
> --- a/lib/dpif-netlink.c
> +++ b/lib/dpif-netlink.c
> @@ -699,7 +699,7 @@ get_vport_type(const struct dpif_netlink_vport *vport)
>           return "ip6erspan";
>   
>       case OVS_VPORT_TYPE_IP6GRE:
> -        return "ip6gre";
> +        return "ip6gretap";
>   
>       case OVS_VPORT_TYPE_UNSPEC:
>       case __OVS_VPORT_TYPE_MAX:
> @@ -730,6 +730,8 @@ netdev_to_ovs_vport_type(const char *type)
>           return OVS_VPORT_TYPE_ERSPAN;
>       } else if (!strcmp(type, "ip6erspan")) {
>           return OVS_VPORT_TYPE_IP6ERSPAN;
> +    } else if (!strcmp(type, "ip6gretap")) {
> +        return OVS_VPORT_TYPE_IP6GRE;
>       } else if (!strcmp(type, "ip6gre")) {
>           return OVS_VPORT_TYPE_IP6GRE;
>       } else if (!strcmp(type, "gre")) {
> diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
> index 92a256af16ed..5a20415529eb 100644
> --- a/lib/netdev-vport.c
> +++ b/lib/netdev-vport.c
> @@ -1212,10 +1212,10 @@ netdev_vport_tunnel_register(void)
>             },
>             {{NULL, NULL, 0, 0}}
>           },
> -        { "ip6gre_sys",
> +        { "ip6gretap_sys",
>             {
>                 TUNNEL_FUNCTIONS_COMMON,
> -              .type = "ip6gre",
> +              .type = "ip6gretap",
>                 .build_header = netdev_gre_build_header,
>                 .push_header = netdev_gre_push_header,
>                 .pop_header = netdev_gre_pop_header
> diff --git a/lib/tnl-ports.c b/lib/tnl-ports.c
> index 17353046cc6e..62065c0027cd 100644
> --- a/lib/tnl-ports.c
> +++ b/lib/tnl-ports.c
> @@ -172,7 +172,8 @@ tnl_type_to_nw_proto(const char type[])
>           return IPPROTO_TCP;
>       }
>       if (!strcmp(type, "gre") || !strcmp(type, "erspan") ||
> -        !strcmp(type, "ip6erspan") || !strcmp(type, "ip6gre")) {
> +        !strcmp(type, "ip6erspan") || !strcmp(type, "ip6gre") ||
> +        !strcmp(type, "ip6gretap")) {
>           return IPPROTO_GRE;
>       }
>       if (!strcmp(type, "vxlan")) {
> diff --git a/tests/system-traffic.at b/tests/system-traffic.at
> index d23ee897b0b2..43056733794a 100644
> --- a/tests/system-traffic.at
> +++ b/tests/system-traffic.at
> @@ -340,6 +340,46 @@ NS_CHECK_EXEC([at_ns0], [ping -s 3200 -q -c 3 -i 0.3 -w 2 10.1.1.100 | FORMAT_PI
>   OVS_TRAFFIC_VSWITCHD_STOP
>   AT_CLEANUP
>   
> +AT_SETUP([datapath - ping over ip6gretap tunnel])
> +OVS_CHECK_KERNEL_EXCL(3, 10, 4, 15)
> +OVS_CHECK_GRE()
> +OVS_CHECK_ERSPAN()
> +
> +OVS_TRAFFIC_VSWITCHD_START()
> +ADD_BR([br-underlay])
> +
> +AT_CHECK([ovs-ofctl add-flow br0 "actions=normal"])
> +AT_CHECK([ovs-ofctl add-flow br-underlay "actions=normal"])
> +
> +ADD_NAMESPACES(at_ns0)
> +
> +dnl Set up underlay link from host into the namespace using veth pair.
> +ADD_VETH(p0, at_ns0, br-underlay, "fc00:100::1/96", [], [], nodad)
> +AT_CHECK([ip addr add dev br-underlay "fc00:100::100/96" nodad])
> +AT_CHECK([ip link set dev br-underlay up])
> +
> +dnl Set up tunnel endpoints on OVS outside the namespace and with a native
> +dnl linux device inside the namespace.
> +ADD_OVS_TUNNEL6([ip6gretap], [br0], [at_gretap0], [fc00:100::1], [10.1.1.100/24],
> +                [])
> +ADD_NATIVE_TUNNEL6([ip6gretap], [ns_gretap0], [at_ns0], [fc00:100::100],
> +                   [10.1.1.1/24], [local fc00:100::1])
> +
> +OVS_WAIT_UNTIL([ip netns exec at_ns0 ping6 -c 2 fc00:100::100])
> +
> +dnl First, check the underlay
> +NS_CHECK_EXEC([at_ns0], [ping6 -q -c 3 -i 0.3 -w 2 fc00:100::100 | FORMAT_PING], [0], [dnl
> +3 packets transmitted, 3 received, 0% packet loss, time 0ms
> +])
> +
> +dnl Okay, now check the overlay with different packet sizes
> +NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -w 2 10.1.1.100 | FORMAT_PING], [0], [dnl
> +3 packets transmitted, 3 received, 0% packet loss, time 0ms
> +])
> +OVS_TRAFFIC_VSWITCHD_STOP
> +AT_CLEANUP
> +
> +
>   AT_SETUP([datapath - ping over erspan v1 tunnel])
>   OVS_CHECK_KERNEL_EXCL(3, 10, 4, 15)
>   OVS_CHECK_GRE()
> diff --git a/tests/tunnel-push-pop-ipv6.at b/tests/tunnel-push-pop-ipv6.at
> index cbdd5a32f719..07dd6ab504a0 100644
> --- a/tests/tunnel-push-pop-ipv6.at
> +++ b/tests/tunnel-push-pop-ipv6.at
> @@ -1,5 +1,73 @@
>   AT_BANNER([tunnel_push_pop_ipv6])
>   
> +AT_SETUP([tunnel_push_pop_ipv6 - ip6gretap])
> +
> +OVS_VSWITCHD_START([add-port br0 p0 -- set Interface p0 type=dummy ofport_request=1 other-config:hwaddr=aa:55:aa:55:00:00])
> +AT_CHECK([ovs-vsctl add-br int-br -- set bridge int-br datapath_type=dummy], [0])
> +AT_CHECK([ovs-vsctl add-port int-br t2 -- set Interface t2 type=ip6gretap \
> +                       options:remote_ip=2001:cafe::92 ofport_request=2\
> +                       ], [0])
> +
> +AT_CHECK([ovs-appctl dpif/show], [0], [dnl
> +dummy@ovs-dummy: hit:0 missed:0
> +  br0:
> +    br0 65534/100: (dummy-internal)
> +    p0 1/1: (dummy)
> +  int-br:
> +    int-br 65534/2: (dummy-internal)
> +    t2 2/6: (ip6gretap: remote_ip=2001:cafe::92)
> +])
> +
> +dnl First setup dummy interface IP address, then add the route
> +dnl so that tnl-port table can get valid IP address for the device.
> +AT_CHECK([ovs-appctl netdev-dummy/ip6addr br0 2001:cafe::88/24], [0], [OK
> +])
> +AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 1.1.2.88/24], [0], [OK
> +])
> +AT_CHECK([ovs-appctl ovs/route/add 2001:cafe::92/24 br0], [0], [OK
> +])
> +
> +AT_CHECK([ovs-ofctl add-flow br0 action=normal])
> +
> +dnl Check Neighbour discovery.
> +AT_CHECK([ovs-vsctl -- set Interface p0 options:pcap=p0.pcap])
> +
> +AT_CHECK([ovs-appctl netdev-dummy/receive int-br 'in_port(2),eth(src=aa:55:aa:55:00:00,dst=f8:bc:12:ff:ff:ff),eth_type(0x0800),ipv4(src=1.1.3.92,dst=1.1.3.88,proto=1,tos=0,ttl=64,frag=no),icmp(type=0,code=0)'])
> +AT_CHECK([ovs-pcap p0.pcap > p0.pcap.txt 2>&1])
> +
> +AT_CHECK([cat p0.pcap.txt | grep 92aa55aa55000086dd6000000000203aff2001cafe | uniq], [0], [dnl
> +3333ff000092aa55aa55000086dd6000000000203aff2001cafe000000000000000000000088ff0200000000000000000001ff00009287004d48000000002001cafe0000000000000000000000920101aa55aa550000
> +])
> +
> +dnl
> +AT_CHECK([ovs-appctl netdev-dummy/receive p0 'in_port(1),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x86dd),ipv6(src=2001:cafe::92,dst=2001:cafe::88,label=0,proto=58,tclass=0,hlimit=255,frag=no),icmpv6(type=136,code=0),nd(target=2001:cafe::92,sll=00:00:00:00:00:00,tll=f8:bc:12:44:34:b6)'])
> +
> +AT_CHECK([ovs-appctl tnl/arp/show | tail -n+3 | sort], [0], [dnl
> +2001:cafe::92                                 f8:bc:12:44:34:b6   br0
> +])
> +
> +AT_CHECK([ovs-appctl tnl/ports/show |sort], [0], [dnl
> +Listening ports:
> +ip6gretap_sys (6) ref_cnt=1
> +])
> +
> +dnl Check IPv6 GRE tunnel pop
> +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x86dd),ipv6(src=2001:cafe::92,dst=2001:cafe::88,label=0,proto=47,tclass=0x0,hlimit=64)'], [0], [stdout])
> +AT_CHECK([tail -1 stdout], [0],
> +  [Datapath actions: tnl_pop(6)
> +])
> +
> +dnl Check IPv6 GRE tunnel push
> +AT_CHECK([ovs-ofctl add-flow int-br action=2])
> +AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:01),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout])
> +
> +AT_CHECK([tail -1 stdout], [0],
> +  [Datapath actions: clone(tnl_push(tnl_port(6),header(size=58,type=109,eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:00,dl_type=0x86dd),ipv6(src=2001:cafe::88,dst=2001:cafe::92,label=0,proto=47,tclass=0x0,hlimit=64),gre((flags=0x0,proto=0x6558))),out_port(100)),1)
> +])
> +
> +OVS_VSWITCHD_STOP
> +AT_CLEANUP
> +
>   AT_SETUP([tunnel_push_pop_ipv6 - ip6erspan])
>   
>   OVS_VSWITCHD_START([add-port br0 p0 -- set Interface p0 type=dummy ofport_request=1 other-config:hwaddr=aa:55:aa:55:00:00])
William Tu June 21, 2019, 5:22 p.m. UTC | #6
On Thu, Jun 20, 2019 at 12:23 PM Eli Britstein <elibr@mellanox.com> wrote:
>
>
> On 6/20/2019 9:19 PM, William Tu wrote:
> >> I'll be working on clarifying the documentation.  And we need to clarify
> >> that we will not be supporting ip6gre because it
> >> requires ARPHRD_IP6GRE.  OVS only works with ARPHRD_ETHER so it can only
> >> support ip6gretap.
> >>
> >>> Alternatively, we can maybe detect the options:remote_ip to be an
> >>> IPv4/IPv6 address in type=gre and do the proper adjustments behind the
> >>> scenes.
> >>>
> >>> What do you think?
> > But when users set type=gre, and underneath we might created gre or ip6gretap.
> > I think it better makes it clear using ip6gretap or gre.
>
> In gre we use "gre" for both "gre" or "gretap", so we should maybe use
> "ip6gre" and not "ip6gretap", though "ip6gre" is not supported but only
> "ip6gretap". BTW, can't OVS be updated to support it as well in the future?

Yes, we can do that.
First we need to upstream to netdev to add ARPHRD_IP6GRE support
in ovs_netdev_link() at net/openvswitch/vport-netdev.c. Then we backport
to OVS compat kernel module.

For this patch, let's fix the ip6gretap first.
>
> In any case, I think documentation should be updated in the same commit.
>
Agree, I will update the vswitchd/vswitch.xml in next version

Thanks!
William
William Tu June 21, 2019, 5:25 p.m. UTC | #7
On Fri, Jun 21, 2019 at 10:00 AM Gregory Rose <gvrose8192@gmail.com> wrote:
>
>
> On 6/20/2019 8:55 AM, William Tu wrote:
> > The patch adds ip6gretap support. Tunnel type ip6gretap is a layer 2 GRE
> > tunnel over IPv6, carrying inner ethernet packets and encap with GRE header
> > with outer IPv6 header.  I tested it by running:
> >    # make check-kernel
> > under kernel 5.2 and for userspace:
> >    # make check TESTSUITEFLAGS='-k ip6gretap'
> >
> > Signed-off-by: William Tu <u9012063@gmail.com>
> > ---
> > v1-v2: rebase to master
>
> Thanks William, looks good for testing and documentation.
>
> Tested-by: Greg Rose <gvrose8192@gmail.com>
> Reviewed-by: Greg Rose <gvrose8192@gmail.com>

Thanks Greg,
I will send out v3 adding more Documentation suggested by Eli
and carry over these two tags.

William
Gregory Rose June 21, 2019, 5:26 p.m. UTC | #8
On 6/21/2019 10:25 AM, William Tu wrote:
> On Fri, Jun 21, 2019 at 10:00 AM Gregory Rose <gvrose8192@gmail.com> wrote:
>>
>> On 6/20/2019 8:55 AM, William Tu wrote:
>>> The patch adds ip6gretap support. Tunnel type ip6gretap is a layer 2 GRE
>>> tunnel over IPv6, carrying inner ethernet packets and encap with GRE header
>>> with outer IPv6 header.  I tested it by running:
>>>     # make check-kernel
>>> under kernel 5.2 and for userspace:
>>>     # make check TESTSUITEFLAGS='-k ip6gretap'
>>>
>>> Signed-off-by: William Tu <u9012063@gmail.com>
>>> ---
>>> v1-v2: rebase to master
>> Thanks William, looks good for testing and documentation.
>>
>> Tested-by: Greg Rose <gvrose8192@gmail.com>
>> Reviewed-by: Greg Rose <gvrose8192@gmail.com>
> Thanks Greg,
> I will send out v3 adding more Documentation suggested by Eli
> and carry over these two tags.

Sounds good, I forgot about vswitchd.xml.

Thanks!

>
> William
diff mbox series

Patch

diff --git a/Documentation/faq/configuration.rst b/Documentation/faq/configuration.rst
index cb2c6b4eca98..c9bcfa8a790d 100644
--- a/Documentation/faq/configuration.rst
+++ b/Documentation/faq/configuration.rst
@@ -212,6 +212,18 @@  Q: Does Open vSwitch support ERSPAN?
                 options:erspan_ver=2 options:erspan_dir=1 \
                 options:erspan_hwid=4
 
+Q: Does Open vSwitch support IPv6 GRE?
+
+    A: Yes. L2 tunnel interface GRE over IPv6 is supported.
+    L3 GRE tunnel over IPv6 is not supported.
+
+    ::
+
+        $ ovs-vsctl add-br br0
+        $ ovs-vsctl add-port br0 at_gretap0 -- \
+                set int at_gretap0 type=ip6gretap \
+                options:remote_ip=fc00:100::1
+
 Q: How do I connect two bridges?
 
     A: First, why do you want to do this?  Two connected bridges are not much
diff --git a/NEWS b/NEWS
index a38ab258fc6c..c7e84ed7931d 100644
--- a/NEWS
+++ b/NEWS
@@ -47,6 +47,7 @@  Post-v2.11.0
    - Linux datapath:
      * Support for the kernel versions 4.19.x and 4.20.x.
      * Support for the kernel version 5.0.x.
+   - Add L2 GRE tunnel over IPv6 support.
 
 
 v2.11.0 - 19 Feb 2019
diff --git a/datapath/linux/compat/ip6_gre.c b/datapath/linux/compat/ip6_gre.c
index ca4e66133570..ab50c72d0753 100644
--- a/datapath/linux/compat/ip6_gre.c
+++ b/datapath/linux/compat/ip6_gre.c
@@ -2550,7 +2550,7 @@  static struct rtnl_link_ops ip6gre_link_ops __read_mostly = {
 };
 
 static struct rtnl_link_ops ip6gre_tap_ops __read_mostly = {
-	.kind		= "ip6gre",
+	.kind		= "ip6gretap",
 	.maxtype	= RPL_IFLA_GRE_MAX,
 	.policy		= ip6gre_policy,
 	.priv_size	= sizeof(struct ip6_tnl),
diff --git a/lib/dpif-netlink-rtnl.c b/lib/dpif-netlink-rtnl.c
index 2e23a8c14fcf..d666f239aeed 100644
--- a/lib/dpif-netlink-rtnl.c
+++ b/lib/dpif-netlink-rtnl.c
@@ -104,7 +104,7 @@  vport_type_to_kind(enum ovs_vport_type type,
     case OVS_VPORT_TYPE_IP6ERSPAN:
         return "ip6erspan";
     case OVS_VPORT_TYPE_IP6GRE:
-        return "ip6gre";
+        return "ip6gretap";
     case OVS_VPORT_TYPE_NETDEV:
     case OVS_VPORT_TYPE_INTERNAL:
     case OVS_VPORT_TYPE_LISP:
diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c
index ba80a0079181..fc1d1591975e 100644
--- a/lib/dpif-netlink.c
+++ b/lib/dpif-netlink.c
@@ -699,7 +699,7 @@  get_vport_type(const struct dpif_netlink_vport *vport)
         return "ip6erspan"; 
 
     case OVS_VPORT_TYPE_IP6GRE:
-        return "ip6gre";
+        return "ip6gretap";
 
     case OVS_VPORT_TYPE_UNSPEC:
     case __OVS_VPORT_TYPE_MAX:
@@ -730,6 +730,8 @@  netdev_to_ovs_vport_type(const char *type)
         return OVS_VPORT_TYPE_ERSPAN;
     } else if (!strcmp(type, "ip6erspan")) {
         return OVS_VPORT_TYPE_IP6ERSPAN;
+    } else if (!strcmp(type, "ip6gretap")) {
+        return OVS_VPORT_TYPE_IP6GRE;
     } else if (!strcmp(type, "ip6gre")) {
         return OVS_VPORT_TYPE_IP6GRE;
     } else if (!strcmp(type, "gre")) {
diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
index 92a256af16ed..5a20415529eb 100644
--- a/lib/netdev-vport.c
+++ b/lib/netdev-vport.c
@@ -1212,10 +1212,10 @@  netdev_vport_tunnel_register(void)
           },
           {{NULL, NULL, 0, 0}}
         },
-        { "ip6gre_sys",
+        { "ip6gretap_sys",
           {
               TUNNEL_FUNCTIONS_COMMON,
-              .type = "ip6gre",
+              .type = "ip6gretap",
               .build_header = netdev_gre_build_header,
               .push_header = netdev_gre_push_header,
               .pop_header = netdev_gre_pop_header
diff --git a/lib/tnl-ports.c b/lib/tnl-ports.c
index 17353046cc6e..62065c0027cd 100644
--- a/lib/tnl-ports.c
+++ b/lib/tnl-ports.c
@@ -172,7 +172,8 @@  tnl_type_to_nw_proto(const char type[])
         return IPPROTO_TCP;
     }
     if (!strcmp(type, "gre") || !strcmp(type, "erspan") ||
-        !strcmp(type, "ip6erspan") || !strcmp(type, "ip6gre")) {
+        !strcmp(type, "ip6erspan") || !strcmp(type, "ip6gre") ||
+        !strcmp(type, "ip6gretap")) {
         return IPPROTO_GRE;
     }
     if (!strcmp(type, "vxlan")) {
diff --git a/tests/system-traffic.at b/tests/system-traffic.at
index d23ee897b0b2..43056733794a 100644
--- a/tests/system-traffic.at
+++ b/tests/system-traffic.at
@@ -340,6 +340,46 @@  NS_CHECK_EXEC([at_ns0], [ping -s 3200 -q -c 3 -i 0.3 -w 2 10.1.1.100 | FORMAT_PI
 OVS_TRAFFIC_VSWITCHD_STOP
 AT_CLEANUP
 
+AT_SETUP([datapath - ping over ip6gretap tunnel])
+OVS_CHECK_KERNEL_EXCL(3, 10, 4, 15)
+OVS_CHECK_GRE()
+OVS_CHECK_ERSPAN()
+
+OVS_TRAFFIC_VSWITCHD_START()
+ADD_BR([br-underlay])
+
+AT_CHECK([ovs-ofctl add-flow br0 "actions=normal"])
+AT_CHECK([ovs-ofctl add-flow br-underlay "actions=normal"])
+
+ADD_NAMESPACES(at_ns0)
+
+dnl Set up underlay link from host into the namespace using veth pair.
+ADD_VETH(p0, at_ns0, br-underlay, "fc00:100::1/96", [], [], nodad)
+AT_CHECK([ip addr add dev br-underlay "fc00:100::100/96" nodad])
+AT_CHECK([ip link set dev br-underlay up])
+
+dnl Set up tunnel endpoints on OVS outside the namespace and with a native
+dnl linux device inside the namespace.
+ADD_OVS_TUNNEL6([ip6gretap], [br0], [at_gretap0], [fc00:100::1], [10.1.1.100/24],
+                [])
+ADD_NATIVE_TUNNEL6([ip6gretap], [ns_gretap0], [at_ns0], [fc00:100::100],
+                   [10.1.1.1/24], [local fc00:100::1])
+
+OVS_WAIT_UNTIL([ip netns exec at_ns0 ping6 -c 2 fc00:100::100])
+
+dnl First, check the underlay
+NS_CHECK_EXEC([at_ns0], [ping6 -q -c 3 -i 0.3 -w 2 fc00:100::100 | FORMAT_PING], [0], [dnl
+3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+
+dnl Okay, now check the overlay with different packet sizes
+NS_CHECK_EXEC([at_ns0], [ping -q -c 3 -i 0.3 -w 2 10.1.1.100 | FORMAT_PING], [0], [dnl
+3 packets transmitted, 3 received, 0% packet loss, time 0ms
+])
+OVS_TRAFFIC_VSWITCHD_STOP
+AT_CLEANUP
+
+
 AT_SETUP([datapath - ping over erspan v1 tunnel])
 OVS_CHECK_KERNEL_EXCL(3, 10, 4, 15)
 OVS_CHECK_GRE()
diff --git a/tests/tunnel-push-pop-ipv6.at b/tests/tunnel-push-pop-ipv6.at
index cbdd5a32f719..07dd6ab504a0 100644
--- a/tests/tunnel-push-pop-ipv6.at
+++ b/tests/tunnel-push-pop-ipv6.at
@@ -1,5 +1,73 @@ 
 AT_BANNER([tunnel_push_pop_ipv6])
 
+AT_SETUP([tunnel_push_pop_ipv6 - ip6gretap])
+
+OVS_VSWITCHD_START([add-port br0 p0 -- set Interface p0 type=dummy ofport_request=1 other-config:hwaddr=aa:55:aa:55:00:00])
+AT_CHECK([ovs-vsctl add-br int-br -- set bridge int-br datapath_type=dummy], [0])
+AT_CHECK([ovs-vsctl add-port int-br t2 -- set Interface t2 type=ip6gretap \
+                       options:remote_ip=2001:cafe::92 ofport_request=2\
+                       ], [0])
+
+AT_CHECK([ovs-appctl dpif/show], [0], [dnl
+dummy@ovs-dummy: hit:0 missed:0
+  br0:
+    br0 65534/100: (dummy-internal)
+    p0 1/1: (dummy)
+  int-br:
+    int-br 65534/2: (dummy-internal)
+    t2 2/6: (ip6gretap: remote_ip=2001:cafe::92)
+])
+
+dnl First setup dummy interface IP address, then add the route
+dnl so that tnl-port table can get valid IP address for the device.
+AT_CHECK([ovs-appctl netdev-dummy/ip6addr br0 2001:cafe::88/24], [0], [OK
+])
+AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 1.1.2.88/24], [0], [OK
+])
+AT_CHECK([ovs-appctl ovs/route/add 2001:cafe::92/24 br0], [0], [OK
+])
+
+AT_CHECK([ovs-ofctl add-flow br0 action=normal])
+
+dnl Check Neighbour discovery.
+AT_CHECK([ovs-vsctl -- set Interface p0 options:pcap=p0.pcap])
+
+AT_CHECK([ovs-appctl netdev-dummy/receive int-br 'in_port(2),eth(src=aa:55:aa:55:00:00,dst=f8:bc:12:ff:ff:ff),eth_type(0x0800),ipv4(src=1.1.3.92,dst=1.1.3.88,proto=1,tos=0,ttl=64,frag=no),icmp(type=0,code=0)'])
+AT_CHECK([ovs-pcap p0.pcap > p0.pcap.txt 2>&1])
+
+AT_CHECK([cat p0.pcap.txt | grep 92aa55aa55000086dd6000000000203aff2001cafe | uniq], [0], [dnl
+3333ff000092aa55aa55000086dd6000000000203aff2001cafe000000000000000000000088ff0200000000000000000001ff00009287004d48000000002001cafe0000000000000000000000920101aa55aa550000
+])
+
+dnl
+AT_CHECK([ovs-appctl netdev-dummy/receive p0 'in_port(1),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x86dd),ipv6(src=2001:cafe::92,dst=2001:cafe::88,label=0,proto=58,tclass=0,hlimit=255,frag=no),icmpv6(type=136,code=0),nd(target=2001:cafe::92,sll=00:00:00:00:00:00,tll=f8:bc:12:44:34:b6)'])
+
+AT_CHECK([ovs-appctl tnl/arp/show | tail -n+3 | sort], [0], [dnl
+2001:cafe::92                                 f8:bc:12:44:34:b6   br0
+])
+
+AT_CHECK([ovs-appctl tnl/ports/show |sort], [0], [dnl
+Listening ports:
+ip6gretap_sys (6) ref_cnt=1
+])
+
+dnl Check IPv6 GRE tunnel pop
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:00),eth_type(0x86dd),ipv6(src=2001:cafe::92,dst=2001:cafe::88,label=0,proto=47,tclass=0x0,hlimit=64)'], [0], [stdout])
+AT_CHECK([tail -1 stdout], [0],
+  [Datapath actions: tnl_pop(6)
+])
+
+dnl Check IPv6 GRE tunnel push
+AT_CHECK([ovs-ofctl add-flow int-br action=2])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(2),eth(src=f8:bc:12:44:34:b6,dst=aa:55:aa:55:00:01),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=47,tos=0,ttl=64,frag=no)'], [0], [stdout])
+
+AT_CHECK([tail -1 stdout], [0],
+  [Datapath actions: clone(tnl_push(tnl_port(6),header(size=58,type=109,eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:00,dl_type=0x86dd),ipv6(src=2001:cafe::88,dst=2001:cafe::92,label=0,proto=47,tclass=0x0,hlimit=64),gre((flags=0x0,proto=0x6558))),out_port(100)),1)
+])
+
+OVS_VSWITCHD_STOP
+AT_CLEANUP
+
 AT_SETUP([tunnel_push_pop_ipv6 - ip6erspan])
 
 OVS_VSWITCHD_START([add-port br0 p0 -- set Interface p0 type=dummy ofport_request=1 other-config:hwaddr=aa:55:aa:55:00:00])