return 0;
        }
 
-       nb_ports = rte_eth_dev_count();
+       nb_ports = rte_eth_dev_count_avail();
        if (nb_ports == 0)
                rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n");
 
 
        case EVT_PROD_TYPE_ETH_RX_ADPTR:
                snprintf(name, EVT_PROD_MAX_NAME_LEN,
                                "Ethdev Rx Adapter producers");
-               evt_dump("nb_ethdev", "%d", rte_eth_dev_count());
+               evt_dump("nb_ethdev", "%d", rte_eth_dev_count_avail());
                break;
        case EVT_PROD_TYPE_EVENT_TIMER_ADPTR:
                if (opt->timdev_use_burst)
 
 {
        /* nb_queues = number of producers */
        return opt->prod_type == EVT_PROD_TYPE_ETH_RX_ADPTR ?
-               rte_eth_dev_count() : evt_nr_active_lcores(opt->plcores);
+               rte_eth_dev_count_avail() : evt_nr_active_lcores(opt->plcores);
 }
 
 static inline __attribute__((always_inline)) void
 
                        opt->prod_type == EVT_PROD_TYPE_EVENT_TIMER_ADPTR)
                return 0;
 
-       if (!rte_eth_dev_count()) {
+       if (!rte_eth_dev_count_avail()) {
                evt_err("No ethernet ports found.");
                return -ENODEV;
        }
 
 {
        /* nb_queues = number of producers * number of stages */
        uint8_t nb_prod = opt->prod_type == EVT_PROD_TYPE_ETH_RX_ADPTR ?
-               rte_eth_dev_count() : evt_nr_active_lcores(opt->plcores);
+               rte_eth_dev_count_avail() : evt_nr_active_lcores(opt->plcores);
        return nb_prod * opt->nb_stages;
 }
 
 
 {
        RTE_SET_USED(opt);
 
-       return rte_eth_dev_count();
+       return rte_eth_dev_count_avail();
 }
 
 static int
        uint8_t nb_worker_queues = 0;
 
        nb_ports = evt_nr_active_lcores(opt->wlcores);
-       nb_queues = rte_eth_dev_count();
+       nb_queues = rte_eth_dev_count_avail();
 
        /* One extra port and queueu for Tx service */
        if (t->mt_unsafe) {
 
         */
        lcores = 2;
 
-       if (!rte_eth_dev_count()) {
+       if (!rte_eth_dev_count_avail()) {
                evt_err("test needs minimum 1 ethernet dev");
                return -1;
        }
        };
 
        RTE_SET_USED(opt);
-       if (!rte_eth_dev_count()) {
+       if (!rte_eth_dev_count_avail()) {
                evt_err("No ethernet ports found.\n");
                return -ENODEV;
        }
        tx->dev_id = opt->dev_id;
        tx->queue_id = tx_queue_id;
        tx->port_id = tx_port_id;
-       tx->nb_ethports = rte_eth_dev_count();
+       tx->nb_ethports = rte_eth_dev_count_avail();
        tx->t = t;
 
        /* Register Tx service */
 
 static __rte_always_inline int
 pipeline_queue_nb_event_queues(struct evt_options *opt)
 {
-       uint16_t eth_count = rte_eth_dev_count();
+       uint16_t eth_count = rte_eth_dev_count_avail();
 
        return (eth_count * opt->nb_stages) + eth_count;
 }
        uint8_t nb_worker_queues = 0;
 
        nb_ports = evt_nr_active_lcores(opt->wlcores);
-       nb_queues = rte_eth_dev_count() * (nb_stages);
+       nb_queues = rte_eth_dev_count_avail() * (nb_stages);
 
        /* Extra port for Tx service. */
        if (t->mt_unsafe) {
                nb_ports++;
                nb_queues++;
        } else
-               nb_queues += rte_eth_dev_count();
+               nb_queues += rte_eth_dev_count_avail();
 
        rte_event_dev_info_get(opt->dev_id, &info);
 
 
                                port_id);
 
                /* Update number of ports */
-               nb_ports = rte_eth_dev_count();
+               nb_ports = rte_eth_dev_count_avail();
                reconfig(port_id, res->socket);
                rte_eth_promiscuous_enable(port_id);
        }
 
        reconfig(pi, socket_id);
        rte_eth_promiscuous_enable(pi);
 
-       nb_ports = rte_eth_dev_count();
+       nb_ports = rte_eth_dev_count_avail();
 
        ports[pi].port_status = RTE_PORT_STOPPED;
 
                return;
        }
 
