X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=examples%2Fkni%2Fmain.c;h=8bea07182f7f05d689ad347d1b62c36bcebbf3ca;hb=6d13ea8e8e49ab957deae2bba5ecf4a4bfe747d1;hp=274990b31942adedb7ce4991c3f055785c196ee0;hpb=13c4ebd65a77fae2d6c5a08a2a2f3498758b68d2;p=dpdk.git diff --git a/examples/kni/main.c b/examples/kni/main.c index 274990b319..8bea07182f 100644 --- a/examples/kni/main.c +++ b/examples/kni/main.c @@ -1,34 +1,5 @@ -/*- - * BSD LICENSE - * - * Copyright(c) 2010-2014 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. +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2010-2014 Intel Corporation */ #include @@ -53,8 +24,6 @@ #include #include #include -#include -#include #include #include #include @@ -62,12 +31,10 @@ #include #include #include -#include +#include #include #include #include -#include -#include #include #include #include @@ -81,9 +48,8 @@ /* Max size of a single packet */ #define MAX_PACKET_SZ 2048 -/* Number of bytes needed for each mbuf */ -#define MBUF_SZ \ - (MAX_PACKET_SZ + sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM) +/* Size of the data buffer in each mbuf */ +#define MBUF_DATA_SZ (MAX_PACKET_SZ + RTE_PKTMBUF_HEADROOM) /* Number of mbufs in mempool that is created */ #define NB_MBUF (8192 * 16) @@ -95,10 +61,10 @@ #define MEMPOOL_CACHE_SZ PKT_BURST_SZ /* Number of RX ring descriptors */ -#define NB_RXD 128 +#define NB_RXD 1024 /* Number of TX ring descriptors */ -#define NB_TXD 512 +#define NB_TXD 1024 /* Total octets in ethernet header */ #define KNI_ENET_HEADER_SIZE 14 @@ -114,7 +80,7 @@ * Structure of port parameters */ struct kni_port_params { - uint8_t port_id;/* Port ID */ + uint16_t port_id;/* Port ID */ unsigned lcore_rx; /* lcore ID for RX */ unsigned lcore_tx; /* lcore ID for TX */ uint32_t nb_lcore_k; /* Number of lcores for KNI multi kernel threads */ @@ -125,46 +91,9 @@ struct kni_port_params { static struct kni_port_params *kni_port_params_array[RTE_MAX_ETHPORTS]; -/* RX and TX Prefetch, Host, and Write-back threshold values should be - * carefully set for optimal performance. Consult the network - * controller's datasheet and supporting DPDK documentation for guidance - * on how these parameters should be set. - */ -/* RX ring configuration */ -static const struct rte_eth_rxconf rx_conf = { - .rx_thresh = { - .pthresh = 8, /* Ring prefetch threshold */ - .hthresh = 8, /* Ring host threshold */ - .wthresh = 4, /* Ring writeback threshold */ - }, - .rx_free_thresh = 0, /* Immediately free RX descriptors */ -}; - -/* - * These default values are optimized for use with the Intel(R) 82599 10 GbE - * Controller and the DPDK ixgbe PMD. Consider using other values for other - * network controllers and/or network drivers. - */ -/* TX ring configuration */ -static const struct rte_eth_txconf tx_conf = { - .tx_thresh = { - .pthresh = 36, /* Ring prefetch threshold */ - .hthresh = 0, /* Ring host threshold */ - .wthresh = 0, /* Ring writeback threshold */ - }, - .tx_free_thresh = 0, /* Use PMD default values */ - .tx_rs_thresh = 0, /* Use PMD default values */ -}; /* Options for configuring ethernet port */ static struct rte_eth_conf port_conf = { - .rxmode = { - .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 */ - }, .txmode = { .mq_mode = ETH_MQ_TX_NONE, }, @@ -177,6 +106,8 @@ static struct rte_mempool * pktmbuf_pool = NULL; static uint32_t ports_mask = 0; /* Ports set in promiscuous mode off by default. */ static int promiscuous_on = 0; +/* Monitor link status continually. off by default. */ +static int monitor_links; /* Structure type for recording kni interface specific stats */ struct kni_interface_stats { @@ -196,16 +127,18 @@ struct kni_interface_stats { /* kni device statistics array */ static struct kni_interface_stats kni_stats[RTE_MAX_ETHPORTS]; -static int kni_change_mtu(uint8_t port_id, unsigned new_mtu); -static int kni_config_network_interface(uint8_t port_id, uint8_t if_up); +static int kni_change_mtu(uint16_t port_id, unsigned int new_mtu); +static int kni_config_network_interface(uint16_t port_id, uint8_t if_up); +static int kni_config_mac_address(uint16_t port_id, uint8_t mac_addr[]); static rte_atomic32_t kni_stop = RTE_ATOMIC32_INIT(0); +static rte_atomic32_t kni_pause = RTE_ATOMIC32_INIT(0); /* Print out statistics on packets handled */ static void print_stats(void) { - uint8_t i; + uint16_t i; printf("\n**KNI example application statistics**\n" "====== ============== ============ ============ ============ ============\n" @@ -239,14 +172,13 @@ signal_handler(int signum) /* When we receive a USR2 signal, reset stats */ if (signum == SIGUSR2) { memset(&kni_stats, 0, sizeof(kni_stats)); - printf("\n**Statistics have been reset**\n"); + printf("\n** Statistics have been reset **\n"); return; } /* When we receive a RTMIN or SIGINT signal, stop kni processing */ if (signum == SIGRTMIN || signum == SIGINT){ - printf("SIGRTMIN is received, and the KNI processing is " - "going to stop\n"); + printf("\nSIGRTMIN/SIGINT received. KNI processing stopping.\n"); rte_atomic32_inc(&kni_stop); return; } @@ -272,7 +204,8 @@ kni_burst_free_mbufs(struct rte_mbuf **pkts, unsigned num) static void kni_ingress(struct kni_port_params *p) { - uint8_t i, port_id; + uint8_t i; + uint16_t port_id; unsigned nb_rx, num; uint32_t nb_kni; struct rte_mbuf *pkts_burst[PKT_BURST_SZ]; @@ -291,7 +224,8 @@ kni_ingress(struct kni_port_params *p) } /* Burst tx to kni */ num = rte_kni_tx_burst(p->kni[i], pkts_burst, nb_rx); - kni_stats[port_id].rx_packets += num; + if (num) + kni_stats[port_id].rx_packets += num; rte_kni_handle_request(p->kni[i]); if (unlikely(num < nb_rx)) { @@ -308,7 +242,8 @@ kni_ingress(struct kni_port_params *p) static void kni_egress(struct kni_port_params *p) { - uint8_t i, port_id; + uint8_t i; + uint16_t port_id; unsigned nb_tx, num; uint32_t nb_kni; struct rte_mbuf *pkts_burst[PKT_BURST_SZ]; @@ -327,7 +262,8 @@ kni_egress(struct kni_port_params *p) } /* Burst tx to eth */ nb_tx = rte_eth_tx_burst(port_id, 0, pkts_burst, (uint16_t)num); - kni_stats[port_id].tx_packets += nb_tx; + if (nb_tx) + kni_stats[port_id].tx_packets += nb_tx; if (unlikely(nb_tx < num)) { /* Free mbufs not tx to NIC */ kni_burst_free_mbufs(&pkts_burst[nb_tx], num - nb_tx); @@ -339,8 +275,9 @@ kni_egress(struct kni_port_params *p) static int main_loop(__rte_unused void *arg) { - uint8_t i, nb_ports = rte_eth_dev_count(); + uint16_t i; int32_t f_stop; + int32_t f_pause; const unsigned lcore_id = rte_lcore_id(); enum lcore_rxtx { LCORE_NONE, @@ -350,9 +287,7 @@ main_loop(__rte_unused void *arg) }; enum lcore_rxtx flag = LCORE_NONE; - nb_ports = (uint8_t)(nb_ports < RTE_MAX_ETHPORTS ? - nb_ports : RTE_MAX_ETHPORTS); - for (i = 0; i < nb_ports; i++) { + RTE_ETH_FOREACH_DEV(i) { if (!kni_port_params_array[i]) continue; if (kni_port_params_array[i]->lcore_rx == (uint8_t)lcore_id) { @@ -371,8 +306,11 @@ main_loop(__rte_unused void *arg) kni_port_params_array[i]->port_id); while (1) { f_stop = rte_atomic32_read(&kni_stop); + f_pause = rte_atomic32_read(&kni_pause); if (f_stop) break; + if (f_pause) + continue; kni_ingress(kni_port_params_array[i]); } } else if (flag == LCORE_TX) { @@ -381,8 +319,11 @@ main_loop(__rte_unused void *arg) kni_port_params_array[i]->port_id); while (1) { f_stop = rte_atomic32_read(&kni_stop); + f_pause = rte_atomic32_read(&kni_pause); if (f_stop) break; + if (f_pause) + continue; kni_egress(kni_port_params_array[i]); } } else @@ -395,11 +336,12 @@ main_loop(__rte_unused void *arg) static void print_usage(const char *prgname) { - RTE_LOG(INFO, APP, "\nUsage: %s [EAL options] -- -p PORTMASK -P " + RTE_LOG(INFO, APP, "\nUsage: %s [EAL options] -- -p PORTMASK -P -m " "[--config (port,lcore_rx,lcore_tx,lcore_kthread...)" "[,(port,lcore_rx,lcore_tx,lcore_kthread...)]]\n" " -p PORTMASK: hex bitmask of ports to use\n" " -P : enable promiscuous mode\n" + " -m : enable monitoring of port carrier state\n" " --config (port,lcore_rx,lcore_tx,lcore_kthread...): " "port and lcore configurations\n", prgname); @@ -452,7 +394,7 @@ parse_config(const char *arg) int i, j, nb_token; char *str_fld[_NUM_FLD]; unsigned long int_fld[_NUM_FLD]; - uint8_t port_id, nb_kni_port_params = 0; + uint16_t port_id, nb_kni_port_params = 0; memset(&kni_port_params_array, 0, sizeof(kni_port_params_array)); while (((p = strchr(p0, '(')) != NULL) && @@ -465,7 +407,7 @@ parse_config(const char *arg) printf("Invalid config parameters\n"); goto fail; } - rte_snprintf(s, sizeof(s), "%.*s", size, p); + snprintf(s, sizeof(s), "%.*s", size, p); nb_token = rte_strsplit(s, sizeof(s), str_fld, _NUM_FLD, ','); if (nb_token <= FLD_LCORE_TX) { printf("Invalid config parameters\n"); @@ -481,7 +423,7 @@ parse_config(const char *arg) } i = 0; - port_id = (uint8_t)int_fld[i++]; + port_id = int_fld[i++]; if (port_id >= RTE_MAX_ETHPORTS) { printf("Port ID %d could not exceed the maximum %d\n", port_id, RTE_MAX_ETHPORTS); @@ -491,9 +433,9 @@ parse_config(const char *arg) printf("Port %d has been configured\n", port_id); goto fail; } - kni_port_params_array[port_id] = - (struct kni_port_params*)rte_zmalloc("KNI_port_params", - sizeof(struct kni_port_params), CACHE_LINE_SIZE); + kni_port_params_array[port_id] = + rte_zmalloc("KNI_port_params", + sizeof(struct kni_port_params), RTE_CACHE_LINE_SIZE); kni_port_params_array[port_id]->port_id = port_id; kni_port_params_array[port_id]->lcore_rx = (uint8_t)int_fld[i++]; @@ -557,7 +499,7 @@ validate_parameters(uint32_t portmask) "port %d transmitting not enabled\n", kni_port_params_array[i]->lcore_tx, kni_port_params_array[i]->port_id); - + } return 0; @@ -580,7 +522,7 @@ parse_args(int argc, char **argv) opterr = 0; /* Parse command line */ - while ((opt = getopt_long(argc, argv, "p:P", longopts, + while ((opt = getopt_long(argc, argv, "p:Pm", longopts, &longindex)) != EOF) { switch (opt) { case 'p': @@ -589,6 +531,9 @@ parse_args(int argc, char **argv) case 'P': promiscuous_on = 1; break; + case 'm': + monitor_links = 1; + break; case 0: if (!strncmp(longopts[longindex].name, CMDLINE_OPT_CONFIG, @@ -616,28 +561,66 @@ parse_args(int argc, char **argv) return ret; } +/* Initialize KNI subsystem */ +static void +init_kni(void) +{ + unsigned int num_of_kni_ports = 0, i; + struct kni_port_params **params = kni_port_params_array; + + /* Calculate the maximum number of KNI interfaces that will be used */ + for (i = 0; i < RTE_MAX_ETHPORTS; i++) { + if (kni_port_params_array[i]) { + num_of_kni_ports += (params[i]->nb_lcore_k ? + params[i]->nb_lcore_k : 1); + } + } + + /* Invoke rte KNI init to preallocate the ports */ + rte_kni_init(num_of_kni_ports); +} + /* Initialise a single port on an Ethernet device */ static void -init_port(uint8_t port) +init_port(uint16_t port) { int ret; + uint16_t nb_rxd = NB_RXD; + uint16_t nb_txd = NB_TXD; + struct rte_eth_dev_info dev_info; + struct rte_eth_rxconf rxq_conf; + struct rte_eth_txconf txq_conf; + struct rte_eth_conf local_port_conf = port_conf; /* Initialise device and RX/TX queues */ RTE_LOG(INFO, APP, "Initialising port %u ...\n", (unsigned)port); fflush(stdout); - ret = rte_eth_dev_configure(port, 1, 1, &port_conf); + rte_eth_dev_info_get(port, &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(port, 1, 1, &local_port_conf); if (ret < 0) rte_exit(EXIT_FAILURE, "Could not configure port%u (%d)\n", (unsigned)port, ret); - ret = rte_eth_rx_queue_setup(port, 0, NB_RXD, - rte_eth_dev_socket_id(port), &rx_conf, pktmbuf_pool); + ret = rte_eth_dev_adjust_nb_rx_tx_desc(port, &nb_rxd, &nb_txd); + if (ret < 0) + rte_exit(EXIT_FAILURE, "Could not adjust number of descriptors " + "for port%u (%d)\n", (unsigned)port, ret); + + rxq_conf = dev_info.default_rxconf; + rxq_conf.offloads = local_port_conf.rxmode.offloads; + ret = rte_eth_rx_queue_setup(port, 0, nb_rxd, + rte_eth_dev_socket_id(port), &rxq_conf, pktmbuf_pool); if (ret < 0) rte_exit(EXIT_FAILURE, "Could not setup up RX queue for " "port%u (%d)\n", (unsigned)port, ret); - ret = rte_eth_tx_queue_setup(port, 0, NB_TXD, - rte_eth_dev_socket_id(port), &tx_conf); + txq_conf = dev_info.default_txconf; + 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); if (ret < 0) rte_exit(EXIT_FAILURE, "Could not setup up TX queue for " "port%u (%d)\n", (unsigned)port, ret); @@ -653,18 +636,19 @@ init_port(uint8_t port) /* Check the link status of all ports in up to 9s, and print them finally */ static void -check_all_ports_link_status(uint8_t port_num, uint32_t port_mask) +check_all_ports_link_status(uint32_t port_mask) { #define CHECK_INTERVAL 100 /* 100ms */ #define MAX_CHECK_TIME 90 /* 9s (90 * 100ms) in total */ - uint8_t portid, count, all_ports_up, print_flag = 0; + uint16_t portid; + uint8_t count, all_ports_up, print_flag = 0; struct rte_eth_link link; printf("\nChecking link status\n"); fflush(stdout); for (count = 0; count <= MAX_CHECK_TIME; count++) { all_ports_up = 1; - for (portid = 0; portid < port_num; portid++) { + RTE_ETH_FOREACH_DEV(portid) { if ((port_mask & (1 << portid)) == 0) continue; memset(&link, 0, sizeof(link)); @@ -672,18 +656,17 @@ check_all_ports_link_status(uint8_t port_num, uint32_t port_mask) /* print link status if flag set */ if (print_flag == 1) { if (link.link_status) - printf("Port %d Link Up - speed %u " - "Mbps - %s\n", (uint8_t)portid, - (unsigned)link.link_speed, + printf( + "Port%d Link Up - speed %uMbps - %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", - (uint8_t)portid); + printf("Port %d Link Down\n", portid); continue; } /* clear all_ports_up flag if any link down */ - if (link.link_status == 0) { + if (link.link_status == ETH_LINK_DOWN) { all_ports_up = 0; break; } @@ -706,14 +689,66 @@ check_all_ports_link_status(uint8_t port_num, uint32_t port_mask) } } +static void +log_link_state(struct rte_kni *kni, int prev, struct rte_eth_link *link) +{ + if (kni == NULL || link == NULL) + return; + + if (prev == ETH_LINK_DOWN && link->link_status == ETH_LINK_UP) { + RTE_LOG(INFO, APP, "%s NIC Link is Up %d Mbps %s %s.\n", + rte_kni_get_name(kni), + link->link_speed, + link->link_autoneg ? "(AutoNeg)" : "(Fixed)", + link->link_duplex ? "Full Duplex" : "Half Duplex"); + } else if (prev == ETH_LINK_UP && link->link_status == ETH_LINK_DOWN) { + RTE_LOG(INFO, APP, "%s NIC Link is Down.\n", + rte_kni_get_name(kni)); + } +} + +/* + * Monitor the link status of all ports and update the + * corresponding KNI interface(s) + */ +static void * +monitor_all_ports_link_status(void *arg) +{ + uint16_t portid; + struct rte_eth_link link; + unsigned int i; + struct kni_port_params **p = kni_port_params_array; + int prev; + (void) arg; + + while (monitor_links) { + rte_delay_ms(500); + RTE_ETH_FOREACH_DEV(portid) { + if ((ports_mask & (1 << portid)) == 0) + continue; + memset(&link, 0, sizeof(link)); + rte_eth_link_get_nowait(portid, &link); + for (i = 0; i < p[portid]->nb_kni; i++) { + prev = rte_kni_update_link(p[portid]->kni[i], + link.link_status); + log_link_state(p[portid]->kni[i], prev, &link); + } + } + } + return NULL; +} + /* Callback for request of changing MTU */ static int -kni_change_mtu(uint8_t port_id, unsigned new_mtu) +kni_change_mtu(uint16_t port_id, unsigned int new_mtu) { int ret; + uint16_t nb_rxd = NB_RXD; struct rte_eth_conf conf; + struct rte_eth_dev_info dev_info; + struct rte_eth_rxconf rxq_conf; - if (port_id >= rte_eth_dev_count()) { + if (!rte_eth_dev_is_valid_port(port_id)) { RTE_LOG(ERR, APP, "Invalid port id %d\n", port_id); return -EINVAL; } @@ -726,9 +761,9 @@ kni_change_mtu(uint8_t port_id, unsigned new_mtu) memcpy(&conf, &port_conf, sizeof(conf)); /* Set new MTU */ if (new_mtu > ETHER_MAX_LEN) - conf.rxmode.jumbo_frame = 1; - else - conf.rxmode.jumbo_frame = 0; + conf.rxmode.offloads |= DEV_RX_OFFLOAD_JUMBO_FRAME; + else + conf.rxmode.offloads &= ~DEV_RX_OFFLOAD_JUMBO_FRAME; /* mtu + length of header + length of FCS = max pkt length */ conf.rxmode.max_rx_pkt_len = new_mtu + KNI_ENET_HEADER_SIZE + @@ -739,6 +774,23 @@ kni_change_mtu(uint8_t port_id, unsigned new_mtu) return ret; } + ret = rte_eth_dev_adjust_nb_rx_tx_desc(port_id, &nb_rxd, NULL); + if (ret < 0) + rte_exit(EXIT_FAILURE, "Could not adjust number of descriptors " + "for port%u (%d)\n", (unsigned int)port_id, + ret); + + rte_eth_dev_info_get(port_id, &dev_info); + rxq_conf = dev_info.default_rxconf; + rxq_conf.offloads = conf.rxmode.offloads; + ret = rte_eth_rx_queue_setup(port_id, 0, nb_rxd, + rte_eth_dev_socket_id(port_id), &rxq_conf, pktmbuf_pool); + if (ret < 0) { + RTE_LOG(ERR, APP, "Fail to setup Rx queue of port %d\n", + port_id); + return ret; + } + /* Restart specific port */ ret = rte_eth_dev_start(port_id); if (ret < 0) { @@ -751,11 +803,11 @@ kni_change_mtu(uint8_t port_id, unsigned new_mtu) /* Callback for request of configuring network interface up/down */ static int -kni_config_network_interface(uint8_t port_id, uint8_t if_up) +kni_config_network_interface(uint16_t port_id, uint8_t if_up) { int ret = 0; - if (port_id >= rte_eth_dev_count() || port_id >= RTE_MAX_ETHPORTS) { + if (!rte_eth_dev_is_valid_port(port_id)) { RTE_LOG(ERR, APP, "Invalid port id %d\n", port_id); return -EINVAL; } @@ -763,20 +815,55 @@ kni_config_network_interface(uint8_t port_id, uint8_t if_up) RTE_LOG(INFO, APP, "Configure network interface of %d %s\n", port_id, if_up ? "up" : "down"); + rte_atomic32_inc(&kni_pause); + if (if_up != 0) { /* Configure network interface up */ rte_eth_dev_stop(port_id); ret = rte_eth_dev_start(port_id); } else /* Configure network interface down */ rte_eth_dev_stop(port_id); + rte_atomic32_dec(&kni_pause); + if (ret < 0) RTE_LOG(ERR, APP, "Failed to start port %d\n", port_id); return ret; } +static void +print_ethaddr(const char *name, struct rte_ether_addr *mac_addr) +{ + char buf[ETHER_ADDR_FMT_SIZE]; + ether_format_addr(buf, ETHER_ADDR_FMT_SIZE, mac_addr); + RTE_LOG(INFO, APP, "\t%s%s\n", name, buf); +} + +/* Callback for request of configuring mac address */ +static int +kni_config_mac_address(uint16_t port_id, uint8_t mac_addr[]) +{ + int ret = 0; + + if (!rte_eth_dev_is_valid_port(port_id)) { + RTE_LOG(ERR, APP, "Invalid port id %d\n", port_id); + return -EINVAL; + } + + RTE_LOG(INFO, APP, "Configure mac address of %d\n", port_id); + print_ethaddr("Address:", (struct rte_ether_addr *)mac_addr); + + ret = rte_eth_dev_default_mac_addr_set(port_id, + (struct rte_ether_addr *)mac_addr); + if (ret < 0) + RTE_LOG(ERR, APP, "Failed to config mac_addr for port %d\n", + port_id); + + return ret; +} + static int -kni_alloc(uint8_t port_id) +kni_alloc(uint16_t port_id) { uint8_t i; struct rte_kni *kni; @@ -793,14 +880,14 @@ kni_alloc(uint8_t port_id) /* Clear conf at first */ memset(&conf, 0, sizeof(conf)); if (params[port_id]->nb_lcore_k) { - rte_snprintf(conf.name, RTE_KNI_NAMESIZE, + snprintf(conf.name, RTE_KNI_NAMESIZE, "vEth%u_%u", port_id, i); conf.core_id = params[port_id]->lcore_k[i]; conf.force_bind = 1; } else - rte_snprintf(conf.name, RTE_KNI_NAMESIZE, + snprintf(conf.name, RTE_KNI_NAMESIZE, "vEth%u", port_id); - conf.group_id = (uint16_t)port_id; + conf.group_id = port_id; conf.mbuf_size = MAX_PACKET_SZ; /* * The first KNI device associated to a port @@ -810,16 +897,30 @@ kni_alloc(uint8_t port_id) if (i == 0) { struct rte_kni_ops ops; struct rte_eth_dev_info dev_info; + const struct rte_pci_device *pci_dev; + const struct rte_bus *bus = NULL; memset(&dev_info, 0, sizeof(dev_info)); rte_eth_dev_info_get(port_id, &dev_info); - conf.addr = dev_info.pci_dev->addr; - conf.id = dev_info.pci_dev->id; + + if (dev_info.device) + bus = rte_bus_find_by_device(dev_info.device); + if (bus && !strcmp(bus->name, "pci")) { + pci_dev = RTE_DEV_TO_PCI(dev_info.device); + conf.addr = pci_dev->addr; + conf.id = pci_dev->id; + } + /* Get the interface default mac address */ + rte_eth_macaddr_get(port_id, + (struct rte_ether_addr *)&conf.mac_addr); + + rte_eth_dev_get_mtu(port_id, &conf.mtu); memset(&ops, 0, sizeof(ops)); ops.port_id = port_id; ops.change_mtu = kni_change_mtu; ops.config_network_if = kni_config_network_interface; + ops.config_mac_address = kni_config_mac_address; kni = rte_kni_alloc(pktmbuf_pool, &conf, &ops); } else @@ -835,7 +936,7 @@ kni_alloc(uint8_t port_id) } static int -kni_free_kni(uint8_t port_id) +kni_free_kni(uint16_t port_id) { uint8_t i; struct kni_port_params **p = kni_port_params_array; @@ -843,9 +944,10 @@ kni_free_kni(uint8_t port_id) if (port_id >= RTE_MAX_ETHPORTS || !p[port_id]) return -1; - for (i = 0; i < p[i]->nb_kni; i++) { - rte_kni_release(p[i]->kni[i]); - p[i]->kni[i] = NULL; + for (i = 0; i < p[port_id]->nb_kni; i++) { + if (rte_kni_release(p[port_id]->kni[i])) + printf("Fail to release kni\n"); + p[port_id]->kni[i] = NULL; } rte_eth_dev_stop(port_id); @@ -857,8 +959,11 @@ int main(int argc, char** argv) { int ret; - uint8_t nb_sys_ports, port; + uint16_t nb_sys_ports, port; unsigned i; + void *retval; + pthread_t kni_link_tid; + int pid; /* Associate signal_hanlder function with USR signals */ signal(SIGUSR1, signal_handler); @@ -879,41 +984,29 @@ main(int argc, char** argv) rte_exit(EXIT_FAILURE, "Could not parse input parameters\n"); /* Create the mbuf pool */ - pktmbuf_pool = rte_mempool_create("mbuf_pool", NB_MBUF, MBUF_SZ, - MEMPOOL_CACHE_SZ, - sizeof(struct rte_pktmbuf_pool_private), - rte_pktmbuf_pool_init, NULL, rte_pktmbuf_init, NULL, - rte_socket_id(), 0); + pktmbuf_pool = rte_pktmbuf_pool_create("mbuf_pool", NB_MBUF, + MEMPOOL_CACHE_SZ, 0, MBUF_DATA_SZ, rte_socket_id()); if (pktmbuf_pool == NULL) { rte_exit(EXIT_FAILURE, "Could not initialise mbuf pool\n"); return -1; } - /* Initialise PMD driver(s) */ - ret = rte_pmd_init_all(); - if (ret < 0) - rte_exit(EXIT_FAILURE, "Could not initialise PMD (%d)\n", ret); - - /* Scan PCI bus for recognised devices */ - ret = rte_eal_pci_probe(); - if (ret < 0) - rte_exit(EXIT_FAILURE, "Could not probe PCI (%d)\n", ret); - /* 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 devices found - " - "check that CONFIG_RTE_LIBRTE_IGB_PMD=y and/or " - "CONFIG_RTE_LIBRTE_IXGBE_PMD=y in the config file\n"); + rte_exit(EXIT_FAILURE, "No supported Ethernet device found\n"); /* Check if the configured port ID is valid */ for (i = 0; i < RTE_MAX_ETHPORTS; i++) - if (kni_port_params_array[i] && i >= nb_sys_ports) + if (kni_port_params_array[i] && !rte_eth_dev_is_valid_port(i)) rte_exit(EXIT_FAILURE, "Configured invalid " "port ID %u\n", i); + /* Initialize KNI subsystem */ + init_kni(); + /* Initialise each port */ - for (port = 0; port < nb_sys_ports; port++) { + RTE_ETH_FOREACH_DEV(port) { /* Skip ports that are not enabled */ if (!(ports_mask & (1 << port))) continue; @@ -925,7 +1018,24 @@ main(int argc, char** argv) kni_alloc(port); } - check_all_ports_link_status(nb_sys_ports, ports_mask); + check_all_ports_link_status(ports_mask); + + pid = getpid(); + RTE_LOG(INFO, APP, "========================\n"); + RTE_LOG(INFO, APP, "KNI Running\n"); + RTE_LOG(INFO, APP, "kill -SIGUSR1 %d\n", pid); + RTE_LOG(INFO, APP, " Show KNI Statistics.\n"); + RTE_LOG(INFO, APP, "kill -SIGUSR2 %d\n", pid); + RTE_LOG(INFO, APP, " Zero KNI Statistics.\n"); + RTE_LOG(INFO, APP, "========================\n"); + fflush(stdout); + + ret = rte_ctrl_thread_create(&kni_link_tid, + "KNI link status check", NULL, + monitor_all_ports_link_status, NULL); + if (ret < 0) + rte_exit(EXIT_FAILURE, + "Could not create link status thread!\n"); /* Launch per-lcore function on every lcore */ rte_eal_mp_remote_launch(main_loop, NULL, CALL_MASTER); @@ -933,16 +1043,15 @@ main(int argc, char** argv) if (rte_eal_wait_lcore(i) < 0) return -1; } + monitor_links = 0; + pthread_join(kni_link_tid, &retval); /* Release resources */ - for (port = 0; port < nb_sys_ports; port++) { + RTE_ETH_FOREACH_DEV(port) { if (!(ports_mask & (1 << port))) continue; kni_free_kni(port); } -#ifdef RTE_LIBRTE_XEN_DOM0 - rte_kni_close(); -#endif for (i = 0; i < RTE_MAX_ETHPORTS; i++) if (kni_port_params_array[i]) { rte_free(kni_port_params_array[i]); @@ -951,4 +1060,3 @@ main(int argc, char** argv) return 0; } -