From 04dd17822334871b23ea2862f7798fb0e0007777 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Sat, 11 May 2024 08:53:19 +0000 Subject: [PATCH] change otg to host mode --- kernel/drivers/net/bonding/bond_3ad.c | 609 ++++++++++++++++++++++++++++++------------------------ 1 files changed, 339 insertions(+), 270 deletions(-) diff --git a/kernel/drivers/net/bonding/bond_3ad.c b/kernel/drivers/net/bonding/bond_3ad.c index e3f814e..320e546 100644 --- a/kernel/drivers/net/bonding/bond_3ad.c +++ b/kernel/drivers/net/bonding/bond_3ad.c @@ -1,23 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * */ #include <linux/skbuff.h> @@ -31,6 +14,7 @@ #include <net/net_namespace.h> #include <net/bonding.h> #include <net/bond_3ad.h> +#include <net/netlink.h> /* General definitions */ #define AD_SHORT_TIMEOUT 1 @@ -46,16 +30,6 @@ #define AD_LONG_TIMEOUT_TIME (3*AD_SLOW_PERIODIC_TIME) #define AD_CHURN_DETECTION_TIME 60 #define AD_AGGREGATE_WAIT_TIME 2 - -/* Port state definitions (43.4.2.2 in the 802.3ad standard) */ -#define AD_STATE_LACP_ACTIVITY 0x1 -#define AD_STATE_LACP_TIMEOUT 0x2 -#define AD_STATE_AGGREGATION 0x4 -#define AD_STATE_SYNCHRONIZATION 0x8 -#define AD_STATE_COLLECTING 0x10 -#define AD_STATE_DISTRIBUTING 0x20 -#define AD_STATE_DEFAULTED 0x40 -#define AD_STATE_EXPIRED 0x80 /* Port Variables definitions used by the State Machines (43.4.7 in the * 802.3ad standard) @@ -111,8 +85,9 @@ static u16 ad_ticks_per_sec; static const int ad_delta_in_ticks = (AD_TIMER_INTERVAL * HZ) / 1000; -static const u8 lacpdu_mcast_addr[ETH_ALEN + 2] __long_aligned = - MULTICAST_LACPDU_ADDR; +const u8 lacpdu_mcast_addr[ETH_ALEN + 2] __long_aligned = { + 0x01, 0x80, 0xC2, 0x00, 0x00, 0x02 +}; /* ================= main 802.3ad protocol functions ================== */ static int ad_lacpdu_send(struct port *port); @@ -156,7 +131,7 @@ /** * __get_first_agg - get the first aggregator in the bond - * @bond: the bond we're looking at + * @port: the port we're looking at * * Return the aggregator of the first slave in @bond, or %NULL if it can't be * found. @@ -341,17 +316,17 @@ default: /* unknown speed value from ethtool. shouldn't happen */ if (slave->speed != SPEED_UNKNOWN) - pr_warn_once("%s: unknown ethtool speed (%d) for port %d (set it to 0)\n", + pr_warn_once("%s: (slave %s): unknown ethtool speed (%d) for port %d (set it to 0)\n", slave->bond->dev->name, - slave->speed, + slave->dev->name, slave->speed, port->actor_port_number); speed = 0; break; } } - netdev_dbg(slave->bond->dev, "Port %d Received link speed %d update from adapter\n", - port->actor_port_number, speed); + slave_dbg(slave->bond->dev, slave->dev, "Port %d Received link speed %d update from adapter\n", + port->actor_port_number, speed); return speed; } @@ -375,14 +350,14 @@ switch (slave->duplex) { case DUPLEX_FULL: retval = 0x1; - netdev_dbg(slave->bond->dev, "Port %d Received status full duplex update from adapter\n", - port->actor_port_number); + slave_dbg(slave->bond->dev, slave->dev, "Port %d Received status full duplex update from adapter\n", + port->actor_port_number); break; case DUPLEX_HALF: default: retval = 0x0; - netdev_dbg(slave->bond->dev, "Port %d Received status NOT full duplex update from adapter\n", - port->actor_port_number); + slave_dbg(slave->bond->dev, slave->dev, "Port %d Received status NOT full duplex update from adapter\n", + port->actor_port_number); break; } } @@ -473,8 +448,8 @@ MAC_ADDRESS_EQUAL(&(lacpdu->partner_system), &(port->actor_system)) && (ntohs(lacpdu->partner_system_priority) == port->actor_system_priority) && (ntohs(lacpdu->partner_key) == port->actor_oper_port_key) && - ((lacpdu->partner_state & AD_STATE_AGGREGATION) == (port->actor_oper_port_state & AD_STATE_AGGREGATION))) || - ((lacpdu->actor_state & AD_STATE_AGGREGATION) == 0) + ((lacpdu->partner_state & LACP_STATE_AGGREGATION) == (port->actor_oper_port_state & LACP_STATE_AGGREGATION))) || + ((lacpdu->actor_state & LACP_STATE_AGGREGATION) == 0) ) { port->sm_vars |= AD_PORT_MATCHED; } else { @@ -508,18 +483,20 @@ partner->port_state = lacpdu->actor_state; /* set actor_oper_port_state.defaulted to FALSE */ - port->actor_oper_port_state &= ~AD_STATE_DEFAULTED; + port->actor_oper_port_state &= ~LACP_STATE_DEFAULTED; /* set the partner sync. to on if the partner is sync, * and the port is matched */ if ((port->sm_vars & AD_PORT_MATCHED) && - (lacpdu->actor_state & AD_STATE_SYNCHRONIZATION)) { - partner->port_state |= AD_STATE_SYNCHRONIZATION; - pr_debug("%s partner sync=1\n", port->slave->dev->name); + (lacpdu->actor_state & LACP_STATE_SYNCHRONIZATION)) { + partner->port_state |= LACP_STATE_SYNCHRONIZATION; + slave_dbg(port->slave->bond->dev, port->slave->dev, + "partner sync=1\n"); } else { - partner->port_state &= ~AD_STATE_SYNCHRONIZATION; - pr_debug("%s partner sync=0\n", port->slave->dev->name); + partner->port_state &= ~LACP_STATE_SYNCHRONIZATION; + slave_dbg(port->slave->bond->dev, port->slave->dev, + "partner sync=0\n"); } } } @@ -540,7 +517,7 @@ sizeof(struct port_params)); /* set actor_oper_port_state.defaulted to true */ - port->actor_oper_port_state |= AD_STATE_DEFAULTED; + port->actor_oper_port_state |= LACP_STATE_DEFAULTED; } } @@ -570,7 +547,7 @@ !MAC_ADDRESS_EQUAL(&lacpdu->actor_system, &partner->system) || ntohs(lacpdu->actor_system_priority) != partner->system_priority || ntohs(lacpdu->actor_key) != partner->key || - (lacpdu->actor_state & AD_STATE_AGGREGATION) != (partner->port_state & AD_STATE_AGGREGATION)) { + (lacpdu->actor_state & LACP_STATE_AGGREGATION) != (partner->port_state & LACP_STATE_AGGREGATION)) { port->sm_vars &= ~AD_PORT_SELECTED; } } @@ -602,8 +579,8 @@ !MAC_ADDRESS_EQUAL(&admin->system, &oper->system) || admin->system_priority != oper->system_priority || admin->key != oper->key || - (admin->port_state & AD_STATE_AGGREGATION) - != (oper->port_state & AD_STATE_AGGREGATION)) { + (admin->port_state & LACP_STATE_AGGREGATION) + != (oper->port_state & LACP_STATE_AGGREGATION)) { port->sm_vars &= ~AD_PORT_SELECTED; } } @@ -633,10 +610,10 @@ !MAC_ADDRESS_EQUAL(&(lacpdu->partner_system), &(port->actor_system)) || (ntohs(lacpdu->partner_system_priority) != port->actor_system_priority) || (ntohs(lacpdu->partner_key) != port->actor_oper_port_key) || - ((lacpdu->partner_state & AD_STATE_LACP_ACTIVITY) != (port->actor_oper_port_state & AD_STATE_LACP_ACTIVITY)) || - ((lacpdu->partner_state & AD_STATE_LACP_TIMEOUT) != (port->actor_oper_port_state & AD_STATE_LACP_TIMEOUT)) || - ((lacpdu->partner_state & AD_STATE_SYNCHRONIZATION) != (port->actor_oper_port_state & AD_STATE_SYNCHRONIZATION)) || - ((lacpdu->partner_state & AD_STATE_AGGREGATION) != (port->actor_oper_port_state & AD_STATE_AGGREGATION)) + ((lacpdu->partner_state & LACP_STATE_LACP_ACTIVITY) != (port->actor_oper_port_state & LACP_STATE_LACP_ACTIVITY)) || + ((lacpdu->partner_state & LACP_STATE_LACP_TIMEOUT) != (port->actor_oper_port_state & LACP_STATE_LACP_TIMEOUT)) || + ((lacpdu->partner_state & LACP_STATE_SYNCHRONIZATION) != (port->actor_oper_port_state & LACP_STATE_SYNCHRONIZATION)) || + ((lacpdu->partner_state & LACP_STATE_AGGREGATION) != (port->actor_oper_port_state & LACP_STATE_AGGREGATION)) ) { port->ntt = true; } @@ -805,8 +782,9 @@ lacpdu->actor_port_priority = htons(port->actor_port_priority); lacpdu->actor_port = htons(port->actor_port_number); lacpdu->actor_state = port->actor_oper_port_state; - pr_debug("update lacpdu: %s, actor port state %x\n", - port->slave->dev->name, port->actor_oper_port_state); + slave_dbg(port->slave->bond->dev, port->slave->dev, + "update lacpdu: actor port state %x\n", + port->actor_oper_port_state); /* lacpdu->reserved_3_1 initialized * lacpdu->tlv_type_partner_info initialized @@ -851,6 +829,9 @@ if (!skb) return -ENOMEM; + atomic64_inc(&SLAVE_AD_INFO(slave)->stats.lacpdu_tx); + atomic64_inc(&BOND_AD_INFO(slave->bond).stats.lacpdu_tx); + skb->dev = slave->dev; skb_reset_mac_header(skb); skb->network_header = skb->mac_header + ETH_HLEN; @@ -891,6 +872,17 @@ skb = dev_alloc_skb(length + 16); if (!skb) return -ENOMEM; + + switch (marker->tlv_type) { + case AD_MARKER_INFORMATION_SUBTYPE: + atomic64_inc(&SLAVE_AD_INFO(slave)->stats.marker_tx); + atomic64_inc(&BOND_AD_INFO(slave->bond).stats.marker_tx); + break; + case AD_MARKER_RESPONSE_SUBTYPE: + atomic64_inc(&SLAVE_AD_INFO(slave)->stats.marker_resp_tx); + atomic64_inc(&BOND_AD_INFO(slave->bond).stats.marker_resp_tx); + break; + } skb_reserve(skb, 16); @@ -977,7 +969,7 @@ * edable port will take place only after this timer) */ if ((port->sm_vars & AD_PORT_SELECTED) && - (port->partner_oper.port_state & AD_STATE_SYNCHRONIZATION) && + (port->partner_oper.port_state & LACP_STATE_SYNCHRONIZATION) && !__check_agg_selection_timer(port)) { if (port->aggregator->is_active) port->sm_mux_state = @@ -995,14 +987,14 @@ port->sm_mux_state = AD_MUX_DETACHED; } else if (port->aggregator->is_active) { port->actor_oper_port_state |= - AD_STATE_SYNCHRONIZATION; + LACP_STATE_SYNCHRONIZATION; } break; case AD_MUX_COLLECTING_DISTRIBUTING: if (!(port->sm_vars & AD_PORT_SELECTED) || (port->sm_vars & AD_PORT_STANDBY) || - !(port->partner_oper.port_state & AD_STATE_SYNCHRONIZATION) || - !(port->actor_oper_port_state & AD_STATE_SYNCHRONIZATION)) { + !(port->partner_oper.port_state & LACP_STATE_SYNCHRONIZATION) || + !(port->actor_oper_port_state & LACP_STATE_SYNCHRONIZATION)) { port->sm_mux_state = AD_MUX_ATTACHED; } else { /* if port state hasn't changed make @@ -1024,18 +1016,18 @@ /* check if the state machine was changed */ if (port->sm_mux_state != last_state) { - pr_debug("Mux Machine: Port=%d (%s), Last State=%d, Curr State=%d\n", - port->actor_port_number, - port->slave->dev->name, - last_state, - port->sm_mux_state); + slave_dbg(port->slave->bond->dev, port->slave->dev, + "Mux Machine: Port=%d, Last State=%d, Curr State=%d\n", + port->actor_port_number, + last_state, + port->sm_mux_state); switch (port->sm_mux_state) { case AD_MUX_DETACHED: - port->actor_oper_port_state &= ~AD_STATE_SYNCHRONIZATION; + port->actor_oper_port_state &= ~LACP_STATE_SYNCHRONIZATION; ad_disable_collecting_distributing(port, update_slave_arr); - port->actor_oper_port_state &= ~AD_STATE_COLLECTING; - port->actor_oper_port_state &= ~AD_STATE_DISTRIBUTING; + port->actor_oper_port_state &= ~LACP_STATE_COLLECTING; + port->actor_oper_port_state &= ~LACP_STATE_DISTRIBUTING; port->ntt = true; break; case AD_MUX_WAITING: @@ -1044,20 +1036,20 @@ case AD_MUX_ATTACHED: if (port->aggregator->is_active) port->actor_oper_port_state |= - AD_STATE_SYNCHRONIZATION; + LACP_STATE_SYNCHRONIZATION; else port->actor_oper_port_state &= - ~AD_STATE_SYNCHRONIZATION; - port->actor_oper_port_state &= ~AD_STATE_COLLECTING; - port->actor_oper_port_state &= ~AD_STATE_DISTRIBUTING; + ~LACP_STATE_SYNCHRONIZATION; + port->actor_oper_port_state &= ~LACP_STATE_COLLECTING; + port->actor_oper_port_state &= ~LACP_STATE_DISTRIBUTING; ad_disable_collecting_distributing(port, update_slave_arr); port->ntt = true; break; case AD_MUX_COLLECTING_DISTRIBUTING: - port->actor_oper_port_state |= AD_STATE_COLLECTING; - port->actor_oper_port_state |= AD_STATE_DISTRIBUTING; - port->actor_oper_port_state |= AD_STATE_SYNCHRONIZATION; + port->actor_oper_port_state |= LACP_STATE_COLLECTING; + port->actor_oper_port_state |= LACP_STATE_DISTRIBUTING; + port->actor_oper_port_state |= LACP_STATE_SYNCHRONIZATION; ad_enable_collecting_distributing(port, update_slave_arr); port->ntt = true; @@ -1086,6 +1078,10 @@ */ last_state = port->sm_rx_state; + if (lacpdu) { + atomic64_inc(&SLAVE_AD_INFO(port->slave)->stats.lacpdu_rx); + atomic64_inc(&BOND_AD_INFO(port->slave->bond).stats.lacpdu_rx); + } /* check if state machine should change state */ /* first, check if port was reinitialized */ @@ -1138,11 +1134,11 @@ /* check if the State machine was changed or new lacpdu arrived */ if ((port->sm_rx_state != last_state) || (lacpdu)) { - pr_debug("Rx Machine: Port=%d (%s), Last State=%d, Curr State=%d\n", - port->actor_port_number, - port->slave->dev->name, - last_state, - port->sm_rx_state); + slave_dbg(port->slave->bond->dev, port->slave->dev, + "Rx Machine: Port=%d, Last State=%d, Curr State=%d\n", + port->actor_port_number, + last_state, + port->sm_rx_state); switch (port->sm_rx_state) { case AD_RX_INITIALIZE: if (!(port->actor_oper_port_key & AD_DUPLEX_KEY_MASKS)) @@ -1151,19 +1147,19 @@ port->sm_vars |= AD_PORT_LACP_ENABLED; port->sm_vars &= ~AD_PORT_SELECTED; __record_default(port); - port->actor_oper_port_state &= ~AD_STATE_EXPIRED; + port->actor_oper_port_state &= ~LACP_STATE_EXPIRED; port->sm_rx_state = AD_RX_PORT_DISABLED; - /* Fall Through */ + fallthrough; case AD_RX_PORT_DISABLED: port->sm_vars &= ~AD_PORT_MATCHED; break; case AD_RX_LACP_DISABLED: port->sm_vars &= ~AD_PORT_SELECTED; __record_default(port); - port->partner_oper.port_state &= ~AD_STATE_AGGREGATION; + port->partner_oper.port_state &= ~LACP_STATE_AGGREGATION; port->sm_vars |= AD_PORT_MATCHED; - port->actor_oper_port_state &= ~AD_STATE_EXPIRED; + port->actor_oper_port_state &= ~LACP_STATE_EXPIRED; break; case AD_RX_EXPIRED: /* Reset of the Synchronization flag (Standard 43.4.12) @@ -1172,34 +1168,33 @@ * case of EXPIRED even if LINK_DOWN didn't arrive for * the port. */ - port->partner_oper.port_state &= ~AD_STATE_SYNCHRONIZATION; + port->partner_oper.port_state &= ~LACP_STATE_SYNCHRONIZATION; port->sm_vars &= ~AD_PORT_MATCHED; - port->partner_oper.port_state |= AD_STATE_LACP_TIMEOUT; - port->partner_oper.port_state |= AD_STATE_LACP_ACTIVITY; + port->partner_oper.port_state |= LACP_STATE_LACP_TIMEOUT; + port->partner_oper.port_state |= LACP_STATE_LACP_ACTIVITY; port->sm_rx_timer_counter = __ad_timer_to_ticks(AD_CURRENT_WHILE_TIMER, (u16)(AD_SHORT_TIMEOUT)); - port->actor_oper_port_state |= AD_STATE_EXPIRED; + port->actor_oper_port_state |= LACP_STATE_EXPIRED; port->sm_vars |= AD_PORT_CHURNED; break; case AD_RX_DEFAULTED: __update_default_selected(port); __record_default(port); port->sm_vars |= AD_PORT_MATCHED; - port->actor_oper_port_state &= ~AD_STATE_EXPIRED; + port->actor_oper_port_state &= ~LACP_STATE_EXPIRED; break; case AD_RX_CURRENT: /* detect loopback situation */ if (MAC_ADDRESS_EQUAL(&(lacpdu->actor_system), &(port->actor_system))) { - netdev_err(port->slave->bond->dev, "An illegal loopback occurred on adapter (%s)\n" - "Check the configuration to verify that all adapters are connected to 802.3ad compliant switch ports\n", - port->slave->dev->name); + slave_err(port->slave->bond->dev, port->slave->dev, "An illegal loopback occurred on slave\n" + "Check the configuration to verify that all adapters are connected to 802.3ad compliant switch ports\n"); return; } __update_selected(lacpdu, port); __update_ntt(lacpdu, port); __record_pdu(lacpdu, port); - port->sm_rx_timer_counter = __ad_timer_to_ticks(AD_CURRENT_WHILE_TIMER, (u16)(port->actor_oper_port_state & AD_STATE_LACP_TIMEOUT)); - port->actor_oper_port_state &= ~AD_STATE_EXPIRED; + port->sm_rx_timer_counter = __ad_timer_to_ticks(AD_CURRENT_WHILE_TIMER, (u16)(port->actor_oper_port_state & LACP_STATE_LACP_TIMEOUT)); + port->actor_oper_port_state &= ~LACP_STATE_EXPIRED; break; default: break; @@ -1220,14 +1215,14 @@ port->sm_churn_partner_state = AD_CHURN_MONITOR; port->sm_churn_actor_timer_counter = __ad_timer_to_ticks(AD_ACTOR_CHURN_TIMER, 0); - port->sm_churn_partner_timer_counter = + port->sm_churn_partner_timer_counter = __ad_timer_to_ticks(AD_PARTNER_CHURN_TIMER, 0); return; } if (port->sm_churn_actor_timer_counter && !(--port->sm_churn_actor_timer_counter) && port->sm_churn_actor_state == AD_CHURN_MONITOR) { - if (port->actor_oper_port_state & AD_STATE_SYNCHRONIZATION) { + if (port->actor_oper_port_state & LACP_STATE_SYNCHRONIZATION) { port->sm_churn_actor_state = AD_NO_CHURN; } else { port->churn_actor_count++; @@ -1237,7 +1232,7 @@ if (port->sm_churn_partner_timer_counter && !(--port->sm_churn_partner_timer_counter) && port->sm_churn_partner_state == AD_CHURN_MONITOR) { - if (port->partner_oper.port_state & AD_STATE_SYNCHRONIZATION) { + if (port->partner_oper.port_state & LACP_STATE_SYNCHRONIZATION) { port->sm_churn_partner_state = AD_NO_CHURN; } else { port->churn_partner_count++; @@ -1261,8 +1256,10 @@ __update_lacpdu_from_port(port); if (ad_lacpdu_send(port) >= 0) { - pr_debug("Sent LACPDU on port %d\n", - port->actor_port_number); + slave_dbg(port->slave->bond->dev, + port->slave->dev, + "Sent LACPDU on port %d\n", + port->actor_port_number); /* mark ntt as false, so it will not be sent * again until demanded @@ -1292,7 +1289,7 @@ /* check if port was reinitialized */ if (((port->sm_vars & AD_PORT_BEGIN) || !(port->sm_vars & AD_PORT_LACP_ENABLED) || !port->is_enabled) || - (!(port->actor_oper_port_state & AD_STATE_LACP_ACTIVITY) && !(port->partner_oper.port_state & AD_STATE_LACP_ACTIVITY)) + (!(port->actor_oper_port_state & LACP_STATE_LACP_ACTIVITY) && !(port->partner_oper.port_state & LACP_STATE_LACP_ACTIVITY)) ) { port->sm_periodic_state = AD_NO_PERIODIC; } @@ -1309,11 +1306,11 @@ switch (port->sm_periodic_state) { case AD_FAST_PERIODIC: if (!(port->partner_oper.port_state - & AD_STATE_LACP_TIMEOUT)) + & LACP_STATE_LACP_TIMEOUT)) port->sm_periodic_state = AD_SLOW_PERIODIC; break; case AD_SLOW_PERIODIC: - if ((port->partner_oper.port_state & AD_STATE_LACP_TIMEOUT)) { + if ((port->partner_oper.port_state & LACP_STATE_LACP_TIMEOUT)) { port->sm_periodic_timer_counter = 0; port->sm_periodic_state = AD_PERIODIC_TX; } @@ -1329,7 +1326,7 @@ break; case AD_PERIODIC_TX: if (!(port->partner_oper.port_state & - AD_STATE_LACP_TIMEOUT)) + LACP_STATE_LACP_TIMEOUT)) port->sm_periodic_state = AD_SLOW_PERIODIC; else port->sm_periodic_state = AD_FAST_PERIODIC; @@ -1341,9 +1338,10 @@ /* check if the state machine was changed */ if (port->sm_periodic_state != last_state) { - pr_debug("Periodic Machine: Port=%d, Last State=%d, Curr State=%d\n", - port->actor_port_number, last_state, - port->sm_periodic_state); + slave_dbg(port->slave->bond->dev, port->slave->dev, + "Periodic Machine: Port=%d, Last State=%d, Curr State=%d\n", + port->actor_port_number, last_state, + port->sm_periodic_state); switch (port->sm_periodic_state) { case AD_NO_PERIODIC: port->sm_periodic_timer_counter = 0; @@ -1419,9 +1417,9 @@ port->next_port_in_aggregator = NULL; port->actor_port_aggregator_identifier = 0; - netdev_dbg(bond->dev, "Port %d left LAG %d\n", - port->actor_port_number, - temp_aggregator->aggregator_identifier); + slave_dbg(bond->dev, port->slave->dev, "Port %d left LAG %d\n", + port->actor_port_number, + temp_aggregator->aggregator_identifier); /* if the aggregator is empty, clear its * parameters, and set it ready to be attached */ @@ -1434,10 +1432,10 @@ /* meaning: the port was related to an aggregator * but was not on the aggregator port list */ - net_warn_ratelimited("%s: Warning: Port %d (on %s) was related to aggregator %d but was not on its port list\n", + net_warn_ratelimited("%s: (slave %s): Warning: Port %d was related to aggregator %d but was not on its port list\n", port->slave->bond->dev->name, - port->actor_port_number, port->slave->dev->name, + port->actor_port_number, port->aggregator->aggregator_identifier); } } @@ -1468,9 +1466,9 @@ port->next_port_in_aggregator = aggregator->lag_ports; port->aggregator->num_of_ports++; aggregator->lag_ports = port; - netdev_dbg(bond->dev, "Port %d joined LAG %d(existing LAG)\n", - port->actor_port_number, - port->aggregator->aggregator_identifier); + slave_dbg(bond->dev, slave->dev, "Port %d joined LAG %d (existing LAG)\n", + port->actor_port_number, + port->aggregator->aggregator_identifier); /* mark this port as selected */ port->sm_vars |= AD_PORT_SELECTED; @@ -1515,12 +1513,14 @@ /* mark this port as selected */ port->sm_vars |= AD_PORT_SELECTED; - netdev_dbg(bond->dev, "Port %d joined LAG %d(new LAG)\n", - port->actor_port_number, - port->aggregator->aggregator_identifier); + slave_dbg(bond->dev, port->slave->dev, "Port %d joined LAG %d (new LAG)\n", + port->actor_port_number, + port->aggregator->aggregator_identifier); } else { - netdev_err(bond->dev, "Port %d (on %s) did not find a suitable aggregator\n", - port->actor_port_number, port->slave->dev->name); + slave_err(bond->dev, port->slave->dev, + "Port %d did not find a suitable aggregator\n", + port->actor_port_number); + return; } } /* if all aggregator's ports are READY_N == TRUE, set ready=TRUE @@ -1534,7 +1534,7 @@ ad_agg_selection_logic(aggregator, update_slave_arr); if (!port->aggregator->is_active) - port->actor_oper_port_state &= ~AD_STATE_SYNCHRONIZATION; + port->actor_oper_port_state &= ~LACP_STATE_SYNCHRONIZATION; } /* Decide if "agg" is a better choice for the new active aggregator that @@ -1590,7 +1590,7 @@ if (__agg_active_ports(curr) < __agg_active_ports(best)) return best; - /*FALLTHROUGH*/ + fallthrough; case BOND_AD_STABLE: case BOND_AD_BANDWIDTH: if (__get_agg_bandwidth(curr) > __get_agg_bandwidth(best)) @@ -1599,8 +1599,9 @@ break; default: - net_warn_ratelimited("%s: Impossible agg select mode %d\n", + net_warn_ratelimited("%s: (slave %s): Impossible agg select mode %d\n", curr->slave->bond->dev->name, + curr->slave->dev->name, __get_agg_selection_mode(curr->lag_ports)); break; } @@ -1627,7 +1628,7 @@ /** * ad_agg_selection_logic - select an aggregation group for a team - * @aggregator: the aggregator we're looking at + * @agg: the aggregator we're looking at * @update_slave_arr: Does slave array need update? * * It is assumed that only one aggregator may be selected for a team. @@ -1701,36 +1702,37 @@ /* if there is new best aggregator, activate it */ if (best) { - netdev_dbg(bond->dev, "best Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n", + netdev_dbg(bond->dev, "(slave %s): best Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n", + best->slave ? best->slave->dev->name : "NULL", best->aggregator_identifier, best->num_of_ports, best->actor_oper_aggregator_key, best->partner_oper_aggregator_key, best->is_individual, best->is_active); - netdev_dbg(bond->dev, "best ports %p slave %p %s\n", - best->lag_ports, best->slave, - best->slave ? best->slave->dev->name : "NULL"); + netdev_dbg(bond->dev, "(slave %s): best ports %p slave %p\n", + best->slave ? best->slave->dev->name : "NULL", + best->lag_ports, best->slave); bond_for_each_slave_rcu(bond, slave, iter) { agg = &(SLAVE_AD_INFO(slave)->aggregator); - netdev_dbg(bond->dev, "Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n", - agg->aggregator_identifier, agg->num_of_ports, - agg->actor_oper_aggregator_key, - agg->partner_oper_aggregator_key, - agg->is_individual, agg->is_active); + slave_dbg(bond->dev, slave->dev, "Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n", + agg->aggregator_identifier, agg->num_of_ports, + agg->actor_oper_aggregator_key, + agg->partner_oper_aggregator_key, + agg->is_individual, agg->is_active); } - /* check if any partner replys */ - if (best->is_individual) { + /* check if any partner replies */ + if (best->is_individual) net_warn_ratelimited("%s: Warning: No 802.3ad response from the link partner for any adapters in the bond\n", - best->slave ? - best->slave->bond->dev->name : "NULL"); - } + bond->dev->name); best->is_active = 1; - netdev_dbg(bond->dev, "LAG %d chosen as the active LAG\n", + netdev_dbg(bond->dev, "(slave %s): LAG %d chosen as the active LAG\n", + best->slave ? best->slave->dev->name : "NULL", best->aggregator_identifier); - netdev_dbg(bond->dev, "Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n", + netdev_dbg(bond->dev, "(slave %s): Agg=%d; P=%d; a k=%d; p k=%d; Ind=%d; Act=%d\n", + best->slave ? best->slave->dev->name : "NULL", best->aggregator_identifier, best->num_of_ports, best->actor_oper_aggregator_key, best->partner_oper_aggregator_key, @@ -1787,7 +1789,9 @@ aggregator->lag_ports = NULL; aggregator->is_active = 0; aggregator->num_of_ports = 0; - pr_debug("LAG %d was cleared\n", + pr_debug("%s: LAG %d was cleared\n", + aggregator->slave ? + aggregator->slave->dev->name : "NULL", aggregator->aggregator_identifier); } } @@ -1809,7 +1813,7 @@ /** * ad_initialize_port - initialize a given port's parameters - * @aggregator: the aggregator we're looking at + * @port: the port we're looking at * @lacp_fast: boolean. whether fast periodic should be used */ static void ad_initialize_port(struct port *port, int lacp_fast) @@ -1837,13 +1841,13 @@ port->actor_port_priority = 0xff; port->actor_port_aggregator_identifier = 0; port->ntt = false; - port->actor_admin_port_state = AD_STATE_AGGREGATION | - AD_STATE_LACP_ACTIVITY; - port->actor_oper_port_state = AD_STATE_AGGREGATION | - AD_STATE_LACP_ACTIVITY; + port->actor_admin_port_state = LACP_STATE_AGGREGATION | + LACP_STATE_LACP_ACTIVITY; + port->actor_oper_port_state = LACP_STATE_AGGREGATION | + LACP_STATE_LACP_ACTIVITY; if (lacp_fast) - port->actor_oper_port_state |= AD_STATE_LACP_TIMEOUT; + port->actor_oper_port_state |= LACP_STATE_LACP_TIMEOUT; memcpy(&port->partner_admin, &tmpl, sizeof(tmpl)); memcpy(&port->partner_oper, &tmpl, sizeof(tmpl)); @@ -1884,9 +1888,10 @@ bool *update_slave_arr) { if (port->aggregator->is_active) { - pr_debug("Enabling port %d(LAG %d)\n", - port->actor_port_number, - port->aggregator->aggregator_identifier); + slave_dbg(port->slave->bond->dev, port->slave->dev, + "Enabling port %d (LAG %d)\n", + port->actor_port_number, + port->aggregator->aggregator_identifier); __enable_port(port); /* Slave array needs update */ *update_slave_arr = true; @@ -1904,9 +1909,10 @@ if (port->aggregator && !MAC_ADDRESS_EQUAL(&(port->aggregator->partner_system), &(null_mac_addr))) { - pr_debug("Disabling port %d(LAG %d)\n", - port->actor_port_number, - port->aggregator->aggregator_identifier); + slave_dbg(port->slave->bond->dev, port->slave->dev, + "Disabling port %d (LAG %d)\n", + port->actor_port_number, + port->aggregator->aggregator_identifier); __disable_port(port); /* Slave array needs an update */ *update_slave_arr = true; @@ -1919,9 +1925,12 @@ * @port: the port we're looking at */ static void ad_marker_info_received(struct bond_marker *marker_info, - struct port *port) + struct port *port) { struct bond_marker marker; + + atomic64_inc(&SLAVE_AD_INFO(port->slave)->stats.marker_rx); + atomic64_inc(&BOND_AD_INFO(port->slave->bond).stats.marker_rx); /* copy the received marker data to the response marker */ memcpy(&marker, marker_info, sizeof(struct bond_marker)); @@ -1929,10 +1938,10 @@ marker.tlv_type = AD_MARKER_RESPONSE_SUBTYPE; /* send the marker response */ - if (ad_marker_send(port, &marker) >= 0) { - pr_debug("Sent Marker Response on port %d\n", - port->actor_port_number); - } + if (ad_marker_send(port, &marker) >= 0) + slave_dbg(port->slave->bond->dev, port->slave->dev, + "Sent Marker Response on port %d\n", + port->actor_port_number); } /** @@ -1947,6 +1956,9 @@ static void ad_marker_response_received(struct bond_marker *marker, struct port *port) { + atomic64_inc(&SLAVE_AD_INFO(port->slave)->stats.marker_resp_rx); + atomic64_inc(&BOND_AD_INFO(port->slave->bond).stats.marker_resp_rx); + /* DO NOTHING, SINCE WE DECIDED NOT TO IMPLEMENT THIS FEATURE FOR NOW */ } @@ -1958,6 +1970,7 @@ /** * bond_3ad_initiate_agg_selection - initate aggregator selection * @bond: bonding struct + * @timeout: timeout value to set * * Set the aggregation selection timer, to initiate an agg selection in * the very near future. Called during first initialization, and during @@ -1977,30 +1990,24 @@ */ void bond_3ad_initialize(struct bonding *bond, u16 tick_resolution) { - /* check that the bond is not initialized yet */ - if (!MAC_ADDRESS_EQUAL(&(BOND_AD_INFO(bond).system.sys_mac_addr), - bond->dev->dev_addr)) { + BOND_AD_INFO(bond).aggregator_identifier = 0; + BOND_AD_INFO(bond).system.sys_priority = + bond->params.ad_actor_sys_prio; + if (is_zero_ether_addr(bond->params.ad_actor_system)) + BOND_AD_INFO(bond).system.sys_mac_addr = + *((struct mac_addr *)bond->dev->dev_addr); + else + BOND_AD_INFO(bond).system.sys_mac_addr = + *((struct mac_addr *)bond->params.ad_actor_system); - BOND_AD_INFO(bond).aggregator_identifier = 0; + /* initialize how many times this module is called in one + * second (should be about every 100ms) + */ + ad_ticks_per_sec = tick_resolution; - BOND_AD_INFO(bond).system.sys_priority = - bond->params.ad_actor_sys_prio; - if (is_zero_ether_addr(bond->params.ad_actor_system)) - BOND_AD_INFO(bond).system.sys_mac_addr = - *((struct mac_addr *)bond->dev->dev_addr); - else - BOND_AD_INFO(bond).system.sys_mac_addr = - *((struct mac_addr *)bond->params.ad_actor_system); - - /* initialize how many times this module is called in one - * second (should be about every 100ms) - */ - ad_ticks_per_sec = tick_resolution; - - bond_3ad_initiate_agg_selection(bond, - AD_AGGREGATOR_SELECTION_TIMER * - ad_ticks_per_sec); - } + bond_3ad_initiate_agg_selection(bond, + AD_AGGREGATOR_SELECTION_TIMER * + ad_ticks_per_sec); } /** @@ -2078,19 +2085,18 @@ /* if slave is null, the whole port is not initialized */ if (!port->slave) { - netdev_warn(bond->dev, "Trying to unbind an uninitialized port on %s\n", - slave->dev->name); + slave_warn(bond->dev, slave->dev, "Trying to unbind an uninitialized port\n"); goto out; } - netdev_dbg(bond->dev, "Unbinding Link Aggregation Group %d\n", - aggregator->aggregator_identifier); + slave_dbg(bond->dev, slave->dev, "Unbinding Link Aggregation Group %d\n", + aggregator->aggregator_identifier); /* Tell the partner that this port is not suitable for aggregation */ - port->actor_oper_port_state &= ~AD_STATE_SYNCHRONIZATION; - port->actor_oper_port_state &= ~AD_STATE_COLLECTING; - port->actor_oper_port_state &= ~AD_STATE_DISTRIBUTING; - port->actor_oper_port_state &= ~AD_STATE_AGGREGATION; + port->actor_oper_port_state &= ~LACP_STATE_SYNCHRONIZATION; + port->actor_oper_port_state &= ~LACP_STATE_COLLECTING; + port->actor_oper_port_state &= ~LACP_STATE_DISTRIBUTING; + port->actor_oper_port_state &= ~LACP_STATE_AGGREGATION; __update_lacpdu_from_port(port); ad_lacpdu_send(port); @@ -2122,14 +2128,14 @@ * new aggregator */ if ((new_aggregator) && ((!new_aggregator->lag_ports) || ((new_aggregator->lag_ports == port) && !new_aggregator->lag_ports->next_port_in_aggregator))) { - netdev_dbg(bond->dev, "Some port(s) related to LAG %d - replacing with LAG %d\n", - aggregator->aggregator_identifier, - new_aggregator->aggregator_identifier); + slave_dbg(bond->dev, slave->dev, "Some port(s) related to LAG %d - replacing with LAG %d\n", + aggregator->aggregator_identifier, + new_aggregator->aggregator_identifier); if ((new_aggregator->lag_ports == port) && new_aggregator->is_active) { - netdev_info(bond->dev, "Removing an active aggregator\n"); - select_new_active_agg = 1; + slave_info(bond->dev, slave->dev, "Removing an active aggregator\n"); + select_new_active_agg = 1; } new_aggregator->is_individual = aggregator->is_individual; @@ -2159,7 +2165,7 @@ ad_agg_selection_logic(__get_first_agg(port), &dummy_slave_update); } else { - netdev_warn(bond->dev, "unbinding aggregator, and could not find a new aggregator for its ports\n"); + slave_warn(bond->dev, slave->dev, "unbinding aggregator, and could not find a new aggregator for its ports\n"); } } else { /* in case that the only port related to this @@ -2168,7 +2174,7 @@ select_new_active_agg = aggregator->is_active; ad_clear_agg(aggregator); if (select_new_active_agg) { - netdev_info(bond->dev, "Removing an active aggregator\n"); + slave_info(bond->dev, slave->dev, "Removing an active aggregator\n"); /* select new active aggregator */ temp_aggregator = __get_first_agg(port); if (temp_aggregator) @@ -2178,7 +2184,7 @@ } } - netdev_dbg(bond->dev, "Unbinding port %d\n", port->actor_port_number); + slave_dbg(bond->dev, slave->dev, "Unbinding port %d\n", port->actor_port_number); /* find the aggregator that this port is connected to */ bond_for_each_slave(bond, slave_iter, iter) { @@ -2199,9 +2205,10 @@ temp_aggregator->num_of_ports--; if (__agg_active_ports(temp_aggregator) == 0) { select_new_active_agg = temp_aggregator->is_active; - ad_clear_agg(temp_aggregator); + if (temp_aggregator->num_of_ports == 0) + ad_clear_agg(temp_aggregator); if (select_new_active_agg) { - netdev_info(bond->dev, "Removing an active aggregator\n"); + slave_info(bond->dev, slave->dev, "Removing an active aggregator\n"); /* select new active aggregator */ ad_agg_selection_logic(__get_first_agg(port), &dummy_slave_update); @@ -2273,7 +2280,7 @@ /** * bond_3ad_state_machine_handler - handle state machines timeout - * @bond: bonding struct to work on + * @work: work context to fetch bonding struct to work on from * * The state machine handling concept in this module is to check every tick * which state machine should operate any function. The execution order is @@ -2369,66 +2376,68 @@ * bond_3ad_rx_indication - handle a received frame * @lacpdu: received lacpdu * @slave: slave struct to work on - * @length: length of the data received * * It is assumed that frames that were sent on this NIC don't returned as new * received frames (loopback). Since only the payload is given to this * function, it check for loopback. */ -static int bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave, - u16 length) +static int bond_3ad_rx_indication(struct lacpdu *lacpdu, struct slave *slave) { - struct port *port; + struct bonding *bond = slave->bond; int ret = RX_HANDLER_ANOTHER; + struct bond_marker *marker; + struct port *port; + atomic64_t *stat; - if (length >= sizeof(struct lacpdu)) { - - port = &(SLAVE_AD_INFO(slave)->port); - - if (!port->slave) { - net_warn_ratelimited("%s: Warning: port of slave %s is uninitialized\n", - slave->dev->name, slave->bond->dev->name); - return ret; - } - - switch (lacpdu->subtype) { - case AD_TYPE_LACPDU: - ret = RX_HANDLER_CONSUMED; - netdev_dbg(slave->bond->dev, - "Received LACPDU on port %d slave %s\n", - port->actor_port_number, - slave->dev->name); - /* Protect against concurrent state machines */ - spin_lock(&slave->bond->mode_lock); - ad_rx_machine(lacpdu, port); - spin_unlock(&slave->bond->mode_lock); - break; - - case AD_TYPE_MARKER: - ret = RX_HANDLER_CONSUMED; - /* No need to convert fields to Little Endian since we - * don't use the marker's fields. - */ - - switch (((struct bond_marker *)lacpdu)->tlv_type) { - case AD_MARKER_INFORMATION_SUBTYPE: - netdev_dbg(slave->bond->dev, "Received Marker Information on port %d\n", - port->actor_port_number); - ad_marker_info_received((struct bond_marker *)lacpdu, port); - break; - - case AD_MARKER_RESPONSE_SUBTYPE: - netdev_dbg(slave->bond->dev, "Received Marker Response on port %d\n", - port->actor_port_number); - ad_marker_response_received((struct bond_marker *)lacpdu, port); - break; - - default: - netdev_dbg(slave->bond->dev, "Received an unknown Marker subtype on slot %d\n", - port->actor_port_number); - } - } + port = &(SLAVE_AD_INFO(slave)->port); + if (!port->slave) { + net_warn_ratelimited("%s: Warning: port of slave %s is uninitialized\n", + slave->dev->name, slave->bond->dev->name); + return ret; } + + switch (lacpdu->subtype) { + case AD_TYPE_LACPDU: + ret = RX_HANDLER_CONSUMED; + slave_dbg(slave->bond->dev, slave->dev, + "Received LACPDU on port %d\n", + port->actor_port_number); + /* Protect against concurrent state machines */ + spin_lock(&slave->bond->mode_lock); + ad_rx_machine(lacpdu, port); + spin_unlock(&slave->bond->mode_lock); + break; + case AD_TYPE_MARKER: + ret = RX_HANDLER_CONSUMED; + /* No need to convert fields to Little Endian since we + * don't use the marker's fields. + */ + marker = (struct bond_marker *)lacpdu; + switch (marker->tlv_type) { + case AD_MARKER_INFORMATION_SUBTYPE: + slave_dbg(slave->bond->dev, slave->dev, "Received Marker Information on port %d\n", + port->actor_port_number); + ad_marker_info_received(marker, port); + break; + case AD_MARKER_RESPONSE_SUBTYPE: + slave_dbg(slave->bond->dev, slave->dev, "Received Marker Response on port %d\n", + port->actor_port_number); + ad_marker_response_received(marker, port); + break; + default: + slave_dbg(slave->bond->dev, slave->dev, "Received an unknown Marker subtype on port %d\n", + port->actor_port_number); + stat = &SLAVE_AD_INFO(slave)->stats.marker_unknown_rx; + atomic64_inc(stat); + stat = &BOND_AD_INFO(bond).stats.marker_unknown_rx; + atomic64_inc(stat); + } + break; + default: + atomic64_inc(&SLAVE_AD_INFO(slave)->stats.lacpdu_unknown_rx); + atomic64_inc(&BOND_AD_INFO(bond).stats.lacpdu_unknown_rx); + } + return ret; } @@ -2467,9 +2476,10 @@ if (!reset) { if (!speed) { - netdev_err(port->slave->dev, - "speed changed to 0 for port %s", - port->slave->dev->name); + slave_err(port->slave->bond->dev, + port->slave->dev, + "speed changed to 0 on port %d\n", + port->actor_port_number); } else if (duplex && ospeed != speed) { /* Speed change restarts LACP state-machine */ port->sm_vars |= AD_PORT_BEGIN; @@ -2494,23 +2504,22 @@ /* if slave is null, the whole port is not initialized */ if (!port->slave) { - netdev_warn(slave->bond->dev, - "speed/duplex changed for uninitialized port %s\n", - slave->dev->name); + slave_warn(slave->bond->dev, slave->dev, + "speed/duplex changed for uninitialized port\n"); return; } spin_lock_bh(&slave->bond->mode_lock); ad_update_actor_keys(port, false); spin_unlock_bh(&slave->bond->mode_lock); - netdev_dbg(slave->bond->dev, "Port %d slave %s changed speed/duplex\n", - port->actor_port_number, slave->dev->name); + slave_dbg(slave->bond->dev, slave->dev, "Port %d changed speed/duplex\n", + port->actor_port_number); } /** * bond_3ad_handle_link_change - handle a slave's link status change indication * @slave: slave struct to work on - * @status: whether the link is now up or down + * @link: whether the link is now up or down * * Handle reselection of aggregator (if needed) for this port. */ @@ -2524,8 +2533,7 @@ /* if slave is null, the whole port is not initialized */ if (!port->slave) { - netdev_warn(slave->bond->dev, "link status changed for uninitialized port on %s\n", - slave->dev->name); + slave_warn(slave->bond->dev, slave->dev, "link status changed for uninitialized port\n"); return; } @@ -2550,9 +2558,9 @@ spin_unlock_bh(&slave->bond->mode_lock); - netdev_dbg(slave->bond->dev, "Port %d changed link status to %s\n", - port->actor_port_number, - link == BOND_LINK_UP ? "UP" : "DOWN"); + slave_dbg(slave->bond->dev, slave->dev, "Port %d changed link status to %s\n", + port->actor_port_number, + link == BOND_LINK_UP ? "UP" : "DOWN"); /* RTNL is held and mode_lock is released so it's safe * to update slave_array here. @@ -2562,7 +2570,7 @@ /** * bond_3ad_set_carrier - set link state for bonding master - * @bond - bonding structure + * @bond: bonding structure * * if we have an active aggregator, we're up, if not, we're down. * Presumes that we cannot have an active aggregator if there are @@ -2664,15 +2672,18 @@ return RX_HANDLER_ANOTHER; lacpdu = skb_header_pointer(skb, 0, sizeof(_lacpdu), &_lacpdu); - if (!lacpdu) + if (!lacpdu) { + atomic64_inc(&SLAVE_AD_INFO(slave)->stats.lacpdu_illegal_rx); + atomic64_inc(&BOND_AD_INFO(bond).stats.lacpdu_illegal_rx); return RX_HANDLER_ANOTHER; + } - return bond_3ad_rx_indication(lacpdu, slave, skb->len); + return bond_3ad_rx_indication(lacpdu, slave); } /** * bond_3ad_update_lacp_rate - change the lacp rate - * @bond - bonding struct + * @bond: bonding struct * * When modify lacp_rate parameter via sysfs, * update actor_oper_port_state of each port. @@ -2693,9 +2704,67 @@ bond_for_each_slave(bond, slave, iter) { port = &(SLAVE_AD_INFO(slave)->port); if (lacp_fast) - port->actor_oper_port_state |= AD_STATE_LACP_TIMEOUT; + port->actor_oper_port_state |= LACP_STATE_LACP_TIMEOUT; else - port->actor_oper_port_state &= ~AD_STATE_LACP_TIMEOUT; + port->actor_oper_port_state &= ~LACP_STATE_LACP_TIMEOUT; } spin_unlock_bh(&bond->mode_lock); } + +size_t bond_3ad_stats_size(void) +{ + return nla_total_size_64bit(sizeof(u64)) + /* BOND_3AD_STAT_LACPDU_RX */ + nla_total_size_64bit(sizeof(u64)) + /* BOND_3AD_STAT_LACPDU_TX */ + nla_total_size_64bit(sizeof(u64)) + /* BOND_3AD_STAT_LACPDU_UNKNOWN_RX */ + nla_total_size_64bit(sizeof(u64)) + /* BOND_3AD_STAT_LACPDU_ILLEGAL_RX */ + nla_total_size_64bit(sizeof(u64)) + /* BOND_3AD_STAT_MARKER_RX */ + nla_total_size_64bit(sizeof(u64)) + /* BOND_3AD_STAT_MARKER_TX */ + nla_total_size_64bit(sizeof(u64)) + /* BOND_3AD_STAT_MARKER_RESP_RX */ + nla_total_size_64bit(sizeof(u64)) + /* BOND_3AD_STAT_MARKER_RESP_TX */ + nla_total_size_64bit(sizeof(u64)); /* BOND_3AD_STAT_MARKER_UNKNOWN_RX */ +} + +int bond_3ad_stats_fill(struct sk_buff *skb, struct bond_3ad_stats *stats) +{ + u64 val; + + val = atomic64_read(&stats->lacpdu_rx); + if (nla_put_u64_64bit(skb, BOND_3AD_STAT_LACPDU_RX, val, + BOND_3AD_STAT_PAD)) + return -EMSGSIZE; + val = atomic64_read(&stats->lacpdu_tx); + if (nla_put_u64_64bit(skb, BOND_3AD_STAT_LACPDU_TX, val, + BOND_3AD_STAT_PAD)) + return -EMSGSIZE; + val = atomic64_read(&stats->lacpdu_unknown_rx); + if (nla_put_u64_64bit(skb, BOND_3AD_STAT_LACPDU_UNKNOWN_RX, val, + BOND_3AD_STAT_PAD)) + return -EMSGSIZE; + val = atomic64_read(&stats->lacpdu_illegal_rx); + if (nla_put_u64_64bit(skb, BOND_3AD_STAT_LACPDU_ILLEGAL_RX, val, + BOND_3AD_STAT_PAD)) + return -EMSGSIZE; + + val = atomic64_read(&stats->marker_rx); + if (nla_put_u64_64bit(skb, BOND_3AD_STAT_MARKER_RX, val, + BOND_3AD_STAT_PAD)) + return -EMSGSIZE; + val = atomic64_read(&stats->marker_tx); + if (nla_put_u64_64bit(skb, BOND_3AD_STAT_MARKER_TX, val, + BOND_3AD_STAT_PAD)) + return -EMSGSIZE; + val = atomic64_read(&stats->marker_resp_rx); + if (nla_put_u64_64bit(skb, BOND_3AD_STAT_MARKER_RESP_RX, val, + BOND_3AD_STAT_PAD)) + return -EMSGSIZE; + val = atomic64_read(&stats->marker_resp_tx); + if (nla_put_u64_64bit(skb, BOND_3AD_STAT_MARKER_RESP_TX, val, + BOND_3AD_STAT_PAD)) + return -EMSGSIZE; + val = atomic64_read(&stats->marker_unknown_rx); + if (nla_put_u64_64bit(skb, BOND_3AD_STAT_MARKER_UNKNOWN_RX, val, + BOND_3AD_STAT_PAD)) + return -EMSGSIZE; + + return 0; +} -- Gitblit v1.6.2