From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 5C35DA00C2; Mon, 2 Jan 2023 18:01:56 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 024DB42B7E; Mon, 2 Jan 2023 18:01:56 +0100 (CET) Received: from mail-pl1-f170.google.com (mail-pl1-f170.google.com [209.85.214.170]) by mails.dpdk.org (Postfix) with ESMTP id 1806140693 for ; Mon, 2 Jan 2023 18:01:55 +0100 (CET) Received: by mail-pl1-f170.google.com with SMTP id d3so30043954plr.10 for ; Mon, 02 Jan 2023 09:01:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=networkplumber-org.20210112.gappssmtp.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=2PVTZ1GK7GrmEhsN+wHUATqopNjUmZLq/v5eEWLBlH8=; b=ZnGCGL97gmvsRjZQlBVen4KZJBbiZN3l4/rHgyTPjvbLDwLtboYbWqFnkAoE/DjgF8 ni2KPPZe4C9chpamtuAV3utcnQLE2CNPtKdPtR0NyW6s+8PkByFFutpF/kcPFaDn7B4h UsrtUpMQx2KyvOO+BopJvtxFbxyATKU5ldPZIPlnI+GkuCwhj8i+M4uxkOVvO7oPwneD /vpIZpIenFrgXma4iLPESDxrU+HGfKN1FJwgFS0HauWZAqWwE1w/5kNbbbxFo3v28sWj bWktocbFBB4zng/irhjIYcc/TSk7I8RPhi057Lc2QJaCqGvIA59oJiXOjJP6YElQMQdQ JisQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=2PVTZ1GK7GrmEhsN+wHUATqopNjUmZLq/v5eEWLBlH8=; b=Zxl316kreHZj24qJUZu3TF5FJ751+XtcoQqB5E2DoWi0RP0HL2jn3yoRosFLyQ9B+T l3wfz/ipBTJyRNHvivcKo35xrWzPbYuwGgyBHL2s+1UQImHpT6NUkAurY9ieLGchXto9 9YJ6flGhEfu1rY0CHx8oS/LM0uw/eNtXwQhx9lRftwFHkFTnz4tq3AAmlLnvPcsrxy/K 9FUlLoUNDCfZyE6Iyovqw9/5Es8ajFL1WdZV71m/QA7VMrc/L2eRpjmtY7UZm7morRDI uSXYyMXkNMhMv0QyNIFN3UOWWvydJ7jE/aJ243aoaUChg9ZKgGZqI/Pzo2c8RujB1Q3p S/LQ== X-Gm-Message-State: AFqh2kqi4wn2p9ypmqTSg7KFrX53X9JItEcGj5Q/qzAl1Nx/y9vVghwd Z+UBbpeNbfrXFlxRZ0AHXoe8kA== X-Google-Smtp-Source: AMrXdXvBWYNszwJ1HTrcsr7olGrxeYWxleJbfou0I3KUAo0epnSVuWxsggV0kt+ekIMciC2kA3uzGA== X-Received: by 2002:a17:902:7805:b0:191:bb:c207 with SMTP id p5-20020a170902780500b0019100bbc207mr41615263pll.37.1672678914213; Mon, 02 Jan 2023 09:01:54 -0800 (PST) Received: from hermes.local (204-195-120-218.wavecable.com. [204.195.120.218]) by smtp.gmail.com with ESMTPSA id j7-20020a170902da8700b0017f756563bcsm20508204plx.47.2023.01.02.09.01.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 02 Jan 2023 09:01:53 -0800 (PST) From: Stephen Hemminger To: Ben Magistro Cc: dev@dpdk.org, Stephen Hemminger Subject: [RFT] dumpcap: fix multiple interface and promiscious handling Date: Mon, 2 Jan 2023 09:01:53 -0800 Message-Id: <20230102170153.29308-1-stephen@networkplumber.org> X-Mailer: git-send-email 2.39.0 In-Reply-To: <20230102162441.6205-1-koncept1@gmail.com> References: <20230102162441.6205-1-koncept1@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org The code to handle multiple interfaces needs to setup the interface list when command line is parsed, otherwise multiple interfaces won't work. Dumpcap enables promiscuous on a port, and then always resets it on exit. If the device was already in promiscuous mode, then don't change it. The handling of the -p flag should match what dumpcap does. Fixes: 499b1cbcf9d3 ("app/dumpcap: check for failure to set promiscuous") Signed-off-by: Stephen Hemminger --- app/dumpcap/main.c | 98 ++++++++++++++++++++++++---------------------- 1 file changed, 52 insertions(+), 46 deletions(-) diff --git a/app/dumpcap/main.c b/app/dumpcap/main.c index 2eb8414efaa5..33125710428e 100644 --- a/app/dumpcap/main.c +++ b/app/dumpcap/main.c @@ -65,8 +65,6 @@ static const char *file_prefix; static uint32_t snaplen = RTE_MBUF_DEFAULT_BUF_SIZE; static bool dump_bpf; static bool show_interfaces; -static bool select_interfaces; -const char *interface_arg; static struct { uint64_t duration; /* nanoseconds */ @@ -83,6 +81,7 @@ static size_t file_size; struct interface { TAILQ_ENTRY(interface) next; uint16_t port; + bool promisc_mode; char name[RTE_ETH_NAME_MAX_LEN]; struct rte_rxtx_callback *rx_cb[RTE_MAX_QUEUES_PER_PORT]; @@ -90,7 +89,6 @@ struct interface { TAILQ_HEAD(interface_list, interface); static struct interface_list interfaces = TAILQ_HEAD_INITIALIZER(interfaces); -static struct interface *port2intf[RTE_MAX_ETHPORTS]; /* Can do either pcap or pcapng format output */ typedef union { @@ -197,29 +195,36 @@ static void add_interface(uint16_t port, const char *name) { struct interface *intf; + if (strlen(name) >= RTE_ETH_NAME_MAX_LEN) + rte_exit(EXIT_FAILURE, "invalid name for interface: '%s'\n", name); + intf = malloc(sizeof(*intf)); if (!intf) rte_exit(EXIT_FAILURE, "no memory for interface\n"); memset(intf, 0, sizeof(*intf)); rte_strscpy(intf->name, name, sizeof(intf->name)); + intf->promisc_mode = promiscuous_mode; + intf->port = port; /* set later */ - printf("Capturing on '%s'\n", name); - - port2intf[port] = intf; TAILQ_INSERT_TAIL(&interfaces, intf, next); } -/* Select all valid DPDK interfaces */ -static void select_all_interfaces(void) +/* Name has been set but need to lookup port after eal_init */ +static void find_interfaces(void) { - char name[RTE_ETH_NAME_MAX_LEN]; - uint16_t p; + struct interface *intf; - RTE_ETH_FOREACH_DEV(p) { - if (rte_eth_dev_get_name_by_port(p, name) < 0) + TAILQ_FOREACH(intf, &interfaces, next) { + /* if name is valid then just record port */ + if (rte_eth_dev_get_port_by_name(intf->name, &intf->port) == 0) continue; - add_interface(p, name); + + /* maybe got passed port number string as name */ + intf->port = get_uint(intf->name, "port_number", UINT16_MAX); + if (rte_eth_dev_get_name_by_port(intf->port, intf->name) < 0) + rte_exit(EXIT_FAILURE, "Invalid port number %u\n", + intf->port); } } @@ -235,32 +240,13 @@ static void set_default_interface(void) RTE_ETH_FOREACH_DEV(p) { if (rte_eth_dev_get_name_by_port(p, name) < 0) continue; + add_interface(p, name); return; } rte_exit(EXIT_FAILURE, "No usable interfaces found\n"); } -/* Lookup interface by name or port and add it to the list */ -static void select_interface(const char *arg) -{ - uint16_t port; - - if (strcmp(arg, "*") == 0) - select_all_interfaces(); - else if (rte_eth_dev_get_port_by_name(arg, &port) == 0) - add_interface(port, arg); - else { - char name[RTE_ETH_NAME_MAX_LEN]; - - port = get_uint(arg, "port_number", UINT16_MAX); - if (rte_eth_dev_get_name_by_port(port, name) < 0) - rte_exit(EXIT_FAILURE, "Invalid port number %u\n", - port); - add_interface(port, name); - } -} - /* Display list of possible interfaces that can be used. */ static void dump_interfaces(void) { @@ -377,8 +363,7 @@ static void parse_opts(int argc, char **argv) usage(); exit(0); case 'i': - select_interfaces = true; - interface_arg = optarg; + add_interface(-1, optarg); break; case 'n': use_pcapng = true; @@ -387,7 +372,22 @@ static void parse_opts(int argc, char **argv) ring_size = get_uint(optarg, "packet_limit", 0); break; case 'p': - promiscuous_mode = false; + /* Like dumpcap this option can occur multiple times. + * + * If used before the first occurrence of the -i option, + * no interface will be put into the promiscuous mode. + * If used after an -i option, the interface specified + * by the last -i option occurring before this option + * will not be put into the promiscuous mode. + */ + if (TAILQ_EMPTY(&interfaces)) { + promiscuous_mode = false; + } else { + struct interface *intf; + + intf = TAILQ_LAST(&interfaces, interface_list); + intf->promisc_mode = false; + } break; case 'P': use_pcapng = false; @@ -436,7 +436,7 @@ cleanup_pdump_resources(void) TAILQ_FOREACH(intf, &interfaces, next) { rte_pdump_disable(intf->port, RTE_PDUMP_ALL_QUEUES, RTE_PDUMP_FLAG_RXTX); - if (promiscuous_mode) + if (intf->promisc_mode) rte_eth_promiscuous_disable(intf->port); } } @@ -696,12 +696,17 @@ static void enable_pdump(struct rte_ring *r, struct rte_mempool *mp) flags |= RTE_PDUMP_FLAG_PCAPNG; TAILQ_FOREACH(intf, &interfaces, next) { - if (promiscuous_mode) { - ret = rte_eth_promiscuous_enable(intf->port); - if (ret != 0) - fprintf(stderr, - "port %u set promiscuous enable failed: %d\n", - intf->port, ret); + if (intf->promisc_mode) { + if (rte_eth_promiscuous_get(intf->port) == 1) { + /* promiscuous already enabled */ + intf->promisc_mode = false; + } else { + ret = rte_eth_promiscuous_enable(intf->port); + if (ret != 0) + fprintf(stderr, + "port %u set promiscuous enable failed: %d\n", + intf->port, ret); + } } ret = rte_pdump_enable_bpf(intf->port, RTE_PDUMP_ALL_QUEUES, @@ -711,6 +716,8 @@ static void enable_pdump(struct rte_ring *r, struct rte_mempool *mp) rte_exit(EXIT_FAILURE, "Packet dump enable failed: %s\n", rte_strerror(-ret)); + + printf("Capturing on '%s'\n", intf->name); } } @@ -817,14 +824,13 @@ int main(int argc, char **argv) if (rte_eth_dev_count_avail() == 0) rte_exit(EXIT_FAILURE, "No Ethernet ports found\n"); - if (select_interfaces) - select_interface(interface_arg); - if (filter_str) compile_filter(); if (TAILQ_EMPTY(&interfaces)) set_default_interface(); + else + find_interfaces(); r = create_ring(); mp = create_mempool(); -- 2.39.0