From patchwork Thu May 28 15:05:20 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ivan Boule X-Patchwork-Id: 4934 Return-Path: X-Original-To: patchwork@dpdk.org Delivered-To: patchwork@dpdk.org Received: from [92.243.14.124] (localhost [IPv6:::1]) by dpdk.org (Postfix) with ESMTP id 1F07BC31C; Thu, 28 May 2015 17:05:36 +0200 (CEST) Received: from smtp-ft2.fr.colt.net (smtp-ft2.fr.colt.net [213.41.78.204]) by dpdk.org (Postfix) with ESMTP id E2240C30A for ; Thu, 28 May 2015 17:05:34 +0200 (CEST) Received: from smtp-ex4.fr.colt.net (smtp-ex4.fr.colt.net [213.41.78.193]) by smtp-ft2.fr.colt.net (8.14.3/8.14.3/Debian-5+lenny1) with ESMTP id t4SF5Sih020023 for ; Thu, 28 May 2015 17:05:28 +0200 Received: from 33.106-14-84.ripe.coltfrance.com ([84.14.106.33] helo=proxy.6wind.com) by smtp-ex4.fr.colt.net with esmtp (Exim) (envelope-from ) id 1YxzNF-0001jG-0B for ; Thu, 28 May 2015 17:05:34 +0200 Received: from 6wind.com (unknown [10.16.0.189]) by proxy.6wind.com (Postfix) with SMTP id E8012281D5; Thu, 28 May 2015 17:05:31 +0200 (CEST) Received: by 6wind.com (sSMTP sendmail emulation); Thu, 28 May 2015 17:05:29 +0200 From: Ivan Boule To: dev@dpdk.org Date: Thu, 28 May 2015 17:05:20 +0200 Message-Id: <1432825523-19006-3-git-send-email-ivan.boule@6wind.com> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1432825523-19006-1-git-send-email-ivan.boule@6wind.com> References: <1432825523-19006-1-git-send-email-ivan.boule@6wind.com> X-ACL-Warn: 1/1 recipients OK. Subject: [dpdk-dev] [PATCH 2/5] app/testpmd: new command to add/remove multicast MAC addresses X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Add the new interactive command: mcast_addr add|remove X to add/remove the multicast MAC address to/from the set of multicast addresses filtered by port . Command used to test the function "rte_eth_dev_set_mc_addr_list" that has been added to the API of PMDs. Signed-off-by: Ivan Boule --- app/test-pmd/cmdline.c | 52 ++++++++++++++++++ app/test-pmd/config.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++++ app/test-pmd/testpmd.h | 6 ++ 3 files changed, 200 insertions(+) diff --git a/app/test-pmd/cmdline.c b/app/test-pmd/cmdline.c index f01db2a..952a9df 100644 --- a/app/test-pmd/cmdline.c +++ b/app/test-pmd/cmdline.c @@ -8733,6 +8733,57 @@ cmdline_parse_inst_t cmd_set_hash_global_config = { }, }; +/* *** ADD/REMOVE A MULTICAST MAC ADDRESS TO/FROM A PORT *** */ +struct cmd_mcast_addr_result { + cmdline_fixed_string_t mcast_addr_cmd; + cmdline_fixed_string_t what; + uint8_t port_num; + struct ether_addr mc_addr; +}; + +static void cmd_mcast_addr_parsed(void *parsed_result, + __attribute__((unused)) struct cmdline *cl, + __attribute__((unused)) void *data) +{ + struct cmd_mcast_addr_result *res = parsed_result; + + if (!is_multicast_ether_addr(&res->mc_addr)) { + printf("Invalid multicast addr %02X:%02X:%02X:%02X:%02X:%02X\n", + res->mc_addr.addr_bytes[0], res->mc_addr.addr_bytes[1], + res->mc_addr.addr_bytes[2], res->mc_addr.addr_bytes[3], + res->mc_addr.addr_bytes[4], res->mc_addr.addr_bytes[5]); + return; + } + if (strcmp(res->what, "add") == 0) + mcast_addr_add(res->port_num, &res->mc_addr); + else + mcast_addr_remove(res->port_num, &res->mc_addr); +} + +cmdline_parse_token_string_t cmd_mcast_addr_cmd = + TOKEN_STRING_INITIALIZER(struct cmd_mcast_addr_result, + mcast_addr_cmd, "mcast_addr"); +cmdline_parse_token_string_t cmd_mcast_addr_what = + TOKEN_STRING_INITIALIZER(struct cmd_mcast_addr_result, what, + "add#remove"); +cmdline_parse_token_num_t cmd_mcast_addr_portnum = + TOKEN_NUM_INITIALIZER(struct cmd_mcast_addr_result, port_num, UINT8); +cmdline_parse_token_etheraddr_t cmd_mcast_addr_addr = + TOKEN_ETHERADDR_INITIALIZER(struct cmd_mac_addr_result, address); + +cmdline_parse_inst_t cmd_mcast_addr = { + .f = cmd_mcast_addr_parsed, + .data = (void *)0, + .help_str = "mcast_addr add|remove X : add/remove multicast MAC address on port X", + .tokens = { + (void *)&cmd_mcast_addr_cmd, + (void *)&cmd_mcast_addr_what, + (void *)&cmd_mcast_addr_portnum, + (void *)&cmd_mcast_addr_addr, + NULL, + }, +}; + /* ******************************************************************************** */ /* list of instructions */ @@ -8862,6 +8913,7 @@ cmdline_parse_ctx_t main_ctx[] = { (cmdline_parse_inst_t *)&cmd_set_sym_hash_ena_per_port, (cmdline_parse_inst_t *)&cmd_get_hash_global_config, (cmdline_parse_inst_t *)&cmd_set_hash_global_config, + (cmdline_parse_inst_t *)&cmd_mcast_addr, NULL, }; diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c index f788ed5..52917c7 100644 --- a/app/test-pmd/config.c +++ b/app/test-pmd/config.c @@ -2130,3 +2130,145 @@ set_vf_rate_limit(portid_t port_id, uint16_t vf, uint16_t rate, uint64_t q_msk) port_id, diag); return diag; } + +/* + * Functions to manage the set of filtered Multicast MAC addresses. + * + * A pool of filtered multicast MAC addresses is associated with each port. + * The pool is allocated in chunks of MCAST_POOL_INC multicast addresses. + * The address of the pool and the number of valid multicast MAC addresses + * recorded in the pool are stored in the fields "mc_addr_pool" and + * "mc_addr_nb" of the "rte_port" data structure. + * + * The function "rte_eth_dev_set_mc_addr_list" of the PMDs API imposes + * to be supplied a contiguous array of multicast MAC addresses. + * To comply with this constraint, the set of multicast addresses recorded + * into the pool are systematically compacted at the beginning of the pool. + * Hence, when a multicast address is removed from the pool, all following + * addresses, if any, are copied back to keep the set contiguous. + */ +#define MCAST_POOL_INC 32 + +static int +mcast_addr_pool_extend(struct rte_port *port) +{ + struct ether_addr *mc_pool; + size_t mc_pool_size; + + /* + * If a free entry is available at the end of the pool, just + * increment the number of recorded multicast addresses. + */ + if ((port->mc_addr_nb % MCAST_POOL_INC) != 0) { + port->mc_addr_nb++; + return 0; + } + + /* + * [re]allocate a pool with MCAST_POOL_INC more entries. + * The previous test guarantees that port->mc_addr_nb is a multiple + * of MCAST_POOL_INC. + */ + mc_pool_size = sizeof(struct ether_addr) * (port->mc_addr_nb + + MCAST_POOL_INC); + mc_pool = (struct ether_addr *) realloc(port->mc_addr_pool, + mc_pool_size); + if (mc_pool == NULL) { + printf("allocation of pool of %u multicast addresses failed\n", + port->mc_addr_nb + MCAST_POOL_INC); + return -ENOMEM; + } + + port->mc_addr_pool = mc_pool; + port->mc_addr_nb++; + return 0; + +} + +static void +mcast_addr_pool_remove(struct rte_port *port, uint32_t addr_idx) +{ + port->mc_addr_nb--; + if (addr_idx == port->mc_addr_nb) { + /* No need to recompact the set of multicast addressses. */ + if (port->mc_addr_nb == 0) { + /* free the pool of multicast addresses. */ + free(port->mc_addr_pool); + port->mc_addr_pool = NULL; + } + return; + } + memmove(&port->mc_addr_pool[addr_idx], + &port->mc_addr_pool[addr_idx + 1], + sizeof(struct ether_addr) * (port->mc_addr_nb - addr_idx)); +} + +static void +eth_port_multicast_addr_list_set(uint8_t port_id) +{ + struct rte_port *port; + int diag; + + port = &ports[port_id]; + diag = rte_eth_dev_set_mc_addr_list(port_id, port->mc_addr_pool, + port->mc_addr_nb); + if (diag == 0) + return; + printf("rte_eth_dev_set_mc_addr_list(port=%d, nb=%u) failed. diag=%d\n", + port->mc_addr_nb, port_id, -diag); +} + +void +mcast_addr_add(uint8_t port_id, struct ether_addr *mc_addr) +{ + struct rte_port *port; + uint32_t i; + + if (port_id_is_invalid(port_id, ENABLED_WARN)) + return; + + port = &ports[port_id]; + + /* + * Check that the added multicast MAC address is not already recorded + * in the pool of multicast addresses. + */ + for (i = 0; i < port->mc_addr_nb; i++) { + if (is_same_ether_addr(mc_addr, &port->mc_addr_pool[i])) { + printf("multicast address already filtered by port\n"); + return; + } + } + + if (mcast_addr_pool_extend(port) != 0) + return; + ether_addr_copy(mc_addr, &port->mc_addr_pool[i]); + eth_port_multicast_addr_list_set(port_id); +} + +void +mcast_addr_remove(uint8_t port_id, struct ether_addr *mc_addr) +{ + struct rte_port *port; + uint32_t i; + + if (port_id_is_invalid(port_id, ENABLED_WARN)) + return; + + port = &ports[port_id]; + + /* + * Search the pool of multicast MAC addresses for the removed address. + */ + for (i = 0; i < port->mc_addr_nb; i++) { + if (is_same_ether_addr(mc_addr, &port->mc_addr_pool[i])) + break; + } + if (i == port->mc_addr_nb) { + printf("multicast address not filtered by port %d\n", port_id); + return; + } + + mcast_addr_pool_remove(port, i); + eth_port_multicast_addr_list_set(port_id); +} diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index c3b6700..f2c84d9 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -162,6 +162,8 @@ struct rte_port { uint8_t dcb_flag; /**< enable dcb */ struct rte_eth_rxconf rx_conf; /**< rx configuration */ struct rte_eth_txconf tx_conf; /**< tx configuration */ + struct ether_addr *mc_addr_pool; /**< pool of multicast addrs */ + uint32_t mc_addr_nb; /**< nb. of addr. in mc_addr_pool */ }; extern portid_t __rte_unused @@ -563,6 +565,10 @@ void get_5tuple_filter(uint8_t port_id, uint16_t index); int rx_queue_id_is_invalid(queueid_t rxq_id); int tx_queue_id_is_invalid(queueid_t txq_id); +/* Functions to manage the set of filtered Multicast MAC addresses */ +void mcast_addr_add(uint8_t port_id, struct ether_addr *mc_addr); +void mcast_addr_remove(uint8_t port_id, struct ether_addr *mc_addr); + enum print_warning { ENABLED_WARN = 0, DISABLED_WARN