License cleanup: add SPDX GPL-2.0 license identifier to files with no license
Many source files in the tree are missing licensing information, which
makes it harder for compliance tools to determine the correct license.
By default all files without license information are under the default
license of the kernel, which is GPL version 2.
Update the files which contain no license information with the 'GPL-2.0'
SPDX license identifier. The SPDX identifier is a legally binding
shorthand, which can be used instead of the full boiler plate text.
This patch is based on work done by Thomas Gleixner and Kate Stewart and
Philippe Ombredanne.
How this work was done:
Patches were generated and checked against linux-4.14-rc6 for a subset of
the use cases:
- file had no licensing information it it.
- file was a */uapi/* one with no licensing information in it,
- file was a */uapi/* one with existing licensing information,
Further patches will be generated in subsequent months to fix up cases
where non-standard license headers were used, and references to license
had to be inferred by heuristics based on keywords.
The analysis to determine which SPDX License Identifier to be applied to
a file was done in a spreadsheet of side by side results from of the
output of two independent scanners (ScanCode & Windriver) producing SPDX
tag:value files created by Philippe Ombredanne. Philippe prepared the
base worksheet, and did an initial spot review of a few 1000 files.
The 4.13 kernel was the starting point of the analysis with 60,537 files
assessed. Kate Stewart did a file by file comparison of the scanner
results in the spreadsheet to determine which SPDX license identifier(s)
to be applied to the file. She confirmed any determination that was not
immediately clear with lawyers working with the Linux Foundation.
Criteria used to select files for SPDX license identifier tagging was:
- Files considered eligible had to be source code files.
- Make and config files were included as candidates if they contained >5
lines of source
- File already had some variant of a license header in it (even if <5
lines).
All documentation files were explicitly excluded.
The following heuristics were used to determine which SPDX license
identifiers to apply.
- when both scanners couldn't find any license traces, file was
considered to have no license information in it, and the top level
COPYING file license applied.
For non */uapi/* files that summary was:
SPDX license identifier # files
---------------------------------------------------|-------
GPL-2.0 11139
and resulted in the first patch in this series.
If that file was a */uapi/* path one, it was "GPL-2.0 WITH
Linux-syscall-note" otherwise it was "GPL-2.0". Results of that was:
SPDX license identifier # files
---------------------------------------------------|-------
GPL-2.0 WITH Linux-syscall-note 930
and resulted in the second patch in this series.
- if a file had some form of licensing information in it, and was one
of the */uapi/* ones, it was denoted with the Linux-syscall-note if
any GPL family license was found in the file or had no licensing in
it (per prior point). Results summary:
SPDX license identifier # files
---------------------------------------------------|------
GPL-2.0 WITH Linux-syscall-note 270
GPL-2.0+ WITH Linux-syscall-note 169
((GPL-2.0 WITH Linux-syscall-note) OR BSD-2-Clause) 21
((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) 17
LGPL-2.1+ WITH Linux-syscall-note 15
GPL-1.0+ WITH Linux-syscall-note 14
((GPL-2.0+ WITH Linux-syscall-note) OR BSD-3-Clause) 5
LGPL-2.0+ WITH Linux-syscall-note 4
LGPL-2.1 WITH Linux-syscall-note 3
((GPL-2.0 WITH Linux-syscall-note) OR MIT) 3
((GPL-2.0 WITH Linux-syscall-note) AND MIT) 1
and that resulted in the third patch in this series.
- when the two scanners agreed on the detected license(s), that became
the concluded license(s).
- when there was disagreement between the two scanners (one detected a
license but the other didn't, or they both detected different
licenses) a manual inspection of the file occurred.
- In most cases a manual inspection of the information in the file
resulted in a clear resolution of the license that should apply (and
which scanner probably needed to revisit its heuristics).
- When it was not immediately clear, the license identifier was
confirmed with lawyers working with the Linux Foundation.
- If there was any question as to the appropriate license identifier,
the file was flagged for further research and to be revisited later
in time.
In total, over 70 hours of logged manual review was done on the
spreadsheet to determine the SPDX license identifiers to apply to the
source files by Kate, Philippe, Thomas and, in some cases, confirmation
by lawyers working with the Linux Foundation.
Kate also obtained a third independent scan of the 4.13 code base from
FOSSology, and compared selected files where the other two scanners
disagreed against that SPDX file, to see if there was new insights. The
Windriver scanner is based on an older version of FOSSology in part, so
they are related.
Thomas did random spot checks in about 500 files from the spreadsheets
for the uapi headers and agreed with SPDX license identifier in the
files he inspected. For the non-uapi files Thomas did random spot checks
in about 15000 files.
In initial set of patches against 4.14-rc6, 3 files were found to have
copy/paste license identifier errors, and have been fixed to reflect the
correct identifier.
Additionally Philippe spent 10 hours this week doing a detailed manual
inspection and review of the 12,461 patched files from the initial patch
version early this week with:
- a full scancode scan run, collecting the matched texts, detected
license ids and scores
- reviewing anything where there was a license detected (about 500+
files) to ensure that the applied SPDX license was correct
- reviewing anything where there was no detection but the patch license
was not GPL-2.0 WITH Linux-syscall-note to ensure that the applied
SPDX license was correct
This produced a worksheet with 20 files needing minor correction. This
worksheet was then exported into 3 different .csv files for the
different types of files to be modified.
These .csv files were then reviewed by Greg. Thomas wrote a script to
parse the csv files and add the proper SPDX tag to the file, in the
format that the file expected. This script was further refined by Greg
based on the output to detect more types of files automatically and to
distinguish between header and source .c files (which need different
comment types.) Finally Greg ran the script using the .csv files to
generate the patches.
Reviewed-by: Kate Stewart <kstewart@linuxfoundation.org>
Reviewed-by: Philippe Ombredanne <pombredanne@nexb.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2017-11-01 17:07:57 +03:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
2016-08-25 19:42:37 +03:00
|
|
|
#include <linux/kernel.h>
|
|
|
|
#include <linux/list.h>
|
|
|
|
#include <linux/netdevice.h>
|
|
|
|
#include <linux/rtnetlink.h>
|
|
|
|
#include <linux/skbuff.h>
|
|
|
|
#include <net/switchdev.h>
|
|
|
|
|
|
|
|
#include "br_private.h"
|
|
|
|
|
|
|
|
static int br_switchdev_mark_get(struct net_bridge *br, struct net_device *dev)
|
|
|
|
{
|
|
|
|
struct net_bridge_port *p;
|
|
|
|
|
|
|
|
/* dev is yet to be added to the port list. */
|
|
|
|
list_for_each_entry(p, &br->port_list, list) {
|
2019-02-06 20:45:46 +03:00
|
|
|
if (netdev_port_same_parent_id(dev, p->dev))
|
2016-08-25 19:42:37 +03:00
|
|
|
return p->offload_fwd_mark;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ++br->offload_fwd_mark;
|
|
|
|
}
|
|
|
|
|
|
|
|
int nbp_switchdev_mark_set(struct net_bridge_port *p)
|
|
|
|
{
|
2019-02-06 20:45:46 +03:00
|
|
|
struct netdev_phys_item_id ppid = { };
|
2016-08-25 19:42:37 +03:00
|
|
|
int err;
|
|
|
|
|
|
|
|
ASSERT_RTNL();
|
|
|
|
|
2019-02-06 20:45:46 +03:00
|
|
|
err = dev_get_port_parent_id(p->dev, &ppid, true);
|
2016-08-25 19:42:37 +03:00
|
|
|
if (err) {
|
|
|
|
if (err == -EOPNOTSUPP)
|
|
|
|
return 0;
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
p->offload_fwd_mark = br_switchdev_mark_get(p->br, p->dev);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void nbp_switchdev_frame_mark(const struct net_bridge_port *p,
|
|
|
|
struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
if (skb->offload_fwd_mark && !WARN_ON_ONCE(!p->offload_fwd_mark))
|
|
|
|
BR_INPUT_SKB_CB(skb)->offload_fwd_mark = p->offload_fwd_mark;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool nbp_switchdev_allowed_egress(const struct net_bridge_port *p,
|
|
|
|
const struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
return !skb->offload_fwd_mark ||
|
|
|
|
BR_INPUT_SKB_CB(skb)->offload_fwd_mark != p->offload_fwd_mark;
|
|
|
|
}
|
2017-06-08 09:44:11 +03:00
|
|
|
|
|
|
|
/* Flags that can be offloaded to hardware */
|
|
|
|
#define BR_PORT_FLAGS_HW_OFFLOAD (BR_LEARNING | BR_FLOOD | \
|
|
|
|
BR_MCAST_FLOOD | BR_BCAST_FLOOD)
|
|
|
|
|
|
|
|
int br_switchdev_set_port_flag(struct net_bridge_port *p,
|
|
|
|
unsigned long flags,
|
2021-02-12 18:15:53 +03:00
|
|
|
unsigned long mask,
|
|
|
|
struct netlink_ext_ack *extack)
|
2017-06-08 09:44:11 +03:00
|
|
|
{
|
|
|
|
struct switchdev_attr attr = {
|
|
|
|
.orig_dev = p->dev,
|
|
|
|
};
|
2019-02-27 22:44:31 +03:00
|
|
|
struct switchdev_notifier_port_attr_info info = {
|
|
|
|
.attr = &attr,
|
|
|
|
};
|
2017-06-08 09:44:11 +03:00
|
|
|
int err;
|
|
|
|
|
2021-02-12 18:15:52 +03:00
|
|
|
mask &= BR_PORT_FLAGS_HW_OFFLOAD;
|
|
|
|
if (!mask)
|
2017-06-08 09:44:11 +03:00
|
|
|
return 0;
|
|
|
|
|
net: switchdev: pass flags and mask to both {PRE_,}BRIDGE_FLAGS attributes
This switchdev attribute offers a counterproductive API for a driver
writer, because although br_switchdev_set_port_flag gets passed a
"flags" and a "mask", those are passed piecemeal to the driver, so while
the PRE_BRIDGE_FLAGS listener knows what changed because it has the
"mask", the BRIDGE_FLAGS listener doesn't, because it only has the final
value. But certain drivers can offload only certain combinations of
settings, like for example they cannot change unicast flooding
independently of multicast flooding - they must be both on or both off.
The way the information is passed to switchdev makes drivers not
expressive enough, and unable to reject this request ahead of time, in
the PRE_BRIDGE_FLAGS notifier, so they are forced to reject it during
the deferred BRIDGE_FLAGS attribute, where the rejection is currently
ignored.
This patch also changes drivers to make use of the "mask" field for edge
detection when possible.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Grygorii Strashko <grygorii.strashko@ti.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-02-12 18:15:55 +03:00
|
|
|
attr.id = SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS;
|
|
|
|
attr.u.brport_flags.val = flags;
|
|
|
|
attr.u.brport_flags.mask = mask;
|
2021-02-12 18:15:52 +03:00
|
|
|
|
2019-02-27 22:44:31 +03:00
|
|
|
/* We run from atomic context here */
|
|
|
|
err = call_switchdev_notifiers(SWITCHDEV_PORT_ATTR_SET, p->dev,
|
2021-02-12 18:15:53 +03:00
|
|
|
&info.info, extack);
|
2019-02-27 22:44:31 +03:00
|
|
|
err = notifier_to_errno(err);
|
2017-06-08 09:44:11 +03:00
|
|
|
if (err == -EOPNOTSUPP)
|
|
|
|
return 0;
|
|
|
|
|
2019-02-21 03:58:24 +03:00
|
|
|
if (err) {
|
2021-02-12 18:15:53 +03:00
|
|
|
if (extack && !extack->_msg)
|
|
|
|
NL_SET_ERR_MSG_MOD(extack,
|
|
|
|
"bridge flag offload is not supported");
|
2017-06-08 09:44:11 +03:00
|
|
|
return -EOPNOTSUPP;
|
|
|
|
}
|
|
|
|
|
|
|
|
attr.id = SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS;
|
|
|
|
attr.flags = SWITCHDEV_F_DEFER;
|
2019-02-21 03:58:24 +03:00
|
|
|
|
2021-02-13 23:43:17 +03:00
|
|
|
err = switchdev_port_attr_set(p->dev, &attr, extack);
|
2017-06-08 09:44:11 +03:00
|
|
|
if (err) {
|
2021-02-13 23:43:17 +03:00
|
|
|
if (extack && !extack->_msg)
|
|
|
|
NL_SET_ERR_MSG_MOD(extack,
|
|
|
|
"error setting offload flag on port");
|
2017-06-08 09:44:11 +03:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2017-06-08 09:44:14 +03:00
|
|
|
|
|
|
|
static void
|
|
|
|
br_switchdev_fdb_call_notifiers(bool adding, const unsigned char *mac,
|
2018-05-03 15:43:46 +03:00
|
|
|
u16 vid, struct net_device *dev,
|
2018-10-17 11:53:29 +03:00
|
|
|
bool added_by_user, bool offloaded)
|
2017-06-08 09:44:14 +03:00
|
|
|
{
|
|
|
|
struct switchdev_notifier_fdb_info info;
|
|
|
|
unsigned long notifier_type;
|
|
|
|
|
|
|
|
info.addr = mac;
|
|
|
|
info.vid = vid;
|
2018-05-03 15:43:46 +03:00
|
|
|
info.added_by_user = added_by_user;
|
2018-10-17 11:53:29 +03:00
|
|
|
info.offloaded = offloaded;
|
2017-06-08 09:44:14 +03:00
|
|
|
notifier_type = adding ? SWITCHDEV_FDB_ADD_TO_DEVICE : SWITCHDEV_FDB_DEL_TO_DEVICE;
|
2019-01-17 02:06:56 +03:00
|
|
|
call_switchdev_notifiers(notifier_type, dev, &info.info, NULL);
|
2017-06-08 09:44:14 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
br_switchdev_fdb_notify(const struct net_bridge_fdb_entry *fdb, int type)
|
|
|
|
{
|
2018-05-03 15:43:53 +03:00
|
|
|
if (!fdb->dst)
|
2017-06-08 09:44:14 +03:00
|
|
|
return;
|
net: bridge: don't notify switchdev for local FDB addresses
As explained in this discussion:
https://lore.kernel.org/netdev/20210117193009.io3nungdwuzmo5f7@skbuf/
the switchdev notifiers for FDB entries managed to have a zero-day bug.
The bridge would not say that this entry is local:
ip link add br0 type bridge
ip link set swp0 master br0
bridge fdb add dev swp0 00:01:02:03:04:05 master local
and the switchdev driver would be more than happy to offload it as a
normal static FDB entry. This is despite the fact that 'local' and
non-'local' entries have completely opposite directions: a local entry
is locally terminated and not forwarded, whereas a static entry is
forwarded and not locally terminated. So, for example, DSA would install
this entry on swp0 instead of installing it on the CPU port as it should.
There is an even sadder part, which is that the 'local' flag is implicit
if 'static' is not specified, meaning that this command produces the
same result of adding a 'local' entry:
bridge fdb add dev swp0 00:01:02:03:04:05 master
I've updated the man pages for 'bridge', and after reading it now, it
should be pretty clear to any user that the commands above were broken
and should have never resulted in the 00:01:02:03:04:05 address being
forwarded (this behavior is coherent with non-switchdev interfaces):
https://patchwork.kernel.org/project/netdevbpf/cover/20210211104502.2081443-1-olteanv@gmail.com/
If you're a user reading this and this is what you want, just use:
bridge fdb add dev swp0 00:01:02:03:04:05 master static
Because switchdev should have given drivers the means from day one to
classify FDB entries as local/non-local, but didn't, it means that all
drivers are currently broken. So we can just as well omit the switchdev
notifications for local FDB entries, which is exactly what this patch
does to close the bug in stable trees. For further development work
where drivers might want to trap the local FDB entries to the host, we
can add a 'bool is_local' to br_switchdev_fdb_call_notifiers(), and
selectively make drivers act upon that bit, while all the others ignore
those entries if the 'is_local' bit is set.
Fixes: 6b26b51b1d13 ("net: bridge: Add support for notifying devices about FDB add/del")
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-03-22 21:21:08 +03:00
|
|
|
if (test_bit(BR_FDB_LOCAL, &fdb->flags))
|
|
|
|
return;
|
2017-06-08 09:44:14 +03:00
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case RTM_DELNEIGH:
|
2017-12-12 17:02:50 +03:00
|
|
|
br_switchdev_fdb_call_notifiers(false, fdb->key.addr.addr,
|
|
|
|
fdb->key.vlan_id,
|
2018-05-03 15:43:46 +03:00
|
|
|
fdb->dst->dev,
|
2019-10-29 14:45:56 +03:00
|
|
|
test_bit(BR_FDB_ADDED_BY_USER,
|
|
|
|
&fdb->flags),
|
2019-10-29 14:45:58 +03:00
|
|
|
test_bit(BR_FDB_OFFLOADED,
|
|
|
|
&fdb->flags));
|
2017-06-08 09:44:14 +03:00
|
|
|
break;
|
|
|
|
case RTM_NEWNEIGH:
|
2017-12-12 17:02:50 +03:00
|
|
|
br_switchdev_fdb_call_notifiers(true, fdb->key.addr.addr,
|
|
|
|
fdb->key.vlan_id,
|
2018-05-03 15:43:46 +03:00
|
|
|
fdb->dst->dev,
|
2019-10-29 14:45:56 +03:00
|
|
|
test_bit(BR_FDB_ADDED_BY_USER,
|
|
|
|
&fdb->flags),
|
2019-10-29 14:45:58 +03:00
|
|
|
test_bit(BR_FDB_OFFLOADED,
|
|
|
|
&fdb->flags));
|
2017-06-08 09:44:14 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2018-05-30 03:56:03 +03:00
|
|
|
|
2018-12-12 20:02:50 +03:00
|
|
|
int br_switchdev_port_vlan_add(struct net_device *dev, u16 vid, u16 flags,
|
|
|
|
struct netlink_ext_ack *extack)
|
2018-05-30 03:56:03 +03:00
|
|
|
{
|
|
|
|
struct switchdev_obj_port_vlan v = {
|
|
|
|
.obj.orig_dev = dev,
|
|
|
|
.obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN,
|
|
|
|
.flags = flags,
|
net: switchdev: remove vid_begin -> vid_end range from VLAN objects
The call path of a switchdev VLAN addition to the bridge looks something
like this today:
nbp_vlan_init
| __br_vlan_set_default_pvid
| | |
| | br_afspec |
| | | |
| | v |
| | br_process_vlan_info |
| | | |
| | v |
| | br_vlan_info |
| | / \ /
| | / \ /
| | / \ /
| | / \ /
v v v v v
nbp_vlan_add br_vlan_add ------+
| ^ ^ | |
| / | | |
| / / / |
\ br_vlan_get_master/ / v
\ ^ / / br_vlan_add_existing
\ | / / |
\ | / / /
\ | / / /
\ | / / /
\ | / / /
v | | v /
__vlan_add /
/ | /
/ | /
v | /
__vlan_vid_add | /
\ | /
v v v
br_switchdev_port_vlan_add
The ranges UAPI was introduced to the bridge in commit bdced7ef7838
("bridge: support for multiple vlans and vlan ranges in setlink and
dellink requests") (Jan 10 2015). But the VLAN ranges (parsed in br_afspec)
have always been passed one by one, through struct bridge_vlan_info
tmp_vinfo, to br_vlan_info. So the range never went too far in depth.
Then Scott Feldman introduced the switchdev_port_bridge_setlink function
in commit 47f8328bb1a4 ("switchdev: add new switchdev bridge setlink").
That marked the introduction of the SWITCHDEV_OBJ_PORT_VLAN, which made
full use of the range. But switchdev_port_bridge_setlink was called like
this:
br_setlink
-> br_afspec
-> switchdev_port_bridge_setlink
Basically, the switchdev and the bridge code were not tightly integrated.
Then commit 41c498b9359e ("bridge: restore br_setlink back to original")
came, and switchdev drivers were required to implement
.ndo_bridge_setlink = switchdev_port_bridge_setlink for a while.
In the meantime, commits such as 0944d6b5a2fa ("bridge: try switchdev op
first in __vlan_vid_add/del") finally made switchdev penetrate the
br_vlan_info() barrier and start to develop the call path we have today.
But remember, br_vlan_info() still receives VLANs one by one.
Then Arkadi Sharshevsky refactored the switchdev API in 2017 in commit
29ab586c3d83 ("net: switchdev: Remove bridge bypass support from
switchdev") so that drivers would not implement .ndo_bridge_setlink any
longer. The switchdev_port_bridge_setlink also got deleted.
This refactoring removed the parallel bridge_setlink implementation from
switchdev, and left the only switchdev VLAN objects to be the ones
offloaded from __vlan_vid_add (basically RX filtering) and __vlan_add
(the latter coming from commit 9c86ce2c1ae3 ("net: bridge: Notify about
bridge VLANs")).
That is to say, today the switchdev VLAN object ranges are not used in
the kernel. Refactoring the above call path is a bit complicated, when
the bridge VLAN call path is already a bit complicated.
Let's go off and finish the job of commit 29ab586c3d83 by deleting the
bogus iteration through the VLAN ranges from the drivers. Some aspects
of this feature never made too much sense in the first place. For
example, what is a range of VLANs all having the BRIDGE_VLAN_INFO_PVID
flag supposed to mean, when a port can obviously have a single pvid?
This particular configuration _is_ denied as of commit 6623c60dc28e
("bridge: vlan: enforce no pvid flag in vlan ranges"), but from an API
perspective, the driver still has to play pretend, and only offload the
vlan->vid_end as pvid. And the addition of a switchdev VLAN object can
modify the flags of another, completely unrelated, switchdev VLAN
object! (a VLAN that is PVID will invalidate the PVID flag from whatever
other VLAN had previously been offloaded with switchdev and had that
flag. Yet switchdev never notifies about that change, drivers are
supposed to guess).
Nonetheless, having a VLAN range in the API makes error handling look
scarier than it really is - unwinding on errors and all of that.
When in reality, no one really calls this API with more than one VLAN.
It is all unnecessary complexity.
And despite appearing pretentious (two-phase transactional model and
all), the switchdev API is really sloppy because the VLAN addition and
removal operations are not paired with one another (you can add a VLAN
100 times and delete it just once). The bridge notifies through
switchdev of a VLAN addition not only when the flags of an existing VLAN
change, but also when nothing changes. There are switchdev drivers out
there who don't like adding a VLAN that has already been added, and
those checks don't really belong at driver level. But the fact that the
API contains ranges is yet another factor that prevents this from being
addressed in the future.
Of the existing switchdev pieces of hardware, it appears that only
Mellanox Spectrum supports offloading more than one VLAN at a time,
through mlxsw_sp_port_vlan_set. I have kept that code internal to the
driver, because there is some more bookkeeping that makes use of it, but
I deleted it from the switchdev API. But since the switchdev support for
ranges has already been de facto deleted by a Mellanox employee and
nobody noticed for 4 years, I'm going to assume it's not a biggie.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com> # switchdev and mlxsw
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Reviewed-by: Kurt Kanzenbach <kurt@linutronix.de> # hellcreek
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2021-01-09 03:01:46 +03:00
|
|
|
.vid = vid,
|
2018-05-30 03:56:03 +03:00
|
|
|
};
|
|
|
|
|
2018-12-12 20:02:52 +03:00
|
|
|
return switchdev_port_obj_add(dev, &v.obj, extack);
|
2018-05-30 03:56:03 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
int br_switchdev_port_vlan_del(struct net_device *dev, u16 vid)
|
|
|
|
{
|
|
|
|
struct switchdev_obj_port_vlan v = {
|
|
|
|
.obj.orig_dev = dev,
|
|
|
|
.obj.id = SWITCHDEV_OBJ_ID_PORT_VLAN,
|
net: switchdev: remove vid_begin -> vid_end range from VLAN objects
The call path of a switchdev VLAN addition to the bridge looks something
like this today:
nbp_vlan_init
| __br_vlan_set_default_pvid
| | |
| | br_afspec |
| | | |
| | v |
| | br_process_vlan_info |
| | | |
| | v |
| | br_vlan_info |
| | / \ /
| | / \ /
| | / \ /
| | / \ /
v v v v v
nbp_vlan_add br_vlan_add ------+
| ^ ^ | |
| / | | |
| / / / |
\ br_vlan_get_master/ / v
\ ^ / / br_vlan_add_existing
\ | / / |
\ | / / /
\ | / / /
\ | / / /
\ | / / /
v | | v /
__vlan_add /
/ | /
/ | /
v | /
__vlan_vid_add | /
\ | /
v v v
br_switchdev_port_vlan_add
The ranges UAPI was introduced to the bridge in commit bdced7ef7838
("bridge: support for multiple vlans and vlan ranges in setlink and
dellink requests") (Jan 10 2015). But the VLAN ranges (parsed in br_afspec)
have always been passed one by one, through struct bridge_vlan_info
tmp_vinfo, to br_vlan_info. So the range never went too far in depth.
Then Scott Feldman introduced the switchdev_port_bridge_setlink function
in commit 47f8328bb1a4 ("switchdev: add new switchdev bridge setlink").
That marked the introduction of the SWITCHDEV_OBJ_PORT_VLAN, which made
full use of the range. But switchdev_port_bridge_setlink was called like
this:
br_setlink
-> br_afspec
-> switchdev_port_bridge_setlink
Basically, the switchdev and the bridge code were not tightly integrated.
Then commit 41c498b9359e ("bridge: restore br_setlink back to original")
came, and switchdev drivers were required to implement
.ndo_bridge_setlink = switchdev_port_bridge_setlink for a while.
In the meantime, commits such as 0944d6b5a2fa ("bridge: try switchdev op
first in __vlan_vid_add/del") finally made switchdev penetrate the
br_vlan_info() barrier and start to develop the call path we have today.
But remember, br_vlan_info() still receives VLANs one by one.
Then Arkadi Sharshevsky refactored the switchdev API in 2017 in commit
29ab586c3d83 ("net: switchdev: Remove bridge bypass support from
switchdev") so that drivers would not implement .ndo_bridge_setlink any
longer. The switchdev_port_bridge_setlink also got deleted.
This refactoring removed the parallel bridge_setlink implementation from
switchdev, and left the only switchdev VLAN objects to be the ones
offloaded from __vlan_vid_add (basically RX filtering) and __vlan_add
(the latter coming from commit 9c86ce2c1ae3 ("net: bridge: Notify about
bridge VLANs")).
That is to say, today the switchdev VLAN object ranges are not used in
the kernel. Refactoring the above call path is a bit complicated, when
the bridge VLAN call path is already a bit complicated.
Let's go off and finish the job of commit 29ab586c3d83 by deleting the
bogus iteration through the VLAN ranges from the drivers. Some aspects
of this feature never made too much sense in the first place. For
example, what is a range of VLANs all having the BRIDGE_VLAN_INFO_PVID
flag supposed to mean, when a port can obviously have a single pvid?
This particular configuration _is_ denied as of commit 6623c60dc28e
("bridge: vlan: enforce no pvid flag in vlan ranges"), but from an API
perspective, the driver still has to play pretend, and only offload the
vlan->vid_end as pvid. And the addition of a switchdev VLAN object can
modify the flags of another, completely unrelated, switchdev VLAN
object! (a VLAN that is PVID will invalidate the PVID flag from whatever
other VLAN had previously been offloaded with switchdev and had that
flag. Yet switchdev never notifies about that change, drivers are
supposed to guess).
Nonetheless, having a VLAN range in the API makes error handling look
scarier than it really is - unwinding on errors and all of that.
When in reality, no one really calls this API with more than one VLAN.
It is all unnecessary complexity.
And despite appearing pretentious (two-phase transactional model and
all), the switchdev API is really sloppy because the VLAN addition and
removal operations are not paired with one another (you can add a VLAN
100 times and delete it just once). The bridge notifies through
switchdev of a VLAN addition not only when the flags of an existing VLAN
change, but also when nothing changes. There are switchdev drivers out
there who don't like adding a VLAN that has already been added, and
those checks don't really belong at driver level. But the fact that the
API contains ranges is yet another factor that prevents this from being
addressed in the future.
Of the existing switchdev pieces of hardware, it appears that only
Mellanox Spectrum supports offloading more than one VLAN at a time,
through mlxsw_sp_port_vlan_set. I have kept that code internal to the
driver, because there is some more bookkeeping that makes use of it, but
I deleted it from the switchdev API. But since the switchdev support for
ranges has already been de facto deleted by a Mellanox employee and
nobody noticed for 4 years, I'm going to assume it's not a biggie.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com> # switchdev and mlxsw
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Reviewed-by: Kurt Kanzenbach <kurt@linutronix.de> # hellcreek
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2021-01-09 03:01:46 +03:00
|
|
|
.vid = vid,
|
2018-05-30 03:56:03 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
return switchdev_port_obj_del(dev, &v.obj);
|
|
|
|
}
|