[dpdk-dev,1/6] bond: link status interrupt support

Message ID 1408456313-28812-2-git-send-email-declan.doherty@intel.com (mailing list archive)
State Superseded, archived
Headers

Commit Message

Doherty, Declan Aug. 19, 2014, 1:51 p.m. UTC
  Adding support for lsc interrupt from bonded device to link
bonding library with supporting unit tests in the test application.

Signed-off-by: Declan Doherty <declan.doherty@intel.com>
---
 app/test/test_link_bonding.c           |  216 +++++++++++++++++++++++++++-----
 lib/librte_pmd_bond/rte_eth_bond_api.c |    4 +
 lib/librte_pmd_bond/rte_eth_bond_pmd.c |    6 +
 3 files changed, 192 insertions(+), 34 deletions(-)
  

Comments

Sanford, Robert Aug. 20, 2014, 8:24 p.m. UTC | #1
Reviewed-by: Robert Sanford <rsanford@akamai.com>


>Adding support for lsc interrupt from bonded device to link
>bonding library with supporting unit tests in the test application.
>
>Signed-off-by: Declan Doherty <declan.doherty@intel.com>
>---
> app/test/test_link_bonding.c           |  216
>+++++++++++++++++++++++++++-----
> lib/librte_pmd_bond/rte_eth_bond_api.c |    4 +
> lib/librte_pmd_bond/rte_eth_bond_pmd.c |    6 +
> 3 files changed, 192 insertions(+), 34 deletions(-)
>
>diff --git a/app/test/test_link_bonding.c b/app/test/test_link_bonding.c
>index 5c1303e..02823b6 100644
>--- a/app/test/test_link_bonding.c
>+++ b/app/test/test_link_bonding.c
>@@ -39,6 +39,7 @@
> #include <inttypes.h>
> #include <errno.h>
> #include <sys/queue.h>
>+#include <sys/time.h>
>
> #include <rte_byteorder.h>
> #include <rte_common.h>
>@@ -224,10 +225,15 @@ static struct rte_eth_txconf tx_conf_default = {
> };
>
> static int
>-configure_ethdev(uint8_t port_id, uint8_t start)
>+configure_ethdev(uint8_t port_id, uint8_t start, uint8_t en_isr)
> {
>       int q_id;
>
>+      if (en_isr)
>+              default_pmd_conf.intr_conf.lsc = 1;
>+      else
>+              default_pmd_conf.intr_conf.lsc = 0;
>+
>       if (rte_eth_dev_configure(port_id, test_params->nb_rx_q,
>                       test_params->nb_tx_q, &default_pmd_conf) != 0) {
>               goto error;
>@@ -312,7 +318,7 @@ test_setup(void)
>
>                       printf("Created virtual ethdev %s\n", pmd_name);
>
>-                      retval = configure_ethdev(test_params->slave_port_ids[i], 1);
>+                      retval = configure_ethdev(test_params->slave_port_ids[i], 1, 0);
>                       if (retval != 0) {
>                               printf("Failed to configure virtual ethdev %s\n", pmd_name);
>                               return -1;
>@@ -341,7 +347,7 @@ test_create_bonded_device(void)
>               TEST_ASSERT(test_params->bonded_port_id >= 0,
>                               "Failed to create bonded ethdev %s", BONDED_DEV_NAME);
>
>-              TEST_ASSERT_SUCCESS(configure_ethdev(test_params->bonded_port_id, 0),
>+              TEST_ASSERT_SUCCESS(configure_ethdev(test_params->bonded_port_id, 0,
>0),
>                               "Failed to configure bonded ethdev %s", BONDED_DEV_NAME);
>       }
>
>@@ -1078,12 +1084,12 @@ test_set_explicit_bonded_mac(void)
>
>
> static int
>-initialize_bonded_device_with_slaves(uint8_t bonding_mode,
>+initialize_bonded_device_with_slaves(uint8_t bonding_mode, uint8_t
>bond_en_isr,
>               uint8_t number_of_slaves, uint8_t enable_slave)
> {
>       /* configure bonded device */
>-      TEST_ASSERT_SUCCESS(configure_ethdev(test_params->bonded_port_id, 0),
>-                      "Failed to configure bonding port (%d) in mode %d "
>+      TEST_ASSERT_SUCCESS(configure_ethdev(test_params->bonded_port_id, 0,
>+                      bond_en_isr), "Failed to configure bonding port (%d) in mode %d "
>                       "with (%d) slaves.", test_params->bonded_port_id, bonding_mode,
>                       number_of_slaves);
>
>@@ -1116,8 +1122,8 @@ test_adding_slave_after_bonded_device_started(void)
> {
>       int i;
>
>-      if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 4,
>0) !=
>-                      0)
>+      if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 0,
>4, 0)
>+                      != 0)
>               return -1;
>
>       /* Enabled slave devices */
>@@ -1141,6 +1147,147 @@
>test_adding_slave_after_bonded_device_started(void)
>       return remove_slaves_and_stop_bonded_device();
> }
>
>+#define TEST_STATUS_INTERRUPT_SLAVE_COUNT     4
>+#define TEST_LSC_WAIT_TIMEOUT_MS      500
>+
>+int test_lsc_interupt_count;
>+
>+static pthread_mutex_t mutex;
>+static pthread_cond_t cvar;
>+
>+static void
>+test_bonding_lsc_event_callback(uint8_t port_id __rte_unused,
>+              enum rte_eth_event_type type  __rte_unused, void *param __rte_unused)
>+{
>+      pthread_mutex_lock(&mutex);
>+      test_lsc_interupt_count++;
>+
>+      pthread_cond_signal(&cvar);
>+      pthread_mutex_unlock(&mutex);
>+}
>+
>+static inline int
>+lsc_timeout(int wait_us)
>+{
>+      int retval = 0;
>+
>+      struct timespec ts;
>+      struct timeval tp;
>+
>+      gettimeofday(&tp, NULL);
>+
>+      /* Convert from timeval to timespec */
>+      ts.tv_sec  = tp.tv_sec;
>+      ts.tv_nsec = tp.tv_usec * 1000;
>+      ts.tv_nsec += wait_us * 1000;
>+
>+      pthread_mutex_lock(&mutex);
>+      if (test_lsc_interupt_count < 1)
>+              retval = pthread_cond_timedwait(&cvar, &mutex, &ts);
>+
>+      pthread_mutex_unlock(&mutex);
>+
>+      if (test_lsc_interupt_count  < 1)
>+               return retval;
>+
>+      return 0;
>+}
>+
>+static int
>+test_status_interrupt(void)
>+{
>+      int slave_count;
>+      uint8_t slaves[RTE_MAX_ETHPORTS];
>+
>+      pthread_mutex_init(&mutex, NULL);
>+      pthread_cond_init(&cvar, NULL);
>+
>+      /* initialized bonding device with T slaves */
>+      if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 1,
>+                      TEST_STATUS_INTERRUPT_SLAVE_COUNT, 1) != 0)
>+              return -1;
>+
>+      test_lsc_interupt_count = 0;
>+
>+      /* register link status change interrupt callback */
>+      rte_eth_dev_callback_register(test_params->bonded_port_id,
>+                      RTE_ETH_EVENT_INTR_LSC, test_bonding_lsc_event_callback,
>+                      &test_params->bonded_port_id);
>+
>+      slave_count =
>rte_eth_bond_active_slaves_get(test_params->bonded_port_id,
>+                      slaves, RTE_MAX_ETHPORTS);
>+
>+      TEST_ASSERT_EQUAL(slave_count, TEST_STATUS_INTERRUPT_SLAVE_COUNT,
>+                      "Number of active slaves (%d) is not as expected (%d)",
>+                      slave_count, TEST_STATUS_INTERRUPT_SLAVE_COUNT);
>+
>+      /* Bring all 4 slaves link status to down and test that we have
>received a
>+       * lsc interrupts */
>+      virtual_ethdev_simulate_link_status_interrupt(
>+                      test_params->slave_port_ids[0], 0);
>+      virtual_ethdev_simulate_link_status_interrupt(
>+                      test_params->slave_port_ids[1], 0);
>+      virtual_ethdev_simulate_link_status_interrupt(
>+                      test_params->slave_port_ids[2], 0);
>+
>+      TEST_ASSERT_EQUAL(test_lsc_interupt_count, 0,
>+                      "Received a link status change interrupt unexpectedly");
>+
>+      virtual_ethdev_simulate_link_status_interrupt(
>+                      test_params->slave_port_ids[3], 0);
>+
>+      TEST_ASSERT(lsc_timeout(TEST_LSC_WAIT_TIMEOUT_MS) == 0,
>+                      "timed out waiting for interrupt");
>+
>+      TEST_ASSERT(test_lsc_interupt_count > 0,
>+                      "Did not receive link status change interrupt");
>+
>+      slave_count =
>rte_eth_bond_active_slaves_get(test_params->bonded_port_id,
>+                      slaves, RTE_MAX_ETHPORTS);
>+
>+      TEST_ASSERT_EQUAL(slave_count, 0,
>+                      "Number of active slaves (%d) is not as expected (%d)",
>+                      slave_count, 0);
>+
>+      /* bring one slave port up so link status will change */
>+      test_lsc_interupt_count = 0;
>+
>+      virtual_ethdev_simulate_link_status_interrupt(
>+                      test_params->slave_port_ids[0], 1);
>+
>+      TEST_ASSERT(lsc_timeout(TEST_LSC_WAIT_TIMEOUT_MS) == 0,
>+                      "timed out waiting for interrupt");
>+
>+      /* test that we have received another lsc interrupt */
>+      TEST_ASSERT(test_lsc_interupt_count > 0,
>+                      "Did not receive link status change interrupt");
>+
>+      /* Verify that calling the same slave lsc interrupt doesn't cause
>another
>+       * lsc interrupt from bonded device */
>+      test_lsc_interupt_count = 0;
>+
>+      virtual_ethdev_simulate_link_status_interrupt(
>+                      test_params->slave_port_ids[0], 1);
>+
>+      TEST_ASSERT(lsc_timeout(TEST_LSC_WAIT_TIMEOUT_MS) != 0,
>+                      "received unexpected interrupt");
>+
>+      TEST_ASSERT_EQUAL(test_lsc_interupt_count, 0,
>+                      "Did not receive link status change interrupt");
>+
>+
>+      /* unregister lsc callback before exiting */
>+      rte_eth_dev_callback_unregister(test_params->bonded_port_id,
>+                              RTE_ETH_EVENT_INTR_LSC, test_bonding_lsc_event_callback,
>+                              &test_params->bonded_port_id);
>+
>+      pthread_mutex_destroy(&mutex);
>+      pthread_cond_destroy(&cvar);
>+
>+      /* Clean up and remove slaves from bonded device */
>+      return remove_slaves_and_stop_bonded_device();
>+}
>+
> static int
> generate_test_burst(struct rte_mbuf **pkts_burst, uint16_t burst_size,
>               uint8_t vlan, uint8_t ipv4, uint8_t toggle_dst_mac,
>@@ -1209,7 +1356,7 @@ test_roundrobin_tx_burst(void)
>       struct rte_mbuf *pkt_burst[MAX_PKT_BURST];
>       struct rte_eth_stats port_stats;
>
>-      if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 2, 1)
>+      if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 0,
>2, 1)
>                       != 0)
>               return -1;
>
>@@ -1279,7 +1426,7 @@ test_roundrobin_rx_burst_on_single_slave(void)
>       int i, j, nb_rx, burst_size = 25;
>
>       /* Initialize bonded device with 4 slaves in round robin mode */
>-      if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 4,
>1) !=
>+      if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 0,
>4, 1) !=
>                       0)
>               return -1;
>
>@@ -1369,7 +1516,7 @@ test_roundrobin_rx_burst_on_multiple_slaves(void)
>
>
>       /* Initialize bonded device with 4 slaves in round robin mode */
>-      if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 4,
>1) !=
>+      if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 0,
>4, 1) !=
>                       0)
>               return -1;
>
>@@ -1461,7 +1608,7 @@ test_roundrobin_verify_mac_assignment(void)
>       rte_eth_macaddr_get(test_params->slave_port_ids[2],
>&expected_mac_addr_2);
>
>       /* Initialize bonded device with 4 slaves in round robin mode */
>-      if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 4, 1)
>+      if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 0,
>4, 1)
>                       != 0)
>               return -1;
>
>@@ -1552,7 +1699,7 @@
>test_roundrobin_verify_promiscuous_enable_disable(void)
>       int i, promiscuous_en;
>
>       /* Initialize bonded device with 4 slaves in round robin mode */
>-      if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 4,
>1) !=
>+      if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 0,
>4, 1) !=
>                       0)
>               return -1;
>
>@@ -1616,7 +1763,7 @@
>test_roundrobin_verify_slave_link_status_change_behaviour(void)
>
>       /* Initialize bonded device with TEST_RR_LINK_STATUS_SLAVE_COUNT slaves
>        * in round robin mode */
>-      if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN,
>+      if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 0,
>                       TEST_RR_LINK_STATUS_SLAVE_COUNT, 1) != 0)
>               return -1;
>
>@@ -1757,7 +1904,7 @@ test_activebackup_tx_burst(void)
>       struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
>       struct rte_eth_stats port_stats;
>
>-      retval =
>initialize_bonded_device_with_slaves(BONDING_MODE_ACTIVE_BACKUP, 2, 1);
>+      retval =
>initialize_bonded_device_with_slaves(BONDING_MODE_ACTIVE_BACKUP, 0, 2, 1);
>       if (retval != 0) {
>               printf("Failed to initialize_bonded_device_with_slaves.\n");
>               return -1;
>@@ -1854,7 +2001,7 @@ test_activebackup_rx_burst(void)
>       int i, j, nb_rx, burst_size = 17;
>
>       /* Initialize bonded device with 4 slaves in round robin mode */
>-      if (initialize_bonded_device_with_slaves(BONDING_MODE_ACTIVE_BACKUP,
>+      if (initialize_bonded_device_with_slaves(BONDING_MODE_ACTIVE_BACKUP, 0,
>                       TEST_ACTIVE_BACKUP_RX_BURST_SLAVE_COUNT, 1)
>                       != 0)
>               return -1;
>@@ -1948,7 +2095,7 @@
>test_activebackup_verify_promiscuous_enable_disable(void)
>       int i, primary_port, promiscuous_en;
>
>       /* Initialize bonded device with 4 slaves in round robin mode */
>-      if (initialize_bonded_device_with_slaves(BONDING_MODE_ACTIVE_BACKUP, 4,
>1)
>+      if (initialize_bonded_device_with_slaves(BONDING_MODE_ACTIVE_BACKUP, 0,
>4, 1)
>                       != 0)
>               return -1;
>
>@@ -2018,7 +2165,7 @@ test_activebackup_verify_mac_assignment(void)
>       rte_eth_macaddr_get(test_params->slave_port_ids[1],
>&expected_mac_addr_1);
>
>       /* Initialize bonded device with 2 slaves in active backup mode */
>-      if (initialize_bonded_device_with_slaves(BONDING_MODE_ACTIVE_BACKUP, 2,
>1)
>+      if (initialize_bonded_device_with_slaves(BONDING_MODE_ACTIVE_BACKUP, 0,
>2, 1)
>                       != 0)
>               return -1;
>
>@@ -2157,7 +2304,7 @@
>test_activebackup_verify_slave_link_status_change_failover(void)
>       }
>
>       /* Initialize bonded device with 4 slaves in round robin mode */
>-      if (initialize_bonded_device_with_slaves(BONDING_MODE_ACTIVE_BACKUP,
>+      if (initialize_bonded_device_with_slaves(BONDING_MODE_ACTIVE_BACKUP, 0,
>                       TEST_ACTIVE_BACKUP_RX_BURST_SLAVE_COUNT, 1)
>                       != 0)
>               return -1;
>@@ -2328,7 +2475,7 @@ test_balance_xmit_policy_configuration(void)
> {
>       int retval;
>
>-      retval =
>initialize_bonded_device_with_slaves(BONDING_MODE_ACTIVE_BACKUP,
>+      retval =
>initialize_bonded_device_with_slaves(BONDING_MODE_ACTIVE_BACKUP, 0,
>                       2, 1);
>       if (retval != 0) {
>               printf("Failed to initialize_bonded_device_with_slaves.\n");
>@@ -2408,7 +2555,7 @@ test_balance_l2_tx_burst(void)
>       int retval, i;
>       struct rte_eth_stats port_stats;
>
>-      retval = initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE,
>+      retval = initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 0,
>                       TEST_BALANCE_L2_TX_BURST_SLAVE_COUNT, 1);
>       if (retval != 0) {
>               printf("Failed to initialize_bonded_device_with_slaves.\n");
>@@ -2506,7 +2653,7 @@ balance_l23_tx_burst(uint8_t vlan_enabled, uint8_t
>ipv4,
>
>       struct rte_eth_stats port_stats;
>
>-      retval = initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 2,
>1);
>+      retval = initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 0,
>2, 1);
>       if (retval != 0) {
>               printf("Failed to initialize_bonded_device_with_slaves.\n");
>               return -1;
>@@ -2634,7 +2781,7 @@ balance_l34_tx_burst(uint8_t vlan_enabled, uint8_t
>ipv4,
>
>       struct rte_eth_stats port_stats;
>
>-      retval = initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 2,
>1);
>+      retval = initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 0,
>2, 1);
>       if (retval != 0) {
>               printf("Failed to initialize_bonded_device_with_slaves.\n");
>               return -1;
>@@ -2772,7 +2919,7 @@ test_balance_rx_burst(void)
>       memset(gen_pkt_burst, 0, sizeof(gen_pkt_burst));
>
>       /* Initialize bonded device with 4 slaves in round robin mode */
>-      if (initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 3, 1)
>+      if (initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 0, 3, 1)
>                       != 0)
>               return -1;
>
>@@ -2861,7 +3008,7 @@ test_balance_verify_promiscuous_enable_disable(void)
>       int i, promiscuous_en;
>
>       /* Initialize bonded device with 4 slaves in round robin mode */
>-      if (initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 4, 1) !=
>0)
>+      if (initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 0, 4, 1)
>!= 0)
>               return -1;
>
>       rte_eth_promiscuous_enable(test_params->bonded_port_id);
>@@ -2915,7 +3062,7 @@ test_balance_verify_mac_assignment(void)
>       rte_eth_macaddr_get(test_params->slave_port_ids[1],
>&expected_mac_addr_1);
>
>       /* Initialize bonded device with 2 slaves in active backup mode */
>-      if (initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 2, 1) !=
>0)
>+      if (initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 0, 2, 1)
>!= 0)
>               return -1;
>
>       /* Verify that bonded MACs is that of first slave and that the other
>slave
>@@ -3045,7 +3192,7 @@
>test_balance_verify_slave_link_status_change_behaviour(void)
>       memset(pkt_burst, 0, sizeof(pkt_burst));
>
>       /* Initialize bonded device with 4 slaves in round robin mode */
>-      if (initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE,
>+      if (initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 0,
>                       TEST_BALANCE_LINK_STATUS_SLAVE_COUNT, 1) != 0)
>               return -1;
>
>@@ -3237,7 +3384,7 @@ test_broadcast_tx_burst(void)
>
>       struct rte_eth_stats port_stats;
>
>-      retval = initialize_bonded_device_with_slaves(BONDING_MODE_BROADCAST,
>2, 1);
>+      retval = initialize_bonded_device_with_slaves(BONDING_MODE_BROADCAST,
>0, 2, 1);
>       if (retval != 0) {
>               printf("Failed to initialize_bonded_device_with_slaves.\n");
>               return -1;
>@@ -3327,7 +3474,7 @@ test_broadcast_rx_burst(void)
>       memset(gen_pkt_burst, 0, sizeof(gen_pkt_burst));
>
>       /* Initialize bonded device with 4 slaves in round robin mode */
>-      if (initialize_bonded_device_with_slaves(BONDING_MODE_BROADCAST, 3, 1)
>!= 0)
>+      if (initialize_bonded_device_with_slaves(BONDING_MODE_BROADCAST, 0, 3,
>1) != 0)
>               return -1;
>
>
>@@ -3419,7 +3566,7 @@
>test_broadcast_verify_promiscuous_enable_disable(void)
>       int i, promiscuous_en;
>
>       /* Initialize bonded device with 4 slaves in round robin mode */
>-      if (initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 4, 1) !=
>0)
>+      if (initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 0, 4, 1)
>!= 0)
>               return -1;
>
>       rte_eth_promiscuous_enable(test_params->bonded_port_id);
>@@ -3475,7 +3622,7 @@ test_broadcast_verify_mac_assignment(void)
>       rte_eth_macaddr_get(test_params->slave_port_ids[2],
>&expected_mac_addr_1);
>
>       /* Initialize bonded device with 4 slaves in round robin mode */
>-      if (initialize_bonded_device_with_slaves(BONDING_MODE_BROADCAST, 4, 1)
>!= 0)
>+      if (initialize_bonded_device_with_slaves(BONDING_MODE_BROADCAST, 0, 4,
>1) != 0)
>               return -1;
>
>       /* Verify that all MACs are the same as first slave added to bonded
>@@ -3575,7 +3722,7 @@
>test_broadcast_verify_slave_link_status_change_behaviour(void)
>       memset(pkt_burst, 0, sizeof(pkt_burst));
>
>       /* Initialize bonded device with 4 slaves in round robin mode */
>-      if (initialize_bonded_device_with_slaves(BONDING_MODE_BROADCAST,
>+      if (initialize_bonded_device_with_slaves(BONDING_MODE_BROADCAST, 0,
>                       BROADCAST_LINK_STATUS_NUM_OF_SLAVES, 1) != 0)
>               return -1;
>
>@@ -3711,7 +3858,7 @@ test_reconfigure_bonded_device(void)
>       test_params->nb_rx_q = 4;
>       test_params->nb_tx_q = 4;
>
>-      if (configure_ethdev(test_params->bonded_port_id, 0)  != 0) {
>+      if (configure_ethdev(test_params->bonded_port_id, 0, 0)  != 0) {
>               printf("failed to reconfigure bonded device");
>               return -1;
>       }
>@@ -3720,7 +3867,7 @@ test_reconfigure_bonded_device(void)
>       test_params->nb_rx_q = 2;
>       test_params->nb_tx_q = 2;
>
>-      if (configure_ethdev(test_params->bonded_port_id, 0)  != 0) {
>+      if (configure_ethdev(test_params->bonded_port_id, 0, 0)  != 0) {
>               printf("failed to reconfigure bonded device with less rx/tx queues");
>               return -1;
>       }
>@@ -3768,6 +3915,7 @@ static struct unit_test_suite
>link_bonding_test_suite  = {
>               TEST_CASE(test_set_bonding_mode),
>               TEST_CASE(test_set_primary_slave),
>               TEST_CASE(test_set_explicit_bonded_mac),
>+              TEST_CASE(test_status_interrupt),
>               TEST_CASE(test_adding_slave_after_bonded_device_started),
>               TEST_CASE(test_roundrobin_tx_burst),
>               TEST_CASE(test_roundrobin_rx_burst_on_single_slave),
>diff --git a/lib/librte_pmd_bond/rte_eth_bond_api.c
>b/lib/librte_pmd_bond/rte_eth_bond_api.c
>index 75f5694..dd33119 100644
>--- a/lib/librte_pmd_bond/rte_eth_bond_api.c
>+++ b/lib/librte_pmd_bond/rte_eth_bond_api.c
>@@ -177,6 +177,8 @@ rte_eth_bond_create(const char *name, uint8_t mode,
>uint8_t socket_id)
>       pci_drv->id_table->vendor_id = PCI_ANY_ID;
>       pci_drv->id_table->subsystem_vendor_id = PCI_ANY_ID;
>
>+      pci_drv->drv_flags = RTE_PCI_DRV_INTR_LSC;
>+
>       internals = rte_zmalloc_socket(name, sizeof(*internals), 0, socket_id);
>       if (internals == NULL) {
>               RTE_LOG(ERR, PMD, "Unable to malloc internals on socket\n");
>@@ -200,6 +202,8 @@ rte_eth_bond_create(const char *name, uint8_t mode,
>uint8_t socket_id)
>       eth_dev->data->nb_rx_queues = (uint16_t)1;
>       eth_dev->data->nb_tx_queues = (uint16_t)1;
>
>+      TAILQ_INIT(&(eth_dev->callbacks));
>+
>       eth_dev->data->dev_link.link_status = 0;
>
>       eth_dev->data->mac_addrs = rte_zmalloc_socket(name, ETHER_ADDR_LEN, 0,
>diff --git a/lib/librte_pmd_bond/rte_eth_bond_pmd.c
>b/lib/librte_pmd_bond/rte_eth_bond_pmd.c
>index d72d6ed..cd3eecf 100644
>--- a/lib/librte_pmd_bond/rte_eth_bond_pmd.c
>+++ b/lib/librte_pmd_bond/rte_eth_bond_pmd.c
>@@ -921,6 +921,7 @@ bond_ethdev_lsc_event_callback(uint8_t port_id, enum
>rte_eth_event_type type,
>       struct rte_eth_link link;
>
>       int i, valid_slave = 0, active_pos = -1;
>+      uint8_t lsc_flag = 0;
>
>       if (type != RTE_ETH_EVENT_INTR_LSC || param == NULL)
>               return;
>@@ -966,6 +967,7 @@ bond_ethdev_lsc_event_callback(uint8_t port_id, enum
>rte_eth_event_type type,
>                       /* If first active slave, then change link status */
>                       bonded_eth_dev->data->dev_link.link_status = 1;
>                       internals->current_primary_port = port_id;
>+                      lsc_flag = 1;
>
>                       /* Inherit eth dev link properties from first active slave */
>                       link_properties_set(bonded_eth_dev,
>@@ -990,6 +992,7 @@ bond_ethdev_lsc_event_callback(uint8_t port_id, enum
>rte_eth_event_type type,
>               /* No active slaves, change link status to down and reset other
>                * link properties */
>               if (internals->active_slave_count < 1) {
>+                      lsc_flag = 1;
>                       bonded_eth_dev->data->dev_link.link_status = 0;
>
>                       link_properties_reset(bonded_eth_dev);
>@@ -1005,6 +1008,9 @@ bond_ethdev_lsc_event_callback(uint8_t port_id,
>enum rte_eth_event_type type,
>                               internals->current_primary_port = internals->primary_port;
>               }
>       }
>+
>+      if (lsc_flag)
>+              _rte_eth_dev_callback_process(bonded_eth_dev, RTE_ETH_EVENT_INTR_LSC);
> }
>
> struct eth_dev_ops default_dev_ops = {
>--
>1.7.0.7
>
  

Patch

diff --git a/app/test/test_link_bonding.c b/app/test/test_link_bonding.c
index 5c1303e..02823b6 100644
--- a/app/test/test_link_bonding.c
+++ b/app/test/test_link_bonding.c
@@ -39,6 +39,7 @@ 
 #include <inttypes.h>
 #include <errno.h>
 #include <sys/queue.h>
+#include <sys/time.h>
 
 #include <rte_byteorder.h>
 #include <rte_common.h>
@@ -224,10 +225,15 @@  static struct rte_eth_txconf tx_conf_default = {
 };
 
 static int
-configure_ethdev(uint8_t port_id, uint8_t start)
+configure_ethdev(uint8_t port_id, uint8_t start, uint8_t en_isr)
 {
 	int q_id;
 
+	if (en_isr)
+		default_pmd_conf.intr_conf.lsc = 1;
+	else
+		default_pmd_conf.intr_conf.lsc = 0;
+
 	if (rte_eth_dev_configure(port_id, test_params->nb_rx_q,
 			test_params->nb_tx_q, &default_pmd_conf) != 0) {
 		goto error;
@@ -312,7 +318,7 @@  test_setup(void)
 
 			printf("Created virtual ethdev %s\n", pmd_name);
 
-			retval = configure_ethdev(test_params->slave_port_ids[i], 1);
+			retval = configure_ethdev(test_params->slave_port_ids[i], 1, 0);
 			if (retval != 0) {
 				printf("Failed to configure virtual ethdev %s\n", pmd_name);
 				return -1;
@@ -341,7 +347,7 @@  test_create_bonded_device(void)
 		TEST_ASSERT(test_params->bonded_port_id >= 0,
 				"Failed to create bonded ethdev %s", BONDED_DEV_NAME);
 
-		TEST_ASSERT_SUCCESS(configure_ethdev(test_params->bonded_port_id, 0),
+		TEST_ASSERT_SUCCESS(configure_ethdev(test_params->bonded_port_id, 0, 0),
 				"Failed to configure bonded ethdev %s", BONDED_DEV_NAME);
 	}
 
@@ -1078,12 +1084,12 @@  test_set_explicit_bonded_mac(void)
 
 
 static int
-initialize_bonded_device_with_slaves(uint8_t bonding_mode,
+initialize_bonded_device_with_slaves(uint8_t bonding_mode, uint8_t bond_en_isr,
 		uint8_t number_of_slaves, uint8_t enable_slave)
 {
 	/* configure bonded device */
-	TEST_ASSERT_SUCCESS(configure_ethdev(test_params->bonded_port_id, 0),
-			"Failed to configure bonding port (%d) in mode %d "
+	TEST_ASSERT_SUCCESS(configure_ethdev(test_params->bonded_port_id, 0,
+			bond_en_isr), "Failed to configure bonding port (%d) in mode %d "
 			"with (%d) slaves.", test_params->bonded_port_id, bonding_mode,
 			number_of_slaves);
 
@@ -1116,8 +1122,8 @@  test_adding_slave_after_bonded_device_started(void)
 {
 	int i;
 
-	if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 4, 0) !=
-			0)
+	if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 0, 4, 0)
+			!= 0)
 		return -1;
 
 	/* Enabled slave devices */
@@ -1141,6 +1147,147 @@  test_adding_slave_after_bonded_device_started(void)
 	return remove_slaves_and_stop_bonded_device();
 }
 
+#define TEST_STATUS_INTERRUPT_SLAVE_COUNT	4
+#define TEST_LSC_WAIT_TIMEOUT_MS	500
+
+int test_lsc_interupt_count;
+
+static pthread_mutex_t mutex;
+static pthread_cond_t cvar;
+
+static void
+test_bonding_lsc_event_callback(uint8_t port_id __rte_unused,
+		enum rte_eth_event_type type  __rte_unused, void *param __rte_unused)
+{
+	pthread_mutex_lock(&mutex);
+	test_lsc_interupt_count++;
+
+	pthread_cond_signal(&cvar);
+	pthread_mutex_unlock(&mutex);
+}
+
+static inline int
+lsc_timeout(int wait_us)
+{
+	int retval = 0;
+
+	struct timespec ts;
+	struct timeval tp;
+
+	gettimeofday(&tp, NULL);
+
+	/* Convert from timeval to timespec */
+	ts.tv_sec  = tp.tv_sec;
+	ts.tv_nsec = tp.tv_usec * 1000;
+	ts.tv_nsec += wait_us * 1000;
+
+	pthread_mutex_lock(&mutex);
+	if (test_lsc_interupt_count < 1)
+		retval = pthread_cond_timedwait(&cvar, &mutex, &ts);
+
+	pthread_mutex_unlock(&mutex);
+
+	if (test_lsc_interupt_count  < 1)
+               return retval;
+
+	return 0;
+}
+
+static int
+test_status_interrupt(void)
+{
+	int slave_count;
+	uint8_t slaves[RTE_MAX_ETHPORTS];
+
+	pthread_mutex_init(&mutex, NULL);
+	pthread_cond_init(&cvar, NULL);
+
+	/* initialized bonding device with T slaves */
+	if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 1,
+			TEST_STATUS_INTERRUPT_SLAVE_COUNT, 1) != 0)
+		return -1;
+
+	test_lsc_interupt_count = 0;
+
+	/* register link status change interrupt callback */
+	rte_eth_dev_callback_register(test_params->bonded_port_id,
+			RTE_ETH_EVENT_INTR_LSC, test_bonding_lsc_event_callback,
+			&test_params->bonded_port_id);
+
+	slave_count = rte_eth_bond_active_slaves_get(test_params->bonded_port_id,
+			slaves, RTE_MAX_ETHPORTS);
+
+	TEST_ASSERT_EQUAL(slave_count, TEST_STATUS_INTERRUPT_SLAVE_COUNT,
+			"Number of active slaves (%d) is not as expected (%d)",
+			slave_count, TEST_STATUS_INTERRUPT_SLAVE_COUNT);
+
+	/* Bring all 4 slaves link status to down and test that we have received a
+	 * lsc interrupts */
+	virtual_ethdev_simulate_link_status_interrupt(
+			test_params->slave_port_ids[0], 0);
+	virtual_ethdev_simulate_link_status_interrupt(
+			test_params->slave_port_ids[1], 0);
+	virtual_ethdev_simulate_link_status_interrupt(
+			test_params->slave_port_ids[2], 0);
+
+	TEST_ASSERT_EQUAL(test_lsc_interupt_count, 0,
+			"Received a link status change interrupt unexpectedly");
+
+	virtual_ethdev_simulate_link_status_interrupt(
+			test_params->slave_port_ids[3], 0);
+
+	TEST_ASSERT(lsc_timeout(TEST_LSC_WAIT_TIMEOUT_MS) == 0,
+			"timed out waiting for interrupt");
+
+	TEST_ASSERT(test_lsc_interupt_count > 0,
+			"Did not receive link status change interrupt");
+
+	slave_count = rte_eth_bond_active_slaves_get(test_params->bonded_port_id,
+			slaves, RTE_MAX_ETHPORTS);
+
+	TEST_ASSERT_EQUAL(slave_count, 0,
+			"Number of active slaves (%d) is not as expected (%d)",
+			slave_count, 0);
+
+	/* bring one slave port up so link status will change */
+	test_lsc_interupt_count = 0;
+
+	virtual_ethdev_simulate_link_status_interrupt(
+			test_params->slave_port_ids[0], 1);
+
+	TEST_ASSERT(lsc_timeout(TEST_LSC_WAIT_TIMEOUT_MS) == 0,
+			"timed out waiting for interrupt");
+
+	/* test that we have received another lsc interrupt */
+	TEST_ASSERT(test_lsc_interupt_count > 0,
+			"Did not receive link status change interrupt");
+
+	/* Verify that calling the same slave lsc interrupt doesn't cause another
+	 * lsc interrupt from bonded device */
+	test_lsc_interupt_count = 0;
+
+	virtual_ethdev_simulate_link_status_interrupt(
+			test_params->slave_port_ids[0], 1);
+
+	TEST_ASSERT(lsc_timeout(TEST_LSC_WAIT_TIMEOUT_MS) != 0,
+			"received unexpected interrupt");
+
+	TEST_ASSERT_EQUAL(test_lsc_interupt_count, 0,
+			"Did not receive link status change interrupt");
+
+
+	/* unregister lsc callback before exiting */
+	rte_eth_dev_callback_unregister(test_params->bonded_port_id,
+				RTE_ETH_EVENT_INTR_LSC, test_bonding_lsc_event_callback,
+				&test_params->bonded_port_id);
+
+	pthread_mutex_destroy(&mutex);
+	pthread_cond_destroy(&cvar);
+
+	/* Clean up and remove slaves from bonded device */
+	return remove_slaves_and_stop_bonded_device();
+}
+
 static int
 generate_test_burst(struct rte_mbuf **pkts_burst, uint16_t burst_size,
 		uint8_t vlan, uint8_t ipv4, uint8_t toggle_dst_mac,
@@ -1209,7 +1356,7 @@  test_roundrobin_tx_burst(void)
 	struct rte_mbuf *pkt_burst[MAX_PKT_BURST];
 	struct rte_eth_stats port_stats;
 
-	if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 2, 1)
+	if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 0, 2, 1)
 			!= 0)
 		return -1;
 
@@ -1279,7 +1426,7 @@  test_roundrobin_rx_burst_on_single_slave(void)
 	int i, j, nb_rx, burst_size = 25;
 
 	/* Initialize bonded device with 4 slaves in round robin mode */
-	if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 4, 1) !=
+	if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 0, 4, 1) !=
 			0)
 		return -1;
 
@@ -1369,7 +1516,7 @@  test_roundrobin_rx_burst_on_multiple_slaves(void)
 
 
 	/* Initialize bonded device with 4 slaves in round robin mode */
-	if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 4, 1) !=
+	if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 0, 4, 1) !=
 			0)
 		return -1;
 
@@ -1461,7 +1608,7 @@  test_roundrobin_verify_mac_assignment(void)
 	rte_eth_macaddr_get(test_params->slave_port_ids[2], &expected_mac_addr_2);
 
 	/* Initialize bonded device with 4 slaves in round robin mode */
-	if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 4, 1)
+	if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 0, 4, 1)
 			!= 0)
 		return -1;
 
@@ -1552,7 +1699,7 @@  test_roundrobin_verify_promiscuous_enable_disable(void)
 	int i, promiscuous_en;
 
 	/* Initialize bonded device with 4 slaves in round robin mode */
-	if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 4, 1) !=
+	if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 0, 4, 1) !=
 			0)
 		return -1;
 
