net: Add framework to allow sending packets with customized CRC.
authorBen Greear <greearb@candelatech.com>
Sat, 11 Feb 2012 15:39:30 +0000 (15:39 +0000)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Fri, 24 Feb 2012 09:37:35 +0000 (01:37 -0800)
This is useful for testing RX handling of frames with bad
CRCs.

Requires driver support to actually put the packet on the
wire properly.

Signed-off-by: Ben Greear <greearb@candelatech.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
24 files changed:
arch/alpha/include/asm/socket.h
arch/arm/include/asm/socket.h
arch/avr32/include/asm/socket.h
arch/cris/include/asm/socket.h
arch/frv/include/asm/socket.h
arch/h8300/include/asm/socket.h
arch/ia64/include/asm/socket.h
arch/m32r/include/asm/socket.h
arch/m68k/include/asm/socket.h
arch/mips/include/asm/socket.h
arch/mn10300/include/asm/socket.h
arch/parisc/include/asm/socket.h
arch/powerpc/include/asm/socket.h
arch/s390/include/asm/socket.h
arch/sparc/include/asm/socket.h
arch/xtensa/include/asm/socket.h
include/asm-generic/socket.h
include/linux/if.h
include/linux/netdevice.h
include/linux/skbuff.h
include/net/sock.h
net/core/skbuff.c
net/core/sock.c
net/packet/af_packet.c

index 16449d330dae91fa33e6559516a45121607b5b30..dcb221a4b5be3505686b05fb3060307cde68f29b 100644 (file)
@@ -73,6 +73,9 @@
 #define SCM_WIFI_STATUS                SO_WIFI_STATUS
 #define SO_PEEK_OFF            42
 
+/* Instruct lower device to use last 4-bytes of skb data as FCS */
+#define SO_NOFCS               43
+
 /* O_NONBLOCK clashes with the bits used for socket types.  Therefore we
  * have to define SOCK_NONBLOCK to a different value here.
  */
index d958c74e5260839c9c35b0a8d5aff6038f320138..6433cadb6ed411ee0ca809d06b2d82e53731e1a7 100644 (file)
@@ -66,4 +66,7 @@
 #define SCM_WIFI_STATUS                SO_WIFI_STATUS
 #define SO_PEEK_OFF            42
 
+/* Instruct lower device to use last 4-bytes of skb data as FCS */
+#define SO_NOFCS               43
+
 #endif /* _ASM_SOCKET_H */
index 30078f98b3ab8f4e228bf200a99374f3fd1c92a1..a473f8c6a9aa2be66f04f375ef7b7820b7c0683a 100644 (file)
@@ -66,4 +66,7 @@
 #define SCM_WIFI_STATUS                SO_WIFI_STATUS
 #define SO_PEEK_OFF            42
 
+/* Instruct lower device to use last 4-bytes of skb data as FCS */
+#define SO_NOFCS               43
+
 #endif /* __ASM_AVR32_SOCKET_H */
index 048aba64600c98dd5cd70e442e32bf725caa10c1..ae52825021afd98237557656abf77dad4a75491f 100644 (file)
@@ -68,6 +68,9 @@
 #define SCM_WIFI_STATUS                SO_WIFI_STATUS
 #define SO_PEEK_OFF            42
 
+/* Instruct lower device to use last 4-bytes of skb data as FCS */
+#define SO_NOFCS               43
+
 #endif /* _ASM_SOCKET_H */
 
 
index 7a361810f3cce60a61fdc0c4a192b5062a149c9b..a5b1d7dbb205389eef5e2d5627f0aad3744778fe 100644 (file)
@@ -66,5 +66,8 @@
 #define SCM_WIFI_STATUS                SO_WIFI_STATUS
 #define SO_PEEK_OFF            42
 
+/* Instruct lower device to use last 4-bytes of skb data as FCS */
+#define SO_NOFCS               43
+
 #endif /* _ASM_SOCKET_H */
 
index e7bbfcee5b9919629e70879d59bc7db672f6cc03..ec4554e7b04b68ab4c41ad93e612469ac896708c 100644 (file)
@@ -66,4 +66,7 @@
 #define SCM_WIFI_STATUS                SO_WIFI_STATUS
 #define SO_PEEK_OFF            42
 
+/* Instruct lower device to use last 4-bytes of skb data as FCS */
+#define SO_NOFCS               43
+
 #endif /* _ASM_SOCKET_H */
