Skip to content

Commit

Permalink
app/testpmd: new command to add/remove multicast MAC addresses
Browse files Browse the repository at this point in the history
Add the new interactive command:
    mcast_addr add|remove X <mcast_addr>
to add/remove the multicast MAC address <mcast_addr> to/from the set of
multicast addresses filtered by port <X>.
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 <[email protected]>
  • Loading branch information
ivan6wind authored and Thomas Monjalon committed Jun 12, 2015
1 parent 64b7acd commit 8fff667
Show file tree
Hide file tree
Showing 3 changed files with 200 additions and 0 deletions.
52 changes: 52 additions & 0 deletions app/test-pmd/cmdline.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 <mcast_addr>: 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 */
Expand Down Expand Up @@ -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,
};

Expand Down
142 changes: 142 additions & 0 deletions app/test-pmd/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
6 changes: 6 additions & 0 deletions app/test-pmd/testpmd.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 8fff667

Please sign in to comment.