@@ -1616,7 +1763,7 @@  test_roundrobin_verify_slave_link_status_change_behaviour(void)
 
 	/* Initialize bonded device with TEST_RR_LINK_STATUS_SLAVE_COUNT slaves
 	 * in round robin mode */
-	if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN,
+	if (initialize_bonded_device_with_slaves(BONDING_MODE_ROUND_ROBIN, 0,
 			TEST_RR_LINK_STATUS_SLAVE_COUNT, 1) != 0)
 		return -1;
 
@@ -1757,7 +1904,7 @@  test_activebackup_tx_burst(void)
 	struct rte_mbuf *pkts_burst[MAX_PKT_BURST];
 	struct rte_eth_stats port_stats;
 
-	retval = initialize_bonded_device_with_slaves(BONDING_MODE_ACTIVE_BACKUP, 2, 1);
+	retval = initialize_bonded_device_with_slaves(BONDING_MODE_ACTIVE_BACKUP, 0, 2, 1);
 	if (retval != 0) {
 		printf("Failed to initialize_bonded_device_with_slaves.\n");
 		return -1;
@@ -1854,7 +2001,7 @@  test_activebackup_rx_burst(void)
 	int i, j, nb_rx, burst_size = 17;
 
 	/* Initialize bonded device with 4 slaves in round robin mode */
-	if (initialize_bonded_device_with_slaves(BONDING_MODE_ACTIVE_BACKUP,
+	if (initialize_bonded_device_with_slaves(BONDING_MODE_ACTIVE_BACKUP, 0,
 			TEST_ACTIVE_BACKUP_RX_BURST_SLAVE_COUNT, 1)
 			!= 0)
 		return -1;
@@ -1948,7 +2095,7 @@  test_activebackup_verify_promiscuous_enable_disable(void)
 	int i, primary_port, promiscuous_en;
 
 	/* Initialize bonded device with 4 slaves in round robin mode */
-	if (initialize_bonded_device_with_slaves(BONDING_MODE_ACTIVE_BACKUP, 4, 1)
+	if (initialize_bonded_device_with_slaves(BONDING_MODE_ACTIVE_BACKUP, 0, 4, 1)
 			!= 0)
 		return -1;
 
@@ -2018,7 +2165,7 @@  test_activebackup_verify_mac_assignment(void)
 	rte_eth_macaddr_get(test_params->slave_port_ids[1], &expected_mac_addr_1);
 
 	/* Initialize bonded device with 2 slaves in active backup mode */
-	if (initialize_bonded_device_with_slaves(BONDING_MODE_ACTIVE_BACKUP, 2, 1)
+	if (initialize_bonded_device_with_slaves(BONDING_MODE_ACTIVE_BACKUP, 0, 2, 1)
 			!= 0)
 		return -1;
 
@@ -2157,7 +2304,7 @@  test_activebackup_verify_slave_link_status_change_failover(void)
 	}
 
 	/* Initialize bonded device with 4 slaves in round robin mode */
-	if (initialize_bonded_device_with_slaves(BONDING_MODE_ACTIVE_BACKUP,
+	if (initialize_bonded_device_with_slaves(BONDING_MODE_ACTIVE_BACKUP, 0,
 			TEST_ACTIVE_BACKUP_RX_BURST_SLAVE_COUNT, 1)
 			!= 0)
 		return -1;
@@ -2328,7 +2475,7 @@  test_balance_xmit_policy_configuration(void)
 {
 	int retval;
 
-	retval = initialize_bonded_device_with_slaves(BONDING_MODE_ACTIVE_BACKUP,
+	retval = initialize_bonded_device_with_slaves(BONDING_MODE_ACTIVE_BACKUP, 0,
 			2, 1);
 	if (retval != 0) {
 		printf("Failed to initialize_bonded_device_with_slaves.\n");
@@ -2408,7 +2555,7 @@  test_balance_l2_tx_burst(void)
 	int retval, i;
 	struct rte_eth_stats port_stats;
 
-	retval = initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE,
+	retval = initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 0,
 			TEST_BALANCE_L2_TX_BURST_SLAVE_COUNT, 1);
 	if (retval != 0) {
 		printf("Failed to initialize_bonded_device_with_slaves.\n");
@@ -2506,7 +2653,7 @@  balance_l23_tx_burst(uint8_t vlan_enabled, uint8_t ipv4,
 
 	struct rte_eth_stats port_stats;
 
-	retval = initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 2, 1);
+	retval = initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 0, 2, 1);
 	if (retval != 0) {
 		printf("Failed to initialize_bonded_device_with_slaves.\n");
 		return -1;
@@ -2634,7 +2781,7 @@  balance_l34_tx_burst(uint8_t vlan_enabled, uint8_t ipv4,
 
 	struct rte_eth_stats port_stats;
 
-	retval = initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 2, 1);
+	retval = initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 0, 2, 1);
 	if (retval != 0) {
 		printf("Failed to initialize_bonded_device_with_slaves.\n");
 		return -1;
@@ -2772,7 +2919,7 @@  test_balance_rx_burst(void)
 	memset(gen_pkt_burst, 0, sizeof(gen_pkt_burst));
 
 	/* Initialize bonded device with 4 slaves in round robin mode */
-	if (initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 3, 1)
+	if (initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 0, 3, 1)
 			!= 0)
 		return -1;
 
@@ -2861,7 +3008,7 @@  test_balance_verify_promiscuous_enable_disable(void)
 	int i, promiscuous_en;
 
 	/* Initialize bonded device with 4 slaves in round robin mode */
-	if (initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 4, 1) != 0)
+	if (initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 0, 4, 1) != 0)
 		return -1;
 
 	rte_eth_promiscuous_enable(test_params->bonded_port_id);
@@ -2915,7 +3062,7 @@  test_balance_verify_mac_assignment(void)
 	rte_eth_macaddr_get(test_params->slave_port_ids[1], &expected_mac_addr_1);
 
 	/* Initialize bonded device with 2 slaves in active backup mode */
-	if (initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 2, 1) != 0)
+	if (initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 0, 2, 1) != 0)
 		return -1;
 
 	/* Verify that bonded MACs is that of first slave and that the other slave
@@ -3045,7 +3192,7 @@  test_balance_verify_slave_link_status_change_behaviour(void)
 	memset(pkt_burst, 0, sizeof(pkt_burst));
 
 	/* Initialize bonded device with 4 slaves in round robin mode */
-	if (initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE,
+	if (initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 0,
 			TEST_BALANCE_LINK_STATUS_SLAVE_COUNT, 1) != 0)
 		return -1;
 
@@ -3237,7 +3384,7 @@  test_broadcast_tx_burst(void)
 
 	struct rte_eth_stats port_stats;
 
-	retval = initialize_bonded_device_with_slaves(BONDING_MODE_BROADCAST, 2, 1);
+	retval = initialize_bonded_device_with_slaves(BONDING_MODE_BROADCAST, 0, 2, 1);
 	if (retval != 0) {
 		printf("Failed to initialize_bonded_device_with_slaves.\n");
 		return -1;
@@ -3327,7 +3474,7 @@  test_broadcast_rx_burst(void)
 	memset(gen_pkt_burst, 0, sizeof(gen_pkt_burst));
 
 	/* Initialize bonded device with 4 slaves in round robin mode */
-	if (initialize_bonded_device_with_slaves(BONDING_MODE_BROADCAST, 3, 1) != 0)
+	if (initialize_bonded_device_with_slaves(BONDING_MODE_BROADCAST, 0, 3, 1) != 0)
 		return -1;
 
 
@@ -3419,7 +3566,7 @@  test_broadcast_verify_promiscuous_enable_disable(void)
 	int i, promiscuous_en;
 
 	/* Initialize bonded device with 4 slaves in round robin mode */
-	if (initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 4, 1) != 0)
+	if (initialize_bonded_device_with_slaves(BONDING_MODE_BALANCE, 0, 4, 1) != 0)
 		return -1;
 
 	rte_eth_promiscuous_enable(test_params->bonded_port_id);
@@ -3475,7 +3622,7 @@  test_broadcast_verify_mac_assignment(void)
 	rte_eth_macaddr_get(test_params->slave_port_ids[2], &expected_mac_addr_1);
 
 	/* Initialize bonded device with 4 slaves in round robin mode */
-	if (initialize_bonded_device_with_slaves(BONDING_MODE_BROADCAST, 4, 1) != 0)
+	if (initialize_bonded_device_with_slaves(BONDING_MODE_BROADCAST, 0, 4, 1) != 0)
 		return -1;
 
 	/* Verify that all MACs are the same as first slave added to bonded
@@ -3575,7 +3722,7 @@  test_broadcast_verify_slave_link_status_change_behaviour(void)
 	memset(pkt_burst, 0, sizeof(pkt_burst));
 
 	/* Initialize bonded device with 4 slaves in round robin mode */
-	if (initialize_bonded_device_with_slaves(BONDING_MODE_BROADCAST,
+	if (initialize_bonded_device_with_slaves(BONDING_MODE_BROADCAST, 0,
 			BROADCAST_LINK_STATUS_NUM_OF_SLAVES, 1) != 0)
 		return -1;
 
@@ -3711,7 +3858,7 @@  test_reconfigure_bonded_device(void)
 	test_params->nb_rx_q = 4;
 	test_params->nb_tx_q = 4;
 
-	if (configure_ethdev(test_params->bonded_port_id, 0)  != 0) {
+	if (configure_ethdev(test_params->bonded_port_id, 0, 0)  != 0) {
 		printf("failed to reconfigure bonded device");
 		return -1;
 	}
@@ -3720,7 +3867,7 @@  test_reconfigure_bonded_device(void)
 	test_params->nb_rx_q = 2;
 	test_params->nb_tx_q = 2;
 
-	if (configure_ethdev(test_params->bonded_port_id, 0)  != 0) {
+	if (configure_ethdev(test_params->bonded_port_id, 0, 0)  != 0) {
 		printf("failed to reconfigure bonded device with less rx/tx queues");
 		return -1;
 	}
@@ -3768,6 +3915,7 @@  static struct unit_test_suite link_bonding_test_suite  = {
 		TEST_CASE(test_set_bonding_mode),
 		TEST_CASE(test_set_primary_slave),
 		TEST_CASE(test_set_explicit_bonded_mac),
+		TEST_CASE(test_status_interrupt),
 		TEST_CASE(test_adding_slave_after_bonded_device_started),
 		TEST_CASE(test_roundrobin_tx_burst),
 		TEST_CASE(test_roundrobin_rx_burst_on_single_slave),
diff --git a/lib/librte_pmd_bond/rte_eth_bond_api.c b/lib/librte_pmd_bond/rte_eth_bond_api.c
index 75f5694..dd33119 100644
--- a/lib/librte_pmd_bond/rte_eth_bond_api.c
+++ b/lib/librte_pmd_bond/rte_eth_bond_api.c
@@ -177,6 +177,8 @@  rte_eth_bond_create(const char *name, uint8_t mode, uint8_t socket_id)
 	pci_drv->id_table->vendor_id = PCI_ANY_ID;
 	pci_drv->id_table->subsystem_vendor_id = PCI_ANY_ID;
 
+	pci_drv->drv_flags = RTE_PCI_DRV_INTR_LSC;
+
 	internals = rte_zmalloc_socket(name, sizeof(*internals), 0, socket_id);
 	if (internals == NULL) {
 		RTE_LOG(ERR, PMD, "Unable to malloc internals on socket\n");
@@ -200,6 +202,8 @@  rte_eth_bond_create(const char *name, uint8_t mode, uint8_t socket_id)
 	eth_dev->data->nb_rx_queues = (uint16_t)1;
 	eth_dev->data->nb_tx_queues = (uint16_t)1;
 
+	TAILQ_INIT(&(eth_dev->callbacks));
+
 	eth_dev->data->dev_link.link_status = 0;
 
 	eth_dev->data->mac_addrs = rte_zmalloc_socket(name, ETHER_ADDR_LEN, 0,
diff --git a/lib/librte_pmd_bond/rte_eth_bond_pmd.c b/lib/librte_pmd_bond/rte_eth_bond_pmd.c
index d72d6ed..cd3eecf 100644
--- a/lib/librte_pmd_bond/rte_eth_bond_pmd.c
+++ b/lib/librte_pmd_bond/rte_eth_bond_pmd.c
@@ -921,6 +921,7 @@  bond_ethdev_lsc_event_callback(uint8_t port_id, enum rte_eth_event_type type,
 	struct rte_eth_link link;
 
 	int i, valid_slave = 0, active_pos = -1;
+	uint8_t lsc_flag = 0;
 
 	if (type != RTE_ETH_EVENT_INTR_LSC || param == NULL)
 		return;
@@ -966,6 +967,7 @@  bond_ethdev_lsc_event_callback(uint8_t port_id, enum rte_eth_event_type type,
 			/* If first active slave, then change link status */
 			bonded_eth_dev->data->dev_link.link_status = 1;
 			internals->current_primary_port = port_id;
+			lsc_flag = 1;
 
 			/* Inherit eth dev link properties from first active slave */
 			link_properties_set(bonded_eth_dev,
@@ -990,6 +992,7 @@  bond_ethdev_lsc_event_callback(uint8_t port_id, enum rte_eth_event_type type,
 		/* No active slaves, change link status to down and reset other
 		 * link properties */
 		if (internals->active_slave_count < 1) {
+			lsc_flag = 1;
 			bonded_eth_dev->data->dev_link.link_status = 0;
 
 			link_properties_reset(bonded_eth_dev);
@@ -1005,6 +1008,9 @@  bond_ethdev_lsc_event_callback(uint8_t port_id, enum rte_eth_event_type type,
 				internals->current_primary_port = internals->primary_port;
 		}
 	}
+
+	if (lsc_flag)
+		_rte_eth_dev_callback_process(bonded_eth_dev, RTE_ETH_EVENT_INTR_LSC);
 }
 
 struct eth_dev_ops default_dev_ops = {