From patchwork Sun Feb 4 16:22:42 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Darrell Ball X-Patchwork-Id: 869051 X-Patchwork-Delegate: ian.stokes@intel.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=openvswitch.org (client-ip=140.211.169.12; helo=mail.linuxfoundation.org; envelope-from=ovs-dev-bounces@openvswitch.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="n817rfSs"; dkim-atps=neutral Received: from mail.linuxfoundation.org (mail.linuxfoundation.org [140.211.169.12]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3zZGN810C9z9s7v for ; Mon, 5 Feb 2018 03:27:36 +1100 (AEDT) Received: from mail.linux-foundation.org (localhost [127.0.0.1]) by mail.linuxfoundation.org (Postfix) with ESMTP id 4A56F100C; Sun, 4 Feb 2018 16:23:11 +0000 (UTC) X-Original-To: dev@openvswitch.org Delivered-To: ovs-dev@mail.linuxfoundation.org Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id 880BCFE8 for ; Sun, 4 Feb 2018 16:23:08 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-pl0-f65.google.com (mail-pl0-f65.google.com [209.85.160.65]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id CC737305 for ; Sun, 4 Feb 2018 16:23:07 +0000 (UTC) Received: by mail-pl0-f65.google.com with SMTP id 11so10123061plc.9 for ; Sun, 04 Feb 2018 08:23:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references; bh=hRaxjMwutepRK1troeUqgp0Mvufzt2VaACCfJUOTFNg=; b=n817rfSsbobG6XOhJLwuhlkQpYWX6lOhxd1B4rsxtwIh2ffiTUxccHWqBWkr+JmGy7 kOoxCD7qffEUNc6JHUVUNzxxS0AeXoRrT6Tl/YLTros6jr2427sVtOXv8lbB/S2RfZV1 FDXu2FhyFocTUmEt6RAFQPz4KfJZp1Xn+KPqOQKAyIyAs3kbWbxvOl9kivASG517vwTI Z8uafmmnBPLbNsisU1jvdH0c+ABUWd4b7d/7PKX8a5QBtmNxA2PRqsFrCRuFF3egwz58 M5W7/A7ejqiH3X+GfwfXld2tLoLU62sZTNOYYDpYLQQARjuySSkOpmHlWnGM/aOe0Xt4 S9KA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=hRaxjMwutepRK1troeUqgp0Mvufzt2VaACCfJUOTFNg=; b=K3N44iwxVb/gQ9lg+m+2kgqvrn5m67kS8q0E7PnqudWBnvYhREAoTZI4BLUMQrUagc nsDzfTEuXIdqLngpbAgZpxjuz+yZPgf+NTmaTYLxD6rPlCZhYfbnI3FjcJAB5axYfw0i azImfjk6Yznr2yZ7CpeGsv50RBaFpbJ9+90Zu7o1CinF7FSJ1UoYXfX5r55NTRF5Ep8A k6tiRQSbAznPAuQgFgXEwi5gVOxyxBctFs0x1M3zwABqrdagsrswUS9Vqaeri28yS1gR Xcu6+A/tIpIG2neWwHCBTW5JdFekPbynKy2DeDTPfxJpWCmjfybJhBXg1KneCZrLFmfq FHKQ== X-Gm-Message-State: AKwxytcHbjCaTYih5msXoxXEoK8nxVU6LTeg9IkatqVROFFq39E3kyxZ YvGKasCc4FF304ntoH+UO78qyg== X-Google-Smtp-Source: AH8x226mBRj9pswMd6DY4XAV+SCTwI/Bi4APEBIbFgYRmCRhOp6XaBoNZMJ5L0Yf2eCLqclx+rAbcA== X-Received: by 2002:a17:902:2884:: with SMTP id f4-v6mr18898876plb.35.1517761387490; Sun, 04 Feb 2018 08:23:07 -0800 (PST) Received: from ubuntu.localdomain (c-73-162-236-45.hsd1.ca.comcast.net. [73.162.236.45]) by smtp.gmail.com with ESMTPSA id e9sm10109503pgv.14.2018.02.04.08.23.06 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sun, 04 Feb 2018 08:23:06 -0800 (PST) From: Darrell Ball To: dlu998@gmail.com, dev@openvswitch.org Date: Sun, 4 Feb 2018 08:22:42 -0800 Message-Id: <1517761364-17655-10-git-send-email-dlu998@gmail.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1517761364-17655-1-git-send-email-dlu998@gmail.com> References: <1517761364-17655-1-git-send-email-dlu998@gmail.com> X-Spam-Status: No, score=-1.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_ENVFROM_END_DIGIT,FREEMAIL_FROM, RCVD_IN_DNSWL_NONE autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org Subject: [ovs-dev] [patch v5 09/11] ipf: Enhance ipf_get_status. X-BeenThere: ovs-dev@openvswitch.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: ovs-dev-bounces@openvswitch.org Errors-To: ovs-dev-bounces@openvswitch.org A verbose option is added to dump the frag lists. Signed-off-by: Darrell Ball --- lib/ct-dpif.c | 24 +++++++++++++++++ lib/ct-dpif.h | 4 +++ lib/dpctl.c | 37 ++++++++++++++++++++++++-- lib/dpctl.man | 5 ++-- lib/dpif-netdev.c | 25 ++++++++++++++++++ lib/dpif-netlink.c | 3 +++ lib/dpif-provider.h | 5 ++++ lib/ipf.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/ipf.h | 11 ++++++++ 9 files changed, 186 insertions(+), 4 deletions(-) diff --git a/lib/ct-dpif.c b/lib/ct-dpif.c index 60c8986..adcf42b 100644 --- a/lib/ct-dpif.c +++ b/lib/ct-dpif.c @@ -209,6 +209,30 @@ int ct_dpif_ipf_get_status(struct dpif *dpif, bool *ipf_v4_enabled, : EOPNOTSUPP); } +int +ct_dpif_ipf_dump_start(struct dpif *dpif, struct ipf_dump_ctx **dump_ctx) +{ + return (dpif->dpif_class->ipf_dump_start + ? dpif->dpif_class->ipf_dump_start(dpif, dump_ctx) + : EOPNOTSUPP); +} + +int +ct_dpif_ipf_dump_next(struct dpif *dpif, void *dump_ctx, char **dump) +{ + return (dpif->dpif_class->ipf_dump_next + ? dpif->dpif_class->ipf_dump_next(dpif, dump_ctx, dump) + : EOPNOTSUPP); +} + +int +ct_dpif_ipf_dump_done(struct dpif *dpif, void *dump_ctx) +{ + return (dpif->dpif_class->ipf_dump_done + ? dpif->dpif_class->ipf_dump_done(dpif, dump_ctx) + : EOPNOTSUPP); +} + void ct_dpif_entry_uninit(struct ct_dpif_entry *entry) { diff --git a/lib/ct-dpif.h b/lib/ct-dpif.h index 8a24128..0db17d9 100644 --- a/lib/ct-dpif.h +++ b/lib/ct-dpif.h @@ -17,6 +17,7 @@ #ifndef CT_DPIF_H #define CT_DPIF_H +#include "ipf.h" #include "openvswitch/types.h" #include "packets.h" @@ -209,6 +210,9 @@ int ct_dpif_ipf_get_status(struct dpif *dpif, bool *, unsigned int *, unsigned int *, bool *, unsigned int *, unsigned int *, unsigned int *, unsigned int *, unsigned int *, unsigned int *); +int ct_dpif_ipf_dump_start(struct dpif *dpif, struct ipf_dump_ctx **); +int ct_dpif_ipf_dump_next(struct dpif *dpif, void *, char **); +int ct_dpif_ipf_dump_done(struct dpif *dpif, void *); void ct_dpif_entry_uninit(struct ct_dpif_entry *); void ct_dpif_format_entry(const struct ct_dpif_entry *, struct ds *, bool verbose, bool print_stats); diff --git a/lib/dpctl.c b/lib/dpctl.c index 8860903..58b4ba9 100644 --- a/lib/dpctl.c +++ b/lib/dpctl.c @@ -35,6 +35,7 @@ #include "dpif.h" #include "openvswitch/dynamic-string.h" #include "flow.h" +#include "ipf.h" #include "openvswitch/match.h" #include "netdev.h" #include "netdev-dpdk.h" @@ -1851,12 +1852,37 @@ dpctl_ct_ipf_set_nfrag_max(int argc, const char *argv[], return error; } +static void +dpctl_dump_ipf(struct dpif *dpif, struct dpctl_params *dpctl_p) +{ + struct ipf_dump_ctx *dump_ctx; + char *dump; + + int error = ct_dpif_ipf_dump_start(dpif, &dump_ctx); + if (error) { + dpctl_error(dpctl_p, error, "starting ipf dump"); + return; + } + + dpctl_print(dpctl_p, "\n\tFragment Lists:\n\n"); + while (!(error = ct_dpif_ipf_dump_next(dpif, dump_ctx, &dump))) { + dpctl_print(dpctl_p, "%s\n", dump); + free(dump); + } + + if (error && error != EOF) { + dpctl_error(dpctl_p, error, "dumping ipf entry"); + } + + ct_dpif_ipf_dump_done(dpif, dump_ctx); +} + static int dpctl_ct_ipf_get_status(int argc, const char *argv[], struct dpctl_params *dpctl_p) { struct dpif *dpif; - int error = dpctl_ct_open_dp(argc, argv, dpctl_p, &dpif, 2); + int error = dpctl_ct_open_dp(argc, argv, dpctl_p, &dpif, 3); if (!error) { bool ipf_v4_enabled; unsigned int min_v4_frag_size; @@ -1915,7 +1941,13 @@ dpctl_ct_ipf_get_status(int argc, const char *argv[], } else { dpctl_error(dpctl_p, error, "ipf status could not be retrieved"); + return error; + } + + if (argc > 1 && !strncmp(argv[argc - 1], "verbose", 7)) { + dpctl_dump_ipf(dpif, dpctl_p); } + dpif_close(dpif); } @@ -2227,7 +2259,8 @@ static const struct dpctl_command all_commands[] = { dpctl_ct_ipf_set_min_frag, DP_RW }, { "ipf-set-maxfrags", "[dp] maxfrags", 1, 2, dpctl_ct_ipf_set_nfrag_max, DP_RW }, - { "ipf-get-status", "[dp]", 0, 1, dpctl_ct_ipf_get_status, DP_RO }, + { "ipf-get-status", "[dp] [verbose]", 0, 2, dpctl_ct_ipf_get_status, + DP_RO }, { "help", "", 0, INT_MAX, dpctl_help, DP_RO }, { "list-commands", "", 0, INT_MAX, dpctl_list_commands, DP_RO }, diff --git a/lib/dpctl.man b/lib/dpctl.man index e56eb26..8cb144a 100644 --- a/lib/dpctl.man +++ b/lib/dpctl.man @@ -296,6 +296,7 @@ module while fragments are incomplete, but will timeout after 15 seconds. Memory pool sizing should be set accordingly when fragmentation is enabled. . .TP -\*(DX\fBipf\-get\-status\fR [\fIdp\fR] +\*(DX\fBipf\-get\-status\fR [\fIdp\fR] [\fIverbose\fR] Gets the configuration settings and fragment counters associated with the -fragmentation handling of the userspace datapath connection tracker. +fragmentation handling of the userspace datapath connection tracker. If +verbose is specified, also dumps the ipf list entries. diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c index 5add8ee..7dd4784 100644 --- a/lib/dpif-netdev.c +++ b/lib/dpif-netdev.c @@ -5925,6 +5925,28 @@ dpif_netdev_ipf_get_status(struct dpif *dpif OVS_UNUSED, return 0; } +static int +dpif_netdev_ipf_dump_start(struct dpif *dpif OVS_UNUSED, + struct ipf_dump_ctx **ipf_dump_ctx) +{ + return ipf_dump_start(ipf_dump_ctx); +} + +static int +dpif_netdev_ipf_dump_next(struct dpif *dpif OVS_UNUSED, + void *ipf_dump_ctx, char **dump) +{ + return ipf_dump_next(ipf_dump_ctx, dump); +} + +static int +dpif_netdev_ipf_dump_done(struct dpif *dpif OVS_UNUSED, + void *ipf_dump_ctx) +{ + return ipf_dump_done(ipf_dump_ctx); + +} + const struct dpif_class dpif_netdev_class = { "netdev", dpif_netdev_init, @@ -5977,6 +5999,9 @@ const struct dpif_class dpif_netdev_class = { dpif_netdev_ipf_set_min_frag, dpif_netdev_ipf_set_nfrag_max, dpif_netdev_ipf_get_status, + dpif_netdev_ipf_dump_start, + dpif_netdev_ipf_dump_next, + dpif_netdev_ipf_dump_done, dpif_netdev_meter_get_features, dpif_netdev_meter_set, dpif_netdev_meter_get, diff --git a/lib/dpif-netlink.c b/lib/dpif-netlink.c index cac931c..16edd2c 100644 --- a/lib/dpif-netlink.c +++ b/lib/dpif-netlink.c @@ -2996,6 +2996,9 @@ const struct dpif_class dpif_netlink_class = { NULL, /* ipf_set_min_frag */ NULL, /* ipf_set_nfrag_max */ NULL, /* ipf_get_status */ + NULL, /* ipf_dump_start */ + NULL, /* ipf_dump_next */ + NULL, /* ipf_dump_done */ dpif_netlink_meter_get_features, dpif_netlink_meter_set, dpif_netlink_meter_get, diff --git a/lib/dpif-provider.h b/lib/dpif-provider.h index 82fbbfc..385394f 100644 --- a/lib/dpif-provider.h +++ b/lib/dpif-provider.h @@ -24,6 +24,7 @@ #include "openflow/openflow.h" #include "dpif.h" +#include "ipf.h" #include "util.h" #ifdef __cplusplus @@ -457,6 +458,10 @@ struct dpif_class { unsigned int *, bool *, unsigned int *, unsigned int *, unsigned int *, unsigned int *, unsigned int *, unsigned int *); + int (*ipf_dump_start)(struct dpif *, struct ipf_dump_ctx **); + /* Gets an ipf list entry to display. */ + int (*ipf_dump_next)(struct dpif *, void *, char **); + int (*ipf_dump_done)(struct dpif *, void *); /* Meters */ /* Queries 'dpif' for supported meter features. diff --git a/lib/ipf.c b/lib/ipf.c index dd92864..150d74b 100644 --- a/lib/ipf.c +++ b/lib/ipf.c @@ -52,6 +52,10 @@ enum ipf_list_state { IPF_LIST_STATE_NUM, }; +static char *ipf_state_name[IPF_LIST_STATE_NUM] = + {"unused", "reassemble fail", "other frag", "first frag", "last frag", + "first/last frag", "complete"}; + enum ipf_list_type { IPF_FRAG_COMPLETED_LIST, IPF_FRAG_EXPIRY_LIST, @@ -1312,3 +1316,75 @@ ipf_get_status(struct ipf_status *ipf_status) ipf_status->n6frag_overlap = atomic_count_get(&n6frag_overlap); return 0; } + +struct ipf_dump_ctx { + struct hmap_position bucket_pos; +}; + +int +ipf_dump_start(struct ipf_dump_ctx **ipf_dump_ctx) +{ + *ipf_dump_ctx = xzalloc(sizeof **ipf_dump_ctx); + return 0; +} + +static void +ipf_dump_create(const struct ipf_list *ipf_list, struct ds *ds) +{ + + ds_put_cstr(ds, "frag list elem=("); + if (ipf_list->key.dl_type == htons(ETH_TYPE_IP)) { + ds_put_format(ds, "src="IP_FMT",dst="IP_FMT",", + IP_ARGS(ipf_list->key.src_addr.ipv4_aligned), + IP_ARGS(ipf_list->key.dst_addr.ipv4_aligned)); + } else { + ds_put_cstr(ds, "src="); + ipv6_format_addr(&ipf_list->key.src_addr.ipv6_aligned, ds); + ds_put_cstr(ds, ",dst="); + ipv6_format_addr(&ipf_list->key.dst_addr.ipv6_aligned, ds); + ds_put_cstr(ds, ","); + } + + ds_put_format(ds, "recirc_id=%u,ip_id=%u,dl_type=0x%x,zone=%u,nw_proto=%u", + ipf_list->key.recirc_id, ntohl(ipf_list->key.ip_id), + ntohs(ipf_list->key.dl_type), ipf_list->key.zone, + ipf_list->key.nw_proto); + + ds_put_format(ds, ",num_fragments=%u,state=%s", + ipf_list->last_inuse_idx + 1, + ipf_state_name[ipf_list->state]); + + ds_put_cstr(ds, ")"); +} + +int +ipf_dump_next(struct ipf_dump_ctx *ipf_dump_ctx, char **dump) +{ + struct ds ds = DS_EMPTY_INITIALIZER; + ipf_lock_lock(&ipf_lock); + + for (;;) { + struct hmap_node *node = hmap_at_position(&frag_lists, + &ipf_dump_ctx->bucket_pos); + if (!node) { + ipf_lock_unlock(&ipf_lock); + return EOF; + } else { + struct ipf_list *ipf_list_; + INIT_CONTAINER(ipf_list_, node, node); + struct ipf_list ipf_list = *ipf_list_; + ipf_lock_unlock(&ipf_lock); + ipf_dump_create(&ipf_list, &ds); + *dump = xstrdup(ds.string); + ds_destroy(&ds); + return 0; + } + } +} + +int +ipf_dump_done(struct ipf_dump_ctx *ipf_dump_ctx) +{ + free(ipf_dump_ctx); + return 0; +} diff --git a/lib/ipf.h b/lib/ipf.h index a9fee06..866c711 100644 --- a/lib/ipf.h +++ b/lib/ipf.h @@ -72,4 +72,15 @@ ipf_set_nfrag_max(uint32_t value); int ipf_get_status(struct ipf_status *ipf_status); +struct ipf_dump_ctx; + +int +ipf_dump_start(struct ipf_dump_ctx **ipf_dump_ctx); + +int +ipf_dump_next(struct ipf_dump_ctx *ipf_dump_ctx, char **dump); + +int +ipf_dump_done(struct ipf_dump_ctx *ipf_dump_ctx); + #endif /* ipf.h */