[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