X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=app%2Ftest-pmd%2Fconfig.c;h=cf2aa6e46cac9e8204b1230e4b74ffc857aa899c;hb=7acf894d07d1cfbab50c525300e5c61fce2468d6;hp=fc91a6d24afb4b0d2602174e5d345330a7e7bd82;hpb=9df58d413ae236c68bcdd3963d5fcd63058c13ab;p=dpdk.git diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c index fc91a6d24a..cf2aa6e46c 100644 --- a/app/test-pmd/config.c +++ b/app/test-pmd/config.c @@ -79,7 +79,6 @@ #include #include #include -#include #include #include #include @@ -96,20 +95,7 @@ #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) @@ -125,11 +111,15 @@ nic_stats_display(portid_t port_id) 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); @@ -202,8 +192,13 @@ nic_stats_display(portid_t port_id) 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); @@ -250,11 +245,15 @@ nic_stats_mapping_display(portid_t 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; } @@ -303,9 +302,13 @@ port_infos_display(portid_t port_id) 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]; @@ -358,16 +361,39 @@ port_infos_display(portid_t 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; } @@ -426,7 +452,7 @@ port_reg_bit_display(portid_t port_id, uint32_t reg_off, uint8_t bit_x) 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; @@ -445,7 +471,7 @@ port_reg_bit_field_display(portid_t port_id, uint32_t reg_off, 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; @@ -472,7 +498,7 @@ port_reg_display(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; @@ -486,7 +512,7 @@ port_reg_bit_set(portid_t port_id, uint32_t reg_off, uint8_t bit_pos, { 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; @@ -514,7 +540,7 @@ port_reg_bit_field_set(portid_t port_id, uint32_t reg_off, 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; @@ -548,7 +574,7 @@ port_reg_bit_field_set(portid_t port_id, uint32_t reg_off, 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; @@ -561,7 +587,7 @@ port_mtu_set(portid_t port_id, uint16_t mtu) { 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) @@ -724,7 +750,7 @@ rx_ring_desc_display(portid_t port_id, queueid_t rxq_id, uint16_t rxd_id) { 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; @@ -741,7 +767,7 @@ tx_ring_desc_display(portid_t port_id, queueid_t txq_id, uint16_t txd_id) { 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; @@ -802,7 +828,7 @@ port_rss_reta_info(portid_t port_id, 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); @@ -828,13 +854,36 @@ port_rss_reta_info(portid_t port_id, 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; @@ -859,24 +908,10 @@ port_rss_hash_conf_show(portid_t port_id, int show_rss_key) 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; @@ -1412,12 +1447,8 @@ set_fwd_ports_list(unsigned int *portlist, unsigned int nb_pt) 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; } @@ -1575,7 +1606,7 @@ vlan_extend_set(portid_t port_id, int 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); @@ -1597,7 +1628,7 @@ rx_vlan_strip_set(portid_t port_id, int 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); @@ -1618,7 +1649,7 @@ rx_vlan_strip_set_on_queue(portid_t port_id, uint16_t queue_id, int on) { 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); @@ -1633,7 +1664,7 @@ rx_vlan_filter_set(portid_t port_id, int 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); @@ -1649,21 +1680,22 @@ rx_vlan_filter_set(portid_t port_id, int on) "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 @@ -1671,17 +1703,19 @@ rx_vlan_all_filter_set(portid_t port_id, int on) { 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); @@ -1696,26 +1730,45 @@ vlan_tpid_set(portid_t port_id, uint16_t 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); @@ -1727,7 +1780,7 @@ set_qmap(portid_t port_id, uint8_t is_rx, uint16_t queue_id, uint8_t map_value) 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))) @@ -1815,15 +1868,51 @@ print_fdir_flex_payload(struct rte_eth_fdir_flex_conf *flex_conf, uint32_t num) 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]); } @@ -1833,13 +1922,17 @@ print_fdir_flex_mask(struct rte_eth_fdir_flex_conf *flex_conf, uint32_t num) 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"); } @@ -1853,7 +1946,7 @@ fdir_get_infos(portid_t port_id) 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) { @@ -1872,11 +1965,11 @@ fdir_get_infos(portid_t port_id) 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"); @@ -1922,13 +2015,13 @@ fdir_set_flex_mask(portid_t port_id, struct rte_eth_fdir_flex_mask *cfg) 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++; @@ -1979,7 +2072,7 @@ set_vf_traffic(portid_t port_id, uint8_t is_rx, uint16_t vf, uint8_t on) { 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); @@ -2001,7 +2094,7 @@ set_vf_rx_vlan(portid_t port_id, uint16_t vlan_id, uint64_t vf_mask, uint8_t 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; @@ -2018,7 +2111,7 @@ set_queue_rate_limit(portid_t port_id, uint16_t queue_idx, uint16_t rate) 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) { @@ -2043,7 +2136,7 @@ set_vf_rate_limit(portid_t port_id, uint16_t vf, uint16_t rate, uint64_t q_msk) 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) { @@ -2059,69 +2152,144 @@ set_vf_rate_limit(portid_t port_id, uint16_t vf, uint16_t rate, uint64_t q_msk) 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); }