All of lore.kernel.org
 help / color / mirror / Atom feed
From: Karsten Graul <kgraul@linux.ibm.com>
To: David Miller <davem@davemloft.net>, Jakub Kicinski <kuba@kernel.org>
Cc: netdev@vger.kernel.org, linux-s390@vger.kernel.org,
	Heiko Carstens <hca@linux.ibm.com>,
	Guvenc Gulce <guvenc@linux.ibm.com>,
	Julian Wiedmann <jwi@linux.ibm.com>,
	Wenjia Zhang <wenjia@linux.ibm.com>,
	Alexandra Winter <wintera@linux.ibm.com>
Subject: [PATCH net-next 2/3] s390/qeth: Switchdev event handler
Date: Fri,  6 Aug 2021 17:26:02 +0200	[thread overview]
Message-ID: <20210806152603.375642-3-kgraul@linux.ibm.com> (raw)
In-Reply-To: <20210806152603.375642-1-kgraul@linux.ibm.com>

From: Alexandra Winter <wintera@linux.ibm.com>

QETH HiperSockets devices with LEARNING_SYNC capability can be used
to construct a linux bridge with:
2 isolated southbound interfaces:
     a) a default network interface
     b) a LEARNING-SYNC HiperSockets interface
and 1 non-isolated northbound interface. This is called a 'HiperSockets
Converged Interface' (HSCI).
The existing LEARNING_SYNC functionality is used to update the bridge fdb
with MAC addresses that should be sent-out via the HiperSockets interface,
instead of the default network interface.

Add handling of switchdev events SWITCHDEV_FDB_ADD_TO_DEVICE and
SWITCHDEV_FDB_DEL_TO_DEVICE to the qeth LEARNING_SYNC functionality. Thus
if the northbound bridgeport of an HSCI doesn't only have a single static
MAC address, but instead is a learning bridgeport, work is enqueued, so
the HiperSockets virtual switch (that is external to this Linux instance)
can update its fdb.

When BRIDGE is a loadable module, QETH_L2 mustn't be built-in:

drivers/s390/net/qeth_l2_main.o: in function 'qeth_l2_switchdev_event':
drivers/s390/net/qeth_l2_main.c:927: undefined reference to
'br_port_flag_is_set'

Add Kconfig dependency to enforce usable configurations.

Signed-off-by: Alexandra Winter <wintera@linux.ibm.com>
Reviewed-by: Wenjia Zhang <wenjia@linux.ibm.com>
Signed-off-by: Karsten Graul <kgraul@linux.ibm.com>
---
 drivers/s390/net/Kconfig        |  1 +
 drivers/s390/net/qeth_l2_main.c | 83 +++++++++++++++++++++++++++++++--
 2 files changed, 79 insertions(+), 5 deletions(-)

diff --git a/drivers/s390/net/Kconfig b/drivers/s390/net/Kconfig
index cff91b4f1a76..9c67b97faba2 100644
--- a/drivers/s390/net/Kconfig
+++ b/drivers/s390/net/Kconfig
@@ -74,6 +74,7 @@ config QETH_L2
 	def_tristate y
 	prompt "qeth layer 2 device support"
 	depends on QETH
+	depends on BRIDGE || BRIDGE=n
 	help
 	  Select this option to be able to run qeth devices in layer 2 mode.
 	  To compile as a module, choose M. The module name is qeth_l2.
diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c
index 3d02d35df5d3..e38a1befce3f 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -717,15 +717,79 @@ static int qeth_l2_dev2br_an_set(struct qeth_card *card, bool enable)
 	return rc;
 }
 
