[ovs-dev] [PATCH v7 3/3] userspace: add vxlan gpe support to vport

Zoltán Balogh zoltan.balogh at ericsson.com
Fri May 26 08:46:16 UTC 2017


Hi,

Please have a look at v8:
https://mail.openvswitch.org/pipermail/ovs-dev/2017-May/332898.html

Best regards,
Zoltan


> -----Original Message-----
> From: ovs-dev-bounces at openvswitch.org [mailto:ovs-dev-bounces at openvswitch.org] On Behalf Of Zoltán Balogh
> Sent: Thursday, May 25, 2017 5:38 PM
> To: 'dev at openvswitch.org' <dev at openvswitch.org>
> Subject: [ovs-dev] [PATCH v7 3/3] userspace: add vxlan gpe support to vport
> 
> From: Georg Schmuecking <georg.schmuecking at ericsson.com>
> 
> This patch is based on the "datapath: enable vxlangpe creation in compat mode"
> from Yi Yang. It introduces an extension option "gpe" to the vxlan port in the
> netdev-dpdk datapath. Description of vxlan gpe protocoll was added to header
> file lib/packets.h. In the vxlan specific methods the different packet are
> introduced and handled.
> 
> Added VXLAN GPE tunnel push test.
> 
> Signed-off-by: Yi Yang <yi.y.yang at intel.com>
> Signed-off-by: Georg Schmuecking <georg.schmuecking at ericsson.com>
> ---
>  datapath/linux/compat/include/linux/openvswitch.h |  1 +
>  include/openvswitch/automake.mk                   |  1 -
>  lib/netdev-native-tnl.c                           | 59 +++++++++++++++++++++--
>  lib/netdev-vport.c                                | 22 +++++++--
>  lib/packets.h                                     | 54 ++++++++++++++++++++-
>  tests/tunnel-push-pop.at                          | 10 ++++
>  6 files changed, 135 insertions(+), 12 deletions(-)
> 
> diff --git a/datapath/linux/compat/include/linux/openvswitch.h b/datapath/linux/compat/include/linux/openvswitch.h
> index 7990638..2ae1797 100644
> --- a/datapath/linux/compat/include/linux/openvswitch.h
> +++ b/datapath/linux/compat/include/linux/openvswitch.h
> @@ -291,6 +291,7 @@ enum ovs_vport_attr {
>  enum {
>  	OVS_VXLAN_EXT_UNSPEC,
>  	OVS_VXLAN_EXT_GBP,      /* Flag or __u32 */
> +	OVS_VXLAN_EXT_GPE = 8,  /* Flag or __u32 */
>  	__OVS_VXLAN_EXT_MAX,
>  };
> 
> diff --git a/include/openvswitch/automake.mk b/include/openvswitch/automake.mk
> index c0e276f..699d9d7 100644
> --- a/include/openvswitch/automake.mk
> +++ b/include/openvswitch/automake.mk
> @@ -30,4 +30,3 @@ openvswitchinclude_HEADERS = \
>  	include/openvswitch/version.h \
>  	include/openvswitch/vconn.h \
>  	include/openvswitch/vlog.h
> -
> diff --git a/lib/netdev-native-tnl.c b/lib/netdev-native-tnl.c
> index 0651322..8ae8893 100644
> --- a/lib/netdev-native-tnl.c
> +++ b/lib/netdev-native-tnl.c
> @@ -499,6 +499,8 @@ netdev_vxlan_pop_header(struct dp_packet *packet)
>      struct flow_tnl *tnl = &md->tunnel;
>      struct vxlanhdr *vxh;
>      unsigned int hlen;
> +    ovs_be32 vx_flags;
> +    enum packet_type next_pt = PT_ETH;
> 
>      pkt_metadata_init_tnl(md);
>      if (VXLAN_HLEN > dp_packet_l4_size(packet)) {
> @@ -510,18 +512,43 @@ netdev_vxlan_pop_header(struct dp_packet *packet)
>          goto err;
>      }
> 
> -    if (get_16aligned_be32(&vxh->vx_flags) != htonl(VXLAN_FLAGS) ||
> +    vx_flags = get_16aligned_be32(&vxh->vx_flags);
> +    if (vx_flags & htonl(VXLAN_HF_GPE)) {
> +        vx_flags &= htonl(~VXLAN_GPE_USED_BITS);
> +        /* Drop the OAM packets */
> +        if (vxh->vx_pge.flags & VXLAN_GPE_FLAGS_O) {
> +            goto err;
> +        }
> +        switch (vxh->vx_pge.next_protocol) {
> +        case VXLAN_GPE_NP_IPV4:
> +            next_pt = PT_IPV4;
> +            break;
> +        case VXLAN_GPE_NP_IPV6:
> +            next_pt = PT_IPV6;
> +            break;
> +        case VXLAN_GPE_NP_ETHERNET:
> +            next_pt = PT_ETH;
> +            break;
> +        default:
> +            goto err;
> +        }
> +    }
> +
> +    if (vx_flags != htonl(VXLAN_FLAGS) ||
>         (get_16aligned_be32(&vxh->vx_vni) & htonl(0xff))) {
>          VLOG_WARN_RL(&err_rl, "invalid vxlan flags=%#x vni=%#x\n",
> -                     ntohl(get_16aligned_be32(&vxh->vx_flags)),
> +                     ntohl(vx_flags),
>                       ntohl(get_16aligned_be32(&vxh->vx_vni)));
>          goto err;
>      }
>      tnl->tun_id = htonll(ntohl(get_16aligned_be32(&vxh->vx_vni)) >> 8);
>      tnl->flags |= FLOW_TNL_F_KEY;
> 
> -    packet->packet_type = htonl(PT_ETH);
> +    packet->packet_type = htonl(next_pt);
>      dp_packet_reset_packet(packet, hlen + VXLAN_HLEN);
> +    if (next_pt != PT_ETH) {
> +        packet->l3_ofs = 0;
> +    }
> 
>      return packet;
>  err:
> @@ -544,8 +571,30 @@ netdev_vxlan_build_header(const struct netdev *netdev,
> 
>      vxh = udp_build_header(tnl_cfg, data, params);
> 
> -    put_16aligned_be32(&vxh->vx_flags, htonl(VXLAN_FLAGS));
> -    put_16aligned_be32(&vxh->vx_vni, htonl(ntohll(params->flow->tunnel.tun_id) << 8));
> +    if (tnl_cfg->exts & (1 << OVS_VXLAN_EXT_GPE)) {
> +        put_16aligned_be32(&vxh->vx_flags, htonl(VXLAN_FLAGS | VXLAN_HF_GPE));
> +        put_16aligned_be32(&vxh->vx_vni,
> +                           htonl(ntohll(params->flow->tunnel.tun_id) << 8));
> +        if (tnl_cfg->is_layer3) {
> +            switch (ntohs(params->flow->dl_type)) {
> +            case ETH_TYPE_IP:
> +                vxh->vx_pge.next_protocol = VXLAN_GPE_NP_IPV4;
> +                break;
> +            case ETH_TYPE_IPV6:
> +                vxh->vx_pge.next_protocol = VXLAN_GPE_NP_IPV6;
> +                break;
> +            case ETH_TYPE_TEB:
> +                vxh->vx_pge.next_protocol = VXLAN_GPE_NP_ETHERNET;
> +                break;
> +            }
> +        } else {
> +            vxh->vx_pge.next_protocol = VXLAN_GPE_NP_ETHERNET;
> +        }
> +    } else {
> +        put_16aligned_be32(&vxh->vx_flags, htonl(VXLAN_FLAGS));
> +        put_16aligned_be32(&vxh->vx_vni,
> +                           htonl(ntohll(params->flow->tunnel.tun_id) << 8));
> +    }
> 
>      ovs_mutex_unlock(&dev->mutex);
>      data->header_len += sizeof *vxh;
> diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
> index ba69461..d390f37 100644
> --- a/lib/netdev-vport.c
> +++ b/lib/netdev-vport.c
> @@ -414,6 +414,7 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args, char **errp)
>      uint16_t dst_proto = 0, src_proto = 0;
>      struct netdev_tunnel_config tnl_cfg;
>      struct smap_node *node;
> +    bool is_layer3 = false;
>      int err;
> 
>      has_csum = strstr(type, "gre") || strstr(type, "geneve") ||
> @@ -508,6 +509,9 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args, char **errp)
>              while (ext) {
>                  if (!strcmp(type, "vxlan") && !strcmp(ext, "gbp")) {
>                      tnl_cfg.exts |= (1 << OVS_VXLAN_EXT_GBP);
> +                } else if (!strcmp(type, "vxlan") && !strcmp(ext, "gpe")) {
> +                    tnl_cfg.exts |= (1 << OVS_VXLAN_EXT_GPE);
> +                    optional_layer3 = true;
>                  } else {
>                      ds_put_format(&errors, "%s: unknown extension '%s'\n",
>                                    name, ext);
> @@ -520,16 +524,23 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args, char **errp)
>          } else if (!strcmp(node->key, "egress_pkt_mark")) {
>              tnl_cfg.egress_pkt_mark = strtoul(node->value, NULL, 10);
>              tnl_cfg.set_egress_pkt_mark = true;
> -        } else if (!strcmp(node->key, "layer3") && optional_layer3) {
> +        } else if (!strcmp(node->key, "layer3")) {
>              if (!strcmp(node->value, "true")) {
> -                tnl_cfg.is_layer3 = true;
> +                is_layer3 = true;
>              }
>          } else {
> -            ds_put_format(&errors, "%s: unknown %s argument '%s'\n",
> -                          name, type, node->key);
> +            ds_put_format(&errors, "%s: unknown %s argument '%s'\n", name,
> +                          type, node->key);
>          }
>      }
> 
> +    if (optional_layer3 && is_layer3) {
> +       tnl_cfg.is_layer3 = is_layer3;
> +    } else if (!optional_layer3 && is_layer3) {
> +        ds_put_format(&errors, "%s: unknown %s argument '%s'\n",
> +                      name, type, "layer3");
> +    }
> +
>      if (!ipv6_addr_is_set(&tnl_cfg.ipv6_dst) && !tnl_cfg.ip_dst_flow) {
>          ds_put_format(&errors,
>                        "%s: %s type requires valid 'remote_ip' argument\n",
> @@ -660,7 +671,8 @@ get_tunnel_config(const struct netdev *dev, struct smap *args)
>          smap_add(args, "csum", "true");
>      }
> 
> -    if (tnl_cfg.is_layer3 && !strcmp("gre", type)) {
> +    if (tnl_cfg.is_layer3 && (!strcmp("gre", type) ||
> +        !strcmp("vxlan", type))) {
>          smap_add(args, "layer3", "true");
>      }
> 
> diff --git a/lib/packets.h b/lib/packets.h
> index d53e0b7..a00792d 100644
> --- a/lib/packets.h
> +++ b/lib/packets.h
> @@ -1174,12 +1174,64 @@ struct gre_base_hdr {
> 
>  /* VXLAN protocol header */
>  struct vxlanhdr {
> -    ovs_16aligned_be32 vx_flags;
> +    union {
> +        ovs_16aligned_be32 vx_flags; /* VXLAN flags. */
> +        struct {
> +            uint8_t flags;           /* VXLAN GPE flags. */
> +            uint8_t reserved_1;      /* 16 bits reserved. */
> +            uint8_t reserved_2;
> +            uint8_t next_protocol;   /* Next Protocol field for VXLAN GPE. */
> +        } vx_pge;
> +    };
>      ovs_16aligned_be32 vx_vni;
>  };
> 
>  #define VXLAN_FLAGS 0x08000000  /* struct vxlanhdr.vx_flags required value. */
> 
> +/*
> + * VXLAN Generic Protocol Extension (VXLAN_F_GPE):
> + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
> + * |R|R|Ver|I|P|R|O|       Reserved                |Next Protocol  |
> + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
> + * |                VXLAN Network Identifier (VNI) |   Reserved    |
> + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
> + *
> + * Ver = Version. Indicates VXLAN GPE protocol version.
> + *
> + * P = Next Protocol Bit. The P bit is set to indicate that the
> + *     Next Protocol field is present.
> + *
> + * O = OAM Flag Bit. The O bit is set to indicate that the packet
> + *     is an OAM packet.
> + *
> + * Next Protocol = This 8 bit field indicates the protocol header
> + * immediately following the VXLAN GPE header.
> + *
> + * https://tools.ietf.org/html/draft-ietf-nvo3-vxlan-gpe-01
> + */
> +
> +/* Fields in struct vxlanhdr.vx_gpe.flags */
> +#define VXLAN_GPE_FLAGS_VER     0x30    /* Version. */
> +#define VLXAN_GPE_FLAGS_P       0x04    /* Next Protocol Bit. */
> +#define VXLAN_GPE_FLAGS_O       0x01    /* OAM Bit. */
> +
> +/* VXLAN-GPE header flags. */
> +#define VXLAN_HF_VER   ((1U <<29) | (1U <<28))
> +#define VXLAN_HF_NP    (1U <<26)
> +#define VXLAN_HF_OAM   (1U <<24)
> +
> +#define VXLAN_GPE_USED_BITS (VXLAN_HF_VER | VXLAN_HF_NP | VXLAN_HF_OAM | \
> +                            0xff)
> +
> +/* VXLAN-GPE header Next Protocol. */
> +#define VXLAN_GPE_NP_IPV4      0x01
> +#define VXLAN_GPE_NP_IPV6      0x02
> +#define VXLAN_GPE_NP_ETHERNET  0x03
> +#define VXLAN_GPE_NP_NSH       0x04
> +
> +#define VXLAN_F_GPE  0x4000
> +#define VXLAN_HF_GPE 0x04000000
> +
>  /* Input values for PACKET_TYPE macros have to be in host byte order.
>   * The _BE postfix indicates result is in network byte order. Otherwise result
>   * is in host byte order. */
> diff --git a/tests/tunnel-push-pop.at b/tests/tunnel-push-pop.at
> index afa345e..e3aecb4 100644
> --- a/tests/tunnel-push-pop.at
> +++ b/tests/tunnel-push-pop.at
> @@ -16,6 +16,8 @@ AT_CHECK([ovs-vsctl add-port int-br t2 -- set Interface t2 type=vxlan \
>                         options:remote_ip=1.1.2.93 options:out_key=flow options:egress_pkt_mark=1234
> ofport_request=6\
>                      -- add-port int-br t6 -- set Interface t6 type=gre \
>                         options:remote_ip=1.1.2.92 options:key=456 options:layer3=true ofport_request=7\
> +                    -- add-port int-br t7 -- set Interface t7 type=vxlan \
> +                       options:remote_ip=1.1.2.92 options:key=345 options:exts=gpe ofport_request=8\
>                         ], [0])
> 
>  AT_CHECK([ovs-appctl dpif/show], [0], [dnl
> @@ -31,6 +33,7 @@ dummy at ovs-dummy: hit:0 missed:0
>  		t4 5/6081: (geneve: key=123, remote_ip=flow)
>  		t5 6/6081: (geneve: egress_pkt_mark=1234, out_key=flow, remote_ip=1.1.2.93)
>  		t6 7/3: (gre: key=456, layer3=true, remote_ip=1.1.2.92)
> +		t7 8/4789: (vxlan: key=345, remote_ip=1.1.2.92)
>  ])
> 
>  dnl First setup dummy interface IP address, then add the route
> @@ -113,6 +116,13 @@ AT_CHECK([tail -1 stdout], [0],
>    [Datapath actions:
> tnl_push(tnl_port(4789),header(size=50,type=4,eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(s
> rc=1.1.2.88,dst=1.1.2.92,proto=17,tos=0,ttl=64,frag=0x4000),udp(src=0,dst=4789,csum=0x0),vxlan(flags=0x8000000,vni=0
> x7b)),out_port(100))
>  ])
> 
> +dnl Check VXLAN GPE tunnel push
> +AT_CHECK([ovs-ofctl add-flow int-br action=8])
> +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:
> tnl_push(tnl_port(4789),header(size=50,type=4,eth(dst=f8:bc:12:44:34:b6,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(s
> rc=1.1.2.88,dst=1.1.2.92,proto=17,tos=0,ttl=64,frag=0x4000),udp(src=0,dst=4789,csum=0x0),vxlan(flags=0xc000003,vni=0
> x159)),out_port(100))
> +])
> +
>  dnl Check VXLAN tunnel push set tunnel id by flow and checksum
>  AT_CHECK([ovs-ofctl add-flow int-br "actions=set_tunnel:124,4"])
>  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:00),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=
> 47,tos=0,ttl=64,frag=no)'], [0], [stdout])
> --
> 2.7.4
> 
> _______________________________________________
> dev mailing list
> dev at openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev


More information about the dev mailing list