Skip to contentSkip to conversation

Add ability to receive and transmit ethernet frames with bad CRC (e1000)

PATCH Ben Greear 1 participant 1 message Oct 25, 2004

Subsystems (2)
lore
Share & tools
lore

Ben Greear

author
#0 lore raw

I have patched the e1000 driver to allow one to send frames with bad (ie, custom) CRCs, as well as receive packets with bad CRCs and other errors. The receive logic should be very useful for packet sniffing, and the tx is useful for testing error cases for ethernet equipment.

The rest of the patch to turn on/off these bits is tangled in with ethtool changes and several other files, but I will dis-entangle them if it is agreed that this feature is desired. I also have driver support for the e100 driver.

Comments welcome, and let me know if it's worth my time to break out the other components of this feature from my big patch.

Thanks,
Ben

drivers/net/e1000/e1000_main.c +69 -5
@@ -1,4 +1,4 @@
-/*******************************************************************************
+/** -*-linux-c -*- ***************************************************************
 
 
   Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
@@ -120,7 +120,7 @@
 static void e1000_setup_rctl(struct e1000_adapter *adapter);
 static void e1000_clean_tx_ring(struct e1000_adapter *adapter);
 static void e1000_clean_rx_ring(struct e1000_adapter *adapter);
-static void e1000_set_multi(struct net_device *netdev);
+void e1000_set_multi(struct net_device *netdev);
 static void e1000_update_phy_info(unsigned long data);
 static void e1000_watchdog(unsigned long data);
 static void e1000_82547_tx_fifo_stall(unsigned long data);
@@ -499,6 +499,10 @@
 	if(pci_using_dac)
 		netdev->features |= NETIF_F_HIGHDMA;
 
+	/* Has ability to receive all frames (even bad CRCs and such) */
+	netdev->features |= NETIF_F_RX_ALL | NETIF_F_SAVE_CRC;
+
+	
  	/* hard_start_xmit is safe against parallel locking */
  	netdev->features |= NETIF_F_LLTX;
 
@@ -1269,7 +1273,7 @@
  * promiscuous mode, and all-multi behavior.
  **/
 
-static void
+void
 e1000_set_multi(struct net_device *netdev)
 {
 	struct e1000_adapter *adapter = netdev->priv;
@@ -1297,6 +1301,35 @@
 
 	E1000_WRITE_REG(hw, RCTL, rctl);
 
+
+	/* This is useful for using ethereal or tcpdump to sniff
+        * packets in promiscuous mode without stripping VLAN/priority
+        * information, and also letting bad packets through.
+        *
+        * THIS IS NOT PRODUCTION CODE - FOR INTERNAL USE ONLY!!!
+        *
+        */
+        if (netdev->priv_flags & IFF_ACCEPT_ALL_FRAMES) {
+		uint32_t ctrl;
+		/*printk("%s: Enabling acceptance of ALL frames (bad CRC too).\n",
+		  netdev->name); */
+		/* store bad packets, promisc/multicast all, no VLAN
+		 * filter */
+		rctl = E1000_READ_REG(hw, RCTL);
+		rctl |= (E1000_RCTL_SBP | E1000_RCTL_UPE | E1000_RCTL_MPE);
+		rctl &= ~(E1000_RCTL_VFE | E1000_RCTL_CFIEN);
+		E1000_WRITE_REG(hw, RCTL, rctl);
+		/* disable VLAN tagging/striping */
+		ctrl = E1000_READ_REG(hw, CTRL);
+		ctrl &= ~E1000_CTRL_VME;
+		E1000_WRITE_REG(hw, CTRL, ctrl);
+	}
+	else {
+		/* TODO:  Do we need a way to explicitly turn this off if it was
+		 * previously enabled, or will it magically go back to normal??? --Ben
+		 */
+	}
+	
 	/* 82542 2.0 needs to be in reset to write receive address registers */
 
 	if(hw->mac_type == e1000_82542_rev2_0)
@@ -1493,6 +1526,7 @@
 #define E1000_TX_FLAGS_CSUM		0x00000001
 #define E1000_TX_FLAGS_VLAN		0x00000002
 #define E1000_TX_FLAGS_TSO		0x00000004
+#define E1000_TX_FLAGS_NO_FCS		0x00000008
 #define E1000_TX_FLAGS_VLAN_MASK	0xffff0000
 #define E1000_TX_FLAGS_VLAN_SHIFT	16
 
@@ -1697,6 +1731,13 @@
 		txd_upper |= (tx_flags & E1000_TX_FLAGS_VLAN_MASK);
 	}
 
+#ifdef CONFIG_SUPPORT_SEND_BAD_CRC
+	if (unlikely(tx_flags & E1000_TX_FLAGS_NO_FCS)) {
+		txd_lower &= ~(E1000_TXD_CMD_IFCS);
+		/* printk("Disabling CRC in tx_queue, txd_lower: 0x%x\n", txd_lower); */
+	}
+#endif
+	
 	i = tx_ring->next_to_use;
 
 	while(count--) {
@@ -1711,6 +1752,14 @@
 
 	tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd);
 
+#ifdef CONFIG_SUPPORT_SEND_BAD_CRC
+	/* txd_cmd re-enables FCS, so we'll re-disable it here as desired. */
+	if (unlikely(tx_flags & E1000_TX_FLAGS_NO_FCS)) {
+		tx_desc->lower.data &= ~(cpu_to_le32(E1000_TXD_CMD_IFCS));
+		/* printk("Disabling2 CRC in tx_queue, txd_lower: 0x%x\n", tx_desc->lower.data); */
+	}
+#endif
+	
 	/* Force memory writes to complete before letting h/w
 	 * know there are new descriptors to fetch.  (Only
 	 * applicable for weak-ordered memory model archs,
@@ -1849,6 +1898,12 @@
 	else if(likely(e1000_tx_csum(adapter, skb)))
 		tx_flags |= E1000_TX_FLAGS_CSUM;
 
+#ifdef CONFIG_SUPPORT_SEND_BAD_CRC
+	if (unlikely(skb->general_flags & DONT_DO_TX_CRC)) {
+		tx_flags |= E1000_TX_FLAGS_NO_FCS;
+	}
+#endif	
+
 	e1000_tx_queue(adapter,
 		e1000_tx_map(adapter, skb, first, max_per_txd, nr_frags, mss),
 		tx_flags);
@@ -2307,7 +2362,11 @@
 			goto next_desc;
 		}
 
-		if(unlikely(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) {
+		/* If we are accepting all frames, then do not pay attention to the
+		 * framing errors.
+		 */
+ 		if (unlikely(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK) &&
+		    !(netdev->priv_flags & IFF_ACCEPT_ALL_FRAMES)) {
 			last_byte = *(skb->data + length - 1);
 			if(TBI_ACCEPT(&adapter->hw, rx_desc->status,
 			              rx_desc->errors, length, last_byte)) {
@@ -2325,7 +2384,12 @@
 		}
 
 		/* Good Receive */
-		skb_put(skb, length - ETHERNET_FCS_SIZE);
+		if (netdev->priv_flags & IFF_SAVE_FCS) {
+			skb_put(skb, length);
+		}
+		else {
+			skb_put(skb, length - ETHERNET_FCS_SIZE);
+		}
 
 		/* Receive Checksum Offload */
 		e1000_rx_checksum(adapter, rx_desc, skb);
drivers/net/e1000/e1000_ethtool.c +58 -1

80 lines not on this page · raw message

Signature · 2 lines
Ben Greear <[email protected]>
Candela Technologies Inc  http://www.candelatech.com