index ced62de9d5a92fd9d937c9272691655b82a586cd..41fc28a4a18a2305763db7be6e0d51210671030e 100644 (file)
@@ -75,4 +75,7 @@
 #define SCM_WIFI_STATUS                SO_WIFI_STATUS
 #define SO_PEEK_OFF            42
 
+/* Instruct lower device to use last 4-bytes of skb data as FCS */
+#define SO_NOFCS               43
+
 #endif /* _ASM_IA64_SOCKET_H */
index 696cb4c7ca4e4bb694bfe836ffa29cf9bee0ec7c..a15f40b527834256eababa34dd23d076cf003e2d 100644 (file)
@@ -66,4 +66,7 @@
 #define SCM_WIFI_STATUS                SO_WIFI_STATUS
 #define SO_PEEK_OFF            42
 
+/* Instruct lower device to use last 4-bytes of skb data as FCS */
+#define SO_NOFCS               43
+
 #endif /* _ASM_M32R_SOCKET_H */
index e8b41a6775f9ce053c3e58e97cc39a8576b3a6c8..d1be684edf97925331569d9af422a5f427e2a271 100644 (file)
@@ -66,4 +66,7 @@
 #define SCM_WIFI_STATUS                SO_WIFI_STATUS
 #define SO_PEEK_OFF            42
 
+/* Instruct lower device to use last 4-bytes of skb data as FCS */
+#define SO_NOFCS               43
+
 #endif /* _ASM_SOCKET_H */
index 52104872e9e3679136184e068553c138b5b620a0..a2ed6fdad4e0ee70aac755fad96157f817af900c 100644 (file)
@@ -86,6 +86,9 @@ To add: #define SO_REUSEPORT 0x0200   /* Allow local address and port reuse.  */
 #define SCM_WIFI_STATUS                SO_WIFI_STATUS
 #define SO_PEEK_OFF            42
 
+/* Instruct lower device to use last 4-bytes of skb data as FCS */
+#define SO_NOFCS               43
+
 #ifdef __KERNEL__
 
 /** sock_type - Socket types
index 013fcc51698f8e72dc7f77afe951f7298c8a1050..820463a484b8dbc5b21ee627822297d4a33bf91f 100644 (file)
@@ -66,4 +66,7 @@
 #define SCM_WIFI_STATUS                SO_WIFI_STATUS
 #define SO_PEEK_OFF            42
 
+/* Instruct lower device to use last 4-bytes of skb data as FCS */
+#define SO_NOFCS               43
+
 #endif /* _ASM_SOCKET_H */
index f717c9bec16fe5ea553abddd7eb1534fdc48cf28..1b52c2c31a7a284c8e4f6b6d08cc53faa60da42f 100644 (file)
 #define SCM_WIFI_STATUS                SO_WIFI_STATUS
 #define SO_PEEK_OFF            0x4023
 
+/* Instruct lower device to use last 4-bytes of skb data as FCS */
+#define SO_NOFCS               0x4024
+
+
 /* O_NONBLOCK clashes with the bits used for socket types.  Therefore we
  * have to define SOCK_NONBLOCK to a different value here.
  */
index fe1c0b478fd7b7121156e89f1ea218f7018a43a8..3d5179bb122f120e24477c3be6f1459182b8bec5 100644 (file)
@@ -73,4 +73,7 @@
 #define SCM_WIFI_STATUS                SO_WIFI_STATUS
 #define SO_PEEK_OFF            42
 
+/* Instruct lower device to use last 4-bytes of skb data as FCS */
+#define SO_NOFCS               43
+
 #endif /* _ASM_POWERPC_SOCKET_H */
index 581702fa1b0c54f8cc96f26e09c5bbb2840908cd..c91b720965c07063436949394acfb8cb7b2f74f9 100644 (file)
@@ -74,4 +74,7 @@
 #define SCM_WIFI_STATUS                SO_WIFI_STATUS
 #define SO_PEEK_OFF            42
 
+/* Instruct lower device to use last 4-bytes of skb data as FCS */
+#define SO_NOFCS               43
+
 #endif /* _ASM_SOCKET_H */
index 68e2e2746f6f87d64c602c04df9f7f01b0d61165..bea1568ae4af1aeee10008fbf1ae110dc6fa47ae 100644 (file)
 #define SCM_WIFI_STATUS                SO_WIFI_STATUS
 #define SO_PEEK_OFF            0x0026
 
+/* Instruct lower device to use last 4-bytes of skb data as FCS */
+#define SO_NOFCS               0x0027
+
+
 /* Security levels - as per NRL IPv6 - don't actually do anything */
 #define SO_SECURITY_AUTHENTICATION             0x5001
 #define SO_SECURITY_ENCRYPTION_TRANSPORT       0x5002
