From patchwork Wed Dec 18 14:40:53 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eli Britstein X-Patchwork-Id: 1212483 X-Patchwork-Delegate: i.maximets@samsung.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.133; helo=hemlock.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=mellanox.com Received: from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 47dHlj5gNNz9sRv for ; Thu, 19 Dec 2019 01:42:09 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by hemlock.osuosl.org (Postfix) with ESMTP id CF88C886A7; Wed, 18 Dec 2019 14:42:07 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from hemlock.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id WA+YKbpsRQuG; Wed, 18 Dec 2019 14:42:03 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by hemlock.osuosl.org (Postfix) with ESMTP id 73E8088579; Wed, 18 Dec 2019 14:41:43 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 4E749C1D92; Wed, 18 Dec 2019 14:41:43 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from silver.osuosl.org (smtp3.osuosl.org [140.211.166.136]) by lists.linuxfoundation.org (Postfix) with ESMTP id BA3CDC1D8D for ; Wed, 18 Dec 2019 14:41:28 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by silver.osuosl.org (Postfix) with ESMTP id B6EEE2048E for ; Wed, 18 Dec 2019 14:41:28 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from silver.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id khTMkWWmIV2l for ; Wed, 18 Dec 2019 14:41:26 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from mellanox.co.il (mail-il-dmz.mellanox.com [193.47.165.129]) by silver.osuosl.org (Postfix) with ESMTP id C424820784 for ; Wed, 18 Dec 2019 14:41:25 +0000 (UTC) Received: from Internal Mail-Server by MTLPINE1 (envelope-from elibr@mellanox.com) with ESMTPS (AES256-SHA encrypted); 18 Dec 2019 16:41:22 +0200 Received: from dev-r-vrt-215.mtr.labs.mlnx. (dev-r-vrt-215.mtr.labs.mlnx [10.212.215.1]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id xBIEfMlo027222; Wed, 18 Dec 2019 16:41:22 +0200 From: Eli Britstein To: dev@openvswitch.org, Ilya Maximets Date: Wed, 18 Dec 2019 14:40:53 +0000 Message-Id: <20191218144110.18653-2-elibr@mellanox.com> X-Mailer: git-send-email 2.14.5 In-Reply-To: <20191218144110.18653-1-elibr@mellanox.com> References: <20191218144110.18653-1-elibr@mellanox.com> Cc: Oz Shlomo , Simon Horman , Majd Dibbiny , Eli Britstein , Ameer Mahagneh Subject: [ovs-dev] [PATCH V5 01/18] netdev-offload-dpdk: Refactor flow patterns X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" Refactor the flow patterns code to a helper function for better readability and towards supporting more matches. Signed-off-by: Eli Britstein Reviewed-by: Oz Shlomo --- lib/netdev-offload-dpdk.c | 207 +++++++++++++++++++++++++--------------------- 1 file changed, 111 insertions(+), 96 deletions(-) diff --git a/lib/netdev-offload-dpdk.c b/lib/netdev-offload-dpdk.c index 96794dc4d..71da12aab 100644 --- a/lib/netdev-offload-dpdk.c +++ b/lib/netdev-offload-dpdk.c @@ -410,54 +410,39 @@ add_flow_rss_action(struct flow_actions *actions, return rss_data; } +struct flow_items { + struct rte_flow_item_eth eth; + struct rte_flow_item_vlan vlan; + struct rte_flow_item_ipv4 ipv4; + union { + struct rte_flow_item_tcp tcp; + struct rte_flow_item_udp udp; + struct rte_flow_item_sctp sctp; + struct rte_flow_item_icmp icmp; + }; +}; + static int -netdev_offload_dpdk_add_flow(struct netdev *netdev, - const struct match *match, - struct nlattr *nl_actions OVS_UNUSED, - size_t actions_len OVS_UNUSED, - const ovs_u128 *ufid, - struct offload_info *info) +parse_flow_match(struct flow_patterns *patterns, + struct flow_items *spec, + struct flow_items *mask, + const struct match *match) { - const struct rte_flow_attr flow_attr = { - .group = 0, - .priority = 0, - .ingress = 1, - .egress = 0 - }; - struct flow_patterns patterns = { .items = NULL, .cnt = 0 }; - struct flow_actions actions = { .actions = NULL, .cnt = 0 }; - struct rte_flow *flow; - struct rte_flow_error error; uint8_t proto = 0; - int ret = 0; - struct flow_items { - struct rte_flow_item_eth eth; - struct rte_flow_item_vlan vlan; - struct rte_flow_item_ipv4 ipv4; - union { - struct rte_flow_item_tcp tcp; - struct rte_flow_item_udp udp; - struct rte_flow_item_sctp sctp; - struct rte_flow_item_icmp icmp; - }; - } spec, mask; - - memset(&spec, 0, sizeof spec); - memset(&mask, 0, sizeof mask); /* Eth */ if (!eth_addr_is_zero(match->wc.masks.dl_src) || !eth_addr_is_zero(match->wc.masks.dl_dst)) { - memcpy(&spec.eth.dst, &match->flow.dl_dst, sizeof spec.eth.dst); - memcpy(&spec.eth.src, &match->flow.dl_src, sizeof spec.eth.src); - spec.eth.type = match->flow.dl_type; + memcpy(&spec->eth.dst, &match->flow.dl_dst, sizeof spec->eth.dst); + memcpy(&spec->eth.src, &match->flow.dl_src, sizeof spec->eth.src); + spec->eth.type = match->flow.dl_type; - memcpy(&mask.eth.dst, &match->wc.masks.dl_dst, sizeof mask.eth.dst); - memcpy(&mask.eth.src, &match->wc.masks.dl_src, sizeof mask.eth.src); - mask.eth.type = match->wc.masks.dl_type; + memcpy(&mask->eth.dst, &match->wc.masks.dl_dst, sizeof mask->eth.dst); + memcpy(&mask->eth.src, &match->wc.masks.dl_src, sizeof mask->eth.src); + mask->eth.type = match->wc.masks.dl_type; - add_flow_pattern(&patterns, RTE_FLOW_ITEM_TYPE_ETH, - &spec.eth, &mask.eth); + add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_ETH, + &spec->eth, &mask->eth); } else { /* * If user specifies a flow (like UDP flow) without L2 patterns, @@ -466,41 +451,41 @@ netdev_offload_dpdk_add_flow(struct netdev *netdev, * NIC (such as XL710) doesn't support that. Below is a workaround, * which simply matches any L2 pkts. */ - add_flow_pattern(&patterns, RTE_FLOW_ITEM_TYPE_ETH, NULL, NULL); + add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_ETH, NULL, NULL); } /* VLAN */ if (match->wc.masks.vlans[0].tci && match->flow.vlans[0].tci) { - spec.vlan.tci = match->flow.vlans[0].tci & ~htons(VLAN_CFI); - mask.vlan.tci = match->wc.masks.vlans[0].tci & ~htons(VLAN_CFI); + spec->vlan.tci = match->flow.vlans[0].tci & ~htons(VLAN_CFI); + mask->vlan.tci = match->wc.masks.vlans[0].tci & ~htons(VLAN_CFI); /* Match any protocols. */ - mask.vlan.inner_type = 0; + mask->vlan.inner_type = 0; - add_flow_pattern(&patterns, RTE_FLOW_ITEM_TYPE_VLAN, - &spec.vlan, &mask.vlan); + add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_VLAN, + &spec->vlan, &mask->vlan); } /* IP v4 */ if (match->flow.dl_type == htons(ETH_TYPE_IP)) { - spec.ipv4.hdr.type_of_service = match->flow.nw_tos; - spec.ipv4.hdr.time_to_live = match->flow.nw_ttl; - spec.ipv4.hdr.next_proto_id = match->flow.nw_proto; - spec.ipv4.hdr.src_addr = match->flow.nw_src; - spec.ipv4.hdr.dst_addr = match->flow.nw_dst; + spec->ipv4.hdr.type_of_service = match->flow.nw_tos; + spec->ipv4.hdr.time_to_live = match->flow.nw_ttl; + spec->ipv4.hdr.next_proto_id = match->flow.nw_proto; + spec->ipv4.hdr.src_addr = match->flow.nw_src; + spec->ipv4.hdr.dst_addr = match->flow.nw_dst; - mask.ipv4.hdr.type_of_service = match->wc.masks.nw_tos; - mask.ipv4.hdr.time_to_live = match->wc.masks.nw_ttl; - mask.ipv4.hdr.next_proto_id = match->wc.masks.nw_proto; - mask.ipv4.hdr.src_addr = match->wc.masks.nw_src; - mask.ipv4.hdr.dst_addr = match->wc.masks.nw_dst; + mask->ipv4.hdr.type_of_service = match->wc.masks.nw_tos; + mask->ipv4.hdr.time_to_live = match->wc.masks.nw_ttl; + mask->ipv4.hdr.next_proto_id = match->wc.masks.nw_proto; + mask->ipv4.hdr.src_addr = match->wc.masks.nw_src; + mask->ipv4.hdr.dst_addr = match->wc.masks.nw_dst; - add_flow_pattern(&patterns, RTE_FLOW_ITEM_TYPE_IPV4, - &spec.ipv4, &mask.ipv4); + add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_IPV4, + &spec->ipv4, &mask->ipv4); /* Save proto for L4 protocol setup. */ - proto = spec.ipv4.hdr.next_proto_id & - mask.ipv4.hdr.next_proto_id; + proto = spec->ipv4.hdr.next_proto_id & + mask->ipv4.hdr.next_proto_id; } if (proto != IPPROTO_ICMP && proto != IPPROTO_UDP && @@ -509,79 +494,109 @@ netdev_offload_dpdk_add_flow(struct netdev *netdev, match->wc.masks.tp_dst || match->wc.masks.tcp_flags)) { VLOG_DBG("L4 Protocol (%u) not supported", proto); - ret = -1; - goto out; + return -1; } if ((match->wc.masks.tp_src && match->wc.masks.tp_src != OVS_BE16_MAX) || (match->wc.masks.tp_dst && match->wc.masks.tp_dst != OVS_BE16_MAX)) { - ret = -1; - goto out; + return -1; } switch (proto) { case IPPROTO_TCP: - spec.tcp.hdr.src_port = match->flow.tp_src; - spec.tcp.hdr.dst_port = match->flow.tp_dst; - spec.tcp.hdr.data_off = ntohs(match->flow.tcp_flags) >> 8; - spec.tcp.hdr.tcp_flags = ntohs(match->flow.tcp_flags) & 0xff; + spec->tcp.hdr.src_port = match->flow.tp_src; + spec->tcp.hdr.dst_port = match->flow.tp_dst; + spec->tcp.hdr.data_off = ntohs(match->flow.tcp_flags) >> 8; + spec->tcp.hdr.tcp_flags = ntohs(match->flow.tcp_flags) & 0xff; - mask.tcp.hdr.src_port = match->wc.masks.tp_src; - mask.tcp.hdr.dst_port = match->wc.masks.tp_dst; - mask.tcp.hdr.data_off = ntohs(match->wc.masks.tcp_flags) >> 8; - mask.tcp.hdr.tcp_flags = ntohs(match->wc.masks.tcp_flags) & 0xff; + mask->tcp.hdr.src_port = match->wc.masks.tp_src; + mask->tcp.hdr.dst_port = match->wc.masks.tp_dst; + mask->tcp.hdr.data_off = ntohs(match->wc.masks.tcp_flags) >> 8; + mask->tcp.hdr.tcp_flags = ntohs(match->wc.masks.tcp_flags) & 0xff; - add_flow_pattern(&patterns, RTE_FLOW_ITEM_TYPE_TCP, - &spec.tcp, &mask.tcp); + add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_TCP, + &spec->tcp, &mask->tcp); /* proto == TCP and ITEM_TYPE_TCP, thus no need for proto match. */ - mask.ipv4.hdr.next_proto_id = 0; + mask->ipv4.hdr.next_proto_id = 0; break; case IPPROTO_UDP: - spec.udp.hdr.src_port = match->flow.tp_src; - spec.udp.hdr.dst_port = match->flow.tp_dst; + spec->udp.hdr.src_port = match->flow.tp_src; + spec->udp.hdr.dst_port = match->flow.tp_dst; - mask.udp.hdr.src_port = match->wc.masks.tp_src; - mask.udp.hdr.dst_port = match->wc.masks.tp_dst; + mask->udp.hdr.src_port = match->wc.masks.tp_src; + mask->udp.hdr.dst_port = match->wc.masks.tp_dst; - add_flow_pattern(&patterns, RTE_FLOW_ITEM_TYPE_UDP, - &spec.udp, &mask.udp); + add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_UDP, + &spec->udp, &mask->udp); /* proto == UDP and ITEM_TYPE_UDP, thus no need for proto match. */ - mask.ipv4.hdr.next_proto_id = 0; + mask->ipv4.hdr.next_proto_id = 0; break; case IPPROTO_SCTP: - spec.sctp.hdr.src_port = match->flow.tp_src; - spec.sctp.hdr.dst_port = match->flow.tp_dst; + spec->sctp.hdr.src_port = match->flow.tp_src; + spec->sctp.hdr.dst_port = match->flow.tp_dst; - mask.sctp.hdr.src_port = match->wc.masks.tp_src; - mask.sctp.hdr.dst_port = match->wc.masks.tp_dst; + mask->sctp.hdr.src_port = match->wc.masks.tp_src; + mask->sctp.hdr.dst_port = match->wc.masks.tp_dst; - add_flow_pattern(&patterns, RTE_FLOW_ITEM_TYPE_SCTP, - &spec.sctp, &mask.sctp); + add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_SCTP, + &spec->sctp, &mask->sctp); /* proto == SCTP and ITEM_TYPE_SCTP, thus no need for proto match. */ - mask.ipv4.hdr.next_proto_id = 0; + mask->ipv4.hdr.next_proto_id = 0; break; case IPPROTO_ICMP: - spec.icmp.hdr.icmp_type = (uint8_t) ntohs(match->flow.tp_src); - spec.icmp.hdr.icmp_code = (uint8_t) ntohs(match->flow.tp_dst); + spec->icmp.hdr.icmp_type = (uint8_t) ntohs(match->flow.tp_src); + spec->icmp.hdr.icmp_code = (uint8_t) ntohs(match->flow.tp_dst); - mask.icmp.hdr.icmp_type = (uint8_t) ntohs(match->wc.masks.tp_src); - mask.icmp.hdr.icmp_code = (uint8_t) ntohs(match->wc.masks.tp_dst); + mask->icmp.hdr.icmp_type = (uint8_t) ntohs(match->wc.masks.tp_src); + mask->icmp.hdr.icmp_code = (uint8_t) ntohs(match->wc.masks.tp_dst); - add_flow_pattern(&patterns, RTE_FLOW_ITEM_TYPE_ICMP, - &spec.icmp, &mask.icmp); + add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_ICMP, + &spec->icmp, &mask->icmp); /* proto == ICMP and ITEM_TYPE_ICMP, thus no need for proto match. */ - mask.ipv4.hdr.next_proto_id = 0; + mask->ipv4.hdr.next_proto_id = 0; break; } - add_flow_pattern(&patterns, RTE_FLOW_ITEM_TYPE_END, NULL, NULL); + add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_END, NULL, NULL); + + return 0; +} + +static int +netdev_offload_dpdk_add_flow(struct netdev *netdev, + const struct match *match, + struct nlattr *nl_actions OVS_UNUSED, + size_t actions_len OVS_UNUSED, + const ovs_u128 *ufid, + struct offload_info *info) +{ + const struct rte_flow_attr flow_attr = { + .group = 0, + .priority = 0, + .ingress = 1, + .egress = 0 + }; + struct flow_patterns patterns = { .items = NULL, .cnt = 0 }; + struct flow_actions actions = { .actions = NULL, .cnt = 0 }; + struct rte_flow *flow; + struct rte_flow_error error; + int ret = 0; + struct flow_items spec, mask; + + memset(&spec, 0, sizeof spec); + memset(&mask, 0, sizeof mask); + + ret = parse_flow_match(&patterns, &spec, &mask, match); + if (ret) { + goto out; + } struct rte_flow_action_mark mark; struct action_rss_data *rss;