+static const struct net_device_ops qeth_l2_netdev_ops;
+
+static bool qeth_l2_must_learn(struct net_device *netdev,
+			       struct net_device *dstdev)
+{
+	struct qeth_priv *priv;
+
+	priv = netdev_priv(netdev);
+	return (netdev != dstdev &&
+		(priv->brport_features & BR_LEARNING_SYNC) &&
+		!(br_port_flag_is_set(netdev, BR_ISOLATED) &&
+		  br_port_flag_is_set(dstdev, BR_ISOLATED)) &&
+		netdev->netdev_ops == &qeth_l2_netdev_ops);
+}
+
+/* Called under rtnl_lock */
+static int qeth_l2_switchdev_event(struct notifier_block *unused,
+				   unsigned long event, void *ptr)
+{
+	struct net_device *dstdev, *brdev, *lowerdev;
+	struct switchdev_notifier_fdb_info *fdb_info;
+	struct switchdev_notifier_info *info = ptr;
+	struct list_head *iter;
+	struct qeth_card *card;
+
+	if (!(event == SWITCHDEV_FDB_ADD_TO_DEVICE ||
+	      event == SWITCHDEV_FDB_DEL_TO_DEVICE))
+		return NOTIFY_DONE;
+
+	dstdev = switchdev_notifier_info_to_dev(info);
+	brdev = netdev_master_upper_dev_get_rcu(dstdev);
+	if (!brdev || !netif_is_bridge_master(brdev))
+		return NOTIFY_DONE;
+	fdb_info = container_of(info,
+				struct switchdev_notifier_fdb_info,
+				info);
+	iter = &brdev->adj_list.lower;
+	lowerdev = netdev_next_lower_dev_rcu(brdev, &iter);
+	while (lowerdev) {
+		if (qeth_l2_must_learn(lowerdev, dstdev)) {
+			card = lowerdev->ml_priv;
+			QETH_CARD_TEXT_(card, 4, "b2dqw%03x", event);
+			/* tbd: rc = qeth_l2_br2dev_queue_work(brdev, lowerdev,
+			 *				       dstdev, event,
+			 *				       fdb_info->addr);
+			 */
+		}
+		lowerdev = netdev_next_lower_dev_rcu(brdev, &iter);
+	}
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block qeth_l2_sw_notifier = {
+		.notifier_call = qeth_l2_switchdev_event,
+};
+
 static refcount_t qeth_l2_switchdev_notify_refcnt;
 
 /* Called under rtnl_lock */
 static void qeth_l2_br2dev_get(void)
 {
+	int rc;
+
 	if (!refcount_inc_not_zero(&qeth_l2_switchdev_notify_refcnt)) {
-		/* tbd: register_switchdev_notifier(&qeth_l2_sw_notifier); */
-		refcount_set(&qeth_l2_switchdev_notify_refcnt, 1);
-		QETH_DBF_MESSAGE(2, "qeth_l2_sw_notifier registered\n");
+		rc = register_switchdev_notifier(&qeth_l2_sw_notifier);
+		if (rc) {
+			QETH_DBF_MESSAGE(2,
+					 "failed to register qeth_l2_sw_notifier: %d\n",
+					 rc);
+		} else {
+			refcount_set(&qeth_l2_switchdev_notify_refcnt, 1);
+			QETH_DBF_MESSAGE(2, "qeth_l2_sw_notifier registered\n");
+		}
 	}
 	QETH_DBF_TEXT_(SETUP, 2, "b2d+%04d",
 		       qeth_l2_switchdev_notify_refcnt.refs.counter);
@@ -734,9 +798,18 @@ static void qeth_l2_br2dev_get(void)
 /* Called under rtnl_lock */
 static void qeth_l2_br2dev_put(void)
 {
+	int rc;
+
 	if (refcount_dec_and_test(&qeth_l2_switchdev_notify_refcnt)) {
-		/* tbd: unregister_switchdev_notifier(&qeth_l2_sw_notifier); */
-		QETH_DBF_MESSAGE(2, "qeth_l2_sw_notifier unregistered\n");
+		rc = unregister_switchdev_notifier(&qeth_l2_sw_notifier);
+		if (rc) {
+			QETH_DBF_MESSAGE(2,
+					 "failed to unregister qeth_l2_sw_notifier: %d\n",
+					 rc);
+		} else {
+			QETH_DBF_MESSAGE(2,
+					 "qeth_l2_sw_notifier unregistered\n");
+		}
 	}
 	QETH_DBF_TEXT_(SETUP, 2, "b2d-%04d",
 		       qeth_l2_switchdev_notify_refcnt.refs.counter);
-- 
2.25.1


  parent reply	other threads:[~2021-08-06 15:26 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-08-06 15:26 [PATCH net-next 0/3] s390/qeth: Add bridge to switchdev LEARNING_SYNC Karsten Graul
2021-08-06 15:26 ` [PATCH net-next 1/3] s390/qeth: Register switchdev event handler Karsten Graul
2021-08-06 15:26 ` Karsten Graul [this message]
2021-08-06 15:26 ` [PATCH net-next 3/3] s390/qeth: Update MACs of LEARNING_SYNC device Karsten Graul
2021-08-07  8:50 ` [PATCH net-next 0/3] s390/qeth: Add bridge to switchdev LEARNING_SYNC patchwork-bot+netdevbpf

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=20210806152603.375642-3-kgraul@linux.ibm.com \
    --to=kgraul@linux.ibm.com \
    --cc=davem@davemloft.net \
    --cc=guvenc@linux.ibm.com \
    --cc=hca@linux.ibm.com \
    --cc=jwi@linux.ibm.com \
    --cc=kuba@kernel.org \
    --cc=linux-s390@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=wenjia@linux.ibm.com \
    --cc=wintera@linux.ibm.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.