From patchwork Thu Sep 24 10:24:12 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chris Mi X-Patchwork-Id: 1370590 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 4Bxrl6723mz9sTN for ; Thu, 24 Sep 2020 20:24:50 +1000 (AEST) Received: from localhost (localhost [127.0.0.1]) by silver.osuosl.org (Postfix) with ESMTP id 573572E144; Thu, 24 Sep 2020 10:24:49 +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 tbhHteuiey9T; Thu, 24 Sep 2020 10:24:36 +0000 (UTC) Received: from lists.linuxfoundation.org (lf-lists.osuosl.org [140.211.9.56]) by silver.osuosl.org (Postfix) with ESMTP id B988B2E103; Thu, 24 Sep 2020 10:24:35 +0000 (UTC) Received: from lf-lists.osuosl.org (localhost [127.0.0.1]) by lists.linuxfoundation.org (Postfix) with ESMTP id AE109C0889; Thu, 24 Sep 2020 10:24:35 +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 37355C0051 for ; Thu, 24 Sep 2020 10:24:34 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by hemlock.osuosl.org (Postfix) with ESMTP id 21CAF874E6 for ; Thu, 24 Sep 2020 10:24:34 +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 0xLX1IzB6OBW for ; Thu, 24 Sep 2020 10:24: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 hemlock.osuosl.org (Postfix) with ESMTP id 0E3ED874E4 for ; Thu, 24 Sep 2020 10:24:32 +0000 (UTC) Received: from Internal Mail-Server by MTLPINE1 (envelope-from cmi@nvidia.com) with SMTP; 24 Sep 2020 13:24:29 +0300 Received: from dev-r630-04.mtbc.labs.mlnx (dev-r630-04.mtbc.labs.mlnx [10.75.205.14]) by labmailer.mlnx (8.13.8/8.13.8) with ESMTP id 08OAOJfc016057; Thu, 24 Sep 2020 13:24:28 +0300 From: Chris Mi To: dev@openvswitch.org Date: Thu, 24 Sep 2020 18:24:12 +0800 Message-Id: <20200924102415.23528-7-cmi@nvidia.com> X-Mailer: git-send-email 2.21.1 In-Reply-To: <20200924102415.23528-1-cmi@nvidia.com> References: <20200924102415.23528-1-cmi@nvidia.com> MIME-Version: 1.0 Cc: elibr@nvidia.com, Chris Mi Subject: [ovs-dev] [PATCH v4 6/9] dpif-netlink: Implement psample offload 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 offload API to receive sampled packet from psample netlink socket. Parse sampled packet to ovs format. Signed-off-by: Chris Mi Reviewed-by: Eli Britstein --- lib/dpif-netlink.c | 133 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 130 insertions(+), 3 deletions(-) diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index 55199d35e..fc08623ea 100644 --- a/lib/dpif-netlink.c +++ b/lib/dpif-netlink.c @@ -4016,6 +4016,133 @@ probe_broken_meters(struct dpif *dpif) } return broken_meters; } + +struct dpif_netlink_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 bool +dpif_netlink_psample_enabled(const struct dpif *dpif_) +{ + struct dpif_netlink *dpif = dpif_netlink_cast(dpif_); + + return dpif->psample_sock != NULL; +} + +static int +dpif_netlink_psample_from_ofpbuf(struct dpif_netlink_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 +parse_psample_packet(struct dpif_netlink *dpif, + struct dpif_netlink_psample *psample, + struct dpif_upcall_psample *dupcall) +{ + const char *dpif_type_str = dpif_normalize_type(dpif_type(&dpif->dpif)); + struct netdev *dev; + odp_port_t port; + + 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)); + + dupcall->iifindex = psample->iifindex; + port = netdev_ifindex_to_odp_port(dupcall->iifindex); + dev = netdev_ports_get(port, dpif_type_str); + if (!dev) { + return EOPNOTSUPP; + } + dupcall->sflow_attr = netdev_sflow_attr_get(dev, psample->dp_group_id); + netdev_close(dev); + + return 0; +} + +static int +dpif_netlink_psample_poll(const struct dpif *dpif_, + struct dpif_upcall_psample *dupcall) +{ + for (;;) { + static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); + struct dpif_netlink *dpif = dpif_netlink_cast(dpif_); + struct dpif_netlink_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(dpif->psample_sock, &buf, NULL, false); + + if (!error) { + error = dpif_netlink_psample_from_ofpbuf(&psample, &buf); + if (!error) { + ofpbuf_uninit(&buf); + error = parse_psample_packet(dpif, &psample, dupcall); + return error; + } + } else if (error != EAGAIN) { + VLOG_WARN_RL(&rl, "error reading or parsing netlink (%s)", + ovs_strerror(error)); + nl_sock_drain(dpif->psample_sock); + error = ENOBUFS; + } + + ofpbuf_uninit(&buf); + if (error) { + return error; + } + } +} + +static void +dpif_netlink_psample_poll_wait(const struct dpif *dpif_) +{ + const struct dpif_netlink *dpif = dpif_netlink_cast(dpif_); + + if (dpif->psample_sock) { + nl_sock_wait(dpif->psample_sock, POLLIN); + } else { + poll_immediate_wake(); + } +} + const struct dpif_class dpif_netlink_class = { "system", @@ -4093,9 +4220,9 @@ const struct dpif_class dpif_netlink_class = { NULL, /* bond_add */ NULL, /* bond_del */ NULL, /* bond_stats_get */ - NULL, /* psample_enabled */ - NULL, /* psample_poll */ - NULL, /* psample_poll_wait */ + dpif_netlink_psample_enabled, + dpif_netlink_psample_poll, + dpif_netlink_psample_poll_wait, }; static int