diff mbox

[ovs-dev,v2] Add VxLAN-GBP support for user space data path

Message ID 1461137993-7521-1-git-send-email-johnson.li@intel.com
State Superseded
Headers show

Commit Message

Johnson.Li April 20, 2016, 7:39 a.m. UTC
From: Johnson Li <johnson.li@intel.com>

In user space, only standard VxLAN was support. This patch will
add the VxLAN-GBP support for the user space data path.

How to use:
1> Create VxLAN port with GBP extension
  $ovs-vsctl add-port br-int vxlan0 -- set interface vxlan0 \
           type=vxlan options:dst_port=4789 \
           options:remote_ip=192.168.60.22 \
           options:key=1000 options:exts=gbp
2> Add flow for transmitting
  $ovs-ofctl add-flow br-int "table=0, priority=260, \
             in_port=LOCAL actions=load:0x100->NXM_NX_TUN_GBP_ID[], \
             output:1"
3> Add flow for receiving
  $ovs-ofctl add-flow br-int "table=0, priority=260, \
             in_port=1,tun_gbp_id=0x100 actions=output:LOCAL"

Check data path flow rules:
$ovs-appctl dpif/dump-flows br-int
  recirc_id(0),in_port(1),eth_type(0x0800),ipv4(tos=0/0x3,frag=no),
  packets:0, bytes:0, used:never, actions:tnl_push(tnl_port(2),
  header(size=50,type=4,eth(dst=90:e2:ba:48:7f:a4,src=90:e2:ba:48:7e:1c,
  dl_type=0x0800),ipv4(src=192.168.60.21,dst=192.168.60.22,proto=17,
  tos=0,ttl=64,frag=0x4000),udp(src=0,dst=4789,csum=0x0),
  vxlan(flags=0x88000100,vni=0x3e8)),out_port(3))
  tunnel(tun_id=0x3e8,src=192.168.60.22,dst=192.168.60.21,
  vxlan(gbp(id=256)),flags(-df-csum+key)),skb_mark(0),recirc_id(0),
  in_port(2),eth(dst=ae:1b:ed:1e:e3:4e),eth_type(0x0800),
  ipv4(dst=172.168.60.21,proto=1/0x10,frag=no), packets:0, bytes:0,
  used:never, actions:1

Change Log:
  v2: Set Each enabled bit for the VxLAN-GBP.

Signed-off-by: Johnson Li <johnson.li@intel.com>

Comments

Jesse Gross April 20, 2016, 8:22 p.m. UTC | #1
On Wed, Apr 20, 2016 at 12:39 AM, Johnson.Li <johnson.li@intel.com> wrote:
> From: Johnson Li <johnson.li@intel.com>
>
> In user space, only standard VxLAN was support. This patch will
> add the VxLAN-GBP support for the user space data path.
>
> How to use:
> 1> Create VxLAN port with GBP extension
>   $ovs-vsctl add-port br-int vxlan0 -- set interface vxlan0 \
>            type=vxlan options:dst_port=4789 \
>            options:remote_ip=192.168.60.22 \
>            options:key=1000 options:exts=gbp
> 2> Add flow for transmitting
>   $ovs-ofctl add-flow br-int "table=0, priority=260, \
>              in_port=LOCAL actions=load:0x100->NXM_NX_TUN_GBP_ID[], \
>              output:1"
> 3> Add flow for receiving
>   $ovs-ofctl add-flow br-int "table=0, priority=260, \
>              in_port=1,tun_gbp_id=0x100 actions=output:LOCAL"
>
> Check data path flow rules:
> $ovs-appctl dpif/dump-flows br-int
>   recirc_id(0),in_port(1),eth_type(0x0800),ipv4(tos=0/0x3,frag=no),
>   packets:0, bytes:0, used:never, actions:tnl_push(tnl_port(2),
>   header(size=50,type=4,eth(dst=90:e2:ba:48:7f:a4,src=90:e2:ba:48:7e:1c,
>   dl_type=0x0800),ipv4(src=192.168.60.21,dst=192.168.60.22,proto=17,
>   tos=0,ttl=64,frag=0x4000),udp(src=0,dst=4789,csum=0x0),
>   vxlan(flags=0x88000100,vni=0x3e8)),out_port(3))
>   tunnel(tun_id=0x3e8,src=192.168.60.22,dst=192.168.60.21,
>   vxlan(gbp(id=256)),flags(-df-csum+key)),skb_mark(0),recirc_id(0),
>   in_port(2),eth(dst=ae:1b:ed:1e:e3:4e),eth_type(0x0800),
>   ipv4(dst=172.168.60.21,proto=1/0x10,frag=no), packets:0, bytes:0,
>   used:never, actions:1

