From patchwork Mon Jan 20 15:08:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eli Britstein X-Patchwork-Id: 1226036 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.138; helo=whitealder.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 whitealder.osuosl.org (smtp1.osuosl.org [140.211.166.138]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 481Zq80XYxz9sRk for ; Tue, 21 Jan 2020 02:10:28 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id 2E3A887635; Mon, 20 Jan 2020 15:10:26 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org Received: from whitealder.osuosl.org ([127.0.0.1]) by localhost (.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id E3dkFRIH2p68; Mon, 20 Jan 2020 15:10:19 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by whitealder.osuosl.org (Postfix) with ESMTP id 9772A85C45; Mon, 20 Jan 2020 15:09:17 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 7A44EC1D8D; Mon, 20 Jan 2020 15:09:17 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133]) by lists.linuxfoundation.org (Postfix) with ESMTP id 6CDCAC1D89 for ; Mon, 20 Jan 2020 15:09:03 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by hemlock.osuosl.org (Postfix) with ESMTP id 5924A875CB for ; Mon, 20 Jan 2020 15:09:03 +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 WMnHFIfKdymo for ; Mon, 20 Jan 2020 15:08:57 +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 hemlock.osuosl.org (Postfix) with ESMTP id A8D0E875C2 for ; Mon, 20 Jan 2020 15:08:50 +0000 (UTC) Received: from Internal Mail-Server by MTLPINE1 (envelope-from elibr@mellanox.com) with ESMTPS (AES256-SHA encrypted); 20 Jan 2020 17:08:46 +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 00KF8hVF013116; Mon, 20 Jan 2020 17:08:46 +0200 From: Eli Britstein To: dev@openvswitch.org, Ilya Maximets Date: Mon, 20 Jan 2020 15:08:30 +0000 Message-Id: <20200120150830.16262-26-elibr@mellanox.com> X-Mailer: git-send-email 2.14.5 In-Reply-To: <20200120150830.16262-1-elibr@mellanox.com> References: <20200120150830.16262-1-elibr@mellanox.com> Cc: Simon Horman , Eli Britstein , Ameer Mahagneh Subject: [ovs-dev] [PATCH 25/25] netdev-offload-dpdk: Support offload for vxlan vport 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" From: Ophir Munk For virtual port (as "vxlan"), HW rules match tunnel properties (outer header) and inner packet fields, and with a decap action. The rules are placed on all uplinks as they are the potential for the origin of the traffic. Co-authored-by: Eli Britstein Signed-off-by: Ophir Munk Reviewed-by: Roni Bar Yanai Signed-off-by: Eli Britstein --- Documentation/howto/dpdk.rst | 1 + NEWS | 1 + lib/netdev-offload-dpdk.c | 122 ++++++++++++++++++++++++++++++++++++++----- 3 files changed, 110 insertions(+), 14 deletions(-) diff --git a/Documentation/howto/dpdk.rst b/Documentation/howto/dpdk.rst index ea00b4a94..c12941cb8 100644 --- a/Documentation/howto/dpdk.rst +++ b/Documentation/howto/dpdk.rst @@ -397,6 +397,7 @@ Supported actions for hardware offload are: - Modification of TCP/UDP (mod_tp_src/mod_tp_dst). - Clone/output (tnl_push and output) for encapsulating over a tunnel. - Tunnel pop, for changing from PF port to vport. +- Offloading VXLAN vport. Further Reading --------------- diff --git a/NEWS b/NEWS index d7f9a1e18..24366369e 100644 --- a/NEWS +++ b/NEWS @@ -32,6 +32,7 @@ Post-v2.12.0 TCP/UDP ports and tunnel push-output/pop actions (experimental). * Add experimental support for TSO. * Add hardware offload support for matching IPv6 protocol. + * Add hardware offload support VXLAN vports. - RSTP: * The rstp_statistics column in Port table will only be updated every stats-update-interval configured in Open_vSwitch table. diff --git a/lib/netdev-offload-dpdk.c b/lib/netdev-offload-dpdk.c index 5e8ed33f7..2fd840ed4 100644 --- a/lib/netdev-offload-dpdk.c +++ b/lib/netdev-offload-dpdk.c @@ -59,6 +59,7 @@ static struct cmap ufid_to_rte_flow = CMAP_INITIALIZER; struct act_resources { uint32_t next_table_id; + uint32_t self_table_id; uint32_t flow_miss_ctx_id; }; @@ -436,6 +437,7 @@ find_flow_miss_ctx(int flow_ctx_id, struct flow_miss_ctx *ctx) static void put_action_resources(struct act_resources *act_resources) { + put_table_id(act_resources->self_table_id); put_table_id(act_resources->next_table_id); put_flow_miss_ctx_id(act_resources->flow_miss_ctx_id); } @@ -819,6 +821,8 @@ dump_flow_action(struct ds *s, const struct rte_flow_action *actions) if (jump) { ds_put_format(s, " Jump: group=%"PRIu32"\n", jump->group); } + } else if (actions->type == RTE_FLOW_ACTION_TYPE_VXLAN_DECAP) { + ds_put_cstr(s, "rte flow vxlan-decap action\n"); } else { ds_put_format(s, "unknown rte flow action (%d)\n", actions->type); } @@ -1093,7 +1097,8 @@ parse_vxlan_match(struct flow_patterns *patterns, static int parse_flow_match(struct netdev *netdev, struct flow_patterns *patterns, - struct match *match) + struct match *match, + struct act_resources *act_resources) { uint8_t *next_proto_mask = NULL; struct flow *consumed_masks; @@ -1108,6 +1113,14 @@ parse_flow_match(struct netdev *netdev, goto out; } + if (netdev_vport_is_vport_class(netdev->netdev_class)) { + ret = get_table_id(match->flow.in_port.odp_port, + &act_resources->self_table_id); + if (ret) { + goto out; + } + } + memset(&consumed_masks->in_port, 0, sizeof consumed_masks->in_port); if (match->flow.recirc_id != 0) { ret = -1; @@ -1764,6 +1777,12 @@ add_tnl_pop_action(struct flow_actions *actions, return 0; } +static void +add_vxlan_decap_action(struct flow_actions *actions) +{ + add_flow_action(actions, RTE_FLOW_ACTION_TYPE_VXLAN_DECAP, NULL); +} + static int parse_flow_actions(struct netdev *netdev, struct flow_actions *actions, @@ -1774,6 +1793,9 @@ parse_flow_actions(struct netdev *netdev, struct nlattr *nla; size_t left; + if (!strcmp(netdev_get_type(netdev), "vxlan")) { + add_vxlan_decap_action(actions); + } add_count_action(actions); NL_ATTR_FOR_EACH_UNSAFE (nla, left, nl_actions, nl_actions_len) { if (nl_attr_type(nla) == OVS_ACTION_ATTR_OUTPUT) { @@ -1781,6 +1803,8 @@ parse_flow_actions(struct netdev *netdev, return -1; } } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_DROP) { + free_flow_actions(actions); + add_count_action(actions); add_flow_action(actions, RTE_FLOW_ACTION_TYPE_DROP, NULL); } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_SET || nl_attr_type(nla) == OVS_ACTION_ATTR_SET_MASKED) { @@ -1819,16 +1843,67 @@ parse_flow_actions(struct netdev *netdev, return 0; } +static int +netdev_offload_dpdk_create_tnl_flows(struct netdev *netdev, + struct flow_patterns *patterns, + struct flow_actions *actions, + const ovs_u128 *ufid, + struct act_resources *act_resources, + struct flows_handle *flows) +{ + struct rte_flow_attr flow_attr = { .ingress = 1, .transfer = 1 }; + struct flow_item flow_item = { .devargs = NULL }; + struct netdev_flow_dump **netdev_dumps; + struct rte_flow_error error; + int num_ports = 0; + int ret; + int i; + + netdev_dumps = netdev_ports_flow_dump_create(netdev->dpif_type, + &num_ports); + flow_attr.group = act_resources->self_table_id; + for (i = 0; i < num_ports; i++) { + if (!netdev_dpdk_is_uplink_port(netdev_dumps[i]->netdev)) { + continue; + } + ret = netdev_offload_dpdk_flow_create(netdev_dumps[i]->netdev, + &flow_attr, patterns->items, + actions->actions, &error, + &flow_item); + if (ret) { + continue; + } + flow_item.devargs = + netdev_dpdk_get_port_devargs(netdev_dumps[i]->netdev); + VLOG_DBG_RL(&rl, "%s: installed flow %p by ufid "UUID_FMT"\n", + netdev_get_name(netdev), flow_item.rte_flow, + UUID_ARGS((struct uuid *)ufid)); + add_flow_item(flows, &flow_item); + } + for (i = 0; i < num_ports; i++) { + int err = netdev_flow_dump_destroy(netdev_dumps[i]); + + if (err != 0 && err != EOPNOTSUPP) { + VLOG_ERR("failed dumping netdev: %s", ovs_strerror(err)); + } + } + + ret = flows->cnt > 0 ? 0 : -1; + return ret; +} + static int netdev_offload_dpdk_actions(struct netdev *netdev, struct flow_patterns *patterns, struct nlattr *nl_actions, size_t actions_len, + const ovs_u128 *ufid, struct act_resources *act_resources, - struct flow_item *fi) + struct flows_handle *flows) { const struct rte_flow_attr flow_attr = { .ingress = 1, .transfer = 1 }; struct flow_actions actions = { .actions = NULL, .cnt = 0 }; + struct flow_item flow_item = { .devargs = NULL }; struct rte_flow_error error; int ret; @@ -1837,8 +1912,22 @@ netdev_offload_dpdk_actions(struct netdev *netdev, if (ret) { goto out; } - ret = netdev_offload_dpdk_flow_create(netdev, &flow_attr, patterns->items, - actions.actions, &error, fi); + if (netdev_vport_is_vport_class(netdev->netdev_class)) { + ret = netdev_offload_dpdk_create_tnl_flows(netdev, patterns, &actions, + ufid, act_resources, flows); + } else { + ret = netdev_offload_dpdk_flow_create(netdev, &flow_attr, + patterns->items, + actions.actions, &error, + &flow_item); + if (ret) { + goto out; + } + VLOG_DBG_RL(&rl, "%s: installed flow %p by ufid "UUID_FMT"\n", + netdev_get_name(netdev), flow_item.rte_flow, + UUID_ARGS((struct uuid *)ufid)); + add_flow_item(flows, &flow_item); + } out: free_flow_actions(&actions); return ret; @@ -1857,36 +1946,41 @@ netdev_offload_dpdk_add_flow(struct netdev *netdev, struct flow_item flow_item = { .devargs = NULL }; struct act_resources act_resources; bool actions_offloaded = true; - int ret = 0; + int ret; memset(&act_resources, 0, sizeof act_resources); - ret = parse_flow_match(netdev, &patterns, match); + ret = parse_flow_match(netdev, &patterns, match, &act_resources); if (ret) { goto out; } ret = netdev_offload_dpdk_actions(netdev, &patterns, nl_actions, - actions_len, &act_resources, &flow_item); + actions_len, ufid, &act_resources, + &flows); if (ret) { /* If we failed to offload the rule actions fallback to MARK+RSS * actions. */ - flow_item.rte_flow = netdev_offload_dpdk_mark_rss(&patterns, netdev, - info->flow_mark); - ret = flow_item.rte_flow ? 0 : -1; actions_offloaded = false; + flow_item.rte_flow = act_resources.self_table_id == 0 ? + netdev_offload_dpdk_mark_rss(&patterns, netdev, info->flow_mark) : + NULL; + ret = flow_item.rte_flow ? 0 : -1; + if (ret) { + goto out; + } + VLOG_DBG_RL(&rl, "%s: installed flow %p by ufid "UUID_FMT"\n", + netdev_get_name(netdev), flow_item.rte_flow, + UUID_ARGS((struct uuid *)ufid)); + add_flow_item(&flows, &flow_item); } if (ret) { goto out; } - add_flow_item(&flows, &flow_item); ufid_to_rte_flow_associate(ufid, &flows, actions_offloaded, &act_resources); - VLOG_DBG("%s: installed flow %p by ufid "UUID_FMT"\n", - netdev_get_name(netdev), flow_item.rte_flow, - UUID_ARGS((struct uuid *)ufid)); out: if (ret) {