-       nb_ports = rte_eth_dev_count();
+       nb_ports = rte_eth_dev_count_avail();
 
        printf("Port '%s' is detached. Now total ports is %d\n",
                        name, nb_ports);
        rte_pdump_init(NULL);
 #endif
 
-       nb_ports = (portid_t) rte_eth_dev_count();
+       nb_ports = (portid_t) rte_eth_dev_count_avail();
        if (nb_ports == 0)
                TESTPMD_LOG(WARNING, "No probed ethernet devices\n");
 
 
   memory footprint which helps in better cache utilization when large number
   of meter objects are used.
 
+* ethdev: The function ``rte_eth_dev_count``, often mis-used to iterate
+  over ports, is deprecated and replaced by ``rte_eth_dev_count_avail``.
+  There is also a new function ``rte_eth_dev_count_total`` to get the
+  total number of allocated ports, available or not.
+  The hotplug-proof applications should use ``RTE_ETH_FOREACH_DEV`` or
+  ``RTE_ETH_FOREACH_DEV_OWNED_BY`` as port iterators.
+
 * ethdev, in struct ``struct rte_eth_dev_info``, field ``rte_pci_device *pci_dev``
   replaced with field ``struct rte_device *device``.
 
 
         if (ret < 0)
             rte_exit(EXIT_FAILURE, "rte_pci_probe(): error %d\n", ret);
 
-        if (rte_eth_dev_count() < 2)
+        if (rte_eth_dev_count_avail() < 2)
             rte_exit(EXIT_FAILURE, "Not enough Ethernet port available\n");
     }
 
 
        argc -= ret;
        argv += ret;
 
-       nb_ports = rte_eth_dev_count();
+       nb_ports = rte_eth_dev_count_avail();
        if (nb_ports == 0)
                rte_exit(EXIT_FAILURE, "Give at least one port\n");
        else if (nb_ports > MAX_PORTS)
 
 static int
 lcore_rx(struct lcore_params *p)
 {
-       const uint16_t nb_ports = rte_eth_dev_count();
+       const uint16_t nb_ports = rte_eth_dev_count_avail();
        const int socket_id = rte_socket_id();
        uint16_t port;
        struct rte_mbuf *bufs[BURST_SIZE*2];
         * for single port, xor_val will be zero so we won't modify the output
         * port, otherwise we send traffic from 0 to 1, 2 to 3, and vice versa
         */
-       const unsigned xor_val = (rte_eth_dev_count() > 1);
+       const unsigned xor_val = (rte_eth_dev_count_avail() > 1);
        struct rte_mbuf *buf[8] __rte_cache_aligned;
 
        for (i = 0; i < 8; i++)
                                "1 lcore for packet TX\n"
                                "and at least 1 lcore for worker threads\n");
 
-       nb_ports = rte_eth_dev_count();
+       nb_ports = rte_eth_dev_count_avail();
        if (nb_ports == 0)
                rte_exit(EXIT_FAILURE, "Error: no ethernet ports detected\n");
        if (nb_ports != 1 && (nb_ports & 1))
 
        if (cnt_args_parsed < 0)
                rte_exit(EXIT_FAILURE, "rte_eal_init(): Failed");
 