Can you please turn these into actual unit tests? Otherwise nobody
will ever execute them.

> Change Log:
>   v2: Set Each enabled bit for the VxLAN-GBP.

Please put this below three dashes so it won't be included in the
final commit message.

> diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
> index e398562..0ac449e 100644
> --- a/lib/netdev-vport.c
> +++ b/lib/netdev-vport.c
> @@ -1297,10 +1298,18 @@ netdev_vxlan_pop_header(struct dp_packet *packet)
>          return EINVAL;
>      }
>
> -    if (get_16aligned_be32(&vxh->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)),
> +    vxh_flags = get_16aligned_be32(&vxh->vx_flags);
> +    if (vxh_flags & htonl(VXLAN_HF_GBP)) {

This check needs to be conditional on GBP actually being enabled in
some form. Otherwise, you could misinterpret a different extension
that uses overlapping bit combinations.

> +        tnl->gbp_id = htons(ntohl(vxh_flags) & VXLAN_GBP_ID_MASK);

You can apply the byteswap to the mask instead of doing it twice on
the flags - AND operations can be done in any byte order.

>      ovs_mutex_unlock(&dev->mutex);
> diff --git a/lib/packets.h b/lib/packets.h
> index 8139a6b..c78b053 100644
> --- a/lib/packets.h
> +++ b/lib/packets.h
> @@ -1003,6 +1003,11 @@ struct vxlanhdr {
>
>  #define VXLAN_FLAGS 0x08000000  /* struct vxlanhdr.vx_flags required value. */

This is itself representing a flag in the VXLAN header, can you rename
it to be consistent with the other header flags?

> +#define VXLAN_HF_GBP 0x80000000  /* Group Based Policy, BIT(31) */
> +#define VXLAN_GBP_DONT_LEARN 0x400000 /* Don't Learn, (BIT(6) << 16) */
> +#define VXLAN_GBP_POLICY_APPLIED 0x80000 /* Policy Applied, (BIT(3) << 16) */

I think you can just represent this as bit shifts directly - no need
to keep it in the comments.
Johnson.Li April 21, 2016, 1:10 a.m. UTC | #2
> -----Original Message-----

> From: Jesse Gross [mailto:jesse@kernel.org]

> Sent: Thursday, April 21, 2016 4:23 AM

> To: Li, Johnson <johnson.li@intel.com>

> Cc: ovs dev <dev@openvswitch.org>

> Subject: Re: [ovs-dev] [PATCH v2] Add VxLAN-GBP support for user space

> data path

> 

> On Wed, Apr 20, 2016 at 12:39 AM, Johnson.Li <johnson.li@intel.com> wrote:

> > From: Johnson Li <johnson.li@intel.com>

> >

> > In user space, only standard VxLAN was support. This patch will add

> > the VxLAN-GBP support for the user space data path.

> 

> Can you please turn these into actual unit tests? Otherwise nobody will ever

> execute them.

Ok, I will try to add test cases. 
> 

> > Change Log:

> >   v2: Set Each enabled bit for the VxLAN-GBP.

> 

> Please put this below three dashes so it won't be included in the final commit

> message.

> 

Ok, I will. 
> > diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c index

> > e398562..0ac449e 100644

> > --- a/lib/netdev-vport.c

> > +++ b/lib/netdev-vport.c

> > @@ -1297,10 +1298,18 @@ netdev_vxlan_pop_header(struct dp_packet

> *packet)

> >          return EINVAL;

> >      }

> >

> > -    if (get_16aligned_be32(&vxh->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)),

> > +    vxh_flags = get_16aligned_be32(&vxh->vx_flags);

> > +    if (vxh_flags & htonl(VXLAN_HF_GBP)) {

> 

> This check needs to be conditional on GBP actually being enabled in some

> form. Otherwise, you could misinterpret a different extension that uses

> overlapping bit combinations.

From the spec at 
https://tools.ietf.org/html/draft-smith-vxlan-group-policy-01#section-2.1
it says " Bit 0 of the initial word is defined as the G (Group Based Policy Extension) bit".
If the G bit is set, it indicates that the GBP ID is carried. Then I can conclude that if
The header is VxLAN header(Special UDP destination port is detected), and the bit 0
Is set, then the header should be VxLAN-GBP header.
> 

> > +        tnl->gbp_id = htons(ntohl(vxh_flags) & VXLAN_GBP_ID_MASK);

> 

> You can apply the byteswap to the mask instead of doing it twice on the flags

> - AND operations can be done in any byte order.

> 

> >      ovs_mutex_unlock(&dev->mutex);

> > diff --git a/lib/packets.h b/lib/packets.h index 8139a6b..c78b053

> > 100644

> > --- a/lib/packets.h

> > +++ b/lib/packets.h

> > @@ -1003,6 +1003,11 @@ struct vxlanhdr {

> >

> >  #define VXLAN_FLAGS 0x08000000  /* struct vxlanhdr.vx_flags required

> > value. */

> 

> This is itself representing a flag in the VXLAN header, can you rename it to be

> consistent with the other header flags?

This just indicates that the VNI is set and valid for the VxLAN [-GB P|-GPE] header. 
> 

> > +#define VXLAN_HF_GBP 0x80000000  /* Group Based Policy, BIT(31) */

> > +#define VXLAN_GBP_DONT_LEARN 0x400000 /* Don't Learn, (BIT(6) <<

> 16)

> > +*/ #define VXLAN_GBP_POLICY_APPLIED 0x80000 /* Policy Applied,

> > +(BIT(3) << 16) */

> 

> I think you can just represent this as bit shifts directly - no need to keep it in

> the comments.

Just followed the origin implementation. I can follow you advice and copy the definition
From the implementation for Kernel data path.
Jesse Gross April 21, 2016, 1:15 a.m. UTC | #3
On Wed, Apr 20, 2016 at 6:10 PM, Li, Johnson <johnson.li@intel.com> wrote:
>> -----Original Message-----
>> From: Jesse Gross [mailto:jesse@kernel.org]
>> Sent: Thursday, April 21, 2016 4:23 AM
>> To: Li, Johnson <johnson.li@intel.com>
>> Cc: ovs dev <dev@openvswitch.org>
>> Subject: Re: [ovs-dev] [PATCH v2] Add VxLAN-GBP support for user space
>> data path
>> > diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c index
>> > e398562..0ac449e 100644
>> > --- a/lib/netdev-vport.c
>> > +++ b/lib/netdev-vport.c
>> > @@ -1297,10 +1298,18 @@ netdev_vxlan_pop_header(struct dp_packet
>> *packet)
>> >          return EINVAL;
>> >      }
>> >
>> > -    if (get_16aligned_be32(&vxh->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)),
>> > +    vxh_flags = get_16aligned_be32(&vxh->vx_flags);
>> > +    if (vxh_flags & htonl(VXLAN_HF_GBP)) {
>>
>> This check needs to be conditional on GBP actually being enabled in some
>> form. Otherwise, you could misinterpret a different extension that uses
>> overlapping bit combinations.
> From the spec at
> https://tools.ietf.org/html/draft-smith-vxlan-group-policy-01#section-2.1
> it says " Bit 0 of the initial word is defined as the G (Group Based Policy Extension) bit".
> If the G bit is set, it indicates that the GBP ID is carried. Then I can conclude that if
> The header is VxLAN header(Special UDP destination port is detected), and the bit 0
> Is set, then the header should be VxLAN-GBP header.

This draft is an extension to VXLAN and so you can only follow it if
you know that that extension is being used. There are other proposals
with conflicting definitions.

>> > +        tnl->gbp_id = htons(ntohl(vxh_flags) & VXLAN_GBP_ID_MASK);
>>
>> You can apply the byteswap to the mask instead of doing it twice on the flags
>> - AND operations can be done in any byte order.
>>
>> >      ovs_mutex_unlock(&dev->mutex);
>> > diff --git a/lib/packets.h b/lib/packets.h index 8139a6b..c78b053
>> > 100644
>> > --- a/lib/packets.h
>> > +++ b/lib/packets.h
>> > @@ -1003,6 +1003,11 @@ struct vxlanhdr {
>> >
>> >  #define VXLAN_FLAGS 0x08000000  /* struct vxlanhdr.vx_flags required
>> > value. */
>>
>> This is itself representing a flag in the VXLAN header, can you rename it to be
>> consistent with the other header flags?
> This just indicates that the VNI is set and valid for the VxLAN [-GB P|-GPE] header.

Yes, please define it that way.
diff mbox

Patch

diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
index e398562..0ac449e 100644
--- a/lib/netdev-vport.c
+++ b/lib/netdev-vport.c
@@ -1286,6 +1286,7 @@  netdev_vxlan_pop_header(struct dp_packet *packet)
     struct flow_tnl *tnl = &md->tunnel;
     struct vxlanhdr *vxh;
     unsigned int hlen;
+    uint32_t vxh_flags;
 
     pkt_metadata_init_tnl(md);
     if (VXLAN_HLEN > dp_packet_l4_size(packet)) {
@@ -1297,10 +1298,18 @@  netdev_vxlan_pop_header(struct dp_packet *packet)
         return EINVAL;
     }
 
-    if (get_16aligned_be32(&vxh->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)),
+    vxh_flags = get_16aligned_be32(&vxh->vx_flags);
+    if (vxh_flags & htonl(VXLAN_HF_GBP)) {
+        tnl->gbp_id = htons(ntohl(vxh_flags) & VXLAN_GBP_ID_MASK);
+        vxh_flags &= (VXLAN_GBP_DONT_LEARN | VXLAN_GBP_POLICY_APPLIED);
+        tnl->gbp_flags = vxh_flags >> 16;
+    } else if (vxh_flags != htonl(VXLAN_FLAGS)) {
+        VLOG_WARN_RL(&err_rl, "invalid vxlan flags=%#x\n",
+                     ntohl(get_16aligned_be32(&vxh->vx_flags)));
+        return EINVAL;
+    }
+    if (get_16aligned_be32(&vxh->vx_vni) & htonl(0xff)) {
+        VLOG_WARN_RL(&err_rl, "invalid vxlan vni=%#x\n",
                      ntohl(get_16aligned_be32(&vxh->vx_vni)));
         return EINVAL;
     }
@@ -1312,6 +1321,26 @@  netdev_vxlan_pop_header(struct dp_packet *packet)
     return 0;
 }
 
+static void
+netdev_vxlan_build_gbp_header(struct vxlanhdr *vxh,
+                              const struct flow *tnl_flow)
+{
+    uint32_t vxh_flags = VXLAN_FLAGS;
+
+    /* G bit to indicates that the source TSI Group membership is being
+     * carried within the Group Policy ID field. */
+    vxh_flags |= VXLAN_HF_GBP;
+
+    /* Only D bit and A bit is valid in gbp_flags. Other bit which is
+     * set will be ignored. */
+    vxh_flags |= (tnl_flow->tunnel.gbp_flags << 16)
+              & (VXLAN_GBP_DONT_LEARN | VXLAN_GBP_POLICY_APPLIED);
+
+    vxh_flags |= ntohs(tnl_flow->tunnel.gbp_id);
+
+    put_16aligned_be32(&vxh->vx_flags, htonl(vxh_flags));
+}
+
 static int
 netdev_vxlan_build_header(const struct netdev *netdev,
                           struct ovs_action_push_tnl *data,
@@ -1328,7 +1357,11 @@  netdev_vxlan_build_header(const struct netdev *netdev,
 
     vxh = udp_build_header(tnl_cfg, tnl_flow, data, &hlen);
 
-    put_16aligned_be32(&vxh->vx_flags, htonl(VXLAN_FLAGS));
+    if (tnl_cfg->exts & (1 << OVS_VXLAN_EXT_GBP)) {
+        netdev_vxlan_build_gbp_header(vxh, tnl_flow);
+    } else {
+        put_16aligned_be32(&vxh->vx_flags, htonl(VXLAN_FLAGS));
+    }
     put_16aligned_be32(&vxh->vx_vni, htonl(ntohll(tnl_flow->tunnel.tun_id) << 8));
 
     ovs_mutex_unlock(&dev->mutex);
diff --git a/lib/packets.h b/lib/packets.h
index 8139a6b..c78b053 100644
--- a/lib/packets.h
+++ b/lib/packets.h
@@ -1003,6 +1003,11 @@  struct vxlanhdr {
 
 #define VXLAN_FLAGS 0x08000000  /* struct vxlanhdr.vx_flags required value. */
 
+#define VXLAN_HF_GBP 0x80000000  /* Group Based Policy, BIT(31) */
+#define VXLAN_GBP_DONT_LEARN 0x400000 /* Don't Learn, (BIT(6) << 16) */
+#define VXLAN_GBP_POLICY_APPLIED 0x80000 /* Policy Applied, (BIT(3) << 16) */
+#define VXLAN_GBP_ID_MASK 0xFFFF /* GBP ID */
+
 void ipv6_format_addr(const struct in6_addr *addr, struct ds *);
 void ipv6_format_addr_bracket(const struct in6_addr *addr, struct ds *,
                               bool bracket);