From patchwork Mon May 15 17:04:57 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yi-Hung Wei X-Patchwork-Id: 762640 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3wRRpN1w1Zz9s0Z for ; Tue, 16 May 2017 03:07:24 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="fPi0buW3"; dkim-atps=neutral Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id BDE5BB76; Mon, 15 May 2017 17:05:13 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 8E07DB68 for ; Mon, 15 May 2017 17:05:11 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pg0-f65.google.com (mail-pg0-f65.google.com [74.125.83.65]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 5FF7624C for ; Mon, 15 May 2017 17:05:10 +0000 (UTC) Received: by mail-pg0-f65.google.com with SMTP id i63so17661273pgd.2 for ; Mon, 15 May 2017 10:05:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=SWlaxc08L+7H3wJssrJxzzkZu82e1gD1RrESplAn4Fc=; b=fPi0buW32AvB9M7DaQxWeT+8hEUIvZlzZDR60fK57CHa7JZPfkwnPTTT+inLp+OJ7o BeXKLoGjMhZ2JMTqo7CBMBsjaJ0DncvcCqPJd5Y4WKf92urZKEfAIbJP3sJoUeKaBNxU jVfQminVxecZLXdzH6Q7PTm+hP5Aw3/v21MfiNIhoGPcoj0ftWRai5ttJq+wi17/IebY F6R9yQIQX6K6O2MlXKomeQxT33V65P7TI5EoctwVqohenW8Sq7ilkqqcakxiVmIqmZyI jKRZoA7rQRxao2p1jnb+cgXHmQL0dEcW+/aLn8SQXAvd6O97QRKUKWOA1Yyg8kv9mj7O 0vQw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=SWlaxc08L+7H3wJssrJxzzkZu82e1gD1RrESplAn4Fc=; b=PUcLgSZdjzFpaM6LYZr+AwFkcKs2h4hyCE7L00ty842sCBzZmrSZFnSW5bzjLtpq2D OWz3/nfBp70QPk3Hvi6bAK5Yjl/AmBggy314vVPr4SmW+LpJnRtMVGCv7F71wPGP2wsJ NpV87rNxHDkvbH5wWYCVGbCY76JUcEXu1LCgKv42HahpqBCYewC8P5rBQZozh4eO1CBN BKwywhkAPOqsU72HxlFM4lsbouRt3OokLH/C21gBHd79DHd/nm/WG1IbU807tYhvyAtC YpksvI7Urk5ZzN1ix4L7Qo9nKNjiHd3+zatOqbVxqxOEZpxgYpiK/Qpo8tBK3m6F9BtD v1Dw== X-Gm-Message-State: AODbwcAC6rLPE2L91JkbklMIIM5cJL+lgcTxaaIFiPl7wfZ0Aqbfqk5d A1JT/nomSQf2og68tHE= X-Received: by 10.98.110.138 with SMTP id j132mr7310101pfc.51.1494867909469; Mon, 15 May 2017 10:05:09 -0700 (PDT) Received: from vm-01.vmware.com ([208.91.2.1]) by smtp.gmail.com with ESMTPSA id k86sm4725447pfk.125.2017.05.15.10.05.08 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 15 May 2017 10:05:08 -0700 (PDT) From: Yi-Hung Wei To: dev@openvswitch.org Date: Mon, 15 May 2017 10:04:57 -0700 Message-Id: <1494867899-87288-4-git-send-email-yihung.wei@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1494867899-87288-1-git-send-email-yihung.wei@gmail.com> References: <1494867899-87288-1-git-send-email-yihung.wei@gmail.com> X-Spam-Status: No, score=-1.5 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, RCVD_IN_DNSWL_NONE, RCVD_IN_SORBS_SPAM autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [PATCH 3/5] ofproto: Add pipeline fields support for OF 1.5 packet-out X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org 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 --- include/openvswitch/meta-flow.h | 1 + include/openvswitch/ofp-errors.h | 3 ++ lib/meta-flow.c | 90 ++++++++++++++++++++++++++++++++++++++++ lib/nx-match.c | 54 ++++++++++++++---------- lib/nx-match.h | 14 ++++--- lib/ofp-util.c | 23 +++++----- ofproto/ofproto.c | 9 +++- tests/ofp-print.at | 38 +++++++++++++++++ utilities/ovs-ofctl.c | 17 ++++---- 9 files changed, 201 insertions(+), 48 deletions(-) diff --git a/include/openvswitch/meta-flow.h b/include/openvswitch/meta-flow.h index 11852d2a07d8..1a0ba9b38c3a 100644 --- a/include/openvswitch/meta-flow.h +++ b/include/openvswitch/meta-flow.h @@ -2055,6 +2055,7 @@ void mf_set_flow_value_masked(const struct mf_field *, const union mf_value *mask, struct flow *); bool mf_is_tun_metadata(const struct mf_field *); +bool mf_is_pipeline_field(const struct mf_field *); bool mf_is_set(const struct mf_field *, const struct flow *); void mf_mask_field(const struct mf_field *, struct flow_wildcards *); void mf_mask_field_masked(const struct mf_field *, const union mf_value *mask, diff --git a/include/openvswitch/ofp-errors.h b/include/openvswitch/ofp-errors.h index a5bba8619bcb..e228ff0b010a 100644 --- a/include/openvswitch/ofp-errors.h +++ b/include/openvswitch/ofp-errors.h @@ -175,6 +175,9 @@ enum ofperr { /* OF1.3+(1,13). Multipart request overflowed the assigned buffer. */ OFPERR_OFPBRC_MULTIPART_BUFFER_OVERFLOW, + /* OF1.5+(1,17). Match fields must include only pipleline fields. */ + OFPERR_OFPBRC_PIPELINE_FIELDS_ONLY, + /* NX1.0-1.1(1,256), NX1.2+(2). Invalid NXM flow match. */ OFPERR_NXBRC_NXM_INVALID, diff --git a/lib/meta-flow.c b/lib/meta-flow.c index 6b97794f1753..d9c3b28b5cdb 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 68e58d393198..5d8aac571ac3 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 6afb310efa4b..90cb6f8fd329 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 b4d63931ecdb..5ba11239883e 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, false, NULL, + 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; } @@ -6829,7 +6830,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 @@ -6937,8 +6938,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; } diff --git a/ofproto/ofproto.c b/ofproto/ofproto.c index 2020fe85df7a..23ba3a191034 100644 --- a/ofproto/ofproto.c +++ b/ofproto/ofproto.c @@ -3458,6 +3458,10 @@ ofproto_packet_out_init(struct ofproto *ofproto, { enum ofperr error; struct match match; + struct { + struct miniflow mf; + uint64_t buf[FLOW_U64S]; + } m; if (ofp_to_u16(po->flow_metadata.flow.in_port.ofp_port) >= ofproto->max_ports @@ -3476,8 +3480,9 @@ ofproto_packet_out_init(struct ofproto *ofproto, po->packet_len, 2); /* Store struct flow. */ opo->flow = xmalloc(sizeof *opo->flow); - flow_extract(opo->packet, opo->flow); - opo->flow->in_port.ofp_port = po->flow_metadata.flow.in_port.ofp_port; + *opo->flow = po->flow_metadata.flow; + miniflow_extract(opo->packet, &m.mf); + flow_union_with_miniflow(opo->flow, &m.mf); /* Check actions like for flow mods. We pass a 'table_id' of 0 to * ofproto_check_consistency(), which isn't strictly correct because these diff --git a/tests/ofp-print.at b/tests/ofp-print.at index 6b950a0d90e9..a00e3f3fe74b 100644 --- a/tests/ofp-print.at +++ b/tests/ofp-print.at @@ -815,6 +815,44 @@ AT_CHECK([ovs-ofctl ofp-print "\ "], [0], [dnl OFPT_PACKET_OUT (OF1.5) (xid=0x11223344): ***decode error: OFPBRC_BAD_PORT*** ]) + +AT_CHECK([ovs-ofctl ofp-print "\ +06 0d 00 48 11 22 33 44 ff ff ff 00 00 10 00 00 \ +00 01 00 28 80 00 00 04 00 00 00 01 80 00 04 08 \ +00 00 00 00 00 00 00 03 80 00 4C 08 00 00 00 00 \ +00 00 00 05 00 00 00 00 00 00 00 10 ff ff ff fb \ +05 dc 00 00 00 00 00 00 \ +"], [0], [dnl +OFPT_PACKET_OUT (OF1.5) (xid=0x11223344): tun_id=0x5,metadata=0x3,in_port=1 actions=FLOOD buffer=0xffffff00 +]) + +dnl include non pipeline field +AT_CHECK([ovs-ofctl ofp-print "\ +06 0d 00 38 11 22 33 44 ff ff ff 00 00 10 00 00 \ +00 01 00 18 80 00 00 04 00 00 00 01 80 00 16 04 \ +11 22 33 44 00 00 00 00 00 00 00 10 ff ff ff fb \ +05 dc 00 00 00 00 00 00 \ +"], [0], [dnl +OFPT_PACKET_OUT (OF1.5) (xid=0x11223344): ***decode error: OFPBRC_PIPELINE_FIELDS_ONLY*** +]) + +AT_CLEANUP + +AT_SETUP([OFPT_PACKET_OUT - OF1.5, with packet]) +AT_KEYWORDS([ofp-print packet-out]) +AT_CHECK([ovs-ofctl ofp-print "\ +06 0d 00 74 11 22 33 44 ff ff ff ff 00 10 00 00 \ +00 01 00 18 80 00 00 04 00 00 00 01 80 00 04 08 \ +00 00 00 00 00 00 00 03 00 00 00 10 ff ff ff fb \ +05 dc 00 00 00 00 00 00 50 54 00 00 00 05 50 54 \ +00 00 00 06 08 00 45 00 00 28 00 00 40 00 40 06 \ +b9 7c c0 a8 00 02 c0 a8 00 01 00 00 2b 60 00 00 \ +00 00 6a 4f 2b 58 50 14 00 00 6d 75 00 00 00 00 \ +00 00 00 00 +"], [0], [dnl +OFPT_PACKET_OUT (OF1.5) (xid=0x11223344): metadata=0x3,in_port=1 actions=FLOOD data_len=60 +tcp,vlan_tci=0x0000,dl_src=50:54:00:00:00:06,dl_dst=50:54:00:00:00:05,nw_src=192.168.0.2,nw_dst=192.168.0.1,nw_tos=0,nw_ecn=0,nw_ttl=64,tp_src=0,tp_dst=11104,tcp_flags=rst|ack tcp_csum:6d75 +]) AT_CLEANUP # The flow is formatted with cls_rule_format() for the low-verbosity case. diff --git a/utilities/ovs-ofctl.c b/utilities/ovs-ofctl.c index 17ee64649f7f..22ac8d126000 100644 --- a/utilities/ovs-ofctl.c +++ b/utilities/ovs-ofctl.c @@ -3744,17 +3744,18 @@ ofctl_parse_nxm__(bool oxm, enum ofp_version version) /* Convert nx_match to match. */ if (strict) { if (oxm) { - error = oxm_pull_match(&nx_match, NULL, NULL, &match); + error = oxm_pull_match(&nx_match, false, NULL, NULL, &match); } else { - error = nx_pull_match(&nx_match, match_len, &match, - &cookie, &cookie_mask, NULL, NULL); + error = nx_pull_match(&nx_match, match_len, &match, &cookie, + &cookie_mask, false, NULL, NULL); } } else { if (oxm) { - error = oxm_pull_match_loose(&nx_match, NULL, &match); + error = oxm_pull_match_loose(&nx_match, false, NULL, &match); } else { error = nx_pull_match_loose(&nx_match, match_len, &match, - &cookie, &cookie_mask, NULL); + &cookie, &cookie_mask, false, + NULL); } } @@ -4164,8 +4165,8 @@ ofctl_check_vlan(struct ovs_cmdl_context *ctx) ofpbuf_init(&nxm, 0); nxm_match_len = nx_put_match(&nxm, &match, htonll(0), htonll(0)); nxm_s = nx_match_to_string(nxm.data, nxm_match_len); - error = nx_pull_match(&nxm, nxm_match_len, &nxm_match, NULL, NULL, NULL, - NULL); + error = nx_pull_match(&nxm, nxm_match_len, &nxm_match, NULL, NULL, false, + NULL, NULL); printf("NXM: %s -> ", nxm_s); if (error) { printf("%s\n", ofperr_to_string(error)); @@ -4181,7 +4182,7 @@ ofctl_check_vlan(struct ovs_cmdl_context *ctx) ofpbuf_init(&nxm, 0); nxm_match_len = oxm_put_match(&nxm, &match, OFP12_VERSION); nxm_s = oxm_match_to_string(&nxm, nxm_match_len); - error = oxm_pull_match(&nxm, NULL, NULL, &nxm_match); + error = oxm_pull_match(&nxm, false, NULL, NULL, &nxm_match); printf("OXM: %s -> ", nxm_s); if (error) { printf("%s\n", ofperr_to_string(error));