diff options
author | Jan Scheurich <jan.scheurich@ericsson.com> | 2017-06-23 16:47:57 +0000 |
---|---|---|
committer | Ben Pfaff <blp@ovn.org> | 2017-06-27 17:28:30 -0400 |
commit | 3d4b2e6eb74ed5bb5b35373aa8a489536938fee6 (patch) | |
tree | f086a8ec9d205140a69fd39db0c4c8be67ab855c /lib/nx-match.c | |
parent | be7ac2f3c105866542de5c1d4c7e2651250a3e92 (diff) | |
download | openvswitch-3d4b2e6eb74ed5bb5b35373aa8a489536938fee6.tar.gz |
userspace: Add OXM field MFF_PACKET_TYPE
Allow packet type namespace OFPHTN_ETHERTYPE as alternative pre-requisite
for matching L3 protocols (MPLS, IP, IPv6, ARP etc).
Change the meta-flow definition of packet_type field to use the new
custom format MFS_PACKET_TYPE representing "(NS,NS_TYPE)".
Parsing routine for MFS_PACKET_TYPE added to meta-flow.c. Formatting
routine for field packet_type extracted from match_format() and moved to
flow.c to be used from meta-flow.c for formatting MFS_PACKET_TYPE.
Updated the ovs-fields man page source meta-flow.xml with documentation
for packet-type-aware bridges and added documentation for field packet_type.
Added packet_type to the matching properties in tests/ofproto.at.
If dl_type is unwildcarded due to later packet modification, make sure it
is cleared again if the original packet_type was not PT_ETH.
Signed-off-by: Jan Scheurich <jan.scheurich@ericsson.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
Diffstat (limited to 'lib/nx-match.c')
-rw-r--r-- | lib/nx-match.c | 34 |
1 files changed, 29 insertions, 5 deletions
diff --git a/lib/nx-match.c b/lib/nx-match.c index 6278b7758..cb0cad845 100644 --- a/lib/nx-match.c +++ b/lib/nx-match.c @@ -561,6 +561,8 @@ nx_pull_raw(const uint8_t *p, unsigned int match_len, bool strict, free(err_str); return OFPERR_OFPBMC_BAD_VALUE; } + + match_add_ethernet_prereq(match, field); } if (error) { @@ -775,6 +777,7 @@ oxm_pull_field_array(const void *fields_data, size_t fields_len, struct nxm_put_ctx { struct ofpbuf *output; + bool implied_ethernet; }; void @@ -795,6 +798,9 @@ nxm_put__(struct nxm_put_ctx *ctx, const void *value, const void *mask, size_t n_bytes) { nxm_put_entry_raw(ctx->output, field, version, value, mask, n_bytes); + if (!ctx->implied_ethernet && mf_from_id(field)->prereqs != MFP_NONE) { + ctx->implied_ethernet = true; + } } static void @@ -904,8 +910,9 @@ nxm_put_ip(struct nxm_put_ctx *ctx, const struct match *match, enum ofp_version oxm) { const struct flow *flow = &match->flow; + ovs_be16 dl_type = get_dl_type(flow); - if (flow->dl_type == htons(ETH_TYPE_IP)) { + if (dl_type == htons(ETH_TYPE_IP)) { nxm_put_32m(ctx, MFF_IPV4_SRC, oxm, flow->nw_src, match->wc.masks.nw_src); nxm_put_32m(ctx, MFF_IPV4_DST, oxm, @@ -1014,12 +1021,19 @@ nx_put_raw(struct ofpbuf *b, enum ofp_version oxm, const struct match *match, { const struct flow *flow = &match->flow; const size_t start_len = b->size; + ovs_be16 dl_type = get_dl_type(flow); int match_len; int i; BUILD_ASSERT_DECL(FLOW_WC_SEQ == 39); - struct nxm_put_ctx ctx = { .output = b }; + struct nxm_put_ctx ctx = { .output = b, .implied_ethernet = false }; + + /* OpenFlow Packet Type. Must be first. */ + if (match->wc.masks.packet_type && !match_has_default_packet_type(match)) { + nxm_put_32m(&ctx, MFF_PACKET_TYPE, oxm, flow->packet_type, + match->wc.masks.packet_type); + } /* Metadata. */ if (match->wc.masks.dp_hash) { @@ -1082,7 +1096,7 @@ nx_put_raw(struct ofpbuf *b, enum ofp_version oxm, const struct match *match, } /* MPLS. */ - if (eth_type_mpls(flow->dl_type)) { + if (eth_type_mpls(dl_type)) { if (match->wc.masks.mpls_lse[0] & htonl(MPLS_TC_MASK)) { nxm_put_8(&ctx, MFF_MPLS_TC, oxm, mpls_lse_to_tc(flow->mpls_lse[0])); @@ -1102,8 +1116,8 @@ nx_put_raw(struct ofpbuf *b, enum ofp_version oxm, const struct match *match, /* L3. */ if (is_ip_any(flow)) { nxm_put_ip(&ctx, match, oxm); - } else if (flow->dl_type == htons(ETH_TYPE_ARP) || - flow->dl_type == htons(ETH_TYPE_RARP)) { + } else if (dl_type == htons(ETH_TYPE_ARP) || + dl_type == htons(ETH_TYPE_RARP)) { /* ARP. */ if (match->wc.masks.nw_proto) { nxm_put_16(&ctx, MFF_ARP_OP, oxm, @@ -1198,6 +1212,16 @@ nx_put_raw(struct ofpbuf *b, enum ofp_version oxm, const struct match *match, } } + if (match_has_default_packet_type(match) && !ctx.implied_ethernet) { + uint64_t pt_stub[16 / 8]; + struct ofpbuf pt; + ofpbuf_use_stack(&pt, pt_stub, sizeof pt_stub); + nxm_put_entry_raw(&pt, MFF_PACKET_TYPE, oxm, &flow->packet_type, + NULL, sizeof flow->packet_type); + + ofpbuf_insert(b, start_len, pt.data, pt.size); + } + match_len = b->size - start_len; return match_len; } |