diff options
-rw-r--r-- | arch/alpha/include/asm/socket.h | 3 | ||||
-rw-r--r-- | arch/arm/include/asm/socket.h | 3 | ||||
-rw-r--r-- | arch/avr32/include/asm/socket.h | 3 | ||||
-rw-r--r-- | arch/cris/include/asm/socket.h | 3 | ||||
-rw-r--r-- | arch/frv/include/asm/socket.h | 3 | ||||
-rw-r--r-- | arch/h8300/include/asm/socket.h | 3 | ||||
-rw-r--r-- | arch/ia64/include/asm/socket.h | 3 | ||||
-rw-r--r-- | arch/m32r/include/asm/socket.h | 3 | ||||
-rw-r--r-- | arch/m68k/include/asm/socket.h | 3 | ||||
-rw-r--r-- | arch/mips/include/asm/socket.h | 3 | ||||
-rw-r--r-- | arch/mn10300/include/asm/socket.h | 3 | ||||
-rw-r--r-- | arch/parisc/include/asm/socket.h | 4 | ||||
-rw-r--r-- | arch/powerpc/include/asm/socket.h | 3 | ||||
-rw-r--r-- | arch/s390/include/asm/socket.h | 3 | ||||
-rw-r--r-- | arch/sparc/include/asm/socket.h | 4 | ||||
-rw-r--r-- | arch/xtensa/include/asm/socket.h | 3 | ||||
-rw-r--r-- | include/asm-generic/socket.h | 4 | ||||
-rw-r--r-- | include/linux/if.h | 2 | ||||
-rw-r--r-- | include/linux/netdevice.h | 8 | ||||
-rw-r--r-- | include/linux/skbuff.h | 4 | ||||
-rw-r--r-- | include/net/sock.h | 4 | ||||
-rw-r--r-- | net/core/skbuff.c | 1 | ||||
-rw-r--r-- | net/core/sock.c | 5 | ||||
-rw-r--r-- | net/packet/af_packet.c | 32 |
24 files changed, 104 insertions, 6 deletions
diff --git a/arch/alpha/include/asm/socket.h b/arch/alpha/include/asm/socket.h index 16449d330dae..dcb221a4b5be 100644 --- a/arch/alpha/include/asm/socket.h +++ b/arch/alpha/include/asm/socket.h | |||
@@ -73,6 +73,9 @@ | |||
73 | #define SCM_WIFI_STATUS SO_WIFI_STATUS | 73 | #define SCM_WIFI_STATUS SO_WIFI_STATUS |
74 | #define SO_PEEK_OFF 42 | 74 | #define SO_PEEK_OFF 42 |
75 | 75 | ||
76 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ | ||
77 | #define SO_NOFCS 43 | ||
78 | |||
76 | /* O_NONBLOCK clashes with the bits used for socket types. Therefore we | 79 | /* O_NONBLOCK clashes with the bits used for socket types. Therefore we |
77 | * have to define SOCK_NONBLOCK to a different value here. | 80 | * have to define SOCK_NONBLOCK to a different value here. |
78 | */ | 81 | */ |
diff --git a/arch/arm/include/asm/socket.h b/arch/arm/include/asm/socket.h index d958c74e5260..6433cadb6ed4 100644 --- a/arch/arm/include/asm/socket.h +++ b/arch/arm/include/asm/socket.h | |||
@@ -66,4 +66,7 @@ | |||
66 | #define SCM_WIFI_STATUS SO_WIFI_STATUS | 66 | #define SCM_WIFI_STATUS SO_WIFI_STATUS |
67 | #define SO_PEEK_OFF 42 | 67 | #define SO_PEEK_OFF 42 |
68 | 68 | ||
69 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ | ||
70 | #define SO_NOFCS 43 | ||
71 | |||
69 | #endif /* _ASM_SOCKET_H */ | 72 | #endif /* _ASM_SOCKET_H */ |
diff --git a/arch/avr32/include/asm/socket.h b/arch/avr32/include/asm/socket.h index 30078f98b3ab..a473f8c6a9aa 100644 --- a/arch/avr32/include/asm/socket.h +++ b/arch/avr32/include/asm/socket.h | |||
@@ -66,4 +66,7 @@ | |||
66 | #define SCM_WIFI_STATUS SO_WIFI_STATUS | 66 | #define SCM_WIFI_STATUS SO_WIFI_STATUS |
67 | #define SO_PEEK_OFF 42 | 67 | #define SO_PEEK_OFF 42 |
68 | 68 | ||
69 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ | ||
70 | #define SO_NOFCS 43 | ||
71 | |||
69 | #endif /* __ASM_AVR32_SOCKET_H */ | 72 | #endif /* __ASM_AVR32_SOCKET_H */ |
diff --git a/arch/cris/include/asm/socket.h b/arch/cris/include/asm/socket.h index 048aba64600c..ae52825021af 100644 --- a/arch/cris/include/asm/socket.h +++ b/arch/cris/include/asm/socket.h | |||
@@ -68,6 +68,9 @@ | |||
68 | #define SCM_WIFI_STATUS SO_WIFI_STATUS | 68 | #define SCM_WIFI_STATUS SO_WIFI_STATUS |
69 | #define SO_PEEK_OFF 42 | 69 | #define SO_PEEK_OFF 42 |
70 | 70 | ||
71 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ | ||
72 | #define SO_NOFCS 43 | ||
73 | |||
71 | #endif /* _ASM_SOCKET_H */ | 74 | #endif /* _ASM_SOCKET_H */ |
72 | 75 | ||
73 | 76 | ||
diff --git a/arch/frv/include/asm/socket.h b/arch/frv/include/asm/socket.h index 7a361810f3cc..a5b1d7dbb205 100644 --- a/arch/frv/include/asm/socket.h +++ b/arch/frv/include/asm/socket.h | |||
@@ -66,5 +66,8 @@ | |||
66 | #define SCM_WIFI_STATUS SO_WIFI_STATUS | 66 | #define SCM_WIFI_STATUS SO_WIFI_STATUS |
67 | #define SO_PEEK_OFF 42 | 67 | #define SO_PEEK_OFF 42 |
68 | 68 | ||
69 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ | ||
70 | #define SO_NOFCS 43 | ||
71 | |||
69 | #endif /* _ASM_SOCKET_H */ | 72 | #endif /* _ASM_SOCKET_H */ |
70 | 73 | ||
diff --git a/arch/h8300/include/asm/socket.h b/arch/h8300/include/asm/socket.h index e7bbfcee5b99..ec4554e7b04b 100644 --- a/arch/h8300/include/asm/socket.h +++ b/arch/h8300/include/asm/socket.h | |||
@@ -66,4 +66,7 @@ | |||
66 | #define SCM_WIFI_STATUS SO_WIFI_STATUS | 66 | #define SCM_WIFI_STATUS SO_WIFI_STATUS |
67 | #define SO_PEEK_OFF 42 | 67 | #define SO_PEEK_OFF 42 |
68 | 68 | ||
69 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ | ||
70 | #define SO_NOFCS 43 | ||
71 | |||
69 | #endif /* _ASM_SOCKET_H */ | 72 | #endif /* _ASM_SOCKET_H */ |
diff --git a/arch/ia64/include/asm/socket.h b/arch/ia64/include/asm/socket.h index ced62de9d5a9..41fc28a4a18a 100644 --- a/arch/ia64/include/asm/socket.h +++ b/arch/ia64/include/asm/socket.h | |||
@@ -75,4 +75,7 @@ | |||
75 | #define SCM_WIFI_STATUS SO_WIFI_STATUS | 75 | #define SCM_WIFI_STATUS SO_WIFI_STATUS |
76 | #define SO_PEEK_OFF 42 | 76 | #define SO_PEEK_OFF 42 |
77 | 77 | ||
78 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ | ||
79 | #define SO_NOFCS 43 | ||
80 | |||
78 | #endif /* _ASM_IA64_SOCKET_H */ | 81 | #endif /* _ASM_IA64_SOCKET_H */ |
diff --git a/arch/m32r/include/asm/socket.h b/arch/m32r/include/asm/socket.h index 696cb4c7ca4e..a15f40b52783 100644 --- a/arch/m32r/include/asm/socket.h +++ b/arch/m32r/include/asm/socket.h | |||
@@ -66,4 +66,7 @@ | |||
66 | #define SCM_WIFI_STATUS SO_WIFI_STATUS | 66 | #define SCM_WIFI_STATUS SO_WIFI_STATUS |
67 | #define SO_PEEK_OFF 42 | 67 | #define SO_PEEK_OFF 42 |
68 | 68 | ||
69 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ | ||
70 | #define SO_NOFCS 43 | ||
71 | |||
69 | #endif /* _ASM_M32R_SOCKET_H */ | 72 | #endif /* _ASM_M32R_SOCKET_H */ |
diff --git a/arch/m68k/include/asm/socket.h b/arch/m68k/include/asm/socket.h index e8b41a6775f9..d1be684edf97 100644 --- a/arch/m68k/include/asm/socket.h +++ b/arch/m68k/include/asm/socket.h | |||
@@ -66,4 +66,7 @@ | |||
66 | #define SCM_WIFI_STATUS SO_WIFI_STATUS | 66 | #define SCM_WIFI_STATUS SO_WIFI_STATUS |
67 | #define SO_PEEK_OFF 42 | 67 | #define SO_PEEK_OFF 42 |
68 | 68 | ||
69 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ | ||
70 | #define SO_NOFCS 43 | ||
71 | |||
69 | #endif /* _ASM_SOCKET_H */ | 72 | #endif /* _ASM_SOCKET_H */ |
diff --git a/arch/mips/include/asm/socket.h b/arch/mips/include/asm/socket.h index 52104872e9e3..a2ed6fdad4e0 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. */ | |||
86 | #define SCM_WIFI_STATUS SO_WIFI_STATUS | 86 | #define SCM_WIFI_STATUS SO_WIFI_STATUS |
87 | #define SO_PEEK_OFF 42 | 87 | #define SO_PEEK_OFF 42 |
88 | 88 | ||
89 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ | ||
90 | #define SO_NOFCS 43 | ||
91 | |||
89 | #ifdef __KERNEL__ | 92 | #ifdef __KERNEL__ |
90 | 93 | ||
91 | /** sock_type - Socket types | 94 | /** sock_type - Socket types |
diff --git a/arch/mn10300/include/asm/socket.h b/arch/mn10300/include/asm/socket.h index 013fcc51698f..820463a484b8 100644 --- a/arch/mn10300/include/asm/socket.h +++ b/arch/mn10300/include/asm/socket.h | |||
@@ -66,4 +66,7 @@ | |||
66 | #define SCM_WIFI_STATUS SO_WIFI_STATUS | 66 | #define SCM_WIFI_STATUS SO_WIFI_STATUS |
67 | #define SO_PEEK_OFF 42 | 67 | #define SO_PEEK_OFF 42 |
68 | 68 | ||
69 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ | ||
70 | #define SO_NOFCS 43 | ||
71 | |||
69 | #endif /* _ASM_SOCKET_H */ | 72 | #endif /* _ASM_SOCKET_H */ |
diff --git a/arch/parisc/include/asm/socket.h b/arch/parisc/include/asm/socket.h index f717c9bec16f..1b52c2c31a7a 100644 --- a/arch/parisc/include/asm/socket.h +++ b/arch/parisc/include/asm/socket.h | |||
@@ -65,6 +65,10 @@ | |||
65 | #define SCM_WIFI_STATUS SO_WIFI_STATUS | 65 | #define SCM_WIFI_STATUS SO_WIFI_STATUS |
66 | #define SO_PEEK_OFF 0x4023 | 66 | #define SO_PEEK_OFF 0x4023 |
67 | 67 | ||
68 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ | ||
69 | #define SO_NOFCS 0x4024 | ||
70 | |||
71 | |||
68 | /* O_NONBLOCK clashes with the bits used for socket types. Therefore we | 72 | /* O_NONBLOCK clashes with the bits used for socket types. Therefore we |
69 | * have to define SOCK_NONBLOCK to a different value here. | 73 | * have to define SOCK_NONBLOCK to a different value here. |
70 | */ | 74 | */ |
diff --git a/arch/powerpc/include/asm/socket.h b/arch/powerpc/include/asm/socket.h index fe1c0b478fd7..3d5179bb122f 100644 --- a/arch/powerpc/include/asm/socket.h +++ b/arch/powerpc/include/asm/socket.h | |||
@@ -73,4 +73,7 @@ | |||
73 | #define SCM_WIFI_STATUS SO_WIFI_STATUS | 73 | #define SCM_WIFI_STATUS SO_WIFI_STATUS |
74 | #define SO_PEEK_OFF 42 | 74 | #define SO_PEEK_OFF 42 |
75 | 75 | ||
76 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ | ||
77 | #define SO_NOFCS 43 | ||
78 | |||
76 | #endif /* _ASM_POWERPC_SOCKET_H */ | 79 | #endif /* _ASM_POWERPC_SOCKET_H */ |
diff --git a/arch/s390/include/asm/socket.h b/arch/s390/include/asm/socket.h index 581702fa1b0c..c91b720965c0 100644 --- a/arch/s390/include/asm/socket.h +++ b/arch/s390/include/asm/socket.h | |||
@@ -74,4 +74,7 @@ | |||
74 | #define SCM_WIFI_STATUS SO_WIFI_STATUS | 74 | #define SCM_WIFI_STATUS SO_WIFI_STATUS |
75 | #define SO_PEEK_OFF 42 | 75 | #define SO_PEEK_OFF 42 |
76 | 76 | ||
77 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ | ||
78 | #define SO_NOFCS 43 | ||
79 | |||
77 | #endif /* _ASM_SOCKET_H */ | 80 | #endif /* _ASM_SOCKET_H */ |
diff --git a/arch/sparc/include/asm/socket.h b/arch/sparc/include/asm/socket.h index 68e2e2746f6f..bea1568ae4af 100644 --- a/arch/sparc/include/asm/socket.h +++ b/arch/sparc/include/asm/socket.h | |||
@@ -62,6 +62,10 @@ | |||
62 | #define SCM_WIFI_STATUS SO_WIFI_STATUS | 62 | #define SCM_WIFI_STATUS SO_WIFI_STATUS |
63 | #define SO_PEEK_OFF 0x0026 | 63 | #define SO_PEEK_OFF 0x0026 |
64 | 64 | ||
65 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ | ||
66 | #define SO_NOFCS 0x0027 | ||
67 | |||
68 | |||
65 | /* Security levels - as per NRL IPv6 - don't actually do anything */ | 69 | /* Security levels - as per NRL IPv6 - don't actually do anything */ |
66 | #define SO_SECURITY_AUTHENTICATION 0x5001 | 70 | #define SO_SECURITY_AUTHENTICATION 0x5001 |
67 | #define SO_SECURITY_ENCRYPTION_TRANSPORT 0x5002 | 71 | #define SO_SECURITY_ENCRYPTION_TRANSPORT 0x5002 |
diff --git a/arch/xtensa/include/asm/socket.h b/arch/xtensa/include/asm/socket.h index 74818b161362..e36c68184920 100644 --- a/arch/xtensa/include/asm/socket.h +++ b/arch/xtensa/include/asm/socket.h | |||
@@ -77,4 +77,7 @@ | |||
77 | #define SCM_WIFI_STATUS SO_WIFI_STATUS | 77 | #define SCM_WIFI_STATUS SO_WIFI_STATUS |
78 | #define SO_PEEK_OFF 42 | 78 | #define SO_PEEK_OFF 42 |
79 | 79 | ||
80 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ | ||
81 | #define SO_NOFCS 43 | ||
82 | |||
80 | #endif /* _XTENSA_SOCKET_H */ | 83 | #endif /* _XTENSA_SOCKET_H */ |
diff --git a/include/asm-generic/socket.h b/include/asm-generic/socket.h index d9aaac0c36d4..b1bea03274d5 100644 --- a/include/asm-generic/socket.h +++ b/include/asm-generic/socket.h | |||
@@ -68,4 +68,8 @@ | |||
68 | #define SO_WIFI_STATUS 41 | 68 | #define SO_WIFI_STATUS 41 |
69 | #define SCM_WIFI_STATUS SO_WIFI_STATUS | 69 | #define SCM_WIFI_STATUS SO_WIFI_STATUS |
70 | #define SO_PEEK_OFF 42 | 70 | #define SO_PEEK_OFF 42 |
71 | |||
72 | /* Instruct lower device to use last 4-bytes of skb data as FCS */ | ||
73 | #define SO_NOFCS 43 | ||
74 | |||
71 | #endif /* __ASM_GENERIC_SOCKET_H */ | 75 | #endif /* __ASM_GENERIC_SOCKET_H */ |
diff --git a/include/linux/if.h b/include/linux/if.h index 06b6ef60c821..f995c663c493 100644 --- a/include/linux/if.h +++ b/include/linux/if.h | |||
@@ -80,6 +80,8 @@ | |||
80 | * skbs on transmit */ | 80 | * skbs on transmit */ |
81 | #define IFF_UNICAST_FLT 0x20000 /* Supports unicast filtering */ | 81 | #define IFF_UNICAST_FLT 0x20000 /* Supports unicast filtering */ |
82 | #define IFF_TEAM_PORT 0x40000 /* device used as team port */ | 82 | #define IFF_TEAM_PORT 0x40000 /* device used as team port */ |
83 | #define IFF_SUPP_NOFCS 0x80000 /* device supports sending custom FCS */ | ||
84 | |||
83 | 85 | ||
84 | #define IF_GET_IFACE 0x0001 /* for querying only */ | 86 | #define IF_GET_IFACE 0x0001 /* for querying only */ |
85 | #define IF_GET_PROTO 0x0002 | 87 | #define IF_GET_PROTO 0x0002 |
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 0eac07c95255..f1b7d037c2c5 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -1082,7 +1082,8 @@ struct net_device { | |||
1082 | const struct header_ops *header_ops; | 1082 | const struct header_ops *header_ops; |
1083 | 1083 | ||
1084 | unsigned int flags; /* interface flags (a la BSD) */ | 1084 | unsigned int flags; /* interface flags (a la BSD) */ |
1085 | unsigned int priv_flags; /* Like 'flags' but invisible to userspace. */ | 1085 | unsigned int priv_flags; /* Like 'flags' but invisible to userspace. |
1086 | * See if.h for definitions. */ | ||
1086 | unsigned short gflags; | 1087 | unsigned short gflags; |
1087 | unsigned short padded; /* How much padding added by alloc_netdev() */ | 1088 | unsigned short padded; /* How much padding added by alloc_netdev() */ |
1088 | 1089 | ||
@@ -2650,6 +2651,11 @@ static inline int netif_is_bond_slave(struct net_device *dev) | |||
2650 | return dev->flags & IFF_SLAVE && dev->priv_flags & IFF_BONDING; | 2651 | return dev->flags & IFF_SLAVE && dev->priv_flags & IFF_BONDING; |
2651 | } | 2652 | } |
2652 | 2653 | ||
2654 | static inline bool netif_supports_nofcs(struct net_device *dev) | ||
2655 | { | ||
2656 | return dev->priv_flags & IFF_SUPP_NOFCS; | ||
2657 | } | ||
2658 | |||
2653 | extern struct pernet_operations __net_initdata loopback_net_ops; | 2659 | extern struct pernet_operations __net_initdata loopback_net_ops; |
2654 | 2660 | ||
2655 | /* Logging, debugging and troubleshooting/diagnostic helpers. */ | 2661 | /* Logging, debugging and troubleshooting/diagnostic helpers. */ |
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index c11a44ea1bf4..06a4c0fd7bef 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h | |||
@@ -361,6 +361,7 @@ typedef unsigned char *sk_buff_data_t; | |||
361 | * ports. | 361 | * ports. |
362 | * @wifi_acked_valid: wifi_acked was set | 362 | * @wifi_acked_valid: wifi_acked was set |
363 | * @wifi_acked: whether frame was acked on wifi or not | 363 | * @wifi_acked: whether frame was acked on wifi or not |
364 | * @no_fcs: Request NIC to treat last 4 bytes as Ethernet FCS | ||
364 | * @dma_cookie: a cookie to one of several possible DMA operations | 365 | * @dma_cookie: a cookie to one of several possible DMA operations |
365 | * done by skb DMA functions | 366 | * done by skb DMA functions |
366 | * @secmark: security marking | 367 | * @secmark: security marking |
@@ -459,7 +460,8 @@ struct sk_buff { | |||
459 | __u8 l4_rxhash:1; | 460 | __u8 l4_rxhash:1; |
460 | __u8 wifi_acked_valid:1; | 461 | __u8 wifi_acked_valid:1; |
461 | __u8 wifi_acked:1; | 462 | __u8 wifi_acked:1; |
462 | /* 10/12 bit hole (depending on ndisc_nodetype presence) */ | 463 | __u8 no_fcs:1; |
464 | /* 9/11 bit hole (depending on ndisc_nodetype presence) */ | ||
463 | kmemcheck_bitfield_end(flags2); | 465 | kmemcheck_bitfield_end(flags2); |
464 | 466 | ||
465 | #ifdef CONFIG_NET_DMA | 467 | #ifdef CONFIG_NET_DMA |
diff --git a/include/net/sock.h b/include/net/sock.h index 9c0553b9e451..ba761e7de252 100644 --- a/include/net/sock.h +++ b/include/net/sock.h | |||
@@ -615,6 +615,10 @@ enum sock_flags { | |||
615 | SOCK_RXQ_OVFL, | 615 | SOCK_RXQ_OVFL, |
616 | SOCK_ZEROCOPY, /* buffers from userspace */ | 616 | SOCK_ZEROCOPY, /* buffers from userspace */ |
617 | SOCK_WIFI_STATUS, /* push wifi status to userspace */ | 617 | SOCK_WIFI_STATUS, /* push wifi status to userspace */ |
618 | SOCK_NOFCS, /* Tell NIC not to do the Ethernet FCS. | ||
619 | * Will use last 4 bytes of packet sent from | ||
620 | * user-space instead. | ||
621 | */ | ||
618 | }; | 622 | }; |
619 | 623 | ||
620 | static inline void sock_copy_flags(struct sock *nsk, struct sock *osk) | 624 | 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 f3a530780753..6eb656acdfe5 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) | |||
592 | new->rxhash = old->rxhash; | 592 | new->rxhash = old->rxhash; |
593 | new->ooo_okay = old->ooo_okay; | 593 | new->ooo_okay = old->ooo_okay; |
594 | new->l4_rxhash = old->l4_rxhash; | 594 | new->l4_rxhash = old->l4_rxhash; |
595 | new->no_fcs = old->no_fcs; | ||
595 | #ifdef CONFIG_XFRM | 596 | #ifdef CONFIG_XFRM |
596 | new->sp = secpath_get(old->sp); | 597 | new->sp = secpath_get(old->sp); |
597 | #endif | 598 | #endif |
diff --git a/net/core/sock.c b/net/core/sock.c index 19942d4bb6e6..55011cb691ad 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -799,6 +799,11 @@ set_rcvbuf: | |||
799 | else | 799 | else |
800 | ret = -EOPNOTSUPP; | 800 | ret = -EOPNOTSUPP; |
801 | break; | 801 | break; |
802 | |||
803 | case SO_NOFCS: | ||
804 | sock_valbool_flag(sk, SOCK_NOFCS, valbool); | ||
805 | break; | ||
806 | |||
802 | default: | 807 | default: |
803 | ret = -ENOPROTOOPT; | 808 | ret = -ENOPROTOOPT; |
804 | break; | 809 | break; |
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 2dbb32b988c4..ae2d484416dd 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, | |||
1459 | struct net_device *dev; | 1459 | struct net_device *dev; |
1460 | __be16 proto = 0; | 1460 | __be16 proto = 0; |
1461 | int err; | 1461 | int err; |
1462 | int extra_len = 0; | ||
1462 | 1463 | ||
1463 | /* | 1464 | /* |
1464 | * Get and verify the address. | 1465 | * Get and verify the address. |
@@ -1493,8 +1494,16 @@ retry: | |||
1493 | * raw protocol and you must do your own fragmentation at this level. | 1494 | * raw protocol and you must do your own fragmentation at this level. |
1494 | */ | 1495 | */ |
1495 | 1496 | ||
1497 | if (unlikely(sock_flag(sk, SOCK_NOFCS))) { | ||
1498 | if (!netif_supports_nofcs(dev)) { | ||
1499 | err = -EPROTONOSUPPORT; | ||
1500 | goto out_unlock; | ||
1501 | } | ||
1502 | extra_len = 4; /* We're doing our own CRC */ | ||
1503 | } | ||
1504 | |||
1496 | err = -EMSGSIZE; | 1505 | err = -EMSGSIZE; |
1497 | if (len > dev->mtu + dev->hard_header_len + VLAN_HLEN) | 1506 | if (len > dev->mtu + dev->hard_header_len + VLAN_HLEN + extra_len) |
1498 | goto out_unlock; | 1507 | goto out_unlock; |
1499 | 1508 | ||
1500 | if (!skb) { | 1509 | if (!skb) { |
@@ -1526,7 +1535,7 @@ retry: | |||
1526 | goto retry; | 1535 | goto retry; |
1527 | } | 1536 | } |
1528 | 1537 | ||
1529 | if (len > (dev->mtu + dev->hard_header_len)) { | 1538 | if (len > (dev->mtu + dev->hard_header_len + extra_len)) { |
1530 | /* Earlier code assumed this would be a VLAN pkt, | 1539 | /* Earlier code assumed this would be a VLAN pkt, |
1531 | * double-check this now that we have the actual | 1540 | * double-check this now that we have the actual |
1532 | * packet in hand. | 1541 | * packet in hand. |
@@ -1548,6 +1557,9 @@ retry: | |||
1548 | if (err < 0) | 1557 | if (err < 0) |
1549 | goto out_unlock; | 1558 | goto out_unlock; |
1550 | 1559 | ||
1560 | if (unlikely(extra_len == 4)) | ||
1561 | skb->no_fcs = 1; | ||
1562 | |||
1551 | dev_queue_xmit(skb); | 1563 | dev_queue_xmit(skb); |
1552 | rcu_read_unlock(); | 1564 | rcu_read_unlock(); |
1553 | return len; | 1565 | return len; |
@@ -2209,6 +2221,7 @@ static int packet_snd(struct socket *sock, | |||
2209 | struct packet_sock *po = pkt_sk(sk); | 2221 | struct packet_sock *po = pkt_sk(sk); |
2210 | unsigned short gso_type = 0; | 2222 | unsigned short gso_type = 0; |
2211 | int hlen, tlen; | 2223 | int hlen, tlen; |
2224 | int extra_len = 0; | ||
2212 | 2225 | ||
2213 | /* | 2226 | /* |
2214 | * Get and verify the address. | 2227 | * Get and verify the address. |
@@ -2288,8 +2301,16 @@ static int packet_snd(struct socket *sock, | |||
2288 | } | 2301 | } |
2289 | } | 2302 | } |
2290 | 2303 | ||
2304 | if (unlikely(sock_flag(sk, SOCK_NOFCS))) { | ||
2305 | if (!netif_supports_nofcs(dev)) { | ||
2306 | err = -EPROTONOSUPPORT; | ||
2307 | goto out_unlock; | ||
2308 | } | ||
2309 | extra_len = 4; /* We're doing our own CRC */ | ||
2310 | } | ||
2311 | |||
2291 | err = -EMSGSIZE; | 2312 | err = -EMSGSIZE; |
2292 | if (!gso_type && (len > dev->mtu + reserve + VLAN_HLEN)) | 2313 | if (!gso_type && (len > dev->mtu + reserve + VLAN_HLEN + extra_len)) |
2293 | goto out_unlock; | 2314 | goto out_unlock; |
2294 | 2315 | ||
2295 | err = -ENOBUFS; | 2316 | err = -ENOBUFS; |
@@ -2315,7 +2336,7 @@ static int packet_snd(struct socket *sock, | |||
2315 | if (err < 0) | 2336 | if (err < 0) |
2316 | goto out_free; | 2337 | goto out_free; |
2317 | 2338 | ||
2318 | if (!gso_type && (len > dev->mtu + reserve)) { | 2339 | if (!gso_type && (len > dev->mtu + reserve + extra_len)) { |
2319 | /* Earlier code assumed this would be a VLAN pkt, | 2340 | /* Earlier code assumed this would be a VLAN pkt, |
2320 | * double-check this now that we have the actual | 2341 | * double-check this now that we have the actual |
2321 | * packet in hand. | 2342 | * packet in hand. |
@@ -2353,6 +2374,9 @@ static int packet_snd(struct socket *sock, | |||
2353 | len += vnet_hdr_len; | 2374 | len += vnet_hdr_len; |
2354 | } | 2375 | } |
2355 | 2376 | ||
2377 | if (unlikely(extra_len == 4)) | ||
2378 | skb->no_fcs = 1; | ||
2379 | |||
2356 | /* | 2380 | /* |
2357 | * Now send it | 2381 | * Now send it |
2358 | */ | 2382 | */ |