On Thu, May 17, 2018 at 02:15:16PM -0700, Greg Rose wrote:
> From: William Tu <u9012...@gmail.com>
> 
> ERSPAN is a tunneling protocol based on GRE tunnel.  The patch
> add erspan tunnel support for ovs-vswitchd with userspace datapath.
> Configuring erspan tunnel is similar to gre tunnel, but with
> additional erspan's parameters.  Matching a flow on erspan's
> metadata is also supported, see ovs-fields for more details.
> 
> Signed-off-by: William Tu <u9012...@gmail.com>

Thanks.

Here is an incremental I suggest folding in.  The changes to .c and .h
files fix some unaligned access issues that Clang reported.

--8<--------------------------cut here-------------------------->8--

diff --git a/include/openvswitch/meta-flow.h b/include/openvswitch/meta-flow.h
index 2c1be7f2ea16..64470b524495 100644
--- a/include/openvswitch/meta-flow.h
+++ b/include/openvswitch/meta-flow.h
@@ -454,27 +454,27 @@ enum OVS_PACKED_ENUM mf_field_id {
      *
      * ERSPAN index (direction/port number)
      *
-     * Type: be32.
+     * Type: be32 (low 20 bits).
      * Maskable: bitwise.
      * Formatting: hexadecimal.
      * Prerequisites: none.
      * Access: read/write.
      * NXM: none.
-     * OXM: NXOXM_ET_ERSPAN_IDX(11) since OF1.5 and v2.9.
+     * OXM: NXOXM_ET_ERSPAN_IDX(11) since OF1.5 and v2.10.
      */
     MFF_TUN_ERSPAN_IDX,
 
     /* "tun_erspan_ver".
      *
-     * ERSPAN vsersion (v1 / v2)
+     * ERSPAN version (v1 / v2)
      *
-     * Type: u8.
+     * Type: u8 (low 4 bits).
      * Maskable: bitwise.
      * Formatting: decimal.
      * Prerequisites: none.
      * Access: read/write.
      * NXM: none.
-     * OXM: NXOXM_ET_ERSPAN_VER(12) since OF1.5 and v2.9.
+     * OXM: NXOXM_ET_ERSPAN_VER(12) since OF1.5 and v2.10.
      */
     MFF_TUN_ERSPAN_VER,
 
@@ -482,13 +482,13 @@ enum OVS_PACKED_ENUM mf_field_id {
      *
      * ERSPAN mirrored traffic's direction
      *
-     * Type: u8.
+     * Type: u8 (low 1 bits).
      * Maskable: bitwise.
      * Formatting: decimal.
      * Prerequisites: none.
      * Access: read/write.
      * NXM: none.
-     * OXM: NXOXM_ET_ERSPAN_DIR(13) since OF1.5 and v2.9.
+     * OXM: NXOXM_ET_ERSPAN_DIR(13) since OF1.5 and v2.10.
      */
     MFF_TUN_ERSPAN_DIR,
 
@@ -496,13 +496,13 @@ enum OVS_PACKED_ENUM mf_field_id {
      *
      * ERSPAN Hardware ID
      *
-     * Type: u8.
+     * Type: u8 (low 6 bits).
      * Maskable: bitwise.
      * Formatting: hexadecimal.
      * Prerequisites: none.
      * Access: read/write.
      * NXM: none.
-     * OXM: NXOXM_ET_ERSPAN_HWID(14) since OF1.5 and v2.9.
+     * OXM: NXOXM_ET_ERSPAN_HWID(14) since OF1.5 and v2.10.
      */
     MFF_TUN_ERSPAN_HWID,
 
diff --git a/lib/meta-flow.xml b/lib/meta-flow.xml
index 8c7aa00ad769..144657c34422 100644
--- a/lib/meta-flow.xml
+++ b/lib/meta-flow.xml
@@ -1716,20 +1716,19 @@ ovs-ofctl add-flow br-int 
'in_port=3,tun_src=192.168.1.1,tun_id=5001 actions=1'
       </dl>
     </field>
 
-    <h2>ERSPAN Metadata Fields FIXME</h2>
+    <h2>ERSPAN Metadata Fields</h2>
     <p>
-      These fields provide access to features in the ERSPAN tunneling
-      protocol.  The ERSPAN header is defined in the draft <url
-      href="https://tools.ietf.org/html/draft-foschiano-erspan-03"/>
+      These fields provide access to features in the ERSPAN tunneling protocol
+      [ERSPAN], which has two major versions: version 1 (aka type II) and
+      version 2 (aka type III).
+    </p>
+
+    <p>
+      Regardless of version, ERSPAN is encapsulated within a fixed 8-byte GRE
+      header that consists of a 4-byte GRE base header and a 4-byte sequence
+      number.  The ERSPAN version 1 header format is:
     </p>
-    <field id="MFF_TUN_ERSPAN_VER" title="ERSPAN Version">
-      <p>
-        ERSPAN version number. 1 for version 1 (type II)
-        or 2 for version 2 (type III).
-      </p>
-    </field>
 
-    <p> ERSPAN version 1 header format:</p>
     <diagram>
       <header name="GRE">
         <bits name="..." above="16" width="0.4"/>
@@ -1739,7 +1738,7 @@ ovs-ofctl add-flow br-int 
'in_port=3,tun_src=192.168.1.1,tun_id=5001 actions=1'
       <header name="ERSPAN v1">
         <bits name="ver" above="4" below="1" width="0.4"/>
         <bits name="..." above="18" width="0.4"/>
-        <bits name="session" above="10" below="tun_id" width="0.4"/>
+        <bits name="session" above="10" below="tun_id" width="0.5"/>
         <bits name="..." above="12" width="0.4"/>
         <bits name="idx" above="20" width="0.6"/>
       </header>
@@ -1751,19 +1750,10 @@ ovs-ofctl add-flow br-int 
'in_port=3,tun_src=192.168.1.1,tun_id=5001 actions=1'
       <dots/>
     </diagram>
 
-    <p> ERSPAN has a fixed 8-byte GRE header, including 4-byte GRE base header
-        another 4-byte sequence number.  The ERSPAN's 10-bit session ID holds
-        the tunnel ID.
+    <p>
+      The ERSPAN version 2 header format is:
     </p>
-    <field id="MFF_TUN_ERSPAN_IDX" title="ERSPAN Index">
-      <p>
-        ERSPAN index is a 20-bit index/port number associated with the ERSPAN
-        traffic's source port and direction (ingress/egress).  This field is
-        platform dependent.
-      </p>
-    </field>
 
-    <p> ERSPAN version 2 header format:</p>
     <diagram>
       <header name="GRE">
         <bits name="..." above="16" width="0.4"/>
@@ -1773,8 +1763,8 @@ ovs-ofctl add-flow br-int 
'in_port=3,tun_src=192.168.1.1,tun_id=5001 actions=1'
       <header name="ERSPAN v2">
         <bits name="ver" above="4" below="2" width="0.4"/>
         <bits name="..." above="18" width="0.4"/>
-        <bits name="session" above="10" below="tun_id" width="0.4"/>
-        <bits name="timestamp" above="32" width=".4"/>
+        <bits name="session" above="10" below="tun_id" width="0.5"/>
+        <bits name="timestamp" above="32" width=".7"/>
         <bits name="..." above="22" width="0.4"/>
         <bits name="hwid" above="6" width="0.4"/>
         <bits name="dir" above="1" below="0/1" width="0.4"/>
@@ -1788,17 +1778,23 @@ ovs-ofctl add-flow br-int 
'in_port=3,tun_src=192.168.1.1,tun_id=5001 actions=1'
       <dots/>
     </diagram>
 
+    <field id="MFF_TUN_ERSPAN_VER" title="ERSPAN Version">
+      ERSPAN version number: 1 for version 1, or 2 for version 2.
+    </field>
+
+    <field id="MFF_TUN_ERSPAN_IDX" title="ERSPAN Index">
+      This field is a 20-bit index/port number associated with the ERSPAN
+      traffic's source port and direction (ingress/egress).  This field is
+      platform dependent.
+    </field>
+
     <field id="MFF_TUN_ERSPAN_DIR" title="ERSPAN Direction">
-      <p>
-        Specifies the ERSPAN v2 mirrored traffic's direction.
-        Value 1 for egress traffic, and value 0 for ingress traffic.
-      </p>
+      For ERSPAN v2, the mirrored traffic's direction: 0 for ingress traffic, 1
+      for egress traffic.
     </field>
+
     <field id="MFF_TUN_ERSPAN_HWID" title="ERSPAN Hardware ID">
-      <p>
-        ERSPAN hardware ID is a 6-bit unique identifier of an
-        ERSPAN v2 engine within a system.
-      </p>
+      A 6-bit unique identifier of an ERSPAN v2 engine within a system.
     </field>
 
     <h2>Geneve Fields</h2>
@@ -4606,6 +4602,13 @@ r r c c c.
       Computer Communications Review, October 2007.
     </dd>
 
+    <dt>ERSPAN</dt>
+    <dd>
+      M. Foschiano, K. Ghosh, M. Mehta, ``Cisco Systems' Encapsulated Remote
+      Switch Port Analyzer (ERSPAN),'' <url
+      href="https://tools.ietf.org/html/draft-foschiano-erspan-03"/>.
+    </dd>
+
     <dt>EXT-56</dt>
     <dd>
       J. Tonsing, ``Permit one of a set of prerequisites to apply, e.g. don't
diff --git a/lib/netdev-native-tnl.c b/lib/netdev-native-tnl.c
index 7152f3e995c0..66eb18ef9b0d 100644
--- a/lib/netdev-native-tnl.c
+++ b/lib/netdev-native-tnl.c
@@ -556,15 +556,13 @@ netdev_erspan_pop_header(struct dp_packet *packet)
     tnl->erspan_ver = ersh->ver;
 
     if (ersh->ver == 1) {
-        ovs_be32 *index;
-        index = (ovs_be32 *)(ersh + 1);
-        tnl->erspan_idx = ntohl(*index);
+        ovs_16aligned_be32 *index = ALIGNED_CAST(ovs_16aligned_be32 *,
+                                                 ersh + 1);
+        tnl->erspan_idx = ntohl(get_16aligned_be32(index));
         tnl->flags |= FLOW_TNL_F_KEY;
         hlen = ulen + ERSPAN_GREHDR_LEN + sizeof *ersh + ERSPAN_V1_MDSIZE;
     } else if (ersh->ver == 2) {
-        struct erspan_md2 *md2;
-
-        md2 = (struct erspan_md2 *)(ersh + 1);
+        struct erspan_md2 *md2 = ALIGNED_CAST(struct erspan_md2 *, ersh + 1);
         tnl->erspan_dir = md2->dir;
         tnl->erspan_hwid = get_hwid(md2);
         tnl->flags |= FLOW_TNL_F_KEY;
@@ -597,21 +595,20 @@ netdev_erspan_push_header(const struct netdev *netdev,
     struct gre_base_hdr *greh;
     struct erspan_md2 *md2;
     int ip_tot_size;
-    ovs_be32 *seqno;
 
     greh = netdev_tnl_push_ip_header(packet, data->header,
                                      data->header_len, &ip_tot_size);
 
     /* update GRE seqno */
     tnl_cfg = &dev->tnl_cfg;
-    seqno = (ovs_be32 *)(greh + 1);
-    *seqno = htonl(tnl_cfg->seqno++);
+    ovs_16aligned_be32 *seqno = (ovs_16aligned_be32 *) (greh + 1);
+    put_16aligned_be32(seqno, htonl(tnl_cfg->seqno++));
 
     /* update v2 timestamp */
     if (greh->protocol == htons(ETH_TYPE_ERSPAN2)) {
         ersh = ERSPAN_HDR(greh);
-        md2 = (struct erspan_md2 *)(ersh + 1);
-        md2->timestamp = get_erspan_ts(ERSPAN_100US);
+        md2 = ALIGNED_CAST(struct erspan_md2 *, ersh + 1);
+        put_16aligned_be32(&md2->timestamp, get_erspan_ts(ERSPAN_100US));
     }
     return;
 }
@@ -645,29 +642,25 @@ netdev_erspan_build_header(const struct netdev *netdev,
     }
 
     if (tnl_cfg->erspan_ver == 1) {
-        ovs_be32 *index;
-
         greh->protocol = htons(ETH_TYPE_ERSPAN1);
         greh->flags = htons(GRE_SEQ);
         ersh->ver = 1;
         set_sid(ersh, sid);
 
-        index = (ovs_be32 *)(ersh + 1);
-        *index = htonl(tnl_cfg->erspan_idx);
+        put_16aligned_be32(ALIGNED_CAST(ovs_16aligned_be32 *, ersh + 1),
+                           htonl(tnl_cfg->erspan_idx));
 
         hlen = ERSPAN_GREHDR_LEN + sizeof *ersh + ERSPAN_V1_MDSIZE;
     } else if (tnl_cfg->erspan_ver == 2) {
-        struct erspan_md2 *md2;
-
         greh->protocol = htons(ETH_TYPE_ERSPAN2);
         greh->flags = htons(GRE_SEQ);
         ersh->ver = 2;
         set_sid(ersh, sid);
 
-        md2 = (struct erspan_md2 *)(ersh + 1);
+        struct erspan_md2 *md2 = ALIGNED_CAST(struct erspan_md2 *, ersh + 1);
         md2->sgt = 0; /* security group tag */
         md2->gra = 0;
-        md2->timestamp = 0;
+        put_16aligned_be32(&md2->timestamp, 0);
         set_hwid(md2, tnl_cfg->erspan_hwid);
         md2->dir = tnl_cfg->erspan_dir;
 
diff --git a/lib/odp-util.c b/lib/odp-util.c
index 4b54e599b8bd..fc842ee5533a 100644
--- a/lib/odp-util.c
+++ b/lib/odp-util.c
@@ -721,15 +721,13 @@ format_odp_tnl_push_header(struct ds *ds, struct 
ovs_action_push_tnl *data)
         ersh = ERSPAN_HDR(greh);
 
         if (ersh->ver == 1) {
-            const ovs_be32 *index;
-
-            index = (const ovs_be32 *)(ersh + 1);
+            ovs_16aligned_be32 *index = ALIGNED_CAST(ovs_16aligned_be32 *,
+                                                     ersh + 1);
             ds_put_format(ds, "erspan(ver=1,sid=0x%"PRIx16",idx=0x%"PRIx32")",
-                          get_sid(ersh), ntohl(*index));
+                          get_sid(ersh), ntohl(get_16aligned_be32(index)));
         } else if (ersh->ver == 2) {
-            const struct erspan_md2 *md2;
-
-            md2 = (const struct erspan_md2 *)(ersh + 1);
+            struct erspan_md2 *md2 = ALIGNED_CAST(struct erspan_md2 *,
+                                                  ersh + 1);
             ds_put_format(ds, "erspan(ver=2,sid=0x%"PRIx16
                           ",dir=%"PRIu8",hwid=0x%"PRIx8")",
                           get_sid(ersh), md2->dir, get_hwid(md2));
@@ -1603,10 +1601,9 @@ ovs_parse_tnl_push(const char *s, struct 
ovs_action_push_tnl *data)
                      ((uint8_t *) options - (uint8_t *) greh);
     } else if (ovs_scan_len(s, &n, "erspan(ver=1,sid="SCNx16",idx=0x"SCNx32")",
                             &sid, &erspan_idx)) {
-        ovs_be32 *index;
-
         ersh = ERSPAN_HDR(greh);
-        index = (ovs_be32 *)(ersh + 1);
+        ovs_16aligned_be32 *index = ALIGNED_CAST(ovs_16aligned_be32 *,
+                                                 ersh + 1);
 
         if (eth->eth_type == htons(ETH_TYPE_IP)) {
             tnl_type = OVS_VPORT_TYPE_ERSPAN;
@@ -1619,7 +1616,7 @@ ovs_parse_tnl_push(const char *s, struct 
ovs_action_push_tnl *data)
 
         ersh->ver = 1;
         set_sid(ersh, sid);
-        *index = htonl(erspan_idx);
+        put_16aligned_be32(index, htonl(erspan_idx));
 
         if (!ovs_scan_len(s, &n, ")")) {
             return -EINVAL;
@@ -1631,7 +1628,7 @@ ovs_parse_tnl_push(const char *s, struct 
ovs_action_push_tnl *data)
                             ",hwid=0x"SCNx8")", &sid, &dir, &hwid)) {
 
         ersh = ERSPAN_HDR(greh);
-        md2 = (struct erspan_md2 *)(ersh + 1);
+        md2 = ALIGNED_CAST(struct erspan_md2 *, ersh + 1);
 
         if (eth->eth_type == htons(ETH_TYPE_IP)) {
             tnl_type = OVS_VPORT_TYPE_ERSPAN;
diff --git a/lib/packets.h b/lib/packets.h
index 61888da599ef..7645a9de0be0 100644
--- a/lib/packets.h
+++ b/lib/packets.h
@@ -1300,7 +1300,7 @@ struct erspan_base_hdr {
 };
 
 struct erspan_md2 {
-    ovs_be32 timestamp;
+    ovs_16aligned_be32 timestamp;
     ovs_be16 sgt;
     uint8_t hwid_upper:2,
             ft:5,
_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to