This commit brings in a link status check so that the generator will
only start sending packets once there is something on the other end of
the link.
Signed-off-by: Ronan Randles <ronan.randles@intel.com>
---
examples/generator/main.c | 68 ++++++++++++++++++++++++++++++++++++++-
1 file changed, 67 insertions(+), 1 deletion(-)
@@ -27,9 +27,13 @@ static const struct rte_eth_conf port_conf_default = {
.rxmode = {
.max_lro_pkt_size = RTE_ETHER_MAX_LEN,
},
+ .intr_conf = {
+ .lsc = 1, /**< lsc interrupt */
+ },
};
static volatile int done;
+static volatile int link_status[RTE_MAX_ETHPORTS];
static struct rte_mempool *mbuf_pool;
struct rte_gen *gen;
@@ -56,6 +60,30 @@ static struct telemetry_userdata telemetry_userdata;
static void handle_sigint(int sig);
+static int
+link_status_change_cb(uint16_t port_id, enum rte_eth_event_type type,
+ void *param, void *ret_param)
+{
+ if (unlikely(port_id >= RTE_DIM(link_status)))
+ rte_panic("got LSC interrupt for unknown port id\n");
+
+ RTE_SET_USED(type);
+ RTE_SET_USED(param);
+ RTE_SET_USED(ret_param);
+
+ struct rte_eth_link link;
+ int ret = rte_eth_link_get_nowait(port_id, &link);
+ if (ret < 0) {
+ printf("Failed link get on port %d: %s\n",
+ port_id, rte_strerror(-ret));
+ return ret;
+ }
+
+ printf("Link status change port %i\n", port_id);
+ link_status[port_id] = link.link_status;
+ return 0;
+}
+
/* Initializes a given port using global settings and with the RX buffers
* coming from the mbuf_pool passed as a parameter.
*/
@@ -99,6 +127,9 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool)
printf("Not enough threads available\n");
return -1;
}
+ /* Register the LinkStatusChange callback */
+ rte_eth_dev_callback_register(port, RTE_ETH_EVENT_INTR_LSC,
+ link_status_change_cb, NULL);
/* Allocate and set up 1 RX queue per Ethernet port. */
for (q = 0; q < rx_rings; q++) {
@@ -138,9 +169,33 @@ port_init(uint16_t port, struct rte_mempool *mbuf_pool)
if (retval != 0)
return retval;
+ struct rte_eth_link link;
+ int ret = rte_eth_link_get_nowait(port, &link);
+ if (ret < 0) {
+ printf("Failed link get on port %d: %s\n", port,
+ rte_strerror(-ret));
+ return ret;
+ }
+
+ link_status[port] = link.link_status;
+
return 0;
}
+static void
+gen_wait_for_links_up(void)
+{
+ /* Ensure all available ports are up before generating packets */
+ uint16_t nb_eth_ports = rte_eth_dev_count_avail();
+ uint16_t nb_links_up = 0;
+ while (!done && nb_links_up < nb_eth_ports) {
+ if (link_status[nb_links_up])
+ nb_links_up++;
+
+ rte_delay_us_block(100);
+ }
+}
+
/* The lcore main. This is the main thread that does the work, reading from
* an input port and writing to an output port.
*/
@@ -164,12 +219,19 @@ lcore_producer(void *arg)
uint64_t tsc_hz = rte_get_tsc_hz();
uint64_t last_tsc_reading = 0;
uint64_t last_tx_total = 0;
+ uint16_t nb_tx = 0;
+
+ /* Wait for links to come up before generating packets */
+ gen_wait_for_links_up();
+ if (!done)
+ printf("Generating packets...\n");
/* Run until the application is quit or killed. */
while (!done) {
+
struct rte_mbuf *bufs[BURST_SIZE];
- uint16_t nb_tx = 0;
/* Receive packets from gen and then tx them over port */
+
RTE_ETH_FOREACH_DEV(port) {
int nb_generated = rte_gen_rx_burst(gen, bufs,
BURST_SIZE);
@@ -217,8 +279,12 @@ lcore_consumer(void *arg)
"polling thread.\n\tPerformance will "
"not be optimal.\n", port);
+ /* Wait for links to come up before generating packets */
+ gen_wait_for_links_up();
+
/* Run until the application is quit or killed. */
while (!done) {
+
struct rte_mbuf *bufs[BURST_SIZE];
/* Receive packets over port and then tx them to gen library