-       cnt_ports = rte_eth_dev_count();
+       cnt_ports = rte_eth_dev_count_avail();
        printf("Number of NICs: %i\n", cnt_ports);
        if (cnt_ports == 0)
                rte_exit(EXIT_FAILURE, "No available NIC ports!\n");
 
 main(int argc, char **argv)
 {
        struct worker_data *worker_data;
-       unsigned int num_ports;
+       uint16_t num_ports;
        int lcore_id;
        int err;
 
        /* Parse cli options*/
        parse_app_args(argc, argv);
 
-       num_ports = rte_eth_dev_count();
+       num_ports = rte_eth_dev_count_avail();
        if (num_ports == 0)
                rte_panic("No ethernet ports found\n");
 
 
        const uint8_t dev_id = 0;
        const uint8_t nb_ports = cdata.num_workers;
        uint8_t nb_slots = 0;
-       uint8_t nb_queues = rte_eth_dev_count();
+       uint8_t nb_queues = rte_eth_dev_count_avail();
 
        /*
         * In case where all type queues are not enabled, use queues equal to
         */
        if (!atq) {
                nb_queues *= cdata.num_stages;
-               nb_queues += rte_eth_dev_count();
+               nb_queues += rte_eth_dev_count_avail();
        }
 
        struct rte_event_dev_config config = {
 
        }
 
        /* Get number of ports found in scan */
-       nb_sys_ports = rte_eth_dev_count();
+       nb_sys_ports = rte_eth_dev_count_avail();
        if (nb_sys_ports == 0)
                FATAL_ERROR("No supported Ethernet device found");
        /* Find highest port set in portmask */
 
 main(int argc, char *argv[])
 {
        struct rte_mempool *mbuf_pool;
-       uint8_t nb_ports;
+       uint16_t nb_ports;
        uint16_t portid;
        int ret;
        int socket_id;
                rte_exit(EXIT_FAILURE, "Invalid flow_classify parameters\n");
 
        /* Check that there is an even number of ports to send/receive on. */
-       nb_ports = rte_eth_dev_count();
+       nb_ports = rte_eth_dev_count_avail();
        if (nb_ports < 2 || (nb_ports & 1))
                rte_exit(EXIT_FAILURE, "Error: number of ports must be even\n");
 
 
 LDFLAGS_SHARED = $(shell pkg-config --libs libdpdk)
 LDFLAGS_STATIC = -Wl,-Bstatic $(shell pkg-config --static --libs libdpdk)
 
+CFLAGS += -DALLOW_EXPERIMENTAL_API
+
 build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
        $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
 
 
 include $(RTE_SDK)/mk/rte.vars.mk
 
+CFLAGS += -DALLOW_EXPERIMENTAL_API
 CFLAGS += -O3
 CFLAGS += $(WERROR_FLAGS)
 
 
 main(int argc, char **argv)
 {
        int ret;
-       uint8_t nr_ports;
+       uint16_t nr_ports;
        struct rte_flow_error error;
 
        ret = rte_eal_init(argc, argv);
        signal(SIGINT, signal_handler);
        signal(SIGTERM, signal_handler);
 
-       nr_ports = rte_eth_dev_count();
+       nr_ports = rte_eth_dev_count_avail();
        if (nr_ports == 0)
                rte_exit(EXIT_FAILURE, ":: no Ethernet ports found\n");
        port_id = 0;
 
 sources = files(
        'main.c',
 )
+allow_experimental_apis = true
 
        struct rte_eth_txconf *txconf;
        struct rx_queue *rxq;
        int socket, ret;
-       unsigned nb_ports;
+       uint16_t nb_ports;
        uint16_t queueid = 0;
        unsigned lcore_id = 0, rx_lcore_id = 0;
        uint32_t n_tx_queue, nb_lcores;
        if (ret < 0)
                rte_exit(EXIT_FAILURE, "Invalid arguments");
 
-       nb_ports = rte_eth_dev_count();
+       nb_ports = rte_eth_dev_count_avail();
        if (nb_ports == 0)
                rte_exit(EXIT_FAILURE, "No ports found!\n");
 
 
        if (ret < 0)
                rte_exit(EXIT_FAILURE, "Invalid IP reassembly parameters\n");
 
-       nb_ports = rte_eth_dev_count();
+       nb_ports = rte_eth_dev_count_avail();
        if (nb_ports == 0)
                rte_exit(EXIT_FAILURE, "No ports found!\n");
 
 
        if (clone_pool == NULL)
                rte_exit(EXIT_FAILURE, "Cannot init clone mbuf pool\n");
 
-       nb_ports = rte_eth_dev_count();
+       nb_ports = rte_eth_dev_count_avail();
        if (nb_ports == 0)
                rte_exit(EXIT_FAILURE, "No physical ports!\n");
        if (nb_ports > MAX_PORTS)
 
        }
 
        /* Get number of ports found in scan */
-       nb_sys_ports = rte_eth_dev_count();
+       nb_sys_ports = rte_eth_dev_count_avail();
        if (nb_sys_ports == 0)
                rte_exit(EXIT_FAILURE, "No supported Ethernet device found\n");
 
 
        argv += ret;
 
        /* Check that there is an even number of ports to send/receive on. */
-       nb_ports = rte_eth_dev_count();
+       nb_ports = rte_eth_dev_count_avail();
        if (nb_ports < 2 || (nb_ports & 1))
                rte_exit(EXIT_FAILURE, "Error: number of ports must be even\n");
 
 
 {
        uint16_t last_portid = 0, portid;
        unsigned enabled_portcount = 0;
-       unsigned nb_ports = rte_eth_dev_count();
+       unsigned nb_ports = rte_eth_dev_count_avail();
 
        if (nb_ports == 0) {
                printf("No Ethernet ports - bye\n");
 
        if (l2fwd_pktmbuf_pool == NULL)
                rte_exit(EXIT_FAILURE, "Cannot init mbuf pool\n");
 
-       nb_ports = rte_eth_dev_count();
+       nb_ports = rte_eth_dev_count_avail();
        if (nb_ports == 0)
                rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n");
 
 
        if (l2fwd_pktmbuf_pool == NULL)
                rte_exit(EXIT_FAILURE, "Cannot init mbuf pool\n");
 
-       nb_ports = rte_eth_dev_count();
+       nb_ports = rte_eth_dev_count_avail();
        if (nb_ports == 0)
                rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n");
 
 
        /* convert to number of cycles */
        timer_period *= rte_get_timer_hz();
 
-       nb_ports = rte_eth_dev_count();
+       nb_ports = rte_eth_dev_count_avail();
        if (nb_ports == 0)
                rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n");
 
 
        if (ret < 0)
                rte_exit(EXIT_FAILURE, "init_lcore_rx_queues failed\n");
 
-       nb_ports = rte_eth_dev_count();
+       nb_ports = rte_eth_dev_count_avail();
 
        if (check_port_config() < 0)
                rte_exit(EXIT_FAILURE, "check_port_config failed\n");
 
        if (ret < 0)
                rte_exit(EXIT_FAILURE, "init_lcore_rx_queues failed\n");
 
-       nb_ports = rte_eth_dev_count();
+       nb_ports = rte_eth_dev_count_avail();
 
        if (check_port_config() < 0)
                rte_exit(EXIT_FAILURE, "check_port_config failed\n");
 
        if (ret < 0)
                rte_exit(EXIT_FAILURE, "init_lcore_rx_queues failed\n");
 
-       nb_ports = rte_eth_dev_count();
+       nb_ports = rte_eth_dev_count_avail();
 
        if (check_port_config() < 0)
                rte_exit(EXIT_FAILURE, "check_port_config failed\n");
 
        if (ret < 0)
                rte_exit(EXIT_FAILURE, "init_lcore_rx_queues failed\n");
 
-       nb_ports = rte_eth_dev_count();
+       nb_ports = rte_eth_dev_count_avail();
 
        if (check_port_config() < 0)
                rte_exit(EXIT_FAILURE, "check_port_config failed\n");
 
 LDFLAGS_SHARED = $(shell pkg-config --libs libdpdk)
 LDFLAGS_STATIC = -Wl,-Bstatic $(shell pkg-config --static --libs libdpdk)
 
+CFLAGS += -DALLOW_EXPERIMENTAL_API
+
 build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
        $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
 
 
 include $(RTE_SDK)/mk/rte.vars.mk
 
+CFLAGS += -DALLOW_EXPERIMENTAL_API
 CFLAGS += -O3
 CFLAGS += $(WERROR_FLAGS)
 
 
        if (lsi_pktmbuf_pool == NULL)
                rte_panic("Cannot init mbuf pool\n");
 
-       nb_ports = rte_eth_dev_count();
+       nb_ports = rte_eth_dev_count_avail();
        if (nb_ports == 0)
                rte_panic("No Ethernet port - bye\n");
 
 
 # To build this example as a standalone application with an already-installed
 # DPDK instance, use 'make'
 
+allow_experimental_apis = true
 sources = files(
        'main.c'
 )
 
 # all source are stored in SRCS-y
 SRCS-y := client.c
 
+CFLAGS += -DALLOW_EXPERIMENTAL_API
 CFLAGS += $(WERROR_FLAGS) -O3
 CFLAGS += -I$(SRCDIR)/../shared
 
 
        if (parse_app_args(argc, argv) < 0)
                rte_exit(EXIT_FAILURE, "Invalid command-line arguments\n");
 
-       if (rte_eth_dev_count() == 0)
+       if (rte_eth_dev_count_avail() == 0)
                rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n");
 
        rx_ring = rte_ring_lookup(get_rx_queue_name(client_id));
 
 
 INC := $(sort $(wildcard *.h))
 
+CFLAGS += -DALLOW_EXPERIMENTAL_API
 CFLAGS += $(WERROR_FLAGS) -O3
 CFLAGS += -I$(SRCDIR)/../shared
 
 
        argv += retval;
 
        /* get total number of ports */
-       total_ports = rte_eth_dev_count();
+       total_ports = rte_eth_dev_count_total();
 
        /* set up array for port data */
        mz = rte_memzone_reserve(MZ_PORT_INFO, sizeof(*ports),
 
        for (i = 0; i < RTE_MAX_LCORE; i++)
                lcore_resource[i].lcore_id = i;
 
-       nb_ports = rte_eth_dev_count();
+       nb_ports = rte_eth_dev_count_avail();
        if (nb_ports == 0)
                rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n");
 
 
        argv += ret;
 
        /* determine the NIC devices available */
-       if (rte_eth_dev_count() == 0)
+       if (rte_eth_dev_count_avail() == 0)
                rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n");
 
        /* parse application arguments (those after the EAL ones) */
 
 SRCS-y := bridge.c
 SRCS-y += compat_netmap.c
 
+CFLAGS += -DALLOW_EXPERIMENTAL_API
 CFLAGS += -O3 -I$(SRCDIR)/../lib -I$(SRCDIR)/../netmap
 CFLAGS += $(WERROR_FLAGS)
 
 
        if (ports.num == 0)
                rte_exit(EXIT_FAILURE, "no ports specified\n");
 
-       if (rte_eth_dev_count() < 1)
+       if (rte_eth_dev_count_avail() < 1)
                rte_exit(EXIT_FAILURE, "Not enough ethernet ports available\n");
 
        pool = rte_pktmbuf_pool_create("mbuf_pool", MBUF_PER_POOL, 32, 0,
 
 static int
 worker_thread(void *args_ptr)
 {
-       const uint8_t nb_ports = rte_eth_dev_count();
+       const uint16_t nb_ports = rte_eth_dev_count_avail();
        uint16_t i, ret = 0;
        uint16_t burst_size = 0;
        struct worker_thread_args *args;
                                "1 lcore for packet TX\n"
                                "and at least 1 lcore for worker threads\n");
 
-       nb_ports = rte_eth_dev_count();
+       nb_ports = rte_eth_dev_count_avail();
        if (nb_ports == 0)
                rte_exit(EXIT_FAILURE, "Error: no ethernet ports detected\n");
        if (nb_ports != 1 && (nb_ports & 1))
 
        if (ret < 0)
                rte_exit(EXIT_FAILURE, "init_rx_rings failed\n");
 
-       nb_ports = rte_eth_dev_count();
+       nb_ports = rte_eth_dev_count_avail();
 
        if (check_port_config() < 0)
                rte_exit(EXIT_FAILURE, "check_port_config failed\n");
 
                rte_exit(EXIT_FAILURE, "Error with PTP initialization\n");
 
        /* Check that there is an even number of ports to send/receive on. */
-       nb_ports = rte_eth_dev_count();
+       nb_ports = rte_eth_dev_count_avail();
 
        /* Creates a new mempool in memory to hold the mbufs. */
        mbuf_pool = rte_pktmbuf_pool_create("MBUF_POOL", NUM_MBUFS * nb_ports,
 
 LDFLAGS_SHARED = $(shell pkg-config --libs libdpdk)
 LDFLAGS_STATIC = -Wl,-Bstatic $(shell pkg-config --static --libs libdpdk)
 
+CFLAGS += -DALLOW_EXPERIMENTAL_API
+
 build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build
        $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED)
 
 clean:
 else
 
+CFLAGS += -DALLOW_EXPERIMENTAL_API
 CFLAGS += -O3
 CFLAGS += $(WERROR_FLAGS)
 CFLAGS_args.o := -D_GNU_SOURCE
 
        char ring_name[MAX_NAME_LEN];
        char pool_name[MAX_NAME_LEN];
 
-       if (rte_eth_dev_count() == 0)
+       if (rte_eth_dev_count_avail() == 0)
                rte_exit(EXIT_FAILURE, "No Ethernet port - bye\n");
 
        /* load configuration profile */
 
 # DPDK instance, use 'make'
 
 deps += ['sched', 'cfgfile']
+allow_experimental_apis = true
 sources = files(
        'app_thread.c', 'args.c', 'cfg_file.c', 'cmdline.c',
        'init.c', 'main.c', 'stats.c'
 
 # all source are stored in SRCS-y
 SRCS-y := args.c init.c main.c
 
+CFLAGS += -DALLOW_EXPERIMENTAL_API
 CFLAGS += -O3 -DQW_SOFTWARE_FC
 CFLAGS += $(WERROR_FLAGS)
 
 
 void
 init_dpdk(void)
 {
-       if (rte_eth_dev_count() < 2)
+       if (rte_eth_dev_count_avail() < 2)
                rte_exit(EXIT_FAILURE, "Not enough ethernet port available\n");
 }
 
 
        argc -= ret;
        argv += ret;
 
-       nb_ports = rte_eth_dev_count();
+       nb_ports = rte_eth_dev_count_avail();
        if (nb_ports < 2 || (nb_ports & 1))
                rte_exit(EXIT_FAILURE, "Error: number of ports must be even\n");
 
 
 # all source are stored in SRCS-y
 SRCS-y := node.c
 
+CFLAGS += -DALLOW_EXPERIMENTAL_API
 CFLAGS += $(WERROR_FLAGS) -O3
 CFLAGS += -I$(SRCDIR)/../shared
 
 
        if (parse_app_args(argc, argv) < 0)
                rte_exit(EXIT_FAILURE, "Invalid command-line arguments\n");
 
-       if (rte_eth_dev_count() == 0)
+       if (rte_eth_dev_count_avail() == 0)
                rte_exit(EXIT_FAILURE, "No Ethernet ports - bye\n");
 
        rx_ring = rte_ring_lookup(get_rx_queue_name(node_id));
 
 
 INC := $(sort $(wildcard *.h))
 
+CFLAGS += -DALLOW_EXPERIMENTAL_API
 CFLAGS += $(WERROR_FLAGS) -O3
 CFLAGS += -I$(SRCDIR)/../shared
 
 
        argv += retval;
 
        /* get total number of ports */
-       total_ports = rte_eth_dev_count();
+       total_ports = rte_eth_dev_count_avail();
 
        /* set up array for port data */
        mz = rte_memzone_reserve(MZ_SHARED_INFO, sizeof(*info),
 
        argv += ret;
 
        /* Check that there is an even number of ports to send/receive on. */
-       nb_ports = rte_eth_dev_count();
+       nb_ports = rte_eth_dev_count_avail();
        if (nb_ports < 2 || (nb_ports & 1))
                rte_exit(EXIT_FAILURE, "Error: number of ports must be even\n");
 
 
 sources = files(
        'basicfwd.c'
 )
+
+allow_experimental_apis = true
 
        nb_switching_cores = rte_lcore_count()-1;
 
        /* Get the number of physical ports. */
-       nb_ports = rte_eth_dev_count();
+       nb_ports = rte_eth_dev_count_avail();
 
        /*
         * Update the global var NB_PORTS and global array PORTS
 
                rte_exit(EXIT_FAILURE,"Not enough cores\n");
 
        /* Get the number of physical ports. */
-       nb_ports = rte_eth_dev_count();
+       nb_ports = rte_eth_dev_count_avail();
 
        /*
         * Update the global var NUM_PORTS and global array PORTS
 
        if (ret < 0)
                rte_exit(EXIT_FAILURE, "Invalid arguments\n");
 
-       nb_ports = rte_eth_dev_count();
+       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 (rte_lcore_count() > RTE_MAX_LCORE)
                rte_exit(EXIT_FAILURE, "Not enough cores\n");
 
-       nb_ports = rte_eth_dev_count();
+       nb_ports = rte_eth_dev_count_avail();
 
        /*
         * Update the global var NUM_PORTS and global array PORTS
 
                                " number of cores(1-%d)\n\n", RTE_MAX_LCORE);
        }
 
-       nb_ports = rte_eth_dev_count();
+       nb_ports = rte_eth_dev_count_avail();
 
        /*
         * Update the global var NUM_PORTS and global array PORTS
 
 
 uint16_t
 rte_eth_dev_count(void)
+{
+       return rte_eth_dev_count_avail();
+}
+
+uint16_t
+rte_eth_dev_count_avail(void)
 {
        uint16_t p;
        uint16_t count;
        return count;
 }
 
+uint16_t
+rte_eth_dev_count_total(void)
+{
+       uint16_t port, count = 0;
+
+       for (port = 0; port < RTE_MAX_ETHPORTS; port++)
+               if (rte_eth_devices[port].state != RTE_ETH_DEV_UNUSED)
+                       count++;
+
+       return count;
+}
+
 int
 rte_eth_dev_get_name_by_port(uint16_t port_id, char *name)
 {
 rte_eth_dev_attach(const char *devargs, uint16_t *port_id)
 {
        int ret = -1;
-       int current = rte_eth_dev_count();
+       int current = rte_eth_dev_count_total();
        char *name = NULL;
        char *args = NULL;
 
                goto err;
 
        /* no point looking at the port count if no port exists */
-       if (!rte_eth_dev_count()) {
+       if (!rte_eth_dev_count_total()) {
                ethdev_log(ERR, "No port found for device (%s)", name);
                ret = -1;
                goto err;
 
        /* if nothing happened, there is a bug here, since some driver told us
         * it did attach a device, but did not create a port.
+        * FIXME: race condition in case of plug-out of another device
         */
-       if (current == rte_eth_dev_count()) {
+       if (current == rte_eth_dev_count_total()) {
                ret = -1;
                goto err;
        }
 
  * @return
  *   - The total number of usable Ethernet devices.
  */
+__rte_deprecated
 uint16_t rte_eth_dev_count(void);
 
+/**
+ * Get the number of ports which are usable for the application.
+ *
+ * These devices must be iterated by using the macro
+ * ``RTE_ETH_FOREACH_DEV`` or ``RTE_ETH_FOREACH_DEV_OWNED_BY``
+ * to deal with non-contiguous ranges of devices.
+ *
+ * @return
+ *   The count of available Ethernet devices.
+ */
+uint16_t __rte_experimental rte_eth_dev_count_avail(void);
+
+/**
+ * Get the total number of ports which are allocated.
+ *
+ * Some devices may not be available for the application.
+ *
+ * @return
+ *   The total count of Ethernet devices.
+ */
+uint16_t __rte_experimental rte_eth_dev_count_total(void);
+
 /**
  * Attach a new Ethernet device specified by arguments.
  *
 
 EXPERIMENTAL {
        global:
 
+       rte_eth_dev_count_avail;
+       rte_eth_dev_count_total;
        rte_eth_dev_is_removed;
        rte_eth_dev_owner_delete;
        rte_eth_dev_owner_get;
        rte_mtr_stats_read;
        rte_mtr_stats_update;
 
-} DPDK_17.11;
+} DPDK_18.02;
 
        rx_adapter->conf_arg = conf_arg;
        strcpy(rx_adapter->mem_name, mem_name);
        rx_adapter->eth_devices = rte_zmalloc_socket(rx_adapter->mem_name,
-                                       rte_eth_dev_count() *
+                                       /* FIXME: incompatible with hotplug */
+                                       rte_eth_dev_count_total() *
                                        sizeof(struct eth_device_info), 0,
                                        socket_id);
        rte_convert_rss_key((const uint32_t *)default_rss_key,
 
         * so rte_eth_dev_start invokes rte_event_dev_start internally, so
         * call init_ports after rte_event_dev_configure
         */
-       err = init_ports(rte_eth_dev_count());
+       err = init_ports(rte_eth_dev_count_total());
        TEST_ASSERT(err == 0, "Port initialization failed err %d\n", err);
 
        err = rte_event_eth_rx_adapter_caps_get(TEST_DEV_ID, TEST_ETHDEV_ID,
        queue_config.servicing_weight = 1;
 
        err = rte_event_eth_rx_adapter_queue_add(TEST_INST_ID,
-                                               rte_eth_dev_count(),
+                                               rte_eth_dev_count_total(),
                                                -1, &queue_config);
        TEST_ASSERT(err == -EINVAL, "Expected -EINVAL got %d", err);
 
 
                return -1;
        }
 
-       nb_ports = rte_eth_dev_count();
+       nb_ports = rte_eth_dev_count_avail();
        if (nb_ports == 0) {
                printf("no supported nic port found\n");
                return -1;
 
                        TEST_ASSERT(retval >= 0,
                                "Failed to create ring ethdev '%s'\n", name);
 
-                       port->port_id = rte_eth_dev_count() - 1;
+                       port->port_id = rte_eth_dev_count_avail() - 1;
                }
 
                retval = configure_ethdev(port->port_id, 1);
 
        FOR_EACH_PORT(n, port) {
                port = &test_params.slave_ports[n];
 
-               port_id = rte_eth_dev_count();
+               port_id = rte_eth_dev_count_avail();
                snprintf(name, sizeof(name), SLAVE_DEV_NAME_FMT, port_id);
 
                retval = rte_vdev_init(name, "size=64,copy=0");
 
        signal(SIGUSR1, signal_handler);
        signal(SIGUSR2, signal_handler);
 
-       nb_ports = rte_eth_dev_count();
+       nb_ports = rte_eth_dev_count_avail();
        if (nb_ports < NB_ETHPORTS_USED) {
                printf("At least %u port(s) used for perf. test\n",
                       NB_ETHPORTS_USED);
 
        int port, cmdl_port0 = -1;
        uint8_t nb_ports;
 
-       nb_ports = rte_eth_dev_count();
+       nb_ports = rte_eth_dev_count_avail();
        printf("nb_ports=%d\n", (int)nb_ports);
 
        /*  create the rings and eth_rings in the test code.