[dpdk-dev,v2,4/6] bond mode 4: allow external state machine

Message ID 1455909473-13539-5-git-send-email-ehkinzie@gmail.com (mailing list archive)
State Superseded, archived
Delegated to: Bruce Richardson
Headers

Commit Message

Eric Kinzie Feb. 19, 2016, 7:17 p.m. UTC
  From: Eric Kinzie <ekinzie@brocade.com>

Provide functions to allow an external 802.3ad state machine to transmit
and recieve LACPDUs and to set the collection/distribution flags on
slave interfaces.

Signed-off-by: Eric Kinzie <ehkinzie@gmail.com>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Acked-by: Declan Doherty <declan.doherty@intel.com>
---
 drivers/net/bonding/rte_eth_bond_8023ad.c         |  173 +++++++++++++++++++++
 drivers/net/bonding/rte_eth_bond_8023ad.h         |   44 ++++++
 drivers/net/bonding/rte_eth_bond_8023ad_private.h |    2 +
 drivers/net/bonding/rte_eth_bond_version.map      |    6 +
 4 files changed, 225 insertions(+)
  

Comments

Panu Matilainen Feb. 22, 2016, 1:03 p.m. UTC | #1
On 02/19/2016 09:17 PM, Eric Kinzie wrote:
> From: Eric Kinzie <ekinzie@brocade.com>
>
> Provide functions to allow an external 802.3ad state machine to transmit
> and recieve LACPDUs and to set the collection/distribution flags on
> slave interfaces.
>
> Signed-off-by: Eric Kinzie <ehkinzie@gmail.com>
> Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
> Acked-by: Declan Doherty <declan.doherty@intel.com>
[...]
> diff --git a/drivers/net/bonding/rte_eth_bond_8023ad.h b/drivers/net/bonding/rte_eth_bond_8023ad.h
> index ebd0e93..8cfa3d3 100644
> --- a/drivers/net/bonding/rte_eth_bond_8023ad.h
> +++ b/drivers/net/bonding/rte_eth_bond_8023ad.h
> @@ -64,6 +64,8 @@ extern "C" {
>   #define MARKER_TLV_TYPE_INFO                0x01
>   #define MARKER_TLV_TYPE_RESP                0x02
>
> +typedef void (*rte_eth_bond_8023ad_ext_slowrx_fn)(uint8_t slave_id, struct rte_mbuf *lacp_pkt);
> +
>   enum rte_bond_8023ad_selection {
>   	UNSELECTED,
>   	STANDBY,
> @@ -157,6 +159,7 @@ struct rte_eth_bond_8023ad_conf {
>   	uint32_t tx_period_ms;
>   	uint32_t rx_marker_period_ms;
>   	uint32_t update_timeout_ms;
> +	rte_eth_bond_8023ad_ext_slowrx_fn slowrx_cb;
>   };

This still is a likely an ABI break, previously discussed around here:
http://dpdk.org/ml/archives/dev/2015-November/027321.html

It might not be embedded anywhere in DPDK codebase, but there's no 
telling what others might have done with it (have an array of them, 
embed in other structs etc).

Also ultimately ABI compatibility goes both ways: when the library 
soname does not change then an application is free to assume both 
downgrading and upgrading are safe. In this case, upgrading *might* be 
okay, downgrading certainly is not. So by that measure it definitely is 
an ABI break.

[...]
> diff --git a/drivers/net/bonding/rte_eth_bond_version.map b/drivers/net/bonding/rte_eth_bond_version.map
> index 22bd920..33d73ff 100644
> --- a/drivers/net/bonding/rte_eth_bond_version.map
> +++ b/drivers/net/bonding/rte_eth_bond_version.map
> @@ -27,3 +27,9 @@ DPDK_2.1 {
>   	rte_eth_bond_free;
>
>   } DPDK_2.0;
> +
> +DPDK_2.2 {
> +	rte_eth_bond_8023ad_ext_collect;
> +	rte_eth_bond_8023ad_ext_distrib;
> +	rte_eth_bond_8023ad_ext_slowtx;
> +} DPDK_2.1;
>

These symbols are not part of DPDK 2.2, the version here is wrong. 
Technically it would not actually matter much but better not to confuse 
things unnecessarily.

	- Panu -
  
Iremonger, Bernard Feb. 25, 2016, 3:22 p.m. UTC | #2
Hi Eric,
<snip>

> > @@ -157,6 +159,7 @@ struct rte_eth_bond_8023ad_conf {

> >   	uint32_t tx_period_ms;

> >   	uint32_t rx_marker_period_ms;

> >   	uint32_t update_timeout_ms;

> > +	rte_eth_bond_8023ad_ext_slowrx_fn slowrx_cb;

> >   };

> 

> This still is a likely an ABI break, previously discussed around here:

> http://dpdk.org/ml/archives/dev/2015-November/027321.html

> 

> It might not be embedded anywhere in DPDK codebase, but there's no

> telling what others might have done with it (have an array of them, embed in

> other structs etc).

> 

> Also ultimately ABI compatibility goes both ways: when the library soname

> does not change then an application is free to assume both downgrading and

> upgrading are safe. In this case, upgrading *might* be okay, downgrading

> certainly is not. So by that measure it definitely is an ABI break.

> 

> [...]

> > diff --git a/drivers/net/bonding/rte_eth_bond_version.map

> > b/drivers/net/bonding/rte_eth_bond_version.map

> > index 22bd920..33d73ff 100644

> > --- a/drivers/net/bonding/rte_eth_bond_version.map

> > +++ b/drivers/net/bonding/rte_eth_bond_version.map

> > @@ -27,3 +27,9 @@ DPDK_2.1 {

> >   	rte_eth_bond_free;

> >

> >   } DPDK_2.0;

> > +

> > +DPDK_2.2 {

> > +	rte_eth_bond_8023ad_ext_collect;

> > +	rte_eth_bond_8023ad_ext_distrib;

> > +	rte_eth_bond_8023ad_ext_slowtx;

> > +} DPDK_2.1;

> >

> 

> These symbols are not part of DPDK 2.2, the version here is wrong.

> Technically it would not actually matter much but better not to confuse

> things unnecessarily.

> 

> 	- Panu -


It looks like Panu's points are valid, a V3 of this patch set which takes care of these issues will be needed.

Patches 1/6, 5/6 and 6/6 of the patch set are bug fixes, so each patch should contain a fixes line.
Patches 2/6, 3/6 and 4/6 are a new feature, the release notes should be updated for this feature.

Could I suggest splitting the patch set into two patch sets, a bug fix patch set and a new feature patch set.

Regards,

Bernard.
  
Eric Kinzie March 1, 2016, 5:31 p.m. UTC | #3
These are bug fixes and some small enhancements to allow bonding
to work with external control (teamd). Please consider integrating
these into DPDK 2.2

Changes in v2:
- remove "bond: handle slaves with fewer queues than bonding device"
- remove "bond: per-slave intermediate rx ring"

Changes in v3:
This version has only fixes.  Patches with new functionality have been
removed and will be submitted separately.
- remove "bond mode 4: allow external state machine"
- remove "bond: use existing enslaved device queues"

Eric Kinzie (4):
  bond mode 4: copy entire config structure
  bond mode 4: do not ignore multicast
  bond: active slaves with no primary
  bond: do not activate slave twice

 app/test/test_link_bonding_mode4.c        |  7 +++++--
 drivers/net/bonding/rte_eth_bond_8023ad.c |  1 +
 drivers/net/bonding/rte_eth_bond_api.c    | 13 +++++++++++--
 drivers/net/bonding/rte_eth_bond_pmd.c    |  1 +
 4 files changed, 18 insertions(+), 4 deletions(-)
  
Eric Kinzie March 1, 2016, 5:40 p.m. UTC | #4
On Thu Feb 25 15:22:35 +0000 2016, Iremonger, Bernard wrote:
> Hi Eric,
> <snip>
> 
> > > @@ -157,6 +159,7 @@ struct rte_eth_bond_8023ad_conf {
> > >   	uint32_t tx_period_ms;
> > >   	uint32_t rx_marker_period_ms;
> > >   	uint32_t update_timeout_ms;
> > > +	rte_eth_bond_8023ad_ext_slowrx_fn slowrx_cb;
> > >   };
> > 
> > This still is a likely an ABI break, previously discussed around here:
> > http://dpdk.org/ml/archives/dev/2015-November/027321.html
> > 
> > It might not be embedded anywhere in DPDK codebase, but there's no
> > telling what others might have done with it (have an array of them, embed in
> > other structs etc).
> > 
> > Also ultimately ABI compatibility goes both ways: when the library soname
> > does not change then an application is free to assume both downgrading and
> > upgrading are safe. In this case, upgrading *might* be okay, downgrading
> > certainly is not. So by that measure it definitely is an ABI break.
> > 
> > [...]
> > > diff --git a/drivers/net/bonding/rte_eth_bond_version.map
> > > b/drivers/net/bonding/rte_eth_bond_version.map
> > > index 22bd920..33d73ff 100644
> > > --- a/drivers/net/bonding/rte_eth_bond_version.map
> > > +++ b/drivers/net/bonding/rte_eth_bond_version.map
> > > @@ -27,3 +27,9 @@ DPDK_2.1 {
> > >   	rte_eth_bond_free;
> > >
> > >   } DPDK_2.0;
> > > +
> > > +DPDK_2.2 {
> > > +	rte_eth_bond_8023ad_ext_collect;
> > > +	rte_eth_bond_8023ad_ext_distrib;
> > > +	rte_eth_bond_8023ad_ext_slowtx;
> > > +} DPDK_2.1;
> > >
> > 
> > These symbols are not part of DPDK 2.2, the version here is wrong.
> > Technically it would not actually matter much but better not to confuse
> > things unnecessarily.
> > 
> > 	- Panu -
> 
> It looks like Panu's points are valid, a V3 of this patch set which takes care of these issues will be needed.
> 
> Patches 1/6, 5/6 and 6/6 of the patch set are bug fixes, so each patch should contain a fixes line.
> Patches 2/6, 3/6 and 4/6 are a new feature, the release notes should be updated for this feature.
> 
> Could I suggest splitting the patch set into two patch sets, a bug fix patch set and a new feature patch set.
> 
> Regards,
> 
> Bernard.

Bernard, a v3 is on the way.  I included only things that are fixes,
but the patch set doesn't quite match the set of patch numbers you listed
above.  1/6 (bond: use existing enslaved device queues) is an improvement,
but doesn't really fix anything that was broken, so I left that out.
2/6 (bond mode 4: copy entire config structure) and 3/6 (bond mode 4:
do not ignore multicast) fix bugs and are included.


Eric
  
Iremonger, Bernard March 2, 2016, 9:49 a.m. UTC | #5
Hi Eric,

<snip>

> > > > @@ -157,6 +159,7 @@ struct rte_eth_bond_8023ad_conf {
> > > >   	uint32_t tx_period_ms;
> > > >   	uint32_t rx_marker_period_ms;
> > > >   	uint32_t update_timeout_ms;
> > > > +	rte_eth_bond_8023ad_ext_slowrx_fn slowrx_cb;
> > > >   };
> > >
> > > This still is a likely an ABI break, previously discussed around here:
> > > http://dpdk.org/ml/archives/dev/2015-November/027321.html
> > >
> > > It might not be embedded anywhere in DPDK codebase, but there's no
> > > telling what others might have done with it (have an array of them,
> > > embed in other structs etc).
> > >
> > > Also ultimately ABI compatibility goes both ways: when the library
> > > soname does not change then an application is free to assume both
> > > downgrading and upgrading are safe. In this case, upgrading *might*
> > > be okay, downgrading certainly is not. So by that measure it definitely is
> an ABI break.
> > >
> > > [...]
> > > > diff --git a/drivers/net/bonding/rte_eth_bond_version.map
> > > > b/drivers/net/bonding/rte_eth_bond_version.map
> > > > index 22bd920..33d73ff 100644
> > > > --- a/drivers/net/bonding/rte_eth_bond_version.map
> > > > +++ b/drivers/net/bonding/rte_eth_bond_version.map
> > > > @@ -27,3 +27,9 @@ DPDK_2.1 {
> > > >   	rte_eth_bond_free;
> > > >
> > > >   } DPDK_2.0;
> > > > +
> > > > +DPDK_2.2 {
> > > > +	rte_eth_bond_8023ad_ext_collect;
> > > > +	rte_eth_bond_8023ad_ext_distrib;
> > > > +	rte_eth_bond_8023ad_ext_slowtx;
> > > > +} DPDK_2.1;
> > > >
> > >
> > > These symbols are not part of DPDK 2.2, the version here is wrong.
> > > Technically it would not actually matter much but better not to
> > > confuse things unnecessarily.
> > >
> > > 	- Panu -
> >
> > It looks like Panu's points are valid, a V3 of this patch set which takes care of
> these issues will be needed.
> >
> > Patches 1/6, 5/6 and 6/6 of the patch set are bug fixes, so each patch
> should contain a fixes line.
> > Patches 2/6, 3/6 and 4/6 are a new feature, the release notes should be
> updated for this feature.
> >
> > Could I suggest splitting the patch set into two patch sets, a bug fix patch
> set and a new feature patch set.
> >
> > Regards,
> >
> > Bernard.
> 
> Bernard, a v3 is on the way.  I included only things that are fixes, but the
> patch set doesn't quite match the set of patch numbers you listed above.
> 1/6 (bond: use existing enslaved device queues) is an improvement, but
> doesn't really fix anything that was broken, so I left that out.
> 2/6 (bond mode 4: copy entire config structure) and 3/6 (bond mode 4:
> do not ignore multicast) fix bugs and are included.
> 
> 
> Eric

Thanks for the V3 patchset and clarifying which patches in the V2 patchset were fixes.

Regards,

Bernard.
  
Bruce Richardson March 10, 2016, 3:41 p.m. UTC | #6
On Tue, Mar 01, 2016 at 09:31:58AM -0800, Eric Kinzie wrote:
> These are bug fixes and some small enhancements to allow bonding
> to work with external control (teamd). Please consider integrating
> these into DPDK 2.2
> 
> Changes in v2:
> - remove "bond: handle slaves with fewer queues than bonding device"
> - remove "bond: per-slave intermediate rx ring"
> 
> Changes in v3:
> This version has only fixes.  Patches with new functionality have been
> removed and will be submitted separately.
> - remove "bond mode 4: allow external state machine"
> - remove "bond: use existing enslaved device queues"
> 
> Eric Kinzie (4):
>   bond mode 4: copy entire config structure
>   bond mode 4: do not ignore multicast
>   bond: active slaves with no primary
>   bond: do not activate slave twice
> 
>  app/test/test_link_bonding_mode4.c        |  7 +++++--
>  drivers/net/bonding/rte_eth_bond_8023ad.c |  1 +
>  drivers/net/bonding/rte_eth_bond_api.c    | 13 +++++++++++--
>  drivers/net/bonding/rte_eth_bond_pmd.c    |  1 +
>  4 files changed, 18 insertions(+), 4 deletions(-)
> 
> -- 
> 2.1.4
> 
Applied to dpdk-next-net/rel_16_04

/Bruce
  

Patch

diff --git a/drivers/net/bonding/rte_eth_bond_8023ad.c b/drivers/net/bonding/rte_eth_bond_8023ad.c
index 1b7e93a..a260e06 100644
--- a/drivers/net/bonding/rte_eth_bond_8023ad.c
+++ b/drivers/net/bonding/rte_eth_bond_8023ad.c
@@ -42,6 +42,8 @@ 
 
 #include "rte_eth_bond_private.h"
 
+static void bond_mode_8023ad_ext_periodic_cb(void *arg);
+
 #ifdef RTE_LIBRTE_BOND_DEBUG_8023AD
 #define MODE4_DEBUG(fmt, ...) RTE_LOG(DEBUG, PMD, "%6u [Port %u: %s] " fmt, \
 			bond_dbg_get_time_diff_ms(), slave_id, \
@@ -1020,6 +1022,7 @@  bond_mode_8023ad_conf_get(struct rte_eth_dev *dev,
 	conf->tx_period_ms = mode4->tx_period_timeout / ms_ticks;
 	conf->update_timeout_ms = mode4->update_timeout_us / 1000;
 	conf->rx_marker_period_ms = mode4->rx_marker_timeout / ms_ticks;
+	conf->slowrx_cb = mode4->slowrx_cb;
 }
 
 void
@@ -1041,8 +1044,11 @@  bond_mode_8023ad_setup(struct rte_eth_dev *dev,
 		conf->tx_period_ms = BOND_8023AD_TX_MACHINE_PERIOD_MS;
 		conf->rx_marker_period_ms = BOND_8023AD_RX_MARKER_PERIOD_MS;
 		conf->update_timeout_ms = BOND_MODE_8023AX_UPDATE_TIMEOUT_MS;
+		conf->slowrx_cb = NULL;
 	}
 
+	bond_mode_8023ad_stop(dev);
+
 	mode4->fast_periodic_timeout = conf->fast_periodic_ms * ms_ticks;
 	mode4->slow_periodic_timeout = conf->slow_periodic_ms * ms_ticks;
 	mode4->short_timeout = conf->short_timeout_ms * ms_ticks;
@@ -1051,6 +1057,10 @@  bond_mode_8023ad_setup(struct rte_eth_dev *dev,
 	mode4->tx_period_timeout = conf->tx_period_ms * ms_ticks;
 	mode4->rx_marker_timeout = conf->rx_marker_period_ms * ms_ticks;
 	mode4->update_timeout_us = conf->update_timeout_ms * 1000;
+	mode4->slowrx_cb = conf->slowrx_cb;
+
+	if (dev->data->dev_started)
+		bond_mode_8023ad_start(dev);
 }
 
 int
@@ -1068,6 +1078,13 @@  bond_mode_8023ad_enable(struct rte_eth_dev *bond_dev)
 int
 bond_mode_8023ad_start(struct rte_eth_dev *bond_dev)
 {
+	struct bond_dev_private *internals = bond_dev->data->dev_private;
+	struct mode8023ad_private *mode4 = &internals->mode4;
+
+	if (mode4->slowrx_cb)
+		return rte_eal_alarm_set(BOND_MODE_8023AX_UPDATE_TIMEOUT_MS * 1000,
+			&bond_mode_8023ad_ext_periodic_cb, bond_dev);
+
 	return rte_eal_alarm_set(BOND_MODE_8023AX_UPDATE_TIMEOUT_MS * 1000,
 			&bond_mode_8023ad_periodic_cb, bond_dev);
 }
@@ -1075,6 +1092,13 @@  bond_mode_8023ad_start(struct rte_eth_dev *bond_dev)
 void
 bond_mode_8023ad_stop(struct rte_eth_dev *bond_dev)
 {
+	struct bond_dev_private *internals = bond_dev->data->dev_private;
+	struct mode8023ad_private *mode4 = &internals->mode4;
+
+	if (mode4->slowrx_cb) {
+		rte_eal_alarm_cancel(&bond_mode_8023ad_ext_periodic_cb, bond_dev);
+		return;
+	}
 	rte_eal_alarm_cancel(&bond_mode_8023ad_periodic_cb, bond_dev);
 }
 
@@ -1221,3 +1245,152 @@  rte_eth_bond_8023ad_slave_info(uint8_t port_id, uint8_t slave_id,
 	info->agg_port_id = port->aggregator_port_id;
 	return 0;
 }
+
+int
+rte_eth_bond_8023ad_ext_collect(uint8_t port_id, uint8_t slave_id, int enabled)
+{
+	struct rte_eth_dev *bond_dev;
+	struct bond_dev_private *internals;
+	struct mode8023ad_private *mode4;
+	struct port *port;
+
+	if (rte_eth_bond_mode_get(port_id) != BONDING_MODE_8023AD)
+		return -EINVAL;
+
+	bond_dev = &rte_eth_devices[port_id];
+
+	if (!bond_dev->data->dev_started)
+		return -EINVAL;
+
+	internals = bond_dev->data->dev_private;
+	if (find_slave_by_id(internals->active_slaves,
+			internals->active_slave_count, slave_id) ==
+				internals->active_slave_count)
+		return -EINVAL;
+
+	mode4 = &internals->mode4;
+	if (mode4->slowrx_cb == NULL)
+		return -EINVAL;
+
+	port = &mode_8023ad_ports[slave_id];
+
+	if (enabled)
+		ACTOR_STATE_SET(port, COLLECTING);
+	else
+		ACTOR_STATE_CLR(port, COLLECTING);
+
+	return 0;
+}
+
+int
+rte_eth_bond_8023ad_ext_distrib(uint8_t port_id, uint8_t slave_id, int enabled)
+{
+	struct rte_eth_dev *bond_dev;
+	struct bond_dev_private *internals;
+	struct mode8023ad_private *mode4;
+	struct port *port;
+
+	if (rte_eth_bond_mode_get(port_id) != BONDING_MODE_8023AD)
+		return -EINVAL;
+
+	bond_dev = &rte_eth_devices[port_id];
+
+	if (!bond_dev->data->dev_started)
+		return -EINVAL;
+
+	internals = bond_dev->data->dev_private;
+	if (find_slave_by_id(internals->active_slaves,
+			internals->active_slave_count, slave_id) ==
+				internals->active_slave_count)
+		return -EINVAL;
+
+	mode4 = &internals->mode4;
+	if (mode4->slowrx_cb == NULL)
+		return -EINVAL;
+
+	port = &mode_8023ad_ports[slave_id];
+
+	if (enabled)
+		ACTOR_STATE_SET(port, DISTRIBUTING);
+	else
+		ACTOR_STATE_CLR(port, DISTRIBUTING);
+
+	return 0;
+}
+
+int
+rte_eth_bond_8023ad_ext_slowtx(uint8_t port_id, uint8_t slave_id,
+		struct rte_mbuf *lacp_pkt)
+{
+	struct rte_eth_dev *bond_dev;
+	struct bond_dev_private *internals;
+	struct mode8023ad_private *mode4;
+	struct port *port;
+
+	if (rte_eth_bond_mode_get(port_id) != BONDING_MODE_8023AD)
+		return -EINVAL;
+
+	bond_dev = &rte_eth_devices[port_id];
+
+	if (!bond_dev->data->dev_started)
+		return -EINVAL;
+
+	internals = bond_dev->data->dev_private;
+	if (find_slave_by_id(internals->active_slaves,
+			internals->active_slave_count, slave_id) ==
+				internals->active_slave_count)
+		return -EINVAL;
+
+	mode4 = &internals->mode4;
+	if (mode4->slowrx_cb == NULL)
+		return -EINVAL;
+
+	port = &mode_8023ad_ports[slave_id];
+
+	if (rte_pktmbuf_pkt_len(lacp_pkt) < sizeof(struct lacpdu_header))
+		return -EINVAL;
+
+	struct lacpdu_header *lacp;
+
+	/* only enqueue LACPDUs */
+	lacp = rte_pktmbuf_mtod(lacp_pkt, struct lacpdu_header *);
+	if (lacp->lacpdu.subtype != SLOW_SUBTYPE_LACP)
+		return -EINVAL;
+
+	MODE4_DEBUG("sending LACP frame\n");
+
+	return rte_ring_enqueue(port->tx_ring, lacp_pkt);
+}
+
+static void
+bond_mode_8023ad_ext_periodic_cb(void *arg)
+{
+	struct rte_eth_dev *bond_dev = arg;
+	struct bond_dev_private *internals = bond_dev->data->dev_private;
+	struct mode8023ad_private *mode4 = &internals->mode4;
+	struct port *port;
+	void *pkt = NULL;
+	uint16_t i, slave_id;
+
+	for (i = 0; i < internals->active_slave_count; i++) {
+		slave_id = internals->active_slaves[i];
+		port = &mode_8023ad_ports[slave_id];
+
+		if (rte_ring_dequeue(port->rx_ring, &pkt) == 0) {
+			struct rte_mbuf *lacp_pkt = pkt;
+			struct lacpdu_header *lacp;
+
+			lacp = rte_pktmbuf_mtod(lacp_pkt,
+						struct lacpdu_header *);
+			RTE_VERIFY(lacp->lacpdu.subtype == SLOW_SUBTYPE_LACP);
+
+			/* This is LACP frame so pass it to rx callback.
+			 * Callback is responsible for freeing mbuf.
+			 */
+			mode4->slowrx_cb(slave_id, lacp_pkt);
+		}
+	}
+
+	rte_eal_alarm_set(internals->mode4.update_timeout_us,
+			bond_mode_8023ad_ext_periodic_cb, arg);
+}
diff --git a/drivers/net/bonding/rte_eth_bond_8023ad.h b/drivers/net/bonding/rte_eth_bond_8023ad.h
index ebd0e93..8cfa3d3 100644
--- a/drivers/net/bonding/rte_eth_bond_8023ad.h
+++ b/drivers/net/bonding/rte_eth_bond_8023ad.h
@@ -64,6 +64,8 @@  extern "C" {
 #define MARKER_TLV_TYPE_INFO                0x01
 #define MARKER_TLV_TYPE_RESP                0x02
 
+typedef void (*rte_eth_bond_8023ad_ext_slowrx_fn)(uint8_t slave_id, struct rte_mbuf *lacp_pkt);
+
 enum rte_bond_8023ad_selection {
 	UNSELECTED,
 	STANDBY,
@@ -157,6 +159,7 @@  struct rte_eth_bond_8023ad_conf {
 	uint32_t tx_period_ms;
 	uint32_t rx_marker_period_ms;
 	uint32_t update_timeout_ms;
+	rte_eth_bond_8023ad_ext_slowrx_fn slowrx_cb;
 };
 
 struct rte_eth_bond_8023ad_slave_info {
@@ -219,4 +222,45 @@  rte_eth_bond_8023ad_slave_info(uint8_t port_id, uint8_t slave_id,
 }
 #endif
 
+/**
+ * Configure a slave port to start collecting.
+ *
+ * @param port_id	Bonding device id
+ * @param slave_id	Port id of valid slave.
+ * @param enabled	Non-zero when collection enabled.
+ * @return
+ *   0 - if ok
+ *   -EINVAL if slave is not valid.
+ */
+int
+rte_eth_bond_8023ad_ext_collect(uint8_t port_id, uint8_t slave_id, int enabled);
+
+/**
+ * Configure a slave port to start distributing.
+ *
+ * @param port_id	Bonding device id
+ * @param slave_id	Port id of valid slave.
+ * @param enabled	Non-zero when distribution enabled.
+ * @return
+ *   0 - if ok
+ *   -EINVAL if slave is not valid.
+ */
+int
+rte_eth_bond_8023ad_ext_distrib(uint8_t port_id, uint8_t slave_id, int enabled);
+
+/**
+ * LACPDU transmit path for external 802.3ad state machine.  Caller retains
+ * ownership of the packet on failure.
+ *
+ * @param port_id	Bonding device id
+ * @param slave_id	Port ID of valid slave device.
+ * @param lacp_pkt	mbuf containing LACPDU.
+ *
+ * @return
+ *   0 on success, negative value otherwise.
+ */
+int
+rte_eth_bond_8023ad_ext_slowtx(uint8_t port_id, uint8_t slave_id,
+		struct rte_mbuf *lacp_pkt);
+
 #endif /* RTE_ETH_BOND_8023AD_H_ */
diff --git a/drivers/net/bonding/rte_eth_bond_8023ad_private.h b/drivers/net/bonding/rte_eth_bond_8023ad_private.h
index 8adee70..9e15ece 100644
--- a/drivers/net/bonding/rte_eth_bond_8023ad_private.h
+++ b/drivers/net/bonding/rte_eth_bond_8023ad_private.h
@@ -173,6 +173,8 @@  struct mode8023ad_private {
 	uint64_t tx_period_timeout;
 	uint64_t rx_marker_timeout;
 	uint64_t update_timeout_us;
+	rte_eth_bond_8023ad_ext_slowrx_fn slowrx_cb;
+	uint8_t external_sm;
 };
 
 /**
diff --git a/drivers/net/bonding/rte_eth_bond_version.map b/drivers/net/bonding/rte_eth_bond_version.map
index 22bd920..33d73ff 100644
--- a/drivers/net/bonding/rte_eth_bond_version.map
+++ b/drivers/net/bonding/rte_eth_bond_version.map
@@ -27,3 +27,9 @@  DPDK_2.1 {
 	rte_eth_bond_free;
 
 } DPDK_2.0;
+
+DPDK_2.2 {
+	rte_eth_bond_8023ad_ext_collect;
+	rte_eth_bond_8023ad_ext_distrib;
+	rte_eth_bond_8023ad_ext_slowtx;
+} DPDK_2.1;