aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaciej W. Rozycki <macro@linux-mips.org>2018-10-09 18:57:49 -0400
committerDavid S. Miller <davem@davemloft.net>2018-10-16 00:46:06 -0400
commit9f9a742db40f95f4dc20fc7293de4ea6ddb24e47 (patch)
tree5cbd5bcf3514e362f9f42275961b4880deb92fac
parent61414f5ec9834df8aa4f55c90de16b71a3d6ca8d (diff)
FDDI: defza: Support capturing outgoing SMT traffic
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 <macro@linux-mips.org> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/fddi/defza.c33
-rw-r--r--include/linux/netdevice.h1
-rw-r--r--net/core/dev.c13
3 files changed, 44 insertions, 3 deletions
diff --git a/drivers/net/fddi/defza.c b/drivers/net/fddi/defza.c
index 7d01b70f7ed8..3b7f10a5f06a 100644
--- a/drivers/net/fddi/defza.c
+++ b/drivers/net/fddi/defza.c
@@ -797,11 +797,40 @@ static void fza_tx_smt(struct net_device *dev)
797 smt_tx_ptr = fp->mmio + readl_u(&fp->ring_smt_tx[i].buffer); 797 smt_tx_ptr = fp->mmio + readl_u(&fp->ring_smt_tx[i].buffer);
798 len = readl_u(&fp->ring_smt_tx[i].rmc) & FZA_RING_PBC_MASK; 798 len = readl_u(&fp->ring_smt_tx[i].rmc) & FZA_RING_PBC_MASK;
799 799
800 /* Queue the frame to the RMC transmit ring. */ 800 if (!netif_queue_stopped(dev)) {
801 if (!netif_queue_stopped(dev)) 801 if (dev_nit_active(dev)) {
802 struct sk_buff *skb;
803
804 /* Length must be a multiple of 4 as only word
805 * reads are permitted!
806 */
807 skb = fza_alloc_skb_irq(dev, (len + 3) & ~3);
808 if (!skb)
809 goto err_no_skb; /* Drop. */
810
811 skb_data_ptr = (struct fza_buffer_tx *)
812 skb->data;
813
814 fza_reads(smt_tx_ptr, skb_data_ptr,
815 (len + 3) & ~3);
816 skb->dev = dev;
817 skb_reserve(skb, 3); /* Skip over PRH. */
818 skb_put(skb, len - 3);
819 skb_reset_network_header(skb);
820
821 dev_queue_xmit_nit(skb, dev);
822
823 dev_kfree_skb_irq(skb);
824
825err_no_skb:
826 ;
827 }
828
829 /* Queue the frame to the RMC transmit ring. */
802 fza_do_xmit((union fza_buffer_txp) 830 fza_do_xmit((union fza_buffer_txp)
803 { .mmio_ptr = smt_tx_ptr }, 831 { .mmio_ptr = smt_tx_ptr },
804 len, dev, 1); 832 len, dev, 1);
833 }
805 834
806 writel_o(FZA_RING_OWN_FZA, &fp->ring_smt_tx[i].own); 835 writel_o(FZA_RING_OWN_FZA, &fp->ring_smt_tx[i].own);
807 fp->ring_smt_tx_index = 836 fp->ring_smt_tx_index =
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 22e4ef7bb701..dc1d9ed33b31 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -3645,6 +3645,7 @@ static __always_inline int ____dev_forward_skb(struct net_device *dev,
3645 return 0; 3645 return 0;
3646} 3646}
3647 3647
3648bool dev_nit_active(struct net_device *dev);
3648void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev); 3649void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev);
3649 3650
3650extern int netdev_budget; 3651extern int netdev_budget;
diff --git a/net/core/dev.c b/net/core/dev.c
index a4d39b87b4e5..8497feea8fb5 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1976,6 +1976,17 @@ static inline bool skb_loop_sk(struct packet_type *ptype, struct sk_buff *skb)
1976 return false; 1976 return false;
1977} 1977}
1978 1978
1979/**
1980 * dev_nit_active - return true if any network interface taps are in use
1981 *
1982 * @dev: network device to check for the presence of taps
1983 */
1984bool dev_nit_active(struct net_device *dev)
1985{
1986 return !list_empty(&ptype_all) || !list_empty(&dev->ptype_all);
1987}
1988EXPORT_SYMBOL_GPL(dev_nit_active);
1989
1979/* 1990/*
1980 * Support routine. Sends outgoing frames to any network 1991 * Support routine. Sends outgoing frames to any network
1981 * taps currently in use. 1992 * taps currently in use.
@@ -3233,7 +3244,7 @@ static int xmit_one(struct sk_buff *skb, struct net_device *dev,
3233 unsigned int len; 3244 unsigned int len;
3234 int rc; 3245 int rc;
3235 3246
3236 if (!list_empty(&ptype_all) || !list_empty(&dev->ptype_all)) 3247 if (dev_nit_active(dev))
3237 dev_queue_xmit_nit(skb, dev); 3248 dev_queue_xmit_nit(skb, dev);
3238 3249
3239 len = skb->len; 3250 len = skb->len;