netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Radu Rendec <radu.rendec@gmail.com>
To: netdev@vger.kernel.org
Cc: David Miller <davem@davemloft.net>,
	Sabrina Dubroca <sd@queasysnail.net>,
	Radu Rendec <radu.rendec@gmail.com>
Subject: [PATCH 1/1] macsec: reflect the master interface state
Date: Tue, 18 Sep 2018 20:16:12 -0400	[thread overview]
Message-ID: <20180919001612.2636-2-radu.rendec@gmail.com> (raw)
In-Reply-To: <20180919001612.2636-1-radu.rendec@gmail.com>

This patch makes macsec interfaces reflect the state of the underlying
interface: if the master interface changes state to up/down, the macsec
interface changes its state accordingly.

This closes a loophole in the macsec interface state logic: the macsec
interface cannot be brought up if the master interface is down (the
operation is rejected with ENETDOWN); however, if the macsec interface
is brought up while the master interface is up and then the master
interface goes down, the macsec interface stays up.

Reflecting the master interface state can also be useful if the macsec
interface is used as a bridge port: if the master (physical) interface
goes down, the state propagates through the macsec interface to the
bridge module, which can react to the state change (for example if it
runs STP).

The patch does nothing original. The same logic is implemented for vlan
interfaces in vlan_device_event() in net/8021q/vlan.c. In fact, the code
was copied and adapted from there.

Signed-off-by: Radu Rendec <radu.rendec@gmail.com>
---
 drivers/net/macsec.c | 57 +++++++++++++++++++++++++++++++++++---------
 1 file changed, 46 insertions(+), 11 deletions(-)

diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c
index 7de88b33d5b9..cb93a1290f85 100644
--- a/drivers/net/macsec.c
+++ b/drivers/net/macsec.c
@@ -3486,20 +3486,21 @@ static int macsec_notify(struct notifier_block *this, unsigned long event,
 			 void *ptr)
 {
 	struct net_device *real_dev = netdev_notifier_info_to_dev(ptr);
-	LIST_HEAD(head);
+	struct macsec_dev *m;
+	struct macsec_rxh_data *rxd;
 
 	if (!is_macsec_master(real_dev))
 		return NOTIFY_DONE;
 
+	rxd = macsec_data_rtnl(real_dev);
+
 	switch (event) {
 	case NETDEV_UNREGISTER: {
-		struct macsec_dev *m, *n;
-		struct macsec_rxh_data *rxd;
+		struct macsec_dev *n;
+		LIST_HEAD(head);
 
-		rxd = macsec_data_rtnl(real_dev);
-		list_for_each_entry_safe(m, n, &rxd->secys, secys) {
+		list_for_each_entry_safe(m, n, &rxd->secys, secys)
 			macsec_common_dellink(m->secy.netdev, &head);
-		}
 
 		netdev_rx_handler_unregister(real_dev);
 		kfree(rxd);
@@ -3507,11 +3508,7 @@ static int macsec_notify(struct notifier_block *this, unsigned long event,
 		unregister_netdevice_many(&head);
 		break;
 	}
-	case NETDEV_CHANGEMTU: {
-		struct macsec_dev *m;
-		struct macsec_rxh_data *rxd;
-
-		rxd = macsec_data_rtnl(real_dev);
+	case NETDEV_CHANGEMTU:
 		list_for_each_entry(m, &rxd->secys, secys) {
 			struct net_device *dev = m->secy.netdev;
 			unsigned int mtu = real_dev->mtu - (m->secy.icv_len +
@@ -3520,7 +3517,45 @@ static int macsec_notify(struct notifier_block *this, unsigned long event,
 			if (dev->mtu > mtu)
 				dev_set_mtu(dev, mtu);
 		}
+		break;
+	case NETDEV_CHANGE:
+		list_for_each_entry(m, &rxd->secys, secys) {
+			struct net_device *dev = m->secy.netdev;
+
+			netif_stacked_transfer_operstate(real_dev, dev);
+		}
+		break;
+	case NETDEV_DOWN: {
+		struct net_device *dev, *tmp;
+		LIST_HEAD(close_list);
+
+		list_for_each_entry(m, &rxd->secys, secys) {
+			dev = m->secy.netdev;
+
+			if (dev->flags & IFF_UP)
+				list_add(&dev->close_list, &close_list);
+		}
+
+		dev_close_many(&close_list, false);
+
+		list_for_each_entry_safe(dev, tmp, &close_list, close_list) {
+			netif_stacked_transfer_operstate(real_dev, dev);
+			list_del_init(&dev->close_list);
+		}
+		list_del(&close_list);
+		break;
 	}
+	case NETDEV_UP:
+		list_for_each_entry(m, &rxd->secys, secys) {
+			struct net_device *dev = m->secy.netdev;
+			int flags = dev_get_flags(dev);
+
+			if (!(flags & IFF_UP)) {
+				dev_change_flags(dev, flags | IFF_UP);
+				netif_stacked_transfer_operstate(real_dev, dev);
+			}
+		}
+		break;
 	}
 
 	return NOTIFY_OK;
-- 
2.17.1

  reply	other threads:[~2018-09-19  5:51 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-09-19  0:16 [PATCH 0/1] macsec: reflect the master interface state Radu Rendec
2018-09-19  0:16 ` Radu Rendec [this message]
2018-09-19 15:24   ` [PATCH 1/1] " Sabrina Dubroca
2018-09-19 16:44     ` Radu Rendec
2018-10-01 12:52       ` Sabrina Dubroca
2018-10-28 21:14         ` Radu Rendec

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180919001612.2636-2-radu.rendec@gmail.com \
    --to=radu.rendec@gmail.com \
    --cc=davem@davemloft.net \
    --cc=netdev@vger.kernel.org \
    --cc=sd@queasysnail.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).