diff options
Diffstat (limited to 'src/main_dpdk.cpp')
-rw-r--r--[-rwxr-xr-x] | src/main_dpdk.cpp | 363 |
1 files changed, 292 insertions, 71 deletions
diff --git a/src/main_dpdk.cpp b/src/main_dpdk.cpp index 608a05b3..8cc94e7d 100755..100644 --- a/src/main_dpdk.cpp +++ b/src/main_dpdk.cpp @@ -107,7 +107,7 @@ extern "C" { typedef struct rte_mbuf * (*rte_mbuf_convert_to_one_seg_t)(struct rte_mbuf *m); struct rte_mbuf * rte_mbuf_convert_to_one_seg(struct rte_mbuf *m); -extern "C" int vmxnet3_xmit_set_callback(rte_mbuf_convert_to_one_seg_t cb); +extern "C" void i40e_set_trex_mode(int mode); #define RTE_TEST_TX_DESC_DEFAULT 512 #define RTE_TEST_RX_DESC_DROP 0 @@ -140,7 +140,7 @@ public: return(false); } virtual int configure_rx_filter_rules(CPhyEthIF * _if)=0; - + virtual int add_del_rx_flow_stat_rule(uint8_t port_id, enum rte_filter_op op, uint8_t type, uint16_t proto, uint16_t id) {return -1;}; virtual bool is_hardware_support_drop_queue(){ return(false); } @@ -151,6 +151,10 @@ public: virtual int wait_for_stable_link()=0; virtual void wait_after_link_up(){}; virtual bool flow_control_disable_supported(){return true;} + virtual int get_rx_stats(CPhyEthIF * _if, uint32_t *stats, uint32_t *prev_stats, int index) {return -1;} + virtual int dump_fdir_global_stats(CPhyEthIF * _if, FILE *fd) { return -1;} + virtual int get_stat_counters_num() {return 0;} + virtual int get_rx_stat_capabilities() {return 0;} }; @@ -181,7 +185,9 @@ public: virtual int configure_drop_queue(CPhyEthIF * _if); virtual int configure_rx_filter_rules(CPhyEthIF * _if); - + int configure_rx_filter_rules_statefull(CPhyEthIF * _if); + int configure_rx_filter_rules_stateless(CPhyEthIF * _if); + virtual bool is_hardware_support_drop_queue(){ return(true); } @@ -281,6 +287,10 @@ public: class CTRexExtendedDriverBase40G : public CTRexExtendedDriverBase10G { public: CTRexExtendedDriverBase40G(){ + // Since we support only 128 counters per if, it is OK to configure here 4 statically. + // If we want to support more counters in case in case of card having less interfaces, we + // Will have to identify the number of interfaces dynamically. + m_if_per_card = 4; } TrexPlatformApi::driver_speed_e get_driver_speed(uint8_t port_id) { @@ -304,7 +314,7 @@ public: virtual void update_configuration(port_cfg_t * cfg); virtual int configure_rx_filter_rules(CPhyEthIF * _if); - + virtual int add_del_rx_flow_stat_rule(uint8_t port_id, enum rte_filter_op op, uint8_t type, uint16_t proto, uint16_t id); virtual bool is_hardware_filter_is_supported(){ return (true); } @@ -314,13 +324,18 @@ public: } virtual void get_extended_stats(CPhyEthIF * _if,CPhyEthIFStats *stats); virtual void clear_extended_stats(CPhyEthIF * _if); + int get_rx_stats(CPhyEthIF * _if, uint32_t *stats, uint32_t *prev_stats, int index); + int dump_fdir_global_stats(CPhyEthIF * _if, FILE *fd); + int get_stat_counters_num() {return TREX_FDIR_STAT_SIZE;} + int get_rx_stat_capabilities() {return TrexPlatformApi::IF_STAT_IPV4_ID;} virtual int wait_for_stable_link(); // disabling flow control on 40G using DPDK API causes the interface to malfunction bool flow_control_disable_supported(){return false;} +private: + void add_del_rules(enum rte_filter_op op, uint8_t port_id, uint16_t type, uint8_t ttl, uint16_t ip_id, int queue, uint16_t stat_idx); + virtual int configure_rx_filter_rules_statfull(CPhyEthIF * _if); private: - void add_rules(CPhyEthIF * _if, - uint16_t type, - uint8_t ttl); + uint8_t m_if_per_card; }; class CTRexExtendedDriverBaseVIC : public CTRexExtendedDriverBase40G { @@ -339,7 +354,6 @@ public: bool flow_control_disable_supported(){return false;} virtual void update_configuration(port_cfg_t * cfg); - }; @@ -1177,20 +1191,18 @@ typedef struct cnt_name_ { #define MY_REG(a) {a,(char *)#a} void CPhyEthIFStats::Clear(){ - - ipackets =0; - ibytes =0 ; - - f_ipackets=0; - f_ibytes=0; - - opackets=0; - obytes=0; - - ierrors=0; - oerrors=0; - imcasts=0; - rx_nombuf=0; + ipackets = 0; + ibytes = 0; + f_ipackets = 0; + f_ibytes = 0; + opackets = 0; + obytes = 0; + ierrors = 0; + oerrors = 0; + imcasts = 0; + rx_nombuf = 0; + memset(m_rx_per_flow, 0, sizeof(m_rx_per_flow)); + m_fdir_stats_first_time = true; } @@ -1289,18 +1301,21 @@ void CPhyEthIF::dump_stats_extended(FILE *fd){ MY_REG(IXGBE_FDIRMISS ) }; - fprintf (fd," externded counter \n"); + fprintf (fd," extended counters \n"); int i; for (i=0; i<sizeof(reg)/sizeof(reg[0]); i++) { cnt_name_t *lp=®[i]; uint32_t c=pci_reg_read(lp->offset); - if (c) { + // xl710 bug. Counter values are -559038737 when they should be 0 + if (c && c != -559038737 ) { fprintf (fd," %s : %d \n",lp->name,c); } } } - +int CPhyEthIF::get_rx_stat_capabilities() { + return get_ex_drv()->get_rx_stat_capabilities(); +} void CPhyEthIF::configure(uint16_t nb_rx_queue, uint16_t nb_tx_queue, @@ -1551,16 +1566,55 @@ void CPhyEthIF::get_stats_1g(CPhyEthIFStats *stats){ } -void CPhyEthIF::get_stats(CPhyEthIFStats *stats){ +int CPhyEthIF::dump_fdir_global_stats(FILE *fd) { + return get_ex_drv()->dump_fdir_global_stats(this, fd); +} - get_ex_drv()->get_extended_stats(this,stats); +// get/reset flow director counters +// return 0 if OK. -1 if operation not supported. +// stats - If not NULL, returning counter numbers in it. +// index - If non negative, get only counter with this index +// reset - If true, reset counter value after reading +int CPhyEthIF::get_rx_stats(uint64_t *stats, int index, bool reset) { + uint32_t diff_stats[TREX_FDIR_STAT_SIZE]; + int start, len; - m_last_tx_rate = m_bw_tx.add(stats->obytes); - m_last_rx_rate = m_bw_rx.add(stats->ibytes); - m_last_tx_pps = m_pps_tx.add(stats->opackets); - m_last_rx_pps = m_pps_rx.add(stats->ipackets); -} + if (index >= 0) { + start = index; + len = 1; + } else { + start = 0; + len = TREX_FDIR_STAT_SIZE; + } + + if (get_ex_drv()->get_rx_stats(this, diff_stats, m_stats.m_fdir_prev_stats, index) < 0) { + return -1; + } + // First time, just syncing the counters + if (m_stats.m_fdir_stats_first_time) { + m_stats.m_fdir_stats_first_time = false; + if (stats) { + memset(stats, 0, sizeof(uint64_t) * TREX_FDIR_STAT_SIZE); + } + return 0; + } + + for (int i = start; i < (start + len); i++) { + if ( reset ) { + // return value so far, and reset + stats[i] = m_stats.m_rx_per_flow[i] + diff_stats[i]; + m_stats.m_rx_per_flow[i] = 0; + } else { + m_stats.m_rx_per_flow[i] += diff_stats[i]; + if (stats != NULL) { + stats[i] = m_stats.m_rx_per_flow[i]; + } + } + } + + return 0; +} void dump_hw_state(FILE *fd,struct ixgbe_hw_stats *hs ){ @@ -1651,7 +1705,12 @@ void dump_hw_state(FILE *fd,struct ixgbe_hw_stats *hs ){ void CPhyEthIF::update_counters(){ - get_stats(&m_stats); + get_ex_drv()->get_extended_stats(this, &m_stats); + + m_last_tx_rate = m_bw_tx.add(m_stats.obytes); + m_last_rx_rate = m_bw_rx.add(m_stats.ibytes); + m_last_tx_pps = m_pps_tx.add(m_stats.opackets); + m_last_rx_pps = m_pps_rx.add(m_stats.ipackets); } void CPhyEthIF::dump_stats(FILE *fd){ @@ -2588,7 +2647,7 @@ private: void check_for_dp_messages(); public: - int start_send_master(); + int start_master_statefull(); int start_master_stateless(); int run_in_core(virtual_thread_id_t virt_core_id); int stop_core(virtual_thread_id_t virt_core_id); @@ -3539,9 +3598,10 @@ CGlobalTRex::publish_async_data() { m_mg.dump_json_v2(json ); m_zmq_publisher.publish_json(json); - /* stateless info - nothing for now */ - //m_trex_stateless->generate_publish_snapshot(json); - //m_zmq_publisher.publish_json(json); + if (get_is_stateless()) { + if (m_trex_stateless->m_rx_flow_stat.dump_json(json)) + m_zmq_publisher.publish_json(json); + } } void @@ -3804,10 +3864,7 @@ int CGlobalTRex::start_master_stateless(){ return (0); } - - - -int CGlobalTRex::start_send_master(){ +int CGlobalTRex::start_master_statefull() { int i; for (i=0; i<BP_MAX_CORES; i++) { m_signal[i]=0; @@ -4244,7 +4301,8 @@ int main_test(int argc , char * argv[]){ return (-1); } - + // We init i40e fdir registers differently in case of stateless. Must set this before rte_eal_init which initiates the registers + i40e_set_trex_mode(get_is_stateless() ? 1:0 ); ret = rte_eal_init(global_dpdk_args_num, (char **)global_dpdk_args); if (ret < 0){ @@ -4288,7 +4346,7 @@ int main_test(int argc , char * argv[]){ g_trex.start_master_stateless(); }else{ - g_trex.start_send_master(); + g_trex.start_master_statefull(); } if (CGlobalInfo::m_options.m_debug_pkt_proto != 0) { @@ -4378,8 +4436,18 @@ int CTRexExtendedDriverBase1G::configure_drop_queue(CPhyEthIF * _if) { return 0; } + int CTRexExtendedDriverBase1G::configure_rx_filter_rules(CPhyEthIF * _if){ + if ( get_is_stateless() ) { + return configure_rx_filter_rules_stateless(_if); + } else { + return configure_rx_filter_rules_statefull(_if); + } + + return 0; +} +int CTRexExtendedDriverBase1G::configure_rx_filter_rules_statefull(CPhyEthIF * _if) { uint16_t hops = get_rx_check_hops(); uint16_t v4_hops = (hops << 8)&0xff00; uint8_t protocol; @@ -4471,6 +4539,54 @@ int CTRexExtendedDriverBase1G::configure_rx_filter_rules(CPhyEthIF * _if){ return (0); } +// Sadly, DPDK has no support for i350 filters, so we need to implement by writing to registers. +int CTRexExtendedDriverBase1G::configure_rx_filter_rules_stateless(CPhyEthIF * _if) { + /* enable filter to pass packet to rx queue 1 */ + _if->pci_reg_write( E1000_IMIR(0), 0x00020000); + _if->pci_reg_write( E1000_IMIREXT(0), 0x00081000); + + uint8_t len = 24; + uint32_t mask = 0x1 | 0x2; // first two rules + int rule_id; + + // clear rules 0, 1 registers + for (rule_id = 0 ; rule_id < 2; rule_id++) { + for (int i=0; i<0xff; i+=4) { + _if->pci_reg_write( (E1000_FHFT(rule_id)+i) , 0); + } + } + + rule_id = 0; + // filter for byte 18 of packet (lsb of IP ID) should equal ff + _if->pci_reg_write( (E1000_FHFT(rule_id)+(2*16)) , 0x00ff0000); + _if->pci_reg_write( (E1000_FHFT(rule_id)+(2*16) + 8) , 0x04); /* MASK */ + // + bytes 12 + 13 (ether type) should indicate IP. + _if->pci_reg_write( (E1000_FHFT(rule_id)+(1*16) + 4) , 0x00000008); + _if->pci_reg_write( (E1000_FHFT(rule_id)+(1*16) + 8) , 0x30); /* MASK */ + // FLEX_PRIO[[18:16] = 1, RQUEUE[10:8] = 1 + _if->pci_reg_write( (E1000_FHFT(rule_id) + 0xFC) , (1 << 16) | (1 << 8) | len); + + // same like 0, but with vlan. type should be vlan. Inside vlan, should be IP with lsb of IP ID equals 0xff + rule_id = 1; + // filter for byte 22 of packet (msb of IP ID) should equal ff + _if->pci_reg_write( (E1000_FHFT(rule_id)+(2*16) + 4) , 0x00ff0000); + _if->pci_reg_write( (E1000_FHFT(rule_id)+(2*16) + 8) , 0x40 | 0x03); /* MASK */ + // + bytes 12 + 13 (ether type) should indicate VLAN. + _if->pci_reg_write( (E1000_FHFT(rule_id)+(1*16) + 4) , 0x00000081); + _if->pci_reg_write( (E1000_FHFT(rule_id)+(1*16) + 8) , 0x30); /* MASK */ + // + bytes 16 + 17 (vlan type) should indicate IP. + _if->pci_reg_write( (E1000_FHFT(rule_id)+(2*16) ) , 0x00000080); + // Was written together with IP ID filter + // _if->pci_reg_write( (E1000_FHFT(rule_id)+(2*16) + 8) , 0x03); /* MASK */ + // FLEX_PRIO[[18:16] = 1, RQUEUE[10:8] = 1 + _if->pci_reg_write( (E1000_FHFT(rule_id) + 0xFC) , (1 << 16) | (1 << 8) | len); + + /* enable rules */ + _if->pci_reg_write(E1000_WUFC, (mask << 16) | (1 << 14) ); + + return (0); +} + void CTRexExtendedDriverBase1G::get_extended_stats(CPhyEthIF * _if,CPhyEthIFStats *stats){ @@ -4641,15 +4757,10 @@ int CTRexExtendedDriverBase10G::wait_for_stable_link(){ } //////////////////////////////////////////////////////////////////////////////// - - void CTRexExtendedDriverBase40G::clear_extended_stats(CPhyEthIF * _if){ - rte_eth_stats_reset(_if->get_port_id()); - } - void CTRexExtendedDriverBaseVIC::update_configuration(port_cfg_t * cfg){ cfg->m_tx_conf.tx_thresh.pthresh = TX_PTHRESH; cfg->m_tx_conf.tx_thresh.hthresh = TX_HTHRESH; @@ -4664,15 +4775,14 @@ void CTRexExtendedDriverBase40G::update_configuration(port_cfg_t * cfg){ cfg->update_global_config_fdir_40g(); } - /* Add rule to send packets with protocol 'type', and ttl 'ttl' to rx queue 1 */ -void CTRexExtendedDriverBase40G::add_rules(CPhyEthIF * _if, - uint16_t type, - uint8_t ttl){ - uint8_t port_id = _if->get_port_id(); +// ttl is used in statefull mode, and ip_id in stateless. We configure the driver registers so that only one of them applies. +// So, the rule will apply if packet has either the correct ttl or IP ID, depending if we are in statfull or stateless. +void CTRexExtendedDriverBase40G::add_del_rules(enum rte_filter_op op, uint8_t port_id, uint16_t type, uint8_t ttl, uint16_t ip_id, int queue, uint16_t stat_idx) { int ret=rte_eth_dev_filter_supported(port_id, RTE_ETH_FILTER_FDIR); + static int filter_soft_id = 0; - if ( ret !=0 ){ + if ( ret != 0 ){ rte_exit(EXIT_FAILURE, "rte_eth_dev_filter_supported " "err=%d, port=%u \n", ret, port_id); @@ -4682,21 +4792,29 @@ void CTRexExtendedDriverBase40G::add_rules(CPhyEthIF * _if, memset(&filter,0,sizeof(struct rte_eth_fdir_filter)); - filter.action.rx_queue =1; +#if 0 + printf("40g::%s rules: port:%d, type:%d ttl:%d, ip_id:%x, q:%d hw index:%d\n", (op == RTE_ETH_FILTER_ADD) ? "add" : "del" + , port_id, type, ttl, ip_id, queue, stat_idx); +#endif + + filter.action.rx_queue = queue; filter.action.behavior =RTE_ETH_FDIR_ACCEPT; filter.action.report_status =RTE_ETH_FDIR_NO_REPORT_STATUS; - filter.soft_id=0; - + filter.action.stat_count_index = stat_idx; + filter.soft_id = filter_soft_id++; filter.input.flow_type = type; + switch (type) { case RTE_ETH_FLOW_NONFRAG_IPV4_OTHER: filter.input.flow.ip4_flow.ttl=ttl; + filter.input.flow.ip4_flow.ip_id = ip_id; filter.input.flow.ip4_flow.l4_protocol = IPPROTO_ICMP; // In this case we want filter for icmp packets break; case RTE_ETH_FLOW_NONFRAG_IPV4_UDP: case RTE_ETH_FLOW_NONFRAG_IPV4_TCP: case RTE_ETH_FLOW_NONFRAG_IPV4_SCTP: filter.input.flow.ip4_flow.ttl=ttl; + filter.input.flow.ip4_flow.ip_id = ip_id; break; case RTE_ETH_FLOW_NONFRAG_IPV6_UDP: case RTE_ETH_FLOW_NONFRAG_IPV6_TCP: @@ -4708,9 +4826,8 @@ void CTRexExtendedDriverBase40G::add_rules(CPhyEthIF * _if, break; } - /* We want to place latency packets in queue 1 */ ret=rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_FDIR, - RTE_ETH_FILTER_ADD, (void*)&filter); + op, (void*)&filter); if ( ret !=0 ){ rte_exit(EXIT_FAILURE, "rte_eth_dev_filter_ctrl" @@ -4719,25 +4836,107 @@ void CTRexExtendedDriverBase40G::add_rules(CPhyEthIF * _if, } } +// type - rule type. Currently we only support rules in IP ID. +// proto - Packet protocol: UDP or TCP +// id - Counter id in HW. We assume it is in the range 0..TREX_FDIR_STAT_SIZE +int CTRexExtendedDriverBase40G::add_del_rx_flow_stat_rule(uint8_t port_id, enum rte_filter_op op, uint8_t type, uint16_t proto, uint16_t id) { + uint32_t rule_id = (port_id % m_if_per_card) * TREX_FDIR_STAT_SIZE + id; + uint16_t rte_type = RTE_ETH_FLOW_NONFRAG_IPV4_OTHER; + + switch(proto) { + case IPPROTO_TCP: + rte_type = RTE_ETH_FLOW_NONFRAG_IPV4_TCP; + break; + case IPPROTO_UDP: + rte_type = RTE_ETH_FLOW_NONFRAG_IPV4_UDP; + break; + default: + rte_type = RTE_ETH_FLOW_NONFRAG_IPV4_OTHER; + break; + } + add_del_rules(op, port_id, rte_type, 0, IP_ID_RESERVE_BASE + id, MAIN_DPDK_DATA_Q, rule_id); + return 0; +} -int CTRexExtendedDriverBase40G::configure_rx_filter_rules(CPhyEthIF * _if){ +int CTRexExtendedDriverBase40G::configure_rx_filter_rules_statfull(CPhyEthIF * _if) { + uint32_t port_id = _if->get_port_id(); uint16_t hops = get_rx_check_hops(); int i; - for (i=0; i<2; i++) { - uint8_t ttl=0xff-i-hops; - add_rules(_if,RTE_ETH_FLOW_NONFRAG_IPV4_UDP, ttl); - add_rules(_if,RTE_ETH_FLOW_NONFRAG_IPV4_TCP, ttl); - add_rules(_if,RTE_ETH_FLOW_NONFRAG_IPV6_UDP, ttl); - add_rules(_if,RTE_ETH_FLOW_NONFRAG_IPV6_TCP, ttl); + + for (i = 0; i < 2; i++) { + uint8_t ttl = TTL_RESERVE_DUPLICATE - i - hops; + add_del_rules(RTE_ETH_FILTER_ADD, port_id, RTE_ETH_FLOW_NONFRAG_IPV4_UDP, ttl, 0, MAIN_DPDK_RX_Q, 0); + add_del_rules(RTE_ETH_FILTER_ADD, port_id, RTE_ETH_FLOW_NONFRAG_IPV4_TCP, ttl, 0, MAIN_DPDK_RX_Q, 0); + add_del_rules(RTE_ETH_FILTER_ADD, port_id, RTE_ETH_FLOW_NONFRAG_IPV6_UDP, ttl, 0, MAIN_DPDK_RX_Q, 0); + add_del_rules(RTE_ETH_FILTER_ADD, port_id, RTE_ETH_FLOW_NONFRAG_IPV6_TCP, ttl, 0, MAIN_DPDK_RX_Q, 0); } - /* Configure queue for latency packets */ - add_rules(_if,RTE_ETH_FLOW_NONFRAG_IPV4_OTHER, 255); - add_rules(_if,RTE_ETH_FLOW_NONFRAG_IPV4_SCTP, 255); + /* Configure rules for latency measurement packets */ + add_del_rules(RTE_ETH_FILTER_ADD, port_id, RTE_ETH_FLOW_NONFRAG_IPV4_OTHER, TTL_RESERVE_DUPLICATE - hops, 0, MAIN_DPDK_RX_Q, 0); + add_del_rules(RTE_ETH_FILTER_ADD, port_id, RTE_ETH_FLOW_NONFRAG_IPV4_SCTP, TTL_RESERVE_DUPLICATE - hops, 0, MAIN_DPDK_RX_Q, 0); - return (0); + return 0; +} + +int CTRexExtendedDriverBase40G::configure_rx_filter_rules(CPhyEthIF * _if) { + if (get_is_stateless()) { + return 0; // Rules are configured dynamically in stateless + } else { + return configure_rx_filter_rules_statfull(_if); + } +} + +// instead of adding this to rte_ethdev.h +extern "C" int rte_eth_fdir_stats_get(uint8_t port_id, uint32_t *stats, uint32_t start, uint32_t len); +int CTRexExtendedDriverBase40G::get_rx_stats(CPhyEthIF * _if, uint32_t *stats, uint32_t *prev_stats, int index) { + uint32_t hw_stats[TREX_FDIR_STAT_SIZE]; + uint32_t port_id = _if->get_port_id(); + uint32_t len, start, loop_start; + + if (index >= 0) { + len = 1; + start = (port_id % m_if_per_card) * TREX_FDIR_STAT_SIZE + index; + loop_start = index; + } else { + start = (port_id % m_if_per_card) * TREX_FDIR_STAT_SIZE; + len = TREX_FDIR_STAT_SIZE; + loop_start = 0; + } + + rte_eth_fdir_stats_get(port_id, hw_stats, start, len); + for (int i = loop_start; i < loop_start + len; i++) { + if (hw_stats[i] >= prev_stats[i]) { + stats[i] = (uint64_t)(hw_stats[i] - prev_stats[i]); + } else { + // Wrap around + stats[i] = (uint64_t)((hw_stats[i] + ((uint64_t)1 << 32)) - prev_stats[i]); + } + prev_stats[i] = hw_stats[i]; + } + + return 0; } +// if fd != NULL, dump fdir stats of _if +// return num of filters +int CTRexExtendedDriverBase40G::dump_fdir_global_stats(CPhyEthIF * _if, FILE *fd) +{ + uint32_t port_id = _if->get_port_id(); + struct rte_eth_fdir_stats stat; + int ret; + + ret = rte_eth_dev_filter_ctrl(port_id, RTE_ETH_FILTER_FDIR, RTE_ETH_FILTER_STATS, (void*)&stat); + if (ret == 0) { + if (fd) + fprintf(fd, "Num filters on guarant poll:%d, best effort poll:%d\n", stat.guarant_cnt, stat.best_cnt); + return (stat.guarant_cnt + stat.best_cnt); + } else { + if (fd) + fprintf(fd, "Failed reading fdir statistics\n"); + return -1; + } +} + void CTRexExtendedDriverBase40G::get_extended_stats(CPhyEthIF * _if,CPhyEthIFStats *stats){ struct rte_eth_stats stats1; @@ -4881,12 +5080,15 @@ struct rte_mbuf * rte_mbuf_convert_to_one_seg(struct rte_mbuf *m){ return(r); } - /*********************************************************** * platfrom API object * TODO: REMOVE THIS TO A SEPERATE FILE * **********************************************************/ +void TrexDpdkPlatformApi::get_port_num(uint8_t &port_num) const { + port_num = g_trex.m_max_ports; +} + void TrexDpdkPlatformApi::get_global_stats(TrexPlatformGlobalStats &stats) const { CGlobalStats trex_stats; @@ -4950,3 +5152,22 @@ TrexDpdkPlatformApi::publish_async_data_now(uint32_t key) const { g_trex.publish_async_barrier(key); } +void +TrexDpdkPlatformApi::get_interface_stat_info(uint8_t interface_id, uint16_t &num_counters, uint16_t &capabilities) const { + num_counters = CTRexExtendedDriverDb::Ins()->get_drv()->get_stat_counters_num(); + capabilities = CTRexExtendedDriverDb::Ins()->get_drv()->get_rx_stat_capabilities(); +} + +int TrexDpdkPlatformApi::get_rx_stats(uint8 port_id, uint64_t *stats, int index, bool reset) const { + return g_trex.m_ports[port_id].get_rx_stats(stats, index, reset); +} + +int TrexDpdkPlatformApi::add_rx_flow_stat_rule(uint8_t port_id, uint8_t type, uint16_t proto, uint16_t id) const { + return CTRexExtendedDriverDb::Ins()->get_drv() + ->add_del_rx_flow_stat_rule(port_id, RTE_ETH_FILTER_ADD, type, proto, id); +} + +int TrexDpdkPlatformApi::del_rx_flow_stat_rule(uint8_t port_id, uint8_t type, uint16_t proto, uint16_t id) const { + return CTRexExtendedDriverDb::Ins()->get_drv() + ->add_del_rx_flow_stat_rule(port_id, RTE_ETH_FILTER_DELETE, type, proto, id); +} |