From patchwork Fri Oct 2 21:31:59 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas F Herbert X-Patchwork-Id: 525815 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from archives.nicira.com (li376-54.members.linode.com [96.126.127.54]) by ozlabs.org (Postfix) with ESMTP id 2913D1402D5 for ; Sat, 3 Oct 2015 07:32:54 +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=aTNK9hNB; dkim-atps=neutral Received: from archives.nicira.com (localhost [127.0.0.1]) by archives.nicira.com (Postfix) with ESMTP id 72BB822C4A8; Fri, 2 Oct 2015 14:32:53 -0700 (PDT) X-Original-To: dev@openvswitch.org Delivered-To: dev@openvswitch.org Received: from mx3v1.cudamail.com (mx3.cudamail.com [64.34.241.5]) by archives.nicira.com (Postfix) with ESMTPS id 37EE522C479 for ; Fri, 2 Oct 2015 14:32:52 -0700 (PDT) Received: from bar4.cudamail.com (bar2 [192.168.15.2]) by mx3v1.cudamail.com (Postfix) with ESMTP id B8CEC618BE3 for ; Fri, 2 Oct 2015 15:32:51 -0600 (MDT) X-ASG-Debug-ID: 1443821570-03dc2139f31ead0001-byXFYA Received: from mx3-pf3.cudamail.com ([192.168.14.3]) by bar4.cudamail.com with ESMTP id obDR1O0FD8mvryVe (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Fri, 02 Oct 2015 15:32:50 -0600 (MDT) X-Barracuda-Envelope-From: thomasfherbert@gmail.com X-Barracuda-RBL-Trusted-Forwarder: 192.168.14.3 Received: from unknown (HELO mail-qk0-f170.google.com) (209.85.220.170) by mx3-pf3.cudamail.com with ESMTPS (RC4-SHA encrypted); 2 Oct 2015 21:32:49 -0000 Received-SPF: pass (mx3-pf3.cudamail.com: SPF record at _netblocks.google.com designates 209.85.220.170 as permitted sender) X-Barracuda-Apparent-Source-IP: 209.85.220.170 X-Barracuda-RBL-IP: 209.85.220.170 Received: by qkap81 with SMTP id p81so48707269qka.2 for ; Fri, 02 Oct 2015 14:32:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=krsWrBWEcgdN35y1ILvde1TdDSsAqTXjD4779WKAnfk=; b=aTNK9hNBSDYLT1ckkgJbFOAk6ciJ+h5FsOsBlBHWZPX0ntvvYL75aeEoJDr5Vb20tj sC+azPmqLrkHTlmSmeK6jPrFEbGIII0LBRNyxsefR6VTnYKxLgc3hR+1IYrTeoH3dM9a arJ3DLE1mT+gonlA/AABgopiYNZ9WbHxF8uP+wz/nXHofwn5FREMl07LdWuT+fAZSZzm CNGD4FokOIqv2x7P9X49sLHXfcYgF+WELHf9akn4s6dLTtTeCiSGCmDx+xxitUC2tOV1 /4wjEr1KRDJ5Fjt8qvjPY3xxBfBMKyf0iGvIGX1I5uZIIHIkSOvOnAp9aIIIO7ORZvNN 2AIg== X-Received: by 10.55.26.218 with SMTP id l87mr22613591qkh.23.1443821569021; Fri, 02 Oct 2015 14:32:49 -0700 (PDT) Received: from localhost.localdomain (pool-173-53-26-105.rcmdva.fios.verizon.net. [173.53.26.105]) by smtp.gmail.com with ESMTPSA id 139sm5428928qhh.43.2015.10.02.14.32.46 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 02 Oct 2015 14:32:48 -0700 (PDT) X-CudaMail-Envelope-Sender: thomasfherbert@gmail.com From: Thomas F Herbert To: dev@openvswitch.org, pshelar@nicira.com X-CudaMail-MID: CM-V3-1001057920 X-CudaMail-DTE: 100215 X-CudaMail-Originating-IP: 209.85.220.170 Date: Fri, 2 Oct 2015 17:31:59 -0400 X-ASG-Orig-Subj: [##CM-V3-1001057920##][PATCH V14 2/4] Flow key and netlink parsing changes for 802.1AD Message-Id: <1443821521-14770-3-git-send-email-thomasfherbert@gmail.com> X-Mailer: git-send-email 2.4.3 In-Reply-To: <1443821521-14770-1-git-send-email-thomasfherbert@gmail.com> References: <1443821521-14770-1-git-send-email-thomasfherbert@gmail.com> X-GBUdb-Analysis: 0, 209.85.220.170, Ugly c=0.369283 p=-0.333333 Source Normal X-MessageSniffer-Rules: 0-0-0-26159-c X-Barracuda-Connect: UNKNOWN[192.168.14.3] X-Barracuda-Start-Time: 1443821570 X-Barracuda-Encrypted: DHE-RSA-AES256-SHA X-Barracuda-URL: https://web.cudamail.com:443/cgi-mod/mark.cgi X-Barracuda-BRTS-Status: 1 X-Virus-Scanned: by bsmtpd at cudamail.com X-Barracuda-Spam-Score: 0.60 X-Barracuda-Spam-Status: No, SCORE=0.60 using per-user scores of TAG_LEVEL=3.0 QUARANTINE_LEVEL=1000.0 KILL_LEVEL=3.0 tests=BSF_SC5_MJ1963, DKIM_SIGNED, RDNS_NONE X-Barracuda-Spam-Report: Code version 3.2, rules version 3.2.3.23129 Rule breakdown below pts rule name description ---- ---------------------- -------------------------------------------------- 0.00 DKIM_SIGNED Domain Keys Identified Mail: message has a signature 0.10 RDNS_NONE Delivered to trusted network by a host with no rDNS 0.50 BSF_SC5_MJ1963 Custom Rule MJ1963 Cc: therbert@redhat.com Subject: [ovs-dev] [PATCH V14 2/4] Flow key and netlink parsing changes for 802.1AD X-BeenThere: dev@openvswitch.org X-Mailman-Version: 2.1.16 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dev-bounces@openvswitch.org Sender: "dev" From: "Thomas F. Herbert" Netlink parsing and flow key conversion. Netlink attribute encoding is done with double encap attributes. Netlink attributes for 802.1ad look like the following: eth_type(0x88a8),vlan(vid=100),encap(eth_type(0x8100), vlan(vid=200), encap(eth_type(0x0800), ...)) V14 is rebased to recent OVS. V11 fixes issues in the inner vlan encapsulation. Signed-off-by: Thomas F Herbert --- lib/odp-util.c | 281 +++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 242 insertions(+), 39 deletions(-) diff --git a/lib/odp-util.c b/lib/odp-util.c index d7696c9..120657b 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -3348,7 +3348,8 @@ odp_flow_key_from_flow__(const struct odp_flow_key_parms *parms, bool export_mask, struct ofpbuf *buf) { struct ovs_key_ethernet *eth_key; - size_t encap; + size_t encap = 0; + size_t inner_encap = 0; const struct flow *flow = parms->flow; const struct flow *data = export_mask ? parms->mask : parms->flow; @@ -3376,19 +3377,33 @@ odp_flow_key_from_flow__(const struct odp_flow_key_parms *parms, sizeof *eth_key); get_ethernet_key(data, eth_key); - if (flow->vlan_tci != htons(0) || flow->dl_type == htons(ETH_TYPE_VLAN)) { + if ((flow->vlan_tci != htons(0)) || eth_type_vlan(flow->dl_type)) { if (export_mask) { nl_msg_put_be16(buf, OVS_KEY_ATTR_ETHERTYPE, OVS_BE16_MAX); } else { - nl_msg_put_be16(buf, OVS_KEY_ATTR_ETHERTYPE, htons(ETH_TYPE_VLAN)); + nl_msg_put_be16(buf, OVS_KEY_ATTR_ETHERTYPE, + htons(ETH_TYPE_VLAN_8021Q)); } nl_msg_put_be16(buf, OVS_KEY_ATTR_VLAN, data->vlan_tci); encap = nl_msg_start_nested(buf, OVS_KEY_ATTR_ENCAP); if (flow->vlan_tci == htons(0)) { goto unencap; } - } else { - encap = 0; + /* Now, code the inner customer vlan. */ + if ((flow->vlan_ctci != htons(0)) || eth_type_vlan(flow->vlan_tpid)) { + if (export_mask) { + nl_msg_put_be16(buf, OVS_KEY_ATTR_ETHERTYPE, OVS_BE16_MAX); + nl_msg_put_be16(buf, OVS_KEY_ATTR_VLAN, OVS_BE16_MAX); + } else { + nl_msg_put_be16(buf, OVS_KEY_ATTR_ETHERTYPE, data->vlan_tpid); + nl_msg_put_be16(buf, OVS_KEY_ATTR_VLAN, data->vlan_ctci); + } + /* Now, code another layer of nesting for the payload. */ + inner_encap = nl_msg_start_nested(buf, OVS_KEY_ATTR_ENCAP); + if (flow->vlan_ctci == htons(0)) { + goto unencap; + } + } } if (ntohs(flow->dl_type) < ETH_TYPE_MIN) { @@ -3503,6 +3518,9 @@ odp_flow_key_from_flow__(const struct odp_flow_key_parms *parms, } unencap: + if (inner_encap) { + nl_msg_end_nested(buf, inner_encap); + } if (encap) { nl_msg_end_nested(buf, encap); } @@ -4024,9 +4042,36 @@ done: key, key_len); } -/* Parse 802.1Q header then encapsulated L3 attributes. */ static enum odp_key_fitness -parse_8021q_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1], +parse_encap_and_vlan(uint64_t present_attrs, int out_of_range_attr, + uint64_t expected_attrs, struct flow *flow, + const struct nlattr *key, size_t key_len, + const struct flow *src_flow) +{ + bool is_mask = src_flow != flow; + enum odp_key_fitness fitness; + + /* Calculate fitness of vlan and encap attributes. */ + if (!is_mask) { + expected_attrs |= ((UINT64_C(1) << OVS_KEY_ATTR_VLAN) | + (UINT64_C(1) << OVS_KEY_ATTR_ENCAP)); + } else { + if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_VLAN)) { + expected_attrs |= (UINT64_C(1) << OVS_KEY_ATTR_VLAN); + } + if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_ENCAP)) { + expected_attrs |= (UINT64_C(1) << OVS_KEY_ATTR_ENCAP); + } + } + fitness = check_expectations(present_attrs, out_of_range_attr, + expected_attrs, key, key_len); + + return fitness; +} + +/* Parse 802.1AD inner vlan and then parse encapsulated Attributes. */ +static enum odp_key_fitness +parse_cvlan_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1], uint64_t present_attrs, int out_of_range_attr, uint64_t expected_attrs, struct flow *flow, const struct nlattr *key, size_t key_len, @@ -4041,27 +4086,89 @@ parse_8021q_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1], enum odp_key_fitness encap_fitness; enum odp_key_fitness fitness; - /* Calculate fitness of outer attributes. */ + /* Calculate fitness of inner vlan attributes. */ + fitness = parse_encap_and_vlan(present_attrs, out_of_range_attr, + expected_attrs, flow, key, key_len, + src_flow); + + /* Set vlan_ctci and vlan inner tpid. */ + flow->vlan_ctci = (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_VLAN) + ? nl_attr_get_be16(attrs[OVS_KEY_ATTR_VLAN]) + : htons(0)); if (!is_mask) { - expected_attrs |= ((UINT64_C(1) << OVS_KEY_ATTR_VLAN) | - (UINT64_C(1) << OVS_KEY_ATTR_ENCAP)); - } else { - if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_VLAN)) { - expected_attrs |= (UINT64_C(1) << OVS_KEY_ATTR_VLAN); + if (!(present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_VLAN))) { + return ODP_FIT_TOO_LITTLE; + } else if (flow->vlan_ctci == htons(0)) { + /* Corner case for a truncated 802.1AD header. */ + if (fitness == ODP_FIT_PERFECT && nl_attr_get_size(encap)) { + return ODP_FIT_TOO_MUCH; + } + return fitness; + } else if (!(flow->vlan_ctci & htons(VLAN_CFI))) { + VLOG_ERR_RL(&rl, "Cust OVS_KEY_ATTR_VLAN 0x%04"PRIx16" is nonzero " + "but CFI bit is not set", ntohs(flow->vlan_ctci)); + return ODP_FIT_ERROR; } - if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_ENCAP)) { - expected_attrs |= (UINT64_C(1) << OVS_KEY_ATTR_ENCAP); + } else { + if (!(present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_ENCAP))) { + return fitness; } } - fitness = check_expectations(present_attrs, out_of_range_attr, - expected_attrs, key, key_len); - /* Set vlan_tci. + /* Now parse the encapsulated attributes. */ + if (!parse_flow_nlattrs(nl_attr_get(encap), nl_attr_get_size(encap), + attrs, &present_attrs, &out_of_range_attr)) { + return ODP_FIT_ERROR; + } + expected_attrs = 0; + + if (!parse_ethertype(attrs, present_attrs, &expected_attrs, flow, + src_flow)) { + return ODP_FIT_ERROR; + } + encap_fitness = parse_l2_5_onward(attrs, present_attrs, out_of_range_attr, + expected_attrs, flow, key, key_len, + src_flow); + + /* The overall fitness is the worse of the outer and inner attributes. */ + return MAX(fitness, encap_fitness); +} + +/* Parse 802.1AD or 802.1Q and then parse encapsulated Attributes. */ +static enum odp_key_fitness +parse_vlan_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1], + uint64_t present_attrs, int out_of_range_attr, + uint64_t expected_attrs, struct flow *flow, + const struct nlattr *key, size_t key_len, + const struct flow *src_flow) +{ + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + bool is_mask = src_flow != flow; + + const struct nlattr *encap + = (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_ENCAP) + ? attrs[OVS_KEY_ATTR_ENCAP] : NULL); + enum odp_key_fitness encap_fitness; + enum odp_key_fitness fitness; + uint16_t dl_type; + + /* Calculate fitness of outer vlan attributes */ + fitness = parse_encap_and_vlan(present_attrs, out_of_range_attr, + expected_attrs, flow, key, key_len, + src_flow); + + /* Set outertag, vlan_tci. * Remove the TPID from dl_type since it's not the real Ethertype. */ flow->dl_type = htons(0); flow->vlan_tci = (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_VLAN) ? nl_attr_get_be16(attrs[OVS_KEY_ATTR_VLAN]) : htons(0)); + /* Save a copy of the TPID though. If it is 802.1AD, we know to look for + * inner ctci in encapsulated attributes. + */ + dl_type = (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_ETHERTYPE) + ? nl_attr_get_be16(attrs[OVS_KEY_ATTR_ETHERTYPE]) + : htons(0)); if (!is_mask) { if (!(present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_VLAN))) { return ODP_FIT_TOO_LITTLE; @@ -4072,8 +4179,8 @@ parse_8021q_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1], } return fitness; } else if (!(flow->vlan_tci & htons(VLAN_CFI))) { - VLOG_ERR_RL(&rl, "OVS_KEY_ATTR_VLAN 0x%04"PRIx16" is nonzero " - "but CFI bit is not set", ntohs(flow->vlan_tci)); + VLOG_ERR_RL(&rl, "Outer OVS_KEY_ATTR_VLAN 0x%04"PRIx16" is nonzero" + " but CFI bit is not set", ntohs(flow->vlan_tci)); return ODP_FIT_ERROR; } } else { @@ -4089,6 +4196,23 @@ parse_8021q_onward(const struct nlattr *attrs[OVS_KEY_ATTR_MAX + 1], } expected_attrs = 0; + if (dl_type == htons(ETH_TYPE_VLAN_8021AD)) { + if (is_mask + ? (src_flow->vlan_ctci & htons(VLAN_CFI)) != 0 + : eth_type_vlan(dl_type)) { + /* Get inner vlan tag and tpid from the encapsulated attributes. */ + return parse_cvlan_onward(attrs, present_attrs, out_of_range_attr, + expected_attrs, flow, key, key_len, + src_flow); + } + if (is_mask) { + flow->vlan_ctci = htons(0xffff); + if (present_attrs & (UINT64_C(1) << OVS_KEY_ATTR_VLAN)) { + flow->vlan_ctci = nl_attr_get_be16(attrs[OVS_KEY_ATTR_VLAN]); + expected_attrs |= (UINT64_C(1) << OVS_KEY_ATTR_VLAN); + } + } + } if (!parse_ethertype(attrs, present_attrs, &expected_attrs, flow, src_flow)) { return ODP_FIT_ERROR; } @@ -4180,7 +4304,7 @@ odp_flow_key_to_flow__(const struct nlattr *key, size_t key_len, expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_ETHERNET; } - /* Get Ethertype or 802.1Q TPID or FLOW_DL_TYPE_NONE. */ + /* Get Ethertype or VLAN TPID or FLOW_DL_TYPE_NONE. */ if (!parse_ethertype(attrs, present_attrs, &expected_attrs, flow, src_flow)) { return ODP_FIT_ERROR; @@ -4188,9 +4312,9 @@ odp_flow_key_to_flow__(const struct nlattr *key, size_t key_len, if (is_mask ? (src_flow->vlan_tci & htons(VLAN_CFI)) != 0 - : src_flow->dl_type == htons(ETH_TYPE_VLAN)) { - return parse_8021q_onward(attrs, present_attrs, out_of_range_attr, - expected_attrs, flow, key, key_len, src_flow); + : eth_type_vlan(src_flow->dl_type)) { + return parse_vlan_onward(attrs, present_attrs, out_of_range_attr, + expected_attrs, flow, key, key_len, src_flow); } if (is_mask) { flow->vlan_tci = htons(0xffff); @@ -4199,6 +4323,7 @@ odp_flow_key_to_flow__(const struct nlattr *key, size_t key_len, expected_attrs |= (UINT64_C(1) << OVS_KEY_ATTR_VLAN); } } + return parse_l2_5_onward(attrs, present_attrs, out_of_range_attr, expected_attrs, flow, key, key_len, src_flow); } @@ -4460,37 +4585,115 @@ commit_set_ether_addr_action(const struct flow *flow, struct flow *base_flow, put_ethernet_key(&mask, &wc->masks); } } - +static int +flow_get_vlan_depth(const struct flow *flow) +{ + int n = 0; + if (flow->vlan_tci & htons(VLAN_CFI)) + n++; + if (flow->vlan_ctci & htons(VLAN_CFI)) + n++; + return n; +} static void pop_vlan(struct flow *base, struct ofpbuf *odp_actions, struct flow_wildcards *wc) { + int base_n = flow_get_vlan_depth(base); + + if (base_n == 0) + return; + memset(&wc->masks.vlan_tci, 0xff, sizeof wc->masks.vlan_tci); - if (base->vlan_tci & htons(VLAN_CFI)) { - nl_msg_put_flag(odp_actions, OVS_ACTION_ATTR_POP_VLAN); + if (base_n == 1) { + base->vlan_tci = 0; + base->vlan_tpid = 0; + base->vlan_ctci = 0; + + } else if (base_n ==2) { + + base->vlan_tci = base->vlan_ctci; + base->vlan_ctci = 0; + base->vlan_tpid = htons(ETH_TYPE_VLAN_8021Q); } + nl_msg_put_flag(odp_actions, OVS_ACTION_ATTR_POP_VLAN); } static void -commit_vlan_action(ovs_be16 vlan_tci, struct flow *base, - struct ofpbuf *odp_actions, struct flow_wildcards *wc) +push_vlan(struct flow *base, ovs_be16 vlan_tci, ovs_be16 vlan_tpid, + struct ofpbuf *odp_actions, struct flow_wildcards *wc) { - if (base->vlan_tci == vlan_tci) { + struct ovs_action_push_vlan vlan; + int base_n; + ovs_be16 tpid = htons(ETH_TYPE_VLAN_8021Q); + + if (!(vlan_tci & htons(VLAN_CFI))) return; - } - pop_vlan(base, odp_actions, wc); - if (vlan_tci & htons(VLAN_CFI)) { - struct ovs_action_push_vlan vlan; + memset(&wc->masks.vlan_tci, 0xff, sizeof wc->masks.vlan_tci); + - vlan.vlan_tpid = htons(ETH_TYPE_VLAN); - vlan.vlan_tci = vlan_tci; - nl_msg_put_unspec(odp_actions, OVS_ACTION_ATTR_PUSH_VLAN, - &vlan, sizeof vlan); + base_n = flow_get_vlan_depth(base); + + if (base_n == 2) { + return; + } else if (base_n == 1) { + if (!vlan_tpid) { + tpid = htons(ETH_TYPE_VLAN_8021AD); + } else { + tpid = vlan_tpid; + } + base->vlan_ctci = base->vlan_tci; + } else if (base_n == 0) { + if (!vlan_tpid) { + tpid = htons(ETH_TYPE_VLAN_8021Q); + } else { + tpid = vlan_tpid; + } + base->vlan_ctci = 0; } base->vlan_tci = vlan_tci; + base->vlan_tpid = tpid; + + vlan.vlan_tpid = tpid; + vlan.vlan_tci = vlan_tci; + nl_msg_put_unspec(odp_actions, OVS_ACTION_ATTR_PUSH_VLAN, + &vlan, sizeof vlan); +} + +static void +commit_vlan_action(const struct flow *flow, struct flow *base, + struct ofpbuf *odp_actions, struct flow_wildcards *wc) +{ + ovs_be16 vlan_tci = flow->vlan_tci; + ovs_be16 vlan_tpid = flow->vlan_tpid; + int base_n; + int flow_n; + + + if ((base->vlan_tci == vlan_tci) && (base->vlan_ctci == vlan_tci)) + return; + + base_n = flow_get_vlan_depth(base); + flow_n = flow_get_vlan_depth(flow); + + + if (flow_n == base_n) { + if (vlan_tci == base->vlan_tci) { + return; + } else { + pop_vlan(base, odp_actions, wc); + push_vlan(base, vlan_tci, vlan_tpid, odp_actions, wc); + } + } + else if (flow_n > base_n) { + push_vlan(base, vlan_tci, vlan_tpid, odp_actions, wc); + } + else if (flow_n < base_n) { + pop_vlan(base, odp_actions, wc); + } } /* Wildcarding already done at action translation time. */ @@ -4879,7 +5082,7 @@ commit_odp_actions(const struct flow *flow, struct flow *base, slow = commit_set_nw_action(flow, base, odp_actions, wc, use_masked); commit_set_port_action(flow, base, odp_actions, wc, use_masked); commit_mpls_action(flow, base, odp_actions); - commit_vlan_action(flow->vlan_tci, base, odp_actions, wc); + commit_vlan_action(flow, base, odp_actions, wc); commit_set_priority_action(flow, base, odp_actions, wc, use_masked); commit_set_pkt_mark_action(flow, base, odp_actions, wc, use_masked);