Commit 34d2d336 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'net-unsync-addresses-from-ports'



From: Benjamin Poirier <bpoirier@nvidia.com>
To: netdev@vger.kernel.org
Cc: Jay Vosburgh <j.vosburgh@gmail.com>,
	Veaceslav Falico <vfalico@gmail.com>,
	Andy Gospodarek <andy@greyhouse.net>,
	"David S. Miller" <davem@davemloft.net>,
	Eric Dumazet <edumazet@google.com>,
	Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
	Jiri Pirko <jiri@resnulli.us>, Shuah Khan <shuah@kernel.org>,
	Jonathan Toppins <jtoppins@redhat.com>,
	linux-kselftest@vger.kernel.org
Subject: [PATCH net v3 0/4] Unsync addresses from ports when stopping aggregated devices
Date: Wed,  7 Sep 2022 16:56:38 +0900	[thread overview]
Message-ID: <20220907075642.475236-1-bpoirier@nvidia.com> (raw)

This series fixes similar problems in the bonding and team drivers.

Because of missing dev_{uc,mc}_unsync() calls, addresses added to
underlying devices may be leftover after the aggregated device is deleted.
Add the missing calls and a few related tests.

v2:
* fix selftest installation, see patch 3

v3:
* Split lacpdu_multicast changes to their own patch, #1
* In ndo_{add,del}_slave methods, only perform address list changes when
  the aggregated device is up (patches 2 & 3)
* Add selftest function related to the above change (patch 4)
====================

Acked-by: default avatarJay Vosburgh <jay.vosburgh@canonical.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 21be1ad6 bbb774d9
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -19948,6 +19948,7 @@ S: Supported
F:	drivers/net/team/
F:	include/linux/if_team.h
F:	include/uapi/linux/if_team.h
F:	tools/testing/selftests/net/team/
TECHNOLOGIC SYSTEMS TS-5500 PLATFORM SUPPORT
M:	"Savoir-faire Linux Inc." <kernel@savoirfairelinux.com>
+3 −2
Original line number Diff line number Diff line
@@ -88,8 +88,9 @@ static const u8 null_mac_addr[ETH_ALEN + 2] __long_aligned = {
static const u16 ad_ticks_per_sec = 1000 / AD_TIMER_INTERVAL;
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);
+36 −21
Original line number Diff line number Diff line
@@ -865,12 +865,8 @@ static void bond_hw_addr_flush(struct net_device *bond_dev,
	dev_uc_unsync(slave_dev, bond_dev);
	dev_mc_unsync(slave_dev, bond_dev);

	if (BOND_MODE(bond) == BOND_MODE_8023AD) {
		/* del lacpdu mc addr from mc list */
		u8 lacpdu_multicast[ETH_ALEN] = MULTICAST_LACPDU_ADDR;

		dev_mc_del(slave_dev, lacpdu_multicast);
	}
	if (BOND_MODE(bond) == BOND_MODE_8023AD)
		dev_mc_del(slave_dev, lacpdu_mcast_addr);
}

/*--------------------------- Active slave change ---------------------------*/
@@ -890,6 +886,7 @@ static void bond_hw_addr_swap(struct bonding *bond, struct slave *new_active,
		if (bond->dev->flags & IFF_ALLMULTI)
			dev_set_allmulti(old_active->dev, -1);

		if (bond->dev->flags & IFF_UP)
			bond_hw_addr_flush(bond->dev, old_active->dev);
	}

@@ -901,12 +898,14 @@ static void bond_hw_addr_swap(struct bonding *bond, struct slave *new_active,
		if (bond->dev->flags & IFF_ALLMULTI)
			dev_set_allmulti(new_active->dev, 1);

		if (bond->dev->flags & IFF_UP) {
			netif_addr_lock_bh(bond->dev);
			dev_uc_sync(new_active->dev, bond->dev);
			dev_mc_sync(new_active->dev, bond->dev);
			netif_addr_unlock_bh(bond->dev);
		}
	}
}

