+ lacp_unlock();
+}
+
+/* Extract a snapshot of the current state and counters for a slave port.
+ Return false if the slave is not active. */
+bool
+lacp_get_slave_stats(const struct lacp *lacp, const void *slave_, struct lacp_slave_stats *stats)
+ OVS_EXCLUDED(mutex)
+{
+ struct slave *slave;
+ struct lacp_info actor;
+ bool ret;
+
+ ovs_mutex_lock(&mutex);
+
+ slave = slave_lookup(lacp, slave_);
+ if (slave) {
+ ret = true;
+ slave_get_actor(slave, &actor);
+ stats->dot3adAggPortActorSystemID = actor.sys_id;
+ stats->dot3adAggPortPartnerOperSystemID = slave->partner.sys_id;
+ stats->dot3adAggPortAttachedAggID = (lacp->key_slave->key ?
+ lacp->key_slave->key :
+ lacp->key_slave->port_id);
+
+ /* Construct my admin-state. Assume aggregation is configured on. */
+ stats->dot3adAggPortActorAdminState = LACP_STATE_AGG;
+ if (lacp->active) {
+ stats->dot3adAggPortActorAdminState |= LACP_STATE_ACT;
+ }
+ if (lacp->fast) {
+ stats->dot3adAggPortActorAdminState |= LACP_STATE_TIME;
+ }
+ /* XXX Not sure how to know the partner admin state. It
+ * might have to be captured and remembered during the
+ * negotiation phase.
+ */
+ stats->dot3adAggPortPartnerAdminState = 0;
+
+ stats->dot3adAggPortActorOperState = actor.state;
+ stats->dot3adAggPortPartnerOperState = slave->partner.state;
+
+ /* Read out the latest counters */
+ stats->dot3adAggPortStatsLACPDUsRx = slave->count_rx_pdus;
+ stats->dot3adAggPortStatsIllegalRx = slave->count_rx_pdus_bad;
+ stats->dot3adAggPortStatsLACPDUsTx = slave->count_tx_pdus;
+ } else {
+ ret = false;
+ }