From patchwork Fri Jan 22 05:38:06 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Mi X-Patchwork-Id: 1430170 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=) 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 4DMSjd06GMz9sCD for ; Fri, 22 Jan 2021 16:38:45 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by silver.osuosl.org (Postfix) with ESMTP id 8A14B27A49; Fri, 22 Jan 2021 05:38:42 +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 sGv-W29zQBLj; Fri, 22 Jan 2021 05:38:33 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by silver.osuosl.org (Postfix) with ESMTP id 1D96D227DB; Fri, 22 Jan 2021 05:38:32 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id E09D4C1DA8; Fri, 22 Jan 2021 05:38:31 +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 6B9E4C1DA7 for ; Fri, 22 Jan 2021 05:38:28 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by fraxinus.osuosl.org (Postfix) with ESMTP id 5FDDA8600D for ; Fri, 22 Jan 2021 05:38:28 +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 ZOXTHrr2qswr for ; Fri, 22 Jan 2021 05:38:27 +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 3390285FEF for ; Fri, 22 Jan 2021 05:38:26 +0000 (UTC) Received: from Internal Mail-Server by MTLPINE1 (envelope-from cmi@nvidia.com) with SMTP; 22 Jan 2021 07:38:22 +0200 Received: from dev-r630-03.mtbc.labs.mlnx (dev-r630-03.mtbc.labs.mlnx [10.75.205.13]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 10M5cJ3i020652; Fri, 22 Jan 2021 07:38:21 +0200 From: Chris Mi To: dev@openvswitch.org Date: Fri, 22 Jan 2021 13:38:06 +0800 Message-Id: <20210122053816.174632-2-cmi@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210122053816.174632-1-cmi@nvidia.com> References: <20210122053816.174632-1-cmi@nvidia.com> MIME-Version: 1.0 Cc: elibr@nvidia.com, roniba@nvidia.com, i.maximets@ovn.org Subject: [ovs-dev] [PATCH v10 01/11] compat: Add psample and tc sample action defines for older kernels 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: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" Update kernel UAPI to support psample and the tc sample action. Signed-off-by: Chris Mi Reviewed-by: Eli Britstein Acked-by: Eelco Chaudron --- include/linux/automake.mk | 4 ++- include/linux/psample.h | 58 ++++++++++++++++++++++++++++++++ include/linux/tc_act/tc_sample.h | 25 ++++++++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 include/linux/psample.h create mode 100644 include/linux/tc_act/tc_sample.h diff --git a/include/linux/automake.mk b/include/linux/automake.mk index 8f063f482..c48d9699a 100644 --- a/include/linux/automake.mk +++ b/include/linux/automake.mk @@ -7,4 +7,6 @@ noinst_HEADERS += \ include/linux/tc_act/tc_skbedit.h \ include/linux/tc_act/tc_tunnel_key.h \ include/linux/tc_act/tc_vlan.h \ - include/linux/tc_act/tc_ct.h + include/linux/tc_act/tc_ct.h \ + include/linux/tc_act/tc_sample.h \ + include/linux/psample.h diff --git a/include/linux/psample.h b/include/linux/psample.h new file mode 100644 index 000000000..aea26ab14 --- /dev/null +++ b/include/linux/psample.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef __UAPI_PSAMPLE_H +#define __UAPI_PSAMPLE_H + +enum { + /* sampled packet metadata */ + PSAMPLE_ATTR_IIFINDEX, + PSAMPLE_ATTR_OIFINDEX, + PSAMPLE_ATTR_ORIGSIZE, + PSAMPLE_ATTR_SAMPLE_GROUP, + PSAMPLE_ATTR_GROUP_SEQ, + PSAMPLE_ATTR_SAMPLE_RATE, + PSAMPLE_ATTR_DATA, + PSAMPLE_ATTR_TUNNEL, + + /* commands attributes */ + PSAMPLE_ATTR_GROUP_REFCOUNT, + + __PSAMPLE_ATTR_MAX +}; + +enum psample_command { + PSAMPLE_CMD_SAMPLE, + PSAMPLE_CMD_GET_GROUP, + PSAMPLE_CMD_NEW_GROUP, + PSAMPLE_CMD_DEL_GROUP, +}; + +enum psample_tunnel_key_attr { + PSAMPLE_TUNNEL_KEY_ATTR_ID, /* be64 Tunnel ID */ + PSAMPLE_TUNNEL_KEY_ATTR_IPV4_SRC, /* be32 src IP address. */ + PSAMPLE_TUNNEL_KEY_ATTR_IPV4_DST, /* be32 dst IP address. */ + PSAMPLE_TUNNEL_KEY_ATTR_TOS, /* u8 Tunnel IP ToS. */ + PSAMPLE_TUNNEL_KEY_ATTR_TTL, /* u8 Tunnel IP TTL. */ + PSAMPLE_TUNNEL_KEY_ATTR_DONT_FRAGMENT, /* No argument, set DF. */ + PSAMPLE_TUNNEL_KEY_ATTR_CSUM, /* No argument. CSUM packet. */ + PSAMPLE_TUNNEL_KEY_ATTR_OAM, /* No argument. OAM frame. */ + PSAMPLE_TUNNEL_KEY_ATTR_GENEVE_OPTS, /* Array of Geneve options. */ + PSAMPLE_TUNNEL_KEY_ATTR_TP_SRC, /* be16 src Transport Port. */ + PSAMPLE_TUNNEL_KEY_ATTR_TP_DST, /* be16 dst Transport Port. */ + PSAMPLE_TUNNEL_KEY_ATTR_VXLAN_OPTS, /* Nested VXLAN opts* */ + PSAMPLE_TUNNEL_KEY_ATTR_IPV6_SRC, /* struct in6_addr src IPv6 address. */ + PSAMPLE_TUNNEL_KEY_ATTR_IPV6_DST, /* struct in6_addr dst IPv6 address. */ + PSAMPLE_TUNNEL_KEY_ATTR_PAD, + PSAMPLE_TUNNEL_KEY_ATTR_ERSPAN_OPTS, /* struct erspan_metadata */ + PSAMPLE_TUNNEL_KEY_ATTR_IPV4_INFO_BRIDGE, /* No argument. IPV4_INFO_BRIDGE mode.*/ + __PSAMPLE_TUNNEL_KEY_ATTR_MAX +}; + +/* Can be overridden at runtime by module option */ +#define PSAMPLE_ATTR_MAX (__PSAMPLE_ATTR_MAX - 1) + +#define PSAMPLE_NL_MCGRP_CONFIG_NAME "config" +#define PSAMPLE_NL_MCGRP_SAMPLE_NAME "packets" +#define PSAMPLE_GENL_NAME "psample" +#define PSAMPLE_GENL_VERSION 1 + +#endif diff --git a/include/linux/tc_act/tc_sample.h b/include/linux/tc_act/tc_sample.h new file mode 100644 index 000000000..fee1bcc20 --- /dev/null +++ b/include/linux/tc_act/tc_sample.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef __LINUX_TC_SAMPLE_H +#define __LINUX_TC_SAMPLE_H + +#include +#include +#include + +struct tc_sample { + tc_gen; +}; + +enum { + TCA_SAMPLE_UNSPEC, + TCA_SAMPLE_TM, + TCA_SAMPLE_PARMS, + TCA_SAMPLE_RATE, + TCA_SAMPLE_TRUNC_SIZE, + TCA_SAMPLE_PSAMPLE_GROUP, + TCA_SAMPLE_PAD, + __TCA_SAMPLE_MAX +}; +#define TCA_SAMPLE_MAX (__TCA_SAMPLE_MAX - 1) + +#endif From patchwork Fri Jan 22 05:38:07 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Mi X-Patchwork-Id: 1430168 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=) 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 4DMSjV5w7dz9sS8 for ; Fri, 22 Jan 2021 16:38:37 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by silver.osuosl.org (Postfix) with ESMTP id 015A622844; Fri, 22 Jan 2021 05:38:35 +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 TJ2rkzpH26Wi; Fri, 22 Jan 2021 05:38:31 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by silver.osuosl.org (Postfix) with ESMTP id 25C32226EA; Fri, 22 Jan 2021 05:38:31 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 0B271C088B; Fri, 22 Jan 2021 05:38:31 +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 4B733C013A for ; Fri, 22 Jan 2021 05:38:28 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by fraxinus.osuosl.org (Postfix) with ESMTP id 3090686081 for ; Fri, 22 Jan 2021 05:38:28 +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 H5aYBoAo9K6l for ; Fri, 22 Jan 2021 05:38:27 +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 34A038600D for ; Fri, 22 Jan 2021 05:38:26 +0000 (UTC) Received: from Internal Mail-Server by MTLPINE1 (envelope-from cmi@nvidia.com) with SMTP; 22 Jan 2021 07:38:24 +0200 Received: from dev-r630-03.mtbc.labs.mlnx (dev-r630-03.mtbc.labs.mlnx [10.75.205.13]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 10M5cJ3j020652; Fri, 22 Jan 2021 07:38:23 +0200 From: Chris Mi To: dev@openvswitch.org Date: Fri, 22 Jan 2021 13:38:07 +0800 Message-Id: <20210122053816.174632-3-cmi@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210122053816.174632-1-cmi@nvidia.com> References: <20210122053816.174632-1-cmi@nvidia.com> MIME-Version: 1.0 Cc: elibr@nvidia.com, roniba@nvidia.com, i.maximets@ovn.org Subject: [ovs-dev] [PATCH v10 02/11] ovs-kmod-ctl: Load kernel module psample 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: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" Load kernel module psample to receive sampled packets from TC. Before removing kernel module psample, remove act_sample first. Signed-off-by: Chris Mi Reviewed-by: Eli Britstein Acked-by: Eelco Chaudron --- utilities/ovs-kmod-ctl.in | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/utilities/ovs-kmod-ctl.in b/utilities/ovs-kmod-ctl.in index 19f100964..6fa945a83 100644 --- a/utilities/ovs-kmod-ctl.in +++ b/utilities/ovs-kmod-ctl.in @@ -28,6 +28,14 @@ for dir in "$sbindir" "$bindir" /sbin /bin /usr/sbin /usr/bin; do done insert_mods () { + # Try loading psample kernel module. + modinfo psample > /dev/null 2>&1 + if test $? = 0; then + action "Inserting psample module" modprobe psample + else + log_warning_msg "No psample module, can't offload sFlow action" + fi + # Try loading openvswitch kernel module. action "Inserting openvswitch module" modprobe openvswitch } @@ -95,6 +103,12 @@ remove_kmods() { if test -e /sys/module/vxlan; then action "Forcing removal of vxlan module" rmmod vxlan fi + if test -e /sys/module/act_sample; then + action "Forcing removal of act_sample module" rmmod act_sample + fi + if test -e /sys/module/psample; then + action "Forcing removal of psample module" rmmod psample + fi } usage () { From patchwork Fri Jan 22 05:38:08 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Mi X-Patchwork-Id: 1430167 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.137; helo=fraxinus.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4DMSjT6bScz9sCD for ; Fri, 22 Jan 2021 16:38:37 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by fraxinus.osuosl.org (Postfix) with ESMTP id 114EF868CF; Fri, 22 Jan 2021 05:38:36 +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 M9l884Rr-B70; Fri, 22 Jan 2021 05:38:34 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by fraxinus.osuosl.org (Postfix) with ESMTP id BBB44868CB; Fri, 22 Jan 2021 05:38:34 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id AEE0DC1786; Fri, 22 Jan 2021 05:38:34 +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 B78DEC013A for ; Fri, 22 Jan 2021 05:38:33 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by fraxinus.osuosl.org (Postfix) with ESMTP id AD64C868B5 for ; Fri, 22 Jan 2021 05:38:33 +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 YiL-JPowqCEk for ; Fri, 22 Jan 2021 05:38:32 +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 49F7C864EC for ; Fri, 22 Jan 2021 05:38:32 +0000 (UTC) Received: from Internal Mail-Server by MTLPINE1 (envelope-from cmi@nvidia.com) with SMTP; 22 Jan 2021 07:38:26 +0200 Received: from dev-r630-03.mtbc.labs.mlnx (dev-r630-03.mtbc.labs.mlnx [10.75.205.13]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 10M5cJ3k020652; Fri, 22 Jan 2021 07:38:24 +0200 From: Chris Mi To: dev@openvswitch.org Date: Fri, 22 Jan 2021 13:38:08 +0800 Message-Id: <20210122053816.174632-4-cmi@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210122053816.174632-1-cmi@nvidia.com> References: <20210122053816.174632-1-cmi@nvidia.com> MIME-Version: 1.0 Cc: elibr@nvidia.com, roniba@nvidia.com, i.maximets@ovn.org Subject: [ovs-dev] [PATCH v10 03/11] dpif: Introduce register sFlow upcall callback API 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: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" When offloading sample action to TC, psample sends the sampled packets to userspace by a netlink message. The thread polling psample socket will translate the psample netlink message to an sFlow format and call the sFlow upcall callback to send the sFlow packet to right monitoring host. Introduce register sFlow upcall callback API. Signed-off-by: Chris Mi Reviewed-by: Eli Britstein --- lib/dpif-netdev.c | 1 + lib/dpif-netlink.c | 1 + lib/dpif-provider.h | 10 ++++++++++ lib/dpif.c | 8 ++++++++ lib/dpif.h | 23 +++++++++++++++++++++++ 5 files changed, 43 insertions(+) diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index e3fd0a07f..deb95c780 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -8469,6 +8469,7 @@ const struct dpif_class dpif_netdev_class = { dpif_netdev_register_upcall_cb, dpif_netdev_enable_upcall, dpif_netdev_disable_upcall, + NULL, /* register_sflow_upcall_cb */ dpif_netdev_get_datapath_version, dpif_netdev_ct_dump_start, dpif_netdev_ct_dump_next, diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index ceb56c685..3dcad757a 100644 --- a/lib/dpif-netlink.c +++ b/lib/dpif-netlink.c @@ -3983,6 +3983,7 @@ const struct dpif_class dpif_netlink_class = { NULL, /* register_upcall_cb */ NULL, /* enable_upcall */ NULL, /* disable_upcall */ + NULL, /* register_sflow_upcall_cb */ dpif_netlink_get_datapath_version, /* get_datapath_version */ dpif_netlink_ct_dump_start, dpif_netlink_ct_dump_next, diff --git a/lib/dpif-provider.h b/lib/dpif-provider.h index b817fceac..589f11be4 100644 --- a/lib/dpif-provider.h +++ b/lib/dpif-provider.h @@ -427,6 +427,16 @@ struct dpif_class { /* Disables upcalls if 'dpif' directly executes upcall functions. */ void (*disable_upcall)(struct dpif *); + /* When offloading sample action, psample sends the sampled packets to + * userspace by a netlink message. The thread polling psample socket + * will translate the psample netlink message to an sFlow format and call + * the sFlow upcall callback to send the sFlow packet to right monitoring + * host. + * + * Registers an upcall callback to process sFlow packet. + */ + void (*register_sflow_upcall_cb)(struct dpif *, sflow_upcall_callback *); + /* Get datapath version. Caller is responsible for freeing the string * returned. */ char *(*get_datapath_version)(void); diff --git a/lib/dpif.c b/lib/dpif.c index 56d0b4a65..c03ad6a31 100644 --- a/lib/dpif.c +++ b/lib/dpif.c @@ -1520,6 +1520,14 @@ dpif_disable_upcall(struct dpif *dpif) } } +void +dpif_register_sflow_upcall_cb(struct dpif *dpif, sflow_upcall_callback *cb) +{ + if (dpif->dpif_class->register_sflow_upcall_cb) { + dpif->dpif_class->register_sflow_upcall_cb(dpif, cb); + } +} + void dpif_print_packet(struct dpif *dpif, struct dpif_upcall *upcall) { diff --git a/lib/dpif.h b/lib/dpif.h index ecda896c7..aac0c2b46 100644 --- a/lib/dpif.h +++ b/lib/dpif.h @@ -871,6 +871,29 @@ typedef int upcall_callback(const struct dp_packet *packet, void dpif_register_upcall_cb(struct dpif *, upcall_callback *, void *aux); +/* When offloading sample action, userspace creates a unique ID to map + * sFlow action and tunnel info and passes this ID to datapath instead + * of the sFlow info. Datapath will send this ID and sampled packet to + * userspace. Using the ID, userspace can recover the sFlow info and send + * sampled packet to the right sFlow monitoring host. + */ +struct dpif_sflow_attr { + const struct nlattr *sflow; /* sFlow action */ + void *userdata; /* struct user_action_cookie */ + size_t userdata_len; /* struct user_action_cookie length */ + struct flow_tnl *tunnel; /* Tunnel info */ +}; + +/* A sampled packet passed up from datapath to userspace. */ +struct dpif_upcall_sflow { + struct dp_packet packet; /* packet data */ + uint32_t iifindex; /* input ifindex */ + const struct dpif_sflow_attr *sflow_attr; +}; + +typedef int sflow_upcall_callback(struct dpif_upcall_sflow *dupcall); +void dpif_register_sflow_upcall_cb(struct dpif *, sflow_upcall_callback *); + int dpif_recv_set(struct dpif *, bool enable); int dpif_handlers_set(struct dpif *, uint32_t n_handlers); int dpif_set_config(struct dpif *, const struct smap *cfg); From patchwork Fri Jan 22 05:38:09 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Mi X-Patchwork-Id: 1430174 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.137; helo=fraxinus.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4DMSk42Kwfz9sCD for ; Fri, 22 Jan 2021 16:39:08 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by fraxinus.osuosl.org (Postfix) with ESMTP id 92DFF86A36; Fri, 22 Jan 2021 05:38:52 +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 rNSNc3-fHcYg; Fri, 22 Jan 2021 05:38:49 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by fraxinus.osuosl.org (Postfix) with ESMTP id F309386980; Fri, 22 Jan 2021 05:38:45 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id BE0D2C1E7F; Fri, 22 Jan 2021 05:38:45 +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 B1997C1E72 for ; Fri, 22 Jan 2021 05:38:39 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by silver.osuosl.org (Postfix) with ESMTP id 985D82754C for ; Fri, 22 Jan 2021 05:38:39 +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 iNIMhGSapUuV for ; Fri, 22 Jan 2021 05:38:33 +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 7323E2281C for ; Fri, 22 Jan 2021 05:38:32 +0000 (UTC) Received: from Internal Mail-Server by MTLPINE1 (envelope-from cmi@nvidia.com) with SMTP; 22 Jan 2021 07:38:27 +0200 Received: from dev-r630-03.mtbc.labs.mlnx (dev-r630-03.mtbc.labs.mlnx [10.75.205.13]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 10M5cJ3l020652; Fri, 22 Jan 2021 07:38:26 +0200 From: Chris Mi To: dev@openvswitch.org Date: Fri, 22 Jan 2021 13:38:09 +0800 Message-Id: <20210122053816.174632-5-cmi@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210122053816.174632-1-cmi@nvidia.com> References: <20210122053816.174632-1-cmi@nvidia.com> MIME-Version: 1.0 Cc: elibr@nvidia.com, roniba@nvidia.com, i.maximets@ovn.org Subject: [ovs-dev] [PATCH v10 04/11] ofproto: Add upcall callback to process sFlow packet 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: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" When offloading sample action, dpif provider may receive packets for sFlow in a seperate channel. That means the sFlow packets will not be processed by usual upcall. Add an upcall callback, so the dpif thread polling the channel can call it to process the sFlow packet. Signed-off-by: Chris Mi Reviewed-by: Eli Britstein --- ofproto/ofproto-dpif-upcall.c | 42 +++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/ofproto/ofproto-dpif-upcall.c b/ofproto/ofproto-dpif-upcall.c index 5fae46adf..a8b888adc 100644 --- a/ofproto/ofproto-dpif-upcall.c +++ b/ofproto/ofproto-dpif-upcall.c @@ -409,6 +409,7 @@ static int udpif_flow_unprogram(struct udpif *udpif, struct udpif_key *ukey, static upcall_callback upcall_cb; static dp_purge_callback dp_purge_cb; +static sflow_upcall_callback sflow_upcall_cb; static atomic_bool enable_megaflows = ATOMIC_VAR_INIT(true); static atomic_bool enable_ufid = ATOMIC_VAR_INIT(true); @@ -463,6 +464,7 @@ udpif_create(struct dpif_backer *backer, struct dpif *dpif) dpif_register_upcall_cb(dpif, upcall_cb, udpif); dpif_register_dp_purge_cb(dpif, dp_purge_cb, udpif); + dpif_register_sflow_upcall_cb(dpif, sflow_upcall_cb); return udpif; } @@ -1345,6 +1347,46 @@ out: return error; } +int +sflow_upcall_cb(struct dpif_upcall_sflow *dupcall) +{ + const struct dpif_sflow_attr *sflow_attr = dupcall->sflow_attr; + struct user_action_cookie *cookie; + struct ofproto_dpif *ofproto; + struct dpif_sflow *sflow; + uint32_t iifindex; + struct flow flow; + + if (!sflow_attr) { + VLOG_WARN_RL(&rl, "%s: sflow_attr is NULL", __func__); + return EINVAL; + } + + cookie = sflow_attr->userdata; + ofproto = ofproto_dpif_lookup_by_uuid(&cookie->ofproto_uuid); + if (!ofproto) { + VLOG_WARN_RL(&rl, "%s: could not find ofproto", __func__); + return ENODEV; + } + + sflow = ofproto->sflow; + if (!sflow) { + VLOG_WARN_RL(&rl, "%s: could not find sflow", __func__); + return ENODEV; + } + + memset(&flow, 0, sizeof flow); + if (sflow_attr->tunnel) { + memcpy(&flow.tunnel, sflow_attr->tunnel, sizeof flow.tunnel); + } + iifindex = dupcall->iifindex; + dpif_sflow_received(sflow, &dupcall->packet, &flow, + netdev_ifindex_to_odp_port(iifindex), + cookie, NULL); + + return 0; +} + static size_t dpif_get_actions(struct udpif *udpif, struct upcall *upcall, const struct nlattr **actions) From patchwork Fri Jan 22 05:38:10 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Mi X-Patchwork-Id: 1430171 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=) 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 4DMSjf3YlKz9sCD for ; Fri, 22 Jan 2021 16:38:46 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id 0FA5C86E0A; Fri, 22 Jan 2021 05:38:45 +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 BF3NCFYGaenf; Fri, 22 Jan 2021 05:38:40 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by whitealder.osuosl.org (Postfix) with ESMTP id 9563086DE6; Fri, 22 Jan 2021 05:38:38 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 80F94C013A; Fri, 22 Jan 2021 05:38:38 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@lists.linuxfoundation.org Received: from whitealder.osuosl.org (smtp1.osuosl.org [140.211.166.138]) by lists.linuxfoundation.org (Postfix) with ESMTP id 3AB59C088B for ; Fri, 22 Jan 2021 05:38:37 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id 28E8A8575A for ; Fri, 22 Jan 2021 05:38:37 +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 IYECsQUmT3+C for ; Fri, 22 Jan 2021 05:38:33 +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 whitealder.osuosl.org (Postfix) with ESMTP id 6760B8685D for ; Fri, 22 Jan 2021 05:38:32 +0000 (UTC) Received: from Internal Mail-Server by MTLPINE1 (envelope-from cmi@nvidia.com) with SMTP; 22 Jan 2021 07:38:29 +0200 Received: from dev-r630-03.mtbc.labs.mlnx (dev-r630-03.mtbc.labs.mlnx [10.75.205.13]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 10M5cJ3m020652; Fri, 22 Jan 2021 07:38:28 +0200 From: Chris Mi To: dev@openvswitch.org Date: Fri, 22 Jan 2021 13:38:10 +0800 Message-Id: <20210122053816.174632-6-cmi@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210122053816.174632-1-cmi@nvidia.com> References: <20210122053816.174632-1-cmi@nvidia.com> MIME-Version: 1.0 Cc: elibr@nvidia.com, roniba@nvidia.com, i.maximets@ovn.org Subject: [ovs-dev] [PATCH v10 05/11] netdev-offload: Introduce register sFlow upcall callback API 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: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" Introduce register sFlow upcall callback API as a pre-step towards saving the upcall callback. Signed-off-by: Chris Mi Reviewed-by: Eli Britstein --- lib/dpif-netlink.h | 4 ++++ lib/netdev-offload-provider.h | 3 +++ lib/netdev-offload.c | 12 ++++++++++++ lib/netdev-offload.h | 3 +++ 4 files changed, 22 insertions(+) diff --git a/lib/dpif-netlink.h b/lib/dpif-netlink.h index 24294bc42..318a4c71f 100644 --- a/lib/dpif-netlink.h +++ b/lib/dpif-netlink.h @@ -21,6 +21,7 @@ #include #include +#include "dpif.h" #include "flow.h" struct ofpbuf; @@ -60,4 +61,7 @@ bool dpif_netlink_is_internal_device(const char *name); enum ovs_vport_type netdev_to_ovs_vport_type(const char *type); +typedef int dpif_netlink_sflow_upcall_callback(struct dpif_upcall_sflow + *dupcall); + #endif /* dpif-netlink.h */ diff --git a/lib/netdev-offload-provider.h b/lib/netdev-offload-provider.h index cf859d1b4..feeb3b458 100644 --- a/lib/netdev-offload-provider.h +++ b/lib/netdev-offload-provider.h @@ -87,6 +87,9 @@ struct netdev_flow_api { * Return 0 if successful, otherwise returns a positive errno value. */ int (*flow_get_n_flows)(struct netdev *, uint64_t *n_flows); + /* Registers an upcall callback to process sFlow packet */ + void (*register_nl_sflow_upcall_cb)(dpif_netlink_sflow_upcall_callback *); + /* Initializies the netdev flow api. * Return 0 if successful, otherwise returns a positive errno value. */ int (*init_flow_api)(struct netdev *); diff --git a/lib/netdev-offload.c b/lib/netdev-offload.c index 6237667c3..99b2704f6 100644 --- a/lib/netdev-offload.c +++ b/lib/netdev-offload.c @@ -693,3 +693,15 @@ netdev_set_flow_api_enabled(const struct smap *ovs_other_config) } } } + +void +netdev_regsiter_nl_sflow_upcall_cb(struct netdev *netdev, + dpif_netlink_sflow_upcall_callback *cb) +{ + const struct netdev_flow_api *flow_api = + ovsrcu_get(const struct netdev_flow_api *, &netdev->flow_api); + + if (flow_api && flow_api->register_nl_sflow_upcall_cb) { + flow_api->register_nl_sflow_upcall_cb(cb); + } +} diff --git a/lib/netdev-offload.h b/lib/netdev-offload.h index 18b48790f..5ad5463ff 100644 --- a/lib/netdev-offload.h +++ b/lib/netdev-offload.h @@ -22,6 +22,7 @@ #include "openvswitch/types.h" #include "packets.h" #include "flow.h" +#include "dpif-netlink.h" #ifdef __cplusplus extern "C" { @@ -127,6 +128,8 @@ int netdev_ports_flow_get(const char *dpif_type, struct match *match, struct ofpbuf *buf); int netdev_ports_get_n_flows(const char *dpif_type, odp_port_t port_no, uint64_t *n_flows); +void netdev_regsiter_nl_sflow_upcall_cb(struct netdev *netdev, + dpif_netlink_sflow_upcall_callback *cb); #ifdef __cplusplus } From patchwork Fri Jan 22 05:38:11 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Mi X-Patchwork-Id: 1430169 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=) 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 4DMSjc03N5z9sCD for ; Fri, 22 Jan 2021 16:38:43 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by hemlock.osuosl.org (Postfix) with ESMTP id BA526872E7; Fri, 22 Jan 2021 05:38:40 +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 xhPF3FvYaVm4; Fri, 22 Jan 2021 05:38:39 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by hemlock.osuosl.org (Postfix) with ESMTP id CCBE1872AB; Fri, 22 Jan 2021 05:38:39 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id A5925C088B; Fri, 22 Jan 2021 05:38:39 +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 5B9F9C1DA7 for ; Fri, 22 Jan 2021 05:38:38 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by fraxinus.osuosl.org (Postfix) with ESMTP id 5348E868C8 for ; Fri, 22 Jan 2021 05:38:38 +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 PQTgY8oZCz9P for ; Fri, 22 Jan 2021 05:38:38 +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 5B489868F5 for ; Fri, 22 Jan 2021 05:38:37 +0000 (UTC) Received: from Internal Mail-Server by MTLPINE1 (envelope-from cmi@nvidia.com) with SMTP; 22 Jan 2021 07:38:31 +0200 Received: from dev-r630-03.mtbc.labs.mlnx (dev-r630-03.mtbc.labs.mlnx [10.75.205.13]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 10M5cJ3n020652; Fri, 22 Jan 2021 07:38:29 +0200 From: Chris Mi To: dev@openvswitch.org Date: Fri, 22 Jan 2021 13:38:11 +0800 Message-Id: <20210122053816.174632-7-cmi@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210122053816.174632-1-cmi@nvidia.com> References: <20210122053816.174632-1-cmi@nvidia.com> MIME-Version: 1.0 Cc: elibr@nvidia.com, roniba@nvidia.com, i.maximets@ovn.org Subject: [ovs-dev] [PATCH v10 06/11] netdev-offload-tc: Implement register sFlow upcall callback API 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: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" Save the upcall callback as a pre-step towards offloading sample action to TC. Signed-off-by: Chris Mi Reviewed-by: Eli Britstein --- lib/netdev-offload-tc.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c index 717a987d1..2b08ea55e 100644 --- a/lib/netdev-offload-tc.c +++ b/lib/netdev-offload-tc.c @@ -49,6 +49,8 @@ static struct hmap tc_to_ufid = HMAP_INITIALIZER(&tc_to_ufid); static bool multi_mask_per_prio = false; static bool block_support = false; +static dpif_netlink_sflow_upcall_callback *upcall_cb; + struct netlink_field { int offset; int flower_offset; @@ -2003,6 +2005,12 @@ probe_tc_block_support(int ifindex) } } +static void +netdev_tc_register_sflow_upcall_cb(dpif_netlink_sflow_upcall_callback *cb) +{ + upcall_cb = cb; +} + static int netdev_tc_init_flow_api(struct netdev *netdev) { @@ -2063,5 +2071,6 @@ const struct netdev_flow_api netdev_offload_tc = { .flow_get = netdev_tc_flow_get, .flow_del = netdev_tc_flow_del, .flow_get_n_flows = netdev_tc_get_n_flows, + .register_nl_sflow_upcall_cb = netdev_tc_register_sflow_upcall_cb, .init_flow_api = netdev_tc_init_flow_api, }; From patchwork Fri Jan 22 05:38:12 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Mi X-Patchwork-Id: 1430172 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=) 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 4DMSjj28npz9sCD for ; Fri, 22 Jan 2021 16:38:49 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by hemlock.osuosl.org (Postfix) with ESMTP id C79E487307; Fri, 22 Jan 2021 05:38:47 +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 r+bLRmA5u4q2; Fri, 22 Jan 2021 05:38:45 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by hemlock.osuosl.org (Postfix) with ESMTP id 291AB87315; Fri, 22 Jan 2021 05:38:44 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id EB4CCC1E73; Fri, 22 Jan 2021 05:38:43 +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 C5A80C1DA7 for ; Fri, 22 Jan 2021 05:38:39 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by hemlock.osuosl.org (Postfix) with ESMTP id B5112872FA for ; Fri, 22 Jan 2021 05:38:39 +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 KVtOizGrpTvM for ; Fri, 22 Jan 2021 05:38:38 +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 71E8A872F7 for ; Fri, 22 Jan 2021 05:38:37 +0000 (UTC) Received: from Internal Mail-Server by MTLPINE1 (envelope-from cmi@nvidia.com) with SMTP; 22 Jan 2021 07:38:33 +0200 Received: from dev-r630-03.mtbc.labs.mlnx (dev-r630-03.mtbc.labs.mlnx [10.75.205.13]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 10M5cJ3o020652; Fri, 22 Jan 2021 07:38:31 +0200 From: Chris Mi To: dev@openvswitch.org Date: Fri, 22 Jan 2021 13:38:12 +0800 Message-Id: <20210122053816.174632-8-cmi@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210122053816.174632-1-cmi@nvidia.com> References: <20210122053816.174632-1-cmi@nvidia.com> MIME-Version: 1.0 Cc: elibr@nvidia.com, roniba@nvidia.com, i.maximets@ovn.org Subject: [ovs-dev] [PATCH v10 07/11] dpif-netlink: Implement register sFlow upcall callback API 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: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" Implement dpif netlink register sFlow upcall callback API. Signed-off-by: Chris Mi Reviewed-by: Eli Britstein --- lib/dpif-netlink.c | 28 +++++++++++++++++++++++++++- lib/netdev-offload.c | 18 ++++++++++++++++++ lib/netdev-offload.h | 1 + 3 files changed, 46 insertions(+), 1 deletion(-) diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index 3dcad757a..9191ea274 100644 --- a/lib/dpif-netlink.c +++ b/lib/dpif-netlink.c @@ -236,6 +236,8 @@ static unsigned int ovs_vport_mcgroup; * to using the compat interface. */ static bool ovs_tunnels_out_of_tree = true; +static sflow_upcall_callback *sflow_upcall_cb; + static int dpif_netlink_init(void); static int open_dpif(const struct dpif_netlink_dp *, struct dpif **); static uint32_t dpif_netlink_port_get_pid(const struct dpif *, @@ -2825,6 +2827,30 @@ dpif_netlink_recv_purge(struct dpif *dpif_) fat_rwlock_unlock(&dpif->upcall_lock); } +static int +dpif_netlink_sflow_upcall_cb(struct dpif_upcall_sflow *dupcall) +{ + return sflow_upcall_cb(dupcall); +} + +static void +dpif_netlink_register_sflow_upcall_cb(struct dpif *dpif, + sflow_upcall_callback *cb) +{ + const char *dpif_type_str = dpif_normalize_type(dpif_type(dpif)); + struct netdev *dev; + + sflow_upcall_cb = cb; + dev = netdev_get(dpif_type_str); + if (!dev) { + VLOG_ERR("%s: Can't find any netdev for dpif type: %s", __func__, + dpif_type_str); + return; + } + netdev_regsiter_nl_sflow_upcall_cb(dev, dpif_netlink_sflow_upcall_cb); + netdev_close(dev); +} + static char * dpif_netlink_get_datapath_version(void) { @@ -3983,7 +4009,7 @@ const struct dpif_class dpif_netlink_class = { NULL, /* register_upcall_cb */ NULL, /* enable_upcall */ NULL, /* disable_upcall */ - NULL, /* register_sflow_upcall_cb */ + dpif_netlink_register_sflow_upcall_cb, dpif_netlink_get_datapath_version, /* get_datapath_version */ dpif_netlink_ct_dump_start, dpif_netlink_ct_dump_next, diff --git a/lib/netdev-offload.c b/lib/netdev-offload.c index 99b2704f6..f0c7c86c7 100644 --- a/lib/netdev-offload.c +++ b/lib/netdev-offload.c @@ -592,6 +592,24 @@ netdev_ports_get(odp_port_t port_no, const char *dpif_type) return ret; } +struct netdev * +netdev_get(const char *dpif_type) +{ + struct port_to_netdev_data *data; + struct netdev *dev = NULL; + + ovs_rwlock_rdlock(&netdev_hmap_rwlock); + HMAP_FOR_EACH (data, portno_node, &port_to_netdev) { + if (netdev_get_dpif_type(data->netdev) == dpif_type) { + dev = netdev_ref(data->netdev); + break; + } + } + ovs_rwlock_unlock(&netdev_hmap_rwlock); + + return dev; +} + int netdev_ports_remove(odp_port_t port_no, const char *dpif_type) { diff --git a/lib/netdev-offload.h b/lib/netdev-offload.h index 5ad5463ff..d70d40db7 100644 --- a/lib/netdev-offload.h +++ b/lib/netdev-offload.h @@ -110,6 +110,7 @@ struct dpif_port; int netdev_ports_insert(struct netdev *, const char *dpif_type, struct dpif_port *); struct netdev *netdev_ports_get(odp_port_t port, const char *dpif_type); +struct netdev *netdev_get(const char *dpif_type); int netdev_ports_remove(odp_port_t port, const char *dpif_type); odp_port_t netdev_ifindex_to_odp_port(int ifindex); From patchwork Fri Jan 22 05:38:13 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Mi X-Patchwork-Id: 1430173 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=) 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 4DMSjy5T7Gz9sS8 for ; Fri, 22 Jan 2021 16:39:02 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by silver.osuosl.org (Postfix) with ESMTP id 2CE7020344; Fri, 22 Jan 2021 05:39:01 +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 cVPZgU11w5Gk; Fri, 22 Jan 2021 05:38:52 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by silver.osuosl.org (Postfix) with ESMTP id 5DCC8227F8; Fri, 22 Jan 2021 05:38:42 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 38DE4C1DA7; Fri, 22 Jan 2021 05:38:42 +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 3216BC1DA7 for ; Fri, 22 Jan 2021 05:38:39 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by hemlock.osuosl.org (Postfix) with ESMTP id 11756872F9 for ; Fri, 22 Jan 2021 05:38:39 +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 e+Z5wfhTAlqM for ; Fri, 22 Jan 2021 05:38:38 +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 6F9FF872F6 for ; Fri, 22 Jan 2021 05:38:37 +0000 (UTC) Received: from Internal Mail-Server by MTLPINE1 (envelope-from cmi@nvidia.com) with SMTP; 22 Jan 2021 07:38:34 +0200 Received: from dev-r630-03.mtbc.labs.mlnx (dev-r630-03.mtbc.labs.mlnx [10.75.205.13]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 10M5cJ3p020652; Fri, 22 Jan 2021 07:38:33 +0200 From: Chris Mi To: dev@openvswitch.org Date: Fri, 22 Jan 2021 13:38:13 +0800 Message-Id: <20210122053816.174632-9-cmi@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210122053816.174632-1-cmi@nvidia.com> References: <20210122053816.174632-1-cmi@nvidia.com> MIME-Version: 1.0 Cc: elibr@nvidia.com, roniba@nvidia.com, i.maximets@ovn.org Subject: [ovs-dev] [PATCH v10 08/11] netdev-offload-tc: Introduce group ID management API 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: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" When offloading sample action to TC, userspace creates a unique ID to map sFlow action and tunnel info and passes this ID to kernel instead of the sFlow info. psample will send this ID and sampled packet to userspace. Using the ID, userspace can recover the sFlow info and send sampled packet to the right sFlow monitoring host. Signed-off-by: Chris Mi Reviewed-by: Eli Britstein --- lib/netdev-offload-tc.c | 273 +++++++++++++++++++++++++++++++++++++++- lib/tc.h | 1 + 2 files changed, 272 insertions(+), 2 deletions(-) diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c index 2b08ea55e..9b111708d 100644 --- a/lib/netdev-offload-tc.c +++ b/lib/netdev-offload-tc.c @@ -39,6 +39,7 @@ #include "unaligned.h" #include "util.h" #include "dpif-provider.h" +#include "cmap.h" VLOG_DEFINE_THIS_MODULE(netdev_offload_tc); @@ -57,6 +58,263 @@ struct netlink_field { int size; }; +/* This maps a psample group ID to struct dpif_sflow_attr for sFlow */ +struct sgid_node { + struct ovs_list exp_node OVS_GUARDED; + struct cmap_node metadata_node; + struct cmap_node id_node; + struct ovs_refcount refcount; + uint32_t hash; + uint32_t id; + const struct dpif_sflow_attr sflow; +}; + +static struct ovs_rwlock sgid_rwlock = OVS_RWLOCK_INITIALIZER; + +static long long int sgid_last_run OVS_GUARDED_BY(sgid_rwlock); + +static struct cmap sgid_map = CMAP_INITIALIZER; +static struct cmap sgid_metadata_map = CMAP_INITIALIZER; + +static struct ovs_list sgid_expiring OVS_GUARDED_BY(sgid_rwlock) + = OVS_LIST_INITIALIZER(&sgid_expiring); +static struct ovs_list sgid_expired OVS_GUARDED_BY(sgid_rwlock) + = OVS_LIST_INITIALIZER(&sgid_expired); + +static uint32_t next_sample_group_id OVS_GUARDED_BY(sgid_rwlock) = 1; + +#define SGID_RUN_INTERVAL 250 /* msec */ + +static void +sgid_node_free(struct sgid_node *node) +{ + free(node->sflow.tunnel); + free(CONST_CAST(void *, node->sflow.sflow)); + free(node->sflow.userdata); + free(node); +} + +static void +sgid_cleanup(void) +{ + long long int now = time_msec(); + struct sgid_node *node; + + /* Do maintenance at most 4 times / sec. */ + ovs_rwlock_rdlock(&sgid_rwlock); + if (now - sgid_last_run < SGID_RUN_INTERVAL) { + ovs_rwlock_unlock(&sgid_rwlock); + return; + } + ovs_rwlock_unlock(&sgid_rwlock); + + ovs_rwlock_wrlock(&sgid_rwlock); + sgid_last_run = now; + + LIST_FOR_EACH_POP (node, exp_node, &sgid_expired) { + cmap_remove(&sgid_map, &node->id_node, node->id); + ovsrcu_postpone(sgid_node_free, node); + } + + if (!ovs_list_is_empty(&sgid_expiring)) { + /* 'sgid_expired' is now empty, move nodes in + * 'sgid_expiring' to it. */ + ovs_list_splice(&sgid_expired, + ovs_list_front(&sgid_expiring), + &sgid_expiring); + } + ovs_rwlock_unlock(&sgid_rwlock); +} + +/* Lockless RCU protected lookup. If node is needed accross RCU quiescent + * state, caller should copy the contents. */ +static const struct sgid_node * +sgid_find(uint32_t id) +{ + const struct cmap_node *node = cmap_find(&sgid_map, id); + + return node ? CONTAINER_OF(node, const struct sgid_node, id_node) : NULL; +} + +static uint32_t +dpif_sflow_attr_hash(const struct dpif_sflow_attr *sflow) +{ + uint32_t hash = hash_bytes(sflow->sflow, sflow->sflow->nla_len, 0); + + if (sflow->tunnel) { + hash = hash_bytes(sflow->tunnel, sizeof *sflow->tunnel, hash); + } + return hash; +} + +static bool +dpif_sflow_attr_equal(const struct dpif_sflow_attr *a, + const struct dpif_sflow_attr *b) +{ + if (a->sflow->nla_len != b->sflow->nla_len + || memcmp(a->sflow, b->sflow, a->sflow->nla_len)) { + return false; + } + if (!a->tunnel && !b->tunnel) { + return true; + } + if (a->tunnel && b->tunnel) { + return !memcmp(a->tunnel, b->tunnel, sizeof *a->tunnel); + } + + return false; +} + +/* Lockless RCU protected lookup. If node is needed accross RCU quiescent + * state, caller should take a reference. */ +static struct sgid_node * +sgid_find_equal(const struct dpif_sflow_attr *target, uint32_t hash) +{ + struct sgid_node *node; + + CMAP_FOR_EACH_WITH_HASH (node, metadata_node, hash, &sgid_metadata_map) { + if (dpif_sflow_attr_equal(&node->sflow, target)) { + return node; + } + } + return NULL; +} + +static struct sgid_node * +sgid_ref_equal(const struct dpif_sflow_attr *target, uint32_t hash) +{ + struct sgid_node *node; + + do { + node = sgid_find_equal(target, hash); + /* Try again if the node was released before we get the reference. */ + } while (node && !ovs_refcount_try_ref_rcu(&node->refcount)); + + return node; +} + +static void +dpif_sflow_attr_clone(struct dpif_sflow_attr *new, + const struct dpif_sflow_attr *old) +{ + new->sflow = xmemdup(old->sflow, old->sflow->nla_len); + new->userdata = xmemdup(old->userdata, old->userdata_len); + new->userdata_len = old->userdata_len; + new->tunnel = old->tunnel + ? xmemdup(old->tunnel, sizeof *old->tunnel) + : NULL; +} + +/* We use the id as the hash value, which works due to cmap internal rehashing. + * We also only insert nodes with unique IDs, so all possible hash collisions + * remain internal to the cmap. */ +static struct sgid_node * +sgid_find__(uint32_t id) + OVS_REQUIRES(sgid_rwlock) +{ + struct cmap_node *node = cmap_find_protected(&sgid_map, id); + + return node ? CONTAINER_OF(node, struct sgid_node, id_node) : NULL; +} + +/* Allocate a unique group id for the given set of flow metadata. The id + * space is 2^^32, but if looping too many times, we still can't find a + * free one, that means something is wrong, return NULL. + */ +#define SGID_ALLOC_RETRY_MAX 8192 +static struct sgid_node * +sgid_alloc__(const struct dpif_sflow_attr *sflow, uint32_t hash) +{ + struct sgid_node *node = xzalloc(sizeof *node); + int i = 0; + + node->hash = hash; + ovs_refcount_init(&node->refcount); + dpif_sflow_attr_clone(CONST_CAST(struct dpif_sflow_attr *, &node->sflow), + sflow); + + ovs_rwlock_wrlock(&sgid_rwlock); + for (;;) { + node->id = next_sample_group_id++; + if (OVS_UNLIKELY(!node->id)) { + next_sample_group_id = 1; + node->id = next_sample_group_id++; + } + /* Find if the id is free. */ + if (OVS_LIKELY(!sgid_find__(node->id))) { + break; + } + if (++i == SGID_ALLOC_RETRY_MAX) { + VLOG_ERR("%s: Can't find a free group ID after %d retries", + __func__, i); + ovs_rwlock_unlock(&sgid_rwlock); + sgid_node_free(node); + return NULL; + } + } + cmap_insert(&sgid_map, &node->id_node, node->id); + cmap_insert(&sgid_metadata_map, &node->metadata_node, node->hash); + ovs_rwlock_unlock(&sgid_rwlock); + return node; +} + +/* Allocate a unique group id for the given set of flow metadata and + optional actions. */ +static uint32_t +sgid_alloc_ctx(const struct dpif_sflow_attr *sflow) +{ + uint32_t hash = dpif_sflow_attr_hash(sflow); + struct sgid_node *node = sgid_ref_equal(sflow, hash); + + if (!node) { + node = sgid_alloc__(sflow, hash); + } + + return node ? node->id : 0; +} + +static void +sgid_node_unref(const struct sgid_node *node_) + OVS_EXCLUDED(sgid_rwlock) +{ + struct sgid_node *node = CONST_CAST(struct sgid_node *, node_); + + ovs_rwlock_wrlock(&sgid_rwlock); + if (node && ovs_refcount_unref(&node->refcount) == 1) { + /* Prevent re-use of this node by removing the node from + * sgid_metadata_map' */ + cmap_remove(&sgid_metadata_map, &node->metadata_node, node->hash); + /* We keep the node in the 'sgid_map' so that it can be found as + * long as it lingers, and add it to the 'sgid_expiring' list. */ + ovs_list_insert(&sgid_expiring, &node->exp_node); + } + ovs_rwlock_unlock(&sgid_rwlock); +} + +static void +sgid_free(uint32_t id) +{ + const struct sgid_node *node; + + if (!id) + return; + + node = sgid_find(id); + if (node) { + sgid_node_unref(node); + } else { + VLOG_ERR("%s: Freeing nonexistent group ID: %"PRIu32, __func__, id); + } +} + +static int +del_filter_and_sgid(struct tcf_id *id) +{ + sgid_free(id->sample_group_id); + id->sample_group_id = 0; + return tc_del_filter(id); +} + static bool is_internal_port(const char *type) { @@ -199,7 +457,7 @@ del_filter_and_ufid_mapping(struct tcf_id *id, const ovs_u128 *ufid) { int err; - err = tc_del_filter(id); + err = del_filter_and_sgid(id); if (!err) { del_ufid_tc_mapping(ufid); } @@ -358,7 +616,7 @@ netdev_tc_flow_flush(struct netdev *netdev) continue; } - err = tc_del_filter(&data->id); + err = del_filter_and_sgid(&data->id); if (!err) { del_ufid_tc_mapping_unlocked(&data->ufid); } @@ -398,6 +656,12 @@ netdev_tc_flow_dump_create(struct netdev *netdev, *dump_out = dump; + /* Cleanup the sFlow group ID nodes in sgid_expired list. + * In order to avoid creating a dedicated thread to do it, put it in + * the revalidator thread. + */ + sgid_cleanup(); + return 0; } @@ -1797,6 +2061,11 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match, action->type = TC_ACT_GOTO; action->chain = 0; /* 0 is reserved and not used by recirc. */ flower.action_count++; + } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_SAMPLE) { + struct dpif_sflow_attr sflow_attr; + + memset(&sflow_attr, 0, sizeof sflow_attr); + sgid_alloc_ctx(&sflow_attr); } else { VLOG_DBG_RL(&rl, "unsupported put action type: %d", nl_attr_type(nla)); diff --git a/lib/tc.h b/lib/tc.h index 281231c0d..8394d2342 100644 --- a/lib/tc.h +++ b/lib/tc.h @@ -273,6 +273,7 @@ struct tcf_id { uint32_t chain; uint16_t prio; uint32_t handle; + uint32_t sample_group_id; }; static inline struct tcf_id From patchwork Fri Jan 22 05:38:14 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Mi X-Patchwork-Id: 1430176 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.137; helo=fraxinus.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4DMSkF6V0vz9sCD for ; Fri, 22 Jan 2021 16:39:17 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by fraxinus.osuosl.org (Postfix) with ESMTP id D2FEF86946; Fri, 22 Jan 2021 05:38:54 +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 65OhzazFSXuO; Fri, 22 Jan 2021 05:38:53 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by fraxinus.osuosl.org (Postfix) with ESMTP id 3E4AA869C5; Fri, 22 Jan 2021 05:38:47 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 1C309C1E7B; Fri, 22 Jan 2021 05:38:47 +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 783B2C013A for ; Fri, 22 Jan 2021 05:38:44 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by fraxinus.osuosl.org (Postfix) with ESMTP id 4924B86930 for ; Fri, 22 Jan 2021 05:38:44 +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 y28KZqjM_UNv for ; Fri, 22 Jan 2021 05:38:43 +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 6B2E786936 for ; Fri, 22 Jan 2021 05:38:42 +0000 (UTC) Received: from Internal Mail-Server by MTLPINE1 (envelope-from cmi@nvidia.com) with SMTP; 22 Jan 2021 07:38:36 +0200 Received: from dev-r630-03.mtbc.labs.mlnx (dev-r630-03.mtbc.labs.mlnx [10.75.205.13]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 10M5cJ3q020652; Fri, 22 Jan 2021 07:38:35 +0200 From: Chris Mi To: dev@openvswitch.org Date: Fri, 22 Jan 2021 13:38:14 +0800 Message-Id: <20210122053816.174632-10-cmi@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210122053816.174632-1-cmi@nvidia.com> References: <20210122053816.174632-1-cmi@nvidia.com> MIME-Version: 1.0 Cc: elibr@nvidia.com, roniba@nvidia.com, i.maximets@ovn.org Subject: [ovs-dev] [PATCH v10 09/11] netdev-offload-tc: Create psample netlink socket 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: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" Create psample netlink socket as a pre-step towards receiving sampled packets. Signed-off-by: Chris Mi Reviewed-by: Eli Britstein --- lib/netdev-offload-tc.c | 44 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c index 9b111708d..9f839075e 100644 --- a/lib/netdev-offload-tc.c +++ b/lib/netdev-offload-tc.c @@ -18,6 +18,7 @@ #include #include +#include #include "dpif.h" #include "hash.h" @@ -51,6 +52,8 @@ static bool multi_mask_per_prio = false; static bool block_support = false; static dpif_netlink_sflow_upcall_callback *upcall_cb; +static int psample_family; +struct nl_sock *psample_sock; struct netlink_field { int offset; @@ -2280,6 +2283,46 @@ netdev_tc_register_sflow_upcall_cb(dpif_netlink_sflow_upcall_callback *cb) upcall_cb = cb; } +static struct nl_sock * +netdev_tc_psample_init(void) +{ + unsigned int psample_mcgroup; + struct nl_sock *sock; + int error; + + if (nl_lookup_genl_family(PSAMPLE_GENL_NAME, &psample_family)) { + VLOG_INFO("%s: Generic Netlink family '%s' does not exist. " + "Please make sure the kernel module psample is loaded", + __func__, PSAMPLE_GENL_NAME); + return NULL; + } + + if (nl_lookup_genl_mcgroup(PSAMPLE_GENL_NAME, + PSAMPLE_NL_MCGRP_SAMPLE_NAME, + &psample_mcgroup)) { + VLOG_INFO("%s: Failed to join multicast group '%s' for Generic " + "Netlink family '%s'", __func__, + PSAMPLE_NL_MCGRP_SAMPLE_NAME, + PSAMPLE_GENL_NAME); + return NULL; + } + + error = nl_sock_create(NETLINK_GENERIC, &sock); + if (error) { + VLOG_INFO("%s: Failed to create psample socket", __func__); + return NULL; + } + + error = nl_sock_join_mcgroup(sock, psample_mcgroup); + if (error) { + VLOG_INFO("%s: Failed to join psample mcgroup", __func__); + nl_sock_destroy(sock); + return NULL; + } + + return sock; +} + static int netdev_tc_init_flow_api(struct netdev *netdev) { @@ -2314,6 +2357,7 @@ netdev_tc_init_flow_api(struct netdev *netdev) block_id = get_block_id_from_netdev(netdev); probe_multi_mask_per_prio(ifindex); + psample_sock = netdev_tc_psample_init(); ovsthread_once_done(&once); } From patchwork Fri Jan 22 05:38:15 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Mi X-Patchwork-Id: 1430177 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.137; helo=fraxinus.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Received: from fraxinus.osuosl.org (smtp4.osuosl.org [140.211.166.137]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4DMSkQ2Wdjz9sCD for ; Fri, 22 Jan 2021 16:39:26 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by fraxinus.osuosl.org (Postfix) with ESMTP id E192D869F6; Fri, 22 Jan 2021 05:38:58 +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 gppRoEIa87qa; Fri, 22 Jan 2021 05:38:57 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by fraxinus.osuosl.org (Postfix) with ESMTP id 98731869F7; Fri, 22 Jan 2021 05:38:48 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 792A2C1E87; Fri, 22 Jan 2021 05:38:48 +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 BBED4C1E74 for ; Fri, 22 Jan 2021 05:38:44 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by fraxinus.osuosl.org (Postfix) with ESMTP id A688A86918 for ; Fri, 22 Jan 2021 05:38:44 +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 akUku5or15Pt for ; Fri, 22 Jan 2021 05:38:43 +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 715EB86937 for ; Fri, 22 Jan 2021 05:38:42 +0000 (UTC) Received: from Internal Mail-Server by MTLPINE1 (envelope-from cmi@nvidia.com) with SMTP; 22 Jan 2021 07:38:38 +0200 Received: from dev-r630-03.mtbc.labs.mlnx (dev-r630-03.mtbc.labs.mlnx [10.75.205.13]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 10M5cJ3r020652; Fri, 22 Jan 2021 07:38:36 +0200 From: Chris Mi To: dev@openvswitch.org Date: Fri, 22 Jan 2021 13:38:15 +0800 Message-Id: <20210122053816.174632-11-cmi@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210122053816.174632-1-cmi@nvidia.com> References: <20210122053816.174632-1-cmi@nvidia.com> MIME-Version: 1.0 Cc: elibr@nvidia.com, roniba@nvidia.com, i.maximets@ovn.org Subject: [ovs-dev] [PATCH v10 10/11] netdev-offload-tc: Add psample receive handler 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: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" Create a dedicated thread to poll psample netlink socket, receive sampled packet, parse it to sFlow format and send it to sFlow monitoring host. Signed-off-by: Chris Mi Reviewed-by: Eli Britstein --- lib/netdev-offload-tc.c | 123 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c index 9f839075e..809a6ba72 100644 --- a/lib/netdev-offload-tc.c +++ b/lib/netdev-offload-tc.c @@ -19,12 +19,14 @@ #include #include #include +#include #include "dpif.h" #include "hash.h" #include "openvswitch/hmap.h" #include "openvswitch/match.h" #include "openvswitch/ofpbuf.h" +#include "openvswitch/poll-loop.h" #include "openvswitch/thread.h" #include "openvswitch/types.h" #include "openvswitch/util.h" @@ -2323,6 +2325,123 @@ netdev_tc_psample_init(void) return sock; } +struct netdev_tc_psample { + struct nlattr *packet; /* packet data */ + int dp_group_id; /* mapping id for sFlow offload */ + int iifindex; /* input ifindex */ + int group_seq; /* group sequence */ +}; + +static int +netdev_tc_psample_from_ofpbuf(struct netdev_tc_psample *psample, + const struct ofpbuf *buf) +{ + static const struct nl_policy ovs_psample_policy[] = { + [PSAMPLE_ATTR_IIFINDEX] = { .type = NL_A_U16 }, + [PSAMPLE_ATTR_SAMPLE_GROUP] = { .type = NL_A_U32 }, + [PSAMPLE_ATTR_GROUP_SEQ] = { .type = NL_A_U32 }, + [PSAMPLE_ATTR_DATA] = { .type = NL_A_UNSPEC }, + }; + struct nlattr *a[ARRAY_SIZE(ovs_psample_policy)]; + struct genlmsghdr *genl; + struct nlmsghdr *nlmsg; + struct ofpbuf b; + + b = ofpbuf_const_initializer(buf->data, buf->size); + nlmsg = ofpbuf_try_pull(&b, sizeof *nlmsg); + genl = ofpbuf_try_pull(&b, sizeof *genl); + if (!nlmsg || !genl || nlmsg->nlmsg_type != psample_family + || !nl_policy_parse(&b, 0, ovs_psample_policy, a, + ARRAY_SIZE(ovs_psample_policy))) { + return EINVAL; + } + + psample->iifindex = nl_attr_get_u16(a[PSAMPLE_ATTR_IIFINDEX]); + psample->dp_group_id = nl_attr_get_u32(a[PSAMPLE_ATTR_SAMPLE_GROUP]); + psample->group_seq = nl_attr_get_u16(a[PSAMPLE_ATTR_GROUP_SEQ]); + psample->packet = a[PSAMPLE_ATTR_DATA]; + + return 0; +} + +static int +netdev_tc_psample_parse_packet(struct netdev_tc_psample *psample, + struct dpif_upcall_sflow *dupcall) +{ + const struct sgid_node *node; + + dp_packet_use_stub(&dupcall->packet, + CONST_CAST(struct nlattr *, + nl_attr_get(psample->packet)) - 1, + nl_attr_get_size(psample->packet) + + sizeof(struct nlattr)); + dp_packet_set_data(&dupcall->packet, + (char *) dp_packet_data(&dupcall->packet) + + sizeof(struct nlattr)); + dp_packet_set_size(&dupcall->packet, nl_attr_get_size(psample->packet)); + + node = sgid_find(psample->dp_group_id); + dupcall->sflow_attr = &node->sflow; + dupcall->iifindex = psample->iifindex; + + return 0; +} + +static int +netdev_tc_psample_poll(struct dpif_upcall_sflow *dupcall, + struct nl_sock *sock) +{ + for (;;) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + struct netdev_tc_psample psample; + uint64_t buf_stub[4096 / 8]; + struct ofpbuf buf; + int error; + + ofpbuf_use_stub(&buf, buf_stub, sizeof buf_stub); + error = nl_sock_recv(sock, &buf, NULL, false); + + if (!error) { + error = netdev_tc_psample_from_ofpbuf(&psample, &buf); + if (!error) { + ofpbuf_uninit(&buf); + error = netdev_tc_psample_parse_packet(&psample, dupcall); + return error; + } + } else if (error != EAGAIN) { + VLOG_WARN_RL(&rl, "%s: error reading or parsing netlink (%s)", + __func__, ovs_strerror(error)); + nl_sock_drain(sock); + error = ENOBUFS; + } + + ofpbuf_uninit(&buf); + if (error) { + return error; + } + } +} + +static void * +netdev_tc_psample_handler(void *arg) +{ + struct nl_sock *sock = CONST_CAST(struct nl_sock *, arg); + + struct dpif_upcall_sflow dupcall; + int err; + + while (true) { + err = netdev_tc_psample_poll(&dupcall, sock); + if (!err) { + upcall_cb(&dupcall); + } + nl_sock_wait(sock, POLLIN); + poll_block(); + } + + return NULL; +} + static int netdev_tc_init_flow_api(struct netdev *netdev) { @@ -2358,6 +2477,10 @@ netdev_tc_init_flow_api(struct netdev *netdev) probe_multi_mask_per_prio(ifindex); psample_sock = netdev_tc_psample_init(); + if (psample_sock) { + ovs_thread_create("psample_handler", netdev_tc_psample_handler, + psample_sock); + } ovsthread_once_done(&once); } From patchwork Fri Jan 22 05:38:16 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Mi X-Patchwork-Id: 1430175 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=) 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 4DMSkD1GrYz9sCD for ; Fri, 22 Jan 2021 16:39:16 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id AE89C852C7; Fri, 22 Jan 2021 05:39:14 +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 FJsX8W07U24Z; Fri, 22 Jan 2021 05:39:04 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by whitealder.osuosl.org (Postfix) with ESMTP id 4089D86EA0; Fri, 22 Jan 2021 05:38:51 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 20C1CC1E76; Fri, 22 Jan 2021 05:38:51 +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 8816CC1E7B for ; Fri, 22 Jan 2021 05:38:47 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by fraxinus.osuosl.org (Postfix) with ESMTP id 6F128869D0 for ; Fri, 22 Jan 2021 05:38:47 +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 jw56TfLXmiU0 for ; Fri, 22 Jan 2021 05:38:43 +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 763D886938 for ; Fri, 22 Jan 2021 05:38:42 +0000 (UTC) Received: from Internal Mail-Server by MTLPINE1 (envelope-from cmi@nvidia.com) with SMTP; 22 Jan 2021 07:38:40 +0200 Received: from dev-r630-03.mtbc.labs.mlnx (dev-r630-03.mtbc.labs.mlnx [10.75.205.13]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 10M5cJ3s020652; Fri, 22 Jan 2021 07:38:38 +0200 From: Chris Mi To: dev@openvswitch.org Date: Fri, 22 Jan 2021 13:38:16 +0800 Message-Id: <20210122053816.174632-12-cmi@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20210122053816.174632-1-cmi@nvidia.com> References: <20210122053816.174632-1-cmi@nvidia.com> MIME-Version: 1.0 Cc: elibr@nvidia.com, roniba@nvidia.com, i.maximets@ovn.org Subject: [ovs-dev] [PATCH v10 11/11] netdev-offload-tc: Add offload support for sFlow 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: , Errors-To: ovs-dev-bounces@openvswitch.org Sender: "dev" Create a unique group ID to map the sFlow info when offloading sFlow action to TC. When showing the offloaded datapath flows, translate the group ID from TC sample action to sFlow info using the mapping. Signed-off-by: Chris Mi Reviewed-by: Eli Britstein --- lib/netdev-offload-tc.c | 205 +++++++++++++++++++++++++++++++++++++--- lib/tc.c | 61 +++++++++++- lib/tc.h | 15 ++- 3 files changed, 264 insertions(+), 17 deletions(-) diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c index 809a6ba72..f85494884 100644 --- a/lib/netdev-offload-tc.c +++ b/lib/netdev-offload-tc.c @@ -998,6 +998,18 @@ parse_tc_flower_to_match(struct tc_flower *flower, action = flower->actions; for (i = 0; i < flower->action_count; i++, action++) { switch (action->type) { + case TC_ACT_SAMPLE: { + const struct sgid_node *node; + + node = sgid_find(action->sample.action_group_id); + if (!node) { + VLOG_ERR_RL(&error_rl, "%s: sgid node is NULL, sgid: %d", + __func__, action->sample.action_group_id); + return ENOENT; + } + nl_msg_put(buf, node->sflow.sflow, node->sflow.sflow->nla_len); + } + break; case TC_ACT_VLAN_POP: { nl_msg_put_flag(buf, OVS_ACTION_ATTR_POP_VLAN); } @@ -1677,6 +1689,152 @@ flower_match_to_tun_opt(struct tc_flower *flower, const struct flow_tnl *tnl, flower->mask.tunnel.metadata.present.len = tnl->metadata.present.len; } +static int +parse_userspace_attributes(const struct nlattr *actions, + struct dpif_sflow_attr *sflow_attr) +{ + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20); + const struct nlattr *nla; + unsigned int left; + + NL_NESTED_FOR_EACH_UNSAFE (nla, left, actions) { + if (nl_attr_type(nla) == OVS_USERSPACE_ATTR_USERDATA) { + struct user_action_cookie *cookie; + + cookie = CONST_CAST(struct user_action_cookie *, nl_attr_get(nla)); + if (cookie->type == USER_ACTION_COOKIE_SFLOW) { + sflow_attr->userdata = CONST_CAST(void *, nl_attr_get(nla)); + sflow_attr->userdata_len = nl_attr_get_size(nla); + return 0; + } + } + } + + VLOG_DBG_RL(&rl, "%s: cannot offload userspace action other than sFlow", + __func__); + return EOPNOTSUPP; +} + +static int +parse_sample_actions_attribute(const struct nlattr *actions, + struct dpif_sflow_attr *sflow_attr) +{ + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20); + const struct nlattr *nla; + unsigned int left; + int err = EINVAL; + + NL_NESTED_FOR_EACH_UNSAFE (nla, left, actions) { + if (nl_attr_type(nla) == OVS_ACTION_ATTR_USERSPACE) { + err = parse_userspace_attributes(nla, sflow_attr); + } else { + /* We can't offload other nested actions */ + VLOG_DBG_RL(&rl, "%s: can only offload " + "OVS_ACTION_ATTR_USERSPACE attribute", __func__); + return EINVAL; + } + } + + if (err) { + VLOG_ERR_RL(&error_rl, "%s: no OVS_ACTION_ATTR_USERSPACE attribute", + __func__); + } + return err; +} + +static int +parse_sample_action(struct tc_flower *flower, struct tc_action *tc_action, + const struct nlattr *sample_action, + const struct flow_tnl *tnl, uint32_t *group_id) +{ + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20); + struct dpif_sflow_attr sflow_attr; + const struct nlattr *nla; + unsigned int left; + int ret = EINVAL; + + if (!psample_sock) { + VLOG_DBG_RL(&rl, "%s: psample modules is not initialized, " + "sFlow rule can't be offloaded", __func__); + return EINVAL; + } + + memset(&sflow_attr, 0, sizeof sflow_attr); + sflow_attr.sflow = sample_action; + + if (flower->tunnel) { + sflow_attr.tunnel = CONST_CAST(struct flow_tnl *, tnl); + } + + NL_NESTED_FOR_EACH_UNSAFE (nla, left, sample_action) { + if (nl_attr_type(nla) == OVS_SAMPLE_ATTR_ACTIONS) { + ret = parse_sample_actions_attribute(nla, &sflow_attr); + } else if (nl_attr_type(nla) == OVS_SAMPLE_ATTR_PROBABILITY) { + tc_action->type = TC_ACT_SAMPLE; + tc_action->sample.action_rate = UINT32_MAX / nl_attr_get_u32(nla); + } else { + return EINVAL; + } + } + + if (!tc_action->sample.action_rate || ret) { + return EINVAL; + } + + *group_id = sgid_alloc_ctx(&sflow_attr); + if (!*group_id) { + VLOG_DBG_RL(&rl, "%s: Failed allocating group id for sample action", + __func__); + return ENOENT; + } + tc_action->sample.action_group_id = *group_id; + flower->action_count++; + + return 0; +} + +static int +parse_userspace_action(struct tc_flower *flower, struct tc_action *tc_action, + const struct nlattr *userspace_action, + const struct flow_tnl *tnl, uint32_t *group_id) +{ + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(5, 20); + struct dpif_sflow_attr sflow_attr; + int err; + + if (!psample_sock) { + VLOG_DBG_RL(&rl, "%s: psample modules is not initialized, " + "sFlow rule can't be offloaded", __func__); + return EINVAL; + } + + /* If sampling rate is 1, there is only a sFlow cookie inside of a + * userspace action, but no sample attribute. That means we can + * only offload userspace actions for sFlow. + */ + memset(&sflow_attr, 0, sizeof sflow_attr); + if (flower->tunnel) { + sflow_attr.tunnel = CONST_CAST(struct flow_tnl *, tnl); + } + err = parse_userspace_attributes(userspace_action, &sflow_attr); + if (err) { + return err; + } + sflow_attr.sflow = userspace_action; + *group_id = sgid_alloc_ctx(&sflow_attr); + if (!*group_id) { + VLOG_DBG_RL(&rl, "%s: Failed allocating group id for sample action", + __func__); + return ENOENT; + } + tc_action->type = TC_ACT_SAMPLE; + tc_action->sample.action_group_id = *group_id; + tc_action->sample.action_rate = 1; + flower->action_count++; + + return 0; +} + static int netdev_tc_flow_put(struct netdev *netdev, struct match *match, struct nlattr *actions, size_t actions_len, @@ -1693,6 +1851,7 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match, struct tc_action *action; bool recirc_act = false; uint32_t block_id = 0; + uint32_t sample_gid = 0; struct nlattr *nla; struct tcf_id id; uint32_t chain; @@ -1982,7 +2141,8 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match, NL_ATTR_FOR_EACH(nla, left, actions, actions_len) { if (flower.action_count >= TCA_ACT_MAX_NUM) { VLOG_DBG_RL(&rl, "Can only support %d actions", TCA_ACT_MAX_NUM); - return EOPNOTSUPP; + err = EOPNOTSUPP; + goto out; } action = &flower.actions[flower.action_count]; if (nl_attr_type(nla) == OVS_ACTION_ATTR_OUTPUT) { @@ -1992,7 +2152,8 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match, if (!outdev) { VLOG_DBG_RL(&rl, "Can't find netdev for output port %d", port); - return ENODEV; + err = ENODEV; + goto out; } action->out.ifindex_out = netdev_get_ifindex(outdev); action->out.ingress = is_internal_port(netdev_get_type(outdev)); @@ -2030,7 +2191,7 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match, err = parse_put_flow_set_action(&flower, action, set, set_len); if (err) { - return err; + goto out; } if (action->type == TC_ACT_ENCAP) { action->encap.tp_dst = info->tp_dst_port; @@ -2043,7 +2204,7 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match, err = parse_put_flow_set_masked_action(&flower, action, set, set_len, true); if (err) { - return err; + goto out; } } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_CT) { const struct nlattr *ct = nl_attr_get(nla); @@ -2051,7 +2212,7 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match, err = parse_put_flow_ct_action(&flower, action, ct, ct_len); if (err) { - return err; + goto out; } } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_CT_CLEAR) { action->type = TC_ACT_CT; @@ -2067,20 +2228,28 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match, action->chain = 0; /* 0 is reserved and not used by recirc. */ flower.action_count++; } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_SAMPLE) { - struct dpif_sflow_attr sflow_attr; - - memset(&sflow_attr, 0, sizeof sflow_attr); - sgid_alloc_ctx(&sflow_attr); + err = parse_sample_action(&flower, action, nla, tnl, &sample_gid); + if (err) { + goto out; + } + } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_USERSPACE) { + err = parse_userspace_action(&flower, action, nla, tnl, + &sample_gid); + if (err) { + goto out; + } } else { VLOG_DBG_RL(&rl, "unsupported put action type: %d", nl_attr_type(nla)); - return EOPNOTSUPP; + err = EOPNOTSUPP; + goto out; } } if ((chain || recirc_act) && !info->recirc_id_shared_with_tc) { VLOG_ERR_RL(&error_rl, "flow_put: recirc_id sharing not supported"); - return EOPNOTSUPP; + err = EOPNOTSUPP; + goto out; } if (get_ufid_tc_mapping(ufid, &id) == 0) { @@ -2092,20 +2261,30 @@ netdev_tc_flow_put(struct netdev *netdev, struct match *match, prio = get_prio_for_tc_flower(&flower); if (prio == 0) { VLOG_ERR_RL(&rl, "couldn't get tc prio: %s", ovs_strerror(ENOSPC)); - return ENOSPC; + err = ENOSPC; + goto out; } flower.act_cookie.data = ufid; flower.act_cookie.len = sizeof *ufid; block_id = get_block_id_from_netdev(netdev); - id = tc_make_tcf_id_chain(ifindex, block_id, chain, prio, hook); + id = tc_make_tcf_id_all(ifindex, block_id, chain, prio, hook, sample_gid); err = tc_replace_flower(&id, &flower); if (!err) { if (stats) { memset(stats, 0, sizeof *stats); } add_ufid_tc_mapping(netdev, ufid, &id); + } else { + goto out; + } + + return 0; + +out: + if (sample_gid) { + sgid_free(sample_gid); } return err; diff --git a/lib/tc.c b/lib/tc.c index c2de78bfe..dd67ad6b0 100644 --- a/lib/tc.c +++ b/lib/tc.c @@ -23,14 +23,15 @@ #include #include #include +#include #include #include #include #include +#include #include #include #include -#include #include #include #include @@ -1291,6 +1292,38 @@ nl_parse_act_gact(struct nlattr *options, struct tc_flower *flower) return 0; } +static const struct nl_policy sample_policy[] = { + [TCA_SAMPLE_PARMS] = { .type = NL_A_UNSPEC, + .min_len = sizeof(struct tc_sample), + .optional = false, }, + [TCA_SAMPLE_PSAMPLE_GROUP] = { .type = NL_A_U32, + .optional = false, }, + [TCA_SAMPLE_RATE] = { .type = NL_A_U32, + .optional = false, }, +}; + +static int +nl_parse_act_sample(struct nlattr *options, struct tc_flower *flower) +{ + struct nlattr *sample_attrs[ARRAY_SIZE(sample_policy)]; + struct tc_action *action; + + if (!nl_parse_nested(options, sample_policy, sample_attrs, + ARRAY_SIZE(sample_policy))) { + VLOG_ERR_RL(&error_rl, "failed to parse sample action options"); + return EPROTO; + } + + action = &flower->actions[flower->action_count++]; + action->type = TC_ACT_SAMPLE; + action->sample.action_group_id = + nl_attr_get_u32(sample_attrs[TCA_SAMPLE_PSAMPLE_GROUP]); + action->sample.action_rate = + nl_attr_get_u32(sample_attrs[TCA_SAMPLE_RATE]); + + return 0; +} + static const struct nl_policy mirred_policy[] = { [TCA_MIRRED_PARMS] = { .type = NL_A_UNSPEC, .min_len = sizeof(struct tc_mirred), @@ -1699,6 +1732,8 @@ nl_parse_single_action(struct nlattr *action, struct tc_flower *flower, /* Added for TC rule only (not in OvS rule) so ignore. */ } else if (!strcmp(act_kind, "ct")) { nl_parse_act_ct(act_options, flower); + } else if (!strcmp(act_kind, "sample")) { + nl_parse_act_sample(act_options, flower); } else { VLOG_ERR_RL(&error_rl, "unknown tc action kind: %s", act_kind); err = EINVAL; @@ -2294,6 +2329,23 @@ nl_msg_put_act_mirred(struct ofpbuf *request, int ifindex, int action, nl_msg_end_nested(request, offset); } +static void +nl_msg_put_act_sample(struct ofpbuf *request, uint32_t rate, uint32_t group_id) +{ + size_t offset; + + nl_msg_put_string(request, TCA_ACT_KIND, "sample"); + offset = nl_msg_start_nested(request, TCA_ACT_OPTIONS | NLA_F_NESTED); + { + struct tc_sample parm = { .action = TC_ACT_PIPE }; + + nl_msg_put_unspec(request, TCA_SAMPLE_PARMS, &parm, sizeof parm); + nl_msg_put_u32(request, TCA_SAMPLE_RATE, rate); + nl_msg_put_u32(request, TCA_SAMPLE_PSAMPLE_GROUP, group_id); + } + nl_msg_end_nested(request, offset); +} + static inline void nl_msg_put_act_cookie(struct ofpbuf *request, struct tc_cookie *ck) { if (ck->len) { @@ -2553,6 +2605,13 @@ nl_msg_put_flower_acts(struct ofpbuf *request, struct tc_flower *flower) nl_msg_end_nested(request, act_offset); } break; + case TC_ACT_SAMPLE: { + act_offset = nl_msg_start_nested(request, act_index++); + nl_msg_put_act_sample(request, action->sample.action_rate, + action->sample.action_group_id); + nl_msg_end_nested(request, act_offset); + } + break; case TC_ACT_OUTPUT: { if (!released && flower->tunnel) { act_offset = nl_msg_start_nested(request, act_index++); diff --git a/lib/tc.h b/lib/tc.h index 8394d2342..816c50a08 100644 --- a/lib/tc.h +++ b/lib/tc.h @@ -171,6 +171,7 @@ enum tc_action_type { TC_ACT_MPLS_SET, TC_ACT_GOTO, TC_ACT_CT, + TC_ACT_SAMPLE, }; enum nat_type { @@ -253,6 +254,11 @@ struct tc_action { bool force; bool commit; } ct; + + struct { + uint32_t action_rate; + uint32_t action_group_id; + } sample; }; enum tc_action_type type; @@ -291,12 +297,14 @@ tc_make_tcf_id(int ifindex, uint32_t block_id, uint16_t prio, } static inline struct tcf_id -tc_make_tcf_id_chain(int ifindex, uint32_t block_id, uint32_t chain, - uint16_t prio, enum tc_qdisc_hook hook) +tc_make_tcf_id_all(int ifindex, uint32_t block_id, uint32_t chain, + uint16_t prio, enum tc_qdisc_hook hook, + uint32_t sample_group_id) { struct tcf_id id = tc_make_tcf_id(ifindex, block_id, prio, hook); id.chain = chain; + id.sample_group_id = sample_group_id; return id; } @@ -310,7 +318,8 @@ is_tcf_id_eq(struct tcf_id *id1, struct tcf_id *id2) && id1->hook == id2->hook && id1->block_id == id2->block_id && id1->ifindex == id2->ifindex - && id1->chain == id2->chain; + && id1->chain == id2->chain + && id1->sample_group_id == id2->sample_group_id; } enum tc_offload_policy {