summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/alpha/include/asm/socket.h3
-rw-r--r--arch/arm/include/asm/socket.h3
-rw-r--r--arch/avr32/include/asm/socket.h3
-rw-r--r--arch/cris/include/asm/socket.h3
-rw-r--r--arch/frv/include/asm/socket.h3
-rw-r--r--arch/h8300/include/asm/socket.h3
-rw-r--r--arch/ia64/include/asm/socket.h3
-rw-r--r--arch/m32r/include/asm/socket.h3
-rw-r--r--arch/m68k/include/asm/socket.h3
-rw-r--r--arch/mips/include/asm/socket.h3
-rw-r--r--arch/mn10300/include/asm/socket.h3
-rw-r--r--arch/parisc/include/asm/socket.h4
-rw-r--r--arch/powerpc/include/asm/socket.h3
-rw-r--r--arch/s390/include/asm/socket.h3
-rw-r--r--arch/sparc/include/asm/socket.h4
-rw-r--r--arch/xtensa/include/asm/socket.h3
-rw-r--r--include/asm-generic/socket.h4
-rw-r--r--include/linux/if.h2
-rw-r--r--include/linux/netdevice.h8
-rw-r--r--include/linux/skbuff.h4
-rw-r--r--include/net/sock.h4
-rw-r--r--net/core/skbuff.c1
-rw-r--r--net/core/sock.c5
-rw-r--r--net/packet/af_packet.c32
24 files changed, 104 insertions, 6 deletions
diff --git a/arch/alpha/include/asm/socket.h b/arch/alpha/include/asm/socket.h
index 16449d330da..dcb221a4b5b 100644
--- a/arch/alpha/include/asm/socket.h
+++ b/arch/alpha/include/asm/socket.h
@@ -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.
*/
diff --git a/arch/arm/include/asm/socket.h b/arch/arm/include/asm/socket.h
index d958c74e526..6433cadb6ed 100644
--- a/arch/arm/include/asm/socket.h
+++ b/arch/arm/include/asm/socket.h
@@ -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 */
diff --git a/arch/avr32/include/asm/socket.h b/arch/avr32/include/asm/socket.h
index 30078f98b3a..a473f8c6a9a 100644
--- a/arch/avr32/include/asm/socket.h
+++ b/arch/avr32/include/asm/socket.h
@@ -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 */
diff --git a/arch/cris/include/asm/socket.h b/arch/cris/include/asm/socket.h
index 048aba64600..ae52825021a 100644
--- a/arch/cris/include/asm/socket.h
+++ b/arch/cris/include/asm/socket.h
@@ -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 */
diff --git a/arch/frv/include/asm/socket.h b/arch/frv/include/asm/socket.h
index 7a361810f3c..a5b1d7dbb20 100644
--- a/arch/frv/include/asm/socket.h
+++ b/arch/frv/include/asm/socket.h
@@ -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 */
diff --git a/arch/h8300/include/asm/socket.h b/arch/h8300/include/asm/socket.h
index e7bbfcee5b9..ec4554e7b04 100644
--- a/arch/h8300/include/asm/socket.h
+++ b/arch/h8300/include/asm/socket.h
@@ -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 */
diff --git a/arch/ia64/include/asm/socket.h b/arch/ia64/include/asm/socket.h
index ced62de9d5a..41fc28a4a18 100644
--- a/arch/ia64/include/asm/socket.h
+++ b/arch/ia64/include/asm/socket.h
@@ -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 */
diff --git a/arch/m32r/include/asm/socket.h b/arch/m32r/include/asm/socket.h
index 696cb4c7ca4..a15f40b5278 100644
--- a/arch/m32r/include/asm/socket.h
+++ b/arch/m32r/include/asm/socket.h
@@ -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 */
diff --git a/arch/m68k/include/asm/socket.h b/arch/m68k/include/asm/socket.h
index e8b41a6775f..d1be684edf9 100644
--- a/arch/m68k/include/asm/socket.h
+++ b/arch/m68k/include/asm/socket.h
@@ -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 */
diff --git a/arch/mips/include/asm/socket.h b/arch/mips/include/asm/socket.h
index 52104872e9e..a2ed6fdad4e 100644
--- a/arch/mips/include/asm/socket.h
+++ b/arch/mips/include/asm/socket.h
@@ -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
diff --git a/arch/mn10300/include/asm/socket.h b/arch/mn10300/include/asm/socket.h
index 013fcc51698..820463a484b 100644
--- a/arch/mn10300/include/asm/socket.h
+++ b/arch/mn10300/include/asm/socket.h
@@ -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 */
diff --git a/arch/parisc/include/asm/socket.h b/arch/parisc/include/asm/socket.h
index f717c9bec16..1b52c2c31a7 100644
--- a/arch/parisc/include/asm/socket.h
+++ b/arch/parisc/include/asm/socket.h
@@ -65,6 +65,10 @@
#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.
*/
diff --git a/arch/powerpc/include/asm/socket.h b/arch/powerpc/include/asm/socket.h
index fe1c0b478fd..3d5179bb122 100644
--- a/arch/powerpc/include/asm/socket.h
+++ b/arch/powerpc/include/asm/socket.h
@@ -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 */
diff --git a/arch/s390/include/asm/socket.h b/arch/s390/include/asm/socket.h
index 581702fa1b0..c91b720965c 100644
--- a/arch/s390/include/asm/socket.h
+++ b/arch/s390/include/asm/socket.h
@@ -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 */
diff --git a/arch/sparc/include/asm/socket.h b/arch/sparc/include/asm/socket.h
index 68e2e2746f6..bea1568ae4a 100644
--- a/arch/sparc/include/asm/socket.h
+++ b/arch/sparc/include/asm/socket.h
@@ -62,6 +62,10 @@
#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
diff --git a/arch/xtensa/include/asm/socket.h b/arch/xtensa/include/asm/socket.h
index 74818b16136..e36c6818492 100644
--- a/arch/xtensa/include/asm/socket.h
+++ b/arch/xtensa/include/asm/socket.h
@@ -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 */
diff --git a/include/asm-generic/socket.h b/include/asm-generic/socket.h
index d9aaac0c36d..b1bea03274d 100644
--- a/include/asm-generic/socket.h
+++ b/include/asm-generic/socket.h
@@ -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 */
diff --git a/include/linux/if.h b/include/linux/if.h
index 06b6ef60c82..f995c663c49 100644
--- a/include/linux/if.h
+++ b/include/linux/if.h
@@ -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
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 0eac07c9525..f1b7d037c2c 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -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. */
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index c11a44ea1bf..06a4c0fd7be 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -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
diff --git a/include/net/sock.h b/include/net/sock.h
index 9c0553b9e45..ba761e7de25 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -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)
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index f3a53078075..6eb656acdfe 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -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
diff --git a/net/core/sock.c b/net/core/sock.c
index 19942d4bb6e..55011cb691a 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -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;
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 2dbb32b988c..ae2d484416d 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -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
*/