From: Johnson Li <johnson...@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:
  v3: Change Macro definition, add more comments, add unit test.
  v2: Set Each enabled bit for the VxLAN-GBP.

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

diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
index e398562..a7b5923 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,7 +1298,22 @@ netdev_vxlan_pop_header(struct dp_packet *packet)
         return EINVAL;
     }
 
-    if (get_16aligned_be32(&vxh->vx_flags) != htonl(VXLAN_FLAGS) ||
+    /* VXLAN protocol header:
+     * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+     * |G|R|R|R|I|R|R|C|               Reserved                        |
+     * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+     *
+     * G = 1   Group Policy (VXLAN-GBP)
+     * I = 1   VXLAN Network Identifier (VNI) present
+     */
+    vxh_flags = htonl(get_16aligned_be32(&vxh->vx_flags));
+    if (vxh_flags & VXLAN_HF_GBP) {
+        tnl->gbp_id = ntohs(vxh_flags & VXLAN_GBP_ID_MASK);
+        vxh_flags &= (VXLAN_GBP_DONT_LEARN | VXLAN_GBP_POLICY_APPLIED);
+        tnl->gbp_flags = vxh_flags >> 16;
+    }
+
+    if (!(get_16aligned_be32(&vxh->vx_flags) & htonl(VXLAN_HF_VNI)) ||
        (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)),
@@ -1312,6 +1328,27 @@ 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)
+{
+    /* VNI must be valid, so I bit should be set. */
+    uint32_t vxh_flags = VXLAN_HF_VNI;
+
+    /* 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 are valid in gbp_flags. Other bits which are
+     * set should 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 +1365,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_HF_VNI));
+    }
     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..23e964d 100644
--- a/lib/packets.h
+++ b/lib/packets.h
@@ -995,13 +995,49 @@ struct gre_base_hdr {
 #define GRE_FLAGS       0x00F8
 #define GRE_VERSION     0x0007
 
-/* VXLAN protocol header */
+/*
+ * VXLAN Group Based Policy Extension (VXLAN_F_GBP):
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |G|R|R|R|I|R|R|R|R|D|R|R|A|R|R|R|        Group Policy ID        |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                VXLAN Network Identifier (VNI) |   Reserved    |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * G = Group Policy ID present.
+ *
+ * D = Don't Learn bit. When set, this bit indicates that the egress
+ *     VTEP MUST NOT learn the source address of the encapsulated frame.
+ *
+ * A = Indicates that the group policy has already been applied to
+ *     this packet. Policies MUST NOT be applied by devices when the
+ *     A bit is set.
+ *
+ * https://tools.ietf.org/html/draft-smith-vxlan-group-policy
+ */
+#define VXLAN_GBP_DONT_LEARN           (1 << 22)
+#define VXLAN_GBP_POLICY_APPLIED       (1 << 19)
+#define VXLAN_GBP_ID_MASK              (0xFFFF)
+
+/* VXLAN protocol header:
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |G|R|R|R|I|R|R|C|               Reserved                        |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |                VXLAN Network Identifier (VNI) |   Reserved    |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * G = 1       Group Policy (VXLAN-GBP)
+ * I = 1       VXLAN Network Identifier (VNI) present
+ * C = 1       Remote checksum offload (RCO)
+ */
 struct vxlanhdr {
     ovs_16aligned_be32 vx_flags;
     ovs_16aligned_be32 vx_vni;
 };
 
-#define VXLAN_FLAGS 0x08000000  /* struct vxlanhdr.vx_flags required value. */
+/* VXLAN header flags. */
+#define VXLAN_HF_RCO (1 << 21)
+#define VXLAN_HF_VNI (1 << 27)
+#define VXLAN_HF_GBP (1 << 31)
 
 void ipv6_format_addr(const struct in6_addr *addr, struct ds *);
 void ipv6_format_addr_bracket(const struct in6_addr *addr, struct ds *,
diff --git a/tests/tunnel-push-pop.at b/tests/tunnel-push-pop.at
index a7909d3..5bd7096 100644
--- a/tests/tunnel-push-pop.at
+++ b/tests/tunnel-push-pop.at
@@ -12,6 +12,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:csum=true ofport_request=4\
                     -- add-port int-br t4 -- set Interface t4 type=geneve \
                        options:remote_ip=flow options:key=123 ofport_request=5\
+                    -- add-port int-br t5 -- set Interface t5 type=vxlan \
+                       options:remote_ip=1.1.2.94 options:key=456 
options:exts=gbp ofport_request=6\
                        ], [0])
 
 AT_CHECK([ovs-appctl dpif/show], [0], [dnl
@@ -25,6 +27,7 @@ dummy@ovs-dummy: hit:0 missed:0
                t2 2/4789: (vxlan: key=123, remote_ip=1.1.2.92)
                t3 4/4789: (vxlan: csum=true, out_key=flow, remote_ip=1.1.2.93)
                t4 5/6081: (geneve: key=123, remote_ip=flow)
+               t5 6/4789: (vxlan: key=456, remote_ip=1.1.2.94)
 ])
 
 dnl First setup dummy interface IP address, then add the route
