summaryrefslogtreecommitdiff
path: root/drivers/net
diff options
context:
space:
mode:
authorSabrina Dubroca <sd@queasysnail.net>2018-10-28 09:33:09 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-11-28 18:28:42 +0100
commit8f70a4d8adc93c1b15a8116caf3efaf5205d5446 (patch)
tree4341d102ca976aa20bb4caf8dc2418a98889da0e /drivers/net
parent8a7b0a5833c6a9d3d0beeeed57e3acf478e1ed63 (diff)
macsec: update operstate when lower device changes
[ Upstream commit e6ac075882b2afcdf2d5ab328ce4ab42a1eb9593 ] Like all other virtual devices (macvlan, vlan), the operstate of a macsec device should match the state of its lower device. This is done by calling netif_stacked_transfer_operstate from its netdevice notifier. We also need to call netif_stacked_transfer_operstate when a new macsec device is created, so that its operstate is set properly. This is only relevant when we try to bring the device up directly when we create it. Radu Rendec proposed a similar patch, inspired from the 802.1q driver, that included changing the administrative state of the macsec device, instead of just the operstate. This version is similar to what the macvlan driver does, and updates only the operstate. Fixes: c09440f7dcb3 ("macsec: introduce IEEE 802.1AE driver") Reported-by: Radu Rendec <radu.rendec@gmail.com> Reported-by: Patrick Talbert <ptalbert@redhat.com> Signed-off-by: Sabrina Dubroca <sd@queasysnail.net> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/macsec.c17
1 files changed, 17 insertions, 0 deletions
diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
index da10104be16c..d2a3825376be 100644
--- a/drivers/net/macsec.c
+++ b/drivers/net/macsec.c
@@ -3275,6 +3275,9 @@ static int macsec_newlink(struct net *net, struct net_device *dev,
if (err < 0)
goto del_dev;
+ netif_stacked_transfer_operstate(real_dev, dev);
+ linkwatch_fire_event(dev);
+
macsec_generation++;
return 0;
@@ -3446,6 +3449,20 @@ static int macsec_notify(struct notifier_block *this, unsigned long event,
return NOTIFY_DONE;
switch (event) {
+ case NETDEV_DOWN:
+ case NETDEV_UP:
+ case NETDEV_CHANGE: {
+ struct macsec_dev *m, *n;
+ struct macsec_rxh_data *rxd;
+
+ rxd = macsec_data_rtnl(real_dev);
+ list_for_each_entry_safe(m, n, &rxd->secys, secys) {
+ struct net_device *dev = m->secy.netdev;
+
+ netif_stacked_transfer_operstate(real_dev, dev);
+ }
+ break;
+ }
case NETDEV_UNREGISTER: {
struct macsec_dev *m, *n;
struct macsec_rxh_data *rxd;