aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Greear <greearb@candelatech.com>2012-02-11 10:39:30 -0500
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2012-02-24 04:37:35 -0500
commit3bdc0eba0b8b47797f4a76e377dd8360f317450f (patch)
treeda6bd907f599402bc8db0a2484997fd4d3e06f7b
parent0184039a4b6727d6efd545919c773ef141090ae7 (diff)
net: Add framework to allow sending packets with customized CRC.
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>
-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 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
2654static inline bool netif_supports_nofcs(struct net_device *dev)
2655{
2656 return dev->priv_flags & IFF_SUPP_NOFCS;
2657}
2658
2653extern struct pernet_operations __net_initdata loopback_net_ops; 2659extern 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
620static inline void sock_copy_flags(struct sock *nsk, struct sock *osk) 624static 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 */