From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by dpdk.org (Postfix) with ESMTP id 0EB116A95 for ; Mon, 29 Sep 2014 15:45:10 +0200 (CEST) Received: from azsmga001.ch.intel.com ([10.2.17.19]) by fmsmga102.fm.intel.com with ESMTP; 29 Sep 2014 06:51:32 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.04,620,1406617200"; d="scan'208";a="480740170" Received: from irsmsx102.ger.corp.intel.com ([163.33.3.155]) by azsmga001.ch.intel.com with ESMTP; 29 Sep 2014 06:51:01 -0700 Received: from irsmsx109.ger.corp.intel.com ([169.254.13.253]) by IRSMSX102.ger.corp.intel.com ([169.254.2.200]) with mapi id 14.03.0195.001; Mon, 29 Sep 2014 14:51:00 +0100 From: "Jastrzebski, MichalX K" To: "Wodkowski, PawelX" , "dev@dpdk.org" Thread-Topic: [dpdk-dev] [PATCH v2] bond: Add mode 4 support. Thread-Index: AQHP2+ivi3v4GrcbfUG4iudmPfbZS5wYHzTQ Date: Mon, 29 Sep 2014 13:51:00 +0000 Message-ID: <60ABE07DBB3A454EB7FAD707B4BB15821389D4C7@IRSMSX109.ger.corp.intel.com> References: <1411996978-3123-1-git-send-email-pawelx.wodkowski@intel.com> In-Reply-To: <1411996978-3123-1-git-send-email-pawelx.wodkowski@intel.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [163.33.239.182] Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Subject: Re: [dpdk-dev] [PATCH v2] bond: Add mode 4 support. X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 29 Sep 2014 13:45:12 -0000 Please don't take this patch into account. Two files are missing. Best regards Michal > -----Original Message----- > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Pawel Wodkowski > Sent: Monday, September 29, 2014 3:23 PM > To: dev@dpdk.org > Subject: [dpdk-dev] [PATCH v2] bond: Add mode 4 support. >=20 > This patch adds support mode 4 of link bonding. It depend on Delcan > Doherty > patches v3 and rte alarms patch v2 or above. >=20 > New version handles race issues with setting/cancelin callbacks, > fixes promiscus mode setting in mode 4 and some other minor errors in > mode 4 > implementation. >=20 >=20 > Signed-off-by: Pawel Wodkowski > --- > lib/librte_ether/rte_ether.h | 1 + > lib/librte_pmd_bond/Makefile | 1 + > lib/librte_pmd_bond/rte_eth_bond.h | 4 + > lib/librte_pmd_bond/rte_eth_bond_api.c | 82 ++++++--- > lib/librte_pmd_bond/rte_eth_bond_args.c | 1 + > lib/librte_pmd_bond/rte_eth_bond_pmd.c | 261 > +++++++++++++++++++++++++--- > lib/librte_pmd_bond/rte_eth_bond_private.h | 42 ++++- > 7 files changed, 346 insertions(+), 46 deletions(-) >=20 > diff --git a/lib/librte_ether/rte_ether.h b/lib/librte_ether/rte_ether.h > index 2e08f23..1a3711b 100644 > --- a/lib/librte_ether/rte_ether.h > +++ b/lib/librte_ether/rte_ether.h > @@ -293,6 +293,7 @@ struct vlan_hdr { > #define ETHER_TYPE_RARP 0x8035 /**< Reverse Arp Protocol. */ > #define ETHER_TYPE_VLAN 0x8100 /**< IEEE 802.1Q VLAN tagging. */ > #define ETHER_TYPE_1588 0x88F7 /**< IEEE 802.1AS 1588 Precise Time > Protocol. */ > +#define ETHER_TYPE_SLOW 0x8809 /**< Slow protocols (LACP and Marker). > */ >=20 > #ifdef __cplusplus > } > diff --git a/lib/librte_pmd_bond/Makefile b/lib/librte_pmd_bond/Makefile > index 953d75e..c2312c2 100644 > --- a/lib/librte_pmd_bond/Makefile > +++ b/lib/librte_pmd_bond/Makefile > @@ -44,6 +44,7 @@ CFLAGS +=3D $(WERROR_FLAGS) > # > SRCS-$(CONFIG_RTE_LIBRTE_PMD_BOND) +=3D rte_eth_bond_api.c > SRCS-$(CONFIG_RTE_LIBRTE_PMD_BOND) +=3D rte_eth_bond_pmd.c > +SRCS-$(CONFIG_RTE_LIBRTE_PMD_BOND) +=3D rte_eth_bond_8023ad.c > SRCS-$(CONFIG_RTE_LIBRTE_PMD_BOND) +=3D rte_eth_bond_args.c >=20 > # > diff --git a/lib/librte_pmd_bond/rte_eth_bond.h > b/lib/librte_pmd_bond/rte_eth_bond.h > index 6811c7b..b0223c2 100644 > --- a/lib/librte_pmd_bond/rte_eth_bond.h > +++ b/lib/librte_pmd_bond/rte_eth_bond.h > @@ -75,6 +75,10 @@ extern "C" { > /**< Broadcast (Mode 3). > * In this mode all transmitted packets will be transmitted on all avail= able > * active slaves of the bonded. */ > +#define BONDING_MODE_8023AD (4) > +/**< 802.3AD (Mode 4). > + * In this mode transmission and reception of packets is managed by LACP > + * protocol specified in 802.3AD documentation. */ >=20 > /* Balance Mode Transmit Policies */ > #define BALANCE_XMIT_POLICY_LAYER2 (0) > diff --git a/lib/librte_pmd_bond/rte_eth_bond_api.c > b/lib/librte_pmd_bond/rte_eth_bond_api.c > index c690ceb..c547164 100644 > --- a/lib/librte_pmd_bond/rte_eth_bond_api.c > +++ b/lib/librte_pmd_bond/rte_eth_bond_api.c > @@ -31,6 +31,8 @@ > * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH > DAMAGE. > */ >=20 > +#include > + > #include > #include > #include > @@ -104,6 +106,44 @@ valid_slave_port_id(uint8_t port_id) > return 0; > } >=20 > +void > +activate_slave(struct rte_eth_dev *eth_dev, uint8_t port_id) > +{ > + struct bond_dev_private *internals =3D eth_dev->data->dev_private; > + uint8_t active_count =3D internals->active_slave_count; > + > + internals->active_slaves[active_count] =3D port_id; > + > + if (internals->mode =3D=3D BONDING_MODE_8023AD) > + bond_mode_8023ad_slave_append(eth_dev); > + > + internals->active_slave_count =3D active_count + 1; > +} > + > +void > +deactivate_slave(struct rte_eth_dev *eth_dev, > + uint8_t slave_pos) > +{ > + struct bond_dev_private *internals =3D eth_dev->data->dev_private; > + uint8_t active_count =3D internals->active_slave_count; > + > + if (internals->mode =3D=3D BONDING_MODE_8023AD) > + bond_mode_8023ad_deactivate_slave(eth_dev, slave_pos); > + > + active_count--; > + > + /* If slave was not at the end of the list > + * shift active slaves up active array list */ > + if (slave_pos < active_count) { > + memmove(internals->active_slaves + slave_pos, > + internals->active_slaves + slave_pos + 1, > + (active_count - slave_pos) * > + sizeof(internals->active_slaves[0])); > + } > + > + internals->active_slave_count =3D active_count; > +} > + > uint8_t > number_of_sockets(void) > { > @@ -216,12 +256,8 @@ rte_eth_bond_create(const char *name, uint8_t > mode, uint8_t socket_id) > eth_dev->dev_ops =3D &default_dev_ops; > eth_dev->pci_dev =3D pci_dev; >=20 > - if (bond_ethdev_mode_set(eth_dev, mode)) { > - RTE_BOND_LOG(ERR, "Failed to set bonded device %d mode > too %d", > - eth_dev->data->port_id, mode); > - goto err; > - } > - > + internals->port_id =3D eth_dev->data->port_id; > + internals->mode =3D BONDING_MODE_INVALID; > internals->current_primary_port =3D 0; > internals->balance_xmit_policy =3D BALANCE_XMIT_POLICY_LAYER2; > internals->user_defined_mac =3D 0; > @@ -241,6 +277,12 @@ rte_eth_bond_create(const char *name, uint8_t > mode, uint8_t socket_id) > memset(internals->active_slaves, 0, sizeof(internals->active_slaves)); > memset(internals->slaves, 0, sizeof(internals->slaves)); >=20 > + if (bond_ethdev_mode_set(eth_dev, mode)) { > + RTE_BOND_LOG(ERR, "Failed to set bonded device %d mode > too %d", > + eth_dev->data->port_id, mode); > + goto err; > + } > + > return eth_dev->data->port_id; >=20 > err: > @@ -348,14 +390,12 @@ __eth_bond_slave_add_lock_free(uint8_t > bonded_port_id, uint8_t slave_port_id) > rte_eth_link_get_nowait(slave_port_id, &link_props); >=20 > if (link_props.link_status =3D=3D 1) > - internals->active_slaves[internals- > >active_slave_count++] =3D > - slave_port_id; > + activate_slave(bonded_eth_dev, slave_port_id); > } > return 0; >=20 > } >=20 > - > int > rte_eth_bond_slave_add(uint8_t bonded_port_id, uint8_t slave_port_id) > { > @@ -380,31 +420,26 @@ rte_eth_bond_slave_add(uint8_t bonded_port_id, > uint8_t slave_port_id) > return retval; > } >=20 > - > static int > __eth_bond_slave_remove_lock_free(uint8_t bonded_port_id, uint8_t > slave_port_id) > { > + struct rte_eth_dev *bonded_eth_dev; > struct bond_dev_private *internals; >=20 > - int i, slave_idx =3D -1; > + int i, slave_idx; >=20 > if (valid_slave_port_id(slave_port_id) !=3D 0) > return -1; >=20 > - internals =3D rte_eth_devices[bonded_port_id].data->dev_private; > + bonded_eth_dev =3D &rte_eth_devices[bonded_port_id]; > + internals =3D bonded_eth_dev->data->dev_private; >=20 > /* first remove from active slave list */ > - for (i =3D 0; i < internals->active_slave_count; i++) { > - if (internals->active_slaves[i] =3D=3D slave_port_id) > - slave_idx =3D i; > + slave_idx =3D find_slave_by_id(internals->active_slaves, internals- > >active_slave_count, > + slave_port_id); >=20 > - /* shift active slaves up active array list */ > - if (slave_idx >=3D 0 && i < (internals->active_slave_count - 1)) > - internals->active_slaves[i] =3D internals- > >active_slaves[i+1]; > - } > - > - if (slave_idx >=3D 0) > - internals->active_slave_count--; > + if (slave_idx < internals->active_slave_count) > + deactivate_slave(bonded_eth_dev, slave_idx); >=20 > slave_idx =3D -1; > /* now find in slave list */ > @@ -538,6 +573,7 @@ rte_eth_bond_primary_get(uint8_t bonded_port_id) >=20 > return internals->current_primary_port; > } > + > int > rte_eth_bond_slaves_get(uint8_t bonded_port_id, uint8_t slaves[], uint8_= t > len) > { > @@ -673,7 +709,6 @@ rte_eth_bond_xmit_policy_get(uint8_t > bonded_port_id) > return internals->balance_xmit_policy; > } >=20 > - > int > rte_eth_bond_link_monitoring_set(uint8_t bonded_port_id, uint32_t > internal_ms) > { > @@ -729,7 +764,6 @@ rte_eth_bond_link_down_prop_delay_get(uint8_t > bonded_port_id) > return internals->link_down_delay_ms; > } >=20 > - > int > rte_eth_bond_link_up_prop_delay_set(uint8_t bonded_port_id, uint32_t > delay_ms) >=20 > diff --git a/lib/librte_pmd_bond/rte_eth_bond_args.c > b/lib/librte_pmd_bond/rte_eth_bond_args.c > index bbbc69b..a0be0e6 100644 > --- a/lib/librte_pmd_bond/rte_eth_bond_args.c > +++ b/lib/librte_pmd_bond/rte_eth_bond_args.c > @@ -171,6 +171,7 @@ bond_ethdev_parse_slave_mode_kvarg(const char > *key __rte_unused, > case BONDING_MODE_ACTIVE_BACKUP: > case BONDING_MODE_BALANCE: > case BONDING_MODE_BROADCAST: > + case BONDING_MODE_8023AD: > return 0; > default: > RTE_BOND_LOG(ERR, "Invalid slave mode value (%s) > specified", value); > diff --git a/lib/librte_pmd_bond/rte_eth_bond_pmd.c > b/lib/librte_pmd_bond/rte_eth_bond_pmd.c > index 6d0fb1b..13630d9 100644 > --- a/lib/librte_pmd_bond/rte_eth_bond_pmd.c > +++ b/lib/librte_pmd_bond/rte_eth_bond_pmd.c > @@ -44,6 +44,7 @@ >=20 > #include "rte_eth_bond.h" > #include "rte_eth_bond_private.h" > +#include "rte_eth_bond_8023ad.h" >=20 > static uint16_t > bond_ethdev_rx_burst(void *queue, struct rte_mbuf **bufs, uint16_t > nb_pkts) > @@ -168,6 +169,56 @@ bond_ethdev_tx_burst_active_backup(void *queue, > bufs, nb_pkts); > } >=20 > +static uint16_t > +bond_ethdev_rx_burst_8023ad(void *queue, struct rte_mbuf **bufs, > + uint16_t nb_pkts) > +{ > + /* Cast to structure, containing bonded device's port id and queue id > */ > + struct bond_rx_queue *bd_rx_q =3D (struct bond_rx_queue *)queue; > + struct bond_dev_private *internals =3D bd_rx_q->dev_private; > + struct mode8023ad_data *mode4 =3D &internals->mode4; > + struct ether_addr bond_mac; > + > + struct ether_hdr *hdr; > + struct rte_mbuf *pkts[nb_pkts + 1]; /* one packet more for slow > packet */ > + > + uint16_t num_rx_slave =3D 0; /* Number of packet received on > current slave */ > + uint16_t num_rx_total =3D 0; /* Total number of received packets > */ > + > + uint8_t i, j; > + > + rte_eth_macaddr_get(internals->port_id, &bond_mac); > + > + for (i =3D 0; i < internals->active_slave_count && num_rx_total < > nb_pkts; i++) { > + /* Read packets from this slave */ > + num_rx_slave =3D rte_eth_rx_burst(internals->active_slaves[i], > + bd_rx_q->queue_id, pkts, nb_pkts + 1 - > num_rx_total); > + > + /* Separate slow protocol packets from other packets */ > + for (j =3D 0; j < num_rx_slave; j++) { > + hdr =3D rte_pktmbuf_mtod(pkts[j], struct ether_hdr *); > + > + uint16_t ether_type =3D rte_be_to_cpu_16(hdr- > >ether_type); > + if (unlikely(ether_type =3D=3D ETHER_TYPE_SLOW)) { > + > bond_mode_8023ad_handle_slow_pkt(internals, i, pkts[j]); > + continue; > + } > + > + /* Check if we can receive this packet. Also filter > packets if > + * bonding interface is not in promiscuous mode > (slaves are always > + * in promiscuous mode). */ > + if (likely(ACTOR_STATE(&mode4->port_list[i], > COLLECTING)) && > + likely(internals->promiscuous_en || > + is_same_ether_addr(&bond_mac, > &hdr->d_addr))) { > + bufs[num_rx_total++] =3D pkts[j]; > + } else > + rte_pktmbuf_free(pkts[j]); > + } > + } > + > + return num_rx_total; > +} > + > static inline uint16_t > ether_hash(struct ether_hdr *eth_hdr) > { > @@ -350,6 +401,126 @@ bond_ethdev_tx_burst_balance(void *queue, > struct rte_mbuf **bufs, > } >=20 > static uint16_t > +bond_ethdev_tx_burst_8023ad(void *queue, struct rte_mbuf **bufs, > + uint16_t nb_pkts) > +{ > + struct bond_dev_private *internals; > + struct mode8023ad_data *mode4; > + struct bond_tx_queue *bd_tx_q; > + > + uint8_t num_of_slaves; > + uint8_t slaves[RTE_MAX_ETHPORTS]; > + /* possitions in slaves, not ID */ > + uint8_t distributing_offsets[RTE_MAX_ETHPORTS]; > + uint8_t distributing_slaves_count; > + > + uint16_t num_tx_slave, num_tx_total =3D 0, tx_fail_total =3D 0; > + uint16_t i, op_slave_idx; > + > + /* Slow packets from 802.3AX state machines. */ > + struct slow_protocol_msg *slow_msg; > + > + /* Allocate one additional packet in case 8023AD mode. > + * First element if not NULL is slow packet. */ > + struct rte_mbuf *slave_bufs[RTE_MAX_ETHPORTS][nb_pkts + 1]; > + /* Total amount of packets in slave_bufs */ > + uint16_t slave_nb_pkts[RTE_MAX_ETHPORTS] =3D { 0 }; > + /* Array of slow packets placed in each slave */ > + uint8_t slave_slow_packets[RTE_MAX_ETHPORTS] =3D { 0 }; > + > + bd_tx_q =3D (struct bond_tx_queue *)queue; > + internals =3D bd_tx_q->dev_private; > + mode4 =3D &internals->mode4; > + > + /* Copy slave list to protect against slave up/down changes during tx > + * bursting */ > + num_of_slaves =3D internals->active_slave_count; > + if (num_of_slaves < 1) > + return num_tx_total; > + > + memcpy(slaves, internals->active_slaves, sizeof(slaves[0]) * > num_of_slaves); > + > + distributing_slaves_count =3D mode4->distibuting_slaves_count; > + memcpy(distributing_offsets, mode4->distibuting_slaves_offsets, > + sizeof(slaves[0]) * distributing_slaves_count); > + > + for (i =3D 0; i < num_of_slaves; i++) > + slave_bufs[i][0] =3D NULL; > + > + /* It is likely that tx ring will be empty. If it is not empty, it is > + * likely that there will be only one frame. */ > + while (unlikely(!rte_ring_empty(mode4->tx_ring)) && > + rte_ring_dequeue(mode4->tx_ring, (void > **)&slow_msg) !=3D -ENOENT) { > + i =3D find_slave_by_id(slaves, num_of_slaves, slow_msg- > >port_id); > + > + /* Assign slow packet to slave or drop it if slave is not in > active list > + * (ex: link down). */ > + if (likely(i < num_of_slaves)) { > + /* If there is more than one slow packet to the same > slave, send > + * only latest, and drop previouse - tx burst was no > called quick > + * enough. */ > + if (slave_bufs[i][0] !=3D NULL) > + rte_pktmbuf_free(slave_bufs[i][0]); > + > + slave_bufs[i][0] =3D slow_msg->pkt; > + slave_nb_pkts[i] =3D 1; > + slave_slow_packets[i] =3D 1; > + } else > + rte_pktmbuf_free(slow_msg->pkt); > + > + rte_ring_enqueue(mode4->free_ring, slow_msg); > + } > + > + if (likely(distributing_slaves_count > 0)) { > + /* Populate slaves mbuf with the packets which are to be > sent on it */ > + for (i =3D 0; i < nb_pkts; i++) { > + /* Select output slave using hash based on xmit > policy */ > + op_slave_idx =3D xmit_slave_hash(bufs[i], > distributing_slaves_count, > + internals->balance_xmit_policy); > + > + /* Populate slave mbuf arrays with mbufs for that > slave. Use only > + * slaves that are currently distributing. */ > + uint8_t slave_offset =3D > distributing_offsets[op_slave_idx]; > + uint16_t pkt_pos =3D slave_nb_pkts[slave_offset]; > + slave_nb_pkts[slave_offset]++; > + > + slave_bufs[slave_offset][pkt_pos] =3D bufs[i]; > + } > + } > + > + /* Send packet burst on each slave device */ > + for (i =3D 0; i < num_of_slaves; i++) { > + if (slave_nb_pkts[i] > 0) { > + num_tx_slave =3D rte_eth_tx_burst(slaves[i], bd_tx_q- > >queue_id, > + slave_bufs[i], slave_nb_pkts[i]); > + > + /* if tx burst fails move packets to end of bufs */ > + if (unlikely(num_tx_slave < slave_nb_pkts[i])) { > + uint16_t slave_tx_fail_count =3D > slave_nb_pkts[i] - num_tx_slave; > + > + /* Free slow packet if it exists and not send. > */ > + if (slave_slow_packets[i] !=3D 0 && > num_tx_slave =3D=3D 0) { > + rte_pktmbuf_free(slave_bufs[i][0]); > + slave_tx_fail_count--; > + } > + > + tx_fail_total +=3D slave_tx_fail_count; > + memcpy(bufs[nb_pkts - tx_fail_total], > + slave_bufs[i][num_tx_slave], > + slave_tx_fail_count); > + } > + > + if (num_tx_slave > 0) > + num_tx_slave -=3D slave_slow_packets[i]; > + > + num_tx_total +=3D num_tx_slave; > + } > + } > + > + return num_tx_total; > +} > + > +static uint16_t > bond_ethdev_tx_burst_broadcast(void *queue, struct rte_mbuf **bufs, > uint16_t nb_pkts) > { > @@ -448,6 +619,27 @@ link_properties_valid(struct rte_eth_link > *bonded_dev_link, > } >=20 > int > +mac_address_get(struct rte_eth_dev *eth_dev, struct ether_addr > *dst_mac_addr) > +{ > + struct ether_addr *mac_addr; > + > + mac_addr =3D eth_dev->data->mac_addrs; > + > + if (eth_dev =3D=3D NULL) { > + RTE_LOG(ERR, PMD, "%s: NULL pointer eth_dev specified\n", > __func__); > + return -1; > + } > + > + if (dst_mac_addr =3D=3D NULL) { > + RTE_LOG(ERR, PMD, "%s: NULL pointer MAC specified\n", > __func__); > + return -1; > + } > + > + ether_addr_copy(mac_addr, dst_mac_addr); > + return 0; > +} > + > +int > mac_address_set(struct rte_eth_dev *eth_dev, struct ether_addr > *new_mac_addr) > { > struct ether_addr *mac_addr; > @@ -455,7 +647,7 @@ mac_address_set(struct rte_eth_dev *eth_dev, struct > ether_addr *new_mac_addr) > mac_addr =3D eth_dev->data->mac_addrs; >=20 > if (eth_dev =3D=3D NULL) { > - RTE_BOND_LOG(ERR, "NULL pointer eth_dev specified"); > + RTE_BOND_LOG(ERR, "NULL pointer eth_dev specified"); > return -1; > } >=20 > @@ -494,6 +686,8 @@ mac_address_slaves_update(struct rte_eth_dev > *bonded_eth_dev) > } > } > break; > + case BONDING_MODE_8023AD: > + break; > case BONDING_MODE_ACTIVE_BACKUP: > default: > for (i =3D 0; i < internals->slave_count; i++) { > @@ -544,6 +738,13 @@ bond_ethdev_mode_set(struct rte_eth_dev > *eth_dev, int mode) > eth_dev->tx_pkt_burst =3D bond_ethdev_tx_burst_broadcast; > eth_dev->rx_pkt_burst =3D bond_ethdev_rx_burst; > break; > + case BONDING_MODE_8023AD: > + if (bond_mode_8023ad_init(eth_dev) !=3D 0) > + return -1; > + > + eth_dev->rx_pkt_burst =3D bond_ethdev_rx_burst_8023ad; > + eth_dev->tx_pkt_burst =3D bond_ethdev_tx_burst_8023ad; > + break; > default: > return -1; > } > @@ -751,6 +952,8 @@ bond_ethdev_start(struct rte_eth_dev *eth_dev) > if (internals->user_defined_primary_port) > bond_ethdev_primary_set(internals, internals- > >primary_port); >=20 > + if (internals->mode =3D=3D BONDING_MODE_8023AD) > + bond_mode_8023ad_start(eth_dev); >=20 > if (internals->link_status_polling_enabled) > rte_eal_alarm_set(internals->link_status_polling_interval_ms > * 1000, > @@ -765,6 +968,25 @@ bond_ethdev_stop(struct rte_eth_dev *eth_dev) > { > struct bond_dev_private *internals =3D eth_dev->data->dev_private; >=20 > + if (internals->mode =3D=3D BONDING_MODE_8023AD) { > + struct mode8023ad_data *data =3D &internals->mode4; > + struct slow_protocol_msg *msg; > + > + bond_mode_8023ad_stop(eth_dev); > + data->distibuting_slaves_count =3D 0; > + > + /* Discard all messages to/from mode 4 state machines */ > + while (rte_ring_dequeue(data->rx_ring, (void **)&msg) !=3D - > ENOENT) { > + rte_pktmbuf_free(msg->pkt); > + rte_ring_enqueue(data->free_ring, msg); > + } > + > + while (rte_ring_dequeue(data->tx_ring, (void **)&msg) !=3D - > ENOENT) { > + rte_pktmbuf_free(msg->pkt); > + rte_ring_enqueue(data->free_ring, msg); > + } > + } > + > internals->active_slave_count =3D 0; > internals->link_status_polling_enabled =3D 0; >=20 > @@ -832,7 +1054,7 @@ bond_ethdev_tx_queue_setup(struct rte_eth_dev > *dev, uint16_t tx_queue_id, > 0, dev->pci_dev->numa_node); >=20 > if (bd_tx_q =3D=3D NULL) > - return -1; > + return -1; >=20 > bd_tx_q->queue_id =3D tx_queue_id; > bd_tx_q->dev_private =3D dev->data->dev_private; > @@ -863,7 +1085,6 @@ bond_ethdev_tx_queue_release(void *queue) > rte_free(queue); > } >=20 > - > static void > bond_ethdev_slave_link_status_change_monitor(void *cb_arg) > { > @@ -884,7 +1105,7 @@ > bond_ethdev_slave_link_status_change_monitor(void *cb_arg) >=20 > /* If device is currently being configured then don't check slaves link > * status, wait until next period */ > - if (rte_spinlock_trylock(&internals->lock)){ > + if (rte_spinlock_trylock(&internals->lock)) { > for (i =3D 0; i < internals->slave_count; i++) { > if (internals->slaves[i].link_status_polling_enabled) { > slave_ethdev =3D &rte_eth_devices[internals- > >slaves[i].port_id]; > @@ -1002,11 +1223,13 @@ bond_ethdev_promiscuous_enable(struct > rte_eth_dev *eth_dev) > for (i =3D 0; i < internals->slave_count; i++) > rte_eth_promiscuous_enable(internals- > >slaves[i].port_id); > break; > + /* In mode4 promiscus mode is managed when slave is > added/removed */ > + case BONDING_MODE_8023AD: > + break; > /* Promiscuous mode is propagated only to primary slave */ > case BONDING_MODE_ACTIVE_BACKUP: > default: > rte_eth_promiscuous_enable(internals- > >current_primary_port); > - > } > } >=20 > @@ -1017,7 +1240,7 @@ bond_ethdev_promiscuous_disable(struct > rte_eth_dev *dev) > int i; >=20 > internals->promiscuous_en =3D 0; > - > + > switch (internals->mode) { > /* Promiscuous mode is propagated to all slaves */ > case BONDING_MODE_ROUND_ROBIN: > @@ -1026,6 +1249,9 @@ bond_ethdev_promiscuous_disable(struct > rte_eth_dev *dev) > for (i =3D 0; i < internals->slave_count; i++) > rte_eth_promiscuous_disable(internals- > >slaves[i].port_id); > break; > + /* In mode4 promiscus mode is set managed when slave is > added/removed */ > + case BONDING_MODE_8023AD: > + break; > /* Promiscuous mode is propagated only to primary slave */ > case BONDING_MODE_ACTIVE_BACKUP: > default: > @@ -1051,7 +1277,8 @@ bond_ethdev_lsc_event_callback(uint8_t port_id, > enum rte_eth_event_type type, > struct bond_dev_private *internals; > struct rte_eth_link link; >=20 > - int i, valid_slave =3D 0, active_pos =3D -1; > + int i, valid_slave =3D 0; > + uint8_t active_pos; > uint8_t lsc_flag =3D 0; >=20 > if (type !=3D RTE_ETH_EVENT_INTR_LSC || param =3D=3D NULL) > @@ -1081,16 +1308,12 @@ bond_ethdev_lsc_event_callback(uint8_t > port_id, enum rte_eth_event_type type, > return; >=20 > /* Search for port in active port list */ > - for (i =3D 0; i < internals->active_slave_count; i++) { > - if (port_id =3D=3D internals->active_slaves[i]) { > - active_pos =3D i; > - break; > - } > - } > + active_pos =3D find_slave_by_id(internals->active_slaves, > + internals->active_slave_count, port_id); >=20 > rte_eth_link_get_nowait(port_id, &link); > if (link.link_status) { > - if (active_pos >=3D 0) > + if (active_pos < internals->active_slave_count) > return; >=20 > /* if no active slave ports then set this port to be primary > port */ > @@ -1104,21 +1327,19 @@ bond_ethdev_lsc_event_callback(uint8_t > port_id, enum rte_eth_event_type type, > link_properties_set(bonded_eth_dev, > &(slave_eth_dev->data->dev_link)); > } > - internals->active_slaves[internals->active_slave_count++] =3D > port_id; > + > + activate_slave(bonded_eth_dev, port_id); >=20 > /* If user has defined the primary port then default to using > it */ > if (internals->user_defined_primary_port && > internals->primary_port =3D=3D port_id) > bond_ethdev_primary_set(internals, port_id); > } else { > - if (active_pos < 0) > + if (active_pos =3D=3D internals->active_slave_count) > return; >=20 > /* Remove from active slave list */ > - for (i =3D active_pos; i < (internals->active_slave_count - 1); i++) > - internals->active_slaves[i] =3D internals- > >active_slaves[i+1]; > - > - internals->active_slave_count--; > + deactivate_slave(bonded_eth_dev, active_pos); >=20 > /* No active slaves, change link status to down and reset > other > * link properties */ > diff --git a/lib/librte_pmd_bond/rte_eth_bond_private.h > b/lib/librte_pmd_bond/rte_eth_bond_private.h > index 6db5144..77f7bb0 100644 > --- a/lib/librte_pmd_bond/rte_eth_bond_private.h > +++ b/lib/librte_pmd_bond/rte_eth_bond_private.h > @@ -42,6 +42,7 @@ extern "C" { > #include >=20 > #include "rte_eth_bond.h" > +#include "rte_eth_bond_8023ad.h" >=20 > #define PMD_BOND_SLAVE_PORT_KVARG ("slave") > #define PMD_BOND_PRIMARY_SLAVE_KVARG ("primary") > @@ -60,6 +61,8 @@ extern "C" { > #define RTE_BOND_LOG(lvl, msg, ...) \ > RTE_LOG(lvl, PMD, "%s(%d) - " msg "\n", __func__, __LINE__, > ##__VA_ARGS__); >=20 > +#define BONDING_MODE_INVALID 0xFF > + > extern const char *pmd_bond_init_valid_arguments[]; >=20 > extern const char *driver_name; > @@ -89,7 +92,13 @@ struct bond_tx_queue { > /**< Copy of TX configuration structure for queue */ > }; >=20 > - > +/** Persisted Slave Configuration Structure */ > +struct slave_conf { > + uint8_t port_id; > + /**< Port Id of slave eth_dev */ > + struct ether_addr mac_addr; > + /**< Slave eth_dev original MAC address */ > +}; > /** Bonded slave devices structure */ > struct bond_ethdev_slave_ports { > uint8_t slaves[RTE_MAX_ETHPORTS]; /**< Slave port id array */ > @@ -124,7 +133,7 @@ struct bond_dev_private { > uint8_t user_defined_mac; > /**< Flag for whether MAC address is user defined or not */ > uint8_t promiscuous_en; > - /**< Enabled/disable promiscuous mode on slave devices */ > + /**< Enabled/disable promiscuous mode on bonding device */ > uint8_t link_props_set; > /**< flag to denote if the link properties are set */ >=20 > @@ -143,6 +152,9 @@ struct bond_dev_private { > uint8_t slave_count; /**< Number of bonded > slaves */ > struct bond_slave_details slaves[RTE_MAX_ETHPORTS]; > /**< Arary of bonded slaves details */ > + > + struct mode8023ad_data mode4; > + /**< Mode 4 private data */ > }; >=20 > extern struct eth_dev_ops default_dev_ops; > @@ -150,6 +162,21 @@ extern struct eth_dev_ops default_dev_ops; > int > valid_bonded_ethdev(struct rte_eth_dev *eth_dev); >=20 > +/* Search given slave array to find possition of given id. > + * Return slave pos or slaves_count if not found. */ > +static inline uint8_t > +find_slave_by_id(uint8_t *slaves, uint8_t slaves_count, > + uint8_t slave_id ) { > + > + uint8_t pos; > + for (pos =3D 0; pos < slaves_count; pos++) { > + if (slave_id =3D=3D slaves[pos]) > + break; > + } > + > + return pos; > +} > + > int > valid_port_id(uint8_t port_id); >=20 > @@ -160,6 +187,14 @@ int > valid_slave_port_id(uint8_t port_id); >=20 > void > +deactivate_slave(struct rte_eth_dev *eth_dev, > + uint8_t slave_pos ); > + > +void > +activate_slave(struct rte_eth_dev *eth_dev, > + uint8_t port_id ); > + > +void > link_properties_set(struct rte_eth_dev *bonded_eth_dev, > struct rte_eth_link *slave_dev_link); > void > @@ -173,6 +208,9 @@ int > mac_address_set(struct rte_eth_dev *eth_dev, struct ether_addr > *new_mac_addr); >=20 > int > +mac_address_get(struct rte_eth_dev *eth_dev, struct ether_addr > *dst_mac_addr); > + > +int > mac_address_slaves_update(struct rte_eth_dev *bonded_eth_dev); >=20 > uint8_t > -- > 1.7.9.5