#include <rte_memcpy.h>
#include <rte_memzone.h>
#include <rte_launch.h>
-#include <rte_tailq.h>
#include <rte_eal.h>
#include <rte_per_lcore.h>
#include <rte_lcore.h>
#include "testpmd.h"
-static const char *flowtype_str[RTE_ETH_FLOW_TYPE_MAX] = {
- NULL,
- "raw",
- "udp4",
- "tcp4",
- "sctp4",
- "ip4",
- "ip4-frag",
- "udp6",
- "tcp6",
- "sctp6",
- "ip6",
- "ip6-frag",
-};
+static char *flowtype_to_str(uint16_t flow_type);
static void
print_ethaddr(const char *name, struct ether_addr *eth_addr)
struct rte_eth_stats stats;
struct rte_port *port = &ports[port_id];
uint8_t i;
+ portid_t pid;
static const char *nic_stats_border = "########################";
- if (port_id >= nb_ports) {
- printf("Invalid port, range is [0, %d]\n", nb_ports - 1);
+ if (port_id_is_invalid(port_id, ENABLED_WARN)) {
+ printf("Valid port range is [0");
+ FOREACH_PORT(pid, ports)
+ printf(", %d", pid);
+ printf("]\n");
return;
}
rte_eth_stats_get(port_id, &stats);
void
nic_stats_clear(portid_t port_id)
{
- if (port_id >= nb_ports) {
- printf("Invalid port, range is [0, %d]\n", nb_ports - 1);
+ portid_t pid;
+
+ if (port_id_is_invalid(port_id, ENABLED_WARN)) {
+ printf("Valid port range is [0");
+ FOREACH_PORT(pid, ports)
+ printf(", %d", pid);
+ printf("]\n");
return;
}
rte_eth_stats_reset(port_id);
{
struct rte_port *port = &ports[port_id];
uint16_t i;
+ portid_t pid;
static const char *nic_stats_mapping_border = "########################";
- if (port_id >= nb_ports) {
- printf("Invalid port, range is [0, %d]\n", nb_ports - 1);
+ if (port_id_is_invalid(port_id, ENABLED_WARN)) {
+ printf("Valid port range is [0");
+ FOREACH_PORT(pid, ports)
+ printf(", %d", pid);
+ printf("]\n");
return;
}
int vlan_offload;
struct rte_mempool * mp;
static const char *info_border = "*********************";
+ portid_t pid;
- if (port_id >= nb_ports) {
- printf("Invalid port, range is [0, %d]\n", nb_ports - 1);
+ if (port_id_is_invalid(port_id, ENABLED_WARN)) {
+ printf("Valid port range is [0");
+ FOREACH_PORT(pid, ports)
+ printf(", %d", pid);
+ printf("]\n");
return;
}
port = &ports[port_id];
memset(&dev_info, 0, sizeof(dev_info));
rte_eth_dev_info_get(port_id, &dev_info);
+ if (dev_info.hash_key_size > 0)
+ printf("Hash key size in bytes: %u\n", dev_info.hash_key_size);
if (dev_info.reta_size > 0)
printf("Redirection table size: %u\n", dev_info.reta_size);
+ if (!dev_info.flow_type_rss_offloads)
+ printf("No flow type is supported.\n");
+ else {
+ uint16_t i;
+ char *p;
+
+ printf("Supported flow types:\n");
+ for (i = RTE_ETH_FLOW_UNKNOWN + 1; i < RTE_ETH_FLOW_MAX;
+ i++) {
+ if (!(dev_info.flow_type_rss_offloads & (1ULL << i)))
+ continue;
+ p = flowtype_to_str(i);
+ printf(" %s\n", (p ? p : "unknown"));
+ }
+ }
}
int
-port_id_is_invalid(portid_t port_id)
+port_id_is_invalid(portid_t port_id, enum print_warning warning)
{
- if (port_id < nb_ports)
+ if (port_id == (portid_t)RTE_PORT_ALL)
return 0;
- printf("Invalid port %d (must be < nb_ports=%d)\n", port_id, nb_ports);
+
+ if (port_id < RTE_MAX_ETHPORTS && ports[port_id].enabled)
+ return 0;
+
+ if (warning == ENABLED_WARN)
+ printf("Invalid port %d\n", port_id);
+
return 1;
}
uint32_t reg_v;
- if (port_id_is_invalid(port_id))
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
if (port_reg_off_is_invalid(port_id, reg_off))
return;
uint8_t l_bit;
uint8_t h_bit;
- if (port_id_is_invalid(port_id))
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
if (port_reg_off_is_invalid(port_id, reg_off))
return;
{
uint32_t reg_v;
- if (port_id_is_invalid(port_id))
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
if (port_reg_off_is_invalid(port_id, reg_off))
return;
{
uint32_t reg_v;
- if (port_id_is_invalid(port_id))
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
if (port_reg_off_is_invalid(port_id, reg_off))
return;
uint8_t l_bit;
uint8_t h_bit;
- if (port_id_is_invalid(port_id))
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
if (port_reg_off_is_invalid(port_id, reg_off))
return;
void
port_reg_set(portid_t port_id, uint32_t reg_off, uint32_t reg_v)
{
- if (port_id_is_invalid(port_id))
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
if (port_reg_off_is_invalid(port_id, reg_off))
return;
{
int diag;
- if (port_id_is_invalid(port_id))
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
diag = rte_eth_dev_set_mtu(port_id, mtu);
if (diag == 0)
{
const struct rte_memzone *rx_mz;
- if (port_id_is_invalid(port_id))
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
if (rx_queue_id_is_invalid(rxq_id))
return;
{
const struct rte_memzone *tx_mz;
- if (port_id_is_invalid(port_id))
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
if (tx_queue_id_is_invalid(txq_id))
return;
uint16_t i, idx, shift;
int ret;
- if (port_id_is_invalid(port_id))
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
ret = rte_eth_dev_rss_reta_query(port_id, reta_conf, nb_entries);
void
port_rss_hash_conf_show(portid_t port_id, int show_rss_key)
{
+ struct rss_type_info {
+ char str[32];
+ uint64_t rss_type;
+ };
+ static const struct rss_type_info rss_type_table[] = {
+ {"ipv4", ETH_RSS_IPV4},
+ {"ipv4-frag", ETH_RSS_FRAG_IPV4},
+ {"ipv4-tcp", ETH_RSS_NONFRAG_IPV4_TCP},
+ {"ipv4-udp", ETH_RSS_NONFRAG_IPV4_UDP},
+ {"ipv4-sctp", ETH_RSS_NONFRAG_IPV4_SCTP},
+ {"ipv4-other", ETH_RSS_NONFRAG_IPV4_OTHER},
+ {"ipv6", ETH_RSS_IPV6},
+ {"ipv6-frag", ETH_RSS_FRAG_IPV6},
+ {"ipv6-tcp", ETH_RSS_NONFRAG_IPV6_TCP},
+ {"ipv6-udp", ETH_RSS_NONFRAG_IPV6_UDP},
+ {"ipv6-sctp", ETH_RSS_NONFRAG_IPV6_SCTP},
+ {"ipv6-other", ETH_RSS_NONFRAG_IPV6_OTHER},
+ {"l2-payload", ETH_RSS_L2_PAYLOAD},
+ {"ipv6-ex", ETH_RSS_IPV6_EX},
+ {"ipv6-tcp-ex", ETH_RSS_IPV6_TCP_EX},
+ {"ipv6-udp-ex", ETH_RSS_IPV6_UDP_EX},
+ };
+
struct rte_eth_rss_conf rss_conf;
uint8_t rss_key[10 * 4];
uint64_t rss_hf;
uint8_t i;
int diag;
- if (port_id_is_invalid(port_id))
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
/* Get RSS hash key if asked to display it */
rss_conf.rss_key = (show_rss_key) ? rss_key : NULL;
return;
}
printf("RSS functions:\n ");
- if (rss_hf & ETH_RSS_IPV4)
- printf("ip4");
- if (rss_hf & ETH_RSS_IPV4_TCP)
- printf(" tcp4");
- if (rss_hf & ETH_RSS_IPV4_UDP)
- printf(" udp4");
- if (rss_hf & ETH_RSS_IPV6)
- printf(" ip6");
- if (rss_hf & ETH_RSS_IPV6_EX)
- printf(" ip6-ex");
- if (rss_hf & ETH_RSS_IPV6_TCP)
- printf(" tcp6");
- if (rss_hf & ETH_RSS_IPV6_TCP_EX)
- printf(" tcp6-ex");
- if (rss_hf & ETH_RSS_IPV6_UDP)
- printf(" udp6");
- if (rss_hf & ETH_RSS_IPV6_UDP_EX)
- printf(" udp6-ex");
+ for (i = 0; i < RTE_DIM(rss_type_table); i++) {
+ if (rss_hf & rss_type_table[i].rss_type)
+ printf("%s ", rss_type_table[i].str);
+ }
printf("\n");
if (!show_rss_key)
return;
again:
for (i = 0; i < nb_pt; i++) {
port_id = (portid_t) portlist[i];
- if (port_id >= nb_ports) {
- printf("Invalid port id %u >= %u\n",
- (unsigned int) port_id,
- (unsigned int) nb_ports);
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
- }
if (record_now)
fwd_ports_ids[i] = port_id;
}
int diag;
int vlan_offload;
- if (port_id_is_invalid(port_id))
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
vlan_offload = rte_eth_dev_get_vlan_offload(port_id);
int diag;
int vlan_offload;
- if (port_id_is_invalid(port_id))
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
vlan_offload = rte_eth_dev_get_vlan_offload(port_id);
{
int diag;
- if (port_id_is_invalid(port_id))
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
diag = rte_eth_dev_set_vlan_strip_on_queue(port_id, queue_id, on);
int diag;
int vlan_offload;
- if (port_id_is_invalid(port_id))
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
vlan_offload = rte_eth_dev_get_vlan_offload(port_id);
"diag=%d\n", port_id, on, diag);
}
-void
+int
rx_vft_set(portid_t port_id, uint16_t vlan_id, int on)
{
int diag;
- if (port_id_is_invalid(port_id))
- return;
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return 1;
if (vlan_id_is_invalid(vlan_id))
- return;
+ return 1;
diag = rte_eth_dev_vlan_filter(port_id, vlan_id, on);
if (diag == 0)
- return;
+ return 0;
printf("rte_eth_dev_vlan_filter(port_pi=%d, vlan_id=%d, on=%d) failed "
"diag=%d\n",
port_id, vlan_id, on, diag);
+ return -1;
}
void
{
uint16_t vlan_id;
- if (port_id_is_invalid(port_id))
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
- for (vlan_id = 0; vlan_id < 4096; vlan_id++)
- rx_vft_set(port_id, vlan_id, on);
+ for (vlan_id = 0; vlan_id < 4096; vlan_id++) {
+ if (rx_vft_set(port_id, vlan_id, on))
+ break;
+ }
}
void
vlan_tpid_set(portid_t port_id, uint16_t tp_id)
{
int diag;
- if (port_id_is_invalid(port_id))
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
diag = rte_eth_dev_set_vlan_ether_type(port_id, tp_id);
void
tx_vlan_set(portid_t port_id, uint16_t vlan_id)
{
- if (port_id_is_invalid(port_id))
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
if (vlan_id_is_invalid(vlan_id))
return;
+ tx_vlan_reset(port_id);
ports[port_id].tx_ol_flags |= TESTPMD_TX_OFFLOAD_INSERT_VLAN;
ports[port_id].tx_vlan_id = vlan_id;
}
+void
+tx_qinq_set(portid_t port_id, uint16_t vlan_id, uint16_t vlan_id_outer)
+{
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
+ return;
+ if (vlan_id_is_invalid(vlan_id))
+ return;
+ if (vlan_id_is_invalid(vlan_id_outer))
+ return;
+ tx_vlan_reset(port_id);
+ ports[port_id].tx_ol_flags |= TESTPMD_TX_OFFLOAD_INSERT_QINQ;
+ ports[port_id].tx_vlan_id = vlan_id;
+ ports[port_id].tx_vlan_id_outer = vlan_id_outer;
+}
+
void
tx_vlan_reset(portid_t port_id)
{
- if (port_id_is_invalid(port_id))
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
- ports[port_id].tx_ol_flags &= ~TESTPMD_TX_OFFLOAD_INSERT_VLAN;
+ ports[port_id].tx_ol_flags &= ~(TESTPMD_TX_OFFLOAD_INSERT_VLAN |
+ TESTPMD_TX_OFFLOAD_INSERT_QINQ);
+ ports[port_id].tx_vlan_id = 0;
+ ports[port_id].tx_vlan_id_outer = 0;
}
void
tx_vlan_pvid_set(portid_t port_id, uint16_t vlan_id, int on)
{
- if (port_id_is_invalid(port_id))
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
rte_eth_dev_set_vlan_pvid(port_id, vlan_id, on);
uint16_t i;
uint8_t existing_mapping_found = 0;
- if (port_id_is_invalid(port_id))
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
if (is_rx ? (rx_queue_id_is_invalid(queue_id)) : (tx_queue_id_is_invalid(queue_id)))
printf("\n");
}
+static char *
+flowtype_to_str(uint16_t flow_type)
+{
+ struct flow_type_info {
+ char str[32];
+ uint16_t ftype;
+ };
+
+ uint8_t i;
+ static struct flow_type_info flowtype_str_table[] = {
+ {"raw", RTE_ETH_FLOW_RAW},
+ {"ipv4", RTE_ETH_FLOW_IPV4},
+ {"ipv4-frag", RTE_ETH_FLOW_FRAG_IPV4},
+ {"ipv4-tcp", RTE_ETH_FLOW_NONFRAG_IPV4_TCP},
+ {"ipv4-udp", RTE_ETH_FLOW_NONFRAG_IPV4_UDP},
+ {"ipv4-sctp", RTE_ETH_FLOW_NONFRAG_IPV4_SCTP},
+ {"ipv4-other", RTE_ETH_FLOW_NONFRAG_IPV4_OTHER},
+ {"ipv6", RTE_ETH_FLOW_IPV6},
+ {"ipv6-frag", RTE_ETH_FLOW_FRAG_IPV6},
+ {"ipv6-tcp", RTE_ETH_FLOW_NONFRAG_IPV6_TCP},
+ {"ipv6-udp", RTE_ETH_FLOW_NONFRAG_IPV6_UDP},
+ {"ipv6-sctp", RTE_ETH_FLOW_NONFRAG_IPV6_SCTP},
+ {"ipv6-other", RTE_ETH_FLOW_NONFRAG_IPV6_OTHER},
+ {"l2_payload", RTE_ETH_FLOW_L2_PAYLOAD},
+ };
+
+ for (i = 0; i < RTE_DIM(flowtype_str_table); i++) {
+ if (flowtype_str_table[i].ftype == flow_type)
+ return flowtype_str_table[i].str;
+ }
+
+ return NULL;
+}
+
static inline void
print_fdir_flex_mask(struct rte_eth_fdir_flex_conf *flex_conf, uint32_t num)
{
struct rte_eth_fdir_flex_mask *mask;
uint32_t i, j;
+ char *p;
for (i = 0; i < flex_conf->nb_flexmasks; i++) {
mask = &flex_conf->flex_mask[i];
- printf("\n %s:\t", flowtype_str[mask->flow_type]);
+ p = flowtype_to_str(mask->flow_type);
+ printf("\n %s:\t", p ? p : "unknown");
for (j = 0; j < num; j++)
printf(" %02x", mask->mask[j]);
}
static inline void
print_fdir_flow_type(uint32_t flow_types_mask)
{
- int i = 0;
+ int i;
+ char *p;
- for (i = RTE_ETH_FLOW_TYPE_UDPV4;
- i <= RTE_ETH_FLOW_TYPE_FRAG_IPV6;
- i++) {
- if (flow_types_mask & (1 << i))
- printf(" %s", flowtype_str[i]);
+ for (i = RTE_ETH_FLOW_UNKNOWN; i < RTE_ETH_FLOW_MAX; i++) {
+ if (!(flow_types_mask & (1 << i)))
+ continue;
+ p = flowtype_to_str(i);
+ if (p)
+ printf(" %s", p);
+ else
+ printf(" unknown");
}
printf("\n");
}
static const char *fdir_stats_border = "########################";
- if (port_id_is_invalid(port_id))
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
ret = rte_eth_dev_filter_supported(port_id, RTE_ETH_FILTER_FDIR);
if (ret < 0) {
fdir_stats_border, port_id, fdir_stats_border);
printf(" MODE: ");
if (fdir_info.mode == RTE_FDIR_MODE_PERFECT)
- printf(" PERFECT\n");
+ printf(" PERFECT\n");
else if (fdir_info.mode == RTE_FDIR_MODE_SIGNATURE)
- printf(" SIGNATURE\n");
+ printf(" SIGNATURE\n");
else
- printf(" DISABLE\n");
+ printf(" DISABLE\n");
printf(" SUPPORTED FLOW TYPE: ");
print_fdir_flow_type(fdir_info.flow_types_mask[0]);
printf(" FLEX PAYLOAD INFO:\n");
port = &ports[port_id];
flex_conf = &port->dev_conf.fdir_conf.flex_conf;
- for (i = 0; i < RTE_ETH_FLOW_TYPE_MAX; i++) {
+ for (i = 0; i < RTE_ETH_FLOW_MAX; i++) {
if (cfg->flow_type == flex_conf->flex_mask[i].flow_type) {
idx = i;
break;
}
}
- if (i >= RTE_ETH_FLOW_TYPE_MAX) {
+ if (i >= RTE_ETH_FLOW_MAX) {
if (flex_conf->nb_flexmasks < RTE_DIM(flex_conf->flex_mask)) {
idx = flex_conf->nb_flexmasks;
flex_conf->nb_flexmasks++;
{
int diag;
- if (port_id_is_invalid(port_id))
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
if (is_rx)
diag = rte_eth_dev_set_vf_rx(port_id,vf,on);
{
int diag;
- if (port_id_is_invalid(port_id))
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
if (vlan_id_is_invalid(vlan_id))
return;
int diag;
struct rte_eth_link link;
- if (port_id_is_invalid(port_id))
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
return 1;
rte_eth_link_get_nowait(port_id, &link);
if (rate > link.link_speed) {
if (q_msk == 0)
return 0;
- if (port_id_is_invalid(port_id))
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
return 1;
rte_eth_link_get_nowait(port_id, &link);
if (rate > link.link_speed) {
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
-get_2tuple_filter(uint8_t port_id, uint16_t index)
+mcast_addr_add(uint8_t port_id, struct ether_addr *mc_addr)
{
- struct rte_2tuple_filter filter;
- int ret = 0;
- uint16_t rx_queue;
+ struct rte_port *port;
+ uint32_t i;
- memset(&filter, 0, sizeof(filter));
- ret = rte_eth_dev_get_2tuple_filter(port_id, index,
- &filter, &rx_queue);
- if (ret < 0) {
- if (ret == (-ENOENT))
- printf("filter[%d] is not enabled\n", index);
- else
- printf("get 2tuple filter fails(%s)\n", strerror(-ret));
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
- } else {
- printf("filter[%d]:\n", index);
- printf(" Destination Port: 0x%04x mask: %d\n",
- rte_be_to_cpu_16(filter.dst_port),
- filter.dst_port_mask ? 0 : 1);
- printf(" protocol: 0x%02x mask:%d tcp_flags: 0x%02x\n",
- filter.protocol, filter.protocol_mask ? 0 : 1,
- filter.tcp_flags);
- printf(" priority: %d queue: %d\n",
- filter.priority, rx_queue);
+
+ 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
-get_5tuple_filter(uint8_t port_id, uint16_t index)
+mcast_addr_remove(uint8_t port_id, struct ether_addr *mc_addr)
{
- struct rte_5tuple_filter filter;
- int ret = 0;
- uint16_t rx_queue;
+ struct rte_port *port;
+ uint32_t i;
- memset(&filter, 0, sizeof(filter));
- ret = rte_eth_dev_get_5tuple_filter(port_id, index,
- &filter, &rx_queue);
- if (ret < 0) {
- if (ret == (-ENOENT))
- printf("filter[%d] is not enabled\n", index);
- else
- printf("get 5tuple filter fails(%s)\n", strerror(-ret));
+ if (port_id_is_invalid(port_id, ENABLED_WARN))
return;
- } else {
- printf("filter[%d]:\n", index);
- printf(" Destination IP: 0x%08x mask: %d\n",
- (unsigned)rte_be_to_cpu_32(filter.dst_ip),
- filter.dst_ip_mask ? 0 : 1);
- printf(" Source IP: 0x%08x mask: %d\n",
- (unsigned)rte_be_to_cpu_32(filter.src_ip),
- filter.src_ip_mask ? 0 : 1);
- printf(" Destination Port: 0x%04x mask: %d\n",
- rte_be_to_cpu_16(filter.dst_port),
- filter.dst_port_mask ? 0 : 1);
- printf(" Source Port: 0x%04x mask: %d\n",
- rte_be_to_cpu_16(filter.src_port),
- filter.src_port_mask ? 0 : 1);
- printf(" protocol: 0x%02x mask: %d\n",
- filter.protocol,
- filter.protocol_mask ? 0 : 1);
- printf(" priority: %d flags: 0x%02x queue: %d\n",
- filter.priority, filter.tcp_flags, rx_queue);
+
+ 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);
}