On Thu, May 17, 2018 at 02:15:16PM -0700, Greg Rose wrote:
> From: William Tu <[email protected]>
>
> 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 <[email protected]>
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
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev