2022-08-30 20:12:48

by Vladimir Oltean

[permalink] [raw]
Subject: [PATCH net-next 0/9] DSA changes for multiple CPU ports (part 4)

Those who have been following part 1:
https://patchwork.kernel.org/project/netdevbpf/cover/[email protected]/
part 2:
https://patchwork.kernel.org/project/netdevbpf/cover/[email protected]/
and part 3:
https://patchwork.kernel.org/project/netdevbpf/cover/[email protected]/
will know that I am trying to enable the second internal port pair from
the NXP LS1028A Felix switch for DSA-tagged traffic via "ocelot-8021q".

This series represents the final part of that effort. We have:

- the introduction of new UAPI in the form of IFLA_DSA_MASTER

- preparation for LAG DSA masters in terms of suppressing some
operations for masters in the DSA core that simply don't make sense
when those masters are a bonding/team interface

- handling all the net device events that occur between DSA and a
LAG DSA master, including migration to a different DSA master when the
current master joins a LAG, or the LAG gets destroyed

- updating documentation

- adding an implementation for NXP LS1028A, where things are insanely
complicated due to hardware limitations. We have 2 tagging protocols:

* the native "ocelot" protocol (NPI port mode). This does not support
CPU ports in a LAG, and supports a single DSA master. The DSA master
can be changed between eno2 (2.5G) and eno3 (1G), but all ports must
be down during the changing process, and user ports assigned to the
old DSA master will refuse to come up if the user requests that
during a "transient" state.

* the "ocelot-8021q" software-defined protocol, where the Ethernet
ports connected to the CPU are not actually "god mode" ports as far
as the hardware is concerned. So here, static assignment between
user and CPU ports is possible by editing the PGID_SRC masks for
the port-based forwarding matrix, and "CPU ports in a LAG" simply
means "a LAG like any other".

The series was regression-tested on LS1028A using the local_termination.sh
kselftest, in most of the possible operating modes and tagging protocols.
I have not done a detailed performance evaluation yet, but using LAG, is
possible to exceed the termination bandwidth of a single CPU port in an
iperf3 test with multiple senders and multiple receivers.

There was a previous RFC posted, which contains most of these changes,
however it's so old by now that it's unlikely anyone of the reviewers
remembers it in detail. I've applied most of the feedback requested by
Florian and Ansuel there.
https://lore.kernel.org/netdev/[email protected]/

Vladimir Oltean (9):
net: introduce iterators over synced hw addresses
net: dsa: introduce dsa_port_get_master()
net: dsa: allow the DSA master to be seen and changed through
rtnetlink
net: dsa: don't keep track of admin/oper state on LAG DSA masters
net: dsa: suppress appending ethtool stats to LAG DSA masters
net: dsa: suppress device links to LAG DSA masters
net: dsa: allow masters to join a LAG
docs: net: dsa: update information about multiple CPU ports
net: dsa: felix: add support for changing DSA master

.../networking/dsa/configuration.rst | 84 +++++
Documentation/networking/dsa/dsa.rst | 38 ++-
drivers/net/dsa/bcm_sf2.c | 4 +-
drivers/net/dsa/bcm_sf2_cfp.c | 4 +-
drivers/net/dsa/lan9303-core.c | 4 +-
drivers/net/dsa/ocelot/felix.c | 117 ++++++-
drivers/net/dsa/ocelot/felix.h | 3 +
.../net/ethernet/mediatek/mtk_ppe_offload.c | 2 +-
drivers/net/ethernet/mscc/ocelot.c | 3 +-
include/linux/netdevice.h | 6 +
include/net/dsa.h | 19 ++
include/soc/mscc/ocelot.h | 1 +
include/uapi/linux/if_link.h | 10 +
net/dsa/Makefile | 10 +-
net/dsa/dsa.c | 9 +
net/dsa/dsa2.c | 34 ++-
net/dsa/dsa_priv.h | 17 +-
net/dsa/master.c | 82 ++++-
net/dsa/netlink.c | 62 ++++
net/dsa/port.c | 159 +++++++++-
net/dsa/slave.c | 288 +++++++++++++++++-
net/dsa/switch.c | 22 +-
net/dsa/tag_8021q.c | 4 +-
23 files changed, 924 insertions(+), 58 deletions(-)
create mode 100644 net/dsa/netlink.c

--
2.34.1


2022-08-30 20:13:06

by Vladimir Oltean

[permalink] [raw]
Subject: [PATCH net-next 7/9] net: dsa: allow masters to join a LAG

There are 2 ways in which a DSA user port may become handled by 2 CPU
ports in a LAG:

(1) its current DSA master joins a LAG

ip link del bond0 && ip link add bond0 type bond mode 802.3ad
ip link set eno2 master bond0

When this happens, all user ports with "eno2" as DSA master get
automatically migrated to "bond0" as DSA master.

(2) it is explicitly configured as such by the user

# Before, the DSA master was eno3
ip link set swp0 type dsa master bond0

The design of this configuration is that the LAG device dynamically
becomes a DSA master through dsa_master_setup() when the first physical
DSA master becomes a LAG slave, and stops being so through
dsa_master_teardown() when the last physical DSA master leaves.

A LAG interface is considered as a valid DSA master only if it contains
existing DSA masters, and no other lower interfaces. Therefore, we
mainly rely on method (1) to enter this configuration.

Each physical DSA master (LAG slave) retains its dev->dsa_ptr for when
it becomes a standalone DSA master again. But the LAG master also has a
dev->dsa_ptr, and this is actually duplicated from one of the physical
LAG slaves, and therefore needs to be balanced when LAG slaves come and
go.

To the switch driver, putting DSA masters in a LAG is seen as putting
their associated CPU ports in a LAG.

We need to prepare cross-chip host FDB notifiers for CPU ports in a LAG,
by calling the driver's ->lag_fdb_add method rather than ->port_fdb_add.

Signed-off-by: Vladimir Oltean <[email protected]>
---
include/net/dsa.h | 6 ++
net/dsa/dsa_priv.h | 5 ++
net/dsa/master.c | 59 +++++++++++++++++
net/dsa/port.c | 2 +-
net/dsa/slave.c | 157 +++++++++++++++++++++++++++++++++++++++++++--
net/dsa/switch.c | 22 +++++--
6 files changed, 242 insertions(+), 9 deletions(-)

diff --git a/include/net/dsa.h b/include/net/dsa.h
index 3f717c3fcba0..53de8effad60 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -300,6 +300,9 @@ struct dsa_port {
u8 master_admin_up:1;
u8 master_oper_up:1;

+ /* Valid only on user ports */
+ u8 cpu_port_in_lag:1;
+
u8 setup:1;

struct device_node *dn;
@@ -724,6 +727,9 @@ static inline bool dsa_port_offloads_lag(struct dsa_port *dp,

static inline struct net_device *dsa_port_to_master(const struct dsa_port *dp)
{
+ if (dp->cpu_port_in_lag)
+ return dsa_port_lag_dev_get(dp->cpu_dp);
+
return dp->cpu_dp->master;
}

diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index d252a04ed725..5628cd5665b0 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -184,6 +184,11 @@ static inline int dsa_tag_protocol_overhead(const struct dsa_device_ops *ops)
/* master.c */
int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp);
void dsa_master_teardown(struct net_device *dev);
+int dsa_master_lag_setup(struct net_device *lag_dev, struct dsa_port *cpu_dp,
+ struct netdev_lag_upper_info *uinfo,
+ struct netlink_ext_ack *extack);
+void dsa_master_lag_teardown(struct net_device *lag_dev,
+ struct dsa_port *cpu_dp);

static inline struct net_device *dsa_master_find_slave(struct net_device *dev,
int device, int port)
diff --git a/net/dsa/master.c b/net/dsa/master.c
index 2176c14b97a8..9a15135f72db 100644
--- a/net/dsa/master.c
+++ b/net/dsa/master.c
@@ -428,3 +428,62 @@ void dsa_master_teardown(struct net_device *dev)
*/
wmb();
}
+
+int dsa_master_lag_setup(struct net_device *lag_dev, struct dsa_port *cpu_dp,
+ struct netdev_lag_upper_info *uinfo,
+ struct netlink_ext_ack *extack)
+{
+ bool master_setup = false;
+ struct net_device *lower;
+ struct list_head *iter;
+ int err;
+
+ /* To be eligible as a DSA master, a LAG must have all lower
+ * interfaces be eligible DSA masters.
+ */
+ netdev_for_each_lower_dev(lag_dev, lower, iter) {
+ if (!netdev_uses_dsa(lower)) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "All LAG ports must be eligible as DSA masters");
+ return -EINVAL;
+ }
+ }
+
+ if (!netdev_uses_dsa(lag_dev)) {
+ err = dsa_master_setup(lag_dev, cpu_dp);
+ if (err)
+ return err;
+ }
+
+ err = dsa_port_lag_join(cpu_dp, lag_dev, uinfo, extack);
+ if (err) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "CPU port failed to join LAG");
+ goto out_master_teardown;
+ }
+
+ return 0;
+
+out_master_teardown:
+ if (master_setup)
+ dsa_master_teardown(lag_dev);
+ return err;
+}
+
+/* Tear down a master if there isn't any other user port on it,
+ * optionally also destroying LAG information.
+ */
+void dsa_master_lag_teardown(struct net_device *lag_dev,
+ struct dsa_port *cpu_dp)
+{
+ struct net_device *upper;
+ struct list_head *iter;
+
+ dsa_port_lag_leave(cpu_dp, lag_dev);
+
+ netdev_for_each_upper_dev_rcu(lag_dev, upper, iter)
+ if (dsa_slave_dev_check(upper))
+ return;
+
+ dsa_master_teardown(lag_dev);
+}
diff --git a/net/dsa/port.c b/net/dsa/port.c
index b719763fe97d..d152f7c7eb6d 100644
--- a/net/dsa/port.c
+++ b/net/dsa/port.c
@@ -1392,6 +1392,7 @@ static int dsa_port_assign_master(struct dsa_port *dp,
return err;

dp->cpu_dp = master->dsa_ptr;
+ dp->cpu_port_in_lag = netif_is_lag_master(master);

return 0;
}
@@ -1411,7 +1412,6 @@ int dsa_port_change_master(struct dsa_port *dp, struct net_device *master,
struct net_device *old_master = dsa_port_to_master(dp);
struct net_device *dev = dp->slave;
struct dsa_switch *ds = dp->ds;
- int port = dp->index;
bool vlan_filtering;
int err, tmp;

diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 00df6cf07866..1030988d797f 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -2840,6 +2840,10 @@ dsa_master_prechangeupper_sanity_check(struct net_device *master,
if (netif_is_bridge_master(info->upper_dev))
return NOTIFY_DONE;

+ /* Allow LAG uppers */
+ if (netif_is_lag_master(info->upper_dev))
+ return NOTIFY_DONE;
+
extack = netdev_notifier_info_to_extack(&info->info);

NL_SET_ERR_MSG_MOD(extack,
@@ -2887,6 +2891,138 @@ dsa_bridge_prechangelower_sanity_check(struct net_device *new_lower,
return NOTIFY_DONE;
}

+static void dsa_tree_migrate_ports_from_lag_master(struct dsa_switch_tree *dst,
+ struct net_device *lag_dev)
+{
+ struct net_device *new_master;
+ struct dsa_port *dp;
+ int err;
+
+ new_master = dsa_tree_find_first_master(dst);
+
+ dsa_tree_for_each_user_port(dp, dst) {
+ if (dsa_port_to_master(dp) != lag_dev)
+ continue;
+
+ err = dsa_slave_change_master(dp->slave, new_master, NULL);
+ if (err) {
+ netdev_err(dp->slave,
+ "failed to restore master to %s: %pe\n",
+ new_master->name, ERR_PTR(err));
+ }
+ }
+}
+
+static int dsa_master_lag_join(struct net_device *master,
+ struct net_device *lag_dev,
+ struct netdev_lag_upper_info *uinfo,
+ struct netlink_ext_ack *extack)
+{
+ struct dsa_port *cpu_dp = master->dsa_ptr;
+ struct dsa_switch_tree *dst = cpu_dp->dst;
+ struct dsa_port *dp;
+ int err;
+
+ err = dsa_master_lag_setup(lag_dev, cpu_dp, uinfo, extack);
+ if (err)
+ return err;
+
+ dsa_tree_for_each_user_port(dp, dst) {
+ if (dsa_port_to_master(dp) != master)
+ continue;
+
+ err = dsa_slave_change_master(dp->slave, lag_dev, extack);
+ if (err)
+ goto restore;
+ }
+
+ return 0;
+
+restore:
+ dsa_tree_for_each_user_port_continue_reverse(dp, dst) {
+ if (dsa_port_to_master(dp) != lag_dev)
+ continue;
+
+ err = dsa_slave_change_master(dp->slave, master, NULL);
+ if (err) {
+ netdev_err(dp->slave,
+ "failed to restore master to %s: %pe\n",
+ master->name, ERR_PTR(err));
+ }
+ }
+
+ dsa_master_lag_teardown(lag_dev, master->dsa_ptr);
+
+ return err;
+}
+
+static void dsa_master_lag_leave(struct net_device *master,
+ struct net_device *lag_dev)
+{
+ struct dsa_port *dp, *cpu_dp = lag_dev->dsa_ptr;
+ struct dsa_switch_tree *dst = cpu_dp->dst;
+ struct dsa_port *new_cpu_dp = NULL;
+ struct net_device *lower;
+ struct list_head *iter;
+
+ netdev_for_each_lower_dev(lag_dev, lower, iter) {
+ if (netdev_uses_dsa(lower)) {
+ new_cpu_dp = lower->dsa_ptr;
+ break;
+ }
+ }
+
+ if (new_cpu_dp) {
+ /* Update the CPU port of the user ports still under the LAG
+ * so that dsa_port_to_master() continues to work properly
+ */
+ dsa_tree_for_each_user_port(dp, dst)
+ if (dsa_port_to_master(dp) == lag_dev)
+ dp->cpu_dp = new_cpu_dp;
+
+ /* Update the index of the virtual CPU port to match the lowest
+ * physical CPU port
+ */
+ lag_dev->dsa_ptr = new_cpu_dp;
+ wmb();
+ } else {
+ /* If the LAG DSA master has no ports left, migrate back all
+ * user ports to the first physical CPU port
+ */
+ dsa_tree_migrate_ports_from_lag_master(dst, lag_dev);
+ }
+
+ /* This DSA master has left its LAG in any case, so let
+ * the CPU port leave the hardware LAG as well
+ */
+ dsa_master_lag_teardown(lag_dev, master->dsa_ptr);
+}
+
+static int dsa_master_changeupper(struct net_device *dev,
+ struct netdev_notifier_changeupper_info *info)
+{
+ struct netlink_ext_ack *extack;
+ int err = NOTIFY_DONE;
+
+ if (!netdev_uses_dsa(dev))
+ return err;
+
+ extack = netdev_notifier_info_to_extack(&info->info);
+
+ if (netif_is_lag_master(info->upper_dev)) {
+ if (info->linking) {
+ err = dsa_master_lag_join(dev, info->upper_dev,
+ info->upper_info, extack);
+ err = notifier_from_errno(err);
+ } else {
+ dsa_master_lag_leave(dev, info->upper_dev);
+ err = NOTIFY_OK;
+ }
+ }
+
+ return err;
+}
+
static int dsa_slave_netdevice_event(struct notifier_block *nb,
unsigned long event, void *ptr)
{
@@ -2930,6 +3066,10 @@ static int dsa_slave_netdevice_event(struct notifier_block *nb,
if (notifier_to_errno(err))
return err;

+ err = dsa_master_changeupper(dev, ptr);
+ if (notifier_to_errno(err))
+ return err;
+
break;
}
case NETDEV_CHANGELOWERSTATE: {
@@ -2937,12 +3077,21 @@ static int dsa_slave_netdevice_event(struct notifier_block *nb,
struct dsa_port *dp;
int err;

- if (!dsa_slave_dev_check(dev))
- break;
+ if (dsa_slave_dev_check(dev)) {
+ dp = dsa_slave_to_port(dev);
+
+ err = dsa_port_lag_change(dp, info->lower_state_info);
+ }

- dp = dsa_slave_to_port(dev);
+ /* Mirror LAG port events on DSA masters that are in
+ * a LAG towards their respective switch CPU ports
+ */
+ if (netdev_uses_dsa(dev)) {
+ dp = dev->dsa_ptr;
+
+ err = dsa_port_lag_change(dp, info->lower_state_info);
+ }

- err = dsa_port_lag_change(dp, info->lower_state_info);
return notifier_from_errno(err);
}
case NETDEV_CHANGE:
diff --git a/net/dsa/switch.c b/net/dsa/switch.c
index 4dfd68cf61c5..5c2451fe5461 100644
--- a/net/dsa/switch.c
+++ b/net/dsa/switch.c
@@ -398,8 +398,15 @@ static int dsa_switch_host_fdb_add(struct dsa_switch *ds,

dsa_switch_for_each_port(dp, ds) {
if (dsa_port_host_address_match(dp, info->dp)) {
- err = dsa_port_do_fdb_add(dp, info->addr, info->vid,
- info->db);
+ if (dsa_port_is_cpu(dp) && info->dp->cpu_port_in_lag) {
+ err = dsa_switch_do_lag_fdb_add(ds, dp->lag,
+ info->addr,
+ info->vid,
+ info->db);
+ } else {
+ err = dsa_port_do_fdb_add(dp, info->addr,
+ info->vid, info->db);
+ }
if (err)
break;
}
@@ -419,8 +426,15 @@ static int dsa_switch_host_fdb_del(struct dsa_switch *ds,

dsa_switch_for_each_port(dp, ds) {
if (dsa_port_host_address_match(dp, info->dp)) {
- err = dsa_port_do_fdb_del(dp, info->addr, info->vid,
- info->db);
+ if (dsa_port_is_cpu(dp) && info->dp->cpu_port_in_lag) {
+ err = dsa_switch_do_lag_fdb_del(ds, dp->lag,
+ info->addr,
+ info->vid,
+ info->db);
+ } else {
+ err = dsa_port_do_fdb_del(dp, info->addr,
+ info->vid, info->db);
+ }
if (err)
break;
}
--
2.34.1

2022-08-30 20:13:46

by Vladimir Oltean

[permalink] [raw]
Subject: [PATCH net-next 9/9] net: dsa: felix: add support for changing DSA master

Changing the DSA master means different things depending on the tagging
protocol in use.

For NPI mode ("ocelot" and "seville"), there is a single port which can
be configured as NPI, but DSA only permits changing the CPU port
affinity of user ports one by one. So changing a user port to a
different NPI port globally changes what the NPI port is, and breaks the
user ports still using the old one.

To address this while still permitting the change of the NPI port,
require that the user ports which are still affine to the old NPI port
are down, and cannot be brought up until they are all affine to the same
NPI port.

The tag_8021q mode ("ocelot-8021q") is more flexible, in that each user
port can be freely assigned to one CPU port or to the other. This works
by filtering host addresses towards both tag_8021q CPU ports, and then
restricting the forwarding from a certain user port only to one of the
two tag_8021q CPU ports.

Additionally, the 2 tag_8021q CPU ports can be placed in a LAG. This
works by enabling forwarding via PGID_SRC from a certain user port
towards the logical port ID containing both tag_8021q CPU ports, but
then restricting forwarding per packet, via the LAG hash codes in
PGID_AGGR, to either one or the other.

When we change the DSA master to a LAG device, DSA guarantees us that
the LAG has at least one lower interface as a physical DSA master.
But DSA masters can come and go as lowers of that LAG, and
ds->ops->port_change_master() will not get called, because the DSA
master is still the same (the LAG). So we need to hook into the
ds->ops->port_lag_{join,leave} calls on the CPU ports and update the
logical port ID of the LAG that user ports are assigned to.

Signed-off-by: Vladimir Oltean <[email protected]>
---
drivers/net/dsa/ocelot/felix.c | 117 ++++++++++++++++++++++++++++-
drivers/net/dsa/ocelot/felix.h | 3 +
drivers/net/ethernet/mscc/ocelot.c | 3 +-
include/soc/mscc/ocelot.h | 1 +
4 files changed, 121 insertions(+), 3 deletions(-)

diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c
index ee19ed96f284..bf9efb4aec6b 100644
--- a/drivers/net/dsa/ocelot/felix.c
+++ b/drivers/net/dsa/ocelot/felix.c
@@ -42,6 +42,25 @@ static struct net_device *felix_classify_db(struct dsa_db db)
}
}

+static int felix_cpu_port_for_master(struct dsa_switch *ds,
+ struct net_device *master)
+{
+ struct ocelot *ocelot = ds->priv;
+ struct dsa_port *cpu_dp;
+ int lag;
+
+ if (netif_is_lag_master(master)) {
+ mutex_lock(&ocelot->fwd_domain_lock);
+ lag = ocelot_bond_get_id(ocelot, master);
+ mutex_unlock(&ocelot->fwd_domain_lock);
+
+ return lag;
+ }
+
+ cpu_dp = master->dsa_ptr;
+ return cpu_dp->index;
+}
+
/* Set up VCAP ES0 rules for pushing a tag_8021q VLAN towards the CPU such that
* the tagger can perform RX source port identification.
*/
@@ -422,6 +441,39 @@ static unsigned long felix_tag_npi_get_host_fwd_mask(struct dsa_switch *ds)
return BIT(ocelot->num_phys_ports);
}

+static int felix_tag_npi_change_master(struct dsa_switch *ds, int port,
+ struct net_device *master,
+ struct netlink_ext_ack *extack)
+{
+ struct dsa_port *dp = dsa_to_port(ds, port), *other_dp;
+ struct ocelot *ocelot = ds->priv;
+
+ if (netif_is_lag_master(master)) {
+ NL_SET_ERR_MSG_MOD(extack, "LAG DSA master only supported using ocelot-8021q");
+ return -EOPNOTSUPP;
+ }
+
+ /* Changing the NPI port breaks user ports still assigned to the old
+ * one, so only allow it while they're down, and don't allow them to
+ * come back up until they're all changed to the new one.
+ */
+ dsa_switch_for_each_user_port(other_dp, ds) {
+ struct net_device *slave = other_dp->slave;
+
+ if (other_dp != dp && (slave->flags & IFF_UP) &&
+ dsa_port_to_master(other_dp) != master) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "Cannot change while old master still has users");
+ return -EOPNOTSUPP;
+ }
+ }
+
+ felix_npi_port_deinit(ocelot, ocelot->npi);
+ felix_npi_port_init(ocelot, felix_cpu_port_for_master(ds, master));
+
+ return 0;
+}
+
/* Alternatively to using the NPI functionality, that same hardware MAC
* connected internally to the enetc or fman DSA master can be configured to
* use the software-defined tag_8021q frame format. As far as the hardware is
@@ -433,6 +485,7 @@ static const struct felix_tag_proto_ops felix_tag_npi_proto_ops = {
.setup = felix_tag_npi_setup,
.teardown = felix_tag_npi_teardown,
.get_host_fwd_mask = felix_tag_npi_get_host_fwd_mask,
+ .change_master = felix_tag_npi_change_master,
};

static int felix_tag_8021q_setup(struct dsa_switch *ds)
@@ -507,10 +560,24 @@ static unsigned long felix_tag_8021q_get_host_fwd_mask(struct dsa_switch *ds)
return dsa_cpu_ports(ds);
}

+static int felix_tag_8021q_change_master(struct dsa_switch *ds, int port,
+ struct net_device *master,
+ struct netlink_ext_ack *extack)
+{
+ int cpu = felix_cpu_port_for_master(ds, master);
+ struct ocelot *ocelot = ds->priv;
+
+ ocelot_port_unassign_dsa_8021q_cpu(ocelot, port);
+ ocelot_port_assign_dsa_8021q_cpu(ocelot, port, cpu);
+
+ return felix_update_trapping_destinations(ds, true);
+}
+
static const struct felix_tag_proto_ops felix_tag_8021q_proto_ops = {
.setup = felix_tag_8021q_setup,
.teardown = felix_tag_8021q_teardown,
.get_host_fwd_mask = felix_tag_8021q_get_host_fwd_mask,
+ .change_master = felix_tag_8021q_change_master,
};

static void felix_set_host_flood(struct dsa_switch *ds, unsigned long mask,
@@ -673,6 +740,16 @@ static void felix_port_set_host_flood(struct dsa_switch *ds, int port,
!!felix->host_flood_mc_mask, true);
}

+static int felix_port_change_master(struct dsa_switch *ds, int port,
+ struct net_device *master,
+ struct netlink_ext_ack *extack)
+{
+ struct ocelot *ocelot = ds->priv;
+ struct felix *felix = ocelot_to_felix(ocelot);
+
+ return felix->tag_proto_ops->change_master(ds, port, master, extack);
+}
+
static int felix_set_ageing_time(struct dsa_switch *ds,
unsigned int ageing_time)
{
@@ -864,8 +941,17 @@ static int felix_lag_join(struct dsa_switch *ds, int port,
struct netdev_lag_upper_info *info)
{
struct ocelot *ocelot = ds->priv;
+ int err;

- return ocelot_port_lag_join(ocelot, port, lag.dev, info);
+ err = ocelot_port_lag_join(ocelot, port, lag.dev, info);
+ if (err)
+ return err;
+
+ /* Update the logical LAG port that serves as tag_8021q CPU port */
+ if (!dsa_is_cpu_port(ds, port))
+ return 0;
+
+ return felix_port_change_master(ds, port, lag.dev, NULL);
}

static int felix_lag_leave(struct dsa_switch *ds, int port,
@@ -875,7 +961,11 @@ static int felix_lag_leave(struct dsa_switch *ds, int port,

ocelot_port_lag_leave(ocelot, port, lag.dev);

- return 0;
+ /* Update the logical LAG port that serves as tag_8021q CPU port */
+ if (!dsa_is_cpu_port(ds, port))
+ return 0;
+
+ return felix_port_change_master(ds, port, lag.dev, NULL);
}

static int felix_lag_change(struct dsa_switch *ds, int port)
@@ -1013,6 +1103,27 @@ static void felix_phylink_mac_link_up(struct dsa_switch *ds, int port,
felix->info->port_sched_speed_set(ocelot, port, speed);
}

+static int felix_port_enable(struct dsa_switch *ds, int port,
+ struct phy_device *phydev)
+{
+ struct dsa_port *dp = dsa_to_port(ds, port);
+ struct ocelot *ocelot = ds->priv;
+
+ if (!dsa_port_is_user(dp))
+ return 0;
+
+ if (ocelot->npi >= 0) {
+ struct net_device *master = dsa_port_to_master(dp);
+
+ if (felix_cpu_port_for_master(ds, master) != ocelot->npi) {
+ dev_err(ds->dev, "Multiple masters are not allowed\n");
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
static void felix_port_qos_map_init(struct ocelot *ocelot, int port)
{
int i;
@@ -1857,6 +1968,7 @@ const struct dsa_switch_ops felix_switch_ops = {
.phylink_mac_select_pcs = felix_phylink_mac_select_pcs,
.phylink_mac_link_down = felix_phylink_mac_link_down,
.phylink_mac_link_up = felix_phylink_mac_link_up,
+ .port_enable = felix_port_enable,
.port_fast_age = felix_port_fast_age,
.port_fdb_dump = felix_fdb_dump,
.port_fdb_add = felix_fdb_add,
@@ -1912,6 +2024,7 @@ const struct dsa_switch_ops felix_switch_ops = {
.port_add_dscp_prio = felix_port_add_dscp_prio,
.port_del_dscp_prio = felix_port_del_dscp_prio,
.port_set_host_flood = felix_port_set_host_flood,
+ .port_change_master = felix_port_change_master,
};

struct net_device *felix_port_to_netdev(struct ocelot *ocelot, int port)
diff --git a/drivers/net/dsa/ocelot/felix.h b/drivers/net/dsa/ocelot/felix.h
index deb8dde1fc19..e4fd5eef57a0 100644
--- a/drivers/net/dsa/ocelot/felix.h
+++ b/drivers/net/dsa/ocelot/felix.h
@@ -71,6 +71,9 @@ struct felix_tag_proto_ops {
int (*setup)(struct dsa_switch *ds);
void (*teardown)(struct dsa_switch *ds);
unsigned long (*get_host_fwd_mask)(struct dsa_switch *ds);
+ int (*change_master)(struct dsa_switch *ds, int port,
+ struct net_device *master,
+ struct netlink_ext_ack *extack);
};

extern const struct dsa_switch_ops felix_switch_ops;
diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index dddaffdaad9a..9ffe5db90281 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -2054,7 +2054,7 @@ static u32 ocelot_get_bond_mask(struct ocelot *ocelot, struct net_device *bond)
/* The logical port number of a LAG is equal to the lowest numbered physical
* port ID present in that LAG. It may change if that port ever leaves the LAG.
*/
-static int ocelot_bond_get_id(struct ocelot *ocelot, struct net_device *bond)
+int ocelot_bond_get_id(struct ocelot *ocelot, struct net_device *bond)
{
int bond_mask = ocelot_get_bond_mask(ocelot, bond);

@@ -2063,6 +2063,7 @@ static int ocelot_bond_get_id(struct ocelot *ocelot, struct net_device *bond)

return __ffs(bond_mask);
}
+EXPORT_SYMBOL_GPL(ocelot_bond_get_id);

/* Returns the mask of user ports assigned to this DSA tag_8021q CPU port.
* Note that when CPU ports are in a LAG, the user ports are assigned to the
diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
index 2a7e18ee5577..e90ba089d5ba 100644
--- a/include/soc/mscc/ocelot.h
+++ b/include/soc/mscc/ocelot.h
@@ -1105,6 +1105,7 @@ int ocelot_port_lag_join(struct ocelot *ocelot, int port,
void ocelot_port_lag_leave(struct ocelot *ocelot, int port,
struct net_device *bond);
void ocelot_port_lag_change(struct ocelot *ocelot, int port, bool lag_tx_active);
+int ocelot_bond_get_id(struct ocelot *ocelot, struct net_device *bond);

int ocelot_devlink_sb_register(struct ocelot *ocelot);
void ocelot_devlink_sb_unregister(struct ocelot *ocelot);
--
2.34.1

2022-08-30 20:14:33

by Vladimir Oltean

[permalink] [raw]
Subject: [PATCH net-next 6/9] net: dsa: suppress device links to LAG DSA masters

These don't work (print a harmless error about the operation failing)
and make little sense to have anyway, because when a LAG DSA master goes
away, we will introduce logic to move our CPU port back to the first
physical DSA master. So suppress these device links in preparation for
adding support for LAG DSA masters.

Signed-off-by: Vladimir Oltean <[email protected]>
---
net/dsa/master.c | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/net/dsa/master.c b/net/dsa/master.c
index 99d773b24223..2176c14b97a8 100644
--- a/net/dsa/master.c
+++ b/net/dsa/master.c
@@ -364,12 +364,14 @@ int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp)
mtu = ETH_DATA_LEN + dsa_tag_protocol_overhead(tag_ops);

/* The DSA master must use SET_NETDEV_DEV for this to work. */
- consumer_link = device_link_add(ds->dev, dev->dev.parent,
- DL_FLAG_AUTOREMOVE_CONSUMER);
- if (!consumer_link)
- netdev_err(dev,
- "Failed to create a device link to DSA switch %s\n",
- dev_name(ds->dev));
+ if (!netif_is_lag_master(dev)) {
+ consumer_link = device_link_add(ds->dev, dev->dev.parent,
+ DL_FLAG_AUTOREMOVE_CONSUMER);
+ if (!consumer_link)
+ netdev_err(dev,
+ "Failed to create a device link to DSA switch %s\n",
+ dev_name(ds->dev));
+ }

/* The switch driver may not implement ->port_change_mtu(), case in
* which dsa_slave_change_mtu() will not update the master MTU either,
--
2.34.1

2022-08-30 20:14:39

by Vladimir Oltean

[permalink] [raw]
Subject: [PATCH net-next 8/9] docs: net: dsa: update information about multiple CPU ports

DSA now supports multiple CPU ports, explain the use cases that are
covered, the new UAPI, the permitted degrees of freedom, the driver API,
and remove some old "hanging fruits".

Signed-off-by: Vladimir Oltean <[email protected]>
---
.../networking/dsa/configuration.rst | 84 +++++++++++++++++++
Documentation/networking/dsa/dsa.rst | 38 +++++++--
2 files changed, 116 insertions(+), 6 deletions(-)

diff --git a/Documentation/networking/dsa/configuration.rst b/Documentation/networking/dsa/configuration.rst
index 2b08f1a772d3..5c49c1eef8bb 100644
--- a/Documentation/networking/dsa/configuration.rst
+++ b/Documentation/networking/dsa/configuration.rst
@@ -49,6 +49,9 @@ In this documentation the following Ethernet interfaces are used:
*eth0*
the master interface

+*eth1*
+ another master interface, by default unused
+
*lan1*
a slave interface

@@ -360,3 +363,84 @@ the ``self`` flag) has been removed. This results in the following changes:

Script writers are therefore encouraged to use the ``master static`` set of
flags when working with bridge FDB entries on DSA switch interfaces.
+
+Affinity of user ports to CPU ports
+-----------------------------------
+
+Typically, DSA switches are attached to the host via a single Ethernet
+interface, but in cases where the switch chip is discrete, the hardware design
+may permit the use of 2 or more ports connected to the host, for an increase in
+termination throughput.
+
+DSA can make use of multiple CPU ports in two ways. First, it is possible to
+statically assign the termination traffic associated with a certain user port
+to be processed by a certain CPU port. This way, user space can implement
+custom policies of static load balancing between user ports, by spreading the
+affinities according to the available CPU ports.
+
+Secondly, it is possible to perform load balancing between CPU ports on a per
+packet basis, rather than statically assigning user ports to CPU ports.
+This can be achieved by placing the DSA masters under a LAG interface (bonding
+or team). DSA monitors this operation and creates a mirror of this software LAG
+on the CPU ports facing the physical DSA masters that constitute the LAG slave
+devices.
+
+To make use of multiple CPU ports, the firmware (device tree) description of
+the switch must mark all the links between CPU ports and their DSA masters
+using the ``ethernet`` reference/phandle. At startup, only a single CPU port
+and DSA master will be used - the numerically first port from the firmware
+description which has an ``ethernet`` property. It is up to the user to
+configure the system for the switch to use other masters.
+
+DSA uses the ``rtnl_link_ops`` mechanism (with a "dsa" ``kind``) to allow
+changing the DSA master of a user port. The ``IFLA_DSA_MASTER`` u32 netlink
+attribute contains the ifindex of the master device that handles each slave
+device. The DSA master must be a valid candidate based on firmware node
+information, or a LAG interface which contains only slaves which are valid
+candidates.
+
+Using iproute2, the following manipulations are possible:
+
+ .. code-block:: sh
+
+ # See the DSA master in current use
+ ip -d link show dev swp0
+ (...)
+ dsa master eth0
+
+ # Static CPU port distribution
+ ip link set swp0 type dsa master eth1
+ ip link set swp1 type dsa master eth0
+ ip link set swp2 type dsa master eth1
+ ip link set swp3 type dsa master eth0
+
+ # CPU ports in LAG
+ ip link add bond0 type bond mode balance-xor && ip link set bond0 up
+ ip link set eth0 down && ip link set eth0 master bond0
+ ip link set eth1 down && ip link set eth1 master bond0
+ ip -d link show dev swp0
+ (...)
+ dsa master bond0
+
+Notice that in the case of CPU ports under a LAG, the use of the
+``IFLA_DSA_MASTER`` netlink attribute is not strictly needed, but rather, DSA
+reacts to the ``IFLA_MASTER`` attribute change of its present master (``eth0``)
+and migrates all user ports to the new upper of ``eth0``, ``bond0``. Similarly,
+when ``bond0`` is destroyed using ``RTM_DELLINK``, DSA migrates the user ports
+that were assigned to this interface to the first physical DSA master which is
+eligible, based on the firmware description (it effectively reverts to the
+startup configuration).
+
+In a setup with more than 2 physical CPU ports, it is therefore possible to mix
+static user to CPU port assignment with LAG between DSA masters. It is not
+possible to statically assign a user port towards a DSA master that has any
+upper interfaces (this includes LAG devices - the master must always be the LAG
+in this case).
+
+Live changing of the DSA master (and thus CPU port) affinity of a user port is
+permitted, in order to allow dynamic redistribution in response to traffic.
+
+Physical DSA masters are allowed to join and leave at any time a LAG interface
+used as a DSA master; however, DSA will reject a LAG interface as a valid
+candidate for being a DSA master unless it has at least one physical DSA master
+as a slave device.
diff --git a/Documentation/networking/dsa/dsa.rst b/Documentation/networking/dsa/dsa.rst
index d742ba6bd211..a94ddf83348a 100644
--- a/Documentation/networking/dsa/dsa.rst
+++ b/Documentation/networking/dsa/dsa.rst
@@ -303,6 +303,20 @@ These frames are then queued for transmission using the master network device
Ethernet switch will be able to process these incoming frames from the
management interface and deliver them to the physical switch port.

+When using multiple CPU ports, it is possible to stack a LAG (bonding/team)
+device between the DSA slave devices and the physical DSA masters. The LAG
+device is thus also a DSA master, but the LAG slave devices continue to be DSA
+masters as well (just with no user port assigned to them; this is needed for
+recovery in case the LAG DSA master disappears). Thus, the data path of the LAG
+DSA master is used asymmetrically. On RX, the ``ETH_P_XDSA`` handler, which
+calls ``dsa_switch_rcv()``, is invoked early (on the physical DSA master;
+LAG slave). Therefore, the RX data path of the LAG DSA master is not used.
+On the other hand, TX takes place linearly: ``dsa_slave_xmit`` calls
+``dsa_enqueue_skb``, which calls ``dev_queue_xmit`` towards the LAG DSA master.
+The latter calls ``dev_queue_xmit`` towards one physical DSA master or the
+other, and in both cases, the packet exits the system through a hardware path
+towards the switch.
+
Graphical representation
------------------------

@@ -629,6 +643,24 @@ Switch configuration
PHY cannot be found. In this case, probing of the DSA switch continues
without that particular port.

+- ``port_change_master``: method through which the affinity (association used
+ for traffic termination purposes) between a user port and a CPU port can be
+ changed. By default all user ports from a tree are assigned to the first
+ available CPU port that makes sense for them (most of the times this means
+ the user ports of a tree are all assigned to the same CPU port, except for H
+ topologies as described in commit 2c0b03258b8b). The ``port`` argument
+ represents the index of the user port, and the ``master`` argument represents
+ the new DSA master ``net_device``. The CPU port associated with the new
+ master can be retrieved by looking at ``struct dsa_port *cpu_dp =
+ master->dsa_ptr``. Additionally, the master can also be a LAG device where
+ all the slave devices are physical DSA masters. LAG DSA masters also have a
+ valid ``master->dsa_ptr`` pointer, however this is not unique, but rather a
+ duplicate of the first physical DSA master's (LAG slave) ``dsa_ptr``. In case
+ of a LAG DSA master, a further call to ``port_lag_join`` will be emitted
+ separately for the physical CPU ports associated with the physical DSA
+ masters, requesting them to create a hardware LAG associated with the LAG
+ interface.
+
PHY devices and link management
-------------------------------

@@ -1095,9 +1127,3 @@ capable hardware, but does not enforce a strict switch device driver model. On
the other DSA enforces a fairly strict device driver model, and deals with most
of the switch specific. At some point we should envision a merger between these
two subsystems and get the best of both worlds.
-
-Other hanging fruits
---------------------
-
-- allowing more than one CPU/management interface:
- http://comments.gmane.org/gmane.linux.network/365657
--
2.34.1

2022-08-30 20:30:14

by Vladimir Oltean

[permalink] [raw]
Subject: [PATCH net-next 2/9] net: dsa: introduce dsa_port_get_master()

There is a desire to support for DSA masters in a LAG.

That configuration is intended to work by simply enslaving the master to
a bonding/team device. But the physical DSA master (the LAG slave) still
has a dev->dsa_ptr, and that cpu_dp still corresponds to the physical
CPU port.

However, we would like to be able to retrieve the LAG that's the upper
of the physical DSA master. In preparation for that, introduce a helper
called dsa_port_get_master() that replaces all occurrences of the
dp->cpu_dp->master pattern. The distinction between LAG and non-LAG will
be made later within the helper itself.

Signed-off-by: Vladimir Oltean <[email protected]>
Reviewed-by: Florian Fainelli <[email protected]>
---
drivers/net/dsa/bcm_sf2.c | 4 +--
drivers/net/dsa/bcm_sf2_cfp.c | 4 +--
drivers/net/dsa/lan9303-core.c | 4 +--
.../net/ethernet/mediatek/mtk_ppe_offload.c | 2 +-
include/net/dsa.h | 5 ++++
net/dsa/dsa2.c | 8 +++---
net/dsa/dsa_priv.h | 2 +-
net/dsa/port.c | 28 +++++++++----------
net/dsa/slave.c | 11 ++++----
net/dsa/tag_8021q.c | 4 +--
10 files changed, 38 insertions(+), 34 deletions(-)

diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index 572f7450b527..6507663f35e5 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -983,7 +983,7 @@ static int bcm_sf2_sw_resume(struct dsa_switch *ds)
static void bcm_sf2_sw_get_wol(struct dsa_switch *ds, int port,
struct ethtool_wolinfo *wol)
{
- struct net_device *p = dsa_to_port(ds, port)->cpu_dp->master;
+ struct net_device *p = dsa_port_to_master(dsa_to_port(ds, port));
struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
struct ethtool_wolinfo pwol = { };

@@ -1007,7 +1007,7 @@ static void bcm_sf2_sw_get_wol(struct dsa_switch *ds, int port,
static int bcm_sf2_sw_set_wol(struct dsa_switch *ds, int port,
struct ethtool_wolinfo *wol)
{
- struct net_device *p = dsa_to_port(ds, port)->cpu_dp->master;
+ struct net_device *p = dsa_port_to_master(dsa_to_port(ds, port));
struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
s8 cpu_port = dsa_to_port(ds, port)->cpu_dp->index;
struct ethtool_wolinfo pwol = { };
diff --git a/drivers/net/dsa/bcm_sf2_cfp.c b/drivers/net/dsa/bcm_sf2_cfp.c
index edbe5e7f1cb6..90636ae3db98 100644
--- a/drivers/net/dsa/bcm_sf2_cfp.c
+++ b/drivers/net/dsa/bcm_sf2_cfp.c
@@ -1102,7 +1102,7 @@ static int bcm_sf2_cfp_rule_get_all(struct bcm_sf2_priv *priv,
int bcm_sf2_get_rxnfc(struct dsa_switch *ds, int port,
struct ethtool_rxnfc *nfc, u32 *rule_locs)
{
- struct net_device *p = dsa_to_port(ds, port)->cpu_dp->master;
+ struct net_device *p = dsa_port_to_master(dsa_to_port(ds, port));
struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
int ret = 0;

@@ -1145,7 +1145,7 @@ int bcm_sf2_get_rxnfc(struct dsa_switch *ds, int port,
int bcm_sf2_set_rxnfc(struct dsa_switch *ds, int port,
struct ethtool_rxnfc *nfc)
{
- struct net_device *p = dsa_to_port(ds, port)->cpu_dp->master;
+ struct net_device *p = dsa_port_to_master(dsa_to_port(ds, port));
struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
int ret = 0;

diff --git a/drivers/net/dsa/lan9303-core.c b/drivers/net/dsa/lan9303-core.c
index e03ff1f267bb..181e082b0919 100644
--- a/drivers/net/dsa/lan9303-core.c
+++ b/drivers/net/dsa/lan9303-core.c
@@ -1090,7 +1090,7 @@ static int lan9303_port_enable(struct dsa_switch *ds, int port,
if (!dsa_port_is_user(dp))
return 0;

- vlan_vid_add(dp->cpu_dp->master, htons(ETH_P_8021Q), port);
+ vlan_vid_add(dsa_port_to_master(dp), htons(ETH_P_8021Q), port);

return lan9303_enable_processing_port(chip, port);
}
@@ -1103,7 +1103,7 @@ static void lan9303_port_disable(struct dsa_switch *ds, int port)
if (!dsa_port_is_user(dp))
return;

- vlan_vid_del(dp->cpu_dp->master, htons(ETH_P_8021Q), port);
+ vlan_vid_del(dsa_port_to_master(dp), htons(ETH_P_8021Q), port);

lan9303_disable_processing_port(chip, port);
lan9303_phy_write(ds, chip->phy_addr_base + port, MII_BMCR, BMCR_PDOWN);
diff --git a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
index 25dc3c3aa31d..5a1fc4bcd7a5 100644
--- a/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
+++ b/drivers/net/ethernet/mediatek/mtk_ppe_offload.c
@@ -173,7 +173,7 @@ mtk_flow_get_dsa_port(struct net_device **dev)
if (dp->cpu_dp->tag_ops->proto != DSA_TAG_PROTO_MTK)
return -ENODEV;

- *dev = dp->cpu_dp->master;
+ *dev = dsa_port_to_master(dp);

return dp->index;
#else
diff --git a/include/net/dsa.h b/include/net/dsa.h
index f2ce12860546..23eac1bda843 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -718,6 +718,11 @@ static inline bool dsa_port_offloads_lag(struct dsa_port *dp,
return dsa_port_lag_dev_get(dp) == lag->dev;
}

+static inline struct net_device *dsa_port_to_master(const struct dsa_port *dp)
+{
+ return dp->cpu_dp->master;
+}
+
static inline
struct net_device *dsa_port_to_bridge_port(const struct dsa_port *dp)
{
diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index ed56c7a554b8..f1f96e2e56aa 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -1263,11 +1263,11 @@ int dsa_tree_change_tag_proto(struct dsa_switch_tree *dst,
* attempts to change the tagging protocol. If we ever lift the IFF_UP
* restriction, there needs to be another mutex which serializes this.
*/
- list_for_each_entry(dp, &dst->ports, list) {
- if (dsa_port_is_cpu(dp) && (dp->master->flags & IFF_UP))
+ dsa_tree_for_each_user_port(dp, dst) {
+ if (dsa_port_to_master(dp)->flags & IFF_UP)
goto out_unlock;

- if (dsa_port_is_user(dp) && (dp->slave->flags & IFF_UP))
+ if (dp->slave->flags & IFF_UP)
goto out_unlock;
}

@@ -1797,7 +1797,7 @@ void dsa_switch_shutdown(struct dsa_switch *ds)
rtnl_lock();

dsa_switch_for_each_user_port(dp, ds) {
- master = dp->cpu_dp->master;
+ master = dsa_port_to_master(dp);
slave_dev = dp->slave;

netdev_upper_dev_unlink(master, slave_dev);
diff --git a/net/dsa/dsa_priv.h b/net/dsa/dsa_priv.h
index 614fbba8fe39..c48c5c8ba790 100644
--- a/net/dsa/dsa_priv.h
+++ b/net/dsa/dsa_priv.h
@@ -322,7 +322,7 @@ dsa_slave_to_master(const struct net_device *dev)
{
struct dsa_port *dp = dsa_slave_to_port(dev);

- return dp->cpu_dp->master;
+ return dsa_port_to_master(dp);
}

/* If under a bridge with vlan_filtering=0, make sure to send pvid-tagged
diff --git a/net/dsa/port.c b/net/dsa/port.c
index 7afc35db0c29..4183e60db4f9 100644
--- a/net/dsa/port.c
+++ b/net/dsa/port.c
@@ -1026,7 +1026,7 @@ int dsa_port_standalone_host_fdb_add(struct dsa_port *dp,
int dsa_port_bridge_host_fdb_add(struct dsa_port *dp,
const unsigned char *addr, u16 vid)
{
- struct dsa_port *cpu_dp = dp->cpu_dp;
+ struct net_device *master = dsa_port_to_master(dp);
struct dsa_db db = {
.type = DSA_DB_BRIDGE,
.bridge = *dp->bridge,
@@ -1037,8 +1037,8 @@ int dsa_port_bridge_host_fdb_add(struct dsa_port *dp,
* requires rtnl_lock(), since we can't guarantee that is held here,
* and we can't take it either.
*/
- if (cpu_dp->master->priv_flags & IFF_UNICAST_FLT) {
- err = dev_uc_add(cpu_dp->master, addr);
+ if (master->priv_flags & IFF_UNICAST_FLT) {
+ err = dev_uc_add(master, addr);
if (err)
return err;
}
@@ -1077,15 +1077,15 @@ int dsa_port_standalone_host_fdb_del(struct dsa_port *dp,
int dsa_port_bridge_host_fdb_del(struct dsa_port *dp,
const unsigned char *addr, u16 vid)
{
- struct dsa_port *cpu_dp = dp->cpu_dp;
+ struct net_device *master = dsa_port_to_master(dp);
struct dsa_db db = {
.type = DSA_DB_BRIDGE,
.bridge = *dp->bridge,
};
int err;

- if (cpu_dp->master->priv_flags & IFF_UNICAST_FLT) {
- err = dev_uc_del(cpu_dp->master, addr);
+ if (master->priv_flags & IFF_UNICAST_FLT) {
+ err = dev_uc_del(master, addr);
if (err)
return err;
}
@@ -1208,14 +1208,14 @@ int dsa_port_standalone_host_mdb_add(const struct dsa_port *dp,
int dsa_port_bridge_host_mdb_add(const struct dsa_port *dp,
const struct switchdev_obj_port_mdb *mdb)
{
- struct dsa_port *cpu_dp = dp->cpu_dp;
+ struct net_device *master = dsa_port_to_master(dp);
struct dsa_db db = {
.type = DSA_DB_BRIDGE,
.bridge = *dp->bridge,
};
int err;

- err = dev_mc_add(cpu_dp->master, mdb->addr);
+ err = dev_mc_add(master, mdb->addr);
if (err)
return err;

@@ -1252,14 +1252,14 @@ int dsa_port_standalone_host_mdb_del(const struct dsa_port *dp,
int dsa_port_bridge_host_mdb_del(const struct dsa_port *dp,
const struct switchdev_obj_port_mdb *mdb)
{
- struct dsa_port *cpu_dp = dp->cpu_dp;
+ struct net_device *master = dsa_port_to_master(dp);
struct dsa_db db = {
.type = DSA_DB_BRIDGE,
.bridge = *dp->bridge,
};
int err;

- err = dev_mc_del(cpu_dp->master, mdb->addr);
+ err = dev_mc_del(master, mdb->addr);
if (err)
return err;

@@ -1294,19 +1294,19 @@ int dsa_port_host_vlan_add(struct dsa_port *dp,
const struct switchdev_obj_port_vlan *vlan,
struct netlink_ext_ack *extack)
{
+ struct net_device *master = dsa_port_to_master(dp);
struct dsa_notifier_vlan_info info = {
.dp = dp,
.vlan = vlan,
.extack = extack,
};
- struct dsa_port *cpu_dp = dp->cpu_dp;
int err;

err = dsa_port_notify(dp, DSA_NOTIFIER_HOST_VLAN_ADD, &info);
if (err && err != -EOPNOTSUPP)
return err;

- vlan_vid_add(cpu_dp->master, htons(ETH_P_8021Q), vlan->vid);
+ vlan_vid_add(master, htons(ETH_P_8021Q), vlan->vid);

return err;
}
@@ -1314,18 +1314,18 @@ int dsa_port_host_vlan_add(struct dsa_port *dp,
int dsa_port_host_vlan_del(struct dsa_port *dp,
const struct switchdev_obj_port_vlan *vlan)
{
+ struct net_device *master = dsa_port_to_master(dp);
struct dsa_notifier_vlan_info info = {
.dp = dp,
.vlan = vlan,
};
- struct dsa_port *cpu_dp = dp->cpu_dp;
int err;

err = dsa_port_notify(dp, DSA_NOTIFIER_HOST_VLAN_DEL, &info);
if (err && err != -EOPNOTSUPP)
return err;

- vlan_vid_del(cpu_dp->master, htons(ETH_P_8021Q), vlan->vid);
+ vlan_vid_del(master, htons(ETH_P_8021Q), vlan->vid);

return err;
}
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 345106b1ed78..55094b94a5ae 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -1503,8 +1503,7 @@ static int dsa_slave_setup_tc_block(struct net_device *dev,
static int dsa_slave_setup_ft_block(struct dsa_switch *ds, int port,
void *type_data)
{
- struct dsa_port *cpu_dp = dsa_to_port(ds, port)->cpu_dp;
- struct net_device *master = cpu_dp->master;
+ struct net_device *master = dsa_port_to_master(dsa_to_port(ds, port));

if (!master->netdev_ops->ndo_setup_tc)
return -EOPNOTSUPP;
@@ -2147,13 +2146,14 @@ static int dsa_slave_fill_forward_path(struct net_device_path_ctx *ctx,
struct net_device_path *path)
{
struct dsa_port *dp = dsa_slave_to_port(ctx->dev);
+ struct net_device *master = dsa_port_to_master(dp);
struct dsa_port *cpu_dp = dp->cpu_dp;

path->dev = ctx->dev;
path->type = DEV_PATH_DSA;
path->dsa.proto = cpu_dp->tag_ops->proto;
path->dsa.port = dp->index;
- ctx->dev = cpu_dp->master;
+ ctx->dev = master;

return 0;
}
@@ -2271,9 +2271,9 @@ static int dsa_slave_phy_setup(struct net_device *slave_dev)
void dsa_slave_setup_tagger(struct net_device *slave)
{
struct dsa_port *dp = dsa_slave_to_port(slave);
+ struct net_device *master = dsa_port_to_master(dp);
struct dsa_slave_priv *p = netdev_priv(slave);
const struct dsa_port *cpu_dp = dp->cpu_dp;
- struct net_device *master = cpu_dp->master;
const struct dsa_switch *ds = dp->ds;

slave->needed_headroom = cpu_dp->tag_ops->needed_headroom;
@@ -2330,8 +2330,7 @@ int dsa_slave_resume(struct net_device *slave_dev)

int dsa_slave_create(struct dsa_port *port)
{
- const struct dsa_port *cpu_dp = port->cpu_dp;
- struct net_device *master = cpu_dp->master;
+ struct net_device *master = dsa_port_to_master(port);
struct dsa_switch *ds = port->ds;
const char *name = port->name;
struct net_device *slave_dev;
diff --git a/net/dsa/tag_8021q.c b/net/dsa/tag_8021q.c
index b5f80bc45ceb..34e5ec5d3e23 100644
--- a/net/dsa/tag_8021q.c
+++ b/net/dsa/tag_8021q.c
@@ -330,7 +330,7 @@ static int dsa_tag_8021q_port_setup(struct dsa_switch *ds, int port)
if (!dsa_port_is_user(dp))
return 0;

- master = dp->cpu_dp->master;
+ master = dsa_port_to_master(dp);

err = dsa_port_tag_8021q_vlan_add(dp, vid, false);
if (err) {
@@ -359,7 +359,7 @@ static void dsa_tag_8021q_port_teardown(struct dsa_switch *ds, int port)
if (!dsa_port_is_user(dp))
return;

- master = dp->cpu_dp->master;
+ master = dsa_port_to_master(dp);

dsa_port_tag_8021q_vlan_del(dp, vid, false);

--
2.34.1

2022-08-30 20:59:12

by Vladimir Oltean

[permalink] [raw]
Subject: [PATCH net-next 1/9] net: introduce iterators over synced hw addresses

Some network drivers use __dev_mc_sync()/__dev_uc_sync() and therefore
program the hardware only with addresses with a non-zero sync_cnt.

Some of the above drivers also need to save/restore the address
filtering lists when certain events happen, and they need to walk
through the struct net_device :: uc and struct net_device :: mc lists.
But these lists contain unsynced addresses too.

To keep the appearance of an elementary form of data encapsulation,
provide iterators through these lists that only look at entries with a
non-zero sync_cnt, instead of filtering entries out from device drivers.

Signed-off-by: Vladimir Oltean <[email protected]>
Reviewed-by: Florian Fainelli <[email protected]>
---
include/linux/netdevice.h | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index eec35f9b6616..2979293b966c 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -253,11 +253,17 @@ struct netdev_hw_addr_list {
#define netdev_uc_empty(dev) netdev_hw_addr_list_empty(&(dev)->uc)
#define netdev_for_each_uc_addr(ha, dev) \
netdev_hw_addr_list_for_each(ha, &(dev)->uc)
+#define netdev_for_each_synced_uc_addr(_ha, _dev) \
+ netdev_for_each_uc_addr((_ha), (_dev)) \
+ if ((_ha)->sync_cnt)

#define netdev_mc_count(dev) netdev_hw_addr_list_count(&(dev)->mc)
#define netdev_mc_empty(dev) netdev_hw_addr_list_empty(&(dev)->mc)
#define netdev_for_each_mc_addr(ha, dev) \
netdev_hw_addr_list_for_each(ha, &(dev)->mc)
+#define netdev_for_each_synced_mc_addr(_ha, _dev) \
+ netdev_for_each_mc_addr((_ha), (_dev)) \
+ if ((_ha)->sync_cnt)

struct hh_cache {
unsigned int hh_len;
--
2.34.1

2022-08-30 21:10:37

by Vladimir Oltean

[permalink] [raw]
Subject: [PATCH net-next 4/9] net: dsa: don't keep track of admin/oper state on LAG DSA masters

We store information about the DSA master's state in
cpu_dp->master_admin_up and cpu_dp->master_oper_up, and this assumes a
bijective association between a CPU port and a DSA master.

However, when we have CPU ports in a LAG (and DSA masters in a LAG too),
the way in which we set up things is that the physical DSA masters still
have dev->dsa_ptr pointing to our cpu_dp, but the bonding/team device
itself also has its dev->dsa_ptr pointing towards one of the CPU port
structures (the first one).

So logically speaking, that first cpu_dp can't keep track of both the
physical master's admin/oper state, and of the bonding master's state.

This isn't even needed; the reason why we keep track of the DSA master's
state is to know when it is available for Ethernet-based register access.
For that use case, we don't even need LAG; we just need to decide upon
one of the physical DSA masters (if there is more than 1 available) and
use that.

This change suppresses dsa_tree_master_{admin,oper}_state_change() calls
on LAG DSA masters (which will be supported in a future change), to
allow the tracking of just physical DSA masters.

Link: https://lore.kernel.org/netdev/[email protected]/
Suggested-by: Christian Marangi <[email protected]>
Signed-off-by: Vladimir Oltean <[email protected]>
---
net/dsa/dsa2.c | 12 ++++++++++++
1 file changed, 12 insertions(+)

diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c
index 42422ddea59b..7024e2120de1 100644
--- a/net/dsa/dsa2.c
+++ b/net/dsa/dsa2.c
@@ -1326,6 +1326,12 @@ void dsa_tree_master_admin_state_change(struct dsa_switch_tree *dst,
struct dsa_port *cpu_dp = master->dsa_ptr;
bool notify = false;

+ /* Don't keep track of admin state on LAG DSA masters,
+ * but rather just of physical DSA masters
+ */
+ if (netif_is_lag_master(master))
+ return;
+
if ((dsa_port_master_is_operational(cpu_dp)) !=
(up && cpu_dp->master_oper_up))
notify = true;
@@ -1343,6 +1349,12 @@ void dsa_tree_master_oper_state_change(struct dsa_switch_tree *dst,
struct dsa_port *cpu_dp = master->dsa_ptr;
bool notify = false;

+ /* Don't keep track of oper state on LAG DSA masters,
+ * but rather just of physical DSA masters
+ */
+ if (netif_is_lag_master(master))
+ return;
+
if ((dsa_port_master_is_operational(cpu_dp)) !=
(cpu_dp->master_admin_up && up))
notify = true;
--
2.34.1

2022-09-02 10:58:02

by Vladimir Oltean

[permalink] [raw]
Subject: Re: [PATCH net-next 0/9] DSA changes for multiple CPU ports (part 4)

On Tue, Aug 30, 2022 at 10:59:23PM +0300, Vladimir Oltean wrote:
> This series represents the final part of that effort. We have:
>
> - the introduction of new UAPI in the form of IFLA_DSA_MASTER

Call for opinions: when I resend this, should I keep rtnl_link_ops,
or should I do what Marek attempted to do, and make the existing iflink
between a user port and its master writable from user space?
https://lore.kernel.org/netdev/[email protected]/

I'm not sure if we have that many more use cases for rtnl_link_ops..
at some point I was thinking we could change the way in which dsa_loop
probes, and allow dynamic creation of such interfaces using RTM_NEWLINK;
but looking closer at that, it's a bit more complicated, since we'd need
to attach dsa_loop user ports to a virtual switch, and probe all ports
at the same time rather than one by one.

2022-09-02 18:53:13

by Christian Marangi

[permalink] [raw]
Subject: Re: [PATCH net-next 0/9] DSA changes for multiple CPU ports (part 4)

On Tue, Aug 30, 2022 at 10:59:23PM +0300, Vladimir Oltean wrote:
> Those who have been following part 1:
> https://patchwork.kernel.org/project/netdevbpf/cover/[email protected]/
> part 2:
> https://patchwork.kernel.org/project/netdevbpf/cover/[email protected]/
> and part 3:
> https://patchwork.kernel.org/project/netdevbpf/cover/[email protected]/
> will know that I am trying to enable the second internal port pair from
> the NXP LS1028A Felix switch for DSA-tagged traffic via "ocelot-8021q".
>
> This series represents the final part of that effort. We have:
>
> - the introduction of new UAPI in the form of IFLA_DSA_MASTER
>
> - preparation for LAG DSA masters in terms of suppressing some
> operations for masters in the DSA core that simply don't make sense
> when those masters are a bonding/team interface
>
> - handling all the net device events that occur between DSA and a
> LAG DSA master, including migration to a different DSA master when the
> current master joins a LAG, or the LAG gets destroyed
>
> - updating documentation
>
> - adding an implementation for NXP LS1028A, where things are insanely
> complicated due to hardware limitations. We have 2 tagging protocols:
>
> * the native "ocelot" protocol (NPI port mode). This does not support
> CPU ports in a LAG, and supports a single DSA master. The DSA master
> can be changed between eno2 (2.5G) and eno3 (1G), but all ports must
> be down during the changing process, and user ports assigned to the
> old DSA master will refuse to come up if the user requests that
> during a "transient" state.
>
> * the "ocelot-8021q" software-defined protocol, where the Ethernet
> ports connected to the CPU are not actually "god mode" ports as far
> as the hardware is concerned. So here, static assignment between
> user and CPU ports is possible by editing the PGID_SRC masks for
> the port-based forwarding matrix, and "CPU ports in a LAG" simply
> means "a LAG like any other".
>
> The series was regression-tested on LS1028A using the local_termination.sh
> kselftest, in most of the possible operating modes and tagging protocols.
> I have not done a detailed performance evaluation yet, but using LAG, is
> possible to exceed the termination bandwidth of a single CPU port in an
> iperf3 test with multiple senders and multiple receivers.
>
> There was a previous RFC posted, which contains most of these changes,
> however it's so old by now that it's unlikely anyone of the reviewers
> remembers it in detail. I've applied most of the feedback requested by
> Florian and Ansuel there.
> https://lore.kernel.org/netdev/[email protected]/

Hi,
I would love to test this but for me it's a bit problematic to use a
net-next kernel. I wonder if it's possible to backport the 4 part to
older kernel or other prereq are needed. (I know backporting the 4 part
will be crazy but it's something that has to be done anyway to actually
use this on OpenWrt where we currently use 5.10 and 5.15)

Would be good to know if the 4 part require other changes to dsa core to
make a LAG implementation working. (talking for 5.15 since backporting
this to 5.10 is a nono...)

>
> Vladimir Oltean (9):
> net: introduce iterators over synced hw addresses
> net: dsa: introduce dsa_port_get_master()
> net: dsa: allow the DSA master to be seen and changed through
> rtnetlink
> net: dsa: don't keep track of admin/oper state on LAG DSA masters
> net: dsa: suppress appending ethtool stats to LAG DSA masters
> net: dsa: suppress device links to LAG DSA masters
> net: dsa: allow masters to join a LAG
> docs: net: dsa: update information about multiple CPU ports
> net: dsa: felix: add support for changing DSA master
>
> .../networking/dsa/configuration.rst | 84 +++++
> Documentation/networking/dsa/dsa.rst | 38 ++-
> drivers/net/dsa/bcm_sf2.c | 4 +-
> drivers/net/dsa/bcm_sf2_cfp.c | 4 +-
> drivers/net/dsa/lan9303-core.c | 4 +-
> drivers/net/dsa/ocelot/felix.c | 117 ++++++-
> drivers/net/dsa/ocelot/felix.h | 3 +
> .../net/ethernet/mediatek/mtk_ppe_offload.c | 2 +-
> drivers/net/ethernet/mscc/ocelot.c | 3 +-
> include/linux/netdevice.h | 6 +
> include/net/dsa.h | 19 ++
> include/soc/mscc/ocelot.h | 1 +
> include/uapi/linux/if_link.h | 10 +
> net/dsa/Makefile | 10 +-
> net/dsa/dsa.c | 9 +
> net/dsa/dsa2.c | 34 ++-
> net/dsa/dsa_priv.h | 17 +-
> net/dsa/master.c | 82 ++++-
> net/dsa/netlink.c | 62 ++++
> net/dsa/port.c | 159 +++++++++-
> net/dsa/slave.c | 288 +++++++++++++++++-
> net/dsa/switch.c | 22 +-
> net/dsa/tag_8021q.c | 4 +-
> 23 files changed, 924 insertions(+), 58 deletions(-)
> create mode 100644 net/dsa/netlink.c
>
> --
> 2.34.1
>

--
Ansuel

2022-09-02 19:01:07

by Florian Fainelli

[permalink] [raw]
Subject: Re: [PATCH net-next 0/9] DSA changes for multiple CPU ports (part 4)



On 9/2/2022 3:31 AM, Vladimir Oltean wrote:
> On Tue, Aug 30, 2022 at 10:59:23PM +0300, Vladimir Oltean wrote:
>> This series represents the final part of that effort. We have:
>>
>> - the introduction of new UAPI in the form of IFLA_DSA_MASTER
>
> Call for opinions: when I resend this, should I keep rtnl_link_ops,
> or should I do what Marek attempted to do, and make the existing iflink
> between a user port and its master writable from user space?
> https://lore.kernel.org/netdev/[email protected]/
>
> I'm not sure if we have that many more use cases for rtnl_link_ops..

It's a bit hard to see one right now, I agree.

> at some point I was thinking we could change the way in which dsa_loop
> probes, and allow dynamic creation of such interfaces using RTM_NEWLINK;
> but looking closer at that, it's a bit more complicated, since we'd need
> to attach dsa_loop user ports to a virtual switch, and probe all ports
> at the same time rather than one by one.

Yes, not sure the custom netlink operations would be the preferred way
of doing that configuration, maybe module parameters and/or debugfs
might just do?
--
Florian

2022-09-02 19:47:54

by Vladimir Oltean

[permalink] [raw]
Subject: Re: [PATCH net-next 0/9] DSA changes for multiple CPU ports (part 4)

On Fri, Sep 02, 2022 at 11:33:31AM -0700, Florian Fainelli wrote:
> > at some point I was thinking we could change the way in which dsa_loop
> > probes, and allow dynamic creation of such interfaces using RTM_NEWLINK;
> > but looking closer at that, it's a bit more complicated, since we'd need
> > to attach dsa_loop user ports to a virtual switch, and probe all ports
> > at the same time rather than one by one.
>
> Yes, not sure the custom netlink operations would be the preferred way of
> doing that configuration, maybe module parameters and/or debugfs might just
> do?

Yeah, or make dsa_loop OF-based and just insert a device tree overlay,
something of that sort, I'd guess.

So it's likely that we won't be extending the DSA rtnl_link_ops too much
in the future. However, it's also likely that "writable iflink" isn't
going to be very useful for other virtual netdevices except DSA, either.
So the argument goes both ways. And while the writable iflink requires a
new ndo operation, the IFLA_DSA_MASTER can be handled 100% within DSA.

I don't know, I'm just rambling, I'm open to suggestions.

2022-09-03 03:02:27

by Marek Behún

[permalink] [raw]
Subject: Re: [PATCH net-next 0/9] DSA changes for multiple CPU ports (part 4)

On Fri, 2 Sep 2022 20:44:37 +0200
Christian Marangi <[email protected]> wrote:

> On Tue, Aug 30, 2022 at 10:59:23PM +0300, Vladimir Oltean wrote:
> > Those who have been following part 1:
> > https://patchwork.kernel.org/project/netdevbpf/cover/[email protected]/
> > part 2:
> > https://patchwork.kernel.org/project/netdevbpf/cover/[email protected]/
> > and part 3:
> > https://patchwork.kernel.org/project/netdevbpf/cover/[email protected]/
> > will know that I am trying to enable the second internal port pair from
> > the NXP LS1028A Felix switch for DSA-tagged traffic via "ocelot-8021q".
> >
> > This series represents the final part of that effort. We have:
> >
> > - the introduction of new UAPI in the form of IFLA_DSA_MASTER
> >
> > - preparation for LAG DSA masters in terms of suppressing some
> > operations for masters in the DSA core that simply don't make sense
> > when those masters are a bonding/team interface
> >
> > - handling all the net device events that occur between DSA and a
> > LAG DSA master, including migration to a different DSA master when the
> > current master joins a LAG, or the LAG gets destroyed
> >
> > - updating documentation
> >
> > - adding an implementation for NXP LS1028A, where things are insanely
> > complicated due to hardware limitations. We have 2 tagging protocols:
> >
> > * the native "ocelot" protocol (NPI port mode). This does not support
> > CPU ports in a LAG, and supports a single DSA master. The DSA master
> > can be changed between eno2 (2.5G) and eno3 (1G), but all ports must
> > be down during the changing process, and user ports assigned to the
> > old DSA master will refuse to come up if the user requests that
> > during a "transient" state.
> >
> > * the "ocelot-8021q" software-defined protocol, where the Ethernet
> > ports connected to the CPU are not actually "god mode" ports as far
> > as the hardware is concerned. So here, static assignment between
> > user and CPU ports is possible by editing the PGID_SRC masks for
> > the port-based forwarding matrix, and "CPU ports in a LAG" simply
> > means "a LAG like any other".
> >
> > The series was regression-tested on LS1028A using the local_termination.sh
> > kselftest, in most of the possible operating modes and tagging protocols.
> > I have not done a detailed performance evaluation yet, but using LAG, is
> > possible to exceed the termination bandwidth of a single CPU port in an
> > iperf3 test with multiple senders and multiple receivers.
> >
> > There was a previous RFC posted, which contains most of these changes,
> > however it's so old by now that it's unlikely anyone of the reviewers
> > remembers it in detail. I've applied most of the feedback requested by
> > Florian and Ansuel there.
> > https://lore.kernel.org/netdev/[email protected]/
>
> Hi,
> I would love to test this but for me it's a bit problematic to use a
> net-next kernel. I wonder if it's possible to backport the 4 part to
> older kernel or other prereq are needed. (I know backporting the 4 part
> will be crazy but it's something that has to be done anyway to actually
> use this on OpenWrt where we currently use 5.10 and 5.15)
>
> Would be good to know if the 4 part require other changes to dsa core to
> make a LAG implementation working. (talking for 5.15 since backporting
> this to 5.10 is a nono...)

Just use the newest kernel. Trust me, backporting new DSA changes to
5.15 is painful. And to 5.10 and earlier it is a literal hell.

:) Marek

2022-09-03 03:25:51

by Marek Behún

[permalink] [raw]
Subject: Re: [PATCH net-next 0/9] DSA changes for multiple CPU ports (part 4)

On Fri, 2 Sep 2022 10:31:46 +0000
Vladimir Oltean <[email protected]> wrote:

> On Tue, Aug 30, 2022 at 10:59:23PM +0300, Vladimir Oltean wrote:
> > This series represents the final part of that effort. We have:
> >
> > - the introduction of new UAPI in the form of IFLA_DSA_MASTER
>
> Call for opinions: when I resend this, should I keep rtnl_link_ops,
> or should I do what Marek attempted to do, and make the existing iflink
> between a user port and its master writable from user space?
> https://lore.kernel.org/netdev/[email protected]/
>
> I'm not sure if we have that many more use cases for rtnl_link_ops..
> at some point I was thinking we could change the way in which dsa_loop
> probes, and allow dynamic creation of such interfaces using RTM_NEWLINK;
> but looking closer at that, it's a bit more complicated, since we'd need
> to attach dsa_loop user ports to a virtual switch, and probe all ports
> at the same time rather than one by one.

My opinion is that it would be better to add new DSA specific netlink
operations instead of using the existing iflink as I did in the that
patch.

I think that DSA should have it's own IP subcommands. Using the
standard, already existing API, is not sufficient for more complex
configurations/DSA routing settings. Consider DSA where there are
multiple switches and the switches are connected via multiple ports:

+----------+ +---------------+ +---------+
| eth0 <---> sw0p0 sw0p2 <---> sw1p0
| cpu | | | | ....
| eth1 <---> sw0p1 s20p3 <---> sw1p1
+----------+ +---------------+ +---------+

The routing is more complicated in this scenario. The old API is not
sufficient.

Marek

2022-09-04 15:47:58

by Vladimir Oltean

[permalink] [raw]
Subject: Re: [PATCH net-next 0/9] DSA changes for multiple CPU ports (part 4)

On Sat, Sep 03, 2022 at 04:48:32AM +0200, Marek Beh?n wrote:
> My opinion is that it would be better to add new DSA specific netlink
> operations instead of using the existing iflink as I did in the that
> patch.

Ok, I'll send out the iproute2 patch today.

> I think that DSA should have it's own IP subcommands. Using the
> standard, already existing API, is not sufficient for more complex
> configurations/DSA routing settings. Consider DSA where there are
> multiple switches and the switches are connected via multiple ports:
>
> +----------+ +---------------+ +---------+
> | eth0 <---> sw0p0 sw0p2 <---> sw1p0
> | cpu | | | | ....
> | eth1 <---> sw0p1 s20p3 <---> sw1p1
> +----------+ +---------------+ +---------+
>
> The routing is more complicated in this scenario.

This is so problematic that I don't even know where to start.

Does anyone do this? What do they want to achieve? How do they want the
system to behave?

Let's push your example even one step further:

+----------+ +---------------+ +---------------+ +---------+
| eth0 <---> sw0p0 sw0p2 <---> sw1p0 sw1p2 <---> sw2p0
| cpu | | | | | | ....
| eth1 <---> sw0p1 sw0p3 <---> sw1p1 sw1p3 <---> sw2p1
+----------+ +---------------+ +---------------+ +---------+

With our current DT bindings, DSA (cascade) ports would need to contain
links to all DSA ports of indirectly connected switches, because this is
what the dst->rtable expects.

switch@0 {
reg = <0>;
dsa,member = <0 0>;

ethernet-ports {
port@0 {
reg = <0>;
ethernet = <&eth0>;
};

port@1 {
reg = <1>;
ethernet = <&eth1>;
};

sw0p2: port@2 {
reg = <2>;
link = <&sw1p0>, <&sw2p0>, <&sw2p1>;
};

sw0p3: port@3 {
reg = <3>;
link = <&sw1p1>, <&sw2p0>, <&sw2p1>;
};
};
};

switch@1 {
reg = <1>;
dsa,member = <0 1>;

ethernet-ports {
sw1p0: port@0 {
reg = <0>;
link = <&sw0p2>;
};

sw1p1: port@1 {
reg = <1>;
link = <&sw0p3>;
};

sw1p2: port@2 {
reg = <2>;
link = <&sw2p0>;
};

sw1p3: port@3 {
reg = <3>;
link = <&sw2p1>;
};
};
};

switch@2 {
reg = <2>;
dsa,member = <0 2>;

ethernet-ports {
port@0 {
reg = <0>;
link = <&sw1p2>, <&sw0p2>, <&sw0p3>;
};

port@1 {
reg = <1>;
link = <&sw1p3>, <&sw0p2>, <&sw0p3>;
};
};
};

> The old API is not sufficient.

There is no "old API" to speak of, because none of this is exposed.
So, 'insufficient' is an understatement. Furthermore, the rtnl_link_ops
are exposed per *user* port, we still gain zero control of the
dst->rtable.

The main consumer of the dst->rtable is this:

/* Return the local port used to reach an arbitrary switch device */
static inline unsigned int dsa_routing_port(struct dsa_switch *ds, int device)
{
struct dsa_switch_tree *dst = ds->dst;
struct dsa_link *dl;

list_for_each_entry(dl, &dst->rtable, list)
if (dl->dp->ds == ds && dl->link_dp->ds->index == device)
return dl->dp->index;

return ds->num_ports;
}

Notice the singular *the* local port. So it would currently return the
local cascade port from the first dsa_link added to the rtable (in turn,
the first port which has a 'link' OF node description to a cascade port
of @device). If there are any further dsa_links between a cascade port
of this switch and a cascade port of that switch, they are ignored
(which is a good thing in terms of compatibility between old kernels and
new device trees, but still raises questions).

For each of the functions in the call graph below, we need to determine
exactly what we need to make behave differently (consider a potential
second, third, fourth dsa_link, and how to expose this structure):

dsa_port_host_address_match
|
| dsa_port_host_vlan_match
| |
v v
dsa_switch_is_upstream_of
| |
| |
| mv88e6xxx_lag_sync_map |
v | |
dsa_is_upstream_port | |
| | |
mv88e6xxx_port_vlan | | |
| | | |
v | | |
dsa_switch_upstream_port | | |
| | | |
| | | |
plenty of drivers | | | |
| | | | |
v v v | |
dsa_upstream_port | |
| | |
v v |
dsa_towards_port |
| |
| |
v v
dsa_routing_port

2022-09-04 20:20:29

by Vladimir Oltean

[permalink] [raw]
Subject: Re: [PATCH net-next 0/9] DSA changes for multiple CPU ports (part 4)

On Fri, Sep 02, 2022 at 08:44:37PM +0200, Christian Marangi wrote:
> Hi,
> I would love to test this but for me it's a bit problematic to use a
> net-next kernel. I wonder if it's possible to backport the 4 part to
> older kernel or other prereq are needed. (I know backporting the 4 part
> will be crazy but it's something that has to be done anyway to actually
> use this on OpenWrt where we currently use 5.10 and 5.15)
>
> Would be good to know if the 4 part require other changes to dsa core to
> make a LAG implementation working. (talking for 5.15 since backporting
> this to 5.10 is a nono...)

For testing, iproute2 patch should be coming up soon here:
https://lore.kernel.org/netdev/[email protected]/

I tried to backport something on the current linux-stable/linux-5.15.y.
https://github.com/vladimiroltean/linux/tree/dsa-5.15.y

Consider it a work in progress. It compiles and boots on NXP LS1028A,
but I can't guarantee anything beyond that. Furthermore, I've only
backported the merged patches, not the patch set discussed here proper.

I think it would be nice if we had a collaborative tree with DSA
backports for 5.15, because here I just tried to backport the DSA core
rather than all driver changes (since I would be unable to test those).

For transparency, here is the commit list I used to produce the backport (top-most is most recent):

$ cat stable-commits.txt
5dc760d12082 net: dsa: use dsa_tree_for_each_cpu_port in dsa_tree_{setup,teardown}_master
f41ec1fd1c20 net: dsa: all DSA masters must be down when changing the tagging protocol
7136097e1199 net: dsa: only bring down user ports assigned to a given DSA master
4f03dcc6b9a0 net: dsa: existing DSA masters cannot join upper interfaces
920a33cd7231 net: bridge: move DSA master bridging restriction to DSA
0498277ee17b net: dsa: don't stop at NOTIFY_OK when calling ds->ops->port_prechangeupper
4c3f80d22b2e net: dsa: walk through all changeupper notifier functions
be6ff9665d64 net: dsa: don't emit targeted cross-chip notifiers for MTU change
4715029fa7e9 net: dsa: drop dsa_slave_priv from dsa_slave_change_mtu
cf1c39d3b3a5 net: dsa: avoid one dsa_to_port() in dsa_slave_change_mtu
b2033a05a719 net: dsa: use dsa_tree_for_each_user_port in dsa_slave_change_mtu
726816a129cb net: dsa: make cross-chip notifiers more efficient for host events
8e9e678e4758 net: dsa: move reset of VLAN filtering to dsa_port_switchdev_unsync_attrs
762c2998c962 Revert "net: dsa: setup master before ports"
8e6598a7b0fa net: dsa: Pass VLAN MSTI migration notifications to driver
332afc4c8c0d net: dsa: Validate hardware support for MST
f54fd0e16306 net: bridge: mst: Add helper to query a port's MST state
48d57b2e5f43 net: bridge: mst: Add helper to check if MST is enabled
cceac97afa09 net: bridge: mst: Add helper to map an MSTI to a VID set
7ae9147f4312 net: bridge: mst: Notify switchdev drivers of MST state changes
6284c723d9b9 net: bridge: mst: Notify switchdev drivers of VLAN MSTI migrations
87c167bb94ee net: bridge: mst: Notify switchdev drivers of MST mode changes
122c29486e1f net: bridge: mst: Support setting and reporting MST port states
8c678d60562f net: bridge: mst: Allow changing a VLAN's MSTI
ec7328b59176 net: bridge: mst: Multiple Spanning Tree (MST) mode
0832cd9f1f02 net: dsa: warn if port lists aren't empty in dsa_port_teardown
afb3cc1a397d net: dsa: unlock the rtnl_mutex when dsa_master_setup() fails
7569459a52c9 net: dsa: manage flooding on the CPU ports
499aa9e1b332 net: dsa: install the primary unicast MAC address as standalone port host FDB
5e8a1e03aa4d net: dsa: install secondary unicast and multicast addresses as host FDB/MDB
68d6d71eafd1 net: dsa: rename the host FDB and MDB methods to contain the "bridge" namespace
35aae5ab9121 net: dsa: remove workarounds for changing master promisc/allmulti only while up
06b9cce42634 net: dsa: pass extack to .port_bridge_join driver methods
c26933639b54 net: dsa: request drivers to perform FDB isolation
b6362bdf750b net: dsa: tag_8021q: rename dsa_8021q_bridge_tx_fwd_offload_vid
04b67e18ce5b net: dsa: tag_8021q: merge RX and TX VLANs
08f44db3abe6 net: dsa: felix: delete workarounds present due to SVL tag_8021q bridging
d27656d02d85 docs: net: dsa: sja1105: document limitations of tc-flower rule VLAN awareness
d7f9787a763f net: dsa: tag_8021q: add support for imprecise RX based on the VBID
91495f21fcec net: dsa: tag_8021q: replace the SVL bridging with VLAN-unaware IVL bridging
961d8b699070 net: dsa: felix: support FDB entries on offloaded LAG interfaces
e212fa7c5418 net: dsa: support FDB events on offloaded LAG interfaces
93c798230af5 net: dsa: call SWITCHDEV_FDB_OFFLOADED for the orig_dev
e35f12e993d4 net: dsa: remove "ds" and "port" from struct dsa_switchdev_event_work
ec638740fce9 net: switchdev: remove lag_mod_cb from switchdev_handle_fdb_event_to_device
dedd6a009f41 net: dsa: create a dsa_lag structure
b99dbdf00bc1 net: dsa: mv88e6xxx: use dsa_switch_for_each_port in mv88e6xxx_lag_sync_masks
3d4a0a2a46ab net: dsa: make LAG IDs one-based
066ce9779c7a net: dsa: qca8k: rename references to "lag" as "lag_dev"
e23eba722861 net: dsa: mv88e6xxx: rename references to "lag" as "lag_dev"
46a76724e4c9 net: dsa: rename references to "lag" as "lag_dev"
b9e8b58fd2cb net: dsa: Include BR_PORT_LOCKED in the list of synced brport flags
a21d9a670d81 net: bridge: Add support for bridge port in locked mode
acd8df5880d7 net: switchdev: avoid infinite recursion from LAG to bridge with port object handler
342b6419193c net: dsa: fix panic when removing unoffloaded port from bridge
8940e6b669ca net: dsa: avoid call to __dev_set_promiscuity() while rtnl_mutex isn't held
ba43b547515e net: lan966x: remove guards against !BRIDGE_VLAN_INFO_BRENTRY
e42bd4ed09aa net: mscc: ocelot: keep traps in a list
85ea0daabe5a net: mscc: ocelot: avoid overlap in VCAP IS2 between PTP and MRP traps
b9bace6e534d net: mscc: ocelot: use a single VCAP filter for all MRP traps
36fac35b2907 net: mscc: ocelot: delete OCELOT_MRP_CPUQ
c518afec2883 net: mscc: ocelot: consolidate cookie allocation for private VCAP rules
e3c02b7c655c net: mscc: ocelot: use a consistent cookie for MRP traps
164f861bd40c net: dsa: offload bridge port VLANs on foreign interfaces
134ef2388e7f net: dsa: add explicit support for host bridge VLANs
c4076cdd21f8 net: switchdev: introduce switchdev_handle_port_obj_{add,del} for foreign interfaces
7b465f4cf39e net: switchdev: rename switchdev_lower_dev_find to switchdev_lower_dev_find_rcu
b28d580e2939 net: bridge: switchdev: replay all VLAN groups
263029ae3172 net: bridge: make nbp_switchdev_unsync_objs() follow reverse order of sync()
8d23a54f5bee net: bridge: switchdev: differentiate new VLANs from changed ones
27c5f74c7ba7 net: bridge: vlan: notify switchdev only when something changed
cab2cd770051 net: bridge: vlan: make __vlan_add_flags react only to PVID and UNTAGGED
3116ad0696dd net: bridge: vlan: don't notify to switchdev master VLANs without BRENTRY flag
b2bc58d41fde net: bridge: vlan: check early for lack of BRENTRY flag in br_vlan_add_existing
ef5764057540 net: mscc: ocelot: fix use-after-free in ocelot_vlan_del()
5454f5c28eca net: bridge: vlan: check for errors from __vlan_del in __vlan_flush
867b1db874c9 net: lan966x: Fix when CONFIG_IPV6 is not set
1da52b0e4724 net: lan966x: Fix when CONFIG_PTP_1588_CLOCK is compiled as module
59085208e4a2 net: mscc: ocelot: fix all IP traffic getting trapped to CPU with PTP over IP
47aeea0d57e8 net: lan966x: Implement the callback SWITCHDEV_ATTR_ID_BRIDGE_MC_DISABLED
cddbec19466a net: dsa: qca8k: add tracking state of master port
e83d56537859 net: dsa: replay master state events in dsa_tree_{setup,teardown}_master
295ab96f478d net: dsa: provide switch operations for tracking the master state
a1ff94c2973c net: dsa: stop updating master MTU from master.c
77eecf25bd9d net: lan966x: Update extraction/injection for timestamping
735fec995b21 net: lan966x: Implement SIOCSHWTSTAMP and SIOCGHWTSTAMP
d096459494a8 net: lan966x: Add support for ptp clocks
108dc8741c20 net: dsa: Avoid cross-chip syncing of VLAN filtering
381a730182f1 net: dsa: Move VLAN filtering syncing out of dsa_switch_bridge_leave
5cad43a52ee3 net: dsa: felix: add port fast age support
1b26d364e4e9 net: dsa: warn about dsa_port and dsa_switch bit fields being non atomic
63cfc65753d6 net: dsa: don't enumerate dsa_switch and dsa_port bit fields using commas
11fd667dac31 net: dsa: setup master before ports
1e3f407f3cac net: dsa: first set up shared ports, then non-shared ports
c146f9bc195a net: dsa: hold rtnl_mutex when calling dsa_master_{setup,teardown}
a68dc7b938fb net: dsa: remove cross-chip support for HSR
cad69019f2f8 net: dsa: remove cross-chip support for MRP
4b026e82893b net: dsa: combine two holes in struct dsa_switch_tree
b035c88c6a30 net: dsa: move dsa_switch_tree :: ports and lags to first cache line
258030acc93b net: dsa: make dsa_switch :: num_ports an unsigned int
7787ff776398 net: dsa: merge all bools of struct dsa_switch into a single u32
0625125877da net: dsa: move dsa_port :: type near dsa_port :: index
bde82f389af1 net: dsa: merge all bools of struct dsa_port into a single u8
b08db33dabd1 net: dsa: move dsa_port :: stp_state near dsa_port :: mac
7aacb894b1ad net: lan966x: Extend switchdev with mdb support
11b0a27772f5 net: lan966x: Add PGID_GP_START and PGID_GP_END
fc0c3fe7486f net: lan966x: Add function lan966x_mac_ip_learn()
0c94d657d2a4 net: lan966x: Fix the vlan used by host ports
2e49761e4fd1 net: lan966x: Add support for multiple bridge flags
811ba2771182 net: lan966x: Extend switchdev with fdb support
e14f72398df4 net: lan966x: Extend switchdev bridge flags
6d2c186afa5d net: lan966x: Add vlan support.
cf2f60897e92 net: lan966x: Add support to offload the forwarding.
571bb516a869 net: lan966x: Remove .ndo_change_rx_flags
25ee9561ec62 net: lan966x: More MAC table functionality
5ccd66e01cbe net: lan966x: add support for interrupts from analyzer
ef14049f4db9 net: lan966x: Add registers that are used for switch and vlan functionality
7f2973149c22 net: dsa: make tagging protocols connect to individual switches from a tree
e2f01bfe1406 net: dsa: tag_sja1105: fix zeroization of ds->priv on tag proto disconnect
b26980ab2a97 net: lan966x: Fix the configuration of the pcs
950a419d9de1 net: dsa: tag_sja1105: split sja1105_tagger_data into private and public sections
fcbf979a5b4b Revert "net: dsa: move sja1110_process_meta_tstamp inside the tagging protocol driver"
c79e84866d2a net: dsa: tag_sja1105: convert to tagger-owned data
22ee9f8e4011 net: dsa: sja1105: move ts_id from sja1105_tagger_data
bfcf14252220 net: dsa: sja1105: make dp->priv point directly to sja1105_tagger_data
6f6770ab1ce2 net: dsa: sja1105: remove hwts_tx_en from tagger data
d38049bbe760 net: dsa: sja1105: bring deferred xmit implementation in line with ocelot-8021q
a3d74295d790 net: dsa: sja1105: let deferred packets time out when sent to ports going down
35d976802124 net: dsa: tag_ocelot: convert to tagger-owned data
dc452a471dba net: dsa: introduce tagger-owned storage for private and shared data
857fdd74fb38 net: dsa: eliminate dsa_switch_ops :: port_bridge_tx_fwd_{,un}offload
b079922ba2ac net: dsa: add a "tx_fwd_offload" argument to ->port_bridge_join
d3eed0e57d5d net: dsa: keep the bridge_dev and bridge_num as part of the same structure
6a43cba30340 net: dsa: export bridging offload helpers to drivers
936db8a2dba2 net: dsa: rename dsa_port_offloads_bridge to dsa_port_offloads_bridge_dev
41fb0cf1bced net: dsa: hide dp->bridge_dev and dp->bridge_num in drivers behind helpers
36cbf39b5690 net: dsa: hide dp->bridge_dev and dp->bridge_num in the core behind helpers
65144067d360 net: dsa: mv88e6xxx: compute port vlan membership based on dp->bridge_dev comparison
0493fa7927af net: dsa: mv88e6xxx: iterate using dsa_switch_for_each_user_port in mv88e6xxx_port_check_hw_vlan
872bb81dfbc3 net: dsa: mt7530: iterate using dsa_switch_for_each_user_port in bridging ops
947c8746e2c3 net: dsa: assign a bridge number even without TX forwarding offload
3f9bb0301d50 net: dsa: make dp->bridge_num one-based
bb14bfc7eb92 net: lan966x: fix a IS_ERR() vs NULL check in lan966x_create_targets()
cc9cf69eea48 net: lan966x: Fix builds for lan966x driver
a290cf692779 net: lan966x: Fix duplicate check in frame extraction
12c2d0a5b8e2 net: lan966x: add ethtool configuration and statistics
e18aba8941b4 net: lan966x: add mactable support
d28d6d2e37d1 net: lan966x: add port module support
db8bcaad5393 net: lan966x: add the basic lan966x driver
ef136837aaf6 net: dsa: rtl8365mb: set RGMII RX delay in steps of 0.3 ns
b014861d96a6 net: dsa: realtek-smi: don't log an error on EPROBE_DEFER
1e89ad864d03 net: dsa: realtek-smi: fix indirect reg access for ports>3
b3612ccdf284 net: dsa: microchip: implement multi-bridge support
96ca08c05838 net: mscc: ocelot: set up traps for PTP packets
ec15baec3272 net: ptp: add a definition for the UDP port for IEEE 1588 general messages
95706be13b9f net: mscc: ocelot: create a function that replaces an existing VCAP filter
8abe19703825 net: dsa: felix: enable cut-through forwarding between ports by default
a8bd9fa5b527 net: ocelot: remove "bridge" argument from ocelot_get_bridge_fwd_mask
4636440f913b net: dsa: qca8k: Fix spelling mistake "Mismateched" -> "Mismatched"
0898ca67b86e net: dsa: qca8k: fix warning in LAG feature
def975307c01 net: dsa: qca8k: add LAG support
2c1bdbc7e756 net: dsa: qca8k: add support for mirror mode
ba8f870dfa63 net: dsa: qca8k: add support for mdb_add/del
6a3bdc5209f4 net: dsa: qca8k: add set_ageing_time support
4592538bfb0d net: dsa: qca8k: add support for port fast aging
c126f118b330 net: dsa: qca8k: add additional MIB counter and make it dynamic
8b5f3f29a81a net: dsa: qca8k: initial conversion to regmap helper
36b8af12f424 net: dsa: qca8k: move regmap init in probe and set it mandatory
994c28b6f971 net: dsa: qca8k: remove extra mutex_init in qca8k_setup
90ae68bfc2ff net: dsa: qca8k: convert to GENMASK/FIELD_PREP/FIELD_GET
b9133f3ef5a2 net: dsa: qca8k: remove redundant check in parse_port_config
65258b9d8cde net: dsa: qca8k: fix MTU calculation
3b00a07c2443 net: dsa: qca8k: fix internal delay applied to the wrong PAD config
a7e13edf37be net: dsa: felix: restrict psfp rules on ingress port
76c13ede7120 net: dsa: felix: use vcap policer to set flow meter for psfp
77043c37096d net: mscc: ocelot: use index to set vcap policer
23ae3a787771 net: dsa: felix: add stream gate settings for psfp
7d4b564d6add net: dsa: felix: support psfp filter on vsc9959
23e2c506ad6c net: mscc: ocelot: add gate and police action offload to PSFP
5b1918a54a91 net: mscc: ocelot: set vcap IS2 chain to goto PSFP chain
0568c3bf3f34 net: mscc: ocelot: add MAC table stream learn and lookup operations
02d6fdecb9c3 regmap: allow to define reg_update_bits for no bus configuration
5f15d392dcb4 net: dsa: qca8k: make sure PAD0 MAC06 exchange is disabled
ae0393500e3b net: bridge: switchdev: fix shim definition for br_switchdev_mdb_notify
326b212e9cd6 net: bridge: switchdev: consistent function naming
9776457c784f net: bridge: mdb: move all switchdev logic to br_switchdev.c
9ae9ff994b0e net: bridge: split out the switchdev portion of br_mdb_notify
4a6849e46173 net: bridge: move br_vlan_replay to br_switchdev.c
c5f6e5ebc2af net: bridge: provide shim definition for br_vlan_flags
716a30a97a52 net: switchdev: merge switchdev_handle_fdb_{add,del}_to_device
fab9eca88410 net: bridge: create a common function for populating switchdev FDB entries
5cda5272a460 net: bridge: move br_fdb_replay inside br_switchdev.c
9574fb558044 net: bridge: reduce indentation level in fdb_create
f6814fdcfe1b net: bridge: rename br_fdb_insert to br_fdb_add_local
4731b6d6b257 net: bridge: rename fdb_insert to fdb_add_local
5f94a5e276ae net: bridge: remove fdb_insert forward declaration
4682048af0c8 net: bridge: remove fdb_notify forward declaration
425d19cedef8 net: dsa: stop calling dev_hold in dsa_slave_fdb_event
d7d0d423dbaa net: dsa: flush switchdev workqueue when leaving the bridge
0faf890fc519 net: dsa: drop rtnl_lock from dsa_slave_switchdev_event_work
338a3a4745aa net: dsa: introduce locking for the address lists on CPU and DSA ports
cf231b436f7c net: dsa: lantiq_gswip: serialize access to the PCE registers
f7eb4a1c0864 net: dsa: b53: serialize access to the ARL table
edc90d15850c selftests: net: dsa: add a stress test for unlocked FDB operations
016748961ba5 selftests: lib: forwarding: allow tests to not require mz and jq
f239934cffe5 net: dsa: b53: serialize access to the ARL table
f2c4bdf62d76 net: mscc: ocelot: serialize access to the MAC table
1681ae1691ef net: dsa: sja1105: serialize access to the dynamic config interface
643979cf5ec4 net: dsa: sja1105: wait for dynamic config command completion on writes too
992e5cc7be8e net: dsa: tag_8021q: make dsa_8021q_{rx,tx}_vid take dp as argument
5068887a4fbe net: dsa: tag_sja1105: do not open-code dsa_switch_for_each_port
fac6abd5f132 net: dsa: convert cross-chip notifiers to iterate using dp
57d77986e742 net: dsa: remove gratuitous use of dsa_is_{user,dsa,cpu}_port
65c563a67755 net: dsa: do not open-code dsa_switch_for_each_port
d0004a020bb5 net: dsa: remove the "dsa_to_port in a loop" antipattern from the core
82b318983c51 net: dsa: introduce helpers for iterating through ports using dp
d4004422f6f9 net: mscc: ocelot: track the port pvid using a pointer
bfbab3104413 net: mscc: ocelot: add the local station MAC addresses in VID 0
0da1a1c48911 net: mscc: ocelot: allow a config where all bridge VLANs are egress-untagged
90e0aa8d108d net: mscc: ocelot: convert the VLAN masks to a list
62a22bcbd30e net: mscc: ocelot: add a type definition for REW_TAG_CFG_TAG_CFG
040e926f5813 net: dsa: qca8k: tidy for loop in setup and add cpu port check
9ca482a246f0 net: dsa: sja1105: parse {rx, tx}-internal-delay-ps properties for RGMII delays
4af2950c50c8 net: dsa: realtek-smi: add rtl8365mb subdriver for RTL8365MB-VC
1521d5adfc2b net: dsa: tag_rtl8_4: add realtek 8 byte protocol 4 tag
9cb8edda2157 net: dsa: move NET_DSA_TAG_RTL4_A to right place in Kconfig/Makefile
7bbbbfaa7a1b ether: add EtherType for proprietary Realtek protocols
fd0bb28c547f net: dsa: qca8k: move port config to dedicated struct
cef08115846e net: dsa: qca8k: set internal delay also for sgmii
f477d1c8bdbe net: dsa: qca8k: add support for QCA8328
ed7988d77fbf dt-bindings: net: dsa: qca8k: document support for qca8328
362bb238d8bf net: dsa: qca8k: add support for pws config reg
924087c5c3d4 dt-bindings: net: dsa: qca8k: Document qca,led-open-drain binding
bbc4799e8bb6 net: dsa: qca8k: add explicit SGMII PLL enable
13ad5ccc093f dt-bindings: net: dsa: qca8k: Document qca,sgmii-enable-pll
5654ec78dd7e net: dsa: qca8k: rework rgmii delay logic and scan for cpu port 6
3fcf734aa482 net: dsa: qca8k: add support for cpu port 6
731d613338ec dt-bindings: net: dsa: qca8k: Document support for CPU port 6
6c43809bf1be net: dsa: qca8k: add support for sgmii falling edge
fdbf35df9c09 dt-bindings: net: dsa: qca8k: Add SGMII clock phase properties
d8b6f5bae6d3 dsa: qca8k: add mac_power_sel support
39e222bfd7f3 net: dsa: unregister cross-chip notifier after ds->ops->teardown
339e75f6b9a0 net: dsa: rtl8366rb: remove unneeded semicolon
e674cfd08537 net: dsa: rtl8366rb: Support setting STP state
1fbd19e10b73 net: dsa: rtl8366rb: Support fast aging
56d8bb71a811 net: dsa: rtl8366rb: Support disabling learning
5ca721c54d86 net: dsa: tag_ocelot: set the classified VLAN during xmit
e8c0722927e8 net: mscc: ocelot: write full VLAN TCI in the injection header
de5bbb6f7e4c net: mscc: ocelot: support egress VLAN rewriting via VCAP ES0
55b115c7ecd9 net: dsa: rtl8366rb: Use core filtering tracking
d310b14ae748 net: dsa: rtl8366: Drop and depromote pointless prints
a4eff910ec63 net: dsa: rtl8366rb: Rewrite weird VLAN filering enablement
7776e33c68ae net: dsa: rtl8366: Drop custom VLAN set-up
d5a680295be2 net: dsa: rtl8366rb: Support bridge offloading
bd936bd53b2d net: dsa: Move devlink registration to be last devlink command
6d709cadfde6 net: dsa: move sja1110_process_meta_tstamp inside the tagging protocol driver
68a81bb2eebd net: dsa: sja1105: remove sp->dp
db4278c55fa5 devlink: Make devlink_register to be void
4dcd183fbd67 net: wwan: iosm: devlink registration

There are 2 conflicts expected during merging this patch set due to net
<-> net-next overlaps at the time. One is in include/linux/dsa/sja1105.h
and the other is in net/dsa/dsa2.c. See the resolutions in my git tree
and make sure to enable git rerere so that you don't have to redo them
every time you recreate the branch.

For sorting a list of commits chronologically, I have this:

$ cat ~/bin/git-sort-commit-list
#!/bin/bash

set -e -u -o pipefail

error() {
local lineno="$1"
local code="${2:-1}"

echo "Error on line ${lineno}; status ${code}."
exit "${code}"
}
trap 'error ${LINENO}' ERR

usage() {
echo "Usage:"
echo "$0 --commit-file <file> --oldest-commit <ref> --newest-commit <ref>"
exit
}

argc=$#
argv=( "$@" )

if [ $argc -lt 6 ]; then
usage
fi

cmd="cat"

i=0
while [ $i -lt $argc ]; do
key="${argv[$i]}"
i=$((i + 1))
case "$key" in
-c|--commit-file)
file="${argv[$i]}"
i=$((i + 1))
;;
-n|--newest-commit)
newest="${argv[$i]}"
i=$((i + 1))
;;
-o|--oldest-commit)
oldest="${argv[$i]}"
i=$((i + 1))
;;
*)
usage
;;
esac
done

for rev in $(git rev-list "$newest" ^"$oldest"); do
match="$(grep $(echo ${rev} | head -c 12) ${file} | uniq || :)"
if [ -n "${match}" ]; then
echo ${match}
fi
done

The other script is for the backporting itself:

[tigrisor@skbuf /opt/linux] $ cat ~/bin/git-backport
#!/bin/bash

set -e -u -o pipefail

error() {
local lineno="$1"
local code="${2:-1}"

echo "Error on line ${lineno}; status ${code}."
exit "${code}"
}
trap 'error ${LINENO}' ERR

usage() {
echo "Usage:"
echo "$0 --commit-file <file> --base-branch <ref> --branch-name <string> [--reverse]"
exit
}

argc=$#
argv=( "$@" )

if [ $argc -lt 6 ]; then
usage
fi

cmd="cat"

i=0
while [ $i -lt $argc ]; do
key="${argv[$i]}"
i=$((i + 1))
case "$key" in
-c|--commit-file)
file="${argv[$i]}"
i=$((i + 1))
;;
-b|--branch-name)
branch_name="${argv[$i]}"
i=$((i + 1))
;;
-B|--base-branch)
base_branch="${argv[$i]}"
i=$((i + 1))
;;
-r|--reverse)
cmd="tac"
i=$((i + 1))
;;
*)
usage
;;
esac
done

git checkout -B "${branch_name}"
git reset --hard "${base_branch}"
GIT_SEQUENCE_EDITOR="${cmd} ${file} | awk '{ print \"pick \" \$0; }' >" \
git rebase -i --rerere-autoupdate "${base_branch}"

I run it using:

$ git-backport --commit-file stable-commits.txt --base-branch linux-5.15.y --branch-name dsa-5.15.y --reverse

You can add commits to the commit list pretty much anywhere, and run the sorting script afterwards:

$ git sort-commit-list --commit-file stable-commits.txt --oldest-commit v5.15 --newest-commit 5dc760d12082 | tee stable-commits-sorted.txt

You'll probably need to add more, and rebase onto a different base branch for OpenWRT. Nonetheless, it should be a valid start.
Have fun and let me know if you have something useful to share back!

2022-09-06 17:04:55

by Colin Foster

[permalink] [raw]
Subject: Re: [PATCH net-next 0/9] DSA changes for multiple CPU ports (part 4)

On Sun, Sep 04, 2022 at 07:34:14PM +0000, Vladimir Oltean wrote:
> On Fri, Sep 02, 2022 at 08:44:37PM +0200, Christian Marangi wrote:
> For transparency, here is the commit list I used to produce the backport (top-most is most recent):

Tangentially related: how did you come up with this list?

I can only assume this is a manual process based on intricate knowledge
of net / DSA as a whole. I just want to make sure there isn't a "git
backport net/dsa origin/master v5.10" sort of thing ;-)

>
> $ cat stable-commits.txt
> 5dc760d12082 net: dsa: use dsa_tree_for_each_cpu_port in dsa_tree_{setup,teardown}_master
> f41ec1fd1c20 net: dsa: all DSA masters must be down when changing the tagging protocol
> 7136097e1199 net: dsa: only bring down user ports assigned to a given DSA master
> 4f03dcc6b9a0 net: dsa: existing DSA masters cannot join upper interfaces
> 920a33cd7231 net: bridge: move DSA master bridging restriction to DSA
> 0498277ee17b net: dsa: don't stop at NOTIFY_OK when calling ds->ops->port_prechangeupper
> 4c3f80d22b2e net: dsa: walk through all changeupper notifier functions
> be6ff9665d64 net: dsa: don't emit targeted cross-chip notifiers for MTU change
> 4715029fa7e9 net: dsa: drop dsa_slave_priv from dsa_slave_change_mtu
> cf1c39d3b3a5 net: dsa: avoid one dsa_to_port() in dsa_slave_change_mtu
> b2033a05a719 net: dsa: use dsa_tree_for_each_user_port in dsa_slave_change_mtu
> 726816a129cb net: dsa: make cross-chip notifiers more efficient for host events
> 8e9e678e4758 net: dsa: move reset of VLAN filtering to dsa_port_switchdev_unsync_attrs
> 762c2998c962 Revert "net: dsa: setup master before ports"
> 8e6598a7b0fa net: dsa: Pass VLAN MSTI migration notifications to driver
> 332afc4c8c0d net: dsa: Validate hardware support for MST
> f54fd0e16306 net: bridge: mst: Add helper to query a port's MST state
> 48d57b2e5f43 net: bridge: mst: Add helper to check if MST is enabled
> cceac97afa09 net: bridge: mst: Add helper to map an MSTI to a VID set
> 7ae9147f4312 net: bridge: mst: Notify switchdev drivers of MST state changes
> 6284c723d9b9 net: bridge: mst: Notify switchdev drivers of VLAN MSTI migrations
> 87c167bb94ee net: bridge: mst: Notify switchdev drivers of MST mode changes
> 122c29486e1f net: bridge: mst: Support setting and reporting MST port states
> 8c678d60562f net: bridge: mst: Allow changing a VLAN's MSTI
> ec7328b59176 net: bridge: mst: Multiple Spanning Tree (MST) mode
> 0832cd9f1f02 net: dsa: warn if port lists aren't empty in dsa_port_teardown
> afb3cc1a397d net: dsa: unlock the rtnl_mutex when dsa_master_setup() fails
> 7569459a52c9 net: dsa: manage flooding on the CPU ports
> 499aa9e1b332 net: dsa: install the primary unicast MAC address as standalone port host FDB
> 5e8a1e03aa4d net: dsa: install secondary unicast and multicast addresses as host FDB/MDB
> 68d6d71eafd1 net: dsa: rename the host FDB and MDB methods to contain the "bridge" namespace
> 35aae5ab9121 net: dsa: remove workarounds for changing master promisc/allmulti only while up
> 06b9cce42634 net: dsa: pass extack to .port_bridge_join driver methods
> c26933639b54 net: dsa: request drivers to perform FDB isolation
> b6362bdf750b net: dsa: tag_8021q: rename dsa_8021q_bridge_tx_fwd_offload_vid
> 04b67e18ce5b net: dsa: tag_8021q: merge RX and TX VLANs
> 08f44db3abe6 net: dsa: felix: delete workarounds present due to SVL tag_8021q bridging
> d27656d02d85 docs: net: dsa: sja1105: document limitations of tc-flower rule VLAN awareness
> d7f9787a763f net: dsa: tag_8021q: add support for imprecise RX based on the VBID
> 91495f21fcec net: dsa: tag_8021q: replace the SVL bridging with VLAN-unaware IVL bridging
> 961d8b699070 net: dsa: felix: support FDB entries on offloaded LAG interfaces
> e212fa7c5418 net: dsa: support FDB events on offloaded LAG interfaces
> 93c798230af5 net: dsa: call SWITCHDEV_FDB_OFFLOADED for the orig_dev
> e35f12e993d4 net: dsa: remove "ds" and "port" from struct dsa_switchdev_event_work
> ec638740fce9 net: switchdev: remove lag_mod_cb from switchdev_handle_fdb_event_to_device
> dedd6a009f41 net: dsa: create a dsa_lag structure
> b99dbdf00bc1 net: dsa: mv88e6xxx: use dsa_switch_for_each_port in mv88e6xxx_lag_sync_masks
> 3d4a0a2a46ab net: dsa: make LAG IDs one-based
> 066ce9779c7a net: dsa: qca8k: rename references to "lag" as "lag_dev"
> e23eba722861 net: dsa: mv88e6xxx: rename references to "lag" as "lag_dev"
> 46a76724e4c9 net: dsa: rename references to "lag" as "lag_dev"
> b9e8b58fd2cb net: dsa: Include BR_PORT_LOCKED in the list of synced brport flags
> a21d9a670d81 net: bridge: Add support for bridge port in locked mode
> acd8df5880d7 net: switchdev: avoid infinite recursion from LAG to bridge with port object handler
> 342b6419193c net: dsa: fix panic when removing unoffloaded port from bridge
> 8940e6b669ca net: dsa: avoid call to __dev_set_promiscuity() while rtnl_mutex isn't held
> ba43b547515e net: lan966x: remove guards against !BRIDGE_VLAN_INFO_BRENTRY
> e42bd4ed09aa net: mscc: ocelot: keep traps in a list
> 85ea0daabe5a net: mscc: ocelot: avoid overlap in VCAP IS2 between PTP and MRP traps
> b9bace6e534d net: mscc: ocelot: use a single VCAP filter for all MRP traps
> 36fac35b2907 net: mscc: ocelot: delete OCELOT_MRP_CPUQ
> c518afec2883 net: mscc: ocelot: consolidate cookie allocation for private VCAP rules
> e3c02b7c655c net: mscc: ocelot: use a consistent cookie for MRP traps
> 164f861bd40c net: dsa: offload bridge port VLANs on foreign interfaces
> 134ef2388e7f net: dsa: add explicit support for host bridge VLANs
> c4076cdd21f8 net: switchdev: introduce switchdev_handle_port_obj_{add,del} for foreign interfaces
> 7b465f4cf39e net: switchdev: rename switchdev_lower_dev_find to switchdev_lower_dev_find_rcu
> b28d580e2939 net: bridge: switchdev: replay all VLAN groups
> 263029ae3172 net: bridge: make nbp_switchdev_unsync_objs() follow reverse order of sync()
> 8d23a54f5bee net: bridge: switchdev: differentiate new VLANs from changed ones
> 27c5f74c7ba7 net: bridge: vlan: notify switchdev only when something changed
> cab2cd770051 net: bridge: vlan: make __vlan_add_flags react only to PVID and UNTAGGED
> 3116ad0696dd net: bridge: vlan: don't notify to switchdev master VLANs without BRENTRY flag
> b2bc58d41fde net: bridge: vlan: check early for lack of BRENTRY flag in br_vlan_add_existing
> ef5764057540 net: mscc: ocelot: fix use-after-free in ocelot_vlan_del()
> 5454f5c28eca net: bridge: vlan: check for errors from __vlan_del in __vlan_flush
> 867b1db874c9 net: lan966x: Fix when CONFIG_IPV6 is not set
> 1da52b0e4724 net: lan966x: Fix when CONFIG_PTP_1588_CLOCK is compiled as module
> 59085208e4a2 net: mscc: ocelot: fix all IP traffic getting trapped to CPU with PTP over IP
> 47aeea0d57e8 net: lan966x: Implement the callback SWITCHDEV_ATTR_ID_BRIDGE_MC_DISABLED
> cddbec19466a net: dsa: qca8k: add tracking state of master port
> e83d56537859 net: dsa: replay master state events in dsa_tree_{setup,teardown}_master
> 295ab96f478d net: dsa: provide switch operations for tracking the master state
> a1ff94c2973c net: dsa: stop updating master MTU from master.c
> 77eecf25bd9d net: lan966x: Update extraction/injection for timestamping
> 735fec995b21 net: lan966x: Implement SIOCSHWTSTAMP and SIOCGHWTSTAMP
> d096459494a8 net: lan966x: Add support for ptp clocks
> 108dc8741c20 net: dsa: Avoid cross-chip syncing of VLAN filtering
> 381a730182f1 net: dsa: Move VLAN filtering syncing out of dsa_switch_bridge_leave
> 5cad43a52ee3 net: dsa: felix: add port fast age support
> 1b26d364e4e9 net: dsa: warn about dsa_port and dsa_switch bit fields being non atomic
> 63cfc65753d6 net: dsa: don't enumerate dsa_switch and dsa_port bit fields using commas
> 11fd667dac31 net: dsa: setup master before ports
> 1e3f407f3cac net: dsa: first set up shared ports, then non-shared ports
> c146f9bc195a net: dsa: hold rtnl_mutex when calling dsa_master_{setup,teardown}
> a68dc7b938fb net: dsa: remove cross-chip support for HSR
> cad69019f2f8 net: dsa: remove cross-chip support for MRP
> 4b026e82893b net: dsa: combine two holes in struct dsa_switch_tree
> b035c88c6a30 net: dsa: move dsa_switch_tree :: ports and lags to first cache line
> 258030acc93b net: dsa: make dsa_switch :: num_ports an unsigned int
> 7787ff776398 net: dsa: merge all bools of struct dsa_switch into a single u32
> 0625125877da net: dsa: move dsa_port :: type near dsa_port :: index
> bde82f389af1 net: dsa: merge all bools of struct dsa_port into a single u8
> b08db33dabd1 net: dsa: move dsa_port :: stp_state near dsa_port :: mac
> 7aacb894b1ad net: lan966x: Extend switchdev with mdb support
> 11b0a27772f5 net: lan966x: Add PGID_GP_START and PGID_GP_END
> fc0c3fe7486f net: lan966x: Add function lan966x_mac_ip_learn()
> 0c94d657d2a4 net: lan966x: Fix the vlan used by host ports
> 2e49761e4fd1 net: lan966x: Add support for multiple bridge flags
> 811ba2771182 net: lan966x: Extend switchdev with fdb support
> e14f72398df4 net: lan966x: Extend switchdev bridge flags
> 6d2c186afa5d net: lan966x: Add vlan support.
> cf2f60897e92 net: lan966x: Add support to offload the forwarding.
> 571bb516a869 net: lan966x: Remove .ndo_change_rx_flags
> 25ee9561ec62 net: lan966x: More MAC table functionality
> 5ccd66e01cbe net: lan966x: add support for interrupts from analyzer
> ef14049f4db9 net: lan966x: Add registers that are used for switch and vlan functionality
> 7f2973149c22 net: dsa: make tagging protocols connect to individual switches from a tree
> e2f01bfe1406 net: dsa: tag_sja1105: fix zeroization of ds->priv on tag proto disconnect
> b26980ab2a97 net: lan966x: Fix the configuration of the pcs
> 950a419d9de1 net: dsa: tag_sja1105: split sja1105_tagger_data into private and public sections
> fcbf979a5b4b Revert "net: dsa: move sja1110_process_meta_tstamp inside the tagging protocol driver"
> c79e84866d2a net: dsa: tag_sja1105: convert to tagger-owned data
> 22ee9f8e4011 net: dsa: sja1105: move ts_id from sja1105_tagger_data
> bfcf14252220 net: dsa: sja1105: make dp->priv point directly to sja1105_tagger_data
> 6f6770ab1ce2 net: dsa: sja1105: remove hwts_tx_en from tagger data
> d38049bbe760 net: dsa: sja1105: bring deferred xmit implementation in line with ocelot-8021q
> a3d74295d790 net: dsa: sja1105: let deferred packets time out when sent to ports going down
> 35d976802124 net: dsa: tag_ocelot: convert to tagger-owned data
> dc452a471dba net: dsa: introduce tagger-owned storage for private and shared data
> 857fdd74fb38 net: dsa: eliminate dsa_switch_ops :: port_bridge_tx_fwd_{,un}offload
> b079922ba2ac net: dsa: add a "tx_fwd_offload" argument to ->port_bridge_join
> d3eed0e57d5d net: dsa: keep the bridge_dev and bridge_num as part of the same structure
> 6a43cba30340 net: dsa: export bridging offload helpers to drivers
> 936db8a2dba2 net: dsa: rename dsa_port_offloads_bridge to dsa_port_offloads_bridge_dev
> 41fb0cf1bced net: dsa: hide dp->bridge_dev and dp->bridge_num in drivers behind helpers
> 36cbf39b5690 net: dsa: hide dp->bridge_dev and dp->bridge_num in the core behind helpers
> 65144067d360 net: dsa: mv88e6xxx: compute port vlan membership based on dp->bridge_dev comparison
> 0493fa7927af net: dsa: mv88e6xxx: iterate using dsa_switch_for_each_user_port in mv88e6xxx_port_check_hw_vlan
> 872bb81dfbc3 net: dsa: mt7530: iterate using dsa_switch_for_each_user_port in bridging ops
> 947c8746e2c3 net: dsa: assign a bridge number even without TX forwarding offload
> 3f9bb0301d50 net: dsa: make dp->bridge_num one-based
> bb14bfc7eb92 net: lan966x: fix a IS_ERR() vs NULL check in lan966x_create_targets()
> cc9cf69eea48 net: lan966x: Fix builds for lan966x driver
> a290cf692779 net: lan966x: Fix duplicate check in frame extraction
> 12c2d0a5b8e2 net: lan966x: add ethtool configuration and statistics
> e18aba8941b4 net: lan966x: add mactable support
> d28d6d2e37d1 net: lan966x: add port module support
> db8bcaad5393 net: lan966x: add the basic lan966x driver
> ef136837aaf6 net: dsa: rtl8365mb: set RGMII RX delay in steps of 0.3 ns
> b014861d96a6 net: dsa: realtek-smi: don't log an error on EPROBE_DEFER
> 1e89ad864d03 net: dsa: realtek-smi: fix indirect reg access for ports>3
> b3612ccdf284 net: dsa: microchip: implement multi-bridge support
> 96ca08c05838 net: mscc: ocelot: set up traps for PTP packets
> ec15baec3272 net: ptp: add a definition for the UDP port for IEEE 1588 general messages
> 95706be13b9f net: mscc: ocelot: create a function that replaces an existing VCAP filter
> 8abe19703825 net: dsa: felix: enable cut-through forwarding between ports by default
> a8bd9fa5b527 net: ocelot: remove "bridge" argument from ocelot_get_bridge_fwd_mask
> 4636440f913b net: dsa: qca8k: Fix spelling mistake "Mismateched" -> "Mismatched"
> 0898ca67b86e net: dsa: qca8k: fix warning in LAG feature
> def975307c01 net: dsa: qca8k: add LAG support
> 2c1bdbc7e756 net: dsa: qca8k: add support for mirror mode
> ba8f870dfa63 net: dsa: qca8k: add support for mdb_add/del
> 6a3bdc5209f4 net: dsa: qca8k: add set_ageing_time support
> 4592538bfb0d net: dsa: qca8k: add support for port fast aging
> c126f118b330 net: dsa: qca8k: add additional MIB counter and make it dynamic
> 8b5f3f29a81a net: dsa: qca8k: initial conversion to regmap helper
> 36b8af12f424 net: dsa: qca8k: move regmap init in probe and set it mandatory
> 994c28b6f971 net: dsa: qca8k: remove extra mutex_init in qca8k_setup
> 90ae68bfc2ff net: dsa: qca8k: convert to GENMASK/FIELD_PREP/FIELD_GET
> b9133f3ef5a2 net: dsa: qca8k: remove redundant check in parse_port_config
> 65258b9d8cde net: dsa: qca8k: fix MTU calculation
> 3b00a07c2443 net: dsa: qca8k: fix internal delay applied to the wrong PAD config
> a7e13edf37be net: dsa: felix: restrict psfp rules on ingress port
> 76c13ede7120 net: dsa: felix: use vcap policer to set flow meter for psfp
> 77043c37096d net: mscc: ocelot: use index to set vcap policer
> 23ae3a787771 net: dsa: felix: add stream gate settings for psfp
> 7d4b564d6add net: dsa: felix: support psfp filter on vsc9959
> 23e2c506ad6c net: mscc: ocelot: add gate and police action offload to PSFP
> 5b1918a54a91 net: mscc: ocelot: set vcap IS2 chain to goto PSFP chain
> 0568c3bf3f34 net: mscc: ocelot: add MAC table stream learn and lookup operations
> 02d6fdecb9c3 regmap: allow to define reg_update_bits for no bus configuration
> 5f15d392dcb4 net: dsa: qca8k: make sure PAD0 MAC06 exchange is disabled
> ae0393500e3b net: bridge: switchdev: fix shim definition for br_switchdev_mdb_notify
> 326b212e9cd6 net: bridge: switchdev: consistent function naming
> 9776457c784f net: bridge: mdb: move all switchdev logic to br_switchdev.c
> 9ae9ff994b0e net: bridge: split out the switchdev portion of br_mdb_notify
> 4a6849e46173 net: bridge: move br_vlan_replay to br_switchdev.c
> c5f6e5ebc2af net: bridge: provide shim definition for br_vlan_flags
> 716a30a97a52 net: switchdev: merge switchdev_handle_fdb_{add,del}_to_device
> fab9eca88410 net: bridge: create a common function for populating switchdev FDB entries
> 5cda5272a460 net: bridge: move br_fdb_replay inside br_switchdev.c
> 9574fb558044 net: bridge: reduce indentation level in fdb_create
> f6814fdcfe1b net: bridge: rename br_fdb_insert to br_fdb_add_local
> 4731b6d6b257 net: bridge: rename fdb_insert to fdb_add_local
> 5f94a5e276ae net: bridge: remove fdb_insert forward declaration
> 4682048af0c8 net: bridge: remove fdb_notify forward declaration
> 425d19cedef8 net: dsa: stop calling dev_hold in dsa_slave_fdb_event
> d7d0d423dbaa net: dsa: flush switchdev workqueue when leaving the bridge
> 0faf890fc519 net: dsa: drop rtnl_lock from dsa_slave_switchdev_event_work
> 338a3a4745aa net: dsa: introduce locking for the address lists on CPU and DSA ports
> cf231b436f7c net: dsa: lantiq_gswip: serialize access to the PCE registers
> f7eb4a1c0864 net: dsa: b53: serialize access to the ARL table
> edc90d15850c selftests: net: dsa: add a stress test for unlocked FDB operations
> 016748961ba5 selftests: lib: forwarding: allow tests to not require mz and jq
> f239934cffe5 net: dsa: b53: serialize access to the ARL table
> f2c4bdf62d76 net: mscc: ocelot: serialize access to the MAC table
> 1681ae1691ef net: dsa: sja1105: serialize access to the dynamic config interface
> 643979cf5ec4 net: dsa: sja1105: wait for dynamic config command completion on writes too
> 992e5cc7be8e net: dsa: tag_8021q: make dsa_8021q_{rx,tx}_vid take dp as argument
> 5068887a4fbe net: dsa: tag_sja1105: do not open-code dsa_switch_for_each_port
> fac6abd5f132 net: dsa: convert cross-chip notifiers to iterate using dp
> 57d77986e742 net: dsa: remove gratuitous use of dsa_is_{user,dsa,cpu}_port
> 65c563a67755 net: dsa: do not open-code dsa_switch_for_each_port
> d0004a020bb5 net: dsa: remove the "dsa_to_port in a loop" antipattern from the core
> 82b318983c51 net: dsa: introduce helpers for iterating through ports using dp
> d4004422f6f9 net: mscc: ocelot: track the port pvid using a pointer
> bfbab3104413 net: mscc: ocelot: add the local station MAC addresses in VID 0
> 0da1a1c48911 net: mscc: ocelot: allow a config where all bridge VLANs are egress-untagged
> 90e0aa8d108d net: mscc: ocelot: convert the VLAN masks to a list
> 62a22bcbd30e net: mscc: ocelot: add a type definition for REW_TAG_CFG_TAG_CFG
> 040e926f5813 net: dsa: qca8k: tidy for loop in setup and add cpu port check
> 9ca482a246f0 net: dsa: sja1105: parse {rx, tx}-internal-delay-ps properties for RGMII delays
> 4af2950c50c8 net: dsa: realtek-smi: add rtl8365mb subdriver for RTL8365MB-VC
> 1521d5adfc2b net: dsa: tag_rtl8_4: add realtek 8 byte protocol 4 tag
> 9cb8edda2157 net: dsa: move NET_DSA_TAG_RTL4_A to right place in Kconfig/Makefile
> 7bbbbfaa7a1b ether: add EtherType for proprietary Realtek protocols
> fd0bb28c547f net: dsa: qca8k: move port config to dedicated struct
> cef08115846e net: dsa: qca8k: set internal delay also for sgmii
> f477d1c8bdbe net: dsa: qca8k: add support for QCA8328
> ed7988d77fbf dt-bindings: net: dsa: qca8k: document support for qca8328
> 362bb238d8bf net: dsa: qca8k: add support for pws config reg
> 924087c5c3d4 dt-bindings: net: dsa: qca8k: Document qca,led-open-drain binding
> bbc4799e8bb6 net: dsa: qca8k: add explicit SGMII PLL enable
> 13ad5ccc093f dt-bindings: net: dsa: qca8k: Document qca,sgmii-enable-pll
> 5654ec78dd7e net: dsa: qca8k: rework rgmii delay logic and scan for cpu port 6
> 3fcf734aa482 net: dsa: qca8k: add support for cpu port 6
> 731d613338ec dt-bindings: net: dsa: qca8k: Document support for CPU port 6
> 6c43809bf1be net: dsa: qca8k: add support for sgmii falling edge
> fdbf35df9c09 dt-bindings: net: dsa: qca8k: Add SGMII clock phase properties
> d8b6f5bae6d3 dsa: qca8k: add mac_power_sel support
> 39e222bfd7f3 net: dsa: unregister cross-chip notifier after ds->ops->teardown
> 339e75f6b9a0 net: dsa: rtl8366rb: remove unneeded semicolon
> e674cfd08537 net: dsa: rtl8366rb: Support setting STP state
> 1fbd19e10b73 net: dsa: rtl8366rb: Support fast aging
> 56d8bb71a811 net: dsa: rtl8366rb: Support disabling learning
> 5ca721c54d86 net: dsa: tag_ocelot: set the classified VLAN during xmit
> e8c0722927e8 net: mscc: ocelot: write full VLAN TCI in the injection header
> de5bbb6f7e4c net: mscc: ocelot: support egress VLAN rewriting via VCAP ES0
> 55b115c7ecd9 net: dsa: rtl8366rb: Use core filtering tracking
> d310b14ae748 net: dsa: rtl8366: Drop and depromote pointless prints
> a4eff910ec63 net: dsa: rtl8366rb: Rewrite weird VLAN filering enablement
> 7776e33c68ae net: dsa: rtl8366: Drop custom VLAN set-up
> d5a680295be2 net: dsa: rtl8366rb: Support bridge offloading
> bd936bd53b2d net: dsa: Move devlink registration to be last devlink command
> 6d709cadfde6 net: dsa: move sja1110_process_meta_tstamp inside the tagging protocol driver
> 68a81bb2eebd net: dsa: sja1105: remove sp->dp
> db4278c55fa5 devlink: Make devlink_register to be void
> 4dcd183fbd67 net: wwan: iosm: devlink registration

2022-09-06 17:18:32

by Vladimir Oltean

[permalink] [raw]
Subject: Re: [PATCH net-next 0/9] DSA changes for multiple CPU ports (part 4)

On Tue, Sep 06, 2022 at 09:10:43AM -0700, Colin Foster wrote:
> On Sun, Sep 04, 2022 at 07:34:14PM +0000, Vladimir Oltean wrote:
> > On Fri, Sep 02, 2022 at 08:44:37PM +0200, Christian Marangi wrote:
> > For transparency, here is the commit list I used to produce the backport (top-most is most recent):
>
> Tangentially related: how did you come up with this list?
>
> I can only assume this is a manual process based on intricate knowledge
> of net / DSA as a whole. I just want to make sure there isn't a "git
> backport net/dsa origin/master v5.10" sort of thing ;-)

Years of practice ;)

Although I found a tool called git-deps and I ran it in a few places,
I found it to be fundamentally lacking for correct kernel backporting
work. The way that tool works is it finds patches related to the current
one based on what other lines from this patch's context they touch.
This obviously isn't going to work too well. There may very well be no
connection obvious to this tool between, say, a function prototype added
to include/net/dsa.h and its first use in drivers/net/dsa/mv88e6xxx/chip.c.
So it may not know it has to backport the include/net/dsa.h change.

I suspect one way in which git-deps may be modified in order to be much
more useful for kernel work is for it to backport the entire patch
series from which the dependency commit came. But (1) I don't know
python even enough to be able to manage a pip virtual environment, let
alone code up such a change, and (2) I'm not sure, from a kernel devel
process perspective, that we offer enough machine-parsable hints such
that a python program can just figure out "yes, these are the patches
that all belong to the same patch set as commit X".