From patchwork Tue Oct 9 22:57:49 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Maciej W. Rozycki" X-Patchwork-Id: 981587 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=linux-mips.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 42VCLV2tdFz9sBk for ; Wed, 10 Oct 2018 09:57:54 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726764AbeJJGRE (ORCPT ); Wed, 10 Oct 2018 02:17:04 -0400 Received: from eddie.linux-mips.org ([148.251.95.138]:55974 "EHLO cvs.linux-mips.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726741AbeJJGRE (ORCPT ); Wed, 10 Oct 2018 02:17:04 -0400 Received: (from localhost user: 'macro', uid#1010) by eddie.linux-mips.org with ESMTP id S23994585AbeJIW5tEQpf2 (ORCPT ); Wed, 10 Oct 2018 00:57:49 +0200 Date: Tue, 9 Oct 2018 23:57:49 +0100 (BST) From: "Maciej W. Rozycki" To: netdev@vger.kernel.org Subject: [PATCH net-next v2 2/2] FDDI: defza: Support capturing outgoing SMT traffic In-Reply-To: Message-ID: References: User-Agent: Alpine 2.21 (LFD 202 2017-01-01) MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org DEC FDDIcontroller 700 (DEFZA) uses a Tx/Rx queue pair to communicate SMT frames with adapter's firmware. Any SMT frame received from the RMC via the Rx queue is queued back by the driver to the SMT Rx queue for the firmware to process. Similarly the firmware uses the SMT Tx queue to supply the driver with SMT frames which are queued back to the Tx queue for the RMC to send to the ring. When a network tap is attached to an FDDI interface handled by `defza' any incoming SMT frames captured are queued to our usual processing of network data received, which in turn delivers them to any listening taps. However the outgoing SMT frames produced by the firmware bypass our network protocol stack and are therefore not delivered to taps. This in turn means that taps are missing a part of network traffic sent by the adapter, which may make it more difficult to track down network problems or do general traffic analysis. Call `dev_queue_xmit_nit' then in the SMT Tx path, having checked that a network tap is attached, with a newly-created `dev_nit_active' helper wrapping the usual condition used in the transmit path. Signed-off-by: Maciej W. Rozycki --- New in v2. --- drivers/net/fddi/defza.c | 33 +++++++++++++++++++++++++++++++-- include/linux/netdevice.h | 1 + net/core/dev.c | 13 ++++++++++++- 3 files changed, 44 insertions(+), 3 deletions(-) linux-defza-1.1.4-pcap.patch Index: net-next-20181008-4maxp64/drivers/net/fddi/defza.c =================================================================== --- net-next-20181008-4maxp64.orig/drivers/net/fddi/defza.c +++ net-next-20181008-4maxp64/drivers/net/fddi/defza.c @@ -797,11 +797,40 @@ static void fza_tx_smt(struct net_device smt_tx_ptr = fp->mmio + readl_u(&fp->ring_smt_tx[i].buffer); len = readl_u(&fp->ring_smt_tx[i].rmc) & FZA_RING_PBC_MASK; - /* Queue the frame to the RMC transmit ring. */ - if (!netif_queue_stopped(dev)) + if (!netif_queue_stopped(dev)) { + if (dev_nit_active(dev)) { + struct sk_buff *skb; + + /* Length must be a multiple of 4 as only word + * reads are permitted! + */ + skb = fza_alloc_skb_irq(dev, (len + 3) & ~3); + if (!skb) + goto err_no_skb; /* Drop. */ + + skb_data_ptr = (struct fza_buffer_tx *) + skb->data; + + fza_reads(smt_tx_ptr, skb_data_ptr, + (len + 3) & ~3); + skb->dev = dev; + skb_reserve(skb, 3); /* Skip over PRH. */ + skb_put(skb, len - 3); + skb_reset_network_header(skb); + + dev_queue_xmit_nit(skb, dev); + + dev_kfree_skb_irq(skb); + +err_no_skb: + ; + } + + /* Queue the frame to the RMC transmit ring. */ fza_do_xmit((union fza_buffer_txp) { .mmio_ptr = smt_tx_ptr }, len, dev, 1); + } writel_o(FZA_RING_OWN_FZA, &fp->ring_smt_tx[i].own); fp->ring_smt_tx_index = Index: net-next-20181008-4maxp64/include/linux/netdevice.h =================================================================== --- net-next-20181008-4maxp64.orig/include/linux/netdevice.h +++ net-next-20181008-4maxp64/include/linux/netdevice.h @@ -3632,6 +3632,7 @@ static __always_inline int ____dev_forwa return 0; } +bool dev_nit_active(struct net_device *dev); void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev); extern int netdev_budget; Index: net-next-20181008-4maxp64/net/core/dev.c =================================================================== --- net-next-20181008-4maxp64.orig/net/core/dev.c +++ net-next-20181008-4maxp64/net/core/dev.c @@ -1954,6 +1954,17 @@ static inline bool skb_loop_sk(struct pa return false; } +/** + * dev_nit_active - return true if any network interface taps are in use + * + * @dev: network device to check for the presence of taps + */ +bool dev_nit_active(struct net_device *dev) +{ + return !list_empty(&ptype_all) || !list_empty(&dev->ptype_all); +} +EXPORT_SYMBOL_GPL(dev_nit_active); + /* * Support routine. Sends outgoing frames to any network * taps currently in use. @@ -3211,7 +3222,7 @@ static int xmit_one(struct sk_buff *skb, unsigned int len; int rc; - if (!list_empty(&ptype_all) || !list_empty(&dev->ptype_all)) + if (dev_nit_active(dev)) dev_queue_xmit_nit(skb, dev); len = skb->len;