@@ -55,12 +58,14 @@ 
ffffffffffffaa55aa55000008060001080006040001aa55aa550000010102580000000000000101
 dnl Check ARP Snoop
 AT_CHECK([ovs-appctl netdev-dummy/receive br0 
'recirc_id(0),in_port(100),eth(src=f8:bc:12:44:34:b6,dst=ff:ff:ff:ff:ff:ff),eth_type(0x0806),arp(sip=1.1.2.92,tip=1.1.2.88,op=2,sha=f8:bc:12:44:34:b6,tha=00:00:00:00:00:00)'])
 AT_CHECK([ovs-appctl netdev-dummy/receive br0 
'recirc_id(0),in_port(100),eth(src=f8:bc:12:44:34:b7,dst=ff:ff:ff:ff:ff:ff),eth_type(0x0806),arp(sip=1.1.2.93,tip=1.1.2.88,op=2,sha=f8:bc:12:44:34:b7,tha=00:00:00:00:00:00)'])
+AT_CHECK([ovs-appctl netdev-dummy/receive br0 
'recirc_id(0),in_port(100),eth(src=f8:bc:12:44:34:b8,dst=ff:ff:ff:ff:ff:ff),eth_type(0x0806),arp(sip=1.1.2.94,tip=1.1.2.88,op=2,sha=f8:bc:12:44:34:b8,tha=00:00:00:00:00:00)'])
 
 AT_CHECK([ovs-appctl tnl/neigh/show], [0], [dnl
 IP                                            MAC                 Bridge
 ==========================================================================
 1.1.2.92                                      f8:bc:12:44:34:b6   br0
 1.1.2.93                                      f8:bc:12:44:34:b7   br0
+1.1.2.94                                      f8:bc:12:44:34:b8   br0
 ])
 
 AT_CHECK([ovs-appctl tnl/ports/show |sort], [0], [dnl
@@ -102,6 +107,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:b7,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.93,proto=17,tos=0,ttl=64,frag=0x4000),udp(src=0,dst=4789,csum=0xffff),vxlan(flags=0x8000000,vni=0x7c)),out_port(100))
 ])
 
+dnl Check VXLAN-GBP tunnel push
+AT_CHECK([ovs-ofctl add-flow int-br 
"actions=load:0x100->NXM_NX_TUN_GBP_ID[[]],output:6"])
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 
'in_port(2),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:b8,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=1.1.2.88,dst=1.1.2.94,proto=17,tos=0,ttl=64,frag=0x4000),udp(src=0,dst=4789,csum=0x0),vxlan(flags=0x88000100,vni=0x1c8)),out_port(100))
+])
+
 dnl Check GRE tunnel push
 AT_CHECK([ovs-ofctl add-flow int-br action=3])
 AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 
'in_port(2),eth_type(0x0800),ipv4(src=1.1.3.88,dst=1.1.3.112,proto=47,tos=0,ttl=64,frag=no)'],
 [0], [stdout])
-- 
1.8.4.2

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to