index 74818b161362b5658a13af5aded717d8bad29914..e36c681849205cd728bbc59b5903c87f61a81a73 100644 (file)
@@ -77,4 +77,7 @@
 #define SCM_WIFI_STATUS                SO_WIFI_STATUS
 #define SO_PEEK_OFF            42
 
+/* Instruct lower device to use last 4-bytes of skb data as FCS */
+#define SO_NOFCS               43
+
 #endif /* _XTENSA_SOCKET_H */
index d9aaac0c36d461e2c43c0b7fce61ccccc8602732..b1bea03274d5dd0ca36d31e90b361d0dc63225ec 100644 (file)
@@ -68,4 +68,8 @@
 #define SO_WIFI_STATUS         41
 #define SCM_WIFI_STATUS        SO_WIFI_STATUS
 #define SO_PEEK_OFF            42
+
+/* Instruct lower device to use last 4-bytes of skb data as FCS */
+#define SO_NOFCS               43
+
 #endif /* __ASM_GENERIC_SOCKET_H */
index 06b6ef60c821a43be68135d8fb4055c2425ff441..f995c663c493baf4d369bcf05d3bed20d38dcd1f 100644 (file)
@@ -80,6 +80,8 @@
                                         * skbs on transmit */
 #define IFF_UNICAST_FLT        0x20000         /* Supports unicast filtering   */
 #define IFF_TEAM_PORT  0x40000         /* device used as team port */
+#define IFF_SUPP_NOFCS 0x80000         /* device supports sending custom FCS */
+
 
 #define IF_GET_IFACE   0x0001          /* for querying only */
 #define IF_GET_PROTO   0x0002
index 0eac07c95255a7cb00f2e39667f3945e1b718f3f..f1b7d037c2c5eb2580a5489b6331b136741de6a7 100644 (file)
@@ -1082,7 +1082,8 @@ struct net_device {
        const struct header_ops *header_ops;
 
        unsigned int            flags;  /* interface flags (a la BSD)   */
-       unsigned int            priv_flags; /* Like 'flags' but invisible to userspace. */
+       unsigned int            priv_flags; /* Like 'flags' but invisible to userspace.
+                                            * See if.h for definitions. */
        unsigned short          gflags;
        unsigned short          padded; /* How much padding added by alloc_netdev() */
 
@@ -2650,6 +2651,11 @@ static inline int netif_is_bond_slave(struct net_device *dev)
        return dev->flags & IFF_SLAVE && dev->priv_flags & IFF_BONDING;
 }
 
+static inline bool netif_supports_nofcs(struct net_device *dev)
+{
+       return dev->priv_flags & IFF_SUPP_NOFCS;
+}
+
 extern struct pernet_operations __net_initdata loopback_net_ops;
 
 /* Logging, debugging and troubleshooting/diagnostic helpers. */
index c11a44ea1bf4f0b342c5521426f6f0ce5a45f712..06a4c0fd7bef79dcb1c61411d36713dfb87847a3 100644 (file)
@@ -361,6 +361,7 @@ typedef unsigned char *sk_buff_data_t;
  *             ports.
  *     @wifi_acked_valid: wifi_acked was set
  *     @wifi_acked: whether frame was acked on wifi or not
+ *     @no_fcs:  Request NIC to treat last 4 bytes as Ethernet FCS
  *     @dma_cookie: a cookie to one of several possible DMA operations
  *             done by skb DMA functions
  *     @secmark: security marking
