From patchwork Mon Dec 14 09:39:30 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Mi X-Patchwork-Id: 1415873 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=nvidia.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 4Cvbw64RNRz9sSC for ; Mon, 14 Dec 2020 20:40:06 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id D046E8714D; Mon, 14 Dec 2020 09:40:04 +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 zTA4WD5RWADg; Mon, 14 Dec 2020 09:39:58 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by whitealder.osuosl.org (Postfix) with ESMTP id 5A6E68720D; Mon, 14 Dec 2020 09:39:57 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 3D0D0C1D9F; Mon, 14 Dec 2020 09:39:57 +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 7BBCAC013B for ; Mon, 14 Dec 2020 09:39:54 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by hemlock.osuosl.org (Postfix) with ESMTP id 6A043873DB for ; Mon, 14 Dec 2020 09:39:54 +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 HIiu6LSG0hOk for ; Mon, 14 Dec 2020 09:39:53 +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 AA83787117 for ; Mon, 14 Dec 2020 09:39:52 +0000 (UTC) Received: from Internal Mail-Server by MTLPINE1 (envelope-from cmi@nvidia.com) with SMTP; 14 Dec 2020 11:39:47 +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 0BE9dhVe000334; Mon, 14 Dec 2020 11:39:45 +0200 From: Chris Mi To: dev@openvswitch.org Date: Mon, 14 Dec 2020 17:39:30 +0800 Message-Id: <20201214093940.15722-2-cmi@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201214093940.15722-1-cmi@nvidia.com> References: <20201214093940.15722-1-cmi@nvidia.com> MIME-Version: 1.0 Cc: elibr@nvidia.com, Chris Mi , roniba@nvidia.com, i.maximets@ovn.org Subject: [ovs-dev] [PATCH v8 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 --- 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 Mon Dec 14 09:39:31 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Mi X-Patchwork-Id: 1415869 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=nvidia.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 4Cvbvx5Q8zz9sSC for ; Mon, 14 Dec 2020 20:39:57 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id 427F9871AC; Mon, 14 Dec 2020 09:39:56 +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 42Wv+rfNp6MD; Mon, 14 Dec 2020 09:39:55 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by whitealder.osuosl.org (Postfix) with ESMTP id 84CEE865D6; Mon, 14 Dec 2020 09:39:55 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 54A0EC088E; Mon, 14 Dec 2020 09:39:55 +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 532E2C013B for ; Mon, 14 Dec 2020 09:39:54 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by hemlock.osuosl.org (Postfix) with ESMTP id 4E1E68748A for ; Mon, 14 Dec 2020 09:39:54 +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 Q20X7hJT99KH for ; Mon, 14 Dec 2020 09:39:53 +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 AB83E873DB for ; Mon, 14 Dec 2020 09:39:52 +0000 (UTC) Received: from Internal Mail-Server by MTLPINE1 (envelope-from cmi@nvidia.com) with SMTP; 14 Dec 2020 11:39:49 +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 0BE9dhVf000334; Mon, 14 Dec 2020 11:39:47 +0200 From: Chris Mi To: dev@openvswitch.org Date: Mon, 14 Dec 2020 17:39:31 +0800 Message-Id: <20201214093940.15722-3-cmi@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201214093940.15722-1-cmi@nvidia.com> References: <20201214093940.15722-1-cmi@nvidia.com> MIME-Version: 1.0 Cc: elibr@nvidia.com, Chris Mi , roniba@nvidia.com, i.maximets@ovn.org Subject: [ovs-dev] [PATCH v8 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 --- 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 Mon Dec 14 09:39:32 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Mi X-Patchwork-Id: 1415871 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=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=nvidia.com 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 4Cvbw33tKdz9sSC for ; Mon, 14 Dec 2020 20:40:03 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by fraxinus.osuosl.org (Postfix) with ESMTP id BB7948623E; Mon, 14 Dec 2020 09:40:01 +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 uykmVd6Tvu06; Mon, 14 Dec 2020 09:39:58 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by fraxinus.osuosl.org (Postfix) with ESMTP id 2FC7286257; Mon, 14 Dec 2020 09:39:58 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id EFA9CC1D9F; Mon, 14 Dec 2020 09:39:57 +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 AA0BFC013B for ; Mon, 14 Dec 2020 09:39:54 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id 9845E865D6 for ; Mon, 14 Dec 2020 09:39:54 +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 v4xijZC2QkEa for ; Mon, 14 Dec 2020 09:39:53 +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 160328711F for ; Mon, 14 Dec 2020 09:39:52 +0000 (UTC) Received: from Internal Mail-Server by MTLPINE1 (envelope-from cmi@nvidia.com) with SMTP; 14 Dec 2020 11:39:50 +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 0BE9dhVg000334; Mon, 14 Dec 2020 11:39:49 +0200 From: Chris Mi To: dev@openvswitch.org Date: Mon, 14 Dec 2020 17:39:32 +0800 Message-Id: <20201214093940.15722-4-cmi@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201214093940.15722-1-cmi@nvidia.com> References: <20201214093940.15722-1-cmi@nvidia.com> MIME-Version: 1.0 Cc: elibr@nvidia.com, Chris Mi , roniba@nvidia.com, i.maximets@ovn.org Subject: [ovs-dev] [PATCH v8 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 | 26 ++++++++++++++++++++++++++ 5 files changed, 46 insertions(+) diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index 300861ca5..f47a3fdab 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -8426,6 +8426,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 6858ba612..2a47d483c 100644 --- a/lib/dpif-netlink.c +++ b/lib/dpif-netlink.c @@ -3987,6 +3987,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 ac2860764..6e72b2087 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 7ef148c6d..1ab6e8cd2 100644 --- a/lib/dpif.h +++ b/lib/dpif.h @@ -870,6 +870,32 @@ 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 */ + size_t sflow_len; /* Length of 'sflow' in bytes. */ + + 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 Mon Dec 14 09:39:33 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Mi X-Patchwork-Id: 1415874 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=nvidia.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 4CvbwH67k1z9sSC for ; Mon, 14 Dec 2020 20:40:15 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id 64006873E0; Mon, 14 Dec 2020 09:40: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 pJgpCGNDMf6w; Mon, 14 Dec 2020 09:40:10 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by whitealder.osuosl.org (Postfix) with ESMTP id 39A6F872B7; Mon, 14 Dec 2020 09:40:00 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id E21BAC1DA0; Mon, 14 Dec 2020 09:39:59 +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 0B80CC1DA1 for ; Mon, 14 Dec 2020 09:39:58 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by hemlock.osuosl.org (Postfix) with ESMTP id D6A788748A for ; Mon, 14 Dec 2020 09:39:57 +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 rkTKgo2DLbVo for ; Mon, 14 Dec 2020 09:39:56 +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 4D2468748D for ; Mon, 14 Dec 2020 09:39:56 +0000 (UTC) Received: from Internal Mail-Server by MTLPINE1 (envelope-from cmi@nvidia.com) with SMTP; 14 Dec 2020 11:39:52 +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 0BE9dhVh000334; Mon, 14 Dec 2020 11:39:50 +0200 From: Chris Mi To: dev@openvswitch.org Date: Mon, 14 Dec 2020 17:39:33 +0800 Message-Id: <20201214093940.15722-5-cmi@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201214093940.15722-1-cmi@nvidia.com> References: <20201214093940.15722-1-cmi@nvidia.com> MIME-Version: 1.0 Cc: elibr@nvidia.com, Chris Mi , roniba@nvidia.com, i.maximets@ovn.org Subject: [ovs-dev] [PATCH v8 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 19b92dfe0..6bc60e8c4 100644 --- a/ofproto/ofproto-dpif-upcall.c +++ b/ofproto/ofproto-dpif-upcall.c @@ -410,6 +410,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); @@ -464,6 +465,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; } @@ -1348,6 +1350,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 Mon Dec 14 09:39:34 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Mi X-Patchwork-Id: 1415872 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=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=nvidia.com 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 4Cvbw52LGwz9sSC for ; Mon, 14 Dec 2020 20:40:05 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by fraxinus.osuosl.org (Postfix) with ESMTP id E5AEA86371; Mon, 14 Dec 2020 09:40:03 +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 u0E_32Q780jj; Mon, 14 Dec 2020 09:40:01 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by fraxinus.osuosl.org (Postfix) with ESMTP id 0CB3E86352; Mon, 14 Dec 2020 09:39:59 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 01FDFC1D9F; Mon, 14 Dec 2020 09:39:59 +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 B8F20C013B for ; Mon, 14 Dec 2020 09:39:57 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by hemlock.osuosl.org (Postfix) with ESMTP id 9C667874D7 for ; Mon, 14 Dec 2020 09:39:57 +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 YLrpprYjqFbn for ; Mon, 14 Dec 2020 09:39:56 +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 4C1FE8748A for ; Mon, 14 Dec 2020 09:39:56 +0000 (UTC) Received: from Internal Mail-Server by MTLPINE1 (envelope-from cmi@nvidia.com) with SMTP; 14 Dec 2020 11:39:54 +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 0BE9dhVi000334; Mon, 14 Dec 2020 11:39:52 +0200 From: Chris Mi To: dev@openvswitch.org Date: Mon, 14 Dec 2020 17:39:34 +0800 Message-Id: <20201214093940.15722-6-cmi@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201214093940.15722-1-cmi@nvidia.com> References: <20201214093940.15722-1-cmi@nvidia.com> MIME-Version: 1.0 Cc: elibr@nvidia.com, Chris Mi , roniba@nvidia.com, i.maximets@ovn.org Subject: [ovs-dev] [PATCH v8 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 0bed7bf61..a199c9de1 100644 --- a/lib/netdev-offload-provider.h +++ b/lib/netdev-offload-provider.h @@ -83,6 +83,9 @@ struct netdev_flow_api { int (*flow_del)(struct netdev *, const ovs_u128 *ufid, struct dpif_flow_stats *); + /* 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 2da3bc701..f8d397d08 100644 --- a/lib/netdev-offload.c +++ b/lib/netdev-offload.c @@ -666,3 +666,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 4c0ed2ae8..84d267178 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" { @@ -124,6 +125,8 @@ int netdev_ports_flow_get(const char *dpif_type, struct match *match, struct dpif_flow_stats *stats, struct dpif_flow_attrs *attrs, struct ofpbuf *buf); +void netdev_regsiter_nl_sflow_upcall_cb(struct netdev *netdev, + dpif_netlink_sflow_upcall_callback *cb); #ifdef __cplusplus } From patchwork Mon Dec 14 09:39:35 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Mi X-Patchwork-Id: 1415875 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=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=nvidia.com 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 4CvbwR6F6Tz9sSC for ; Mon, 14 Dec 2020 20:40:23 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by fraxinus.osuosl.org (Postfix) with ESMTP id 4836F866C9; Mon, 14 Dec 2020 09:40:22 +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 DA8gDGPKc0N2; Mon, 14 Dec 2020 09:40:21 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by fraxinus.osuosl.org (Postfix) with ESMTP id 09849861EE; Mon, 14 Dec 2020 09:40:17 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id E17A9C163C; Mon, 14 Dec 2020 09:40:16 +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 86499C088E for ; Mon, 14 Dec 2020 09:40:15 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id 62E3C87276 for ; Mon, 14 Dec 2020 09:40:15 +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 DDr3tCG2TzEp for ; Mon, 14 Dec 2020 09:40:13 +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 9C37E872BA for ; Mon, 14 Dec 2020 09:40:01 +0000 (UTC) Received: from Internal Mail-Server by MTLPINE1 (envelope-from cmi@nvidia.com) with SMTP; 14 Dec 2020 11:39:55 +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 0BE9dhVj000334; Mon, 14 Dec 2020 11:39:54 +0200 From: Chris Mi To: dev@openvswitch.org Date: Mon, 14 Dec 2020 17:39:35 +0800 Message-Id: <20201214093940.15722-7-cmi@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201214093940.15722-1-cmi@nvidia.com> References: <20201214093940.15722-1-cmi@nvidia.com> MIME-Version: 1.0 Cc: elibr@nvidia.com, Chris Mi , roniba@nvidia.com, i.maximets@ovn.org Subject: [ovs-dev] [PATCH v8 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 2a772a971..9c5be9f92 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; @@ -1985,6 +1987,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) { @@ -2044,5 +2052,6 @@ const struct netdev_flow_api netdev_offload_tc = { .flow_put = netdev_tc_flow_put, .flow_get = netdev_tc_flow_get, .flow_del = netdev_tc_flow_del, + .register_nl_sflow_upcall_cb = netdev_tc_register_sflow_upcall_cb, .init_flow_api = netdev_tc_init_flow_api, }; From patchwork Mon Dec 14 09:39:36 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Mi X-Patchwork-Id: 1415876 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.133; helo=hemlock.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=nvidia.com Received: from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Cvbwb2kPhz9sSC for ; Mon, 14 Dec 2020 20:40:31 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by hemlock.osuosl.org (Postfix) with ESMTP id BD0F387510; Mon, 14 Dec 2020 09:40:29 +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 EWzQGC5SeodH; Mon, 14 Dec 2020 09:40:20 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by hemlock.osuosl.org (Postfix) with ESMTP id 1402087528; Mon, 14 Dec 2020 09:40:20 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id EA049C163C; Mon, 14 Dec 2020 09:40:19 +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 9D5BAC088E for ; Mon, 14 Dec 2020 09:40:16 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id 80220872BD for ; Mon, 14 Dec 2020 09:40:16 +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 0c0LcfFpUIfr for ; Mon, 14 Dec 2020 09:40:13 +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 95448871E9 for ; Mon, 14 Dec 2020 09:40:01 +0000 (UTC) Received: from Internal Mail-Server by MTLPINE1 (envelope-from cmi@nvidia.com) with SMTP; 14 Dec 2020 11:39:57 +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 0BE9dhVk000334; Mon, 14 Dec 2020 11:39:56 +0200 From: Chris Mi To: dev@openvswitch.org Date: Mon, 14 Dec 2020 17:39:36 +0800 Message-Id: <20201214093940.15722-8-cmi@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201214093940.15722-1-cmi@nvidia.com> References: <20201214093940.15722-1-cmi@nvidia.com> MIME-Version: 1.0 Cc: elibr@nvidia.com, Chris Mi , roniba@nvidia.com, i.maximets@ovn.org Subject: [ovs-dev] [PATCH v8 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 2a47d483c..fd8db8332 100644 --- a/lib/dpif-netlink.c +++ b/lib/dpif-netlink.c @@ -237,6 +237,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 *, @@ -2829,6 +2831,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) { @@ -3987,7 +4013,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 f8d397d08..17f1592b5 100644 --- a/lib/netdev-offload.c +++ b/lib/netdev-offload.c @@ -581,6 +581,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 84d267178..5a5dd6867 100644 --- a/lib/netdev-offload.h +++ b/lib/netdev-offload.h @@ -109,6 +109,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 Mon Dec 14 09:39:37 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Mi X-Patchwork-Id: 1415877 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=nvidia.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 4Cvbwj3tgsz9sSC for ; Mon, 14 Dec 2020 20:40:37 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id 1EFA887363; Mon, 14 Dec 2020 09:40:36 +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 jjltM-g00cU3; Mon, 14 Dec 2020 09:40:29 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by whitealder.osuosl.org (Postfix) with ESMTP id 1190A87263; Mon, 14 Dec 2020 09:40:09 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id E23E5C1D9F; Mon, 14 Dec 2020 09:40:08 +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 2DDDDC1DCB for ; Mon, 14 Dec 2020 09:40:07 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by fraxinus.osuosl.org (Postfix) with ESMTP id 1961986374 for ; Mon, 14 Dec 2020 09:40:07 +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 DGd3lcF0IbuV for ; Mon, 14 Dec 2020 09:40:04 +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 6B9CC86432 for ; Mon, 14 Dec 2020 09:40:01 +0000 (UTC) Received: from Internal Mail-Server by MTLPINE1 (envelope-from cmi@nvidia.com) with SMTP; 14 Dec 2020 11:39:59 +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 0BE9dhVl000334; Mon, 14 Dec 2020 11:39:57 +0200 From: Chris Mi To: dev@openvswitch.org Date: Mon, 14 Dec 2020 17:39:37 +0800 Message-Id: <20201214093940.15722-9-cmi@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201214093940.15722-1-cmi@nvidia.com> References: <20201214093940.15722-1-cmi@nvidia.com> MIME-Version: 1.0 Cc: elibr@nvidia.com, Chris Mi , roniba@nvidia.com, i.maximets@ovn.org Subject: [ovs-dev] [PATCH v8 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 | 261 ++++++++++++++++++++++++++++++++++++++++ lib/tc.h | 1 + 2 files changed, 262 insertions(+) diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c index 9c5be9f92..a81003a98 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,256 @@ struct netlink_field { int size; }; +/* This maps a psample group ID to struct dpif_sflow_attr for sFlow */ +struct gid_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 gid_rwlock = OVS_RWLOCK_INITIALIZER; + +static long long int gid_last_run OVS_GUARDED_BY(gid_rwlock); + +static struct cmap gid_map = CMAP_INITIALIZER; +static struct cmap gid_metadata_map = CMAP_INITIALIZER; + +static struct ovs_list gid_expiring OVS_GUARDED_BY(gid_rwlock) + = OVS_LIST_INITIALIZER(&gid_expiring); +static struct ovs_list gid_expired OVS_GUARDED_BY(gid_rwlock) + = OVS_LIST_INITIALIZER(&gid_expired); + +static uint32_t next_group_id OVS_GUARDED_BY(gid_rwlock) = 1; + +#define GID_RUN_INTERVAL 250 /* msec */ + +static void +gid_node_free(struct gid_node *node) +{ + if (node->sflow.tunnel) { + free(node->sflow.tunnel); + } + free(CONST_CAST(void *, node->sflow.sflow)); + free(node->sflow.userdata); + free(node); +} + +static void +gid_cleanup(void) +{ + long long int now = time_msec(); + struct gid_node *node; + + /* Do maintenance at most 4 times / sec. */ + ovs_rwlock_rdlock(&gid_rwlock); + if (now - gid_last_run < GID_RUN_INTERVAL) { + ovs_rwlock_unlock(&gid_rwlock); + return; + } + ovs_rwlock_unlock(&gid_rwlock); + + ovs_rwlock_wrlock(&gid_rwlock); + gid_last_run = now; + + LIST_FOR_EACH_POP (node, exp_node, &gid_expired) { + cmap_remove(&gid_map, &node->id_node, node->id); + ovsrcu_postpone(gid_node_free, node); + } + + if (!ovs_list_is_empty(&gid_expiring)) { + /* 'gid_expired' is now empty, move nodes in + * 'gid_expiring' to it. */ + ovs_list_splice(&gid_expired, + ovs_list_front(&gid_expiring), + &gid_expiring); + } + ovs_rwlock_unlock(&gid_rwlock); +} + +/* Lockless RCU protected lookup. If node is needed accross RCU quiescent + * state, caller should copy the contents. */ +static const struct gid_node * +gid_find(uint32_t id) +{ + const struct cmap_node *node = cmap_find(&gid_map, id); + + return node + ? CONTAINER_OF(node, const struct gid_node, id_node) + : NULL; +} + +static uint32_t +dpif_sflow_attr_hash(const struct dpif_sflow_attr *sflow) +{ + uint32_t hash1 = hash_bytes(sflow->sflow, sflow->sflow_len, 0); + uint32_t hash2; + + if (!sflow->tunnel) { + return hash1; + } + + hash2 = hash_bytes(sflow->tunnel, sizeof *sflow->tunnel, 0); + return hash_add(hash1, hash2); +} + +static bool +dpif_sflow_attr_equal(const struct dpif_sflow_attr *a, + const struct dpif_sflow_attr *b) +{ + if (a->sflow_len != b->sflow_len + || memcmp(a->sflow, b->sflow, a->sflow_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 gid_node * +gid_find_equal(const struct dpif_sflow_attr *target, uint32_t hash) +{ + struct gid_node *node; + + CMAP_FOR_EACH_WITH_HASH (node, metadata_node, hash, &gid_metadata_map) { + if (dpif_sflow_attr_equal(&node->sflow, target)) { + return node; + } + } + return NULL; +} + +static struct gid_node * +gid_ref_equal(const struct dpif_sflow_attr *target, uint32_t hash) +{ + struct gid_node *node; + + do { + node = gid_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_len = old->sflow_len; + new->sflow = xmalloc(new->sflow_len); + memcpy(CONST_CAST(void *, new->sflow), old->sflow, new->sflow_len); + + new->userdata_len = old->userdata_len; + new->userdata = xmalloc(new->userdata_len); + memcpy(new->userdata, old->userdata, new->userdata_len); + + if (old->tunnel) { + new->tunnel = xzalloc(sizeof *new->tunnel); + memcpy(new->tunnel, old->tunnel, sizeof *new->tunnel); + } else { + new->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 gid_node * +gid_find__(uint32_t id) + OVS_REQUIRES(gid_rwlock) +{ + struct cmap_node *node = cmap_find_protected(&gid_map, id); + + return node ? CONTAINER_OF(node, struct gid_node, id_node) : NULL; +} + +/* Allocate a unique group id for the given set of flow metadata. + * The ID space is 2^^32, so there should never be a situation in which all + * the IDs are used up. We loop until we find a free one. */ +static struct gid_node * +gid_alloc__(const struct dpif_sflow_attr *sflow, uint32_t hash) +{ + struct gid_node *node = xzalloc(sizeof *node); + + node->hash = hash; + ovs_refcount_init(&node->refcount); + dpif_sflow_attr_clone(CONST_CAST(struct dpif_sflow_attr *, &node->sflow), + sflow); + + ovs_rwlock_wrlock(&gid_rwlock); + for (;;) { + node->id = next_group_id++; + if (OVS_UNLIKELY(!node->id)) { + next_group_id = 1; + node->id = next_group_id++; + } + /* Find if the id is free. */ + if (OVS_LIKELY(!gid_find__(node->id))) { + break; + } + } + cmap_insert(&gid_map, &node->id_node, node->id); + cmap_insert(&gid_metadata_map, &node->metadata_node, node->hash); + ovs_rwlock_unlock(&gid_rwlock); + return node; +} + +/* Allocate a unique group id for the given set of flow metadata and + optional actions. */ +static uint32_t +gid_alloc_ctx(const struct dpif_sflow_attr *sflow) +{ + uint32_t hash = dpif_sflow_attr_hash(sflow); + struct gid_node *node = gid_ref_equal(sflow, hash); + + if (!node) { + node = gid_alloc__(sflow, hash); + } + return node->id; +} + +static void +gid_node_unref(const struct gid_node *node_) + OVS_EXCLUDED(gid_rwlock) +{ + struct gid_node *node = CONST_CAST(struct gid_node *, node_); + + ovs_rwlock_wrlock(&gid_rwlock); + if (node && ovs_refcount_unref(&node->refcount) == 1) { + /* Prevent re-use of this node by removing the node from + * gid_metadata_map' */ + cmap_remove(&gid_metadata_map, &node->metadata_node, node->hash); + /* We keep the node in the 'gid_map' so that it can be found as + * long as it lingers, and add it to the 'gid_expiring' list. */ + ovs_list_insert(&gid_expiring, &node->exp_node); + } + ovs_rwlock_unlock(&gid_rwlock); +} + +static void +gid_free(uint32_t id) +{ + const struct gid_node *node; + + node = gid_find(id); + if (node) { + gid_node_unref(node); + } else { + VLOG_ERR("Freeing nonexistent group ID: %"PRIu32, id); + } +} + static bool is_internal_port(const char *type) { @@ -203,6 +454,9 @@ del_filter_and_ufid_mapping(struct tcf_id *id, const ovs_u128 *ufid) if (!err) { del_ufid_tc_mapping(ufid); } + if (id->sflow_group_id) { + gid_free(id->sflow_group_id); + } return err; } @@ -398,6 +652,8 @@ netdev_tc_flow_dump_create(struct netdev *netdev, *dump_out = dump; + gid_cleanup(); + return 0; } @@ -1797,6 +2053,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); + gid_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..cc2ad025d 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 sflow_group_id; }; static inline struct tcf_id From patchwork Mon Dec 14 09:39:38 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Mi X-Patchwork-Id: 1415879 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.136; helo=silver.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=nvidia.com Received: from silver.osuosl.org (smtp3.osuosl.org [140.211.166.136]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Cvby96sZWz9sSC for ; Mon, 14 Dec 2020 20:41:53 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by silver.osuosl.org (Postfix) with ESMTP id 73B512342E; Mon, 14 Dec 2020 09:41:52 +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 eCD1qqTOoS8k; Mon, 14 Dec 2020 09:41:45 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by silver.osuosl.org (Postfix) with ESMTP id 240592E1A7; Mon, 14 Dec 2020 09:40:29 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 0849FC013B; Mon, 14 Dec 2020 09:40:29 +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 5724DC163C for ; Mon, 14 Dec 2020 09:40:27 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id 46C4C87369 for ; Mon, 14 Dec 2020 09:40:27 +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 y+kq-pL-Dn0U for ; Mon, 14 Dec 2020 09:40:23 +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 9170787359 for ; Mon, 14 Dec 2020 09:40:06 +0000 (UTC) Received: from Internal Mail-Server by MTLPINE1 (envelope-from cmi@nvidia.com) with SMTP; 14 Dec 2020 11:40:01 +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 0BE9dhVm000334; Mon, 14 Dec 2020 11:39:59 +0200 From: Chris Mi To: dev@openvswitch.org Date: Mon, 14 Dec 2020 17:39:38 +0800 Message-Id: <20201214093940.15722-10-cmi@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201214093940.15722-1-cmi@nvidia.com> References: <20201214093940.15722-1-cmi@nvidia.com> MIME-Version: 1.0 Cc: elibr@nvidia.com, Chris Mi , roniba@nvidia.com, i.maximets@ovn.org Subject: [ovs-dev] [PATCH v8 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 | 43 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c index a81003a98..daaa1d1a1 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,7 @@ 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 netlink_field { int offset; @@ -2254,6 +2256,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) { @@ -2288,6 +2330,7 @@ netdev_tc_init_flow_api(struct netdev *netdev) block_id = get_block_id_from_netdev(netdev); probe_multi_mask_per_prio(ifindex); + netdev_tc_psample_init(); ovsthread_once_done(&once); } From patchwork Mon Dec 14 09:39:39 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Mi X-Patchwork-Id: 1415880 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.136; helo=silver.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=nvidia.com Received: from silver.osuosl.org (smtp3.osuosl.org [140.211.166.136]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4CvbzT6y5Sz9sSC for ; Mon, 14 Dec 2020 20:43:01 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by silver.osuosl.org (Postfix) with ESMTP id 68E4A273A9; Mon, 14 Dec 2020 09:43:00 +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 mLFRmJxA2++9; Mon, 14 Dec 2020 09:42:46 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by silver.osuosl.org (Postfix) with ESMTP id 576072E1CA; Mon, 14 Dec 2020 09:40:39 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 3AFCDC1D9F; Mon, 14 Dec 2020 09:40:39 +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 0BAE5C013B for ; Mon, 14 Dec 2020 09:40:38 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by silver.osuosl.org (Postfix) with ESMTP id E38FB20501 for ; Mon, 14 Dec 2020 09:40:37 +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 AtgVPVbswCIB for ; Mon, 14 Dec 2020 09:40:25 +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 3B05727484 for ; Mon, 14 Dec 2020 09:40:06 +0000 (UTC) Received: from Internal Mail-Server by MTLPINE1 (envelope-from cmi@nvidia.com) with SMTP; 14 Dec 2020 11:40:02 +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 0BE9dhVn000334; Mon, 14 Dec 2020 11:40:01 +0200 From: Chris Mi To: dev@openvswitch.org Date: Mon, 14 Dec 2020 17:39:39 +0800 Message-Id: <20201214093940.15722-11-cmi@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201214093940.15722-1-cmi@nvidia.com> References: <20201214093940.15722-1-cmi@nvidia.com> MIME-Version: 1.0 Cc: elibr@nvidia.com, Chris Mi , roniba@nvidia.com, i.maximets@ovn.org Subject: [ovs-dev] [PATCH v8 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 | 127 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 126 insertions(+), 1 deletion(-) diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c index daaa1d1a1..10e704e6a 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" @@ -2296,6 +2298,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 gid_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 = gid_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) { @@ -2325,12 +2444,18 @@ netdev_tc_init_flow_api(struct netdev *netdev) tc_add_del_qdisc(ifindex, false, 0, hook); if (ovsthread_once_start(&once)) { + struct nl_sock *sock; + probe_tc_block_support(ifindex); /* Need to re-fetch block id as it depends on feature availability. */ block_id = get_block_id_from_netdev(netdev); probe_multi_mask_per_prio(ifindex); - netdev_tc_psample_init(); + sock = netdev_tc_psample_init(); + if (sock) { + ovs_thread_create("psample_handler", netdev_tc_psample_handler, + sock); + } ovsthread_once_done(&once); } From patchwork Mon Dec 14 09:39:40 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Mi X-Patchwork-Id: 1415878 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=openvswitch.org (client-ip=140.211.166.133; helo=hemlock.osuosl.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=nvidia.com Received: from hemlock.osuosl.org (smtp2.osuosl.org [140.211.166.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Cvbwk0Zcsz9sSf for ; Mon, 14 Dec 2020 20:40:38 +1100 (AEDT) Received: from localhost (localhost [127.0.0.1]) by hemlock.osuosl.org (Postfix) with ESMTP id 76FEE874A6; Mon, 14 Dec 2020 09:40:36 +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 CdQZMpIbnJqO; Mon, 14 Dec 2020 09:40:33 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by hemlock.osuosl.org (Postfix) with ESMTP id 7C01A874E6; Mon, 14 Dec 2020 09:40:33 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id 508B7C1DA0; Mon, 14 Dec 2020 09:40:33 +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 77192C163C for ; Mon, 14 Dec 2020 09:40:31 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by whitealder.osuosl.org (Postfix) with ESMTP id 5B92F871EC for ; Mon, 14 Dec 2020 09:40:31 +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 FtnigsPtyO+v for ; Mon, 14 Dec 2020 09:40:24 +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 A91D387363 for ; Mon, 14 Dec 2020 09:40:06 +0000 (UTC) Received: from Internal Mail-Server by MTLPINE1 (envelope-from cmi@nvidia.com) with SMTP; 14 Dec 2020 11:40:04 +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 0BE9dhVo000334; Mon, 14 Dec 2020 11:40:02 +0200 From: Chris Mi To: dev@openvswitch.org Date: Mon, 14 Dec 2020 17:39:40 +0800 Message-Id: <20201214093940.15722-12-cmi@nvidia.com> X-Mailer: git-send-email 2.26.2 In-Reply-To: <20201214093940.15722-1-cmi@nvidia.com> References: <20201214093940.15722-1-cmi@nvidia.com> MIME-Version: 1.0 Cc: elibr@nvidia.com, Chris Mi , roniba@nvidia.com, i.maximets@ovn.org Subject: [ovs-dev] [PATCH v8 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 | 170 +++++++++++++++++++++++++++++++++++++--- lib/tc.c | 61 +++++++++++++- lib/tc.h | 9 ++- 3 files changed, 225 insertions(+), 15 deletions(-) diff --git a/lib/netdev-offload-tc.c b/lib/netdev-offload-tc.c index 10e704e6a..e379b46b6 100644 --- a/lib/netdev-offload-tc.c +++ b/lib/netdev-offload-tc.c @@ -989,6 +989,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 gid_node *node; + + node = gid_find(action->sample.action_group_id); + if (!node) { + VLOG_ERR_RL(&error_rl, "gid node is NULL, gid: %d", + action->sample.action_group_id); + return ENOENT; + } + nl_msg_put(buf, node->sflow.sflow, node->sflow.sflow_len); + } + break; case TC_ACT_VLAN_POP: { nl_msg_put_flag(buf, OVS_ACTION_ATTR_POP_VLAN); } @@ -1668,6 +1680,118 @@ 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_sflow_cookie(const struct nlattr *actions, + struct dpif_sflow_attr *sflow_attr) +{ + 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; + } + } + } + + return EINVAL; +} + +static int +parse_sample_action_userspace(const struct nlattr *actions, + struct dpif_sflow_attr *sflow_attr) +{ + const struct nlattr *nla; + unsigned int left; + + NL_NESTED_FOR_EACH_UNSAFE (nla, left, actions) { + if (nl_attr_type(nla) == OVS_ACTION_ATTR_USERSPACE) { + return parse_sflow_cookie(nla, sflow_attr); + } + } + + VLOG_ERR_RL(&error_rl, "%s: no OVS_ACTION_ATTR_USERSPACE attribute", + __func__); + return EINVAL; +} + +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) +{ + struct dpif_sflow_attr sflow_attr; + const struct nlattr *nla; + unsigned int left; + int ret = EINVAL; + + memset(&sflow_attr, 0, sizeof sflow_attr); + sflow_attr.sflow = sample_action; + sflow_attr.sflow_len = sample_action->nla_len; + + 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_action_userspace(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 = gid_alloc_ctx(&sflow_attr); + 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 *sample_action, + const struct flow_tnl *tnl, uint32_t *group_id) +{ + struct dpif_sflow_attr sflow_attr; + int err; + + /* 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_sflow_cookie(sample_action, &sflow_attr); + if (err) { + return err; + } + sflow_attr.sflow = sample_action; + sflow_attr.sflow_len = sample_action->nla_len; + *group_id = gid_alloc_ctx(&sflow_attr); + 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, @@ -1684,6 +1808,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 group_id = 0; struct nlattr *nla; struct tcf_id id; uint32_t chain; @@ -1973,7 +2098,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) { @@ -1983,7 +2109,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)); @@ -2021,7 +2148,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; @@ -2034,7 +2161,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); @@ -2042,7 +2169,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; @@ -2058,20 +2185,27 @@ 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); - gid_alloc_ctx(&sflow_attr); + err = parse_sample_action(&flower, action, nla, tnl, &group_id); + if (err) { + goto out; + } + } else if (nl_attr_type(nla) == OVS_ACTION_ATTR_USERSPACE) { + err = parse_userspace_action(&flower, action, nla, tnl, &group_id); + 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) { @@ -2083,20 +2217,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_chain(ifindex, block_id, chain, prio, hook, group_id); 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 (group_id) { + gid_free(group_id); } 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 cc2ad025d..143e225d1 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; @@ -292,11 +298,12 @@ 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) + uint16_t prio, enum tc_qdisc_hook hook, uint32_t group_id) { struct tcf_id id = tc_make_tcf_id(ifindex, block_id, prio, hook); id.chain = chain; + id.sflow_group_id = group_id; return id; }