summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorYi-Hung Wei <yihung.wei@gmail.com>2017-05-15 10:04:57 -0700
committerBen Pfaff <blp@ovn.org>2017-05-31 14:54:10 -0700
commitd7892c814a8a9cf5681d34c6470bc9d841f4ad21 (patch)
tree3f0a70672a3781b56f3b6f8ae7e41178d4721c94 /lib
parent577bfa9f687936d53970d0ff41928c3a727720e8 (diff)
downloadopenvswitch-d7892c814a8a9cf5681d34c6470bc9d841f4ad21.tar.gz
ofproto: Add pipeline fields support for OF 1.5 packet-out
This patch decodes pipeline fields from a packet-out message, and populates the pipeline fields into datapath. Error OFPERR_OFPBRC_PIPELINE_FIELDS_ONLY is returned if the match field of a packet-out messages contains any non pipeline fields. Currently, the supported pipeline fields are as following. * metadata fields: - in_port, in_port_oxm * tunnel fields: - tun_id, tun_src, tun_dst, tun_ipv6_src, tun_ipv6_dst - tun_gbp_id, tun_gpb_flags, tun_flags - tun_metadata0 - tun_metadata63 * register fields: - metadata - reg0 - reg-15, xreg0 - xreg7, xxreg0 - xxreg3 Signed-off-by: Yi-Hung Wei <yihung.wei@gmail.com> Signed-off-by: Ben Pfaff <blp@ovn.org>
Diffstat (limited to 'lib')
-rw-r--r--lib/meta-flow.c90
-rw-r--r--lib/nx-match.c54
-rw-r--r--lib/nx-match.h14
-rw-r--r--lib/ofp-util.c23
4 files changed, 143 insertions, 38 deletions
diff --git a/lib/meta-flow.c b/lib/meta-flow.c
index b82a27381..b520e11c5 100644
--- a/lib/meta-flow.c
+++ b/lib/meta-flow.c
@@ -1553,6 +1553,96 @@ mf_is_tun_metadata(const struct mf_field *mf)
mf->id < MFF_TUN_METADATA0 + TUN_METADATA_NUM_OPTS;
}
+bool
+mf_is_pipeline_field(const struct mf_field *mf)
+{
+ switch (mf->id) {
+ case MFF_TUN_ID:
+ case MFF_TUN_SRC:
+ case MFF_TUN_DST:
+ case MFF_TUN_IPV6_SRC:
+ case MFF_TUN_IPV6_DST:
+ case MFF_TUN_FLAGS:
+ case MFF_TUN_GBP_ID:
+ case MFF_TUN_GBP_FLAGS:
+ CASE_MFF_TUN_METADATA:
+ case MFF_METADATA:
+ case MFF_IN_PORT:
+ case MFF_IN_PORT_OXM:
+ CASE_MFF_REGS:
+ CASE_MFF_XREGS:
+ CASE_MFF_XXREGS:
+ return true;
+
+ case MFF_DP_HASH:
+ case MFF_RECIRC_ID:
+ case MFF_CONJ_ID:
+ case MFF_TUN_TTL:
+ case MFF_TUN_TOS:
+ case MFF_ACTSET_OUTPUT:
+ case MFF_SKB_PRIORITY:
+ case MFF_PKT_MARK:
+ case MFF_CT_STATE:
+ case MFF_CT_ZONE:
+ case MFF_CT_MARK:
+ case MFF_CT_LABEL:
+ case MFF_CT_NW_PROTO:
+ case MFF_CT_NW_SRC:
+ case MFF_CT_NW_DST:
+ case MFF_CT_IPV6_SRC:
+ case MFF_CT_IPV6_DST:
+ case MFF_CT_TP_SRC:
+ case MFF_CT_TP_DST:
+ case MFF_ETH_SRC:
+ case MFF_ETH_DST:
+ case MFF_ETH_TYPE:
+ case MFF_VLAN_TCI:
+ case MFF_DL_VLAN:
+ case MFF_VLAN_VID:
+ case MFF_DL_VLAN_PCP:
+ case MFF_VLAN_PCP:
+ case MFF_MPLS_LABEL:
+ case MFF_MPLS_TC:
+ case MFF_MPLS_BOS:
+ case MFF_MPLS_TTL:
+ case MFF_IPV4_SRC:
+ case MFF_IPV4_DST:
+ case MFF_IPV6_SRC:
+ case MFF_IPV6_DST:
+ case MFF_IPV6_LABEL:
+ case MFF_IP_PROTO:
+ case MFF_IP_DSCP:
+ case MFF_IP_DSCP_SHIFTED:
+ case MFF_IP_ECN:
+ case MFF_IP_TTL:
+ case MFF_IP_FRAG:
+ case MFF_ARP_OP:
+ case MFF_ARP_SPA:
+ case MFF_ARP_TPA:
+ case MFF_ARP_SHA:
+ case MFF_ARP_THA:
+ case MFF_TCP_SRC:
+ case MFF_TCP_DST:
+ case MFF_TCP_FLAGS:
+ case MFF_UDP_SRC:
+ case MFF_UDP_DST:
+ case MFF_SCTP_SRC:
+ case MFF_SCTP_DST:
+ case MFF_ICMPV4_TYPE:
+ case MFF_ICMPV4_CODE:
+ case MFF_ICMPV6_TYPE:
+ case MFF_ICMPV6_CODE:
+ case MFF_ND_TARGET:
+ case MFF_ND_SLL:
+ case MFF_ND_TLL:
+ return false;
+
+ case MFF_N_IDS:
+ default:
+ OVS_NOT_REACHED();
+ }
+}
+
/* Returns true if 'mf' has previously been set in 'flow', false if
* it contains a non-default value.
*
diff --git a/lib/nx-match.c b/lib/nx-match.c
index 68e58d393..5d8aac571 100644
--- a/lib/nx-match.c
+++ b/lib/nx-match.c
@@ -510,8 +510,8 @@ nx_pull_match_entry(struct ofpbuf *b, bool allow_cookie,
* ethertype being present, when decoding metadata only. */
static enum ofperr
nx_pull_raw(const uint8_t *p, unsigned int match_len, bool strict,
- struct match *match, ovs_be64 *cookie, ovs_be64 *cookie_mask,
- const struct tun_table *tun_table,
+ bool pipeline_fields_only, struct match *match, ovs_be64 *cookie,
+ ovs_be64 *cookie_mask, const struct tun_table *tun_table,
const struct vl_mff_map *vl_mff_map)
{
ovs_assert((cookie != NULL) == (cookie_mask != NULL));
@@ -549,6 +549,8 @@ nx_pull_raw(const uint8_t *p, unsigned int match_len, bool strict,
error = OFPERR_OFPBMC_BAD_PREREQ;
} else if (!mf_is_all_wild(field, &match->wc)) {
error = OFPERR_OFPBMC_DUP_FIELD;
+ } else if (pipeline_fields_only && !mf_is_pipeline_field(field)) {
+ error = OFPERR_OFPBRC_PIPELINE_FIELDS_ONLY;
} else {
char *err_str;
@@ -575,7 +577,7 @@ nx_pull_raw(const uint8_t *p, unsigned int match_len, bool strict,
static enum ofperr
nx_pull_match__(struct ofpbuf *b, unsigned int match_len, bool strict,
- struct match *match,
+ bool pipeline_fields_only, struct match *match,
ovs_be64 *cookie, ovs_be64 *cookie_mask,
const struct tun_table *tun_table,
const struct vl_mff_map *vl_mff_map)
@@ -592,14 +594,17 @@ nx_pull_match__(struct ofpbuf *b, unsigned int match_len, bool strict,
}
}
- return nx_pull_raw(p, match_len, strict, match, cookie, cookie_mask,
- tun_table, vl_mff_map);
+ return nx_pull_raw(p, match_len, strict, pipeline_fields_only, match,
+ cookie, cookie_mask, tun_table, vl_mff_map);
}
/* Parses the nx_match formatted match description in 'b' with length
* 'match_len'. Stores the results in 'match'. If 'cookie' and 'cookie_mask'
* are valid pointers, then stores the cookie and mask in them if 'b' contains
* a "NXM_NX_COOKIE*" match. Otherwise, stores 0 in both.
+ * If 'pipeline_fields_only' is true, this function returns
+ * OFPERR_OFPBRC_PIPELINE_FIELDS_ONLY if there is any non pipeline fields
+ * in 'b'.
*
* 'vl_mff_map" is an optional parameter that is used to validate the length
* of variable length mf_fields in 'match'. If it is not provided, the
@@ -611,11 +616,11 @@ nx_pull_match__(struct ofpbuf *b, unsigned int match_len, bool strict,
enum ofperr
nx_pull_match(struct ofpbuf *b, unsigned int match_len, struct match *match,
ovs_be64 *cookie, ovs_be64 *cookie_mask,
- const struct tun_table *tun_table,
+ bool pipeline_fields_only, const struct tun_table *tun_table,
const struct vl_mff_map *vl_mff_map)
{
- return nx_pull_match__(b, match_len, true, match, cookie, cookie_mask,
- tun_table, vl_mff_map);
+ return nx_pull_match__(b, match_len, true, pipeline_fields_only, match,
+ cookie, cookie_mask, tun_table, vl_mff_map);
}
/* Behaves the same as nx_pull_match(), but skips over unknown NXM headers,
@@ -623,16 +628,16 @@ nx_pull_match(struct ofpbuf *b, unsigned int match_len, struct match *match,
* prerequisities. */
enum ofperr
nx_pull_match_loose(struct ofpbuf *b, unsigned int match_len,
- struct match *match,
- ovs_be64 *cookie, ovs_be64 *cookie_mask,
+ struct match *match, ovs_be64 *cookie,
+ ovs_be64 *cookie_mask, bool pipeline_fields_only,
const struct tun_table *tun_table)
{
- return nx_pull_match__(b, match_len, false, match, cookie, cookie_mask,
- tun_table, NULL);
+ return nx_pull_match__(b, match_len, false, pipeline_fields_only, match,
+ cookie, cookie_mask, tun_table, NULL);
}
static enum ofperr
-oxm_pull_match__(struct ofpbuf *b, bool strict,
+oxm_pull_match__(struct ofpbuf *b, bool strict, bool pipeline_fields_only,
const struct tun_table *tun_table,
const struct vl_mff_map *vl_mff_map, struct match *match)
{
@@ -662,11 +667,15 @@ oxm_pull_match__(struct ofpbuf *b, bool strict,
}
return nx_pull_raw(p + sizeof *omh, match_len - sizeof *omh,
- strict, match, NULL, NULL, tun_table, vl_mff_map);
+ strict, pipeline_fields_only, match, NULL, NULL,
+ tun_table, vl_mff_map);
}
/* Parses the oxm formatted match description preceded by a struct
* ofp11_match_header in 'b'. Stores the result in 'match'.
+ * If 'pipeline_fields_only' is true, this function returns
+ * OFPERR_OFPBRC_PIPELINE_FIELDS_ONLY if there is any non pipeline fields
+ * in 'b'.
*
* 'vl_mff_map' is an optional parameter that is used to validate the length
* of variable length mf_fields in 'match'. If it is not provided, the
@@ -676,20 +685,23 @@ oxm_pull_match__(struct ofpbuf *b, bool strict,
*
* Returns 0 if successful, otherwise an OpenFlow error code. */
enum ofperr
-oxm_pull_match(struct ofpbuf *b, const struct tun_table *tun_table,
+oxm_pull_match(struct ofpbuf *b, bool pipeline_fields_only,
+ const struct tun_table *tun_table,
const struct vl_mff_map *vl_mff_map, struct match *match)
{
- return oxm_pull_match__(b, true, tun_table, vl_mff_map, match);
+ return oxm_pull_match__(b, true, pipeline_fields_only, tun_table,
+ vl_mff_map, match);
}
/* Behaves the same as oxm_pull_match() with two exceptions. Skips over
* unknown OXM headers instead of failing with an error when they are
* encountered, and does not check for field prerequisities. */
enum ofperr
-oxm_pull_match_loose(struct ofpbuf *b, const struct tun_table *tun_table,
- struct match *match)
+oxm_pull_match_loose(struct ofpbuf *b, bool pipeline_fields_only,
+ const struct tun_table *tun_table, struct match *match)
{
- return oxm_pull_match__(b, false, tun_table, NULL, match);
+ return oxm_pull_match__(b, false, pipeline_fields_only, tun_table, NULL,
+ match);
}
/* Parses the OXM match description in the 'oxm_len' bytes in 'oxm'. Stores
@@ -705,8 +717,8 @@ oxm_decode_match(const void *oxm, size_t oxm_len, bool loose,
const struct tun_table *tun_table,
const struct vl_mff_map *vl_mff_map, struct match *match)
{
- return nx_pull_raw(oxm, oxm_len, !loose, match, NULL, NULL, tun_table,
- vl_mff_map);
+ return nx_pull_raw(oxm, oxm_len, !loose, false, match, NULL, NULL,
+ tun_table, vl_mff_map);
}
/* Verify an array of OXM TLVs treating value of each TLV as a mask,
diff --git a/lib/nx-match.h b/lib/nx-match.h
index 6afb310ef..90cb6f8fd 100644
--- a/lib/nx-match.h
+++ b/lib/nx-match.h
@@ -50,17 +50,19 @@ char *mf_parse_subfield(struct mf_subfield *, const char *s)
/* Decoding matches. */
enum ofperr nx_pull_match(struct ofpbuf *, unsigned int match_len,
- struct match *,
- ovs_be64 *cookie, ovs_be64 *cookie_mask,
+ struct match *, ovs_be64 *cookie,
+ ovs_be64 *cookie_mask, bool pipeline_fields_only,
const struct tun_table *, const struct vl_mff_map *);
enum ofperr nx_pull_match_loose(struct ofpbuf *, unsigned int match_len,
struct match *, ovs_be64 *cookie,
ovs_be64 *cookie_mask,
+ bool pipeline_fields_only,
const struct tun_table *);
-enum ofperr oxm_pull_match(struct ofpbuf *, const struct tun_table *,
- const struct vl_mff_map *, struct match *);
-enum ofperr oxm_pull_match_loose(struct ofpbuf *, const struct tun_table *,
- struct match *);
+enum ofperr oxm_pull_match(struct ofpbuf *, bool pipeline_fields_only,
+ const struct tun_table *, const struct vl_mff_map *,
+ struct match *);
+enum ofperr oxm_pull_match_loose(struct ofpbuf *, bool pipeline_fields_only,
+ const struct tun_table *, struct match *);
enum ofperr oxm_decode_match(const void *, size_t, bool,
const struct tun_table *,
const struct vl_mff_map *, struct match *);
diff --git a/lib/ofp-util.c b/lib/ofp-util.c
index 6b9d59f7c..62cc3228c 100644
--- a/lib/ofp-util.c
+++ b/lib/ofp-util.c
@@ -309,7 +309,7 @@ ofputil_pull_ofp11_match(struct ofpbuf *buf, const struct tun_table *tun_table,
if (padded_match_len) {
*padded_match_len = ROUND_UP(match_len, 8);
}
- return oxm_pull_match(buf, tun_table, vl_mff_map, match);
+ return oxm_pull_match(buf, false, tun_table, vl_mff_map, match);
default:
return OFPERR_OFPBMC_BAD_TYPE;
@@ -1685,7 +1685,7 @@ ofputil_decode_flow_mod(struct ofputil_flow_mod *fm,
nfm = ofpbuf_pull(&b, sizeof *nfm);
error = nx_pull_match(&b, ntohs(nfm->match_len),
&fm->match, &fm->cookie, &fm->cookie_mask,
- tun_table, vl_mff_map);
+ false, tun_table, vl_mff_map);
if (error) {
return error;
}
@@ -2324,7 +2324,7 @@ ofputil_decode_nxst_flow_request(struct ofputil_flow_stats_request *fsr,
nfsr = ofpbuf_pull(b, sizeof *nfsr);
error = nx_pull_match(b, ntohs(nfsr->match_len), &fsr->match,
- &fsr->cookie, &fsr->cookie_mask, tun_table,
+ &fsr->cookie, &fsr->cookie_mask, false, tun_table,
vl_mff_map);
if (error) {
return error;
@@ -2996,7 +2996,7 @@ ofputil_decode_flow_stats_reply(struct ofputil_flow_stats *fs,
"claims invalid length %"PRIuSIZE, match_len, length);
return EINVAL;
}
- if (nx_pull_match(msg, match_len, &fs->match, NULL, NULL, NULL,
+ if (nx_pull_match(msg, match_len, &fs->match, NULL, NULL, false, NULL,
NULL)) {
return EINVAL;
}
@@ -3253,7 +3253,7 @@ ofputil_decode_flow_removed(struct ofputil_flow_removed *fr,
nfr = ofpbuf_pull(&b, sizeof *nfr);
error = nx_pull_match(&b, ntohs(nfr->match_len), &fr->match, NULL,
- NULL, NULL, NULL);
+ NULL, false, NULL, NULL);
if (error) {
return error;
}
@@ -3514,7 +3514,7 @@ ofputil_decode_packet_in(const struct ofp_header *oh, bool loose,
const ovs_be64 *cookie = (raw == OFPRAW_OFPT13_PACKET_IN
? ofpbuf_pull(&b, sizeof *cookie)
: NULL);
- enum ofperr error = oxm_pull_match_loose(&b, tun_table,
+ enum ofperr error = oxm_pull_match_loose(&b, false, tun_table,
&pin->flow_metadata);
if (error) {
return error;
@@ -3574,7 +3574,8 @@ ofputil_decode_packet_in(const struct ofp_header *oh, bool loose,
npi = ofpbuf_pull(&b, sizeof *npi);
error = nx_pull_match_loose(&b, ntohs(npi->match_len),
- &pin->flow_metadata, NULL, NULL, NULL);
+ &pin->flow_metadata, NULL, NULL, false,
+ NULL);
if (error) {
return error;
}
@@ -4210,7 +4211,7 @@ ofputil_decode_packet_out(struct ofputil_packet_out *po,
const struct ofp15_packet_out *opo = ofpbuf_pull(&b, sizeof *opo);
po->buffer_id = ntohl(opo->buffer_id);
- error = oxm_pull_match_loose(&b, NULL, &po->flow_metadata);
+ error = oxm_pull_match_loose(&b, true, NULL, &po->flow_metadata);
if (error) {
return error;
}
@@ -6831,7 +6832,7 @@ ofputil_decode_flow_monitor_request(struct ofputil_flow_monitor_request *rq,
rq->table_id = nfmr->table_id;
return nx_pull_match(msg, ntohs(nfmr->match_len), &rq->match, NULL,
- NULL, NULL, NULL);
+ NULL, false, NULL, NULL);
}
void
@@ -6939,8 +6940,8 @@ ofputil_decode_flow_update(struct ofputil_flow_update *update,
update->cookie = nfuf->cookie;
update->priority = ntohs(nfuf->priority);
- error = nx_pull_match(msg, match_len, &update->match, NULL, NULL, NULL,
- NULL);
+ error = nx_pull_match(msg, match_len, &update->match, NULL, NULL,
+ false, NULL, NULL);
if (error) {
return error;
}