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.rand...@intel.com>
---
 examples/generator/main.c | 68 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 67 insertions(+), 1 deletion(-)

diff --git a/examples/generator/main.c b/examples/generator/main.c
index 1ac3caafcc..0834a094a4 100644
--- a/examples/generator/main.c
+++ b/examples/generator/main.c
@@ -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
-- 
2.25.1

Reply via email to