| From 23f3f719c5e9be035725153521df626b63e854db Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Sun, 28 Oct 2018 09:33:09 +0100 |
| Subject: macsec: update operstate when lower device changes |
| |
| From: Sabrina Dubroca <sd@queasysnail.net> |
| |
| [ 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> |
| --- |
| drivers/net/macsec.c | 17 +++++++++++++++++ |
| 1 file changed, 17 insertions(+) |
| |
| diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c |
| index 05115fb0c97a9..50acd8c9d7f53 100644 |
| --- a/drivers/net/macsec.c |
| +++ b/drivers/net/macsec.c |
| @@ -3305,6 +3305,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; |
| @@ -3489,6 +3492,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; |
| -- |
| 2.20.1 |
| |