From patchwork Thu Dec 19 11:54:21 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eli Britstein X-Patchwork-Id: 1213256 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.136; helo=silver.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 silver.osuosl.org (smtp3.osuosl.org [140.211.166.136]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 47dr0s4Nr2z9sPn for ; Thu, 19 Dec 2019 22:55:25 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by silver.osuosl.org (Postfix) with ESMTP id F02D923A18; Thu, 19 Dec 2019 11:55:23 +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 maWIMfUUfCSt; Thu, 19 Dec 2019 11:55:16 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by silver.osuosl.org (Postfix) with ESMTP id 1AAF7234AC; Thu, 19 Dec 2019 11:54:57 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 04DCCC1D81; Thu, 19 Dec 2019 11:54:57 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137]) by lists.linuxfoundation.org (Postfix) with ESMTP id CA67EC1D81 for ; Thu, 19 Dec 2019 11:54:49 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by fraxinus.osuosl.org (Postfix) with ESMTP id C2FD686E92 for ; Thu, 19 Dec 2019 11:54:49 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from fraxinus.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id vl8xqh_LVTxM for ; Thu, 19 Dec 2019 11:54:48 +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 fraxinus.osuosl.org (Postfix) with ESMTP id 59A0486D7B for ; Thu, 19 Dec 2019 11:54:47 +0000 (UTC) Received: from Internal Mail-Server by MTLPINE1 (envelope-from elibr@mellanox.com) with ESMTPS (AES256-SHA encrypted); 19 Dec 2019 13:54:41 +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 xBJBserL014710; Thu, 19 Dec 2019 13:54:40 +0200 From: Eli Britstein To: dev@openvswitch.org, Ilya Maximets Date: Thu, 19 Dec 2019 11:54:21 +0000 Message-Id: <20191219115436.10354-4-elibr@mellanox.com> X-Mailer: git-send-email 2.14.5 In-Reply-To: <20191219115436.10354-1-elibr@mellanox.com> References: <20191219115436.10354-1-elibr@mellanox.com> Cc: Oz Shlomo , Simon Horman , Majd Dibbiny , Eli Britstein , Ameer Mahagneh Subject: [ovs-dev] [PATCH V6 03/18] netdev-offload-dpdk: Dynamically allocate pattern items 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" Instead of statically allocated pattern items on the stack, dynamically allocate only the required items while parsing the matches, to simplify the parsing and make it self-contained, without need of external types, making it easier to support more matches in the future. Signed-off-by: Eli Britstein Reviewed-by: Oz Shlomo --- lib/netdev-offload-dpdk.c | 206 ++++++++++++++++++++++++++-------------------- 1 file changed, 118 insertions(+), 88 deletions(-) diff --git a/lib/netdev-offload-dpdk.c b/lib/netdev-offload-dpdk.c index 89828224a..a5bc4ad33 100644 --- a/lib/netdev-offload-dpdk.c +++ b/lib/netdev-offload-dpdk.c @@ -374,6 +374,24 @@ add_flow_action(struct flow_actions *actions, enum rte_flow_action_type type, actions->cnt++; } +static void +free_flow_patterns(struct flow_patterns *patterns) +{ + int i; + + for (i = 0; i < patterns->cnt; i++) { + if (patterns->items[i].spec) { + free(CONST_CAST(void *, patterns->items[i].spec)); + } + if (patterns->items[i].mask) { + free(CONST_CAST(void *, patterns->items[i].mask)); + } + } + free(patterns->items); + patterns->items = NULL; + patterns->cnt = 0; +} + static void free_flow_actions(struct flow_actions *actions) { @@ -389,39 +407,30 @@ free_flow_actions(struct flow_actions *actions) actions->cnt = 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; - }; -}; - static int parse_flow_match(struct flow_patterns *patterns, - struct flow_items *spec, - struct flow_items *mask, const struct match *match) { + uint8_t *next_proto_mask = NULL; uint8_t proto = 0; /* 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; + struct rte_flow_item_eth *spec, *mask; + + spec = xzalloc(sizeof *spec); + mask = xzalloc(sizeof *mask); + + memcpy(&spec->dst, &match->flow.dl_dst, sizeof spec->dst); + memcpy(&spec->src, &match->flow.dl_src, sizeof spec->src); + spec->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->dst, &match->wc.masks.dl_dst, sizeof mask->dst); + memcpy(&mask->src, &match->wc.masks.dl_src, sizeof mask->src); + mask->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, mask); } else { /* * If user specifies a flow (like UDP flow) without L2 patterns, @@ -435,36 +444,45 @@ parse_flow_match(struct flow_patterns *patterns, /* 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); + struct rte_flow_item_vlan *spec, *mask; + + spec = xzalloc(sizeof *spec); + mask = xzalloc(sizeof *mask); + + spec->tci = match->flow.vlans[0].tci & ~htons(VLAN_CFI); + mask->tci = match->wc.masks.vlans[0].tci & ~htons(VLAN_CFI); /* Match any protocols. */ - mask->vlan.inner_type = 0; + mask->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, mask); } /* 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; + struct rte_flow_item_ipv4 *spec, *mask; + + spec = xzalloc(sizeof *spec); + mask = xzalloc(sizeof *mask); + + spec->hdr.type_of_service = match->flow.nw_tos; + spec->hdr.time_to_live = match->flow.nw_ttl; + spec->hdr.next_proto_id = match->flow.nw_proto; + spec->hdr.src_addr = match->flow.nw_src; + spec->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->hdr.type_of_service = match->wc.masks.nw_tos; + mask->hdr.time_to_live = match->wc.masks.nw_ttl; + mask->hdr.next_proto_id = match->wc.masks.nw_proto; + mask->hdr.src_addr = match->wc.masks.nw_src; + mask->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, mask); /* Save proto for L4 protocol setup. */ - proto = spec->ipv4.hdr.next_proto_id & - mask->ipv4.hdr.next_proto_id; + proto = spec->hdr.next_proto_id & + mask->hdr.next_proto_id; + next_proto_mask = &mask->hdr.next_proto_id; } if (proto != IPPROTO_ICMP && proto != IPPROTO_UDP && @@ -481,66 +499,82 @@ parse_flow_match(struct flow_patterns *patterns, 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; + if (proto == IPPROTO_TCP) { + struct rte_flow_item_tcp *spec, *mask; - 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; + spec = xzalloc(sizeof *spec); + mask = xzalloc(sizeof *mask); - add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_TCP, - &spec->tcp, &mask->tcp); + spec->hdr.src_port = match->flow.tp_src; + spec->hdr.dst_port = match->flow.tp_dst; + spec->hdr.data_off = ntohs(match->flow.tcp_flags) >> 8; + spec->hdr.tcp_flags = ntohs(match->flow.tcp_flags) & 0xff; + + mask->hdr.src_port = match->wc.masks.tp_src; + mask->hdr.dst_port = match->wc.masks.tp_dst; + mask->hdr.data_off = ntohs(match->wc.masks.tcp_flags) >> 8; + mask->hdr.tcp_flags = ntohs(match->wc.masks.tcp_flags) & 0xff; + + add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_TCP, spec, mask); /* proto == TCP and ITEM_TYPE_TCP, thus no need for proto match. */ - mask->ipv4.hdr.next_proto_id = 0; - break; + if (next_proto_mask) { + *next_proto_mask = 0; + } + } else if (proto == IPPROTO_UDP) { + struct rte_flow_item_udp *spec, *mask; - case IPPROTO_UDP: - spec->udp.hdr.src_port = match->flow.tp_src; - spec->udp.hdr.dst_port = match->flow.tp_dst; + spec = xzalloc(sizeof *spec); + mask = xzalloc(sizeof *mask); - mask->udp.hdr.src_port = match->wc.masks.tp_src; - mask->udp.hdr.dst_port = match->wc.masks.tp_dst; + spec->hdr.src_port = match->flow.tp_src; + spec->hdr.dst_port = match->flow.tp_dst; - add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_UDP, - &spec->udp, &mask->udp); + mask->hdr.src_port = match->wc.masks.tp_src; + mask->hdr.dst_port = match->wc.masks.tp_dst; + + add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_UDP, spec, mask); /* proto == UDP and ITEM_TYPE_UDP, thus no need for proto match. */ - mask->ipv4.hdr.next_proto_id = 0; - break; + if (next_proto_mask) { + *next_proto_mask = 0; + } + } else if (proto == IPPROTO_SCTP) { + struct rte_flow_item_sctp *spec, *mask; - case IPPROTO_SCTP: - spec->sctp.hdr.src_port = match->flow.tp_src; - spec->sctp.hdr.dst_port = match->flow.tp_dst; + spec = xzalloc(sizeof *spec); + mask = xzalloc(sizeof *mask); - mask->sctp.hdr.src_port = match->wc.masks.tp_src; - mask->sctp.hdr.dst_port = match->wc.masks.tp_dst; + spec->hdr.src_port = match->flow.tp_src; + spec->hdr.dst_port = match->flow.tp_dst; - add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_SCTP, - &spec->sctp, &mask->sctp); + mask->hdr.src_port = match->wc.masks.tp_src; + mask->hdr.dst_port = match->wc.masks.tp_dst; + + add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_SCTP, spec, mask); /* proto == SCTP and ITEM_TYPE_SCTP, thus no need for proto match. */ - mask->ipv4.hdr.next_proto_id = 0; - break; + if (next_proto_mask) { + *next_proto_mask = 0; + } + } else if (proto == IPPROTO_ICMP) { + struct rte_flow_item_icmp *spec, *mask; - 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 = xzalloc(sizeof *spec); + mask = xzalloc(sizeof *mask); - 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); + spec->hdr.icmp_type = (uint8_t) ntohs(match->flow.tp_src); + spec->hdr.icmp_code = (uint8_t) ntohs(match->flow.tp_dst); - add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_ICMP, - &spec->icmp, &mask->icmp); + mask->hdr.icmp_type = (uint8_t) ntohs(match->wc.masks.tp_src); + mask->hdr.icmp_code = (uint8_t) ntohs(match->wc.masks.tp_dst); + + add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_ICMP, spec, mask); /* proto == ICMP and ITEM_TYPE_ICMP, thus no need for proto match. */ - mask->ipv4.hdr.next_proto_id = 0; - break; + if (next_proto_mask) { + *next_proto_mask = 0; + } } add_flow_pattern(patterns, RTE_FLOW_ITEM_TYPE_END, NULL, NULL); @@ -608,12 +642,8 @@ netdev_offload_dpdk_add_flow(struct netdev *netdev, 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); + ret = parse_flow_match(&patterns, match); if (ret) { goto out; } @@ -635,7 +665,7 @@ netdev_offload_dpdk_add_flow(struct netdev *netdev, netdev_get_name(netdev), flow, UUID_ARGS((struct uuid *)ufid)); out: - free(patterns.items); + free_flow_patterns(&patterns); free_flow_actions(&actions); return ret; }