/**
 * bond_set_dev_addr - clone slave's address to bond
@@ -2166,16 +2165,14 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
			}
		}

		if (bond_dev->flags & IFF_UP) {
			netif_addr_lock_bh(bond_dev);
			dev_mc_sync_multiple(slave_dev, bond_dev);
			dev_uc_sync_multiple(slave_dev, bond_dev);
			netif_addr_unlock_bh(bond_dev);

		if (BOND_MODE(bond) == BOND_MODE_8023AD) {
			/* add lacpdu mc addr to mc list */
			u8 lacpdu_multicast[ETH_ALEN] = MULTICAST_LACPDU_ADDR;

			dev_mc_add(slave_dev, lacpdu_multicast);
			if (BOND_MODE(bond) == BOND_MODE_8023AD)
				dev_mc_add(slave_dev, lacpdu_mcast_addr);
		}
	}

@@ -2447,6 +2444,7 @@ static int __bond_release_one(struct net_device *bond_dev,
		if (old_flags & IFF_ALLMULTI)
			dev_set_allmulti(slave_dev, -1);

		if (old_flags & IFF_UP)
			bond_hw_addr_flush(bond_dev, slave_dev);
	}

@@ -4221,6 +4219,9 @@ static int bond_open(struct net_device *bond_dev)
		/* register to receive LACPDUs */
		bond->recv_probe = bond_3ad_lacpdu_recv;
		bond_3ad_initiate_agg_selection(bond, 1);

		bond_for_each_slave(bond, slave, iter)
			dev_mc_add(slave->dev, lacpdu_mcast_addr);
	}

	if (bond_mode_can_use_xmit_hash(bond))
@@ -4232,6 +4233,7 @@ static int bond_open(struct net_device *bond_dev)
static int bond_close(struct net_device *bond_dev)
{
	struct bonding *bond = netdev_priv(bond_dev);
	struct slave *slave;

	bond_work_cancel_all(bond);
	bond->send_peer_notif = 0;
@@ -4239,6 +4241,19 @@ static int bond_close(struct net_device *bond_dev)
		bond_alb_deinitialize(bond);
	bond->recv_probe = NULL;

	if (bond_uses_primary(bond)) {
		rcu_read_lock();
		slave = rcu_dereference(bond->curr_active_slave);
		if (slave)
			bond_hw_addr_flush(bond_dev, slave->dev);
		rcu_read_unlock();
	} else {
		struct list_head *iter;

		bond_for_each_slave(bond, slave, iter)
			bond_hw_addr_flush(bond_dev, slave->dev);
	}

	return 0;
}

+18 −6
Original line number Diff line number Diff line
@@ -1275,10 +1275,12 @@ static int team_port_add(struct team *team, struct net_device *port_dev,
		}
	}

	if (dev->flags & IFF_UP) {
		netif_addr_lock_bh(dev);
		dev_uc_sync_multiple(port_dev, dev);
		dev_mc_sync_multiple(port_dev, dev);
		netif_addr_unlock_bh(dev);
	}

	port->index = -1;
	list_add_tail_rcu(&port->list, &team->port_list);
@@ -1349,8 +1351,10 @@ static int team_port_del(struct team *team, struct net_device *port_dev)
	netdev_rx_handler_unregister(port_dev);
	team_port_disable_netpoll(port);
	vlan_vids_del_by_dev(port_dev, dev);
	if (dev->flags & IFF_UP) {
		dev_uc_unsync(port_dev, dev);
		dev_mc_unsync(port_dev, dev);
	}
	dev_close(port_dev);
	team_port_leave(team, port);

@@ -1700,6 +1704,14 @@ static int team_open(struct net_device *dev)

static int team_close(struct net_device *dev)
{
	struct team *team = netdev_priv(dev);
	struct team_port *port;

	list_for_each_entry(port, &team->port_list, list) {
		dev_uc_unsync(port->dev, dev);
		dev_mc_unsync(port->dev, dev);
	}

	return 0;
}

+0 −2
Original line number Diff line number Diff line
@@ -15,8 +15,6 @@
#define PKT_TYPE_LACPDU         cpu_to_be16(ETH_P_SLOW)
#define AD_TIMER_INTERVAL       100 /*msec*/

#define MULTICAST_LACPDU_ADDR    {0x01, 0x80, 0xC2, 0x00, 0x00, 0x02}

#define AD_LACP_SLOW 0
#define AD_LACP_FAST 1

Loading