From 4031ae6edb92f7e0aade76357813211ae0520a5c Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 27 Jan 2012 06:22:53 +0000 Subject: skbuff: Move rxhash and vlan_tci to consolidate holes in sk_buff This change helps to reduce the overall size of the sk_buff by moving rxhash and vlan_tci so that the u16 values and u8 bitfields can be better combined to create only one hole instead of multiple. Signed-off-by: Alexander Duyck Tested-by: Stephen Ko Signed-off-by: Jeff Kirsher --- include/linux/skbuff.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'include/linux/skbuff.h') diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 50db9b04a552..2b7317ff297f 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -438,6 +438,11 @@ struct sk_buff { #endif int skb_iif; + + __u32 rxhash; + + __u16 vlan_tci; + #ifdef CONFIG_NET_SCHED __u16 tc_index; /* traffic control index */ #ifdef CONFIG_NET_CLS_ACT @@ -445,8 +450,6 @@ struct sk_buff { #endif #endif - __u32 rxhash; - __u16 queue_mapping; kmemcheck_bitfield_begin(flags2); #ifdef CONFIG_IPV6_NDISC_NODETYPE @@ -470,8 +473,6 @@ struct sk_buff { __u32 dropcount; }; - __u16 vlan_tci; - sk_buff_data_t transport_header; sk_buff_data_t network_header; sk_buff_data_t mac_header; -- cgit v1.2.3-71-gd317 From 3f518bf745cbd6007d8069100fb9cb09e960c872 Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Tue, 21 Feb 2012 07:30:58 +0000 Subject: datagram: Add offset argument to __skb_recv_datagram This one is only considered for MSG_PEEK flag and the value pointed by it specifies where to start peeking bytes from. If the offset happens to point into the middle of the returned skb, the offset within this skb is put back to this very argument. Signed-off-by: Pavel Emelyanov Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- include/linux/skbuff.h | 2 +- net/core/datagram.c | 21 +++++++++++++-------- net/ipv4/udp.c | 4 ++-- net/ipv6/udp.c | 4 ++-- 4 files changed, 18 insertions(+), 13 deletions(-) (limited to 'include/linux/skbuff.h') diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 2b7317ff297f..f3cf43de3c2a 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -2046,7 +2046,7 @@ static inline void skb_frag_add_head(struct sk_buff *skb, struct sk_buff *frag) for (iter = skb_shinfo(skb)->frag_list; iter; iter = iter->next) extern struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned flags, - int *peeked, int *err); + int *peeked, int *off, int *err); extern struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, int noblock, int *err); extern unsigned int datagram_poll(struct file *file, struct socket *sock, diff --git a/net/core/datagram.c b/net/core/datagram.c index 6f54d0a17f8e..d3cf12f62c8f 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c @@ -132,6 +132,8 @@ out_noerr: * __skb_recv_datagram - Receive a datagram skbuff * @sk: socket * @flags: MSG_ flags + * @off: an offset in bytes to peek skb from. Returns an offset + * within an skb where data actually starts * @peeked: returns non-zero if this packet has been seen before * @err: error code returned * @@ -158,7 +160,7 @@ out_noerr: * the standard around please. */ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned flags, - int *peeked, int *err) + int *peeked, int *off, int *err) { struct sk_buff *skb; long timeo; @@ -183,19 +185,22 @@ struct sk_buff *__skb_recv_datagram(struct sock *sk, unsigned flags, struct sk_buff_head *queue = &sk->sk_receive_queue; spin_lock_irqsave(&queue->lock, cpu_flags); - skb = skb_peek(queue); - if (skb) { + skb_queue_walk(queue, skb) { *peeked = skb->peeked; if (flags & MSG_PEEK) { + if (*off >= skb->len) { + *off -= skb->len; + continue; + } skb->peeked = 1; atomic_inc(&skb->users); } else __skb_unlink(skb, queue); - } - spin_unlock_irqrestore(&queue->lock, cpu_flags); - if (skb) + spin_unlock_irqrestore(&queue->lock, cpu_flags); return skb; + } + spin_unlock_irqrestore(&queue->lock, cpu_flags); /* User doesn't want to wait */ error = -EAGAIN; @@ -215,10 +220,10 @@ EXPORT_SYMBOL(__skb_recv_datagram); struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, int noblock, int *err) { - int peeked; + int peeked, off = 0; return __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0), - &peeked, err); + &peeked, &off, err); } EXPORT_SYMBOL(skb_recv_datagram); diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index cd99f1a0f59f..7c41ab84e72e 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1167,7 +1167,7 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name; struct sk_buff *skb; unsigned int ulen, copied; - int peeked; + int peeked, off = 0; int err; int is_udplite = IS_UDPLITE(sk); bool slow; @@ -1183,7 +1183,7 @@ int udp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, try_again: skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0), - &peeked, &err); + &peeked, &off, &err); if (!skb) goto out; diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 8aebf8f90436..37b0699e95e5 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -342,7 +342,7 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, struct inet_sock *inet = inet_sk(sk); struct sk_buff *skb; unsigned int ulen, copied; - int peeked; + int peeked, off = 0; int err; int is_udplite = IS_UDPLITE(sk); int is_udp4; @@ -359,7 +359,7 @@ int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, try_again: skb = __skb_recv_datagram(sk, flags | (noblock ? MSG_DONTWAIT : 0), - &peeked, &err); + &peeked, &off, &err); if (!skb) goto out; -- cgit v1.2.3-71-gd317 From da5ef6e51b327b41180b5d1000c06e8d3595a936 Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Tue, 21 Feb 2012 07:31:18 +0000 Subject: skb: Add skb_peek_next helper Signed-off-by: Pavel Emelyanov Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- include/linux/skbuff.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'include/linux/skbuff.h') diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index f3cf43de3c2a..c11a44ea1bf4 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -876,6 +876,24 @@ static inline struct sk_buff *skb_peek(const struct sk_buff_head *list_) return list; } +/** + * skb_peek_next - peek skb following the given one from a queue + * @skb: skb to start from + * @list_: list to peek at + * + * Returns %NULL when the end of the list is met or a pointer to the + * next element. The reference count is not incremented and the + * reference is therefore volatile. Use with caution. + */ +static inline struct sk_buff *skb_peek_next(struct sk_buff *skb, + const struct sk_buff_head *list_) +{ + struct sk_buff *next = skb->next; + if (next == (struct sk_buff *)list_) + next = NULL; + return next; +} + /** * skb_peek_tail - peek at the tail of an &sk_buff_head * @list_: list to peek at -- cgit v1.2.3-71-gd317 From 3bdc0eba0b8b47797f4a76e377dd8360f317450f Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Sat, 11 Feb 2012 15:39:30 +0000 Subject: 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 Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher --- arch/alpha/include/asm/socket.h | 3 +++ arch/arm/include/asm/socket.h | 3 +++ arch/avr32/include/asm/socket.h | 3 +++ arch/cris/include/asm/socket.h | 3 +++ arch/frv/include/asm/socket.h | 3 +++ arch/h8300/include/asm/socket.h | 3 +++ arch/ia64/include/asm/socket.h | 3 +++ arch/m32r/include/asm/socket.h | 3 +++ arch/m68k/include/asm/socket.h | 3 +++ arch/mips/include/asm/socket.h | 3 +++ arch/mn10300/include/asm/socket.h | 3 +++ arch/parisc/include/asm/socket.h | 4 ++++ arch/powerpc/include/asm/socket.h | 3 +++ arch/s390/include/asm/socket.h | 3 +++ arch/sparc/include/asm/socket.h | 4 ++++ arch/xtensa/include/asm/socket.h | 3 +++ include/asm-generic/socket.h | 4 ++++ include/linux/if.h | 2 ++ include/linux/netdevice.h | 8 +++++++- include/linux/skbuff.h | 4 +++- include/net/sock.h | 4 ++++ net/core/skbuff.c | 1 + net/core/sock.c | 5 +++++ net/packet/af_packet.c | 32 ++++++++++++++++++++++++++++---- 24 files changed, 104 insertions(+), 6 deletions(-) (limited to 'include/linux/skbuff.h') 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 @@ #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 d958c74e5260..6433cadb6ed4 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 30078f98b3ab..a473f8c6a9aa 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 048aba64600c..ae52825021af 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 7a361810f3cc..a5b1d7dbb205 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 e7bbfcee5b99..ec4554e7b04b 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 ced62de9d5a9..41fc28a4a18a 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 696cb4c7ca4e..a15f40b52783 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 e8b41a6775f9..d1be684edf97 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 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. */ #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 013fcc51698f..820463a484b8 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 f717c9bec16f..1b52c2c31a7a 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 fe1c0b478fd7..3d5179bb122f 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 581702fa1b0c..c91b720965c0 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 68e2e2746f6f..bea1568ae4af 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 74818b161362..e36c68184920 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 d9aaac0c36d4..b1bea03274d5 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 06b6ef60c821..f995c663c493 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 0eac07c95255..f1b7d037c2c5 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 c11a44ea1bf4..06a4c0fd7bef 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 9c0553b9e451..ba761e7de252 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 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) 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 19942d4bb6e6..55011cb691ad 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 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, 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 */ -- cgit v1.2.3-71-gd317 From bdcc0924c8c6e6362bb93b6120631f257aac6f87 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 7 Mar 2012 20:53:36 -0500 Subject: net: Use bool in skbuff.h helper functions. In particular do this for skb_is_nonlinear(), skb_is_gso(), and skb_is_gso_v6(). Signed-off-by: David S. Miller --- include/linux/skbuff.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'include/linux/skbuff.h') diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 79ef8209bbb7..8dc8257eab8b 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -1173,7 +1173,7 @@ static inline struct sk_buff *__skb_dequeue_tail(struct sk_buff_head *list) } -static inline int skb_is_nonlinear(const struct sk_buff *skb) +static inline bool skb_is_nonlinear(const struct sk_buff *skb) { return skb->data_len; } @@ -2469,12 +2469,12 @@ static inline struct sec_path *skb_sec_path(struct sk_buff *skb) } #endif -static inline int skb_is_gso(const struct sk_buff *skb) +static inline bool skb_is_gso(const struct sk_buff *skb) { return skb_shinfo(skb)->gso_size; } -static inline int skb_is_gso_v6(const struct sk_buff *skb) +static inline bool skb_is_gso_v6(const struct sk_buff *skb) { return skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6; } -- cgit v1.2.3-71-gd317 From 3af79302b400e05b45e377993a8870869500466b Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Mon, 19 Mar 2012 11:12:41 +0000 Subject: net: update the usage of CHECKSUM_UNNECESSARY As suggested by Ben, this adds the clarification on the usage of CHECKSUM_UNNECESSARY on the outgoing patch. Also add the usage description of NETIF_F_FCOE_CRC and CHECKSUM_UNNECESSARY for the kernel FCoE protocol driver. This is a follow-up to the following: http://patchwork.ozlabs.org/patch/147315/ Signed-off-by: Yi Zou Cc: Ben Hutchings Cc: Jeff Kirsher Cc: www.Open-FCoE.org Signed-off-by: David S. Miller --- include/linux/skbuff.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'include/linux/skbuff.h') diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 8dc8257eab8b..a2b9953b582d 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -94,6 +94,13 @@ * about CHECKSUM_UNNECESSARY. 8) * NETIF_F_IPV6_CSUM about as dumb as the last one but does IPv6 instead. * + * UNNECESSARY: device will do per protocol specific csum. Protocol drivers + * that do not want net to perform the checksum calculation should use + * this flag in their outgoing skbs. + * NETIF_F_FCOE_CRC this indicates the device can do FCoE FC CRC + * offload. Correspondingly, the FCoE protocol driver + * stack should use CHECKSUM_UNNECESSARY. + * * Any questions? No questions, good. --ANK */ -- cgit v1.2.3-71-gd317