@@ -459,7 +460,8 @@ struct sk_buff {
        __u8                    l4_rxhash:1;
        __u8                    wifi_acked_valid:1;
        __u8                    wifi_acked:1;
-       /* 10/12 bit hole (depending on ndisc_nodetype presence) */
+       __u8                    no_fcs:1;
+       /* 9/11 bit hole (depending on ndisc_nodetype presence) */
        kmemcheck_bitfield_end(flags2);
 
 #ifdef CONFIG_NET_DMA
index 9c0553b9e451aa07eae214f3dac8a00057f1dbe4..ba761e7de2523bc7c24d6b246da6afb8b1c5ee35 100644 (file)
@@ -615,6 +615,10 @@ enum sock_flags {
        SOCK_RXQ_OVFL,
        SOCK_ZEROCOPY, /* buffers from userspace */
        SOCK_WIFI_STATUS, /* push wifi status to userspace */
+       SOCK_NOFCS, /* Tell NIC not to do the Ethernet FCS.
+                    * Will use last 4 bytes of packet sent from
+                    * user-space instead.
+                    */
 };
 
 static inline void sock_copy_flags(struct sock *nsk, struct sock *osk)
index f3a53078075395602368d3e5a50f1014fea6ae76..6eb656acdfe53a27680c894b5cd8a6a7222f2db1 100644 (file)
@@ -592,6 +592,7 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
        new->rxhash             = old->rxhash;
        new->ooo_okay           = old->ooo_okay;
        new->l4_rxhash          = old->l4_rxhash;
+       new->no_fcs             = old->no_fcs;
 #ifdef CONFIG_XFRM
        new->sp                 = secpath_get(old->sp);
 #endif
index 19942d4bb6e6e63a6b52ebc51c66698adcc5876a..55011cb691ad53afa5659cc7dda01d6c04c394d0 100644 (file)
@@ -799,6 +799,11 @@ set_rcvbuf:
                else
                        ret = -EOPNOTSUPP;
                break;
+
+       case SO_NOFCS:
+               sock_valbool_flag(sk, SOCK_NOFCS, valbool);
+               break;
+
        default:
                ret = -ENOPROTOOPT;
                break;
index 2dbb32b988c4d476406e212f0ff5632677e0501b..ae2d484416dd5170b3c4eed8bd820ee594e5e474 100644 (file)
@@ -1459,6 +1459,7 @@ static int packet_sendmsg_spkt(struct kiocb *iocb, struct socket *sock,
        struct net_device *dev;
        __be16 proto = 0;
        int err;
+       int extra_len = 0;
 
        /*
         *      Get and verify the address.
@@ -1493,8 +1494,16 @@ retry:
         * raw protocol and you must do your own fragmentation at this level.
         */
 
+       if (unlikely(sock_flag(sk, SOCK_NOFCS))) {
+               if (!netif_supports_nofcs(dev)) {
+                       err = -EPROTONOSUPPORT;
+                       goto out_unlock;
+               }
+               extra_len = 4; /* We're doing our own CRC */
+       }
+
        err = -EMSGSIZE;
-       if (len > dev->mtu + dev->hard_header_len + VLAN_HLEN)
+       if (len > dev->mtu + dev->hard_header_len + VLAN_HLEN + extra_len)
                goto out_unlock;
 
        if (!skb) {
@@ -1526,7 +1535,7 @@ retry:
                goto retry;
        }
 
-       if (len > (dev->mtu + dev->hard_header_len)) {
+       if (len > (dev->mtu + dev->hard_header_len + extra_len)) {
                /* Earlier code assumed this would be a VLAN pkt,
                 * double-check this now that we have the actual
                 * packet in hand.
@@ -1548,6 +1557,9 @@ retry:
        if (err < 0)
                goto out_unlock;
 
+       if (unlikely(extra_len == 4))
+               skb->no_fcs = 1;
+
        dev_queue_xmit(skb);
        rcu_read_unlock();
        return len;
@@ -2209,6 +2221,7 @@ static int packet_snd(struct socket *sock,
        struct packet_sock *po = pkt_sk(sk);
        unsigned short gso_type = 0;
        int hlen, tlen;
+       int extra_len = 0;
 
        /*
         *      Get and verify the address.
@@ -2288,8 +2301,16 @@ static int packet_snd(struct socket *sock,
                }
        }
 
+       if (unlikely(sock_flag(sk, SOCK_NOFCS))) {
+               if (!netif_supports_nofcs(dev)) {
+                       err = -EPROTONOSUPPORT;
+                       goto out_unlock;
+               }
+               extra_len = 4; /* We're doing our own CRC */
+       }
+
        err = -EMSGSIZE;
-       if (!gso_type && (len > dev->mtu + reserve + VLAN_HLEN))
+       if (!gso_type && (len > dev->mtu + reserve + VLAN_HLEN + extra_len))
                goto out_unlock;
 
        err = -ENOBUFS;
@@ -2315,7 +2336,7 @@ static int packet_snd(struct socket *sock,
        if (err < 0)
                goto out_free;
 
-       if (!gso_type && (len > dev->mtu + reserve)) {
+       if (!gso_type && (len > dev->mtu + reserve + extra_len)) {
                /* Earlier code assumed this would be a VLAN pkt,
                 * double-check this now that we have the actual
                 * packet in hand.
@@ -2353,6 +2374,9 @@ static int packet_snd(struct socket *sock,
                len += vnet_hdr_len;
        }
 
+       if (unlikely(extra_len == 4))
+               skb->no_fcs = 1;
+
        /*
         *      Now send it
         */