Blob Blame History Raw
From: Julian Wiedmann <jwi@linux.ibm.com>
Subject: s390/qeth: fix HiperSockets sniffer
Patch-mainline: v4.20-rc2
Git-commit: bd74a7f9cc033cf4d405788f80292268987dc0c5
References: bnc#1113501, LTC#172953

Description:  qeth: fix HiperSockets sniffer
Symptom:      Can't enable HiperSockets sniffer.
Problem:      Sniffing mode for L3 HiperSockets requires that no IP
              addresses are registered with the HW.
              Since commit 5f78e29ceebf
              reworked the IP registration logic in the L3 subdriver,
              this no longer works. When the qeth device is set online,
              qeth_l3_recover_ip() now unconditionally registers all
              unicast addresses from our internal IP table.
Solution:     Skip the IP address registration at the lowest level.
Reproduction: Set 'sniffer' sysfs attribute, and run tcpdump on the
              interface.

Upstream-Description:

              s390/qeth: fix HiperSockets sniffer

              Sniffing mode for L3 HiperSockets requires that no IP addresses are
              registered with the HW. The preferred way to achieve this is for
              userspace to delete all the IPs on the interface. But qeth is expected
              to also tolerate a configuration where that is not the case, by skipping
              the IP registration when in sniffer mode.
              Since commit 5f78e29ceebf ("qeth: optimize IP handling in rx_mode callback")
              reworked the IP registration logic in the L3 subdriver, this no longer
              works. When the qeth device is set online, qeth_l3_recover_ip() now
              unconditionally registers all unicast addresses from our internal
              IP table.

              While we could fix this particular problem by skipping
              qeth_l3_recover_ip() on a sniffer device, the more future-proof change
              is to skip the IP address registration at the lowest level. This way we
              a) catch any future code path that attempts to register an IP address
                 without considering the sniffer scenario, and
              b) continue to build up our internal IP table, so that if sniffer mode
                 is switched off later we can operate just like normal.

              Fixes: 5f78e29ceebf ("qeth: optimize IP handling in rx_mode callback")
              Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com>
              Signed-off-by: David S. Miller <davem@davemloft.net>


Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com>
Acked-by: Petr Tesarik <ptesarik@suse.com>
---
 drivers/s390/net/qeth_l3_main.c |    8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

--- a/drivers/s390/net/qeth_l3_main.c
+++ b/drivers/s390/net/qeth_l3_main.c
@@ -360,9 +360,6 @@ static void qeth_l3_clear_ip_htable(stru
 
 	QETH_CARD_TEXT(card, 4, "clearip");
 
-	if (recover && card->options.sniffer)
-		return;
-
 	spin_lock_bh(&card->ip_lock);
 
 	hash_for_each_safe(card->ip_htable, i, tmp, addr, hnode) {
@@ -828,6 +825,8 @@ static int qeth_l3_register_addr_entry(s
 	int rc = 0;
 	int cnt = 3;
 
+	if (card->options.sniffer)
+		return 0;
 
 	if (addr->proto == QETH_PROT_IPV4) {
 		QETH_CARD_TEXT(card, 2, "setaddr4");
@@ -863,6 +862,9 @@ static int qeth_l3_deregister_addr_entry
 {
 	int rc = 0;
 
+	if (card->options.sniffer)
+		return 0;
+
 	if (addr->proto == QETH_PROT_IPV4) {
 		QETH_CARD_TEXT(card, 2, "deladdr4");
 		QETH_CARD_HEX(card, 3, &addr->u.a4.addr, sizeof(int));