diff options
author | Luca Boccassi <luca.boccassi@gmail.com> | 2018-08-14 18:55:37 +0100 |
---|---|---|
committer | Luca Boccassi <luca.boccassi@gmail.com> | 2018-08-14 18:57:39 +0100 |
commit | ae1479de3027a4a0f68d90bf65ac6ff2b862b837 (patch) | |
tree | 5dbca675b6717b6b61abbe1a9583d5166fed942b /examples | |
parent | 8cee230dd1f0f9f31f4b0339c671d0b1ee14e111 (diff) | |
parent | b63264c8342e6a1b6971c79550d2af2024b6a4de (diff) |
Merge branch 'upstream' into 18.08.x
Change-Id: Ifbda2d554199dd4d11e01f0090881b5f0103ae12
Signed-off-by: Luca Boccassi <luca.boccassi@gmail.com>
Diffstat (limited to 'examples')
92 files changed, 3201 insertions, 2703 deletions
diff --git a/examples/bbdev_app/main.c b/examples/bbdev_app/main.c index 254cc067..045a190b 100644 --- a/examples/bbdev_app/main.c +++ b/examples/bbdev_app/main.c @@ -64,11 +64,7 @@ static const struct rte_eth_conf port_conf = { .mq_mode = ETH_MQ_RX_NONE, .max_rx_pkt_len = ETHER_MAX_LEN, .split_hdr_size = 0, - .header_split = 0, /**< Header Split disabled */ - .hw_ip_checksum = 0, /**< IP checksum offload disabled */ - .hw_vlan_filter = 0, /**< VLAN filtering disabled */ - .jumbo_frame = 0, /**< Jumbo Frame Support disabled */ - .hw_strip_crc = 0, /**< CRC stripped by hardware */ + .offloads = DEV_RX_OFFLOAD_CRC_STRIP, }, .txmode = { .mq_mode = ETH_MQ_TX_NONE, diff --git a/examples/bond/main.c b/examples/bond/main.c index 65e0edd2..23d0981a 100644 --- a/examples/bond/main.c +++ b/examples/bond/main.c @@ -122,7 +122,6 @@ static struct rte_eth_conf port_conf = { .mq_mode = ETH_MQ_RX_NONE, .max_rx_pkt_len = ETHER_MAX_LEN, .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = DEV_RX_OFFLOAD_CRC_STRIP, }, .rx_adv_conf = { @@ -154,6 +153,18 @@ slave_port_init(uint16_t portid, struct rte_mempool *mbuf_pool) if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) local_port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MBUF_FAST_FREE; + + local_port_conf.rx_adv_conf.rss_conf.rss_hf &= + dev_info.flow_type_rss_offloads; + if (local_port_conf.rx_adv_conf.rss_conf.rss_hf != + port_conf.rx_adv_conf.rss_conf.rss_hf) { + printf("Port %u modified RSS hash function based on hardware support," + "requested:%#"PRIx64" configured:%#"PRIx64"\n", + portid, + port_conf.rx_adv_conf.rss_conf.rss_hf, + local_port_conf.rx_adv_conf.rss_conf.rss_hf); + } + retval = rte_eth_dev_configure(portid, 1, 1, &local_port_conf); if (retval != 0) rte_exit(EXIT_FAILURE, "port %u: configuration failed (res=%d)\n", @@ -177,7 +188,6 @@ slave_port_init(uint16_t portid, struct rte_mempool *mbuf_pool) /* TX setup */ txq_conf = dev_info.default_txconf; - txq_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txq_conf.offloads = local_port_conf.txmode.offloads; retval = rte_eth_tx_queue_setup(portid, 0, nb_txd, rte_eth_dev_socket_id(portid), &txq_conf); @@ -246,7 +256,6 @@ bond_port_init(struct rte_mempool *mbuf_pool) /* TX setup */ txq_conf = dev_info.default_txconf; - txq_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txq_conf.offloads = local_port_conf.txmode.offloads; retval = rte_eth_tx_queue_setup(BOND_PORT, 0, nb_txd, rte_eth_dev_socket_id(BOND_PORT), &txq_conf); diff --git a/examples/distributor/main.c b/examples/distributor/main.c index 2c593648..03a05e3d 100644 --- a/examples/distributor/main.c +++ b/examples/distributor/main.c @@ -80,7 +80,6 @@ static const struct rte_eth_conf port_conf_default = { .rxmode = { .mq_mode = ETH_MQ_RX_RSS, .max_rx_pkt_len = ETHER_MAX_LEN, - .ignore_offload_bitfield = 1, }, .txmode = { .mq_mode = ETH_MQ_TX_NONE, @@ -124,6 +123,17 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool) port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MBUF_FAST_FREE; + port_conf.rx_adv_conf.rss_conf.rss_hf &= + dev_info.flow_type_rss_offloads; + if (port_conf.rx_adv_conf.rss_conf.rss_hf != + port_conf_default.rx_adv_conf.rss_conf.rss_hf) { + printf("Port %u modified RSS hash function based on hardware support," + "requested:%#"PRIx64" configured:%#"PRIx64"\n", + port, + port_conf_default.rx_adv_conf.rss_conf.rss_hf, + port_conf.rx_adv_conf.rss_conf.rss_hf); + } + retval = rte_eth_dev_configure(port, rxRings, txRings, &port_conf); if (retval != 0) return retval; @@ -141,7 +151,6 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool) } txconf = dev_info.default_txconf; - txconf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txconf.offloads = port_conf.txmode.offloads; for (q = 0; q < txRings; q++) { retval = rte_eth_tx_queue_setup(port, q, nb_txd, diff --git a/examples/ethtool/Makefile b/examples/ethtool/Makefile index 2b40b4b6..3d9d4f06 100644 --- a/examples/ethtool/Makefile +++ b/examples/ethtool/Makefile @@ -10,7 +10,7 @@ RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk -ifneq ($(CONFIG_RTE_EXEC_ENV),"linuxapp") +ifneq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) $(info This application can only operate in a linuxapp environment, \ please change the definition of the RTE_TARGET environment variable) else diff --git a/examples/ethtool/ethtool-app/main.c b/examples/ethtool/ethtool-app/main.c index c1815bb9..dc93adfe 100644 --- a/examples/ethtool/ethtool-app/main.c +++ b/examples/ethtool/ethtool-app/main.c @@ -99,7 +99,6 @@ static void setup_ports(struct app_config *app_cfg, int cnt_ports) memset(&cfg_port, 0, sizeof(cfg_port)); cfg_port.txmode.mq_mode = ETH_MQ_TX_NONE; - cfg_port.rxmode.ignore_offload_bitfield = 1; for (idx_port = 0; idx_port < cnt_ports; idx_port++) { struct app_port *ptr_port = &app_cfg->ports[idx_port]; @@ -142,7 +141,6 @@ static void setup_ports(struct app_config *app_cfg, int cnt_ports) "rte_eth_rx_queue_setup failed" ); txconf = dev_info.default_txconf; - txconf.txq_flags = ETH_TXQ_FLAGS_IGNORE; if (rte_eth_tx_queue_setup( idx_port, 0, nb_txd, rte_eth_dev_socket_id(idx_port), &txconf) < 0) diff --git a/examples/ethtool/lib/Makefile b/examples/ethtool/lib/Makefile index 2576910f..6eaa640b 100644 --- a/examples/ethtool/lib/Makefile +++ b/examples/ethtool/lib/Makefile @@ -10,7 +10,7 @@ RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk -ifneq ($(CONFIG_RTE_EXEC_ENV),"linuxapp") +ifneq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) $(error This application can only operate in a linuxapp environment, \ please change the definition of the RTE_TARGET environment variable) endif diff --git a/examples/eventdev_pipeline/main.c b/examples/eventdev_pipeline/main.c index b698e4ca..700bc696 100644 --- a/examples/eventdev_pipeline/main.c +++ b/examples/eventdev_pipeline/main.c @@ -267,7 +267,6 @@ port_init(uint8_t port, struct rte_mempool *mbuf_pool) .rxmode = { .mq_mode = ETH_MQ_RX_RSS, .max_rx_pkt_len = ETHER_MAX_LEN, - .ignore_offload_bitfield = 1, }, .rx_adv_conf = { .rss_conf = { @@ -293,6 +292,17 @@ port_init(uint8_t port, struct rte_mempool *mbuf_pool) port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MBUF_FAST_FREE; + port_conf.rx_adv_conf.rss_conf.rss_hf &= + dev_info.flow_type_rss_offloads; + if (port_conf.rx_adv_conf.rss_conf.rss_hf != + port_conf_default.rx_adv_conf.rss_conf.rss_hf) { + printf("Port %u modified RSS hash function based on hardware support," + "requested:%#"PRIx64" configured:%#"PRIx64"\n", + port, + port_conf_default.rx_adv_conf.rss_conf.rss_hf, + port_conf.rx_adv_conf.rss_conf.rss_hf); + } + /* Configure the Ethernet device. */ retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf); if (retval != 0) @@ -307,7 +317,6 @@ port_init(uint8_t port, struct rte_mempool *mbuf_pool) } txconf = dev_info.default_txconf; - txconf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txconf.offloads = port_conf_default.txmode.offloads; /* Allocate and set up 1 TX queue per Ethernet port. */ for (q = 0; q < tx_rings; q++) { diff --git a/examples/exception_path/main.c b/examples/exception_path/main.c index 2b381a5d..440422bc 100644 --- a/examples/exception_path/main.c +++ b/examples/exception_path/main.c @@ -88,7 +88,6 @@ /* Options for configuring ethernet port */ static struct rte_eth_conf port_conf = { .rxmode = { - .ignore_offload_bitfield = 1, .offloads = DEV_RX_OFFLOAD_CRC_STRIP, }, .txmode = { @@ -132,6 +131,9 @@ print_stats(void) " Lcore Port RX TX Dropped on TX\n" "------- ------ ------------ ------------ ---------------\n"); RTE_LCORE_FOREACH(i) { + /* limit ourselves to application supported cores only */ + if (i >= APP_MAX_LCORE) + break; printf("%6u %7u %13"PRIu64" %13"PRIu64" %16"PRIu64"\n", i, (unsigned)port_ids[i], lcore_stats[i].rx, lcore_stats[i].tx, @@ -457,7 +459,6 @@ init_port(uint16_t port) port, ret); txq_conf = dev_info.default_txconf; - txq_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txq_conf.offloads = local_port_conf.txmode.offloads; ret = rte_eth_tx_queue_setup(port, 0, nb_txd, rte_eth_dev_socket_id(port), diff --git a/examples/flow_classify/flow_classify.c b/examples/flow_classify/flow_classify.c index 6412fe44..19961292 100644 --- a/examples/flow_classify/flow_classify.c +++ b/examples/flow_classify/flow_classify.c @@ -62,7 +62,6 @@ const char cb_port_delim[] = ":"; static const struct rte_eth_conf port_conf_default = { .rxmode = { .max_rx_pkt_len = ETHER_MAX_LEN, - .ignore_offload_bitfield = 1, }, }; @@ -222,7 +221,6 @@ port_init(uint8_t port, struct rte_mempool *mbuf_pool) } txconf = dev_info.default_txconf; - txconf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txconf.offloads = port_conf.txmode.offloads; /* Allocate and set up 1 TX queue per Ethernet port. */ for (q = 0; q < tx_rings; q++) { diff --git a/examples/flow_filtering/main.c b/examples/flow_filtering/main.c index e0ee5167..ce91e8a6 100644 --- a/examples/flow_filtering/main.c +++ b/examples/flow_filtering/main.c @@ -121,7 +121,6 @@ init_port(void) struct rte_eth_conf port_conf = { .rxmode = { .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = DEV_RX_OFFLOAD_CRC_STRIP, }, .txmode = { @@ -133,6 +132,22 @@ init_port(void) DEV_TX_OFFLOAD_SCTP_CKSUM | DEV_TX_OFFLOAD_TCP_TSO, }, + /* + * Initialize fdir_conf of rte_eth_conf. + * Fdir is used in flow filtering for I40e, + * so rte_flow rules involve some fdir + * configurations. In long term it's better + * that drivers don't require any fdir + * configuration for rte_flow, but we need to + * get this workaround so that sample app can + * run on I40e. + */ + .fdir_conf = { + .mode = RTE_FDIR_MODE_PERFECT, + .pballoc = RTE_FDIR_PBALLOC_64K, + .status = RTE_FDIR_REPORT_STATUS, + .drop_queue = 127, + }, }; struct rte_eth_txconf txq_conf; struct rte_eth_rxconf rxq_conf; diff --git a/examples/ip_fragmentation/main.c b/examples/ip_fragmentation/main.c index 8952ea45..5306d767 100644 --- a/examples/ip_fragmentation/main.c +++ b/examples/ip_fragmentation/main.c @@ -140,7 +140,6 @@ static struct rte_eth_conf port_conf = { .rxmode = { .max_rx_pkt_len = JUMBO_FRAME_MAX_SIZE, .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = (DEV_RX_OFFLOAD_CHECKSUM | DEV_RX_OFFLOAD_JUMBO_FRAME | DEV_RX_OFFLOAD_CRC_STRIP), @@ -973,7 +972,6 @@ main(int argc, char **argv) fflush(stdout); txconf = &dev_info.default_txconf; - txconf->txq_flags = ETH_TXQ_FLAGS_IGNORE; txconf->offloads = local_port_conf.txmode.offloads; ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd, socket, txconf); diff --git a/examples/ip_pipeline/Makefile b/examples/ip_pipeline/Makefile index 11d2b35d..3fb98ce3 100644 --- a/examples/ip_pipeline/Makefile +++ b/examples/ip_pipeline/Makefile @@ -67,7 +67,7 @@ RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk -ifneq ($(CONFIG_RTE_EXEC_ENV),"linuxapp") +ifneq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) $(info This application can only operate in a linuxapp environment, \ please change the definition of the RTE_TARGET environment variable) all: diff --git a/examples/ip_pipeline/cli.c b/examples/ip_pipeline/cli.c index c9587f56..102a1d6b 100644 --- a/examples/ip_pipeline/cli.c +++ b/examples/ip_pipeline/cli.c @@ -9,6 +9,7 @@ #include <rte_common.h> #include <rte_cycles.h> +#include <rte_ethdev.h> #include "cli.h" #include "kni.h" @@ -48,13 +49,13 @@ is_comment(char *in) return 0; } -/** - * mempool <mempool_name> - * buffer <buffer_size> - * pool <pool_size> - * cache <cache_size> - * cpu <cpu_id> - */ +static const char cmd_mempool_help[] = +"mempool <mempool_name>\n" +" buffer <buffer_size>\n" +" pool <pool_size>\n" +" cache <cache_size>\n" +" cpu <cpu_id>\n"; + static void cmd_mempool(char **tokens, uint32_t n_tokens, @@ -119,14 +120,14 @@ cmd_mempool(char **tokens, } } -/** - * link <link_name> - * dev <device_name> | port <port_id> - * rxq <n_queues> <queue_size> <mempool_name> - * txq <n_queues> <queue_size> - * promiscuous on | off - * [rss <qid_0> ... <qid_n>] - */ +static const char cmd_link_help[] = +"link <link_name>\n" +" dev <device_name> | port <port_id>\n" +" rxq <n_queues> <queue_size> <mempool_name>\n" +" txq <n_queues> <queue_size>\n" +" promiscuous on | off\n" +" [rss <qid_0> ... <qid_n>]\n"; + static void cmd_link(char **tokens, uint32_t n_tokens, @@ -237,12 +238,97 @@ cmd_link(char **tokens, } } -/** - * swq <swq_name> - * size <size> - * cpu <cpu_id> +/* Print the link stats and info */ +static void +print_link_info(struct link *link, char *out, size_t out_size) +{ + struct rte_eth_stats stats; + struct ether_addr mac_addr; + struct rte_eth_link eth_link; + uint16_t mtu; + + memset(&stats, 0, sizeof(stats)); + rte_eth_stats_get(link->port_id, &stats); + + rte_eth_macaddr_get(link->port_id, &mac_addr); + rte_eth_link_get(link->port_id, ð_link); + rte_eth_dev_get_mtu(link->port_id, &mtu); + + snprintf(out, out_size, + "\n" + "%s: flags=<%s> mtu %u\n" + "\tether %02X:%02X:%02X:%02X:%02X:%02X rxqueues %u txqueues %u\n" + "\tport# %u speed %u Mbps\n" + "\tRX packets %" PRIu64" bytes %" PRIu64"\n" + "\tRX errors %" PRIu64" missed %" PRIu64" no-mbuf %" PRIu64"\n" + "\tTX packets %" PRIu64" bytes %" PRIu64"\n" + "\tTX errors %" PRIu64"\n", + link->name, + eth_link.link_status == 0 ? "DOWN" : "UP", + mtu, + mac_addr.addr_bytes[0], mac_addr.addr_bytes[1], + mac_addr.addr_bytes[2], mac_addr.addr_bytes[3], + mac_addr.addr_bytes[4], mac_addr.addr_bytes[5], + link->n_rxq, + link->n_txq, + link->port_id, + eth_link.link_speed, + stats.ipackets, + stats.ibytes, + stats.ierrors, + stats.imissed, + stats.rx_nombuf, + stats.opackets, + stats.obytes, + stats.oerrors); +} + +/* + * link show [<link_name>] */ static void +cmd_link_show(char **tokens, uint32_t n_tokens, char *out, size_t out_size) +{ + struct link *link; + char *link_name; + + if (n_tokens != 2 && n_tokens != 3) { + snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); + return; + } + + if (n_tokens == 2) { + link = link_next(NULL); + + while (link != NULL) { + out_size = out_size - strlen(out); + out = &out[strlen(out)]; + + print_link_info(link, out, out_size); + link = link_next(link); + } + } else { + out_size = out_size - strlen(out); + out = &out[strlen(out)]; + + link_name = tokens[2]; + link = link_find(link_name); + + if (link == NULL) { + snprintf(out, out_size, MSG_ARG_INVALID, + "Link does not exist"); + return; + } + print_link_info(link, out, out_size); + } +} + +static const char cmd_swq_help[] = +"swq <swq_name>\n" +" size <size>\n" +" cpu <cpu_id>\n"; + +static void cmd_swq(char **tokens, uint32_t n_tokens, char *out, @@ -286,12 +372,12 @@ cmd_swq(char **tokens, } } -/** - * tmgr subport profile - * <tb_rate> <tb_size> - * <tc0_rate> <tc1_rate> <tc2_rate> <tc3_rate> - * <tc_period> - */ +static const char cmd_tmgr_subport_profile_help[] = +"tmgr subport profile\n" +" <tb_rate> <tb_size>\n" +" <tc0_rate> <tc1_rate> <tc2_rate> <tc3_rate>\n" +" <tc_period>\n"; + static void cmd_tmgr_subport_profile(char **tokens, uint32_t n_tokens, @@ -334,14 +420,14 @@ cmd_tmgr_subport_profile(char **tokens, } } -/** - * tmgr pipe profile - * <tb_rate> <tb_size> - * <tc0_rate> <tc1_rate> <tc2_rate> <tc3_rate> - * <tc_period> - * <tc_ov_weight> - * <wrr_weight0..15> - */ +static const char cmd_tmgr_pipe_profile_help[] = +"tmgr pipe profile\n" +" <tb_rate> <tb_size>\n" +" <tc0_rate> <tc1_rate> <tc2_rate> <tc3_rate>\n" +" <tc_period>\n" +" <tc_ov_weight>\n" +" <wrr_weight0..15>\n"; + static void cmd_tmgr_pipe_profile(char **tokens, uint32_t n_tokens, @@ -397,16 +483,16 @@ cmd_tmgr_pipe_profile(char **tokens, } } -/** - * tmgr <tmgr_name> - * rate <rate> - * spp <n_subports_per_port> - * pps <n_pipes_per_subport> - * qsize <qsize_tc0> <qsize_tc1> <qsize_tc2> <qsize_tc3> - * fo <frame_overhead> - * mtu <mtu> - * cpu <cpu_id> - */ +static const char cmd_tmgr_help[] = +"tmgr <tmgr_name>\n" +" rate <rate>\n" +" spp <n_subports_per_port>\n" +" pps <n_pipes_per_subport>\n" +" qsize <qsize_tc0> <qsize_tc1> <qsize_tc2> <qsize_tc3>\n" +" fo <frame_overhead>\n" +" mtu <mtu>\n" +" cpu <cpu_id>\n"; + static void cmd_tmgr(char **tokens, uint32_t n_tokens, @@ -503,10 +589,10 @@ cmd_tmgr(char **tokens, } } -/** - * tmgr <tmgr_name> subport <subport_id> - * profile <subport_profile_id> - */ +static const char cmd_tmgr_subport_help[] = +"tmgr <tmgr_name> subport <subport_id>\n" +" profile <subport_profile_id>\n"; + static void cmd_tmgr_subport(char **tokens, uint32_t n_tokens, @@ -541,11 +627,12 @@ cmd_tmgr_subport(char **tokens, } } -/** - * tmgr <tmgr_name> subport <subport_id> pipe - * from <pipe_id_first> to <pipe_id_last> - * profile <pipe_profile_id> - */ + +static const char cmd_tmgr_subport_pipe_help[] = +"tmgr <tmgr_name> subport <subport_id> pipe\n" +" from <pipe_id_first> to <pipe_id_last>\n" +" profile <pipe_profile_id>\n"; + static void cmd_tmgr_subport_pipe(char **tokens, uint32_t n_tokens, @@ -611,9 +698,10 @@ cmd_tmgr_subport_pipe(char **tokens, } } -/** - * tap <tap_name> - */ + +static const char cmd_tap_help[] = +"tap <tap_name>\n"; + static void cmd_tap(char **tokens, uint32_t n_tokens, @@ -637,12 +725,12 @@ cmd_tap(char **tokens, } } -/** - * kni <kni_name> - * link <link_name> - * mempool <mempool_name> - * [thread <thread_id>] - */ +static const char cmd_kni_help[] = +"kni <kni_name>\n" +" link <link_name>\n" +" mempool <mempool_name>\n" +" [thread <thread_id>]\n"; + static void cmd_kni(char **tokens, uint32_t n_tokens, @@ -697,11 +785,12 @@ cmd_kni(char **tokens, } } -/** - * port in action profile <profile_name> - * [filter match | mismatch offset <key_offset> mask <key_mask> key <key_value> port <port_id>] - * [balance offset <key_offset> mask <key_mask> port <port_id0> ... <port_id15>] - */ + +static const char cmd_port_in_action_profile_help[] = +"port in action profile <profile_name>\n" +" [filter match | mismatch offset <key_offset> mask <key_mask> key <key_value> port <port_id>]\n" +" [balance offset <key_offset> mask <key_mask> port <port_id0> ... <port_id15>]\n"; + static void cmd_port_in_action_profile(char **tokens, uint32_t n_tokens, @@ -861,24 +950,25 @@ cmd_port_in_action_profile(char **tokens, } } -/** - * table action profile <profile_name> - * ipv4 | ipv6 - * offset <ip_offset> - * fwd - * [balance offset <key_offset> mask <key_mask> outoffset <out_offset>] - * [meter srtcm | trtcm - * tc <n_tc> - * stats none | pkts | bytes | both] - * [tm spp <n_subports_per_port> pps <n_pipes_per_subport>] - * [encap ether | vlan | qinq | mpls | pppoe] - * [nat src | dst - * proto udp | tcp] - * [ttl drop | fwd - * stats none | pkts] - * [stats pkts | bytes | both] - * [time] - */ + +static const char cmd_table_action_profile_help[] = +"table action profile <profile_name>\n" +" ipv4 | ipv6\n" +" offset <ip_offset>\n" +" fwd\n" +" [balance offset <key_offset> mask <key_mask> outoffset <out_offset>]\n" +" [meter srtcm | trtcm\n" +" tc <n_tc>\n" +" stats none | pkts | bytes | both]\n" +" [tm spp <n_subports_per_port> pps <n_pipes_per_subport>]\n" +" [encap ether | vlan | qinq | mpls | pppoe]\n" +" [nat src | dst\n" +" proto udp | tcp]\n" +" [ttl drop | fwd\n" +" stats none | pkts]\n" +" [stats pkts | bytes | both]\n" +" [time]\n"; + static void cmd_table_action_profile(char **tokens, uint32_t n_tokens, @@ -1207,12 +1297,12 @@ cmd_table_action_profile(char **tokens, } } -/** - * pipeline <pipeline_name> - * period <timer_period_ms> - * offset_port_id <offset_port_id> - * cpu <cpu_id> - */ +static const char cmd_pipeline_help[] = +"pipeline <pipeline_name>\n" +" period <timer_period_ms>\n" +" offset_port_id <offset_port_id>\n" +" cpu <cpu_id>\n"; + static void cmd_pipeline(char **tokens, uint32_t n_tokens, @@ -1267,18 +1357,18 @@ cmd_pipeline(char **tokens, } } -/** - * pipeline <pipeline_name> port in - * bsz <burst_size> - * link <link_name> rxq <queue_id> - * | swq <swq_name> - * | tmgr <tmgr_name> - * | tap <tap_name> mempool <mempool_name> mtu <mtu> - * | kni <kni_name> - * | source mempool <mempool_name> file <file_name> bpp <n_bytes_per_pkt> - * [action <port_in_action_profile_name>] - * [disabled] - */ +static const char cmd_pipeline_port_in_help[] = +"pipeline <pipeline_name> port in\n" +" bsz <burst_size>\n" +" link <link_name> rxq <queue_id>\n" +" | swq <swq_name>\n" +" | tmgr <tmgr_name>\n" +" | tap <tap_name> mempool <mempool_name> mtu <mtu>\n" +" | kni <kni_name>\n" +" | source mempool <mempool_name> file <file_name> bpp <n_bytes_per_pkt>\n" +" [action <port_in_action_profile_name>]\n" +" [disabled]\n"; + static void cmd_pipeline_port_in(char **tokens, uint32_t n_tokens, @@ -1486,16 +1576,16 @@ cmd_pipeline_port_in(char **tokens, } } -/** - * pipeline <pipeline_name> port out - * bsz <burst_size> - * link <link_name> txq <txq_id> - * | swq <swq_name> - * | tmgr <tmgr_name> - * | tap <tap_name> - * | kni <kni_name> - * | sink [file <file_name> pkts <max_n_pkts>] - */ +static const char cmd_pipeline_port_out_help[] = +"pipeline <pipeline_name> port out\n" +" bsz <burst_size>\n" +" link <link_name> txq <txq_id>\n" +" | swq <swq_name>\n" +" | tmgr <tmgr_name>\n" +" | tap <tap_name>\n" +" | kni <kni_name>\n" +" | sink [file <file_name> pkts <max_n_pkts>]\n"; + static void cmd_pipeline_port_out(char **tokens, uint32_t n_tokens, @@ -1640,30 +1730,30 @@ cmd_pipeline_port_out(char **tokens, } } -/** - * pipeline <pipeline_name> table - * match - * acl - * ipv4 | ipv6 - * offset <ip_header_offset> - * size <n_rules> - * | array - * offset <key_offset> - * size <n_keys> - * | hash - * ext | lru - * key <key_size> - * mask <key_mask> - * offset <key_offset> - * buckets <n_buckets> - * size <n_keys> - * | lpm - * ipv4 | ipv6 - * offset <ip_header_offset> - * size <n_rules> - * | stub - * [action <table_action_profile_name>] - */ +static const char cmd_pipeline_table_help[] = +"pipeline <pipeline_name> table\n" +" match\n" +" acl\n" +" ipv4 | ipv6\n" +" offset <ip_header_offset>\n" +" size <n_rules>\n" +" | array\n" +" offset <key_offset>\n" +" size <n_keys>\n" +" | hash\n" +" ext | lru\n" +" key <key_size>\n" +" mask <key_mask>\n" +" offset <key_offset>\n" +" buckets <n_buckets>\n" +" size <n_keys>\n" +" | lpm\n" +" ipv4 | ipv6\n" +" offset <ip_header_offset>\n" +" size <n_rules>\n" +" | stub\n" +" [action <table_action_profile_name>]\n"; + static void cmd_pipeline_table(char **tokens, uint32_t n_tokens, @@ -1925,9 +2015,9 @@ cmd_pipeline_table(char **tokens, } } -/** - * pipeline <pipeline_name> port in <port_id> table <table_id> - */ +static const char cmd_pipeline_port_in_table_help[] = +"pipeline <pipeline_name> port in <port_id> table <table_id>\n"; + static void cmd_pipeline_port_in_table(char **tokens, uint32_t n_tokens, @@ -1979,9 +2069,9 @@ cmd_pipeline_port_in_table(char **tokens, } } -/** - * pipeline <pipeline_name> port in <port_id> stats read [clear] - */ + +static const char cmd_pipeline_port_in_stats_help[] = +"pipeline <pipeline_name> port in <port_id> stats read [clear]\n"; #define MSG_PIPELINE_PORT_IN_STATS \ "Pkts in: %" PRIu64 "\n" \ @@ -2056,9 +2146,10 @@ cmd_pipeline_port_in_stats(char **tokens, stats.stats.n_pkts_drop); } -/** - * pipeline <pipeline_name> port in <port_id> enable - */ + +static const char cmd_pipeline_port_in_enable_help[] = +"pipeline <pipeline_name> port in <port_id> enable\n"; + static void cmd_pipeline_port_in_enable(char **tokens, uint32_t n_tokens, @@ -2103,9 +2194,10 @@ cmd_pipeline_port_in_enable(char **tokens, } } -/** - * pipeline <pipeline_name> port in <port_id> disable - */ + +static const char cmd_pipeline_port_in_disable_help[] = +"pipeline <pipeline_name> port in <port_id> disable\n"; + static void cmd_pipeline_port_in_disable(char **tokens, uint32_t n_tokens, @@ -2150,9 +2242,10 @@ cmd_pipeline_port_in_disable(char **tokens, } } -/** - * pipeline <pipeline_name> port out <port_id> stats read [clear] - */ + +static const char cmd_pipeline_port_out_stats_help[] = +"pipeline <pipeline_name> port out <port_id> stats read [clear]\n"; + #define MSG_PIPELINE_PORT_OUT_STATS \ "Pkts in: %" PRIu64 "\n" \ "Pkts dropped by AH: %" PRIu64 "\n" \ @@ -2226,9 +2319,10 @@ cmd_pipeline_port_out_stats(char **tokens, stats.stats.n_pkts_drop); } -/** - * pipeline <pipeline_name> table <table_id> stats read [clear] - */ + +static const char cmd_pipeline_table_stats_help[] = +"pipeline <pipeline_name> table <table_id> stats read [clear]\n"; + #define MSG_PIPELINE_TABLE_STATS \ "Pkts in: %" PRIu64 "\n" \ "Pkts in with lookup miss: %" PRIu64 "\n" \ @@ -3406,11 +3500,12 @@ parse_table_action(char **tokens, return n_tokens0 - n_tokens; } -/** - * pipeline <pipeline_name> table <table_id> rule add - * match <match> - * action <table_action> - */ + +static const char cmd_pipeline_table_rule_add_help[] = +"pipeline <pipeline_name> table <table_id> rule add\n" +" match <match>\n" +" action <table_action>\n"; + static void cmd_pipeline_table_rule_add(char **tokens, uint32_t n_tokens, @@ -3486,17 +3581,18 @@ cmd_pipeline_table_rule_add(char **tokens, } } -/** - * pipeline <pipeline_name> table <table_id> rule add - * match - * default - * action - * fwd - * drop - * | port <port_id> - * | meta - * | table <table_id> - */ + +static const char cmd_pipeline_table_rule_add_default_help[] = +"pipeline <pipeline_name> table <table_id> rule add\n" +" match\n" +" default\n" +" action\n" +" fwd\n" +" drop\n" +" | port <port_id>\n" +" | meta\n" +" | table <table_id>\n"; + static void cmd_pipeline_table_rule_add_default(char **tokens, uint32_t n_tokens, @@ -3618,12 +3714,13 @@ cmd_pipeline_table_rule_add_default(char **tokens, } } -/** - * pipeline <pipeline_name> table <table_id> rule add bulk <file_name> <n_rules> - * - * File <file_name>: - * - line format: match <match> action <action> - */ + +static const char cmd_pipeline_table_rule_add_bulk_help[] = +"pipeline <pipeline_name> table <table_id> rule add bulk <file_name> <n_rules>\n" +"\n" +" File <file_name>:\n" +" - line format: match <match> action <action>\n"; + static int cli_rule_file_process(const char *file_name, size_t line_len_max, @@ -3745,10 +3842,11 @@ cmd_pipeline_table_rule_add_bulk(char **tokens, free(match); } -/** - * pipeline <pipeline_name> table <table_id> rule delete - * match <match> - */ + +static const char cmd_pipeline_table_rule_delete_help[] = +"pipeline <pipeline_name> table <table_id> rule delete\n" +" match <match>\n"; + static void cmd_pipeline_table_rule_delete(char **tokens, uint32_t n_tokens, @@ -3813,11 +3911,12 @@ cmd_pipeline_table_rule_delete(char **tokens, } } -/** - * pipeline <pipeline_name> table <table_id> rule delete - * match - * default - */ + +static const char cmd_pipeline_table_rule_delete_default_help[] = +"pipeline <pipeline_name> table <table_id> rule delete\n" +" match\n" +" default\n"; + static void cmd_pipeline_table_rule_delete_default(char **tokens, uint32_t n_tokens, @@ -3873,9 +3972,10 @@ cmd_pipeline_table_rule_delete_default(char **tokens, } } -/** - * pipeline <pipeline_name> table <table_id> rule read stats [clear] - */ + +static const char cmd_pipeline_table_rule_stats_read_help[] = +"pipeline <pipeline_name> table <table_id> rule read stats [clear]\n"; + static void cmd_pipeline_table_rule_stats_read(char **tokens, uint32_t n_tokens __rte_unused, @@ -3885,11 +3985,12 @@ cmd_pipeline_table_rule_stats_read(char **tokens, snprintf(out, out_size, MSG_CMD_UNIMPLEM, tokens[0]); } -/** - * pipeline <pipeline_name> table <table_id> meter profile <meter_profile_id> - * add srtcm cir <cir> cbs <cbs> ebs <ebs> - * | trtcm cir <cir> pir <pir> cbs <cbs> pbs <pbs> - */ + +static const char cmd_pipeline_table_meter_profile_add_help[] = +"pipeline <pipeline_name> table <table_id> meter profile <meter_profile_id>\n" +" add srtcm cir <cir> cbs <cbs> ebs <ebs>\n" +" | trtcm cir <cir> pir <pir> cbs <cbs> pbs <pbs>\n"; + static void cmd_pipeline_table_meter_profile_add(char **tokens, uint32_t n_tokens, @@ -4037,10 +4138,11 @@ cmd_pipeline_table_meter_profile_add(char **tokens, } } -/** - * pipeline <pipeline_name> table <table_id> - * meter profile <meter_profile_id> delete - */ + +static const char cmd_pipeline_table_meter_profile_delete_help[] = +"pipeline <pipeline_name> table <table_id>\n" +" meter profile <meter_profile_id> delete\n"; + static void cmd_pipeline_table_meter_profile_delete(char **tokens, uint32_t n_tokens, @@ -4097,9 +4199,10 @@ cmd_pipeline_table_meter_profile_delete(char **tokens, } } -/** - * pipeline <pipeline_name> table <table_id> rule read meter [clear] - */ + +static const char cmd_pipeline_table_rule_meter_read_help[] = +"pipeline <pipeline_name> table <table_id> rule read meter [clear]\n"; + static void cmd_pipeline_table_rule_meter_read(char **tokens, uint32_t n_tokens __rte_unused, @@ -4109,13 +4212,14 @@ cmd_pipeline_table_rule_meter_read(char **tokens, snprintf(out, out_size, MSG_CMD_UNIMPLEM, tokens[0]); } -/** - * pipeline <pipeline_name> table <table_id> dscp <file_name> - * - * File <file_name>: - * - exactly 64 lines - * - line format: <tc_id> <tc_queue_id> <color>, with <color> as: g | y | r - */ + +static const char cmd_pipeline_table_dscp_help[] = +"pipeline <pipeline_name> table <table_id> dscp <file_name>\n" +"\n" +" File <file_name>:\n" +" - exactly 64 lines\n" +" - line format: <tc_id> <tc_queue_id> <color>, with <color> as: g | y | r\n"; + static int load_dscp_table(struct rte_table_action_dscp_table *dscp_table, const char *file_name, @@ -4258,9 +4362,10 @@ cmd_pipeline_table_dscp(char **tokens, } } -/** - * pipeline <pipeline_name> table <table_id> rule read ttl [clear] - */ + +static const char cmd_pipeline_table_rule_ttl_read_help[] = +"pipeline <pipeline_name> table <table_id> rule read ttl [clear]\n"; + static void cmd_pipeline_table_rule_ttl_read(char **tokens, uint32_t n_tokens __rte_unused, @@ -4270,9 +4375,10 @@ cmd_pipeline_table_rule_ttl_read(char **tokens, snprintf(out, out_size, MSG_CMD_UNIMPLEM, tokens[0]); } -/** - * thread <thread_id> pipeline <pipeline_name> enable - */ + +static const char cmd_thread_pipeline_enable_help[] = +"thread <thread_id> pipeline <pipeline_name> enable\n"; + static void cmd_thread_pipeline_enable(char **tokens, uint32_t n_tokens, @@ -4312,9 +4418,10 @@ cmd_thread_pipeline_enable(char **tokens, } } -/** - * thread <thread_id> pipeline <pipeline_name> disable - */ + +static const char cmd_thread_pipeline_disable_help[] = +"thread <thread_id> pipeline <pipeline_name> disable\n"; + static void cmd_thread_pipeline_disable(char **tokens, uint32_t n_tokens, @@ -4355,6 +4462,316 @@ cmd_thread_pipeline_disable(char **tokens, } } +static void +cmd_help(char **tokens, uint32_t n_tokens, char *out, size_t out_size) +{ + tokens++; + n_tokens--; + + if (n_tokens == 0) { + snprintf(out, out_size, + "Type 'help <command>' for details on each command.\n\n" + "List of commands:\n" + "\tmempool\n" + "\tlink\n" + "\tswq\n" + "\ttmgr subport profile\n" + "\ttmgr pipe profile\n" + "\ttmgr\n" + "\ttmgr subport\n" + "\ttmgr subport pipe\n" + "\ttap\n" + "\tkni\n" + "\tport in action profile\n" + "\ttable action profile\n" + "\tpipeline\n" + "\tpipeline port in\n" + "\tpipeline port out\n" + "\tpipeline table\n" + "\tpipeline port in table\n" + "\tpipeline port in stats\n" + "\tpipeline port in enable\n" + "\tpipeline port in disable\n" + "\tpipeline port out stats\n" + "\tpipeline table stats\n" + "\tpipeline table rule add\n" + "\tpipeline table rule add default\n" + "\tpipeline table rule add bulk\n" + "\tpipeline table rule delete\n" + "\tpipeline table rule delete default\n" + "\tpipeline table rule stats read\n" + "\tpipeline table meter profile add\n" + "\tpipeline table meter profile delete\n" + "\tpipeline table rule meter read\n" + "\tpipeline table dscp\n" + "\tpipeline table rule ttl read\n" + "\tthread pipeline enable\n" + "\tthread pipeline disable\n\n"); + return; + } + + if (strcmp(tokens[0], "mempool") == 0) { + snprintf(out, out_size, "\n%s\n", cmd_mempool_help); + return; + } + + if (strcmp(tokens[0], "link") == 0) { + snprintf(out, out_size, "\n%s\n", cmd_link_help); + return; + } + + if (strcmp(tokens[0], "swq") == 0) { + snprintf(out, out_size, "\n%s\n", cmd_swq_help); + return; + } + + if (strcmp(tokens[0], "tmgr") == 0) { + if (n_tokens == 1) { + snprintf(out, out_size, "\n%s\n", cmd_tmgr_help); + return; + } + + if ((n_tokens == 2) && + (strcmp(tokens[1], "subport")) == 0) { + snprintf(out, out_size, "\n%s\n", cmd_tmgr_subport_help); + return; + } + + if ((n_tokens == 3) && + (strcmp(tokens[1], "subport") == 0) && + (strcmp(tokens[2], "profile") == 0)) { + snprintf(out, out_size, "\n%s\n", + cmd_tmgr_subport_profile_help); + return; + } + + if ((n_tokens == 3) && + (strcmp(tokens[1], "subport") == 0) && + (strcmp(tokens[2], "pipe") == 0)) { + snprintf(out, out_size, "\n%s\n", cmd_tmgr_subport_pipe_help); + return; + } + + if ((n_tokens == 3) && + (strcmp(tokens[1], "pipe") == 0) && + (strcmp(tokens[2], "profile") == 0)) { + snprintf(out, out_size, "\n%s\n", cmd_tmgr_pipe_profile_help); + return; + } + } + + if (strcmp(tokens[0], "tap") == 0) { + snprintf(out, out_size, "\n%s\n", cmd_tap_help); + return; + } + + if (strcmp(tokens[0], "kni") == 0) { + snprintf(out, out_size, "\n%s\n", cmd_kni_help); + return; + } + + if ((n_tokens == 4) && + (strcmp(tokens[0], "port") == 0) && + (strcmp(tokens[1], "in") == 0) && + (strcmp(tokens[2], "action") == 0) && + (strcmp(tokens[3], "profile") == 0)) { + snprintf(out, out_size, "\n%s\n", cmd_port_in_action_profile_help); + return; + } + + if ((n_tokens == 3) && + (strcmp(tokens[0], "table") == 0) && + (strcmp(tokens[1], "action") == 0) && + (strcmp(tokens[2], "profile") == 0)) { + snprintf(out, out_size, "\n%s\n", cmd_table_action_profile_help); + return; + } + + if ((strcmp(tokens[0], "pipeline") == 0) && (n_tokens == 1)) { + snprintf(out, out_size, "\n%s\n", cmd_pipeline_help); + return; + } + + if ((strcmp(tokens[0], "pipeline") == 0) && + (strcmp(tokens[1], "port") == 0)) { + if ((n_tokens == 3) && (strcmp(tokens[2], "in")) == 0) { + snprintf(out, out_size, "\n%s\n", cmd_pipeline_port_in_help); + return; + } + + if ((n_tokens == 3) && (strcmp(tokens[2], "out")) == 0) { + snprintf(out, out_size, "\n%s\n", cmd_pipeline_port_out_help); + return; + } + + if ((n_tokens == 4) && + (strcmp(tokens[2], "in") == 0) && + (strcmp(tokens[3], "table") == 0)) { + snprintf(out, out_size, "\n%s\n", + cmd_pipeline_port_in_table_help); + return; + } + + if ((n_tokens == 4) && + (strcmp(tokens[2], "in") == 0) && + (strcmp(tokens[3], "stats") == 0)) { + snprintf(out, out_size, "\n%s\n", + cmd_pipeline_port_in_stats_help); + return; + } + + if ((n_tokens == 4) && + (strcmp(tokens[2], "in") == 0) && + (strcmp(tokens[3], "enable") == 0)) { + snprintf(out, out_size, "\n%s\n", + cmd_pipeline_port_in_enable_help); + return; + } + + if ((n_tokens == 4) && + (strcmp(tokens[2], "in") == 0) && + (strcmp(tokens[3], "disable") == 0)) { + snprintf(out, out_size, "\n%s\n", + cmd_pipeline_port_in_disable_help); + return; + } + + if ((n_tokens == 4) && + (strcmp(tokens[2], "out") == 0) && + (strcmp(tokens[3], "stats") == 0)) { + snprintf(out, out_size, "\n%s\n", + cmd_pipeline_port_out_stats_help); + return; + } + } + + if ((strcmp(tokens[0], "pipeline") == 0) && + (strcmp(tokens[1], "table") == 0)) { + if (n_tokens == 2) { + snprintf(out, out_size, "\n%s\n", cmd_pipeline_table_help); + return; + } + + if ((n_tokens == 3) && strcmp(tokens[2], "stats") == 0) { + snprintf(out, out_size, "\n%s\n", + cmd_pipeline_table_stats_help); + return; + } + + if ((n_tokens == 3) && strcmp(tokens[2], "dscp") == 0) { + snprintf(out, out_size, "\n%s\n", + cmd_pipeline_table_dscp_help); + return; + } + + if ((n_tokens == 4) && + (strcmp(tokens[2], "rule") == 0) && + (strcmp(tokens[3], "add") == 0)) { + snprintf(out, out_size, "\n%s\n", + cmd_pipeline_table_rule_add_help); + return; + } + + if ((n_tokens == 5) && + (strcmp(tokens[2], "rule") == 0) && + (strcmp(tokens[3], "add") == 0) && + (strcmp(tokens[4], "default") == 0)) { + snprintf(out, out_size, "\n%s\n", + cmd_pipeline_table_rule_add_default_help); + return; + } + + if ((n_tokens == 5) && + (strcmp(tokens[2], "rule") == 0) && + (strcmp(tokens[3], "add") == 0) && + (strcmp(tokens[4], "bulk") == 0)) { + snprintf(out, out_size, "\n%s\n", + cmd_pipeline_table_rule_add_bulk_help); + return; + } + + if ((n_tokens == 4) && + (strcmp(tokens[2], "rule") == 0) && + (strcmp(tokens[3], "delete") == 0)) { + snprintf(out, out_size, "\n%s\n", + cmd_pipeline_table_rule_delete_help); + return; + } + + if ((n_tokens == 5) && + (strcmp(tokens[2], "rule") == 0) && + (strcmp(tokens[3], "delete") == 0) && + (strcmp(tokens[4], "default") == 0)) { + snprintf(out, out_size, "\n%s\n", + cmd_pipeline_table_rule_delete_default_help); + return; + } + + if ((n_tokens == 5) && + (strcmp(tokens[2], "rule") == 0) && + (strcmp(tokens[3], "stats") == 0) && + (strcmp(tokens[4], "read") == 0)) { + snprintf(out, out_size, "\n%s\n", + cmd_pipeline_table_rule_stats_read_help); + return; + } + + if ((n_tokens == 5) && + (strcmp(tokens[2], "meter") == 0) && + (strcmp(tokens[3], "profile") == 0) && + (strcmp(tokens[4], "add") == 0)) { + snprintf(out, out_size, "\n%s\n", + cmd_pipeline_table_meter_profile_add_help); + return; + } + + if ((n_tokens == 5) && + (strcmp(tokens[2], "meter") == 0) && + (strcmp(tokens[3], "profile") == 0) && + (strcmp(tokens[4], "delete") == 0)) { + snprintf(out, out_size, "\n%s\n", + cmd_pipeline_table_meter_profile_delete_help); + return; + } + + if ((n_tokens == 5) && + (strcmp(tokens[2], "rule") == 0) && + (strcmp(tokens[3], "meter") == 0) && + (strcmp(tokens[4], "read") == 0)) { + snprintf(out, out_size, "\n%s\n", + cmd_pipeline_table_rule_meter_read_help); + return; + } + + if ((n_tokens == 5) && + (strcmp(tokens[2], "rule") == 0) && + (strcmp(tokens[3], "ttl") == 0) && + (strcmp(tokens[4], "read") == 0)) { + snprintf(out, out_size, "\n%s\n", + cmd_pipeline_table_rule_ttl_read_help); + return; + } + } + + if ((n_tokens == 3) && + (strcmp(tokens[0], "thread") == 0) && + (strcmp(tokens[1], "pipeline") == 0)) { + if (strcmp(tokens[2], "enable") == 0) { + snprintf(out, out_size, "\n%s\n", + cmd_thread_pipeline_enable_help); + return; + } + + if (strcmp(tokens[2], "disable") == 0) { + snprintf(out, out_size, "\n%s\n", + cmd_thread_pipeline_disable_help); + return; + } + } + + snprintf(out, out_size, "Invalid command\n"); +} + void cli_process(char *in, char *out, size_t out_size) { @@ -4374,12 +4791,22 @@ cli_process(char *in, char *out, size_t out_size) if (n_tokens == 0) return; + if (strcmp(tokens[0], "help") == 0) { + cmd_help(tokens, n_tokens, out, out_size); + return; + } + if (strcmp(tokens[0], "mempool") == 0) { cmd_mempool(tokens, n_tokens, out, out_size); return; } if (strcmp(tokens[0], "link") == 0) { + if (strcmp(tokens[1], "show") == 0) { + cmd_link_show(tokens, n_tokens, out, out_size); + return; + } + cmd_link(tokens, n_tokens, out, out_size); return; } diff --git a/examples/ip_pipeline/examples/rss.cli b/examples/ip_pipeline/examples/rss.cli new file mode 100644 index 00000000..29c0a913 --- /dev/null +++ b/examples/ip_pipeline/examples/rss.cli @@ -0,0 +1,112 @@ +; SPDX-License-Identifier: BSD-3-Clause +; Copyright(c) 2010-2018 Intel Corporation + +; This setup demonstrates the usage of NIC Receive Side Scaling (RSS) feature. +; Each NIC splits the input traffic into 4 RX queues, with each of its RX queues +; being handled by a different pipeline: +; +; +-----------+ +----------+ +; +--------------------------->| | | | +; | +------------------->| PIPELINE0 +--->| LINK 0 |---> +; | | +------------->| (CORE A) | | TX | +; | | | +------->| | | | +; | | | | +-----------+ +----------+ +; +----------+ | | | | +; | |-------+ | | | +;--->| LINK 0 |-----------+ | | | +; | RX |---------+ | | | | +; | |-------+ | | | | | +; +----------+ | | | | | | +-----------+ +----------+ +; | | +---|-----|-----|------->| | | | +; +----------+ | | | +---|-----|------->| PIPELINE1 +--->| LINK 1 |---> +; | |-------|-|-----+ | | +---|------->| (CORE B) | | TX | +;--->| LINK 1 |-------|-|-------+ | | | +----->| | | | +; | RX |-------|-|-------+ | | | | +-----------+ +----------+ +; | |-------|-|-----+ | | | | | +; +----------+ | | | | | | | | +; | | | | | | | | +; +----------+ | | | | | | | | +; | |-------|-|-----|-|---+ | | | +;--->| LINK 2 |-------|-|-----|-|-----+ | | +-----------+ +----------+ +; | RX |-----+ | +-----|-|---------|-|----->| | | | +; | |---+ | | | +---------|-|----->| PIPELINE2 +--->| LINK 2 |---> +; +----------+ | +-|-------|-----------|-|----->| (CORE C) | | TX | +; | | | | | +--->| | | | +; +----------+ | | | | | | +-----------+ +----------+ +; | |---|---|-------|-----------+ | | +;--->| LINK 3 |---|---|-------|-------------+ | +; | RX |---|---|-------|---------------+ +; | |---|---|-------|-----------+ +; +----------+ | | | | +; | | | | +-----------+ +----------+ +; | +-------|-----------|------->| | | | +; | +-----------|------->| PIPELINE3 +--->| LINK 3 |---> +; +-----------------------|------->| (CORE D) | | TX | +; +------->| | | | +; +-----------+ +----------+ +; +; + +mempool MEMPOOL0 buffer 2304 pool 32K cache 256 cpu 0 + +link LINK0 dev 0000:02:00.0 rxq 4 128 MEMPOOL0 txq 1 512 promiscuous on rss 0 1 2 3 +link LINK1 dev 0000:02:00.1 rxq 4 128 MEMPOOL0 txq 1 512 promiscuous on rss 0 1 2 3 +link LINK2 dev 0000:06:00.0 rxq 4 128 MEMPOOL0 txq 1 512 promiscuous on rss 0 1 2 3 +link LINK3 dev 0000:06:00.1 rxq 4 128 MEMPOOL0 txq 1 512 promiscuous on rss 0 1 2 3 + +pipeline PIPELINE0 period 10 offset_port_id 0 cpu 0 +pipeline PIPELINE0 port in bsz 32 link LINK0 rxq 0 +pipeline PIPELINE0 port in bsz 32 link LINK1 rxq 0 +pipeline PIPELINE0 port in bsz 32 link LINK2 rxq 0 +pipeline PIPELINE0 port in bsz 32 link LINK3 rxq 0 +pipeline PIPELINE0 port out bsz 32 link LINK0 txq 0 +pipeline PIPELINE0 table match stub +pipeline PIPELINE0 port in 0 table 0 +pipeline PIPELINE0 port in 1 table 0 +pipeline PIPELINE0 port in 2 table 0 +pipeline PIPELINE0 port in 3 table 0 +pipeline PIPELINE0 table 0 rule add match default action fwd port 0 + +pipeline PIPELINE1 period 10 offset_port_id 0 cpu 0 +pipeline PIPELINE1 port in bsz 32 link LINK0 rxq 1 +pipeline PIPELINE1 port in bsz 32 link LINK1 rxq 1 +pipeline PIPELINE1 port in bsz 32 link LINK2 rxq 1 +pipeline PIPELINE1 port in bsz 32 link LINK3 rxq 1 +pipeline PIPELINE1 port out bsz 32 link LINK1 txq 0 +pipeline PIPELINE1 table match stub +pipeline PIPELINE1 port in 0 table 0 +pipeline PIPELINE1 port in 1 table 0 +pipeline PIPELINE1 port in 2 table 0 +pipeline PIPELINE1 port in 3 table 0 +pipeline PIPELINE1 table 0 rule add match default action fwd port 0 + +pipeline PIPELINE2 period 10 offset_port_id 0 cpu 0 +pipeline PIPELINE2 port in bsz 32 link LINK0 rxq 2 +pipeline PIPELINE2 port in bsz 32 link LINK1 rxq 2 +pipeline PIPELINE2 port in bsz 32 link LINK2 rxq 2 +pipeline PIPELINE2 port in bsz 32 link LINK3 rxq 2 +pipeline PIPELINE2 port out bsz 32 link LINK2 txq 0 +pipeline PIPELINE2 table match stub +pipeline PIPELINE2 port in 0 table 0 +pipeline PIPELINE2 port in 1 table 0 +pipeline PIPELINE2 port in 2 table 0 +pipeline PIPELINE2 port in 3 table 0 +pipeline PIPELINE2 table 0 rule add match default action fwd port 0 + +pipeline PIPELINE3 period 10 offset_port_id 0 cpu 0 +pipeline PIPELINE3 port in bsz 32 link LINK0 rxq 3 +pipeline PIPELINE3 port in bsz 32 link LINK1 rxq 3 +pipeline PIPELINE3 port in bsz 32 link LINK2 rxq 3 +pipeline PIPELINE3 port in bsz 32 link LINK3 rxq 3 +pipeline PIPELINE3 port out bsz 32 link LINK3 txq 0 +pipeline PIPELINE3 table match stub +pipeline PIPELINE3 port in 0 table 0 +pipeline PIPELINE3 port in 1 table 0 +pipeline PIPELINE3 port in 2 table 0 +pipeline PIPELINE3 port in 3 table 0 +pipeline PIPELINE3 table 0 rule add match default action fwd port 0 + +thread 1 pipeline PIPELINE0 enable +thread 2 pipeline PIPELINE1 enable +thread 3 pipeline PIPELINE2 enable +thread 4 pipeline PIPELINE3 enable diff --git a/examples/ip_pipeline/link.c b/examples/ip_pipeline/link.c index b8a431f3..392a890f 100644 --- a/examples/ip_pipeline/link.c +++ b/examples/ip_pipeline/link.c @@ -36,22 +36,19 @@ link_find(const char *name) return NULL; } +struct link * +link_next(struct link *link) +{ + return (link == NULL) ? TAILQ_FIRST(&link_list) : TAILQ_NEXT(link, node); +} + static struct rte_eth_conf port_conf_default = { .link_speeds = 0, .rxmode = { .mq_mode = ETH_MQ_RX_NONE, - - .header_split = 0, /* Header split */ - .hw_ip_checksum = 0, /* IP checksum offload */ - .hw_vlan_filter = 0, /* VLAN filtering */ - .hw_vlan_strip = 0, /* VLAN strip */ - .hw_vlan_extend = 0, /* Extended VLAN */ - .jumbo_frame = 0, /* Jumbo frame support */ - .hw_strip_crc = 1, /* CRC strip by HW */ - .enable_scatter = 0, /* Scattered packets RX handler */ - .max_rx_pkt_len = 9000, /* Jumbo frame max packet len */ .split_hdr_size = 0, /* Header split buffer size */ + .offloads = DEV_RX_OFFLOAD_CRC_STRIP, }, .rx_adv_conf = { .rss_conf = { @@ -162,7 +159,8 @@ link_create(const char *name, struct link_params *params) if (rss) { port_conf.rxmode.mq_mode = ETH_MQ_RX_RSS; port_conf.rx_adv_conf.rss_conf.rss_hf = - ETH_RSS_IPV4 | ETH_RSS_IPV6; + (ETH_RSS_IP | ETH_RSS_TCP | ETH_RSS_UDP) & + port_info.flow_type_rss_offloads; } cpu_id = (uint32_t) rte_eth_dev_socket_id(port_id); diff --git a/examples/ip_pipeline/link.h b/examples/ip_pipeline/link.h index 37d3dc43..34ff1149 100644 --- a/examples/ip_pipeline/link.h +++ b/examples/ip_pipeline/link.h @@ -30,6 +30,9 @@ link_init(void); struct link * link_find(const char *name); +struct link * +link_next(struct link *link); + struct link_params_rss { uint32_t queue_id[LINK_RXQ_RSS_MAX]; uint32_t n_queues; diff --git a/examples/ip_pipeline/thread.c b/examples/ip_pipeline/thread.c index fa85cf63..7fc03332 100644 --- a/examples/ip_pipeline/thread.c +++ b/examples/ip_pipeline/thread.c @@ -155,6 +155,29 @@ thread_init(void) return 0; } +static inline int +thread_is_running(uint32_t thread_id) +{ + enum rte_lcore_state_t thread_state; + + thread_state = rte_eal_get_lcore_state(thread_id); + return (thread_state == RUNNING) ? 1 : 0; +} + +/** + * Pipeline is running when: + * (A) Pipeline is mapped to a data plane thread AND + * (B) Its data plane thread is in RUNNING state. + */ +static inline int +pipeline_is_running(struct pipeline *p) +{ + if (p->enabled == 0) + return 0; + + return thread_is_running(p->thread_id); +} + /** * Master thread & data plane threads: message passing */ @@ -254,6 +277,36 @@ thread_pipeline_enable(uint32_t thread_id, p->enabled) return -1; + if (!thread_is_running(thread_id)) { + struct thread_data *td = &thread_data[thread_id]; + struct pipeline_data *tdp = &td->pipeline_data[td->n_pipelines]; + + if (td->n_pipelines >= THREAD_PIPELINES_MAX) + return -1; + + /* Data plane thread */ + td->p[td->n_pipelines] = p->p; + + tdp->p = p->p; + for (i = 0; i < p->n_tables; i++) + tdp->table_data[i].a = p->table[i].a; + + tdp->n_tables = p->n_tables; + + tdp->msgq_req = p->msgq_req; + tdp->msgq_rsp = p->msgq_rsp; + tdp->timer_period = (rte_get_tsc_hz() * p->timer_period_ms) / 1000; + tdp->time_next = rte_get_tsc_cycles() + tdp->timer_period; + + td->n_pipelines++; + + /* Pipeline */ + p->thread_id = thread_id; + p->enabled = 1; + + return 0; + } + /* Allocate request */ req = thread_msg_alloc(); if (req == NULL) @@ -316,6 +369,38 @@ thread_pipeline_disable(uint32_t thread_id, if (p->thread_id != thread_id) return -1; + if (!thread_is_running(thread_id)) { + struct thread_data *td = &thread_data[thread_id]; + uint32_t i; + + for (i = 0; i < td->n_pipelines; i++) { + struct pipeline_data *tdp = &td->pipeline_data[i]; + + if (tdp->p != p->p) + continue; + + /* Data plane thread */ + if (i < td->n_pipelines - 1) { + struct rte_pipeline *pipeline_last = + td->p[td->n_pipelines - 1]; + struct pipeline_data *tdp_last = + &td->pipeline_data[td->n_pipelines - 1]; + + td->p[i] = pipeline_last; + memcpy(tdp, tdp_last, sizeof(*tdp)); + } + + td->n_pipelines--; + + /* Pipeline */ + p->enabled = 0; + + break; + } + + return 0; + } + /* Allocate request */ req = thread_msg_alloc(); if (req == NULL) @@ -698,10 +783,18 @@ pipeline_port_in_stats_read(const char *pipeline_name, p = pipeline_find(pipeline_name); if ((p == NULL) || - (p->enabled == 0) || (port_id >= p->n_ports_in)) return -1; + if (!pipeline_is_running(p)) { + status = rte_pipeline_port_in_stats_read(p->p, + port_id, + stats, + clear); + + return status; + } + /* Allocate request */ req = pipeline_msg_alloc(); if (req == NULL) @@ -743,10 +836,14 @@ pipeline_port_in_enable(const char *pipeline_name, p = pipeline_find(pipeline_name); if ((p == NULL) || - (p->enabled == 0) || (port_id >= p->n_ports_in)) return -1; + if (!pipeline_is_running(p)) { + status = rte_pipeline_port_in_enable(p->p, port_id); + return status; + } + /* Allocate request */ req = pipeline_msg_alloc(); if (req == NULL) @@ -785,10 +882,14 @@ pipeline_port_in_disable(const char *pipeline_name, p = pipeline_find(pipeline_name); if ((p == NULL) || - (p->enabled == 0) || (port_id >= p->n_ports_in)) return -1; + if (!pipeline_is_running(p)) { + status = rte_pipeline_port_in_disable(p->p, port_id); + return status; + } + /* Allocate request */ req = pipeline_msg_alloc(); if (req == NULL) @@ -830,10 +931,18 @@ pipeline_port_out_stats_read(const char *pipeline_name, p = pipeline_find(pipeline_name); if ((p == NULL) || - (p->enabled == 0) || (port_id >= p->n_ports_out)) return -1; + if (!pipeline_is_running(p)) { + status = rte_pipeline_port_out_stats_read(p->p, + port_id, + stats, + clear); + + return status; + } + /* Allocate request */ req = pipeline_msg_alloc(); if (req == NULL) @@ -878,10 +987,18 @@ pipeline_table_stats_read(const char *pipeline_name, p = pipeline_find(pipeline_name); if ((p == NULL) || - (p->enabled == 0) || (table_id >= p->n_tables)) return -1; + if (!pipeline_is_running(p)) { + status = rte_pipeline_table_stats_read(p->p, + table_id, + stats, + clear); + + return status; + } + /* Allocate request */ req = pipeline_msg_alloc(); if (req == NULL) @@ -1070,6 +1187,25 @@ action_default_check(struct table_rule_action *action, return 0; } +union table_rule_match_low_level { + struct rte_table_acl_rule_add_params acl_add; + struct rte_table_acl_rule_delete_params acl_delete; + struct rte_table_array_key array; + uint8_t hash[TABLE_RULE_MATCH_SIZE_MAX]; + struct rte_table_lpm_key lpm_ipv4; + struct rte_table_lpm_ipv6_key lpm_ipv6; +}; + +static int +match_convert(struct table_rule_match *mh, + union table_rule_match_low_level *ml, + int add); + +static int +action_convert(struct rte_table_action *a, + struct table_rule_action *action, + struct rte_pipeline_table_entry *data); + int pipeline_table_rule_add(const char *pipeline_name, uint32_t table_id, @@ -1091,12 +1227,56 @@ pipeline_table_rule_add(const char *pipeline_name, p = pipeline_find(pipeline_name); if ((p == NULL) || - (p->enabled == 0) || (table_id >= p->n_tables) || match_check(match, p, table_id) || action_check(action, p, table_id)) return -1; + if (!pipeline_is_running(p)) { + struct rte_table_action *a = p->table[table_id].a; + union table_rule_match_low_level match_ll; + struct rte_pipeline_table_entry *data_in, *data_out; + int key_found; + uint8_t *buffer; + + buffer = calloc(TABLE_RULE_ACTION_SIZE_MAX, sizeof(uint8_t)); + if (buffer == NULL) + return -1; + + /* Table match-action rule conversion */ + data_in = (struct rte_pipeline_table_entry *)buffer; + + status = match_convert(match, &match_ll, 1); + if (status) { + free(buffer); + return -1; + } + + status = action_convert(a, action, data_in); + if (status) { + free(buffer); + return -1; + } + + /* Add rule (match, action) to table */ + status = rte_pipeline_table_entry_add(p->p, + table_id, + &match_ll, + data_in, + &key_found, + &data_out); + if (status) { + free(buffer); + return -1; + } + + /* Write Response */ + *data = data_out; + + free(buffer); + return 0; + } + /* Allocate request */ req = pipeline_msg_alloc(); if (req == NULL) @@ -1143,11 +1323,44 @@ pipeline_table_rule_add_default(const char *pipeline_name, p = pipeline_find(pipeline_name); if ((p == NULL) || - (p->enabled == 0) || (table_id >= p->n_tables) || action_default_check(action, p, table_id)) return -1; + if (!pipeline_is_running(p)) { + struct rte_pipeline_table_entry *data_in, *data_out; + uint8_t *buffer; + + buffer = calloc(TABLE_RULE_ACTION_SIZE_MAX, sizeof(uint8_t)); + if (buffer == NULL) + return -1; + + /* Apply actions */ + data_in = (struct rte_pipeline_table_entry *)buffer; + + data_in->action = action->fwd.action; + if (action->fwd.action == RTE_PIPELINE_ACTION_PORT) + data_in->port_id = action->fwd.id; + if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE) + data_in->table_id = action->fwd.id; + + /* Add default rule to table */ + status = rte_pipeline_table_default_entry_add(p->p, + table_id, + data_in, + &data_out); + if (status) { + free(buffer); + return -1; + } + + /* Write Response */ + *data = data_out; + + free(buffer); + return 0; + } + /* Allocate request */ req = pipeline_msg_alloc(); if (req == NULL) @@ -1199,7 +1412,6 @@ pipeline_table_rule_add_bulk(const char *pipeline_name, p = pipeline_find(pipeline_name); if ((p == NULL) || - (p->enabled == 0) || (table_id >= p->n_tables)) return -1; @@ -1208,6 +1420,99 @@ pipeline_table_rule_add_bulk(const char *pipeline_name, action_check(action, p, table_id)) return -1; + if (!pipeline_is_running(p)) { + struct rte_table_action *a = p->table[table_id].a; + union table_rule_match_low_level *match_ll; + uint8_t *action_ll; + void **match_ll_ptr; + struct rte_pipeline_table_entry **action_ll_ptr; + struct rte_pipeline_table_entry **entries_ptr = + (struct rte_pipeline_table_entry **)data; + uint32_t bulk = + (p->table[table_id].params.match_type == TABLE_ACL) ? 1 : 0; + int *found; + + /* Memory allocation */ + match_ll = calloc(*n_rules, sizeof(union table_rule_match_low_level)); + action_ll = calloc(*n_rules, TABLE_RULE_ACTION_SIZE_MAX); + match_ll_ptr = calloc(*n_rules, sizeof(void *)); + action_ll_ptr = + calloc(*n_rules, sizeof(struct rte_pipeline_table_entry *)); + found = calloc(*n_rules, sizeof(int)); + + if (match_ll == NULL || + action_ll == NULL || + match_ll_ptr == NULL || + action_ll_ptr == NULL || + found == NULL) + goto fail; + + for (i = 0; i < *n_rules; i++) { + match_ll_ptr[i] = (void *)&match_ll[i]; + action_ll_ptr[i] = + (struct rte_pipeline_table_entry *)&action_ll[i * TABLE_RULE_ACTION_SIZE_MAX]; + } + + /* Rule match conversion */ + for (i = 0; i < *n_rules; i++) { + status = match_convert(&match[i], match_ll_ptr[i], 1); + if (status) + goto fail; + } + + /* Rule action conversion */ + for (i = 0; i < *n_rules; i++) { + status = action_convert(a, &action[i], action_ll_ptr[i]); + if (status) + goto fail; + } + + /* Add rule (match, action) to table */ + if (bulk) { + status = rte_pipeline_table_entry_add_bulk(p->p, + table_id, + match_ll_ptr, + action_ll_ptr, + *n_rules, + found, + entries_ptr); + if (status) + *n_rules = 0; + } else { + for (i = 0; i < *n_rules; i++) { + status = rte_pipeline_table_entry_add(p->p, + table_id, + match_ll_ptr[i], + action_ll_ptr[i], + &found[i], + &entries_ptr[i]); + if (status) { + *n_rules = i; + break; + } + } + } + + /* Free */ + free(found); + free(action_ll_ptr); + free(match_ll_ptr); + free(action_ll); + free(match_ll); + + return status; + +fail: + free(found); + free(action_ll_ptr); + free(match_ll_ptr); + free(action_ll); + free(match_ll); + + *n_rules = 0; + return -1; + } + /* Allocate request */ req = pipeline_msg_alloc(); if (req == NULL) @@ -1256,11 +1561,27 @@ pipeline_table_rule_delete(const char *pipeline_name, p = pipeline_find(pipeline_name); if ((p == NULL) || - (p->enabled == 0) || (table_id >= p->n_tables) || match_check(match, p, table_id)) return -1; + if (!pipeline_is_running(p)) { + union table_rule_match_low_level match_ll; + int key_found; + + status = match_convert(match, &match_ll, 0); + if (status) + return -1; + + status = rte_pipeline_table_entry_delete(p->p, + table_id, + &match_ll, + &key_found, + NULL); + + return status; + } + /* Allocate request */ req = pipeline_msg_alloc(); if (req == NULL) @@ -1300,10 +1621,17 @@ pipeline_table_rule_delete_default(const char *pipeline_name, p = pipeline_find(pipeline_name); if ((p == NULL) || - (p->enabled == 0) || (table_id >= p->n_tables)) return -1; + if (!pipeline_is_running(p)) { + status = rte_pipeline_table_default_entry_delete(p->p, + table_id, + NULL); + + return status; + } + /* Allocate request */ req = pipeline_msg_alloc(); if (req == NULL) @@ -1347,10 +1675,20 @@ pipeline_table_rule_stats_read(const char *pipeline_name, p = pipeline_find(pipeline_name); if ((p == NULL) || - (p->enabled == 0) || (table_id >= p->n_tables)) return -1; + if (!pipeline_is_running(p)) { + struct rte_table_action *a = p->table[table_id].a; + + status = rte_table_action_stats_read(a, + data, + stats, + clear); + + return status; + } + /* Allocate request */ req = pipeline_msg_alloc(); if (req == NULL) @@ -1396,10 +1734,19 @@ pipeline_table_mtr_profile_add(const char *pipeline_name, p = pipeline_find(pipeline_name); if ((p == NULL) || - (p->enabled == 0) || (table_id >= p->n_tables)) return -1; + if (!pipeline_is_running(p)) { + struct rte_table_action *a = p->table[table_id].a; + + status = rte_table_action_meter_profile_add(a, + meter_profile_id, + profile); + + return status; + } + /* Allocate request */ req = pipeline_msg_alloc(); if (req == NULL) @@ -1441,10 +1788,18 @@ pipeline_table_mtr_profile_delete(const char *pipeline_name, p = pipeline_find(pipeline_name); if ((p == NULL) || - (p->enabled == 0) || (table_id >= p->n_tables)) return -1; + if (!pipeline_is_running(p)) { + struct rte_table_action *a = p->table[table_id].a; + + status = rte_table_action_meter_profile_delete(a, + meter_profile_id); + + return status; + } + /* Allocate request */ req = pipeline_msg_alloc(); if (req == NULL) @@ -1490,10 +1845,21 @@ pipeline_table_rule_mtr_read(const char *pipeline_name, p = pipeline_find(pipeline_name); if ((p == NULL) || - (p->enabled == 0) || (table_id >= p->n_tables)) return -1; + if (!pipeline_is_running(p)) { + struct rte_table_action *a = p->table[table_id].a; + + status = rte_table_action_meter_read(a, + data, + tc_mask, + stats, + clear); + + return status; + } + /* Allocate request */ req = pipeline_msg_alloc(); if (req == NULL) @@ -1540,10 +1906,19 @@ pipeline_table_dscp_table_update(const char *pipeline_name, p = pipeline_find(pipeline_name); if ((p == NULL) || - (p->enabled == 0) || (table_id >= p->n_tables)) return -1; + if (!pipeline_is_running(p)) { + struct rte_table_action *a = p->table[table_id].a; + + status = rte_table_action_dscp_table_update(a, + dscp_mask, + dscp_table); + + return status; + } + /* Allocate request */ req = pipeline_msg_alloc(); if (req == NULL) @@ -1590,10 +1965,20 @@ pipeline_table_rule_ttl_read(const char *pipeline_name, p = pipeline_find(pipeline_name); if ((p == NULL) || - (p->enabled == 0) || (table_id >= p->n_tables)) return -1; + if (!pipeline_is_running(p)) { + struct rte_table_action *a = p->table[table_id].a; + + status = rte_table_action_ttl_read(a, + data, + stats, + clear); + + return status; + } + /* Allocate request */ req = pipeline_msg_alloc(); if (req == NULL) @@ -1722,15 +2107,6 @@ pipeline_msg_handle_table_stats_read(struct pipeline_data *p, return rsp; } -union table_rule_match_low_level { - struct rte_table_acl_rule_add_params acl_add; - struct rte_table_acl_rule_delete_params acl_delete; - struct rte_table_array_key array; - uint8_t hash[TABLE_RULE_MATCH_SIZE_MAX]; - struct rte_table_lpm_key lpm_ipv4; - struct rte_table_lpm_ipv6_key lpm_ipv6; -}; - static int match_convert_ipv6_depth(uint32_t depth, uint32_t *depth32) { @@ -2002,138 +2378,136 @@ match_convert(struct table_rule_match *mh, } } -static struct pipeline_msg_rsp * -pipeline_msg_handle_table_rule_add(struct pipeline_data *p, - struct pipeline_msg_req *req) +static int +action_convert(struct rte_table_action *a, + struct table_rule_action *action, + struct rte_pipeline_table_entry *data) { - union table_rule_match_low_level match_ll; - struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req; - struct table_rule_match *match = &req->table_rule_add.match; - struct table_rule_action *action = &req->table_rule_add.action; - struct rte_pipeline_table_entry *data_in, *data_out; - uint32_t table_id = req->id; - int key_found, status; - struct rte_table_action *a = p->table_data[table_id].a; + int status; /* Apply actions */ - memset(p->buffer, 0, sizeof(p->buffer)); - data_in = (struct rte_pipeline_table_entry *) p->buffer; - if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) { status = rte_table_action_apply(a, - data_in, + data, RTE_TABLE_ACTION_FWD, &action->fwd); - if (status) { - rsp->status = -1; - return rsp; - } + if (status) + return status; } if (action->action_mask & (1LLU << RTE_TABLE_ACTION_LB)) { status = rte_table_action_apply(a, - data_in, + data, RTE_TABLE_ACTION_LB, &action->lb); - if (status) { - rsp->status = -1; - return rsp; - } + if (status) + return status; } if (action->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) { status = rte_table_action_apply(a, - data_in, + data, RTE_TABLE_ACTION_MTR, &action->mtr); - if (status) { - rsp->status = -1; - return rsp; - } + if (status) + return status; } if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) { status = rte_table_action_apply(a, - data_in, + data, RTE_TABLE_ACTION_TM, &action->tm); - if (status) { - rsp->status = -1; - return rsp; - } + if (status) + return status; } if (action->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) { status = rte_table_action_apply(a, - data_in, + data, RTE_TABLE_ACTION_ENCAP, &action->encap); - if (status) { - rsp->status = -1; - return rsp; - } + if (status) + return status; } if (action->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) { status = rte_table_action_apply(a, - data_in, + data, RTE_TABLE_ACTION_NAT, &action->nat); - if (status) { - rsp->status = -1; - return rsp; - } + if (status) + return status; } if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TTL)) { status = rte_table_action_apply(a, - data_in, + data, RTE_TABLE_ACTION_TTL, &action->ttl); - if (status) { - rsp->status = -1; - return rsp; - } + if (status) + return status; } if (action->action_mask & (1LLU << RTE_TABLE_ACTION_STATS)) { status = rte_table_action_apply(a, - data_in, + data, RTE_TABLE_ACTION_STATS, &action->stats); - if (status) { - rsp->status = -1; - return rsp; - } + if (status) + return status; } if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TIME)) { status = rte_table_action_apply(a, - data_in, + data, RTE_TABLE_ACTION_TIME, &action->time); - if (status) { - rsp->status = -1; - return rsp; - } + if (status) + return status; } - /* Add rule (match, action) to table */ + return 0; +} + +static struct pipeline_msg_rsp * +pipeline_msg_handle_table_rule_add(struct pipeline_data *p, + struct pipeline_msg_req *req) +{ + union table_rule_match_low_level match_ll; + struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req; + struct table_rule_match *match = &req->table_rule_add.match; + struct table_rule_action *action = &req->table_rule_add.action; + struct rte_pipeline_table_entry *data_in, *data_out; + uint32_t table_id = req->id; + int key_found, status; + struct rte_table_action *a = p->table_data[table_id].a; + + /* Apply actions */ + memset(p->buffer, 0, sizeof(p->buffer)); + data_in = (struct rte_pipeline_table_entry *) p->buffer; + status = match_convert(match, &match_ll, 1); if (status) { rsp->status = -1; return rsp; } + status = action_convert(a, action, data_in); + if (status) { + rsp->status = -1; + return rsp; + } + status = rte_pipeline_table_entry_add(p->p, table_id, &match_ll, @@ -2242,98 +2616,9 @@ pipeline_msg_handle_table_rule_add_bulk(struct pipeline_data *p, /* Rule action conversion */ for (i = 0; i < n_rules; i++) { - void *data_in = action_ll_ptr[i]; - struct table_rule_action *act = &action[i]; - - if (act->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) { - status = rte_table_action_apply(a, - data_in, - RTE_TABLE_ACTION_FWD, - &act->fwd); - - if (status) - goto fail; - } - - if (act->action_mask & (1LLU << RTE_TABLE_ACTION_LB)) { - status = rte_table_action_apply(a, - data_in, - RTE_TABLE_ACTION_LB, - &act->lb); - - if (status) - goto fail; - } - - if (act->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) { - status = rte_table_action_apply(a, - data_in, - RTE_TABLE_ACTION_MTR, - &act->mtr); - - if (status) - goto fail; - } - - if (act->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) { - status = rte_table_action_apply(a, - data_in, - RTE_TABLE_ACTION_TM, - &act->tm); - - if (status) - goto fail; - } - - if (act->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) { - status = rte_table_action_apply(a, - data_in, - RTE_TABLE_ACTION_ENCAP, - &act->encap); - - if (status) - goto fail; - } - - if (act->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) { - status = rte_table_action_apply(a, - data_in, - RTE_TABLE_ACTION_NAT, - &act->nat); - - if (status) - goto fail; - } - - if (act->action_mask & (1LLU << RTE_TABLE_ACTION_TTL)) { - status = rte_table_action_apply(a, - data_in, - RTE_TABLE_ACTION_TTL, - &act->ttl); - - if (status) - goto fail; - } - - if (act->action_mask & (1LLU << RTE_TABLE_ACTION_STATS)) { - status = rte_table_action_apply(a, - data_in, - RTE_TABLE_ACTION_STATS, - &act->stats); - - if (status) - goto fail; - } - - if (act->action_mask & (1LLU << RTE_TABLE_ACTION_TIME)) { - status = rte_table_action_apply(a, - data_in, - RTE_TABLE_ACTION_TIME, - &act->time); - - if (status) - goto fail; - } + status = action_convert(a, &action[i], action_ll_ptr[i]); + if (status) + goto fail; } /* Add rule (match, action) to table */ diff --git a/examples/ip_reassembly/main.c b/examples/ip_reassembly/main.c index 3e8e79c2..b830f67a 100644 --- a/examples/ip_reassembly/main.c +++ b/examples/ip_reassembly/main.c @@ -164,7 +164,6 @@ static struct rte_eth_conf port_conf = { .mq_mode = ETH_MQ_RX_RSS, .max_rx_pkt_len = JUMBO_FRAME_MAX_SIZE, .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = (DEV_RX_OFFLOAD_CHECKSUM | DEV_RX_OFFLOAD_JUMBO_FRAME | DEV_RX_OFFLOAD_CRC_STRIP), @@ -1083,6 +1082,18 @@ main(int argc, char **argv) if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) local_port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MBUF_FAST_FREE; + + local_port_conf.rx_adv_conf.rss_conf.rss_hf &= + dev_info.flow_type_rss_offloads; + if (local_port_conf.rx_adv_conf.rss_conf.rss_hf != + port_conf.rx_adv_conf.rss_conf.rss_hf) { + printf("Port %u modified RSS hash function based on hardware support," + "requested:%#"PRIx64" configured:%#"PRIx64"\n", + portid, + port_conf.rx_adv_conf.rss_conf.rss_hf, + local_port_conf.rx_adv_conf.rss_conf.rss_hf); + } + ret = rte_eth_dev_configure(portid, 1, (uint16_t)n_tx_queue, &local_port_conf); if (ret < 0) { @@ -1121,7 +1132,6 @@ main(int argc, char **argv) fflush(stdout); txconf = &dev_info.default_txconf; - txconf->txq_flags = ETH_TXQ_FLAGS_IGNORE; txconf->offloads = local_port_conf.txmode.offloads; ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd, diff --git a/examples/ipsec-secgw/ipsec-secgw.c b/examples/ipsec-secgw/ipsec-secgw.c index a5da8b28..b45b87bd 100644 --- a/examples/ipsec-secgw/ipsec-secgw.c +++ b/examples/ipsec-secgw/ipsec-secgw.c @@ -199,7 +199,6 @@ static struct rte_eth_conf port_conf = { .split_hdr_size = 0, .offloads = DEV_RX_OFFLOAD_CHECKSUM | DEV_RX_OFFLOAD_CRC_STRIP, - .ignore_offload_bitfield = 1, }, .rx_adv_conf = { .rss_conf = { @@ -331,6 +330,7 @@ prepare_tx_pkt(struct rte_mbuf *pkt, uint16_t port) pkt->l3_len = sizeof(struct ip); pkt->l2_len = ETHER_HDR_LEN; + ip->ip_sum = 0; ethhdr->ether_type = rte_cpu_to_be_16(ETHER_TYPE_IPv4); } else { pkt->ol_flags |= PKT_TX_IPV6; @@ -510,11 +510,13 @@ outbound_sp(struct sp_ctx *sp, struct traffic_type *ip, sa_idx = ip->res[i] & PROTECT_MASK; if (ip->res[i] & DISCARD) rte_pktmbuf_free(m); + else if (ip->res[i] & BYPASS) + ip->pkts[j++] = m; else if (sa_idx < IPSEC_SA_MAX_ENTRIES) { ipsec->res[ipsec->num] = sa_idx; ipsec->pkts[ipsec->num++] = m; - } else /* BYPASS */ - ip->pkts[j++] = m; + } else /* invalid SA idx */ + rte_pktmbuf_free(m); } ip->num = j; } @@ -1440,6 +1442,12 @@ cryptodevs_init(void) dev_conf.socket_id = rte_cryptodev_socket_id(cdev_id); dev_conf.nb_queue_pairs = qp; + uint32_t dev_max_sess = cdev_info.sym.max_nb_sessions; + if (dev_max_sess != 0 && dev_max_sess < (CDEV_MP_NB_OBJS / 2)) + rte_exit(EXIT_FAILURE, + "Device does not support at least %u " + "sessions", CDEV_MP_NB_OBJS / 2); + if (!socket_ctx[dev_conf.socket_id].session_pool) { char mp_name[RTE_MEMPOOL_NAMESIZE]; struct rte_mempool *sess_mp; @@ -1566,6 +1574,18 @@ port_init(uint16_t portid) if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) local_port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MBUF_FAST_FREE; + + local_port_conf.rx_adv_conf.rss_conf.rss_hf &= + dev_info.flow_type_rss_offloads; + if (local_port_conf.rx_adv_conf.rss_conf.rss_hf != + port_conf.rx_adv_conf.rss_conf.rss_hf) { + printf("Port %u modified RSS hash function based on hardware support," + "requested:%#"PRIx64" configured:%#"PRIx64"\n", + portid, + port_conf.rx_adv_conf.rss_conf.rss_hf, + local_port_conf.rx_adv_conf.rss_conf.rss_hf); + } + ret = rte_eth_dev_configure(portid, nb_rx_queue, nb_tx_queue, &local_port_conf); if (ret < 0) @@ -1592,7 +1612,6 @@ port_init(uint16_t portid) printf("Setup txq=%u,%d,%d\n", lcore_id, tx_queueid, socket_id); txconf = &dev_info.default_txconf; - txconf->txq_flags = ETH_TXQ_FLAGS_IGNORE; txconf->offloads = local_port_conf.txmode.offloads; ret = rte_eth_tx_queue_setup(portid, tx_queueid, nb_txd, diff --git a/examples/ipsec-secgw/ipsec.h b/examples/ipsec-secgw/ipsec.h index 9b87278c..c998c807 100644 --- a/examples/ipsec-secgw/ipsec.h +++ b/examples/ipsec-secgw/ipsec.h @@ -191,7 +191,7 @@ ipsec_metadata_size(void) static inline struct ipsec_mbuf_metadata * get_priv(struct rte_mbuf *m) { - return RTE_PTR_ADD(m, sizeof(struct rte_mbuf)); + return rte_mbuf_to_priv(m); } static inline void * diff --git a/examples/ipsec-secgw/sa.c b/examples/ipsec-secgw/sa.c index d9dcc0e0..4ab8e098 100644 --- a/examples/ipsec-secgw/sa.c +++ b/examples/ipsec-secgw/sa.c @@ -939,7 +939,7 @@ inbound_sa_check(struct sa_ctx *sa_ctx, struct rte_mbuf *m, uint32_t sa_idx) { struct ipsec_mbuf_metadata *priv; - priv = RTE_PTR_ADD(m, sizeof(struct rte_mbuf)); + priv = get_priv(m); return (sa_ctx->sa[sa_idx].spi == priv->sa->spi); } diff --git a/examples/ipv4_multicast/main.c b/examples/ipv4_multicast/main.c index ad2072f4..331c32e7 100644 --- a/examples/ipv4_multicast/main.c +++ b/examples/ipv4_multicast/main.c @@ -109,7 +109,6 @@ static struct rte_eth_conf port_conf = { .rxmode = { .max_rx_pkt_len = JUMBO_FRAME_MAX_SIZE, .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = (DEV_RX_OFFLOAD_JUMBO_FRAME | DEV_RX_OFFLOAD_CRC_STRIP), }, @@ -764,7 +763,6 @@ main(int argc, char **argv) fflush(stdout); txconf = &dev_info.default_txconf; - txconf->txq_flags = ETH_TXQ_FLAGS_IGNORE; txconf->offloads = local_port_conf.txmode.offloads; ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd, rte_lcore_to_socket_id(lcore_id), txconf); diff --git a/examples/kni/Makefile b/examples/kni/Makefile index 562dc274..7e19d2e2 100644 --- a/examples/kni/Makefile +++ b/examples/kni/Makefile @@ -48,7 +48,7 @@ RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk -ifneq ($(CONFIG_RTE_EXEC_ENV),"linuxapp") +ifneq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) $(error This application can only operate in a linuxapp environment, \ please change the definition of the RTE_TARGET environment variable) endif diff --git a/examples/kni/main.c b/examples/kni/main.c index 4b162deb..81336087 100644 --- a/examples/kni/main.c +++ b/examples/kni/main.c @@ -95,7 +95,6 @@ static struct kni_port_params *kni_port_params_array[RTE_MAX_ETHPORTS]; /* Options for configuring ethernet port */ static struct rte_eth_conf port_conf = { .rxmode = { - .ignore_offload_bitfield = 1, .offloads = DEV_RX_OFFLOAD_CRC_STRIP, }, .txmode = { @@ -607,7 +606,6 @@ init_port(uint16_t port) "port%u (%d)\n", (unsigned)port, ret); txq_conf = dev_info.default_txconf; - txq_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txq_conf.offloads = local_port_conf.txmode.offloads; ret = rte_eth_tx_queue_setup(port, 0, nb_txd, rte_eth_dev_socket_id(port), &txq_conf); diff --git a/examples/kni/meson.build b/examples/kni/meson.build index 0443ab99..79131639 100644 --- a/examples/kni/meson.build +++ b/examples/kni/meson.build @@ -6,9 +6,8 @@ # To build this example as a standalone application with an already-installed # DPDK instance, use 'make' -if host_machine.system() != 'linux' - build = false -endif +# this app can be built if-and-only-if KNI library is buildable +build = dpdk_conf.has('RTE_LIBRTE_KNI') deps += ['kni', 'bus_pci'] sources = files( 'main.c' diff --git a/examples/l2fwd-crypto/Makefile b/examples/l2fwd-crypto/Makefile index a67f087b..6658fd0d 100644 --- a/examples/l2fwd-crypto/Makefile +++ b/examples/l2fwd-crypto/Makefile @@ -51,5 +51,11 @@ include $(RTE_SDK)/mk/rte.vars.mk CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) +ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),y) +ifeq ($(CONFIG_RTE_LIBRTE_PMD_CRYPTO_SCHEDULER),y) +LDLIBS += -lrte_pmd_crypto_scheduler +endif +endif + include $(RTE_SDK)/mk/rte.extapp.mk endif diff --git a/examples/l2fwd-crypto/main.c b/examples/l2fwd-crypto/main.c index 4bca87b1..6061b751 100644 --- a/examples/l2fwd-crypto/main.c +++ b/examples/l2fwd-crypto/main.c @@ -42,6 +42,9 @@ #include <rte_prefetch.h> #include <rte_random.h> #include <rte_hexdump.h> +#ifdef RTE_LIBRTE_PMD_CRYPTO_SCHEDULER +#include <rte_cryptodev_scheduler.h> +#endif enum cdev_type { CDEV_TYPE_ANY, @@ -59,7 +62,6 @@ enum cdev_type { #define MAX_AAD_SIZE 65535 #define MAX_PKT_BURST 32 #define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ -#define MAX_SESSIONS 32 #define SESSION_POOL_CACHE_SIZE 0 #define MAXIMUM_IV_LENGTH 16 @@ -211,7 +213,6 @@ static struct rte_eth_conf port_conf = { .mq_mode = ETH_MQ_RX_NONE, .max_rx_pkt_len = ETHER_MAX_LEN, .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = DEV_RX_OFFLOAD_CRC_STRIP, }, .txmode = { @@ -407,7 +408,7 @@ l2fwd_simple_crypto_enqueue(struct rte_mbuf *m, /* Zero pad data to be crypto'd so it is block aligned */ data_len = rte_pktmbuf_data_len(m) - ipdata_offset; - if (cparams->do_hash && cparams->hash_verify) + if ((cparams->do_hash || cparams->do_aead) && cparams->hash_verify) data_len -= cparams->digest_length; if (cparams->do_cipher) { @@ -1930,21 +1931,19 @@ check_supported_size(uint16_t length, uint16_t min, uint16_t max, static int check_iv_param(const struct rte_crypto_param_range *iv_range_size, unsigned int iv_param, int iv_random_size, - uint16_t *iv_length) + uint16_t iv_length) { /* * Check if length of provided IV is supported * by the algorithm chosen. */ if (iv_param) { - if (check_supported_size(*iv_length, + if (check_supported_size(iv_length, iv_range_size->min, iv_range_size->max, iv_range_size->increment) - != 0) { - printf("Unsupported IV length\n"); + != 0) return -1; - } /* * Check if length of IV to be randomly generated * is supported by the algorithm chosen. @@ -1954,14 +1953,250 @@ check_iv_param(const struct rte_crypto_param_range *iv_range_size, iv_range_size->min, iv_range_size->max, iv_range_size->increment) - != 0) { - printf("Unsupported IV length\n"); + != 0) + return -1; + } + + return 0; +} + +static int +check_capabilities(struct l2fwd_crypto_options *options, uint8_t cdev_id) +{ + struct rte_cryptodev_info dev_info; + const struct rte_cryptodev_capabilities *cap; + + rte_cryptodev_info_get(cdev_id, &dev_info); + + /* Set AEAD parameters */ + if (options->xform_chain == L2FWD_CRYPTO_AEAD) { + /* Check if device supports AEAD algo */ + cap = check_device_support_aead_algo(options, &dev_info, + cdev_id); + if (cap == NULL) + return -1; + + if (check_iv_param(&cap->sym.aead.iv_size, + options->aead_iv_param, + options->aead_iv_random_size, + options->aead_iv.length) != 0) { + RTE_LOG(DEBUG, USER1, + "Device %u does not support IV length\n", + cdev_id); + return -1; + } + + /* + * Check if length of provided AEAD key is supported + * by the algorithm chosen. + */ + if (options->aead_key_param) { + if (check_supported_size( + options->aead_xform.aead.key.length, + cap->sym.aead.key_size.min, + cap->sym.aead.key_size.max, + cap->sym.aead.key_size.increment) + != 0) { + RTE_LOG(DEBUG, USER1, + "Device %u does not support " + "AEAD key length\n", + cdev_id); + return -1; + } + /* + * Check if length of the aead key to be randomly generated + * is supported by the algorithm chosen. + */ + } else if (options->aead_key_random_size != -1) { + if (check_supported_size(options->aead_key_random_size, + cap->sym.aead.key_size.min, + cap->sym.aead.key_size.max, + cap->sym.aead.key_size.increment) + != 0) { + RTE_LOG(DEBUG, USER1, + "Device %u does not support " + "AEAD key length\n", + cdev_id); + return -1; + } + } + + + /* + * Check if length of provided AAD is supported + * by the algorithm chosen. + */ + if (options->aad_param) { + if (check_supported_size(options->aad.length, + cap->sym.aead.aad_size.min, + cap->sym.aead.aad_size.max, + cap->sym.aead.aad_size.increment) + != 0) { + RTE_LOG(DEBUG, USER1, + "Device %u does not support " + "AAD length\n", + cdev_id); + return -1; + } + /* + * Check if length of AAD to be randomly generated + * is supported by the algorithm chosen. + */ + } else if (options->aad_random_size != -1) { + if (check_supported_size(options->aad_random_size, + cap->sym.aead.aad_size.min, + cap->sym.aead.aad_size.max, + cap->sym.aead.aad_size.increment) + != 0) { + RTE_LOG(DEBUG, USER1, + "Device %u does not support " + "AAD length\n", + cdev_id); + return -1; + } + } + + /* Check if digest size is supported by the algorithm. */ + if (options->digest_size != -1) { + if (check_supported_size(options->digest_size, + cap->sym.aead.digest_size.min, + cap->sym.aead.digest_size.max, + cap->sym.aead.digest_size.increment) + != 0) { + RTE_LOG(DEBUG, USER1, + "Device %u does not support " + "digest length\n", + cdev_id); + return -1; + } + } + } + + /* Set cipher parameters */ + if (options->xform_chain == L2FWD_CRYPTO_CIPHER_HASH || + options->xform_chain == L2FWD_CRYPTO_HASH_CIPHER || + options->xform_chain == L2FWD_CRYPTO_CIPHER_ONLY) { + /* Check if device supports cipher algo */ + cap = check_device_support_cipher_algo(options, &dev_info, + cdev_id); + if (cap == NULL) + return -1; + + if (check_iv_param(&cap->sym.cipher.iv_size, + options->cipher_iv_param, + options->cipher_iv_random_size, + options->cipher_iv.length) != 0) { + RTE_LOG(DEBUG, USER1, + "Device %u does not support IV length\n", + cdev_id); + return -1; + } + + /* + * Check if length of provided cipher key is supported + * by the algorithm chosen. + */ + if (options->ckey_param) { + if (check_supported_size( + options->cipher_xform.cipher.key.length, + cap->sym.cipher.key_size.min, + cap->sym.cipher.key_size.max, + cap->sym.cipher.key_size.increment) + != 0) { + RTE_LOG(DEBUG, USER1, + "Device %u does not support cipher " + "key length\n", + cdev_id); + return -1; + } + /* + * Check if length of the cipher key to be randomly generated + * is supported by the algorithm chosen. + */ + } else if (options->ckey_random_size != -1) { + if (check_supported_size(options->ckey_random_size, + cap->sym.cipher.key_size.min, + cap->sym.cipher.key_size.max, + cap->sym.cipher.key_size.increment) + != 0) { + RTE_LOG(DEBUG, USER1, + "Device %u does not support cipher " + "key length\n", + cdev_id); + return -1; + } + } + } + + /* Set auth parameters */ + if (options->xform_chain == L2FWD_CRYPTO_CIPHER_HASH || + options->xform_chain == L2FWD_CRYPTO_HASH_CIPHER || + options->xform_chain == L2FWD_CRYPTO_HASH_ONLY) { + /* Check if device supports auth algo */ + cap = check_device_support_auth_algo(options, &dev_info, + cdev_id); + if (cap == NULL) return -1; + + if (check_iv_param(&cap->sym.auth.iv_size, + options->auth_iv_param, + options->auth_iv_random_size, + options->auth_iv.length) != 0) { + RTE_LOG(DEBUG, USER1, + "Device %u does not support IV length\n", + cdev_id); + return -1; + } + /* + * Check if length of provided auth key is supported + * by the algorithm chosen. + */ + if (options->akey_param) { + if (check_supported_size( + options->auth_xform.auth.key.length, + cap->sym.auth.key_size.min, + cap->sym.auth.key_size.max, + cap->sym.auth.key_size.increment) + != 0) { + RTE_LOG(DEBUG, USER1, + "Device %u does not support auth " + "key length\n", + cdev_id); + return -1; + } + /* + * Check if length of the auth key to be randomly generated + * is supported by the algorithm chosen. + */ + } else if (options->akey_random_size != -1) { + if (check_supported_size(options->akey_random_size, + cap->sym.auth.key_size.min, + cap->sym.auth.key_size.max, + cap->sym.auth.key_size.increment) + != 0) { + RTE_LOG(DEBUG, USER1, + "Device %u does not support auth " + "key length\n", + cdev_id); + return -1; + } + } + + /* Check if digest size is supported by the algorithm. */ + if (options->digest_size != -1) { + if (check_supported_size(options->digest_size, + cap->sym.auth.digest_size.min, + cap->sym.auth.digest_size.max, + cap->sym.auth.digest_size.increment) + != 0) { + RTE_LOG(DEBUG, USER1, + "Device %u does not support " + "digest length\n", + cdev_id); + return -1; + } } - *iv_length = iv_random_size; - /* No size provided, use minimum size. */ - } else - *iv_length = iv_range_size->min; + } return 0; } @@ -1970,9 +2205,10 @@ static int initialize_cryptodevs(struct l2fwd_crypto_options *options, unsigned nb_ports, uint8_t *enabled_cdevs) { - unsigned int cdev_id, cdev_count, enabled_cdev_count = 0; + uint8_t cdev_id, cdev_count, enabled_cdev_count = 0; const struct rte_cryptodev_capabilities *cap; unsigned int sess_sz, max_sess_sz = 0; + uint32_t sessions_needed = 0; int retval; cdev_count = rte_cryptodev_count(); @@ -1981,16 +2217,31 @@ initialize_cryptodevs(struct l2fwd_crypto_options *options, unsigned nb_ports, return -1; } - for (cdev_id = 0; cdev_id < cdev_count; cdev_id++) { + for (cdev_id = 0; cdev_id < cdev_count && enabled_cdev_count < nb_ports; + cdev_id++) { + if (check_cryptodev_mask(options, cdev_id) < 0) + continue; + + if (check_capabilities(options, cdev_id) < 0) + continue; + sess_sz = rte_cryptodev_sym_get_private_session_size(cdev_id); if (sess_sz > max_sess_sz) max_sess_sz = sess_sz; + + l2fwd_enabled_crypto_mask |= (((uint64_t)1) << cdev_id); + + enabled_cdevs[cdev_id] = 1; + enabled_cdev_count++; } - for (cdev_id = 0; cdev_id < cdev_count && enabled_cdev_count < nb_ports; - cdev_id++) { + for (cdev_id = 0; cdev_id < cdev_count; cdev_id++) { struct rte_cryptodev_qp_conf qp_conf; struct rte_cryptodev_info dev_info; + + if (enabled_cdevs[cdev_id] == 0) + continue; + retval = rte_cryptodev_socket_id(cdev_id); if (retval < 0) { @@ -2005,11 +2256,23 @@ initialize_cryptodevs(struct l2fwd_crypto_options *options, unsigned nb_ports, .socket_id = socket_id, }; - if (check_cryptodev_mask(options, (uint8_t)cdev_id)) - continue; - rte_cryptodev_info_get(cdev_id, &dev_info); + /* + * Two sessions objects are required for each session + * (one for the header, one for the private data) + */ + if (!strcmp(dev_info.driver_name, "crypto_scheduler")) { +#ifdef RTE_LIBRTE_PMD_CRYPTO_SCHEDULER + uint32_t nb_slaves = + rte_cryptodev_scheduler_slaves_get(cdev_id, + NULL); + + sessions_needed = 2 * enabled_cdev_count * nb_slaves; +#endif + } else + sessions_needed = 2 * enabled_cdev_count; + if (session_pool_socket[socket_id] == NULL) { char mp_name[RTE_MEMPOOL_NAMESIZE]; struct rte_mempool *sess_mp; @@ -2022,7 +2285,7 @@ initialize_cryptodevs(struct l2fwd_crypto_options *options, unsigned nb_ports, * device private data */ sess_mp = rte_mempool_create(mp_name, - MAX_SESSIONS * 2, + sessions_needed, max_sess_sz, SESSION_POOL_CACHE_SIZE, 0, NULL, NULL, NULL, @@ -2041,106 +2304,57 @@ initialize_cryptodevs(struct l2fwd_crypto_options *options, unsigned nb_ports, /* Set AEAD parameters */ if (options->xform_chain == L2FWD_CRYPTO_AEAD) { - /* Check if device supports AEAD algo */ cap = check_device_support_aead_algo(options, &dev_info, cdev_id); - if (cap == NULL) - continue; options->block_size = cap->sym.aead.block_size; - check_iv_param(&cap->sym.aead.iv_size, - options->aead_iv_param, - options->aead_iv_random_size, - &options->aead_iv.length); + /* Set IV if not provided from command line */ + if (options->aead_iv_param == 0) { + if (options->aead_iv_random_size != -1) + options->aead_iv.length = + options->aead_iv_random_size; + /* No size provided, use minimum size. */ + else + options->aead_iv.length = + cap->sym.aead.iv_size.min; + } - /* - * Check if length of provided AEAD key is supported - * by the algorithm chosen. - */ - if (options->aead_key_param) { - if (check_supported_size( - options->aead_xform.aead.key.length, - cap->sym.aead.key_size.min, - cap->sym.aead.key_size.max, - cap->sym.aead.key_size.increment) - != 0) { - printf("Unsupported aead key length\n"); - return -1; - } - /* - * Check if length of the aead key to be randomly generated - * is supported by the algorithm chosen. - */ - } else if (options->aead_key_random_size != -1) { - if (check_supported_size(options->aead_key_random_size, - cap->sym.aead.key_size.min, - cap->sym.aead.key_size.max, - cap->sym.aead.key_size.increment) - != 0) { - printf("Unsupported aead key length\n"); - return -1; - } - options->aead_xform.aead.key.length = - options->aead_key_random_size; - /* No size provided, use minimum size. */ - } else - options->aead_xform.aead.key.length = + /* Set key if not provided from command line */ + if (options->aead_key_param == 0) { + if (options->aead_key_random_size != -1) + options->aead_xform.aead.key.length = + options->aead_key_random_size; + /* No size provided, use minimum size. */ + else + options->aead_xform.aead.key.length = cap->sym.aead.key_size.min; - if (!options->aead_key_param) generate_random_key( options->aead_xform.aead.key.data, options->aead_xform.aead.key.length); + } - /* - * Check if length of provided AAD is supported - * by the algorithm chosen. - */ - if (options->aad_param) { - if (check_supported_size(options->aad.length, - cap->sym.aead.aad_size.min, - cap->sym.aead.aad_size.max, - cap->sym.aead.aad_size.increment) - != 0) { - printf("Unsupported AAD length\n"); - return -1; - } - /* - * Check if length of AAD to be randomly generated - * is supported by the algorithm chosen. - */ - } else if (options->aad_random_size != -1) { - if (check_supported_size(options->aad_random_size, - cap->sym.aead.aad_size.min, - cap->sym.aead.aad_size.max, - cap->sym.aead.aad_size.increment) - != 0) { - printf("Unsupported AAD length\n"); - return -1; - } - options->aad.length = options->aad_random_size; - /* No size provided, use minimum size. */ - } else - options->aad.length = cap->sym.auth.aad_size.min; + /* Set AAD if not provided from command line */ + if (options->aad_param == 0) { + if (options->aad_random_size != -1) + options->aad.length = + options->aad_random_size; + /* No size provided, use minimum size. */ + else + options->aad.length = + cap->sym.auth.aad_size.min; + } options->aead_xform.aead.aad_length = options->aad.length; - /* Check if digest size is supported by the algorithm. */ - if (options->digest_size != -1) { - if (check_supported_size(options->digest_size, - cap->sym.aead.digest_size.min, - cap->sym.aead.digest_size.max, - cap->sym.aead.digest_size.increment) - != 0) { - printf("Unsupported digest length\n"); - return -1; - } + /* Set digest size if not provided from command line */ + if (options->digest_size != -1) options->aead_xform.aead.digest_length = options->digest_size; - /* No size provided, use minimum size. */ - } else + /* No size provided, use minimum size. */ + else options->aead_xform.aead.digest_length = cap->sym.aead.digest_size.min; } @@ -2149,127 +2363,76 @@ initialize_cryptodevs(struct l2fwd_crypto_options *options, unsigned nb_ports, if (options->xform_chain == L2FWD_CRYPTO_CIPHER_HASH || options->xform_chain == L2FWD_CRYPTO_HASH_CIPHER || options->xform_chain == L2FWD_CRYPTO_CIPHER_ONLY) { - /* Check if device supports cipher algo */ cap = check_device_support_cipher_algo(options, &dev_info, cdev_id); - if (cap == NULL) - continue; - options->block_size = cap->sym.cipher.block_size; - check_iv_param(&cap->sym.cipher.iv_size, - options->cipher_iv_param, - options->cipher_iv_random_size, - &options->cipher_iv.length); + /* Set IV if not provided from command line */ + if (options->cipher_iv_param == 0) { + if (options->cipher_iv_random_size != -1) + options->cipher_iv.length = + options->cipher_iv_random_size; + /* No size provided, use minimum size. */ + else + options->cipher_iv.length = + cap->sym.cipher.iv_size.min; + } - /* - * Check if length of provided cipher key is supported - * by the algorithm chosen. - */ - if (options->ckey_param) { - if (check_supported_size( - options->cipher_xform.cipher.key.length, - cap->sym.cipher.key_size.min, - cap->sym.cipher.key_size.max, - cap->sym.cipher.key_size.increment) - != 0) { - printf("Unsupported cipher key length\n"); - return -1; - } - /* - * Check if length of the cipher key to be randomly generated - * is supported by the algorithm chosen. - */ - } else if (options->ckey_random_size != -1) { - if (check_supported_size(options->ckey_random_size, - cap->sym.cipher.key_size.min, - cap->sym.cipher.key_size.max, - cap->sym.cipher.key_size.increment) - != 0) { - printf("Unsupported cipher key length\n"); - return -1; - } - options->cipher_xform.cipher.key.length = - options->ckey_random_size; - /* No size provided, use minimum size. */ - } else - options->cipher_xform.cipher.key.length = + /* Set key if not provided from command line */ + if (options->ckey_param == 0) { + if (options->ckey_random_size != -1) + options->cipher_xform.cipher.key.length = + options->ckey_random_size; + /* No size provided, use minimum size. */ + else + options->cipher_xform.cipher.key.length = cap->sym.cipher.key_size.min; - if (!options->ckey_param) generate_random_key( options->cipher_xform.cipher.key.data, options->cipher_xform.cipher.key.length); - + } } /* Set auth parameters */ if (options->xform_chain == L2FWD_CRYPTO_CIPHER_HASH || options->xform_chain == L2FWD_CRYPTO_HASH_CIPHER || options->xform_chain == L2FWD_CRYPTO_HASH_ONLY) { - /* Check if device supports auth algo */ cap = check_device_support_auth_algo(options, &dev_info, cdev_id); - if (cap == NULL) - continue; - check_iv_param(&cap->sym.auth.iv_size, - options->auth_iv_param, - options->auth_iv_random_size, - &options->auth_iv.length); - /* - * Check if length of provided auth key is supported - * by the algorithm chosen. - */ - if (options->akey_param) { - if (check_supported_size( - options->auth_xform.auth.key.length, - cap->sym.auth.key_size.min, - cap->sym.auth.key_size.max, - cap->sym.auth.key_size.increment) - != 0) { - printf("Unsupported auth key length\n"); - return -1; - } - /* - * Check if length of the auth key to be randomly generated - * is supported by the algorithm chosen. - */ - } else if (options->akey_random_size != -1) { - if (check_supported_size(options->akey_random_size, - cap->sym.auth.key_size.min, - cap->sym.auth.key_size.max, - cap->sym.auth.key_size.increment) - != 0) { - printf("Unsupported auth key length\n"); - return -1; - } - options->auth_xform.auth.key.length = - options->akey_random_size; - /* No size provided, use minimum size. */ - } else - options->auth_xform.auth.key.length = + /* Set IV if not provided from command line */ + if (options->auth_iv_param == 0) { + if (options->auth_iv_random_size != -1) + options->auth_iv.length = + options->auth_iv_random_size; + /* No size provided, use minimum size. */ + else + options->auth_iv.length = + cap->sym.auth.iv_size.min; + } + + /* Set key if not provided from command line */ + if (options->akey_param == 0) { + if (options->akey_random_size != -1) + options->auth_xform.auth.key.length = + options->akey_random_size; + /* No size provided, use minimum size. */ + else + options->auth_xform.auth.key.length = cap->sym.auth.key_size.min; - if (!options->akey_param) generate_random_key( options->auth_xform.auth.key.data, options->auth_xform.auth.key.length); + } - /* Check if digest size is supported by the algorithm. */ - if (options->digest_size != -1) { - if (check_supported_size(options->digest_size, - cap->sym.auth.digest_size.min, - cap->sym.auth.digest_size.max, - cap->sym.auth.digest_size.increment) - != 0) { - printf("Unsupported digest length\n"); - return -1; - } + /* Set digest size if not provided from command line */ + if (options->digest_size != -1) options->auth_xform.auth.digest_length = options->digest_size; - /* No size provided, use minimum size. */ - } else + /* No size provided, use minimum size. */ + else options->auth_xform.auth.digest_length = cap->sym.auth.digest_size.min; } @@ -2296,11 +2459,6 @@ initialize_cryptodevs(struct l2fwd_crypto_options *options, unsigned nb_ports, cdev_id, retval); return -1; } - - l2fwd_enabled_crypto_mask |= (((uint64_t)1) << cdev_id); - - enabled_cdevs[cdev_id] = 1; - enabled_cdev_count++; } return enabled_cdev_count; @@ -2371,7 +2529,6 @@ initialize_ports(struct l2fwd_crypto_options *options) /* init one TX queue on each port */ fflush(stdout); txq_conf = dev_info.default_txconf; - txq_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txq_conf.offloads = local_port_conf.txmode.offloads; retval = rte_eth_tx_queue_setup(portid, 0, nb_txd, rte_eth_dev_socket_id(portid), diff --git a/examples/l2fwd-jobstats/main.c b/examples/l2fwd-jobstats/main.c index 34553faa..af542338 100644 --- a/examples/l2fwd-jobstats/main.c +++ b/examples/l2fwd-jobstats/main.c @@ -90,7 +90,6 @@ struct rte_eth_dev_tx_buffer *tx_buffer[RTE_MAX_ETHPORTS]; static struct rte_eth_conf port_conf = { .rxmode = { .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = DEV_RX_OFFLOAD_CRC_STRIP, }, .txmode = { @@ -876,7 +875,6 @@ main(int argc, char **argv) /* init one TX queue on each port */ txq_conf = dev_info.default_txconf; - txq_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txq_conf.offloads = local_port_conf.txmode.offloads; fflush(stdout); ret = rte_eth_tx_queue_setup(portid, 0, nb_txd, diff --git a/examples/l2fwd-keepalive/main.c b/examples/l2fwd-keepalive/main.c index a18b707c..2d8b4d1c 100644 --- a/examples/l2fwd-keepalive/main.c +++ b/examples/l2fwd-keepalive/main.c @@ -81,7 +81,6 @@ struct rte_eth_dev_tx_buffer *tx_buffer[RTE_MAX_ETHPORTS]; static struct rte_eth_conf port_conf = { .rxmode = { .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = DEV_RX_OFFLOAD_CRC_STRIP, }, .txmode = { @@ -671,7 +670,6 @@ main(int argc, char **argv) /* init one TX queue on each port */ fflush(stdout); txq_conf = dev_info.default_txconf; - txq_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txq_conf.offloads = local_port_conf.txmode.offloads; ret = rte_eth_tx_queue_setup(portid, 0, nb_txd, rte_eth_dev_socket_id(portid), diff --git a/examples/l2fwd/main.c b/examples/l2fwd/main.c index 69084357..9bb4c5bc 100644 --- a/examples/l2fwd/main.c +++ b/examples/l2fwd/main.c @@ -82,7 +82,6 @@ static struct rte_eth_dev_tx_buffer *tx_buffer[RTE_MAX_ETHPORTS]; static struct rte_eth_conf port_conf = { .rxmode = { .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = DEV_RX_OFFLOAD_CRC_STRIP, }, .txmode = { @@ -670,7 +669,6 @@ main(int argc, char **argv) /* init one TX queue on each port */ fflush(stdout); txq_conf = dev_info.default_txconf; - txq_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txq_conf.offloads = local_port_conf.txmode.offloads; ret = rte_eth_tx_queue_setup(portid, 0, nb_txd, rte_eth_dev_socket_id(portid), diff --git a/examples/l3fwd-acl/main.c b/examples/l3fwd-acl/main.c index 33ad467d..7c063a8d 100644 --- a/examples/l3fwd-acl/main.c +++ b/examples/l3fwd-acl/main.c @@ -127,7 +127,6 @@ static struct rte_eth_conf port_conf = { .mq_mode = ETH_MQ_RX_RSS, .max_rx_pkt_len = ETHER_MAX_LEN, .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = (DEV_RX_OFFLOAD_CRC_STRIP | DEV_RX_OFFLOAD_CHECKSUM), }, @@ -1926,6 +1925,18 @@ main(int argc, char **argv) if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) local_port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MBUF_FAST_FREE; + + local_port_conf.rx_adv_conf.rss_conf.rss_hf &= + dev_info.flow_type_rss_offloads; + if (local_port_conf.rx_adv_conf.rss_conf.rss_hf != + port_conf.rx_adv_conf.rss_conf.rss_hf) { + printf("Port %u modified RSS hash function based on hardware support," + "requested:%#"PRIx64" configured:%#"PRIx64"\n", + portid, + port_conf.rx_adv_conf.rss_conf.rss_hf, + local_port_conf.rx_adv_conf.rss_conf.rss_hf); + } + ret = rte_eth_dev_configure(portid, nb_rx_queue, (uint16_t)n_tx_queue, &local_port_conf); if (ret < 0) @@ -1982,7 +1993,6 @@ main(int argc, char **argv) rte_eth_dev_info_get(portid, &dev_info); txconf = &dev_info.default_txconf; - txconf->txq_flags = ETH_TXQ_FLAGS_IGNORE; txconf->offloads = local_port_conf.txmode.offloads; ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd, socketid, txconf); diff --git a/examples/l3fwd-power/Makefile b/examples/l3fwd-power/Makefile index 390b7d6b..d7e39a34 100644 --- a/examples/l3fwd-power/Makefile +++ b/examples/l3fwd-power/Makefile @@ -1,11 +1,11 @@ # SPDX-License-Identifier: BSD-3-Clause -# Copyright(c) 2010-2014 Intel Corporation +# Copyright(c) 2010-2018 Intel Corporation # binary name APP = l3fwd-power # all source are stored in SRCS-y -SRCS-y := main.c +SRCS-y := main.c perf_core.c # Build using pkg-config variables if possible $(shell pkg-config --exists libdpdk) @@ -48,7 +48,7 @@ RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk -ifneq ($(CONFIG_RTE_EXEC_ENV),"linuxapp") +ifneq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) $(info This application can only operate in a linuxapp environment, \ please change the definition of the RTE_TARGET environment variable) all: diff --git a/examples/l3fwd-power/main.c b/examples/l3fwd-power/main.c index 596d6454..d15cd520 100644 --- a/examples/l3fwd-power/main.c +++ b/examples/l3fwd-power/main.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2016 Intel Corporation + * Copyright(c) 2010-2018 Intel Corporation */ #include <stdio.h> @@ -44,6 +44,9 @@ #include <rte_power.h> #include <rte_spinlock.h> +#include "perf_core.h" +#include "main.h" + #define RTE_LOGTYPE_L3FWD_POWER RTE_LOGTYPE_USER1 #define MAX_PKT_BURST 32 @@ -155,14 +158,7 @@ struct lcore_rx_queue { #define MAX_RX_QUEUE_INTERRUPT_PER_PORT 16 -#define MAX_LCORE_PARAMS 1024 -struct lcore_params { - uint16_t port_id; - uint8_t queue_id; - uint8_t lcore_id; -} __rte_cache_aligned; - -static struct lcore_params lcore_params_array[MAX_LCORE_PARAMS]; +struct lcore_params lcore_params_array[MAX_LCORE_PARAMS]; static struct lcore_params lcore_params_array_default[] = { {0, 0, 2}, {0, 1, 2}, @@ -175,8 +171,8 @@ static struct lcore_params lcore_params_array_default[] = { {3, 1, 3}, }; -static struct lcore_params * lcore_params = lcore_params_array_default; -static uint16_t nb_lcore_params = sizeof(lcore_params_array_default) / +struct lcore_params *lcore_params = lcore_params_array_default; +uint16_t nb_lcore_params = sizeof(lcore_params_array_default) / sizeof(lcore_params_array_default[0]); static struct rte_eth_conf port_conf = { @@ -184,7 +180,6 @@ static struct rte_eth_conf port_conf = { .mq_mode = ETH_MQ_RX_RSS, .max_rx_pkt_len = ETHER_MAX_LEN, .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = (DEV_RX_OFFLOAD_CRC_STRIP | DEV_RX_OFFLOAD_CHECKSUM), }, @@ -1121,10 +1116,15 @@ print_usage(const char *prgname) { printf ("%s [EAL options] -- -p PORTMASK -P" " [--config (port,queue,lcore)[,(port,queue,lcore]]" + " [--high-perf-cores CORELIST" + " [--perf-config (port,queue,hi_perf,lcore_index)[,(port,queue,hi_perf,lcore_index]]" " [--enable-jumbo [--max-pkt-len PKTLEN]]\n" " -p PORTMASK: hexadecimal bitmask of ports to configure\n" " -P : enable promiscuous mode\n" " --config (port,queue,lcore): rx queues configuration\n" + " --high-perf-cores CORELIST: list of high performance cores\n" + " --perf-config: similar as config, cores specified as indices" + " for bins containing high or regular performance cores\n" " --no-numa: optional, disable numa awareness\n" " --enable-jumbo: enable jumbo frame" " which max packet len is PKTLEN in decimal (64-9600)\n" @@ -1234,6 +1234,8 @@ parse_args(int argc, char **argv) char *prgname = argv[0]; static struct option lgopts[] = { {"config", 1, 0, 0}, + {"perf-config", 1, 0, 0}, + {"high-perf-cores", 1, 0, 0}, {"no-numa", 0, 0, 0}, {"enable-jumbo", 0, 0, 0}, {CMD_LINE_OPT_PARSE_PTYPE, 0, 0, 0}, @@ -1272,6 +1274,26 @@ parse_args(int argc, char **argv) } if (!strncmp(lgopts[option_index].name, + "perf-config", 11)) { + ret = parse_perf_config(optarg); + if (ret) { + printf("invalid perf-config\n"); + print_usage(prgname); + return -1; + } + } + + if (!strncmp(lgopts[option_index].name, + "high-perf-cores", 15)) { + ret = parse_perf_core_list(optarg); + if (ret) { + printf("invalid high-perf-cores\n"); + print_usage(prgname); + return -1; + } + } + + if (!strncmp(lgopts[option_index].name, "no-numa", 7)) { printf("numa is disabled \n"); numa_on = 0; @@ -1609,6 +1631,23 @@ static int check_ptype(uint16_t portid) } +static int +init_power_library(void) +{ + int ret = 0, lcore_id; + for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) { + if (rte_lcore_is_enabled(lcore_id)) { + /* init power management library */ + ret = rte_power_init(lcore_id); + if (ret) + RTE_LOG(ERR, POWER, + "Library initialization failed on core %u\n", + lcore_id); + } + } + return ret; +} + int main(int argc, char **argv) { @@ -1643,6 +1682,12 @@ main(int argc, char **argv) if (ret < 0) rte_exit(EXIT_FAILURE, "Invalid L3FWD parameters\n"); + if (init_power_library()) + rte_exit(EXIT_FAILURE, "init_power_library failed\n"); + + if (update_lcore_params() < 0) + rte_exit(EXIT_FAILURE, "update_lcore_params failed\n"); + if (check_lcore_params() < 0) rte_exit(EXIT_FAILURE, "check_lcore_params failed\n"); @@ -1693,6 +1738,18 @@ main(int argc, char **argv) if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) local_port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MBUF_FAST_FREE; + + local_port_conf.rx_adv_conf.rss_conf.rss_hf &= + dev_info.flow_type_rss_offloads; + if (local_port_conf.rx_adv_conf.rss_conf.rss_hf != + port_conf.rx_adv_conf.rss_conf.rss_hf) { + printf("Port %u modified RSS hash function based on hardware support," + "requested:%#"PRIx64" configured:%#"PRIx64"\n", + portid, + port_conf.rx_adv_conf.rss_conf.rss_hf, + local_port_conf.rx_adv_conf.rss_conf.rss_hf); + } + ret = rte_eth_dev_configure(portid, nb_rx_queue, (uint16_t)n_tx_queue, &local_port_conf); if (ret < 0) @@ -1750,7 +1807,6 @@ main(int argc, char **argv) fflush(stdout); txconf = &dev_info.default_txconf; - txconf->txq_flags = ETH_TXQ_FLAGS_IGNORE; txconf->offloads = local_port_conf.txmode.offloads; ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd, socketid, txconf); @@ -1773,12 +1829,6 @@ main(int argc, char **argv) if (rte_lcore_is_enabled(lcore_id) == 0) continue; - /* init power management library */ - ret = rte_power_init(lcore_id); - if (ret) - RTE_LOG(ERR, POWER, - "Library initialization failed on core %u\n", lcore_id); - /* init timer structures for each enabled lcore */ rte_timer_init(&power_timers[lcore_id]); hz = rte_get_timer_hz(); diff --git a/examples/l3fwd-power/main.h b/examples/l3fwd-power/main.h new file mode 100644 index 00000000..258de98f --- /dev/null +++ b/examples/l3fwd-power/main.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#ifndef _MAIN_H_ +#define _MAIN_H_ + + +#define MAX_LCORE_PARAMS 1024 +struct lcore_params { + uint16_t port_id; + uint8_t queue_id; + uint8_t lcore_id; +} __rte_cache_aligned; + +extern struct lcore_params *lcore_params; +extern uint16_t nb_lcore_params; +extern struct lcore_params lcore_params_array[]; + +#endif /* _MAIN_H_ */ diff --git a/examples/l3fwd-power/meson.build b/examples/l3fwd-power/meson.build index f633a0f1..20c80543 100644 --- a/examples/l3fwd-power/meson.build +++ b/examples/l3fwd-power/meson.build @@ -1,5 +1,5 @@ # SPDX-License-Identifier: BSD-3-Clause -# Copyright(c) 2017 Intel Corporation +# Copyright(c) 2018 Intel Corporation # meson file, for building this example as part of a main DPDK build. # @@ -11,5 +11,5 @@ if host_machine.system() != 'linux' endif deps += ['power', 'timer', 'lpm', 'hash'] sources = files( - 'main.c' + 'main.c', 'perf_core.c' ) diff --git a/examples/l3fwd-power/perf_core.c b/examples/l3fwd-power/perf_core.c new file mode 100644 index 00000000..83948ea2 --- /dev/null +++ b/examples/l3fwd-power/perf_core.c @@ -0,0 +1,230 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#include <stdio.h> +#include <string.h> + +#include <rte_common.h> +#include <rte_memory.h> +#include <rte_lcore.h> +#include <rte_power.h> +#include <rte_string_fns.h> + +#include "perf_core.h" +#include "main.h" + + +static uint16_t hp_lcores[RTE_MAX_LCORE]; +static uint16_t nb_hp_lcores; + +struct perf_lcore_params { + uint16_t port_id; + uint8_t queue_id; + uint8_t high_perf; + uint8_t lcore_idx; +} __rte_cache_aligned; + +static struct perf_lcore_params prf_lc_prms[MAX_LCORE_PARAMS]; +static uint16_t nb_prf_lc_prms; + +int +update_lcore_params(void) +{ + uint8_t non_perf_lcores[RTE_MAX_LCORE]; + uint16_t nb_non_perf_lcores = 0; + int i, j, ret; + + /* if perf-config option was not used do nothing */ + if (nb_prf_lc_prms == 0) + return 0; + + /* if high-perf-cores option was not used query every available core */ + if (nb_hp_lcores == 0) { + for (i = 0; i < RTE_MAX_LCORE; i++) { + if (rte_lcore_is_enabled(i)) { + struct rte_power_core_capabilities caps; + ret = rte_power_get_capabilities(i, &caps); + if (ret == 0 && caps.turbo) { + hp_lcores[nb_hp_lcores] = i; + nb_hp_lcores++; + } + } + } + } + + /* create a list on non high performance cores*/ + for (i = 0; i < RTE_MAX_LCORE; i++) { + if (rte_lcore_is_enabled(i)) { + int hp = 0; + for (j = 0; j < nb_hp_lcores; j++) { + if (hp_lcores[j] == i) { + hp = 1; + break; + } + } + if (!hp) + non_perf_lcores[nb_non_perf_lcores++] = i; + } + } + + /* update the lcore config */ + for (i = 0; i < nb_prf_lc_prms; i++) { + int lcore = -1; + if (prf_lc_prms[i].high_perf) { + if (prf_lc_prms[i].lcore_idx < nb_hp_lcores) + lcore = hp_lcores[prf_lc_prms[i].lcore_idx]; + } else { + if (prf_lc_prms[i].lcore_idx < nb_non_perf_lcores) + lcore = + non_perf_lcores[prf_lc_prms[i].lcore_idx]; + } + + if (lcore < 0) { + printf("Performance cores configuration error\n"); + return -1; + } + + lcore_params_array[i].lcore_id = lcore; + lcore_params_array[i].queue_id = prf_lc_prms[i].queue_id; + lcore_params_array[i].port_id = prf_lc_prms[i].port_id; + } + + lcore_params = lcore_params_array; + nb_lcore_params = nb_prf_lc_prms; + + printf("Updated performance core configuration\n"); + for (i = 0; i < nb_prf_lc_prms; i++) + printf("\t(%d,%d,%d)\n", lcore_params[i].port_id, + lcore_params[i].queue_id, + lcore_params[i].lcore_id); + + return 0; +} + +int +parse_perf_config(const char *q_arg) +{ + char s[256]; + const char *p, *p0 = q_arg; + char *end; + enum fieldnames { + FLD_PORT = 0, + FLD_QUEUE, + FLD_LCORE_HP, + FLD_LCORE_IDX, + _NUM_FLD + }; + unsigned long int_fld[_NUM_FLD]; + char *str_fld[_NUM_FLD]; + int i; + unsigned int size; + + nb_prf_lc_prms = 0; + + while ((p = strchr(p0, '(')) != NULL) { + ++p; + p0 = strchr(p, ')'); + if (p0 == NULL) + return -1; + + size = p0 - p; + if (size >= sizeof(s)) + return -1; + + snprintf(s, sizeof(s), "%.*s", size, p); + if (rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ',') != + _NUM_FLD) + return -1; + for (i = 0; i < _NUM_FLD; i++) { + errno = 0; + int_fld[i] = strtoul(str_fld[i], &end, 0); + if (errno != 0 || end == str_fld[i] || int_fld[i] > 255) + return -1; + } + if (nb_prf_lc_prms >= MAX_LCORE_PARAMS) { + printf("exceeded max number of lcore params: %hu\n", + nb_prf_lc_prms); + return -1; + } + prf_lc_prms[nb_prf_lc_prms].port_id = + (uint8_t)int_fld[FLD_PORT]; + prf_lc_prms[nb_prf_lc_prms].queue_id = + (uint8_t)int_fld[FLD_QUEUE]; + prf_lc_prms[nb_prf_lc_prms].high_perf = + !!(uint8_t)int_fld[FLD_LCORE_HP]; + prf_lc_prms[nb_prf_lc_prms].lcore_idx = + (uint8_t)int_fld[FLD_LCORE_IDX]; + ++nb_prf_lc_prms; + } + + return 0; +} + +int +parse_perf_core_list(const char *corelist) +{ + int i, idx = 0; + unsigned int count = 0; + char *end = NULL; + int min, max; + + if (corelist == NULL) { + printf("invalid core list\n"); + return -1; + } + + + /* Remove all blank characters ahead and after */ + while (isblank(*corelist)) + corelist++; + i = strlen(corelist); + while ((i > 0) && isblank(corelist[i - 1])) + i--; + + /* Get list of cores */ + min = RTE_MAX_LCORE; + do { + while (isblank(*corelist)) + corelist++; + if (*corelist == '\0') + return -1; + errno = 0; + idx = strtoul(corelist, &end, 10); + if (errno || end == NULL) + return -1; + while (isblank(*end)) + end++; + if (*end == '-') { + min = idx; + } else if ((*end == ',') || (*end == '\0')) { + max = idx; + if (min == RTE_MAX_LCORE) + min = idx; + for (idx = min; idx <= max; idx++) { + hp_lcores[count] = idx; + count++; + } + min = RTE_MAX_LCORE; + } else { + printf("invalid core list\n"); + return -1; + } + corelist = end + 1; + } while (*end != '\0'); + + if (count == 0) { + printf("invalid core list\n"); + return -1; + } + + nb_hp_lcores = count; + + printf("Configured %d high performance cores\n", nb_hp_lcores); + for (i = 0; i < nb_hp_lcores; i++) + printf("\tHigh performance core %d %d\n", + i, hp_lcores[i]); + + return 0; +} + diff --git a/examples/l3fwd-power/perf_core.h b/examples/l3fwd-power/perf_core.h new file mode 100644 index 00000000..7b7b747b --- /dev/null +++ b/examples/l3fwd-power/perf_core.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2018 Intel Corporation + */ + +#ifndef _PERF_CORE_H_ +#define _PERF_CORE_H_ + +int parse_perf_config(const char *q_arg); +int parse_perf_core_list(const char *corelist); +int update_lcore_params(void); + +#endif /* _PERF_CORE_H_ */ diff --git a/examples/l3fwd-vf/main.c b/examples/l3fwd-vf/main.c index aaafb7bc..5edd91a7 100644 --- a/examples/l3fwd-vf/main.c +++ b/examples/l3fwd-vf/main.c @@ -161,7 +161,6 @@ static struct rte_eth_conf port_conf = { .mq_mode = ETH_MQ_RX_RSS, .max_rx_pkt_len = ETHER_MAX_LEN, .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = (DEV_RX_OFFLOAD_CRC_STRIP | DEV_RX_OFFLOAD_CHECKSUM), }, @@ -981,6 +980,18 @@ main(int argc, char **argv) if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) local_port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MBUF_FAST_FREE; + + local_port_conf.rx_adv_conf.rss_conf.rss_hf &= + dev_info.flow_type_rss_offloads; + if (local_port_conf.rx_adv_conf.rss_conf.rss_hf != + port_conf.rx_adv_conf.rss_conf.rss_hf) { + printf("Port %u modified RSS hash function based on hardware support," + "requested:%#"PRIx64" configured:%#"PRIx64"\n", + portid, + port_conf.rx_adv_conf.rss_conf.rss_hf, + local_port_conf.rx_adv_conf.rss_conf.rss_hf); + } + ret = rte_eth_dev_configure(portid, nb_rx_queue, n_tx_queue, &local_port_conf); if (ret < 0) @@ -1009,7 +1020,6 @@ main(int argc, char **argv) fflush(stdout); txconf = &dev_info.default_txconf; - txconf->txq_flags = ETH_TXQ_FLAGS_IGNORE; txconf->offloads = local_port_conf.txmode.offloads; ret = rte_eth_tx_queue_setup(portid, 0, nb_txd, socketid, txconf); diff --git a/examples/l3fwd/l3fwd_em.c b/examples/l3fwd/l3fwd_em.c index 9dc3b8c4..fa8f82be 100644 --- a/examples/l3fwd/l3fwd_em.c +++ b/examples/l3fwd/l3fwd_em.c @@ -18,7 +18,6 @@ #include <rte_debug.h> #include <rte_ether.h> #include <rte_ethdev.h> -#include <rte_mempool.h> #include <rte_cycles.h> #include <rte_mbuf.h> #include <rte_ip.h> diff --git a/examples/l3fwd/l3fwd_lpm.c b/examples/l3fwd/l3fwd_lpm.c index a747126a..b1dc195a 100644 --- a/examples/l3fwd/l3fwd_lpm.c +++ b/examples/l3fwd/l3fwd_lpm.c @@ -17,7 +17,6 @@ #include <rte_debug.h> #include <rte_ether.h> #include <rte_ethdev.h> -#include <rte_mempool.h> #include <rte_cycles.h> #include <rte_mbuf.h> #include <rte_ip.h> diff --git a/examples/l3fwd/main.c b/examples/l3fwd/main.c index bf7dbd81..ab019b9e 100644 --- a/examples/l3fwd/main.c +++ b/examples/l3fwd/main.c @@ -120,7 +120,6 @@ static struct rte_eth_conf port_conf = { .mq_mode = ETH_MQ_RX_RSS, .max_rx_pkt_len = ETHER_MAX_LEN, .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = (DEV_RX_OFFLOAD_CRC_STRIP | DEV_RX_OFFLOAD_CHECKSUM), }, @@ -861,6 +860,18 @@ main(int argc, char **argv) if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) local_port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MBUF_FAST_FREE; + + local_port_conf.rx_adv_conf.rss_conf.rss_hf &= + dev_info.flow_type_rss_offloads; + if (local_port_conf.rx_adv_conf.rss_conf.rss_hf != + port_conf.rx_adv_conf.rss_conf.rss_hf) { + printf("Port %u modified RSS hash function based on hardware support," + "requested:%#"PRIx64" configured:%#"PRIx64"\n", + portid, + port_conf.rx_adv_conf.rss_conf.rss_hf, + local_port_conf.rx_adv_conf.rss_conf.rss_hf); + } + ret = rte_eth_dev_configure(portid, nb_rx_queue, (uint16_t)n_tx_queue, &local_port_conf); if (ret < 0) @@ -909,7 +920,6 @@ main(int argc, char **argv) fflush(stdout); txconf = &dev_info.default_txconf; - txconf->txq_flags = ETH_TXQ_FLAGS_IGNORE; txconf->offloads = local_port_conf.txmode.offloads; ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd, socketid, txconf); diff --git a/examples/link_status_interrupt/main.c b/examples/link_status_interrupt/main.c index f5689568..3b732076 100644 --- a/examples/link_status_interrupt/main.c +++ b/examples/link_status_interrupt/main.c @@ -79,7 +79,6 @@ struct rte_eth_dev_tx_buffer *tx_buffer[RTE_MAX_ETHPORTS]; static struct rte_eth_conf port_conf = { .rxmode = { .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = DEV_RX_OFFLOAD_CRC_STRIP, }, .txmode = { @@ -653,7 +652,6 @@ main(int argc, char **argv) /* init one TX queue logical core on each port */ fflush(stdout); txq_conf = dev_info.default_txconf; - txq_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txq_conf.offloads = local_port_conf.txmode.offloads; ret = rte_eth_tx_queue_setup(portid, 0, nb_txd, rte_eth_dev_socket_id(portid), diff --git a/examples/load_balancer/init.c b/examples/load_balancer/init.c index 8d8dbe61..f2045f23 100644 --- a/examples/load_balancer/init.c +++ b/examples/load_balancer/init.c @@ -45,7 +45,6 @@ static struct rte_eth_conf port_conf = { .rxmode = { .mq_mode = ETH_MQ_RX_RSS, .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = (DEV_RX_OFFLOAD_CHECKSUM | DEV_RX_OFFLOAD_CRC_STRIP), }, @@ -417,6 +416,18 @@ app_init_nics(void) if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) local_port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MBUF_FAST_FREE; + + local_port_conf.rx_adv_conf.rss_conf.rss_hf &= + dev_info.flow_type_rss_offloads; + if (local_port_conf.rx_adv_conf.rss_conf.rss_hf != + port_conf.rx_adv_conf.rss_conf.rss_hf) { + printf("Port %u modified RSS hash function based on hardware support," + "requested:%#"PRIx64" configured:%#"PRIx64"\n", + port, + port_conf.rx_adv_conf.rss_conf.rss_hf, + local_port_conf.rx_adv_conf.rss_conf.rss_hf); + } + ret = rte_eth_dev_configure( port, (uint8_t) n_rx_queues, @@ -466,7 +477,6 @@ app_init_nics(void) } txq_conf = dev_info.default_txconf; - txq_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txq_conf.offloads = local_port_conf.txmode.offloads; /* Init TX queues */ if (app.nic_tx_port_mask[port] == 1) { diff --git a/examples/meson.build b/examples/meson.build index 3d156849..4ee7a111 100644 --- a/examples/meson.build +++ b/examples/meson.build @@ -18,12 +18,17 @@ else examples = get_option('examples').split(',') allow_skips = false # error out if we can't build a requested app endif +default_cflags = machine_args +if cc.has_argument('-Wno-format-truncation') + default_cflags += '-Wno-format-truncation' +endif foreach example: examples name = example build = true sources = [] allow_experimental_apis = false - cflags = machine_args + cflags = default_cflags + ext_deps = [execinfo] includes = [include_directories(example)] deps = ['eal', 'mempool', 'net', 'mbuf', 'ethdev', 'cmdline'] diff --git a/examples/multi_process/client_server_mp/mp_server/Makefile b/examples/multi_process/client_server_mp/mp_server/Makefile index af7246e6..9c1caae7 100644 --- a/examples/multi_process/client_server_mp/mp_server/Makefile +++ b/examples/multi_process/client_server_mp/mp_server/Makefile @@ -10,7 +10,7 @@ RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk -ifneq ($(CONFIG_RTE_EXEC_ENV),"linuxapp") +ifneq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) $(error This application can only operate in a linuxapp environment, \ please change the definition of the RTE_TARGET environment variable) endif diff --git a/examples/multi_process/l2fwd_fork/Makefile b/examples/multi_process/l2fwd_fork/Makefile deleted file mode 100644 index b65582ef..00000000 --- a/examples/multi_process/l2fwd_fork/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -# SPDX-License-Identifier: BSD-3-Clause -# Copyright(c) 2010-2014 Intel Corporation - -# binary name -APP = l2fwd-fork - -# all source are stored in SRCS-y -SRCS-y := main.c flib.c - -ifeq ($(RTE_SDK),) -$(error "Please define RTE_SDK environment variable") -endif - -# Default target, can be overridden by command line or environment -RTE_TARGET ?= x86_64-native-linuxapp-gcc - -include $(RTE_SDK)/mk/rte.vars.mk - -CFLAGS += -O3 -CFLAGS += $(WERROR_FLAGS) - -include $(RTE_SDK)/mk/rte.extapp.mk diff --git a/examples/multi_process/l2fwd_fork/flib.c b/examples/multi_process/l2fwd_fork/flib.c deleted file mode 100644 index 52c6152b..00000000 --- a/examples/multi_process/l2fwd_fork/flib.c +++ /dev/null @@ -1,280 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2014 Intel Corporation - */ -#include <unistd.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <stdint.h> -#include <inttypes.h> -#include <sys/types.h> -#include <sys/queue.h> -#include <sys/wait.h> -#include <sys/prctl.h> -#include <netinet/in.h> -#include <setjmp.h> -#include <stdarg.h> -#include <ctype.h> -#include <errno.h> -#include <getopt.h> -#include <dirent.h> -#include <signal.h> - -#include <rte_common.h> -#include <rte_log.h> -#include <rte_malloc.h> -#include <rte_memory.h> -#include <rte_memcpy.h> -#include <rte_eal.h> -#include <rte_launch.h> -#include <rte_atomic.h> -#include <rte_cycles.h> -#include <rte_prefetch.h> -#include <rte_lcore.h> -#include <rte_per_lcore.h> -#include <rte_branch_prediction.h> -#include <rte_interrupts.h> -#include <rte_random.h> -#include <rte_debug.h> -#include <rte_ether.h> -#include <rte_ethdev.h> -#include <rte_mempool.h> -#include <rte_mbuf.h> -#include <rte_string_fns.h> - -#include "flib.h" - -#define SIG_PARENT_EXIT SIGUSR1 - -struct lcore_stat { - pid_t pid; /**< pthread identifier */ - lcore_function_t *f; /**< function to call */ - void *arg; /**< argument of function */ - slave_exit_notify *cb_fn; -} __rte_cache_aligned; - - -static struct lcore_stat *core_cfg; -static uint16_t *lcore_cfg = NULL; - -/* signal handler to be notified after parent leaves */ -static void -sighand_parent_exit(int sig) -{ - printf("lcore = %u : Find parent leaves, sig=%d\n", rte_lcore_id(), - sig); - printf("Child leaving\n"); - exit(0); - - return; -} - -/** - * Real function entrance ran in slave process - **/ -static int -slave_proc_func(void) -{ - struct rte_config *config; - unsigned slave_id = rte_lcore_id(); - struct lcore_stat *cfg = &core_cfg[slave_id]; - - if (prctl(PR_SET_PDEATHSIG, SIG_PARENT_EXIT, 0, 0, 0, 0) != 0) - printf("Warning: Slave can't register for being notified in" - "case master process exited\n"); - else { - struct sigaction act; - memset(&act, 0 , sizeof(act)); - act.sa_handler = sighand_parent_exit; - if (sigaction(SIG_PARENT_EXIT, &act, NULL) != 0) - printf("Fail to register signal handler:%d\n", SIG_PARENT_EXIT); - } - - /* Set slave process to SECONDARY to avoid operation like dev_start/stop etc */ - config = rte_eal_get_configuration(); - if (NULL == config) - printf("Warning:Can't get rte_config\n"); - else - config->process_type = RTE_PROC_SECONDARY; - - printf("Core %u is ready (pid=%d)\n", slave_id, (int)cfg->pid); - - exit(cfg->f(cfg->arg)); -} - -/** - * function entrance ran in master thread, which will spawn slave process and wait until - * specific slave exited. - **/ -static int -lcore_func(void *arg __attribute__((unused))) -{ - unsigned slave_id = rte_lcore_id(); - struct lcore_stat *cfg = &core_cfg[slave_id]; - int pid, stat; - - if (rte_get_master_lcore() == slave_id) - return cfg->f(cfg->arg); - - /* fork a slave process */ - pid = fork(); - - if (pid == -1) { - printf("Failed to fork\n"); - return -1; - } else if (pid == 0) /* child */ - return slave_proc_func(); - else { /* parent */ - cfg->pid = pid; - - waitpid(pid, &stat, 0); - - cfg->pid = 0; - cfg->f = NULL; - cfg->arg = NULL; - /* Notify slave's exit if applicable */ - if(cfg->cb_fn) - cfg->cb_fn(slave_id, stat); - return stat; - } -} - -static int -lcore_id_init(void) -{ - int i; - /* Setup lcore ID allocation map */ - lcore_cfg = rte_zmalloc("LCORE_ID_MAP", - sizeof(uint16_t) * RTE_MAX_LCORE, - RTE_CACHE_LINE_SIZE); - - if(lcore_cfg == NULL) - rte_panic("Failed to malloc\n"); - - for (i = 0; i < RTE_MAX_LCORE; i++) { - if (rte_lcore_is_enabled(i)) - lcore_cfg[i] = 1; - } - return 0; -} - -int -flib_assign_lcore_id(void) -{ - unsigned i; - int ret; - - /** - * thread assigned a lcore id previously, or a slave thread. But still have - * a bug here: If the core mask includes core 0, and that core call this - * function, it still can get a new lcore id. - **/ - if (rte_lcore_id() != 0) - return -1; - - do { - /* Find a lcore id not used yet, avoid to use lcore ID 0 */ - for (i = 1; i < RTE_MAX_LCORE; i++) { - if (lcore_cfg[i] == 0) - break; - } - if (i == RTE_MAX_LCORE) - return -1; - - /* Assign new lcore id to this thread */ - - ret = rte_atomic16_cmpset(&lcore_cfg[i], 0, 1); - } while (unlikely(ret == 0)); - - RTE_PER_LCORE(_lcore_id) = i; - return i; -} - -void -flib_free_lcore_id(unsigned lcore_id) -{ - /* id is not valid or belongs to pinned core id */ - if (lcore_id >= RTE_MAX_LCORE || lcore_id == 0 || - rte_lcore_is_enabled(lcore_id)) - return; - - lcore_cfg[lcore_id] = 0; -} - -int -flib_register_slave_exit_notify(unsigned slave_id, - slave_exit_notify *cb) -{ - if (cb == NULL) - return -EFAULT; - - if (!rte_lcore_is_enabled(slave_id)) - return -ENOENT; - - core_cfg[slave_id].cb_fn = cb; - - return 0; -} - -enum slave_stat -flib_query_slave_status(unsigned slave_id) -{ - if (!rte_lcore_is_enabled(slave_id)) - return ST_FREEZE; - /* pid only be set when slave process spawned */ - if (core_cfg[slave_id].pid != 0) - return ST_RUN; - else - return ST_IDLE; -} - -int -flib_remote_launch(lcore_function_t *f, - void *arg, unsigned slave_id) -{ - if (f == NULL) - return -1; - - if (!rte_lcore_is_enabled(slave_id)) - return -1; - - /* Wait until specific lcore state change to WAIT */ - rte_eal_wait_lcore(slave_id); - - core_cfg[slave_id].f = f; - core_cfg[slave_id].arg = arg; - - return rte_eal_remote_launch(lcore_func, NULL, slave_id); -} - -int -flib_mp_remote_launch(lcore_function_t *f, void *arg, - enum rte_rmt_call_master_t call_master) -{ - int i; - - RTE_LCORE_FOREACH_SLAVE(i) { - core_cfg[i].arg = arg; - core_cfg[i].f = f; - } - - return rte_eal_mp_remote_launch(lcore_func, NULL, call_master); -} - -int -flib_init(void) -{ - if ((core_cfg = rte_zmalloc("core_cfg", - sizeof(struct lcore_stat) * RTE_MAX_LCORE, - RTE_CACHE_LINE_SIZE)) == NULL ) { - printf("rte_zmalloc failed\n"); - return -1; - } - - if (lcore_id_init() != 0) { - printf("lcore_id_init failed\n"); - return -1; - } - - return 0; -} diff --git a/examples/multi_process/l2fwd_fork/flib.h b/examples/multi_process/l2fwd_fork/flib.h deleted file mode 100644 index 8bc13a1f..00000000 --- a/examples/multi_process/l2fwd_fork/flib.h +++ /dev/null @@ -1,120 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2014 Intel Corporation - */ - -#ifndef __FLIB_H -#define __FLIB_H - -/* callback function pointer when specific slave leaves */ -typedef void (slave_exit_notify)(unsigned slaveid, int stat); - -enum slave_stat{ - ST_FREEZE = 1, - ST_IDLE, - ST_RUN, - ST_ZOMBIE, /* Not implemented yet */ -}; - -/** - * Initialize the fork lib. - * - * @return - * - 0 : fork lib initialized successfully - * - -1 : fork lib initialized failed - */ -int flib_init(void); - -/** - * Check that every SLAVE lcores are in WAIT state, then call - * flib_remote_launch() for all of them. If call_master is true - * (set to CALL_MASTER), also call the function on the master lcore. - * - * @param f: - * function pointer need to run - * @param arg: - * argument for f to carry - * @param call_master - * - SKIP_MASTER : only launch function on slave lcores - * - CALL_MASTER : launch function on master and slave lcores - * @return - * - 0 : function execute successfully - * - -1 : function execute failed - */ -int flib_mp_remote_launch(lcore_function_t *f, - void *arg, enum rte_rmt_call_master_t call_master); - -/** - * Send a message to a slave lcore identified by slave_id to call a - * function f with argument arg. - * - * @param f: - * function pointer need to run - * @param arg: - * argument for f to carry - * @param slave_id - * slave lcore id to run on - * @return - * - 0 : function execute successfully - * - -1 : function execute failed - */ -int flib_remote_launch(lcore_function_t *f, - void *arg, unsigned slave_id); - -/** - * Query the running stat for specific slave, wont' work in with master id - * - * @param slave_id: - * lcore id which should not be master id - * @return - * - ST_FREEZE : lcore is not in enabled core mask - * - ST_IDLE : lcore is idle - * - ST_RUN : lcore is running something - */ -enum slave_stat -flib_query_slave_status(unsigned slave_id); - -/** - * Register a callback function to be notified in case specific slave exit. - * - * @param slave_id: - * lcore id which should not be master id - * @param cb: - * callback pointer to register - * @return - * - 0 : function execute successfully - * - -EFAULT : argument error - * - -ENOENT : slave_id not correct - */ -int flib_register_slave_exit_notify(unsigned slave_id, - slave_exit_notify *cb); - -/** - * Assign a lcore ID to non-slave thread. Non-slave thread refers to thread that - * not created by function rte_eal_remote_launch or rte_eal_mp_remote_launch. - * These threads can either bind lcore or float among different lcores. - * This lcore ID will be unique in multi-thread or multi-process DPDK running - * environment, then it can benefit from using the cache mechanism provided in - * mempool library. - * After calling successfully, use rte_lcore_id() to get the assigned lcore ID, but - * other lcore funtions can't guarantee to work correctly. - * - * @return - * - -1 : can't assign a lcore id with 3 possibilities. - * - it's not non-slave thread. - * - it had assign a lcore id previously - * - the lcore id is running out. - * - > 0 : the assigned lcore id. - */ -int flib_assign_lcore_id(void); - -/** - * Free the lcore_id that assigned in flib_assign_lcore_id(). - * call it in case non-slave thread is leaving or left. - * - * @param lcore_id - * The identifier of the lcore, which MUST be between 1 and - * RTE_MAX_LCORE-1. - */ -void flib_free_lcore_id(unsigned lcore_id); - -#endif /* __FLIB_H */ diff --git a/examples/multi_process/l2fwd_fork/main.c b/examples/multi_process/l2fwd_fork/main.c deleted file mode 100644 index 94318ab6..00000000 --- a/examples/multi_process/l2fwd_fork/main.c +++ /dev/null @@ -1,1259 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * Copyright(c) 2010-2016 Intel Corporation - */ -#define _GNU_SOURCE -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <string.h> -#include <stdint.h> -#include <sched.h> -#include <inttypes.h> -#include <sys/types.h> -#include <sys/queue.h> -#include <netinet/in.h> -#include <setjmp.h> -#include <stdarg.h> -#include <ctype.h> -#include <errno.h> -#include <getopt.h> - -#include <rte_common.h> -#include <rte_log.h> -#include <rte_memory.h> -#include <rte_memcpy.h> -#include <rte_eal.h> -#include <rte_launch.h> -#include <rte_atomic.h> -#include <rte_spinlock.h> -#include <rte_cycles.h> -#include <rte_prefetch.h> -#include <rte_lcore.h> -#include <rte_per_lcore.h> -#include <rte_branch_prediction.h> -#include <rte_interrupts.h> -#include <rte_random.h> -#include <rte_debug.h> -#include <rte_ether.h> -#include <rte_ethdev.h> -#include <rte_ring.h> -#include <rte_mempool.h> -#include <rte_mbuf.h> -#include <rte_malloc.h> - -#include "flib.h" - -#define RTE_LOGTYPE_L2FWD RTE_LOGTYPE_USER1 -#define MBUF_NAME "mbuf_pool_%d" -#define MBUF_DATA_SIZE RTE_MBUF_DEFAULT_BUF_SIZE -#define NB_MBUF 8192 -#define RING_MASTER_NAME "l2fwd_ring_m2s_" -#define RING_SLAVE_NAME "l2fwd_ring_s2m_" -#define MAX_NAME_LEN 32 -/* RECREATE flag indicate needs initialize resource and launch slave_core again */ -#define SLAVE_RECREATE_FLAG 0x1 -/* RESTART flag indicate needs restart port and send START command again */ -#define SLAVE_RESTART_FLAG 0x2 -#define INVALID_MAPPING_ID ((unsigned)LCORE_ID_ANY) -/* Maximum message buffer per slave */ -#define NB_CORE_MSGBUF 32 -enum l2fwd_cmd{ - CMD_START, - CMD_STOP, -}; - -#define MAX_PKT_BURST 32 -#define BURST_TX_DRAIN_US 100 /* TX drain every ~100us */ - -/* - * Configurable number of RX/TX ring descriptors - */ -#define RTE_TEST_RX_DESC_DEFAULT 1024 -#define RTE_TEST_TX_DESC_DEFAULT 1024 -static uint16_t nb_rxd = RTE_TEST_RX_DESC_DEFAULT; -static uint16_t nb_txd = RTE_TEST_TX_DESC_DEFAULT; - -/* ethernet addresses of ports */ -static struct ether_addr l2fwd_ports_eth_addr[RTE_MAX_ETHPORTS]; - -/* mask of enabled ports */ -static uint32_t l2fwd_enabled_port_mask = 0; - -/* list of enabled ports */ -static uint32_t l2fwd_dst_ports[RTE_MAX_ETHPORTS]; - -static unsigned int l2fwd_rx_queue_per_lcore = 1; - -struct mbuf_table { - unsigned len; - struct rte_mbuf *m_table[MAX_PKT_BURST]; -}; - -#define MAX_RX_QUEUE_PER_LCORE 16 -#define MAX_TX_QUEUE_PER_PORT 16 -struct lcore_queue_conf { - unsigned n_rx_port; - unsigned rx_port_list[MAX_RX_QUEUE_PER_LCORE]; -} __rte_cache_aligned; -struct lcore_queue_conf lcore_queue_conf[RTE_MAX_LCORE]; - -struct rte_eth_dev_tx_buffer *tx_buffer[RTE_MAX_ETHPORTS]; - -struct lcore_resource_struct { - int enabled; /* Only set in case this lcore involved into packet forwarding */ - int flags; /* Set only slave need to restart or recreate */ - unsigned lcore_id; /* lcore ID */ - unsigned pair_id; /* dependency lcore ID on port */ - char ring_name[2][MAX_NAME_LEN]; - /* ring[0] for master send cmd, slave read */ - /* ring[1] for slave send ack, master read */ - struct rte_ring *ring[2]; - int port_num; /* Total port numbers */ - /* Port id for that lcore to receive packets */ - uint16_t port[RTE_MAX_ETHPORTS]; -}__attribute__((packed)) __rte_cache_aligned; - -static struct lcore_resource_struct lcore_resource[RTE_MAX_LCORE]; -static struct rte_mempool *message_pool; -static rte_spinlock_t res_lock = RTE_SPINLOCK_INITIALIZER; -/* use floating processes */ -static int float_proc = 0; -/* Save original cpu affinity */ -struct cpu_aff_arg{ - cpu_set_t set; - size_t size; -}cpu_aff; - -static const struct rte_eth_conf port_conf = { - .rxmode = { - .split_hdr_size = 0, - .ignore_offload_bitfield = 1, - .offloads = DEV_RX_OFFLOAD_CRC_STRIP, - }, - .txmode = { - .mq_mode = ETH_MQ_TX_NONE, - }, -}; - -static struct rte_mempool * l2fwd_pktmbuf_pool[RTE_MAX_ETHPORTS]; - -/* Per-port statistics struct */ -struct l2fwd_port_statistics { - uint64_t tx; - uint64_t rx; - uint64_t dropped; -} __rte_cache_aligned; -struct l2fwd_port_statistics *port_statistics; -/** - * pointer to lcore ID mapping array, used to return lcore id in case slave - * process exited unexpectedly, use only floating process option applied - **/ -unsigned *mapping_id; - -/* A tsc-based timer responsible for triggering statistics printout */ -#define TIMER_MILLISECOND 2000000ULL /* around 1ms at 2 Ghz */ -#define MAX_TIMER_PERIOD 86400 /* 1 day max */ -static int64_t timer_period = 10 * TIMER_MILLISECOND * 1000; /* default period is 10 seconds */ - -static int l2fwd_launch_one_lcore(void *dummy); - -/* Print out statistics on packets dropped */ -static void -print_stats(void) -{ - uint64_t total_packets_dropped, total_packets_tx, total_packets_rx; - unsigned portid; - - total_packets_dropped = 0; - total_packets_tx = 0; - total_packets_rx = 0; - - const char clr[] = { 27, '[', '2', 'J', '\0' }; - const char topLeft[] = { 27, '[', '1', ';', '1', 'H','\0' }; - - /* Clear screen and move to top left */ - printf("%s%s", clr, topLeft); - - printf("\nPort statistics ===================================="); - - for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) { - /* skip disabled ports */ - if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) - continue; - printf("\nStatistics for port %u ------------------------------" - "\nPackets sent: %24"PRIu64 - "\nPackets received: %20"PRIu64 - "\nPackets dropped: %21"PRIu64, - portid, - port_statistics[portid].tx, - port_statistics[portid].rx, - port_statistics[portid].dropped); - - total_packets_dropped += port_statistics[portid].dropped; - total_packets_tx += port_statistics[portid].tx; - total_packets_rx += port_statistics[portid].rx; - } - printf("\nAggregate statistics ===============================" - "\nTotal packets sent: %18"PRIu64 - "\nTotal packets received: %14"PRIu64 - "\nTotal packets dropped: %15"PRIu64, - total_packets_tx, - total_packets_rx, - total_packets_dropped); - printf("\n====================================================\n"); -} - -static int -clear_cpu_affinity(void) -{ - int s; - - s = sched_setaffinity(0, cpu_aff.size, &cpu_aff.set); - if (s != 0) { - printf("sched_setaffinity failed:%s\n", strerror(errno)); - return -1; - } - - return 0; -} - -static int -get_cpu_affinity(void) -{ - int s; - - cpu_aff.size = sizeof(cpu_set_t); - CPU_ZERO(&cpu_aff.set); - - s = sched_getaffinity(0, cpu_aff.size, &cpu_aff.set); - if (s != 0) { - printf("sched_getaffinity failed:%s\n", strerror(errno)); - return -1; - } - - return 0; -} - -/** - * This fnciton demonstrates the approach to create ring in first instance - * or re-attach an existed ring in later instance. - **/ -static struct rte_ring * -create_ring(const char *name, unsigned count, - int socket_id,unsigned flags) -{ - struct rte_ring *ring; - - if (name == NULL) - return NULL; - - /* If already create, just attached it */ - if (likely((ring = rte_ring_lookup(name)) != NULL)) - return ring; - - /* First call it, create one */ - return rte_ring_create(name, count, socket_id, flags); -} - -/* Malloc with rte_malloc on structures that shared by master and slave */ -static int -l2fwd_malloc_shared_struct(void) -{ - port_statistics = rte_zmalloc("port_stat", - sizeof(struct l2fwd_port_statistics) * RTE_MAX_ETHPORTS, - 0); - if (port_statistics == NULL) - return -1; - - /* allocate mapping_id array */ - if (float_proc) { - int i; - mapping_id = rte_malloc("mapping_id", sizeof(unsigned) * RTE_MAX_LCORE, - 0); - - if (mapping_id == NULL) - return -1; - - for (i = 0 ;i < RTE_MAX_LCORE; i++) - mapping_id[i] = INVALID_MAPPING_ID; - } - return 0; -} - -/* Create ring which used for communicate among master and slave */ -static int -create_ms_ring(unsigned slaveid) -{ - unsigned flag = RING_F_SP_ENQ | RING_F_SC_DEQ; - struct lcore_resource_struct *res = &lcore_resource[slaveid]; - unsigned socketid = rte_socket_id(); - - /* Always assume create ring on master socket_id */ - /* Default only create a ring size 32 */ - snprintf(res->ring_name[0], MAX_NAME_LEN, "%s%u", - RING_MASTER_NAME, slaveid); - if ((res->ring[0] = create_ring(res->ring_name[0], NB_CORE_MSGBUF, - socketid, flag)) == NULL) { - printf("Create m2s ring %s failed\n", res->ring_name[0]); - return -1; - } - - snprintf(res->ring_name[1], MAX_NAME_LEN, "%s%u", - RING_SLAVE_NAME, slaveid); - if ((res->ring[1] = create_ring(res->ring_name[1], NB_CORE_MSGBUF, - socketid, flag)) == NULL) { - printf("Create s2m ring %s failed\n", res->ring_name[1]); - return -1; - } - - return 0; -} - -/* send command to pair in paired master and slave ring */ -static inline int -sendcmd(unsigned slaveid, enum l2fwd_cmd cmd, int is_master) -{ - struct lcore_resource_struct *res = &lcore_resource[slaveid]; - void *msg; - int fd = !is_master; - - /* Only check master, it must be enabled and running if it is slave */ - if (is_master && !res->enabled) - return -1; - - if (res->ring[fd] == NULL) - return -1; - - if (rte_mempool_get(message_pool, &msg) < 0) { - printf("Error to get message buffer\n"); - return -1; - } - - *(enum l2fwd_cmd *)msg = cmd; - - if (rte_ring_enqueue(res->ring[fd], msg) != 0) { - printf("Enqueue error\n"); - rte_mempool_put(message_pool, msg); - return -1; - } - - return 0; -} - -/* Get command from pair in paired master and slave ring */ -static inline int -getcmd(unsigned slaveid, enum l2fwd_cmd *cmd, int is_master) -{ - struct lcore_resource_struct *res = &lcore_resource[slaveid]; - void *msg; - int fd = !!is_master; - int ret; - /* Only check master, it must be enabled and running if it is slave */ - if (is_master && (!res->enabled)) - return -1; - - if (res->ring[fd] == NULL) - return -1; - - ret = rte_ring_dequeue(res->ring[fd], &msg); - - if (ret == 0) { - *cmd = *(enum l2fwd_cmd *)msg; - rte_mempool_put(message_pool, msg); - } - return ret; -} - -/* Master send command to slave and wait until ack received or error met */ -static int -master_sendcmd_with_ack(unsigned slaveid, enum l2fwd_cmd cmd) -{ - enum l2fwd_cmd ack_cmd; - int ret = -1; - - if (sendcmd(slaveid, cmd, 1) != 0) - rte_exit(EXIT_FAILURE, "Failed to send message\n"); - - /* Get ack */ - while (1) { - ret = getcmd(slaveid, &ack_cmd, 1); - if (ret == 0 && cmd == ack_cmd) - break; - - /* If slave not running yet, return an error */ - if (flib_query_slave_status(slaveid) != ST_RUN) { - ret = -ENOENT; - break; - } - } - - return ret; -} - -/* restart all port that assigned to that slave lcore */ -static int -reset_slave_all_ports(unsigned slaveid) -{ - struct lcore_resource_struct *slave = &lcore_resource[slaveid]; - int i, ret = 0; - - /* stop/start port */ - for (i = 0; i < slave->port_num; i++) { - char buf_name[RTE_MEMPOOL_NAMESIZE]; - struct rte_mempool *pool; - printf("Stop port :%d\n", slave->port[i]); - rte_eth_dev_stop(slave->port[i]); - snprintf(buf_name, RTE_MEMPOOL_NAMESIZE, MBUF_NAME, slave->port[i]); - pool = rte_mempool_lookup(buf_name); - if (pool) - printf("Port %d mempool free object is %u(%u)\n", slave->port[i], - rte_mempool_avail_count(pool), - (unsigned int)NB_MBUF); - else - printf("Can't find mempool %s\n", buf_name); - - printf("Start port :%d\n", slave->port[i]); - ret = rte_eth_dev_start(slave->port[i]); - if (ret != 0) - break; - } - return ret; -} - -static int -reset_shared_structures(unsigned slaveid) -{ - int ret; - /* Only port are shared resource here */ - ret = reset_slave_all_ports(slaveid); - - return ret; -} - -/** - * Call this function to re-create resource that needed for slave process that - * exited in last instance - **/ -static int -init_slave_res(unsigned slaveid) -{ - struct lcore_resource_struct *slave = &lcore_resource[slaveid]; - enum l2fwd_cmd cmd; - - if (!slave->enabled) { - printf("Something wrong with lcore=%u enabled=%d\n",slaveid, - slave->enabled); - return -1; - } - - /* Initialize ring */ - if (create_ms_ring(slaveid) != 0) - rte_exit(EXIT_FAILURE, "failed to create ring for slave %u\n", - slaveid); - - /* drain un-read buffer if have */ - while (getcmd(slaveid, &cmd, 1) == 0); - while (getcmd(slaveid, &cmd, 0) == 0); - - return 0; -} - -static int -recreate_one_slave(unsigned slaveid) -{ - int ret = 0; - /* Re-initialize resource for stalled slave */ - if ((ret = init_slave_res(slaveid)) != 0) { - printf("Init slave=%u failed\n", slaveid); - return ret; - } - - if ((ret = flib_remote_launch(l2fwd_launch_one_lcore, NULL, slaveid)) - != 0) - printf("Launch slave %u failed\n", slaveid); - - return ret; -} - -/** - * remapping resource belong to slave_id to new lcore that gets from flib_assign_lcore_id(), - * used only floating process option applied. - * - * @param slaveid - * original lcore_id that apply for remapping - */ -static void -remapping_slave_resource(unsigned slaveid, unsigned map_id) -{ - - /* remapping lcore_resource */ - memcpy(&lcore_resource[map_id], &lcore_resource[slaveid], - sizeof(struct lcore_resource_struct)); - - /* remapping lcore_queue_conf */ - memcpy(&lcore_queue_conf[map_id], &lcore_queue_conf[slaveid], - sizeof(struct lcore_queue_conf)); -} - -static int -reset_pair(unsigned slaveid, unsigned pairid) -{ - int ret; - if ((ret = reset_shared_structures(slaveid)) != 0) - goto back; - - if((ret = reset_shared_structures(pairid)) != 0) - goto back; - - if (float_proc) { - unsigned map_id = mapping_id[slaveid]; - - if (map_id != INVALID_MAPPING_ID) { - printf("%u return mapping id %u\n", slaveid, map_id); - flib_free_lcore_id(map_id); - mapping_id[slaveid] = INVALID_MAPPING_ID; - } - - map_id = mapping_id[pairid]; - if (map_id != INVALID_MAPPING_ID) { - printf("%u return mapping id %u\n", pairid, map_id); - flib_free_lcore_id(map_id); - mapping_id[pairid] = INVALID_MAPPING_ID; - } - } - - if((ret = recreate_one_slave(slaveid)) != 0) - goto back; - - ret = recreate_one_slave(pairid); - -back: - return ret; -} - -static void -slave_exit_cb(unsigned slaveid, __attribute__((unused))int stat) -{ - struct lcore_resource_struct *slave = &lcore_resource[slaveid]; - - printf("Get slave %u leave info\n", slaveid); - if (!slave->enabled) { - printf("Lcore=%u not registered for it's exit\n", slaveid); - return; - } - rte_spinlock_lock(&res_lock); - - /* Change the state and wait master to start them */ - slave->flags = SLAVE_RECREATE_FLAG; - - rte_spinlock_unlock(&res_lock); -} - -static void -l2fwd_simple_forward(struct rte_mbuf *m, unsigned portid) -{ - struct ether_hdr *eth; - void *tmp; - unsigned dst_port; - int sent; - struct rte_eth_dev_tx_buffer *buffer; - - dst_port = l2fwd_dst_ports[portid]; - eth = rte_pktmbuf_mtod(m, struct ether_hdr *); - - /* 02:00:00:00:00:xx */ - tmp = ð->d_addr.addr_bytes[0]; - *((uint64_t *)tmp) = 0x000000000002 + ((uint64_t)dst_port << 40); - - /* src addr */ - ether_addr_copy(&l2fwd_ports_eth_addr[dst_port], ð->s_addr); - - buffer = tx_buffer[dst_port]; - sent = rte_eth_tx_buffer(dst_port, 0, buffer, m); - if (sent) - port_statistics[dst_port].tx += sent; -} - -/* main processing loop */ -static void -l2fwd_main_loop(void) -{ - struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; - struct rte_mbuf *m; - int sent; - unsigned lcore_id; - uint64_t prev_tsc, diff_tsc, cur_tsc; - unsigned i, j, portid, nb_rx; - struct lcore_queue_conf *qconf; - const uint64_t drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * - BURST_TX_DRAIN_US; - struct rte_eth_dev_tx_buffer *buffer; - - prev_tsc = 0; - - lcore_id = rte_lcore_id(); - - qconf = &lcore_queue_conf[lcore_id]; - - if (qconf->n_rx_port == 0) { - RTE_LOG(INFO, L2FWD, "lcore %u has nothing to do\n", lcore_id); - return; - } - - RTE_LOG(INFO, L2FWD, "entering main loop on lcore %u\n", lcore_id); - - for (i = 0; i < qconf->n_rx_port; i++) { - portid = qconf->rx_port_list[i]; - RTE_LOG(INFO, L2FWD, " -- lcoreid=%u portid=%u\n", lcore_id, - portid); - } - - while (1) { - enum l2fwd_cmd cmd; - cur_tsc = rte_rdtsc(); - - if (unlikely(getcmd(lcore_id, &cmd, 0) == 0)) { - sendcmd(lcore_id, cmd, 0); - - /* If get stop command, stop forwarding and exit */ - if (cmd == CMD_STOP) { - return; - } - } - - /* - * TX burst queue drain - */ - diff_tsc = cur_tsc - prev_tsc; - if (unlikely(diff_tsc > drain_tsc)) { - - for (i = 0; i < qconf->n_rx_port; i++) { - - portid = l2fwd_dst_ports[qconf->rx_port_list[i]]; - buffer = tx_buffer[portid]; - - sent = rte_eth_tx_buffer_flush(portid, 0, buffer); - if (sent) - port_statistics[portid].tx += sent; - - } - - prev_tsc = cur_tsc; - } - - /* - * Read packet from RX queues - */ - for (i = 0; i < qconf->n_rx_port; i++) { - - portid = qconf->rx_port_list[i]; - nb_rx = rte_eth_rx_burst((uint8_t) portid, 0, - pkts_burst, MAX_PKT_BURST); - - port_statistics[portid].rx += nb_rx; - - for (j = 0; j < nb_rx; j++) { - m = pkts_burst[j]; - rte_prefetch0(rte_pktmbuf_mtod(m, void *)); - l2fwd_simple_forward(m, portid); - } - } - } -} - -static int -l2fwd_launch_one_lcore(__attribute__((unused)) void *dummy) -{ - unsigned lcore_id = rte_lcore_id(); - - if (float_proc) { - unsigned flcore_id; - - /* Change it to floating process, also change it's lcore_id */ - clear_cpu_affinity(); - RTE_PER_LCORE(_lcore_id) = 0; - /* Get a lcore_id */ - if (flib_assign_lcore_id() < 0 ) { - printf("flib_assign_lcore_id failed\n"); - return -1; - } - flcore_id = rte_lcore_id(); - /* Set mapping id, so master can return it after slave exited */ - mapping_id[lcore_id] = flcore_id; - printf("Org lcore_id = %u, cur lcore_id = %u\n", - lcore_id, flcore_id); - remapping_slave_resource(lcore_id, flcore_id); - } - - l2fwd_main_loop(); - - /* return lcore_id before return */ - if (float_proc) { - flib_free_lcore_id(rte_lcore_id()); - mapping_id[lcore_id] = INVALID_MAPPING_ID; - } - return 0; -} - -/* display usage */ -static void -l2fwd_usage(const char *prgname) -{ - printf("%s [EAL options] -- -p PORTMASK -s COREMASK [-q NQ] -f\n" - " -p PORTMASK: hexadecimal bitmask of ports to configure\n" - " -q NQ: number of queue (=ports) per lcore (default is 1)\n" - " -f use floating process which won't bind to any core to run\n" - " -T PERIOD: statistics will be refreshed each PERIOD seconds (0 to disable, 10 default, 86400 maximum)\n", - prgname); -} - -static int -l2fwd_parse_portmask(const char *portmask) -{ - char *end = NULL; - unsigned long pm; - - /* parse hexadecimal string */ - pm = strtoul(portmask, &end, 16); - if ((portmask[0] == '\0') || (end == NULL) || (*end != '\0')) - return -1; - - if (pm == 0) - return -1; - - return pm; -} - -static unsigned int -l2fwd_parse_nqueue(const char *q_arg) -{ - char *end = NULL; - unsigned long n; - - /* parse hexadecimal string */ - n = strtoul(q_arg, &end, 10); - if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) - return 0; - if (n == 0) - return 0; - if (n >= MAX_RX_QUEUE_PER_LCORE) - return 0; - - return n; -} - -static int -l2fwd_parse_timer_period(const char *q_arg) -{ - char *end = NULL; - int n; - - /* parse number string */ - n = strtol(q_arg, &end, 10); - if ((q_arg[0] == '\0') || (end == NULL) || (*end != '\0')) - return -1; - if (n >= MAX_TIMER_PERIOD) - return -1; - - return n; -} - -/* Parse the argument given in the command line of the application */ -static int -l2fwd_parse_args(int argc, char **argv) -{ - int opt, ret; - char **argvopt; - int option_index; - char *prgname = argv[0]; - static struct option lgopts[] = { - {NULL, 0, 0, 0} - }; - int has_pmask = 0; - - argvopt = argv; - - while ((opt = getopt_long(argc, argvopt, "p:q:T:f", - lgopts, &option_index)) != EOF) { - - switch (opt) { - /* portmask */ - case 'p': - l2fwd_enabled_port_mask = l2fwd_parse_portmask(optarg); - if (l2fwd_enabled_port_mask == 0) { - printf("invalid portmask\n"); - l2fwd_usage(prgname); - return -1; - } - has_pmask = 1; - break; - - /* nqueue */ - case 'q': - l2fwd_rx_queue_per_lcore = l2fwd_parse_nqueue(optarg); - if (l2fwd_rx_queue_per_lcore == 0) { - printf("invalid queue number\n"); - l2fwd_usage(prgname); - return -1; - } - break; - - /* timer period */ - case 'T': - timer_period = l2fwd_parse_timer_period(optarg) * 1000 * TIMER_MILLISECOND; - if (timer_period < 0) { - printf("invalid timer period\n"); - l2fwd_usage(prgname); - return -1; - } - break; - - /* use floating process */ - case 'f': - float_proc = 1; - break; - - /* long options */ - case 0: - l2fwd_usage(prgname); - return -1; - - default: - l2fwd_usage(prgname); - return -1; - } - } - - if (optind >= 0) - argv[optind-1] = prgname; - - if (!has_pmask) { - l2fwd_usage(prgname); - return -1; - } - ret = optind-1; - optind = 1; /* reset getopt lib */ - return ret; -} - -/* Check the link status of all ports in up to 9s, and print them finally */ -static void -check_all_ports_link_status(uint32_t port_mask) -{ -#define CHECK_INTERVAL 100 /* 100ms */ -#define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ - uint16_t portid; - uint8_t count, all_ports_up, print_flag = 0; - struct rte_eth_link link; - - printf("\nChecking link status"); - fflush(stdout); - for (count = 0; count <= MAX_CHECK_TIME; count++) { - all_ports_up = 1; - RTE_ETH_FOREACH_DEV(portid) { - if ((port_mask & (1 << portid)) == 0) - continue; - memset(&link, 0, sizeof(link)); - rte_eth_link_get_nowait(portid, &link); - /* print link status if flag set */ - if (print_flag == 1) { - if (link.link_status) - printf( - "Port%d Link Up- speed %u Mbps- %s\n", - portid, link.link_speed, - (link.link_duplex == ETH_LINK_FULL_DUPLEX) ? - ("full-duplex") : ("half-duplex\n")); - else - printf("Port %d Link Down\n", portid); - continue; - } - /* clear all_ports_up flag if any link down */ - if (link.link_status == ETH_LINK_DOWN) { - all_ports_up = 0; - break; - } - } - /* after finally printing all link status, get out */ - if (print_flag == 1) - break; - - if (all_ports_up == 0) { - printf("."); - fflush(stdout); - rte_delay_ms(CHECK_INTERVAL); - } - - /* set the print_flag if all ports up or timeout */ - if (all_ports_up == 1 || count == (MAX_CHECK_TIME - 1)) { - print_flag = 1; - printf("done\n"); - } - } -} - -int -main(int argc, char **argv) -{ - struct lcore_queue_conf *qconf; - int ret; - uint16_t nb_ports; - uint16_t nb_ports_available = 0; - uint16_t portid, last_port; - unsigned rx_lcore_id; - unsigned nb_ports_in_mask = 0; - unsigned i; - uint64_t prev_tsc, diff_tsc, cur_tsc, timer_tsc; - - /* Save cpu_affinity first, restore it in case it's floating process option */ - if (get_cpu_affinity() != 0) - rte_exit(EXIT_FAILURE, "get_cpu_affinity error\n"); - - /* Also tries to set cpu affinity to detect whether it will fail in child process */ - if(clear_cpu_affinity() != 0) - rte_exit(EXIT_FAILURE, "clear_cpu_affinity error\n"); - - /* init EAL */ - ret = rte_eal_init(argc, argv); - if (ret < 0) - rte_exit(EXIT_FAILURE, "Invalid EAL arguments\n"); - argc -= ret; - argv += ret; - - /* parse application arguments (after the EAL ones) */ - ret = l2fwd_parse_args(argc, argv); - if (ret < 0) - rte_exit(EXIT_FAILURE, "Invalid L2FWD arguments\n"); - - /*flib init */ - if (flib_init() != 0) - rte_exit(EXIT_FAILURE, "flib init error"); - - /** - * Allocated structures that slave lcore would change. For those that slaves are - * read only, needn't use malloc to share and global or static variables is ok since - * slave inherit all the knowledge that master initialized. - **/ - if (l2fwd_malloc_shared_struct() != 0) - rte_exit(EXIT_FAILURE, "malloc mem failed\n"); - - /* Initialize lcore_resource structures */ - memset(lcore_resource, 0, sizeof(lcore_resource)); - for (i = 0; i < RTE_MAX_LCORE; i++) - lcore_resource[i].lcore_id = i; - - nb_ports = rte_eth_dev_count_avail(); - if (nb_ports == 0) - rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n"); - - /* create the mbuf pool */ - RTE_ETH_FOREACH_DEV(portid) { - /* skip ports that are not enabled */ - if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) - continue; - char buf_name[RTE_MEMPOOL_NAMESIZE]; - snprintf(buf_name, RTE_MEMPOOL_NAMESIZE, MBUF_NAME, portid); - l2fwd_pktmbuf_pool[portid] = - rte_pktmbuf_pool_create(buf_name, NB_MBUF, 32, - 0, MBUF_DATA_SIZE, rte_socket_id()); - if (l2fwd_pktmbuf_pool[portid] == NULL) - rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n"); - - printf("Create mbuf %s\n", buf_name); - } - - /* reset l2fwd_dst_ports */ - for (portid = 0; portid < RTE_MAX_ETHPORTS; portid++) - l2fwd_dst_ports[portid] = 0; - last_port = 0; - - /* - * Each logical core is assigned a dedicated TX queue on each port. - */ - RTE_ETH_FOREACH_DEV(portid) { - /* skip ports that are not enabled */ - if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) - continue; - - if (nb_ports_in_mask % 2) { - l2fwd_dst_ports[portid] = last_port; - l2fwd_dst_ports[last_port] = portid; - } - else - last_port = portid; - - nb_ports_in_mask++; - } - if (nb_ports_in_mask % 2) { - printf("Notice: odd number of ports in portmask.\n"); - l2fwd_dst_ports[last_port] = last_port; - } - - rx_lcore_id = 0; - qconf = NULL; - - /* Initialize the port/queue configuration of each logical core */ - RTE_ETH_FOREACH_DEV(portid) { - struct lcore_resource_struct *res; - /* skip ports that are not enabled */ - if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) - continue; - - /* get the lcore_id for this port */ - /* skip master lcore */ - while (rte_lcore_is_enabled(rx_lcore_id) == 0 || - rte_get_master_lcore() == rx_lcore_id || - lcore_queue_conf[rx_lcore_id].n_rx_port == - l2fwd_rx_queue_per_lcore) { - - rx_lcore_id++; - if (rx_lcore_id >= RTE_MAX_LCORE) - rte_exit(EXIT_FAILURE, "Not enough cores\n"); - } - - if (qconf != &lcore_queue_conf[rx_lcore_id]) - /* Assigned a new logical core in the loop above. */ - qconf = &lcore_queue_conf[rx_lcore_id]; - - qconf->rx_port_list[qconf->n_rx_port] = portid; - qconf->n_rx_port++; - - /* Save the port resource info into lcore_resource strucutres */ - res = &lcore_resource[rx_lcore_id]; - res->enabled = 1; - res->port[res->port_num++] = portid; - - printf("Lcore %u: RX port %u\n", rx_lcore_id, (unsigned) portid); - } - - /* Initialise each port */ - RTE_ETH_FOREACH_DEV(portid) { - struct rte_eth_rxconf rxq_conf; - struct rte_eth_txconf txq_conf; - struct rte_eth_conf local_port_conf = port_conf; - - /* skip ports that are not enabled */ - if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) { - printf("Skipping disabled port %u\n", (unsigned) portid); - continue; - } - nb_ports_available++; - /* init port */ - printf("Initializing port %u... ", (unsigned) portid); - fflush(stdout); - rte_eth_dev_info_get(portid, &dev_info); - if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) - local_port_conf.txmode.offloads |= - DEV_TX_OFFLOAD_MBUF_FAST_FREE; - ret = rte_eth_dev_configure(portid, 1, 1, &local_port_conf); - if (ret < 0) - rte_exit(EXIT_FAILURE, "Cannot configure device: err=%d, port=%u\n", - ret, (unsigned) portid); - - ret = rte_eth_dev_adjust_nb_rx_tx_desc(portid, &nb_rxd, - &nb_txd); - if (ret < 0) - rte_exit(EXIT_FAILURE, - "rte_eth_dev_adjust_nb_rx_tx_desc: err=%d, port=%u\n", - ret, (unsigned) portid); - - rte_eth_macaddr_get(portid,&l2fwd_ports_eth_addr[portid]); - - /* init one RX queue */ - fflush(stdout); - rxq_conf = dev_info.default_rxconf; - rxq_conf.offloads = local_port_conf.rxmode.offloads; - ret = rte_eth_rx_queue_setup(portid, 0, nb_rxd, - rte_eth_dev_socket_id(portid), - &rxq_conf, - l2fwd_pktmbuf_pool[portid]); - if (ret < 0) - rte_exit(EXIT_FAILURE, "rte_eth_rx_queue_setup:err=%d, port=%u\n", - ret, (unsigned) portid); - - /* init one TX queue on each port */ - fflush(stdout); - txq_conf = dev_info.default_txconf; - txq_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE; - txq_conf.tx_offloads = local_port_conf.txmode.offloads; - ret = rte_eth_tx_queue_setup(portid, 0, nb_txd, - rte_eth_dev_socket_id(portid), - &txq_conf); - if (ret < 0) - rte_exit(EXIT_FAILURE, "rte_eth_tx_queue_setup:err=%d, port=%u\n", - ret, (unsigned) portid); - - /* Initialize TX buffers */ - tx_buffer[portid] = rte_zmalloc_socket("tx_buffer", - RTE_ETH_TX_BUFFER_SIZE(MAX_PKT_BURST), 0, - rte_eth_dev_socket_id(portid)); - if (tx_buffer[portid] == NULL) - rte_exit(EXIT_FAILURE, "Cannot allocate buffer for tx on port %u\n", - (unsigned) portid); - - rte_eth_tx_buffer_init(tx_buffer[portid], MAX_PKT_BURST); - - ret = rte_eth_tx_buffer_set_err_callback(tx_buffer[portid], - rte_eth_tx_buffer_count_callback, - &port_statistics[portid].dropped); - if (ret < 0) - rte_exit(EXIT_FAILURE, "Cannot set error callback for " - "tx buffer on port %u\n", (unsigned) portid); - - /* Start device */ - ret = rte_eth_dev_start(portid); - if (ret < 0) - rte_exit(EXIT_FAILURE, "rte_eth_dev_start:err=%d, port=%u\n", - ret, (unsigned) portid); - - printf("done: \n"); - - rte_eth_promiscuous_enable(portid); - - printf("Port %u, MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n\n", - (unsigned) portid, - l2fwd_ports_eth_addr[portid].addr_bytes[0], - l2fwd_ports_eth_addr[portid].addr_bytes[1], - l2fwd_ports_eth_addr[portid].addr_bytes[2], - l2fwd_ports_eth_addr[portid].addr_bytes[3], - l2fwd_ports_eth_addr[portid].addr_bytes[4], - l2fwd_ports_eth_addr[portid].addr_bytes[5]); - - /* initialize port stats */ - //memset(&port_statistics, 0, sizeof(port_statistics)); - } - - if (!nb_ports_available) { - rte_exit(EXIT_FAILURE, - "All available ports are disabled. Please set portmask.\n"); - } - - check_all_ports_link_status(l2fwd_enabled_port_mask); - - /* Record pair lcore */ - /** - * Since l2fwd example would create pair between different neighbour port, that's - * port 0 receive and forward to port 1, the same to port 1, these 2 ports will have - * dependency. If one port stopped working (killed, for example), the port need to - * be stopped/started again. During the time, another port need to wait until stop/start - * procedure completed. So, record the pair relationship for those lcores working - * on ports. - **/ - RTE_ETH_FOREACH_DEV(portid) { - uint32_t pair_port; - unsigned lcore = 0, pair_lcore = 0; - unsigned j, find_lcore, find_pair_lcore; - /* skip ports that are not enabled */ - if ((l2fwd_enabled_port_mask & (1 << portid)) == 0) - continue; - - /* Find pair ports' lcores */ - find_lcore = find_pair_lcore = 0; - pair_port = l2fwd_dst_ports[portid]; - for (i = 0; i < RTE_MAX_LCORE; i++) { - if (!rte_lcore_is_enabled(i)) - continue; - for (j = 0; j < lcore_queue_conf[i].n_rx_port;j++) { - if (lcore_queue_conf[i].rx_port_list[j] == portid) { - lcore = i; - find_lcore = 1; - break; - } - if (lcore_queue_conf[i].rx_port_list[j] == pair_port) { - pair_lcore = i; - find_pair_lcore = 1; - break; - } - } - if (find_lcore && find_pair_lcore) - break; - } - if (!find_lcore || !find_pair_lcore) - rte_exit(EXIT_FAILURE, "Not find port=%d pair\n", portid); - - printf("lcore %u and %u paired\n", lcore, pair_lcore); - lcore_resource[lcore].pair_id = pair_lcore; - lcore_resource[pair_lcore].pair_id = lcore; - } - - /* Create message buffer for all master and slave */ - message_pool = rte_mempool_create("ms_msg_pool", - NB_CORE_MSGBUF * RTE_MAX_LCORE, - sizeof(enum l2fwd_cmd), NB_CORE_MSGBUF / 2, - 0, NULL, NULL, NULL, NULL, rte_socket_id(), 0); - - if (message_pool == NULL) - rte_exit(EXIT_FAILURE, "Create msg mempool failed\n"); - - /* Create ring for each master and slave pair, also register cb when slave leaves */ - for (i = 0; i < RTE_MAX_LCORE; i++) { - /** - * Only create ring and register slave_exit cb in case that core involved into - * packet forwarding - **/ - if (lcore_resource[i].enabled) { - /* Create ring for master and slave communication */ - ret = create_ms_ring(i); - if (ret != 0) - rte_exit(EXIT_FAILURE, "Create ring for lcore=%u failed", - i); - - if (flib_register_slave_exit_notify(i, - slave_exit_cb) != 0) - rte_exit(EXIT_FAILURE, - "Register master_trace_slave_exit failed"); - } - } - - /* launch per-lcore init on every lcore except master */ - flib_mp_remote_launch(l2fwd_launch_one_lcore, NULL, SKIP_MASTER); - - /* print statistics 10 second */ - prev_tsc = cur_tsc = rte_rdtsc(); - timer_tsc = 0; - while (1) { - sleep(1); - cur_tsc = rte_rdtsc(); - diff_tsc = cur_tsc - prev_tsc; - /* if timer is enabled */ - if (timer_period > 0) { - - /* advance the timer */ - timer_tsc += diff_tsc; - - /* if timer has reached its timeout */ - if (unlikely(timer_tsc >= (uint64_t) timer_period)) { - - print_stats(); - /* reset the timer */ - timer_tsc = 0; - } - } - - prev_tsc = cur_tsc; - - /* Check any slave need restart or recreate */ - rte_spinlock_lock(&res_lock); - for (i = 0; i < RTE_MAX_LCORE; i++) { - struct lcore_resource_struct *res = &lcore_resource[i]; - struct lcore_resource_struct *pair = &lcore_resource[res->pair_id]; - - /* If find slave exited, try to reset pair */ - if (res->enabled && res->flags && pair->enabled) { - if (!pair->flags) { - master_sendcmd_with_ack(pair->lcore_id, CMD_STOP); - rte_spinlock_unlock(&res_lock); - sleep(1); - rte_spinlock_lock(&res_lock); - if (pair->flags) - continue; - } - if (reset_pair(res->lcore_id, pair->lcore_id) != 0) - rte_exit(EXIT_FAILURE, "failed to reset slave"); - res->flags = 0; - pair->flags = 0; - } - } - rte_spinlock_unlock(&res_lock); - } - -} diff --git a/examples/multi_process/symmetric_mp/main.c b/examples/multi_process/symmetric_mp/main.c index 16f21a18..c6c6a537 100644 --- a/examples/multi_process/symmetric_mp/main.c +++ b/examples/multi_process/symmetric_mp/main.c @@ -178,7 +178,6 @@ smp_port_init(uint16_t port, struct rte_mempool *mbuf_pool, .rxmode = { .mq_mode = ETH_MQ_RX_RSS, .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = (DEV_RX_OFFLOAD_CHECKSUM | DEV_RX_OFFLOAD_CRC_STRIP), }, @@ -200,6 +199,7 @@ smp_port_init(uint16_t port, struct rte_mempool *mbuf_pool, uint16_t q; uint16_t nb_rxd = RX_RING_SIZE; uint16_t nb_txd = TX_RING_SIZE; + uint64_t rss_hf_tmp; if (rte_eal_process_type() == RTE_PROC_SECONDARY) return 0; @@ -216,6 +216,17 @@ smp_port_init(uint16_t port, struct rte_mempool *mbuf_pool, if (info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MBUF_FAST_FREE; + + rss_hf_tmp = port_conf.rx_adv_conf.rss_conf.rss_hf; + port_conf.rx_adv_conf.rss_conf.rss_hf &= info.flow_type_rss_offloads; + if (port_conf.rx_adv_conf.rss_conf.rss_hf != rss_hf_tmp) { + printf("Port %u modified RSS hash function based on hardware support," + "requested:%#"PRIx64" configured:%#"PRIx64"\n", + port, + rss_hf_tmp, + port_conf.rx_adv_conf.rss_conf.rss_hf); + } + retval = rte_eth_dev_configure(port, rx_rings, tx_rings, &port_conf); if (retval < 0) return retval; @@ -236,7 +247,6 @@ smp_port_init(uint16_t port, struct rte_mempool *mbuf_pool, } txq_conf = info.default_txconf; - txq_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txq_conf.offloads = port_conf.txmode.offloads; for (q = 0; q < tx_rings; q ++) { retval = rte_eth_tx_queue_setup(port, q, nb_txd, diff --git a/examples/netmap_compat/bridge/Makefile b/examples/netmap_compat/bridge/Makefile index a7c9c14a..856c847b 100644 --- a/examples/netmap_compat/bridge/Makefile +++ b/examples/netmap_compat/bridge/Makefile @@ -10,7 +10,7 @@ RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk -ifneq ($(CONFIG_RTE_EXEC_ENV),"linuxapp") +ifneq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) $(info This application can only operate in a linuxapp environment, \ please change the definition of the RTE_TARGET environment variable) all: diff --git a/examples/netmap_compat/bridge/bridge.c b/examples/netmap_compat/bridge/bridge.c index cb1882e6..7afca28c 100644 --- a/examples/netmap_compat/bridge/bridge.c +++ b/examples/netmap_compat/bridge/bridge.c @@ -26,7 +26,6 @@ struct rte_eth_conf eth_conf = { .rxmode = { .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = DEV_RX_OFFLOAD_CRC_STRIP, }, .txmode = { diff --git a/examples/netmap_compat/lib/compat_netmap.c b/examples/netmap_compat/lib/compat_netmap.c index af3dd223..0be0663e 100644 --- a/examples/netmap_compat/lib/compat_netmap.c +++ b/examples/netmap_compat/lib/compat_netmap.c @@ -708,7 +708,6 @@ rte_netmap_init_port(uint16_t portid, const struct rte_netmap_port_conf *conf) rxq_conf = dev_info.default_rxconf; rxq_conf.offloads = conf->eth_conf->rxmode.offloads; txq_conf = dev_info.default_txconf; - txq_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txq_conf.offloads = conf->eth_conf->txmode.offloads; for (i = 0; i < conf->nr_tx_rings; i++) { ret = rte_eth_tx_queue_setup(portid, i, tx_slots, diff --git a/examples/packet_ordering/main.c b/examples/packet_ordering/main.c index 7ace7d10..149bfdd0 100644 --- a/examples/packet_ordering/main.c +++ b/examples/packet_ordering/main.c @@ -35,11 +35,7 @@ volatile uint8_t quit_signal; static struct rte_mempool *mbuf_pool; -static struct rte_eth_conf port_conf_default = { - .rxmode = { - .ignore_offload_bitfield = 1, - }, -}; +static struct rte_eth_conf port_conf_default; struct worker_thread_args { struct rte_ring *ring_in; @@ -293,7 +289,6 @@ configure_eth_port(uint16_t port_id) } txconf = dev_info.default_txconf; - txconf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txconf.offloads = port_conf.txmode.offloads; for (q = 0; q < txRings; q++) { ret = rte_eth_tx_queue_setup(port_id, q, nb_txd, diff --git a/examples/performance-thread/common/lthread_pool.h b/examples/performance-thread/common/lthread_pool.h index 315a2e21..6f93775f 100644 --- a/examples/performance-thread/common/lthread_pool.h +++ b/examples/performance-thread/common/lthread_pool.h @@ -1,69 +1,7 @@ /* - *- - * BSD LICENSE - * - * Copyright(c) 2015 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Some portions of this software is derived from the producer - * consumer queues described by Dmitry Vyukov and published here - * http://www.1024cores.net - * - * Copyright (c) 2010-2011 Dmitry Vyukov. All rights reserved. - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY DMITRY VYUKOV "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DMITRY VYUKOV OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are - * those of the authors and should not be interpreted as representing official - * policies, either expressed or implied, of Dmitry Vyukov. + * SPDX-License-Identifier: BSD-3-Clause + * Copyright 2015 Intel Corporation. + * Copyright 2010-2011 Dmitry Vyukov */ #ifndef LTHREAD_POOL_H_ diff --git a/examples/performance-thread/common/lthread_queue.h b/examples/performance-thread/common/lthread_queue.h index 833ed92b..5b63ba22 100644 --- a/examples/performance-thread/common/lthread_queue.h +++ b/examples/performance-thread/common/lthread_queue.h @@ -1,69 +1,7 @@ /* - *- - * BSD LICENSE - * - * Copyright(c) 2015 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* - * Some portions of this software is derived from the producer - * consumer queues described by Dmitry Vyukov and published here - * http://www.1024cores.net - * - * Copyright (c) 2010-2011 Dmitry Vyukov. All rights reserved. - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY DMITRY VYUKOV "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, - * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DMITRY VYUKOV OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT - * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE - * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, - * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * The views and conclusions contained in the software and documentation are - * those of the authors and should not be interpreted as representing official - * policies, either expressed or implied, of Dmitry Vyukov. + * SPDX-License-Identifier: BSD-3-Clause + * Copyright 2015 Intel Corporation. + * Copyright 2010-2011 Dmitry Vyukov */ #ifndef LTHREAD_QUEUE_H_ diff --git a/examples/performance-thread/l3fwd-thread/main.c b/examples/performance-thread/l3fwd-thread/main.c index 40d80723..5392fcea 100644 --- a/examples/performance-thread/l3fwd-thread/main.c +++ b/examples/performance-thread/l3fwd-thread/main.c @@ -306,7 +306,6 @@ static struct rte_eth_conf port_conf = { .mq_mode = ETH_MQ_RX_RSS, .max_rx_pkt_len = ETHER_MAX_LEN, .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = (DEV_RX_OFFLOAD_CHECKSUM | DEV_RX_OFFLOAD_CRC_STRIP), }, @@ -3551,6 +3550,18 @@ main(int argc, char **argv) if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) local_port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MBUF_FAST_FREE; + + local_port_conf.rx_adv_conf.rss_conf.rss_hf &= + dev_info.flow_type_rss_offloads; + if (local_port_conf.rx_adv_conf.rss_conf.rss_hf != + port_conf.rx_adv_conf.rss_conf.rss_hf) { + printf("Port %u modified RSS hash function based on hardware support," + "requested:%#"PRIx64" configured:%#"PRIx64"\n", + portid, + port_conf.rx_adv_conf.rss_conf.rss_hf, + local_port_conf.rx_adv_conf.rss_conf.rss_hf); + } + ret = rte_eth_dev_configure(portid, nb_rx_queue, (uint16_t)n_tx_queue, &local_port_conf); if (ret < 0) @@ -3597,7 +3608,6 @@ main(int argc, char **argv) fflush(stdout); txconf = &dev_info.default_txconf; - txconf->txq_flags = ETH_TXQ_FLAGS_IGNORE; txconf->offloads = local_port_conf.txmode.offloads; ret = rte_eth_tx_queue_setup(portid, queueid, nb_txd, socketid, txconf); diff --git a/examples/ptpclient/ptpclient.c b/examples/ptpclient/ptpclient.c index c44013bc..82ae71c1 100644 --- a/examples/ptpclient/ptpclient.c +++ b/examples/ptpclient/ptpclient.c @@ -50,7 +50,6 @@ static uint8_t ptp_enabled_ports[RTE_MAX_ETHPORTS]; static const struct rte_eth_conf port_conf_default = { .rxmode = { .max_rx_pkt_len = ETHER_MAX_LEN, - .ignore_offload_bitfield = 1, }, }; @@ -217,11 +216,9 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool) /* Allocate and set up 1 TX queue per Ethernet port. */ for (q = 0; q < tx_rings; q++) { - /* Setup txq_flags */ struct rte_eth_txconf *txconf; txconf = &dev_info.default_txconf; - txconf->txq_flags = ETH_TXQ_FLAGS_IGNORE; txconf->offloads = port_conf.txmode.offloads; retval = rte_eth_tx_queue_setup(port, q, nb_txd, diff --git a/examples/qos_meter/Makefile b/examples/qos_meter/Makefile index 6da24076..46341b1a 100644 --- a/examples/qos_meter/Makefile +++ b/examples/qos_meter/Makefile @@ -50,7 +50,6 @@ RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk -CFLAGS += -DALLOW_EXPERIMENTAL_API CFLAGS += -O3 CFLAGS += $(WERROR_FLAGS) diff --git a/examples/qos_meter/main.c b/examples/qos_meter/main.c index 42cf4b29..5cf4e9df 100644 --- a/examples/qos_meter/main.c +++ b/examples/qos_meter/main.c @@ -56,7 +56,6 @@ static struct rte_eth_conf port_conf = { .mq_mode = ETH_MQ_RX_RSS, .max_rx_pkt_len = ETHER_MAX_LEN, .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = (DEV_RX_OFFLOAD_CHECKSUM | DEV_RX_OFFLOAD_CRC_STRIP), }, @@ -333,6 +332,17 @@ main(int argc, char **argv) rte_eth_dev_info_get(port_rx, &dev_info); if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) conf.txmode.offloads |= DEV_TX_OFFLOAD_MBUF_FAST_FREE; + + conf.rx_adv_conf.rss_conf.rss_hf &= dev_info.flow_type_rss_offloads; + if (conf.rx_adv_conf.rss_conf.rss_hf != + port_conf.rx_adv_conf.rss_conf.rss_hf) { + printf("Port %u modified RSS hash function based on hardware support," + "requested:%#"PRIx64" configured:%#"PRIx64"\n", + port_rx, + port_conf.rx_adv_conf.rss_conf.rss_hf, + conf.rx_adv_conf.rss_conf.rss_hf); + } + ret = rte_eth_dev_configure(port_rx, 1, 1, &conf); if (ret < 0) rte_exit(EXIT_FAILURE, "Port %d configuration error (%d)\n", port_rx, ret); @@ -351,7 +361,6 @@ main(int argc, char **argv) rte_exit(EXIT_FAILURE, "Port %d RX queue setup error (%d)\n", port_rx, ret); txq_conf = dev_info.default_txconf; - txq_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txq_conf.offloads = conf.txmode.offloads; ret = rte_eth_tx_queue_setup(port_rx, NIC_TX_QUEUE, nb_txd, rte_eth_dev_socket_id(port_rx), @@ -363,6 +372,17 @@ main(int argc, char **argv) rte_eth_dev_info_get(port_tx, &dev_info); if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) conf.txmode.offloads |= DEV_TX_OFFLOAD_MBUF_FAST_FREE; + + conf.rx_adv_conf.rss_conf.rss_hf &= dev_info.flow_type_rss_offloads; + if (conf.rx_adv_conf.rss_conf.rss_hf != + port_conf.rx_adv_conf.rss_conf.rss_hf) { + printf("Port %u modified RSS hash function based on hardware support," + "requested:%#"PRIx64" configured:%#"PRIx64"\n", + port_tx, + port_conf.rx_adv_conf.rss_conf.rss_hf, + conf.rx_adv_conf.rss_conf.rss_hf); + } + ret = rte_eth_dev_configure(port_tx, 1, 1, &conf); if (ret < 0) rte_exit(EXIT_FAILURE, "Port %d configuration error (%d)\n", port_tx, ret); @@ -383,7 +403,6 @@ main(int argc, char **argv) rte_exit(EXIT_FAILURE, "Port %d RX queue setup error (%d)\n", port_tx, ret); txq_conf = dev_info.default_txconf; - txq_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txq_conf.offloads = conf.txmode.offloads; ret = rte_eth_tx_queue_setup(port_tx, NIC_TX_QUEUE, nb_txd, rte_eth_dev_socket_id(port_tx), diff --git a/examples/qos_meter/meson.build b/examples/qos_meter/meson.build index 10cd4bc7..ef7779f2 100644 --- a/examples/qos_meter/meson.build +++ b/examples/qos_meter/meson.build @@ -7,7 +7,6 @@ # DPDK instance, use 'make' deps += 'meter' -allow_experimental_apis = true sources = files( 'main.c', 'rte_policer.c' ) diff --git a/examples/qos_sched/Makefile b/examples/qos_sched/Makefile index 0f0a31ff..a7ecf978 100644 --- a/examples/qos_sched/Makefile +++ b/examples/qos_sched/Makefile @@ -48,7 +48,7 @@ RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk -ifneq ($(CONFIG_RTE_EXEC_ENV),"linuxapp") +ifneq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) $(info This application can only operate in a linuxapp environment, \ please change the definition of the RTE_TARGET environment variable) all: diff --git a/examples/qos_sched/init.c b/examples/qos_sched/init.c index c9e48797..94cbb26f 100644 --- a/examples/qos_sched/init.c +++ b/examples/qos_sched/init.c @@ -59,7 +59,6 @@ static struct rte_eth_conf port_conf = { .rxmode = { .max_rx_pkt_len = ETHER_MAX_LEN, .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = DEV_RX_OFFLOAD_CRC_STRIP, }, .txmode = { @@ -96,7 +95,6 @@ app_init_port(uint16_t portid, struct rte_mempool *mp) tx_conf.tx_free_thresh = 0; tx_conf.tx_rs_thresh = 0; tx_conf.tx_deferred_start = 0; - tx_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE; /* init port */ RTE_LOG(INFO, APP, "Initializing port %"PRIu16"... ", portid); diff --git a/examples/quota_watermark/qw/init.c b/examples/quota_watermark/qw/init.c index 00725bc9..19164385 100644 --- a/examples/quota_watermark/qw/init.c +++ b/examples/quota_watermark/qw/init.c @@ -24,7 +24,6 @@ static struct rte_eth_conf port_conf = { .rxmode = { .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = DEV_RX_OFFLOAD_CRC_STRIP, }, .txmode = { @@ -82,7 +81,6 @@ void configure_eth_port(uint16_t port_id) /* Initialize the port's TX queue */ txq_conf = dev_info.default_txconf; - txq_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txq_conf.offloads = local_port_conf.txmode.offloads; ret = rte_eth_tx_queue_setup(port_id, 0, nb_txd, rte_eth_dev_socket_id(port_id), diff --git a/examples/rxtx_callbacks/main.c b/examples/rxtx_callbacks/main.c index e63ea288..2058be62 100644 --- a/examples/rxtx_callbacks/main.c +++ b/examples/rxtx_callbacks/main.c @@ -20,7 +20,6 @@ static const struct rte_eth_conf port_conf_default = { .rxmode = { .max_rx_pkt_len = ETHER_MAX_LEN, - .ignore_offload_bitfield = 1, }, }; @@ -104,7 +103,6 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool) } txconf = dev_info.default_txconf; - txconf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txconf.offloads = port_conf.txmode.offloads; for (q = 0; q < tx_rings; q++) { retval = rte_eth_tx_queue_setup(port, q, nb_txd, diff --git a/examples/server_node_efd/server/Makefile b/examples/server_node_efd/server/Makefile index cbb91ebe..df6614c6 100644 --- a/examples/server_node_efd/server/Makefile +++ b/examples/server_node_efd/server/Makefile @@ -10,7 +10,7 @@ RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk -ifneq ($(CONFIG_RTE_EXEC_ENV), "linuxapp") +ifneq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) $(error This application can only operate in a linuxapp environment, \ please change the definition of the RTE_TARGET environment variable) endif diff --git a/examples/server_node_efd/server/init.c b/examples/server_node_efd/server/init.c index 7dfe2fa2..af5a18e2 100644 --- a/examples/server_node_efd/server/init.c +++ b/examples/server_node_efd/server/init.c @@ -97,7 +97,6 @@ init_port(uint16_t port_num) struct rte_eth_conf port_conf = { .rxmode = { .mq_mode = ETH_MQ_RX_RSS, - .ignore_offload_bitfield = 1, }, }; const uint16_t rx_rings = 1, tx_rings = num_nodes; @@ -139,7 +138,6 @@ init_port(uint16_t port_num) } txconf = dev_info.default_txconf; - txconf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txconf.offloads = port_conf.txmode.offloads; for (q = 0; q < tx_rings; q++) { retval = rte_eth_tx_queue_setup(port_num, q, tx_ring_size, diff --git a/examples/skeleton/basicfwd.c b/examples/skeleton/basicfwd.c index 03bc3585..4aba1dc3 100644 --- a/examples/skeleton/basicfwd.c +++ b/examples/skeleton/basicfwd.c @@ -20,7 +20,6 @@ static const struct rte_eth_conf port_conf_default = { .rxmode = { .max_rx_pkt_len = ETHER_MAX_LEN, - .ignore_offload_bitfield = 1, }, }; @@ -68,7 +67,6 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool) } txconf = dev_info.default_txconf; - txconf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txconf.offloads = port_conf.txmode.offloads; /* Allocate and set up 1 TX queue per Ethernet port. */ for (q = 0; q < tx_rings; q++) { diff --git a/examples/tep_termination/Makefile b/examples/tep_termination/Makefile index 2b93446c..8ec1a38e 100644 --- a/examples/tep_termination/Makefile +++ b/examples/tep_termination/Makefile @@ -52,7 +52,7 @@ RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk -ifneq ($(CONFIG_RTE_EXEC_ENV),"linuxapp") +ifneq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) $(error This application can only operate in a linuxapp environment, \ please change the definition of the RTE_TARGET environment variable) endif diff --git a/examples/tep_termination/vxlan_setup.c b/examples/tep_termination/vxlan_setup.c index 299c29d2..b99ab97d 100644 --- a/examples/tep_termination/vxlan_setup.c +++ b/examples/tep_termination/vxlan_setup.c @@ -69,7 +69,6 @@ uint8_t tep_filter_type[] = {RTE_TUNNEL_FILTER_IMAC_TENID, static struct rte_eth_conf port_conf = { .rxmode = { .split_hdr_size = 0, - .ignore_offload_bitfield = 1, .offloads = DEV_RX_OFFLOAD_CRC_STRIP, }, .txmode = { @@ -131,7 +130,6 @@ vxlan_port_init(uint16_t port, struct rte_mempool *mbuf_pool) rxconf = &dev_info.default_rxconf; txconf = &dev_info.default_txconf; - txconf->txq_flags = ETH_TXQ_FLAGS_IGNORE; if (!rte_eth_dev_is_valid_port(port)) return -1; diff --git a/examples/vhost/Makefile b/examples/vhost/Makefile index 67cc55b1..a2ea97a0 100644 --- a/examples/vhost/Makefile +++ b/examples/vhost/Makefile @@ -52,7 +52,7 @@ RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk -ifneq ($(CONFIG_RTE_EXEC_ENV),"linuxapp") +ifneq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) $(info This application can only operate in a linuxapp environment, \ please change the definition of the RTE_TARGET environment variable) all: diff --git a/examples/vhost/main.c b/examples/vhost/main.c index 1659ef31..2175c118 100644 --- a/examples/vhost/main.c +++ b/examples/vhost/main.c @@ -116,7 +116,6 @@ static struct rte_eth_conf vmdq_conf_default = { .rxmode = { .mq_mode = ETH_MQ_RX_VMDQ_ONLY, .split_hdr_size = 0, - .ignore_offload_bitfield = 1, /* * VLAN strip is necessary for 1G NIC such as I350, * this fixes bug of ipv4 forwarding in guest can't @@ -256,7 +255,6 @@ port_init(uint16_t port) rxconf = &dev_info.default_rxconf; txconf = &dev_info.default_txconf; rxconf->rx_drop_en = 1; - txconf->txq_flags = ETH_TXQ_FLAGS_IGNORE; /*configure the number of supported virtio devices based on VMDQ limits */ num_devices = dev_info.max_vmdq_pools; diff --git a/examples/vhost_crypto/Makefile b/examples/vhost_crypto/Makefile index 1bb65e8f..83d33101 100644 --- a/examples/vhost_crypto/Makefile +++ b/examples/vhost_crypto/Makefile @@ -10,7 +10,7 @@ RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk -ifneq ($(CONFIG_RTE_EXEC_ENV),"linuxapp") +ifneq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) $(info This application can only operate in a linuxapp environment, \ please change the definition of the RTE_TARGET environment variable) all: diff --git a/examples/vhost_scsi/Makefile b/examples/vhost_scsi/Makefile index 31bd2563..fa0cf727 100644 --- a/examples/vhost_scsi/Makefile +++ b/examples/vhost_scsi/Makefile @@ -51,7 +51,7 @@ RTE_TARGET ?= x86_64-native-linuxapp-gcc include $(RTE_SDK)/mk/rte.vars.mk -ifneq ($(CONFIG_RTE_EXEC_ENV),"linuxapp") +ifneq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) $(info This application can only operate in a linuxapp environment, \ please change the definition of the RTE_TARGET environment variable) all: diff --git a/examples/vm_power_manager/Makefile b/examples/vm_power_manager/Makefile index ef2a9f95..13a5205b 100644 --- a/examples/vm_power_manager/Makefile +++ b/examples/vm_power_manager/Makefile @@ -19,7 +19,12 @@ APP = vm_power_mgr # all source are stored in SRCS-y SRCS-y := main.c vm_power_cli.c power_manager.c channel_manager.c -SRCS-y += channel_monitor.c +SRCS-y += channel_monitor.c parse.c +ifeq ($(CONFIG_RTE_ARCH_X86_64),y) +SRCS-y += oob_monitor_x86.c +else +SRCS-y += oob_monitor_nop.c +endif CFLAGS += -O3 -I$(RTE_SDK)/lib/librte_power/ CFLAGS += $(WERROR_FLAGS) diff --git a/examples/vm_power_manager/channel_monitor.c b/examples/vm_power_manager/channel_monitor.c index 73bddd99..7fa47ba9 100644 --- a/examples/vm_power_manager/channel_monitor.c +++ b/examples/vm_power_manager/channel_monitor.c @@ -27,6 +27,7 @@ #include "channel_commands.h" #include "channel_manager.h" #include "power_manager.h" +#include "oob_monitor.h" #define RTE_LOGTYPE_CHANNEL_MONITOR RTE_LOGTYPE_USER1 @@ -92,6 +93,10 @@ get_pcpu_to_control(struct policy *pol) struct vm_info info; int pcpu, count; uint64_t mask_u64b; + struct core_info *ci; + int ret; + + ci = get_core_info(); RTE_LOG(INFO, CHANNEL_MONITOR, "Looking for pcpu for %s\n", pol->pkt.vm_name); @@ -100,8 +105,22 @@ get_pcpu_to_control(struct policy *pol) for (count = 0; count < pol->pkt.num_vcpu; count++) { mask_u64b = info.pcpu_mask[pol->pkt.vcpu_to_control[count]]; for (pcpu = 0; mask_u64b; mask_u64b &= ~(1ULL << pcpu++)) { - if ((mask_u64b >> pcpu) & 1) - pol->core_share[count].pcpu = pcpu; + if ((mask_u64b >> pcpu) & 1) { + if (pol->pkt.policy_to_use == BRANCH_RATIO) { + ci->cd[pcpu].oob_enabled = 1; + ret = add_core_to_monitor(pcpu); + if (ret == 0) + printf("Monitoring pcpu %d via Branch Ratio\n", + pcpu); + else + printf("Failed to start OOB Monitoring pcpu %d\n", + pcpu); + + } else { + pol->core_share[count].pcpu = pcpu; + printf("Monitoring pcpu %d\n", pcpu); + } + } } } } diff --git a/examples/vm_power_manager/guest_cli/Makefile b/examples/vm_power_manager/guest_cli/Makefile index d710e22d..8b1db861 100644 --- a/examples/vm_power_manager/guest_cli/Makefile +++ b/examples/vm_power_manager/guest_cli/Makefile @@ -14,7 +14,7 @@ include $(RTE_SDK)/mk/rte.vars.mk APP = guest_vm_power_mgr # all source are stored in SRCS-y -SRCS-y := main.c vm_power_cli_guest.c +SRCS-y := main.c vm_power_cli_guest.c parse.c CFLAGS += -O3 -I$(RTE_SDK)/lib/librte_power/ CFLAGS += $(WERROR_FLAGS) diff --git a/examples/vm_power_manager/guest_cli/main.c b/examples/vm_power_manager/guest_cli/main.c index b17936d6..36365b12 100644 --- a/examples/vm_power_manager/guest_cli/main.c +++ b/examples/vm_power_manager/guest_cli/main.c @@ -2,23 +2,20 @@ * Copyright(c) 2010-2014 Intel Corporation */ -/* #include <stdio.h> -#include <string.h> -#include <stdint.h> -#include <sys/epoll.h> -#include <fcntl.h> -#include <unistd.h> #include <stdlib.h> -#include <errno.h> -*/ #include <signal.h> +#include <getopt.h> +#include <string.h> #include <rte_lcore.h> #include <rte_power.h> #include <rte_debug.h> +#include <rte_eal.h> +#include <rte_log.h> #include "vm_power_cli_guest.h" +#include "parse.h" static void sig_handler(int signo) @@ -32,6 +29,136 @@ sig_handler(int signo) } +#define MAX_HOURS 24 + +/* Parse the argument given in the command line of the application */ +static int +parse_args(int argc, char **argv) +{ + int opt, ret; + char **argvopt; + int option_index; + char *prgname = argv[0]; + const struct option lgopts[] = { + { "vm-name", required_argument, 0, 'n'}, + { "busy-hours", required_argument, 0, 'b'}, + { "quiet-hours", required_argument, 0, 'q'}, + { "port-list", required_argument, 0, 'p'}, + { "vcpu-list", required_argument, 0, 'l'}, + { "policy", required_argument, 0, 'o'}, + {NULL, 0, 0, 0} + }; + struct channel_packet *policy; + unsigned short int hours[MAX_HOURS]; + unsigned short int cores[MAX_VCPU_PER_VM]; + unsigned short int ports[MAX_VCPU_PER_VM]; + int i, cnt, idx; + + policy = get_policy(); + set_policy_defaults(policy); + + argvopt = argv; + + while ((opt = getopt_long(argc, argvopt, "n:b:q:p:", + lgopts, &option_index)) != EOF) { + + switch (opt) { + /* portmask */ + case 'n': + strcpy(policy->vm_name, optarg); + printf("Setting VM Name to [%s]\n", policy->vm_name); + break; + case 'b': + case 'q': + //printf("***Processing set using [%s]\n", optarg); + cnt = parse_set(optarg, hours, MAX_HOURS); + if (cnt < 0) { + printf("Invalid value passed to quiet/busy hours - [%s]\n", + optarg); + break; + } + idx = 0; + for (i = 0; i < MAX_HOURS; i++) { + if (hours[i]) { + if (opt == 'b') { + printf("***Busy Hour %d\n", i); + policy->timer_policy.busy_hours + [idx++] = i; + } else { + printf("***Quiet Hour %d\n", i); + policy->timer_policy.quiet_hours + [idx++] = i; + } + } + } + break; + case 'l': + cnt = parse_set(optarg, cores, MAX_VCPU_PER_VM); + if (cnt < 0) { + printf("Invalid value passed to vcpu-list - [%s]\n", + optarg); + break; + } + idx = 0; + for (i = 0; i < MAX_VCPU_PER_VM; i++) { + if (cores[i]) { + printf("***Using core %d\n", i); + policy->vcpu_to_control[idx++] = i; + } + } + policy->num_vcpu = idx; + printf("Total cores: %d\n", idx); + break; + case 'p': + cnt = parse_set(optarg, ports, MAX_VCPU_PER_VM); + if (cnt < 0) { + printf("Invalid value passed to port-list - [%s]\n", + optarg); + break; + } + idx = 0; + for (i = 0; i < MAX_VCPU_PER_VM; i++) { + if (ports[i]) { + printf("***Using port %d\n", i); + set_policy_mac(i, idx++); + } + } + policy->nb_mac_to_monitor = idx; + printf("Total Ports: %d\n", idx); + break; + case 'o': + if (!strcmp(optarg, "TRAFFIC")) + policy->policy_to_use = TRAFFIC; + else if (!strcmp(optarg, "TIME")) + policy->policy_to_use = TIME; + else if (!strcmp(optarg, "WORKLOAD")) + policy->policy_to_use = WORKLOAD; + else if (!strcmp(optarg, "BRANCH_RATIO")) + policy->policy_to_use = BRANCH_RATIO; + else { + printf("Invalid policy specified: %s\n", + optarg); + return -1; + } + break; + /* long options */ + + case 0: + break; + + default: + return -1; + } + } + + if (optind >= 0) + argv[optind-1] = prgname; + + ret = optind-1; + optind = 0; /* reset getopt lib */ + return ret; +} + int main(int argc, char **argv) { @@ -45,6 +172,14 @@ main(int argc, char **argv) signal(SIGINT, sig_handler); signal(SIGTERM, sig_handler); + argc -= ret; + argv += ret; + + /* parse application arguments (after the EAL ones) */ + ret = parse_args(argc, argv); + if (ret < 0) + rte_exit(EXIT_FAILURE, "Invalid arguments\n"); + rte_power_set_env(PM_ENV_KVM_VM); RTE_LCORE_FOREACH(lcore_id) { rte_power_init(lcore_id); diff --git a/examples/vm_power_manager/guest_cli/parse.c b/examples/vm_power_manager/guest_cli/parse.c new file mode 100644 index 00000000..528df6d6 --- /dev/null +++ b/examples/vm_power_manager/guest_cli/parse.c @@ -0,0 +1,82 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2014 Intel Corporation. + * Copyright(c) 2014 6WIND S.A. + */ + +#include <stdlib.h> +#include <string.h> +#include <rte_log.h> +#include "parse.h" + +/* + * Parse elem, the elem could be single number/range or group + * 1) A single number elem, it's just a simple digit. e.g. 9 + * 2) A single range elem, two digits with a '-' between. e.g. 2-6 + * 3) A group elem, combines multiple 1) or 2) e.g 0,2-4,6 + * Within group, '-' used for a range separator; + * ',' used for a single number. + */ +int +parse_set(const char *input, uint16_t set[], unsigned int num) +{ + unsigned int idx; + const char *str = input; + char *end = NULL; + unsigned int min, max; + + memset(set, 0, num * sizeof(uint16_t)); + + while (isblank(*str)) + str++; + + /* only digit or left bracket is qualify for start point */ + if (!isdigit(*str) || *str == '\0') + return -1; + + while (isblank(*str)) + str++; + if (*str == '\0') + return -1; + + min = num; + do { + + /* go ahead to the first digit */ + while (isblank(*str)) + str++; + if (!isdigit(*str)) + return -1; + + /* get the digit value */ + errno = 0; + idx = strtoul(str, &end, 10); + if (errno || end == NULL || idx >= num) + return -1; + + /* go ahead to separator '-' and ',' */ + while (isblank(*end)) + end++; + if (*end == '-') { + if (min == num) + min = idx; + else /* avoid continuous '-' */ + return -1; + } else if ((*end == ',') || (*end == '\0')) { + max = idx; + + if (min == num) + min = idx; + + for (idx = RTE_MIN(min, max); + idx <= RTE_MAX(min, max); idx++) { + set[idx] = 1; + } + min = num; + } else + return -1; + + str = end + 1; + } while (*end != '\0'); + + return str - input; +} diff --git a/examples/vm_power_manager/guest_cli/parse.h b/examples/vm_power_manager/guest_cli/parse.h new file mode 100644 index 00000000..c8aa0ea5 --- /dev/null +++ b/examples/vm_power_manager/guest_cli/parse.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018 Intel Corporation + */ + +#ifndef PARSE_H_ +#define PARSE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +int +parse_set(const char *, uint16_t [], unsigned int); + +#ifdef __cplusplus +} +#endif + +#endif /* PARSE_H_ */ diff --git a/examples/vm_power_manager/guest_cli/vm_power_cli_guest.c b/examples/vm_power_manager/guest_cli/vm_power_cli_guest.c index 43bdeace..0db1b804 100644 --- a/examples/vm_power_manager/guest_cli/vm_power_cli_guest.c +++ b/examples/vm_power_manager/guest_cli/vm_power_cli_guest.c @@ -33,6 +33,71 @@ struct cmd_quit_result { cmdline_fixed_string_t quit; }; +union PFID { + struct ether_addr addr; + uint64_t pfid; +}; + +static struct channel_packet policy; + +struct channel_packet * +get_policy(void) +{ + return &policy; +} + +int +set_policy_mac(int port, int idx) +{ + struct channel_packet *policy; + union PFID pfid; + + /* Use port MAC address as the vfid */ + rte_eth_macaddr_get(port, &pfid.addr); + + printf("Port %u MAC: %02" PRIx8 ":%02" PRIx8 ":%02" PRIx8 ":" + "%02" PRIx8 ":%02" PRIx8 ":%02" PRIx8 "\n", + port, + pfid.addr.addr_bytes[0], pfid.addr.addr_bytes[1], + pfid.addr.addr_bytes[2], pfid.addr.addr_bytes[3], + pfid.addr.addr_bytes[4], pfid.addr.addr_bytes[5]); + policy = get_policy(); + policy->vfid[idx] = pfid.pfid; + return 0; +} + +void +set_policy_defaults(struct channel_packet *pkt) +{ + set_policy_mac(0, 0); + pkt->nb_mac_to_monitor = 1; + + pkt->t_boost_status.tbEnabled = false; + + pkt->vcpu_to_control[0] = 0; + pkt->vcpu_to_control[1] = 1; + pkt->num_vcpu = 2; + /* Dummy Population. */ + pkt->traffic_policy.min_packet_thresh = 96000; + pkt->traffic_policy.avg_max_packet_thresh = 1800000; + pkt->traffic_policy.max_max_packet_thresh = 2000000; + + pkt->timer_policy.busy_hours[0] = 3; + pkt->timer_policy.busy_hours[1] = 4; + pkt->timer_policy.busy_hours[2] = 5; + pkt->timer_policy.quiet_hours[0] = 11; + pkt->timer_policy.quiet_hours[1] = 12; + pkt->timer_policy.quiet_hours[2] = 13; + + pkt->timer_policy.hours_to_use_traffic_profile[0] = 8; + pkt->timer_policy.hours_to_use_traffic_profile[1] = 10; + + pkt->workload = LOW; + pkt->policy_to_use = TIME; + pkt->command = PKT_POLICY; + strcpy(pkt->vm_name, "ubuntu2"); +} + static void cmd_quit_parsed(__attribute__((unused)) void *parsed_result, __attribute__((unused)) struct cmdline *cl, __attribute__((unused)) void *data) @@ -118,54 +183,12 @@ struct cmd_send_policy_result { cmdline_fixed_string_t cmd; }; -union PFID { - struct ether_addr addr; - uint64_t pfid; -}; - static inline int -send_policy(void) +send_policy(struct channel_packet *pkt) { - struct channel_packet pkt; int ret; - union PFID pfid; - /* Use port MAC address as the vfid */ - rte_eth_macaddr_get(0, &pfid.addr); - printf("Port %u MAC: %02" PRIx8 ":%02" PRIx8 ":%02" PRIx8 ":" - "%02" PRIx8 ":%02" PRIx8 ":%02" PRIx8 "\n", - 1, - pfid.addr.addr_bytes[0], pfid.addr.addr_bytes[1], - pfid.addr.addr_bytes[2], pfid.addr.addr_bytes[3], - pfid.addr.addr_bytes[4], pfid.addr.addr_bytes[5]); - pkt.vfid[0] = pfid.pfid; - - pkt.nb_mac_to_monitor = 1; - pkt.t_boost_status.tbEnabled = false; - - pkt.vcpu_to_control[0] = 0; - pkt.vcpu_to_control[1] = 1; - pkt.num_vcpu = 2; - /* Dummy Population. */ - pkt.traffic_policy.min_packet_thresh = 96000; - pkt.traffic_policy.avg_max_packet_thresh = 1800000; - pkt.traffic_policy.max_max_packet_thresh = 2000000; - - pkt.timer_policy.busy_hours[0] = 3; - pkt.timer_policy.busy_hours[1] = 4; - pkt.timer_policy.busy_hours[2] = 5; - pkt.timer_policy.quiet_hours[0] = 11; - pkt.timer_policy.quiet_hours[1] = 12; - pkt.timer_policy.quiet_hours[2] = 13; - - pkt.timer_policy.hours_to_use_traffic_profile[0] = 8; - pkt.timer_policy.hours_to_use_traffic_profile[1] = 10; - - pkt.workload = LOW; - pkt.policy_to_use = TIME; - pkt.command = PKT_POLICY; - strcpy(pkt.vm_name, "ubuntu2"); - ret = rte_power_guest_channel_send_msg(&pkt, 1); + ret = rte_power_guest_channel_send_msg(pkt, 1); if (ret == 0) return 1; RTE_LOG(DEBUG, POWER, "Error sending message: %s\n", @@ -182,7 +205,7 @@ cmd_send_policy_parsed(void *parsed_result, struct cmdline *cl, if (!strcmp(res->cmd, "now")) { printf("Sending Policy down now!\n"); - ret = send_policy(); + ret = send_policy(&policy); } if (ret != 1) cmdline_printf(cl, "Error sending message: %s\n", diff --git a/examples/vm_power_manager/guest_cli/vm_power_cli_guest.h b/examples/vm_power_manager/guest_cli/vm_power_cli_guest.h index 75a26296..fd77f6a6 100644 --- a/examples/vm_power_manager/guest_cli/vm_power_cli_guest.h +++ b/examples/vm_power_manager/guest_cli/vm_power_cli_guest.h @@ -11,6 +11,12 @@ extern "C" { #include "channel_commands.h" +struct channel_packet *get_policy(void); + +int set_policy_mac(int port, int idx); + +void set_policy_defaults(struct channel_packet *pkt); + void run_cli(__attribute__((unused)) void *arg); #ifdef __cplusplus diff --git a/examples/vm_power_manager/main.c b/examples/vm_power_manager/main.c index c9805a46..58c5fa45 100644 --- a/examples/vm_power_manager/main.c +++ b/examples/vm_power_manager/main.c @@ -29,6 +29,8 @@ #include "channel_monitor.h" #include "power_manager.h" #include "vm_power_cli.h" +#include "oob_monitor.h" +#include "parse.h" #include <rte_pmd_ixgbe.h> #include <rte_pmd_i40e.h> #include <rte_pmd_bnxt.h> @@ -47,7 +49,6 @@ static volatile bool force_quit; static const struct rte_eth_conf port_conf_default = { .rxmode = { .max_rx_pkt_len = ETHER_MAX_LEN, - .ignore_offload_bitfield = 1, }, }; @@ -83,7 +84,6 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool) } txq_conf = dev_info.default_txconf; - txq_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txq_conf.offloads = port_conf.txmode.offloads; /* Allocate and set up 1 TX queue per Ethernet port. */ for (q = 0; q < tx_rings; q++) { @@ -135,18 +135,25 @@ parse_portmask(const char *portmask) static int parse_args(int argc, char **argv) { - int opt, ret; + int opt, ret, cnt, i; char **argvopt; + uint16_t *oob_enable; int option_index; char *prgname = argv[0]; + struct core_info *ci; + float branch_ratio; static struct option lgopts[] = { { "mac-updating", no_argument, 0, 1}, { "no-mac-updating", no_argument, 0, 0}, + { "core-list", optional_argument, 0, 'l'}, + { "port-list", optional_argument, 0, 'p'}, + { "branch-ratio", optional_argument, 0, 'b'}, {NULL, 0, 0, 0} }; argvopt = argv; + ci = get_core_info(); - while ((opt = getopt_long(argc, argvopt, "p:q:T:", + while ((opt = getopt_long(argc, argvopt, "l:p:q:T:b:", lgopts, &option_index)) != EOF) { switch (opt) { @@ -158,6 +165,39 @@ parse_args(int argc, char **argv) return -1; } break; + case 'l': + oob_enable = malloc(ci->core_count * sizeof(uint16_t)); + if (oob_enable == NULL) { + printf("Error - Unable to allocate memory\n"); + return -1; + } + cnt = parse_set(optarg, oob_enable, ci->core_count); + if (cnt < 0) { + printf("Invalid core-list - [%s]\n", + optarg); + break; + } + for (i = 0; i < ci->core_count; i++) { + if (oob_enable[i]) { + printf("***Using core %d\n", i); + ci->cd[i].oob_enabled = 1; + ci->cd[i].global_enabled_cpus = 1; + } + } + free(oob_enable); + break; + case 'b': + branch_ratio = 0.0; + if (strlen(optarg)) + branch_ratio = atof(optarg); + if (branch_ratio <= 0.0) { + printf("invalid branch ratio specified\n"); + return -1; + } + ci->branch_ratio_threshold = branch_ratio; + printf("***Setting branch ratio to %f\n", + branch_ratio); + break; /* long options */ case 0: break; @@ -243,6 +283,17 @@ run_monitor(__attribute__((unused)) void *arg) return 0; } +static int +run_core_monitor(__attribute__((unused)) void *arg) +{ + if (branch_monitor_init() < 0) { + printf("Unable to initialize core monitor\n"); + return -1; + } + run_branch_monitor(); + return 0; +} + static void sig_handler(int signo) { @@ -261,8 +312,15 @@ main(int argc, char **argv) unsigned int nb_ports; struct rte_mempool *mbuf_pool; uint16_t portid; + struct core_info *ci; + ret = core_info_init(); + if (ret < 0) + rte_panic("Cannot allocate core info\n"); + + ci = get_core_info(); + ret = rte_eal_init(argc, argv); if (ret < 0) rte_panic("Cannot init EAL\n"); @@ -280,51 +338,56 @@ main(int argc, char **argv) nb_ports = rte_eth_dev_count_avail(); - mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", NUM_MBUFS * nb_ports, - MBUF_CACHE_SIZE, 0, RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); + if (nb_ports > 0) { + mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", + NUM_MBUFS * nb_ports, MBUF_CACHE_SIZE, 0, + RTE_MBUF_DEFAULT_BUF_SIZE, rte_socket_id()); - if (mbuf_pool == NULL) - rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n"); + if (mbuf_pool == NULL) + rte_exit(EXIT_FAILURE, "Cannot create mbuf pool\n"); - /* Initialize ports. */ - RTE_ETH_FOREACH_DEV(portid) { - struct ether_addr eth; - int w, j; - int ret; + /* Initialize ports. */ + RTE_ETH_FOREACH_DEV(portid) { + struct ether_addr eth; + int w, j; + int ret; - if ((enabled_port_mask & (1 << portid)) == 0) - continue; + if ((enabled_port_mask & (1 << portid)) == 0) + continue; - eth.addr_bytes[0] = 0xe0; - eth.addr_bytes[1] = 0xe0; - eth.addr_bytes[2] = 0xe0; - eth.addr_bytes[3] = 0xe0; - eth.addr_bytes[4] = portid + 0xf0; + eth.addr_bytes[0] = 0xe0; + eth.addr_bytes[1] = 0xe0; + eth.addr_bytes[2] = 0xe0; + eth.addr_bytes[3] = 0xe0; + eth.addr_bytes[4] = portid + 0xf0; - if (port_init(portid, mbuf_pool) != 0) - rte_exit(EXIT_FAILURE, "Cannot init port %"PRIu8 "\n", + if (port_init(portid, mbuf_pool) != 0) + rte_exit(EXIT_FAILURE, + "Cannot init port %"PRIu8 "\n", portid); - for (w = 0; w < MAX_VFS; w++) { - eth.addr_bytes[5] = w + 0xf0; - - ret = rte_pmd_ixgbe_set_vf_mac_addr(portid, - w, ð); - if (ret == -ENOTSUP) - ret = rte_pmd_i40e_set_vf_mac_addr(portid, - w, ð); - if (ret == -ENOTSUP) - ret = rte_pmd_bnxt_set_vf_mac_addr(portid, - w, ð); - - switch (ret) { - case 0: - printf("Port %d VF %d MAC: ", - portid, w); - for (j = 0; j < 6; j++) { - printf("%02x", eth.addr_bytes[j]); - if (j < 5) - printf(":"); + for (w = 0; w < MAX_VFS; w++) { + eth.addr_bytes[5] = w + 0xf0; + + ret = rte_pmd_ixgbe_set_vf_mac_addr(portid, + w, ð); + if (ret == -ENOTSUP) + ret = rte_pmd_i40e_set_vf_mac_addr( + portid, w, ð); + if (ret == -ENOTSUP) + ret = rte_pmd_bnxt_set_vf_mac_addr( + portid, w, ð); + + switch (ret) { + case 0: + printf("Port %d VF %d MAC: ", + portid, w); + for (j = 0; j < 5; j++) { + printf("%02x:", + eth.addr_bytes[j]); + } + printf("%02x\n", eth.addr_bytes[5]); + break; } printf("\n"); break; @@ -332,16 +395,23 @@ main(int argc, char **argv) } } + check_all_ports_link_status(enabled_port_mask); + lcore_id = rte_get_next_lcore(-1, 1, 0); if (lcore_id == RTE_MAX_LCORE) { - RTE_LOG(ERR, EAL, "A minimum of two cores are required to run " + RTE_LOG(ERR, EAL, "A minimum of three cores are required to run " "application\n"); return 0; } - - check_all_ports_link_status(enabled_port_mask); + printf("Running channel monitor on lcore id %d\n", lcore_id); rte_eal_remote_launch(run_monitor, NULL, lcore_id); + lcore_id = rte_get_next_lcore(lcore_id, 1, 0); + if (lcore_id == RTE_MAX_LCORE) { + RTE_LOG(ERR, EAL, "A minimum of three cores are required to run " + "application\n"); + return 0; + } if (power_manager_init() < 0) { printf("Unable to initialize power manager\n"); return -1; @@ -350,8 +420,17 @@ main(int argc, char **argv) printf("Unable to initialize channel manager\n"); return -1; } + + printf("Running core monitor on lcore id %d\n", lcore_id); + rte_eal_remote_launch(run_core_monitor, NULL, lcore_id); + run_cli(NULL); + branch_monitor_exit(); + rte_eal_mp_wait_lcore(); + + free(ci->cd); + return 0; } diff --git a/examples/vm_power_manager/oob_monitor.h b/examples/vm_power_manager/oob_monitor.h new file mode 100644 index 00000000..b96e08df --- /dev/null +++ b/examples/vm_power_manager/oob_monitor.h @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018 Intel Corporation + */ + +#ifndef OOB_MONITOR_H_ +#define OOB_MONITOR_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Setup the Branch Monitor resources required to initialize epoll. + * Must be called first before calling other functions. + * + * @return + * - 0 on success. + * - Negative on error. + */ +int branch_monitor_init(void); + +/** + * Run the OOB branch monitor, loops forever on on epoll_wait. + * + * + * @return + * None + */ +void run_branch_monitor(void); + +/** + * Exit the OOB Branch Monitor. + * + * @return + * None + */ +void branch_monitor_exit(void); + +/** + * Add a core to the list of cores to monitor. + * + * @param core + * Core Number + * + * @return + * - 0 on success. + * - Negative on error. + */ +int add_core_to_monitor(int core); + +/** + * Remove a previously added core from core list. + * + * @param core + * Core Number + * + * @return + * - 0 on success. + * - Negative on error. + */ +int remove_core_from_monitor(int core); + +#ifdef __cplusplus +} +#endif + + +#endif /* OOB_MONITOR_H_ */ diff --git a/examples/vm_power_manager/oob_monitor_nop.c b/examples/vm_power_manager/oob_monitor_nop.c new file mode 100644 index 00000000..7e7b8bc1 --- /dev/null +++ b/examples/vm_power_manager/oob_monitor_nop.c @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2014 Intel Corporation + */ + +#include "oob_monitor.h" + +void branch_monitor_exit(void) +{ +} + +__attribute__((unused)) static float +apply_policy(__attribute__((unused)) int core) +{ + return 0.0; +} + +int +add_core_to_monitor(__attribute__((unused)) int core) +{ + return 0; +} + +int +remove_core_from_monitor(__attribute__((unused)) int core) +{ + return 0; +} + +int +branch_monitor_init(void) +{ + return 0; +} + +void +run_branch_monitor(void) +{ +} diff --git a/examples/vm_power_manager/oob_monitor_x86.c b/examples/vm_power_manager/oob_monitor_x86.c new file mode 100644 index 00000000..589c604e --- /dev/null +++ b/examples/vm_power_manager/oob_monitor_x86.c @@ -0,0 +1,258 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018 Intel Corporation + */ + +#include <unistd.h> +#include <fcntl.h> +#include <rte_log.h> + +#include "oob_monitor.h" +#include "power_manager.h" +#include "channel_manager.h" + +static volatile unsigned run_loop = 1; +static uint64_t g_branches, g_branch_misses; +static int g_active; + +void branch_monitor_exit(void) +{ + run_loop = 0; +} + +/* Number of microseconds between each poll */ +#define INTERVAL 100 +#define PRINT_LOOP_COUNT (1000000/INTERVAL) +#define IA32_PERFEVTSEL0 0x186 +#define IA32_PERFEVTSEL1 0x187 +#define IA32_PERFCTR0 0xc1 +#define IA32_PERFCTR1 0xc2 +#define IA32_PERFEVT_BRANCH_HITS 0x05300c4 +#define IA32_PERFEVT_BRANCH_MISS 0x05300c5 + +static float +apply_policy(int core) +{ + struct core_info *ci; + uint64_t counter; + uint64_t branches, branch_misses; + uint32_t last_branches, last_branch_misses; + int hits_diff, miss_diff; + float ratio; + int ret; + + g_active = 0; + ci = get_core_info(); + + last_branches = ci->cd[core].last_branches; + last_branch_misses = ci->cd[core].last_branch_misses; + + ret = pread(ci->cd[core].msr_fd, &counter, + sizeof(counter), IA32_PERFCTR0); + if (ret < 0) + RTE_LOG(ERR, POWER_MANAGER, + "unable to read counter for core %u\n", + core); + branches = counter; + + ret = pread(ci->cd[core].msr_fd, &counter, + sizeof(counter), IA32_PERFCTR1); + if (ret < 0) + RTE_LOG(ERR, POWER_MANAGER, + "unable to read counter for core %u\n", + core); + branch_misses = counter; + + + ci->cd[core].last_branches = branches; + ci->cd[core].last_branch_misses = branch_misses; + + hits_diff = (int)branches - (int)last_branches; + if (hits_diff <= 0) { + /* Likely a counter overflow condition, skip this round */ + return -1.0; + } + + miss_diff = (int)branch_misses - (int)last_branch_misses; + if (miss_diff <= 0) { + /* Likely a counter overflow condition, skip this round */ + return -1.0; + } + + g_branches = hits_diff; + g_branch_misses = miss_diff; + + if (hits_diff < (INTERVAL*100)) { + /* Likely no workload running on this core. Skip. */ + return -1.0; + } + + ratio = (float)miss_diff * (float)100 / (float)hits_diff; + + if (ratio < ci->branch_ratio_threshold) + power_manager_scale_core_min(core); + else + power_manager_scale_core_max(core); + + g_active = 1; + return ratio; +} + +int +add_core_to_monitor(int core) +{ + struct core_info *ci; + char proc_file[UNIX_PATH_MAX]; + int ret; + + ci = get_core_info(); + + if (core < ci->core_count) { + long setup; + + snprintf(proc_file, UNIX_PATH_MAX, "/dev/cpu/%d/msr", core); + ci->cd[core].msr_fd = open(proc_file, O_RDWR | O_SYNC); + if (ci->cd[core].msr_fd < 0) { + RTE_LOG(ERR, POWER_MANAGER, + "Error opening MSR file for core %d " + "(is msr kernel module loaded?)\n", + core); + return -1; + } + /* + * Set up branch counters + */ + setup = IA32_PERFEVT_BRANCH_HITS; + ret = pwrite(ci->cd[core].msr_fd, &setup, + sizeof(setup), IA32_PERFEVTSEL0); + if (ret < 0) { + RTE_LOG(ERR, POWER_MANAGER, + "unable to set counter for core %u\n", + core); + return ret; + } + setup = IA32_PERFEVT_BRANCH_MISS; + ret = pwrite(ci->cd[core].msr_fd, &setup, + sizeof(setup), IA32_PERFEVTSEL1); + if (ret < 0) { + RTE_LOG(ERR, POWER_MANAGER, + "unable to set counter for core %u\n", + core); + return ret; + } + /* + * Close the file and re-open as read only so + * as not to hog the resource + */ + close(ci->cd[core].msr_fd); + ci->cd[core].msr_fd = open(proc_file, O_RDONLY); + if (ci->cd[core].msr_fd < 0) { + RTE_LOG(ERR, POWER_MANAGER, + "Error opening MSR file for core %d " + "(is msr kernel module loaded?)\n", + core); + return -1; + } + ci->cd[core].oob_enabled = 1; + } + return 0; +} + +int +remove_core_from_monitor(int core) +{ + struct core_info *ci; + char proc_file[UNIX_PATH_MAX]; + int ret; + + ci = get_core_info(); + + if (ci->cd[core].oob_enabled) { + long setup; + + /* + * close the msr file, then reopen rw so we can + * disable the counters + */ + if (ci->cd[core].msr_fd != 0) + close(ci->cd[core].msr_fd); + snprintf(proc_file, UNIX_PATH_MAX, "/dev/cpu/%d/msr", core); + ci->cd[core].msr_fd = open(proc_file, O_RDWR | O_SYNC); + if (ci->cd[core].msr_fd < 0) { + RTE_LOG(ERR, POWER_MANAGER, + "Error opening MSR file for core %d " + "(is msr kernel module loaded?)\n", + core); + return -1; + } + setup = 0x0; /* clear event */ + ret = pwrite(ci->cd[core].msr_fd, &setup, + sizeof(setup), IA32_PERFEVTSEL0); + if (ret < 0) { + RTE_LOG(ERR, POWER_MANAGER, + "unable to set counter for core %u\n", + core); + return ret; + } + setup = 0x0; /* clear event */ + ret = pwrite(ci->cd[core].msr_fd, &setup, + sizeof(setup), IA32_PERFEVTSEL1); + if (ret < 0) { + RTE_LOG(ERR, POWER_MANAGER, + "unable to set counter for core %u\n", + core); + return ret; + } + + close(ci->cd[core].msr_fd); + ci->cd[core].msr_fd = 0; + ci->cd[core].oob_enabled = 0; + } + return 0; +} + +int +branch_monitor_init(void) +{ + return 0; +} + +void +run_branch_monitor(void) +{ + struct core_info *ci; + int print = 0; + float ratio; + int printed; + int reads = 0; + + ci = get_core_info(); + + while (run_loop) { + + if (!run_loop) + break; + usleep(INTERVAL); + int j; + print++; + printed = 0; + for (j = 0; j < ci->core_count; j++) { + if (ci->cd[j].oob_enabled) { + ratio = apply_policy(j); + if ((print > PRINT_LOOP_COUNT) && (g_active)) { + printf(" %d: %.4f {%lu} {%d}", j, + ratio, g_branches, + reads); + printed = 1; + reads = 0; + } else { + reads++; + } + } + } + if (print > PRINT_LOOP_COUNT) { + if (printed) + printf("\n"); + print = 0; + } + } +} diff --git a/examples/vm_power_manager/parse.c b/examples/vm_power_manager/parse.c new file mode 100644 index 00000000..8231533b --- /dev/null +++ b/examples/vm_power_manager/parse.c @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2014 Intel Corporation. + * Copyright(c) 2014 6WIND S.A. + */ + +#include <string.h> +#include <rte_log.h> +#include "parse.h" + +/* + * Parse elem, the elem could be single number/range or group + * 1) A single number elem, it's just a simple digit. e.g. 9 + * 2) A single range elem, two digits with a '-' between. e.g. 2-6 + * 3) A group elem, combines multiple 1) or 2) e.g 0,2-4,6 + * Within group, '-' used for a range separator; + * ',' used for a single number. + */ +int +parse_set(const char *input, uint16_t set[], unsigned int num) +{ + unsigned int idx; + const char *str = input; + char *end = NULL; + unsigned int min, max; + + memset(set, 0, num * sizeof(uint16_t)); + + while (isblank(*str)) + str++; + + /* only digit or left bracket is qualify for start point */ + if (!isdigit(*str) || *str == '\0') + return -1; + + while (isblank(*str)) + str++; + if (*str == '\0') + return -1; + + min = num; + do { + + /* go ahead to the first digit */ + while (isblank(*str)) + str++; + if (!isdigit(*str)) + return -1; + + /* get the digit value */ + errno = 0; + idx = strtoul(str, &end, 10); + if (errno || end == NULL || idx >= num) + return -1; + + /* go ahead to separator '-' and ',' */ + while (isblank(*end)) + end++; + if (*end == '-') { + if (min == num) + min = idx; + else /* avoid continuous '-' */ + return -1; + } else if ((*end == ',') || (*end == '\0')) { + max = idx; + + if (min == num) + min = idx; + + for (idx = RTE_MIN(min, max); + idx <= RTE_MAX(min, max); idx++) { + set[idx] = 1; + } + min = num; + } else + return -1; + + str = end + 1; + } while (*end != '\0'); + + return str - input; +} diff --git a/examples/vm_power_manager/parse.h b/examples/vm_power_manager/parse.h new file mode 100644 index 00000000..a5971e9a --- /dev/null +++ b/examples/vm_power_manager/parse.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018 Intel Corporation + */ + +#ifndef PARSE_H_ +#define PARSE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +int +parse_set(const char *, uint16_t [], unsigned int); + +#ifdef __cplusplus +} +#endif + + +#endif /* PARSE_H_ */ diff --git a/examples/vm_power_manager/power_manager.c b/examples/vm_power_manager/power_manager.c index 35db2559..b7769c3c 100644 --- a/examples/vm_power_manager/power_manager.c +++ b/examples/vm_power_manager/power_manager.c @@ -12,20 +12,21 @@ #include <dirent.h> #include <errno.h> +#include <sys/sysinfo.h> #include <sys/types.h> #include <rte_log.h> #include <rte_power.h> #include <rte_spinlock.h> +#include "channel_manager.h" #include "power_manager.h" - -#define RTE_LOGTYPE_POWER_MANAGER RTE_LOGTYPE_USER1 +#include "oob_monitor.h" #define POWER_SCALE_CORE(DIRECTION, core_num , ret) do { \ - if (core_num >= POWER_MGR_MAX_CPUS) \ + if (core_num >= ci.core_count) \ return -1; \ - if (!(global_enabled_cpus & (1ULL << core_num))) \ + if (!(ci.cd[core_num].global_enabled_cpus)) \ return -1; \ rte_spinlock_lock(&global_core_freq_info[core_num].power_sl); \ ret = rte_power_freq_##DIRECTION(core_num); \ @@ -36,7 +37,7 @@ int i; \ for (i = 0; core_mask; core_mask &= ~(1 << i++)) { \ if ((core_mask >> i) & 1) { \ - if (!(global_enabled_cpus & (1ULL << i))) \ + if (!(ci.cd[i].global_enabled_cpus)) \ continue; \ rte_spinlock_lock(&global_core_freq_info[i].power_sl); \ if (rte_power_freq_##DIRECTION(i) != 1) \ @@ -54,63 +55,82 @@ struct freq_info { static struct freq_info global_core_freq_info[POWER_MGR_MAX_CPUS]; -static uint64_t global_enabled_cpus; +struct core_info ci; #define SYSFS_CPU_PATH "/sys/devices/system/cpu/cpu%u/topology/core_id" -static unsigned -set_host_cpus_mask(void) +struct core_info * +get_core_info(void) { - char path[PATH_MAX]; - unsigned i; - unsigned num_cpus = 0; - - for (i = 0; i < POWER_MGR_MAX_CPUS; i++) { - snprintf(path, sizeof(path), SYSFS_CPU_PATH, i); - if (access(path, F_OK) == 0) { - global_enabled_cpus |= 1ULL << i; - num_cpus++; - } else - return num_cpus; + return &ci; +} + +int +core_info_init(void) +{ + struct core_info *ci; + int i; + + ci = get_core_info(); + + ci->core_count = get_nprocs_conf(); + ci->branch_ratio_threshold = BRANCH_RATIO_THRESHOLD; + ci->cd = malloc(ci->core_count * sizeof(struct core_details)); + if (!ci->cd) { + RTE_LOG(ERR, POWER_MANAGER, "Failed to allocate memory for core info."); + return -1; } - return num_cpus; + for (i = 0; i < ci->core_count; i++) { + ci->cd[i].global_enabled_cpus = 1; + ci->cd[i].oob_enabled = 0; + ci->cd[i].msr_fd = 0; + } + printf("%d cores in system\n", ci->core_count); + return 0; } int power_manager_init(void) { - unsigned int i, num_cpus, num_freqs; - uint64_t cpu_mask; + unsigned int i, num_cpus = 0, num_freqs = 0; int ret = 0; + struct core_info *ci; + + rte_power_set_env(PM_ENV_ACPI_CPUFREQ); - num_cpus = set_host_cpus_mask(); - if (num_cpus == 0) { - RTE_LOG(ERR, POWER_MANAGER, "Unable to detected host CPUs, please " - "ensure that sufficient privileges exist to inspect sysfs\n"); + ci = get_core_info(); + if (!ci) { + RTE_LOG(ERR, POWER_MANAGER, + "Failed to get core info!\n"); return -1; } - rte_power_set_env(PM_ENV_ACPI_CPUFREQ); - cpu_mask = global_enabled_cpus; - for (i = 0; cpu_mask; cpu_mask &= ~(1 << i++)) { - if (rte_power_init(i) < 0) - RTE_LOG(ERR, POWER_MANAGER, - "Unable to initialize power manager " - "for core %u\n", i); - num_freqs = rte_power_freqs(i, global_core_freq_info[i].freqs, + + for (i = 0; i < ci->core_count; i++) { + if (ci->cd[i].global_enabled_cpus) { + if (rte_power_init(i) < 0) + RTE_LOG(ERR, POWER_MANAGER, + "Unable to initialize power manager " + "for core %u\n", i); + num_cpus++; + num_freqs = rte_power_freqs(i, + global_core_freq_info[i].freqs, RTE_MAX_LCORE_FREQS); - if (num_freqs == 0) { - RTE_LOG(ERR, POWER_MANAGER, - "Unable to get frequency list for core %u\n", - i); - global_enabled_cpus &= ~(1 << i); - num_cpus--; - ret = -1; + if (num_freqs == 0) { + RTE_LOG(ERR, POWER_MANAGER, + "Unable to get frequency list for core %u\n", + i); + ci->cd[i].oob_enabled = 0; + ret = -1; + } + global_core_freq_info[i].num_freqs = num_freqs; + + rte_spinlock_init(&global_core_freq_info[i].power_sl); } - global_core_freq_info[i].num_freqs = num_freqs; - rte_spinlock_init(&global_core_freq_info[i].power_sl); + if (ci->cd[i].oob_enabled) + add_core_to_monitor(i); } - RTE_LOG(INFO, POWER_MANAGER, "Detected %u host CPUs , enabled core mask:" - " 0x%"PRIx64"\n", num_cpus, global_enabled_cpus); + RTE_LOG(INFO, POWER_MANAGER, "Managing %u cores out of %u available host cores\n", + num_cpus, ci->core_count); return ret; } @@ -125,7 +145,7 @@ power_manager_get_current_frequency(unsigned core_num) core_num, POWER_MGR_MAX_CPUS-1); return -1; } - if (!(global_enabled_cpus & (1ULL << core_num))) + if (!(ci.cd[core_num].global_enabled_cpus)) return 0; rte_spinlock_lock(&global_core_freq_info[core_num].power_sl); @@ -144,15 +164,26 @@ power_manager_exit(void) { unsigned int i; int ret = 0; + struct core_info *ci; + + ci = get_core_info(); + if (!ci) { + RTE_LOG(ERR, POWER_MANAGER, + "Failed to get core info!\n"); + return -1; + } - for (i = 0; global_enabled_cpus; global_enabled_cpus &= ~(1 << i++)) { - if (rte_power_exit(i) < 0) { - RTE_LOG(ERR, POWER_MANAGER, "Unable to shutdown power manager " - "for core %u\n", i); - ret = -1; + for (i = 0; i < ci->core_count; i++) { + if (ci->cd[i].global_enabled_cpus) { + if (rte_power_exit(i) < 0) { + RTE_LOG(ERR, POWER_MANAGER, "Unable to shutdown power manager " + "for core %u\n", i); + ret = -1; + } + ci->cd[i].global_enabled_cpus = 0; } + remove_core_from_monitor(i); } - global_enabled_cpus = 0; return ret; } @@ -268,10 +299,12 @@ int power_manager_scale_core_med(unsigned int core_num) { int ret = 0; + struct core_info *ci; + ci = get_core_info(); if (core_num >= POWER_MGR_MAX_CPUS) return -1; - if (!(global_enabled_cpus & (1ULL << core_num))) + if (!(ci->cd[core_num].global_enabled_cpus)) return -1; rte_spinlock_lock(&global_core_freq_info[core_num].power_sl); ret = rte_power_set_freq(core_num, diff --git a/examples/vm_power_manager/power_manager.h b/examples/vm_power_manager/power_manager.h index 8a8a84aa..605b3c8f 100644 --- a/examples/vm_power_manager/power_manager.h +++ b/examples/vm_power_manager/power_manager.h @@ -8,6 +8,29 @@ #ifdef __cplusplus extern "C" { #endif +struct core_details { + uint64_t last_branches; + uint64_t last_branch_misses; + uint16_t global_enabled_cpus; + uint16_t oob_enabled; + int msr_fd; +}; + +struct core_info { + uint16_t core_count; + struct core_details *cd; + float branch_ratio_threshold; +}; + +#define BRANCH_RATIO_THRESHOLD 0.1 + +struct core_info * +get_core_info(void); + +int +core_info_init(void); + +#define RTE_LOGTYPE_POWER_MANAGER RTE_LOGTYPE_USER1 /* Maximum number of CPUS to manage */ #define POWER_MGR_MAX_CPUS 64 diff --git a/examples/vmdq/main.c b/examples/vmdq/main.c index 52596dd5..627a5da4 100644 --- a/examples/vmdq/main.c +++ b/examples/vmdq/main.c @@ -65,7 +65,6 @@ static const struct rte_eth_conf vmdq_conf_default = { .rxmode = { .mq_mode = ETH_MQ_RX_VMDQ_ONLY, .split_hdr_size = 0, - .ignore_offload_bitfield = 1, }, .txmode = { @@ -237,7 +236,6 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool) rxconf = &dev_info.default_rxconf; rxconf->rx_drop_en = 1; txconf = &dev_info.default_txconf; - txconf->txq_flags = ETH_TXQ_FLAGS_IGNORE; txconf->offloads = port_conf.txmode.offloads; for (q = 0; q < rxRings; q++) { retval = rte_eth_rx_queue_setup(port, q, rxRingSize, diff --git a/examples/vmdq_dcb/main.c b/examples/vmdq_dcb/main.c index 2626a2f1..64636839 100644 --- a/examples/vmdq_dcb/main.c +++ b/examples/vmdq_dcb/main.c @@ -71,7 +71,6 @@ static const struct rte_eth_conf vmdq_dcb_conf_default = { .rxmode = { .mq_mode = ETH_MQ_RX_VMDQ_DCB, .split_hdr_size = 0, - .ignore_offload_bitfield = 1, }, .txmode = { .mq_mode = ETH_MQ_TX_VMDQ_DCB, @@ -197,6 +196,7 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool) uint16_t queues_per_pool; uint32_t max_nb_pools; struct rte_eth_txconf txq_conf; + uint64_t rss_hf_tmp; /* * The max pool number from dev_info will be used to validate the pool @@ -257,6 +257,18 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool) if (dev_info.tx_offload_capa & DEV_TX_OFFLOAD_MBUF_FAST_FREE) port_conf.txmode.offloads |= DEV_TX_OFFLOAD_MBUF_FAST_FREE; + + rss_hf_tmp = port_conf.rx_adv_conf.rss_conf.rss_hf; + port_conf.rx_adv_conf.rss_conf.rss_hf &= + dev_info.flow_type_rss_offloads; + if (port_conf.rx_adv_conf.rss_conf.rss_hf != rss_hf_tmp) { + printf("Port %u modified RSS hash function based on hardware support," + "requested:%#"PRIx64" configured:%#"PRIx64"\n", + port, + rss_hf_tmp, + port_conf.rx_adv_conf.rss_conf.rss_hf); + } + /* * Though in this example, all queues including pf queues are setup. * This is because VMDQ queues doesn't always start from zero, and the @@ -290,7 +302,6 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool) } txq_conf = dev_info.default_txconf; - txq_conf.txq_flags = ETH_TXQ_FLAGS_IGNORE; txq_conf.offloads = port_conf.txmode.offloads; for (q = 0; q < num_queues; q++) { retval = rte_eth_tx_queue_setup(port, q, txRingSize, |