aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-11-09 04:15:42 -0500
committerJohn W. Linville <linville@tuxdriver.com>2011-11-09 16:01:02 -0500
commit6e3e939f3b1bf8534b32ad09ff199d88800835a0 (patch)
tree78ec0638efbade2fdb0bebb7bad71410ded2e6c6
parent4fdbff0770bea059621bc4906fb7c7f5879f3ae1 (diff)
net: add wireless TX status socket option
The 802.1X EAPOL handshake hostapd does requires knowing whether the frame was ack'ed by the peer. Currently, we fudge this pretty badly by not even transmitting the frame as a normal data frame but injecting it with radiotap and getting the status out of radiotap monitor as well. This is rather complex, confuses users (mon.wlan0 presence) and doesn't work with all hardware. To get rid of that hack, introduce a real wifi TX status option for data frame transmissions. This works similar to the existing TX timestamping in that it reflects the SKB back to the socket's error queue with a SCM_WIFI_STATUS cmsg that has an int indicating ACK status (0/1). Since it is possible that at some point we will want to have TX timestamping and wifi status in a single errqueue SKB (there's little point in not doing that), redefine SO_EE_ORIGIN_TIMESTAMPING to SO_EE_ORIGIN_TXSTATUS which can collect more than just the timestamp; keep the old constant as an alias of course. Currently the internal APIs don't make that possible, but it wouldn't be hard to split them up in a way that makes it possible. Thanks to Neil Horman for helping me figure out the functions that add the control messages. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.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.h3
-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.h3
-rw-r--r--arch/xtensa/include/asm/socket.h3
-rw-r--r--include/asm-generic/socket.h3
-rw-r--r--include/linux/errqueue.h3
-rw-r--r--include/linux/skbuff.h19
-rw-r--r--include/net/sock.h6
-rw-r--r--net/core/skbuff.c20
-rw-r--r--net/core/sock.c9
-rw-r--r--net/socket.c18
23 files changed, 123 insertions, 3 deletions
diff --git a/arch/alpha/include/asm/socket.h b/arch/alpha/include/asm/socket.h
index 06edfefc3373..082355f159e6 100644
--- a/arch/alpha/include/asm/socket.h
+++ b/arch/alpha/include/asm/socket.h
@@ -69,6 +69,9 @@
69 69
70#define SO_RXQ_OVFL 40 70#define SO_RXQ_OVFL 40
71 71
72#define SO_WIFI_STATUS 41
73#define SCM_WIFI_STATUS SO_WIFI_STATUS
74
72/* O_NONBLOCK clashes with the bits used for socket types. Therefore we 75/* O_NONBLOCK clashes with the bits used for socket types. Therefore we
73 * have to define SOCK_NONBLOCK to a different value here. 76 * have to define SOCK_NONBLOCK to a different value here.
74 */ 77 */
diff --git a/arch/arm/include/asm/socket.h b/arch/arm/include/asm/socket.h
index 90ffd04b8e74..dec6f9afb3cf 100644
--- a/arch/arm/include/asm/socket.h
+++ b/arch/arm/include/asm/socket.h
@@ -62,4 +62,7 @@
62 62
63#define SO_RXQ_OVFL 40 63#define SO_RXQ_OVFL 40
64 64
65#define SO_WIFI_STATUS 41
66#define SCM_WIFI_STATUS SO_WIFI_STATUS
67
65#endif /* _ASM_SOCKET_H */ 68#endif /* _ASM_SOCKET_H */
diff --git a/arch/avr32/include/asm/socket.h b/arch/avr32/include/asm/socket.h
index c8d1fae49476..247b88c760be 100644
--- a/arch/avr32/include/asm/socket.h
+++ b/arch/avr32/include/asm/socket.h
@@ -62,4 +62,7 @@
62 62
63#define SO_RXQ_OVFL 40 63#define SO_RXQ_OVFL 40
64 64
65#define SO_WIFI_STATUS 41
66#define SCM_WIFI_STATUS SO_WIFI_STATUS
67
65#endif /* __ASM_AVR32_SOCKET_H */ 68#endif /* __ASM_AVR32_SOCKET_H */
diff --git a/arch/cris/include/asm/socket.h b/arch/cris/include/asm/socket.h
index 1a4a61909ca8..e269264df7c4 100644
--- a/arch/cris/include/asm/socket.h
+++ b/arch/cris/include/asm/socket.h
@@ -64,6 +64,9 @@
64 64
65#define SO_RXQ_OVFL 40 65#define SO_RXQ_OVFL 40
66 66
67#define SO_WIFI_STATUS 41
68#define SCM_WIFI_STATUS SO_WIFI_STATUS
69
67#endif /* _ASM_SOCKET_H */ 70#endif /* _ASM_SOCKET_H */
68 71
69 72
diff --git a/arch/frv/include/asm/socket.h b/arch/frv/include/asm/socket.h
index a6b26880c1ec..ce80fdadcce5 100644
--- a/arch/frv/include/asm/socket.h
+++ b/arch/frv/include/asm/socket.h
@@ -62,5 +62,8 @@
62 62
63#define SO_RXQ_OVFL 40 63#define SO_RXQ_OVFL 40
64 64
65#define SO_WIFI_STATUS 41
66#define SCM_WIFI_STATUS SO_WIFI_STATUS
67
65#endif /* _ASM_SOCKET_H */ 68#endif /* _ASM_SOCKET_H */
66 69
diff --git a/arch/h8300/include/asm/socket.h b/arch/h8300/include/asm/socket.h
index 04c0f4596eb5..cf1daab6f27e 100644
--- a/arch/h8300/include/asm/socket.h
+++ b/arch/h8300/include/asm/socket.h
@@ -62,4 +62,7 @@
62 62
63#define SO_RXQ_OVFL 40 63#define SO_RXQ_OVFL 40
64 64
65#define SO_WIFI_STATUS 41
66#define SCM_WIFI_STATUS SO_WIFI_STATUS
67
65#endif /* _ASM_SOCKET_H */ 68#endif /* _ASM_SOCKET_H */
diff --git a/arch/ia64/include/asm/socket.h b/arch/ia64/include/asm/socket.h
index 51427eaa51ba..4b03664e3fb5 100644
--- a/arch/ia64/include/asm/socket.h
+++ b/arch/ia64/include/asm/socket.h
@@ -71,4 +71,7 @@
71 71
72#define SO_RXQ_OVFL 40 72#define SO_RXQ_OVFL 40
73 73
74#define SO_WIFI_STATUS 41
75#define SCM_WIFI_STATUS SO_WIFI_STATUS
76
74#endif /* _ASM_IA64_SOCKET_H */ 77#endif /* _ASM_IA64_SOCKET_H */
diff --git a/arch/m32r/include/asm/socket.h b/arch/m32r/include/asm/socket.h
index 469787c30098..e8b8c5bb053c 100644
--- a/arch/m32r/include/asm/socket.h
+++ b/arch/m32r/include/asm/socket.h
@@ -62,4 +62,7 @@
62 62
63#define SO_RXQ_OVFL 40 63#define SO_RXQ_OVFL 40
64 64
65#define SO_WIFI_STATUS 41
66#define SCM_WIFI_STATUS SO_WIFI_STATUS
67
65#endif /* _ASM_M32R_SOCKET_H */ 68#endif /* _ASM_M32R_SOCKET_H */
diff --git a/arch/m68k/include/asm/socket.h b/arch/m68k/include/asm/socket.h
index 9bf49c87d954..d4708ce466e0 100644
--- a/arch/m68k/include/asm/socket.h
+++ b/arch/m68k/include/asm/socket.h
@@ -62,4 +62,7 @@
62 62
63#define SO_RXQ_OVFL 40 63#define SO_RXQ_OVFL 40
64 64
65#define SO_WIFI_STATUS 41
66#define SCM_WIFI_STATUS SO_WIFI_STATUS
67
65#endif /* _ASM_SOCKET_H */ 68#endif /* _ASM_SOCKET_H */
diff --git a/arch/mips/include/asm/socket.h b/arch/mips/include/asm/socket.h
index 9de5190f2487..ad5c0a7a02a7 100644
--- a/arch/mips/include/asm/socket.h
+++ b/arch/mips/include/asm/socket.h
@@ -82,6 +82,9 @@ To add: #define SO_REUSEPORT 0x0200 /* Allow local address and port reuse. */
82 82
83#define SO_RXQ_OVFL 40 83#define SO_RXQ_OVFL 40
84 84
85#define SO_WIFI_STATUS 41
86#define SCM_WIFI_STATUS SO_WIFI_STATUS
87
85#ifdef __KERNEL__ 88#ifdef __KERNEL__
86 89
87/** sock_type - Socket types 90/** sock_type - Socket types
diff --git a/arch/mn10300/include/asm/socket.h b/arch/mn10300/include/asm/socket.h
index 4e60c4281288..876356d78522 100644
--- a/arch/mn10300/include/asm/socket.h
+++ b/arch/mn10300/include/asm/socket.h
@@ -62,4 +62,7 @@
62 62
63#define SO_RXQ_OVFL 40 63#define SO_RXQ_OVFL 40
64 64
65#define SO_WIFI_STATUS 41
66#define SCM_WIFI_STATUS SO_WIFI_STATUS
67
65#endif /* _ASM_SOCKET_H */ 68#endif /* _ASM_SOCKET_H */
diff --git a/arch/parisc/include/asm/socket.h b/arch/parisc/include/asm/socket.h
index 225b7d6a1a0a..d28c51b61067 100644
--- a/arch/parisc/include/asm/socket.h
+++ b/arch/parisc/include/asm/socket.h
@@ -61,6 +61,9 @@
61 61
62#define SO_RXQ_OVFL 0x4021 62#define SO_RXQ_OVFL 0x4021
63 63
64#define SO_WIFI_STATUS 0x4022
65#define SCM_WIFI_STATUS SO_WIFI_STATUS
66
64/* O_NONBLOCK clashes with the bits used for socket types. Therefore we 67/* O_NONBLOCK clashes with the bits used for socket types. Therefore we
65 * have to define SOCK_NONBLOCK to a different value here. 68 * have to define SOCK_NONBLOCK to a different value here.
66 */ 69 */
diff --git a/arch/powerpc/include/asm/socket.h b/arch/powerpc/include/asm/socket.h
index 866f7606da68..2fc2af8fbf59 100644
--- a/arch/powerpc/include/asm/socket.h
+++ b/arch/powerpc/include/asm/socket.h
@@ -69,4 +69,7 @@
69 69
70#define SO_RXQ_OVFL 40 70#define SO_RXQ_OVFL 40
71 71
72#define SO_WIFI_STATUS 41
73#define SCM_WIFI_STATUS SO_WIFI_STATUS
74
72#endif /* _ASM_POWERPC_SOCKET_H */ 75#endif /* _ASM_POWERPC_SOCKET_H */
diff --git a/arch/s390/include/asm/socket.h b/arch/s390/include/asm/socket.h
index fdff1e995c73..67b5c1b14b51 100644
--- a/arch/s390/include/asm/socket.h
+++ b/arch/s390/include/asm/socket.h
@@ -70,4 +70,7 @@
70 70
71#define SO_RXQ_OVFL 40 71#define SO_RXQ_OVFL 40
72 72
73#define SO_WIFI_STATUS 41
74#define SCM_WIFI_STATUS SO_WIFI_STATUS
75
73#endif /* _ASM_SOCKET_H */ 76#endif /* _ASM_SOCKET_H */
diff --git a/arch/sparc/include/asm/socket.h b/arch/sparc/include/asm/socket.h
index 9d3fefcff2f5..8af1b64168b3 100644
--- a/arch/sparc/include/asm/socket.h
+++ b/arch/sparc/include/asm/socket.h
@@ -58,6 +58,9 @@
58 58
59#define SO_RXQ_OVFL 0x0024 59#define SO_RXQ_OVFL 0x0024
60 60
61#define SO_WIFI_STATUS 0x0025
62#define SCM_WIFI_STATUS SO_WIFI_STATUS
63
61/* Security levels - as per NRL IPv6 - don't actually do anything */ 64/* Security levels - as per NRL IPv6 - don't actually do anything */
62#define SO_SECURITY_AUTHENTICATION 0x5001 65#define SO_SECURITY_AUTHENTICATION 0x5001
63#define SO_SECURITY_ENCRYPTION_TRANSPORT 0x5002 66#define SO_SECURITY_ENCRYPTION_TRANSPORT 0x5002
diff --git a/arch/xtensa/include/asm/socket.h b/arch/xtensa/include/asm/socket.h
index cbdf2ffaacff..bb06968be227 100644
--- a/arch/xtensa/include/asm/socket.h
+++ b/arch/xtensa/include/asm/socket.h
@@ -73,4 +73,7 @@
73 73
74#define SO_RXQ_OVFL 40 74#define SO_RXQ_OVFL 40
75 75
76#define SO_WIFI_STATUS 41
77#define SCM_WIFI_STATUS SO_WIFI_STATUS
78
76#endif /* _XTENSA_SOCKET_H */ 79#endif /* _XTENSA_SOCKET_H */
diff --git a/include/asm-generic/socket.h b/include/asm-generic/socket.h
index 9a6115e7cf63..49c1704173e7 100644
--- a/include/asm-generic/socket.h
+++ b/include/asm-generic/socket.h
@@ -64,4 +64,7 @@
64#define SO_DOMAIN 39 64#define SO_DOMAIN 39
65 65
66#define SO_RXQ_OVFL 40 66#define SO_RXQ_OVFL 40
67
68#define SO_WIFI_STATUS 41
69#define SCM_WIFI_STATUS SO_WIFI_STATUS
67#endif /* __ASM_GENERIC_SOCKET_H */ 70#endif /* __ASM_GENERIC_SOCKET_H */
diff --git a/include/linux/errqueue.h b/include/linux/errqueue.h
index 034072cea853..c9f522bd17e4 100644
--- a/include/linux/errqueue.h
+++ b/include/linux/errqueue.h
@@ -17,7 +17,8 @@ struct sock_extended_err {
17#define SO_EE_ORIGIN_LOCAL 1 17#define SO_EE_ORIGIN_LOCAL 1
18#define SO_EE_ORIGIN_ICMP 2 18#define SO_EE_ORIGIN_ICMP 2
19#define SO_EE_ORIGIN_ICMP6 3 19#define SO_EE_ORIGIN_ICMP6 3
20#define SO_EE_ORIGIN_TIMESTAMPING 4 20#define SO_EE_ORIGIN_TXSTATUS 4
21#define SO_EE_ORIGIN_TIMESTAMPING SO_EE_ORIGIN_TXSTATUS
21 22
22#define SO_EE_OFFENDER(ee) ((struct sockaddr*)((ee)+1)) 23#define SO_EE_OFFENDER(ee) ((struct sockaddr*)((ee)+1))
23 24
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 6a6b352326d7..ff7e1306a2d2 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -218,6 +218,9 @@ enum {
218 218
219 /* device driver supports TX zero-copy buffers */ 219 /* device driver supports TX zero-copy buffers */
220 SKBTX_DEV_ZEROCOPY = 1 << 4, 220 SKBTX_DEV_ZEROCOPY = 1 << 4,
221
222 /* generate wifi status information (where possible) */
223 SKBTX_WIFI_STATUS = 1 << 5,
221}; 224};
222 225
223/* 226/*
@@ -352,6 +355,8 @@ typedef unsigned char *sk_buff_data_t;
352 * @ooo_okay: allow the mapping of a socket to a queue to be changed 355 * @ooo_okay: allow the mapping of a socket to a queue to be changed
353 * @l4_rxhash: indicate rxhash is a canonical 4-tuple hash over transport 356 * @l4_rxhash: indicate rxhash is a canonical 4-tuple hash over transport
354 * ports. 357 * ports.
358 * @wifi_acked_valid: wifi_acked was set
359 * @wifi_acked: whether frame was acked on wifi or not
355 * @dma_cookie: a cookie to one of several possible DMA operations 360 * @dma_cookie: a cookie to one of several possible DMA operations
356 * done by skb DMA functions 361 * done by skb DMA functions
357 * @secmark: security marking 362 * @secmark: security marking
@@ -445,10 +450,11 @@ struct sk_buff {
445#endif 450#endif
446 __u8 ooo_okay:1; 451 __u8 ooo_okay:1;
447 __u8 l4_rxhash:1; 452 __u8 l4_rxhash:1;
453 __u8 wifi_acked_valid:1;
454 __u8 wifi_acked:1;
455 /* 10/12 bit hole (depending on ndisc_nodetype presence) */
448 kmemcheck_bitfield_end(flags2); 456 kmemcheck_bitfield_end(flags2);
449 457
450 /* 0/13 bit hole */
451
452#ifdef CONFIG_NET_DMA 458#ifdef CONFIG_NET_DMA
453 dma_cookie_t dma_cookie; 459 dma_cookie_t dma_cookie;
454#endif 460#endif
@@ -2263,6 +2269,15 @@ static inline void skb_tx_timestamp(struct sk_buff *skb)
2263 sw_tx_timestamp(skb); 2269 sw_tx_timestamp(skb);
2264} 2270}
2265 2271
2272/**
2273 * skb_complete_wifi_ack - deliver skb with wifi status
2274 *
2275 * @skb: the original outgoing packet
2276 * @acked: ack status
2277 *
2278 */
2279void skb_complete_wifi_ack(struct sk_buff *skb, bool acked);
2280
2266extern __sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len); 2281extern __sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len);
2267extern __sum16 __skb_checksum_complete(struct sk_buff *skb); 2282extern __sum16 __skb_checksum_complete(struct sk_buff *skb);
2268 2283
diff --git a/include/net/sock.h b/include/net/sock.h
index 5ac682f73d63..fa6f5381c5d6 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -564,6 +564,7 @@ enum sock_flags {
564 SOCK_FASYNC, /* fasync() active */ 564 SOCK_FASYNC, /* fasync() active */
565 SOCK_RXQ_OVFL, 565 SOCK_RXQ_OVFL,
566 SOCK_ZEROCOPY, /* buffers from userspace */ 566 SOCK_ZEROCOPY, /* buffers from userspace */
567 SOCK_WIFI_STATUS, /* push wifi status to userspace */
567}; 568};
568 569
569static inline void sock_copy_flags(struct sock *nsk, struct sock *osk) 570static inline void sock_copy_flags(struct sock *nsk, struct sock *osk)
@@ -1714,6 +1715,8 @@ static inline int sock_intr_errno(long timeo)
1714 1715
1715extern void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, 1716extern void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
1716 struct sk_buff *skb); 1717 struct sk_buff *skb);
1718extern void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk,
1719 struct sk_buff *skb);
1717 1720
1718static __inline__ void 1721static __inline__ void
1719sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb) 1722sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb)
@@ -1741,6 +1744,9 @@ sock_recv_timestamp(struct msghdr *msg, struct sock *sk, struct sk_buff *skb)
1741 __sock_recv_timestamp(msg, sk, skb); 1744 __sock_recv_timestamp(msg, sk, skb);
1742 else 1745 else
1743 sk->sk_stamp = kt; 1746 sk->sk_stamp = kt;
1747
1748 if (sock_flag(sk, SOCK_WIFI_STATUS) && skb->wifi_acked_valid)
1749 __sock_recv_wifi_status(msg, sk, skb);
1744} 1750}
1745 1751
1746extern void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk, 1752extern void __sock_recv_ts_and_drops(struct msghdr *msg, struct sock *sk,
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index ca4db40e75b8..2f6babd5a570 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -3168,6 +3168,26 @@ void skb_tstamp_tx(struct sk_buff *orig_skb,
3168} 3168}
3169EXPORT_SYMBOL_GPL(skb_tstamp_tx); 3169EXPORT_SYMBOL_GPL(skb_tstamp_tx);
3170 3170
3171void skb_complete_wifi_ack(struct sk_buff *skb, bool acked)
3172{
3173 struct sock *sk = skb->sk;
3174 struct sock_exterr_skb *serr;
3175 int err;
3176
3177 skb->wifi_acked_valid = 1;
3178 skb->wifi_acked = acked;
3179
3180 serr = SKB_EXT_ERR(skb);
3181 memset(serr, 0, sizeof(*serr));
3182 serr->ee.ee_errno = ENOMSG;
3183 serr->ee.ee_origin = SO_EE_ORIGIN_TXSTATUS;
3184
3185 err = sock_queue_err_skb(sk, skb);
3186 if (err)
3187 kfree_skb(skb);
3188}
3189EXPORT_SYMBOL_GPL(skb_complete_wifi_ack);
3190
3171 3191
3172/** 3192/**
3173 * skb_partial_csum_set - set up and verify partial csum values for packet 3193 * skb_partial_csum_set - set up and verify partial csum values for packet
diff --git a/net/core/sock.c b/net/core/sock.c
index 4ed7b1d12f5e..cbdf51c0d5ac 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -740,6 +740,11 @@ set_rcvbuf:
740 case SO_RXQ_OVFL: 740 case SO_RXQ_OVFL:
741 sock_valbool_flag(sk, SOCK_RXQ_OVFL, valbool); 741 sock_valbool_flag(sk, SOCK_RXQ_OVFL, valbool);
742 break; 742 break;
743
744 case SO_WIFI_STATUS:
745 sock_valbool_flag(sk, SOCK_WIFI_STATUS, valbool);
746 break;
747
743 default: 748 default:
744 ret = -ENOPROTOOPT; 749 ret = -ENOPROTOOPT;
745 break; 750 break;
@@ -961,6 +966,10 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
961 v.val = !!sock_flag(sk, SOCK_RXQ_OVFL); 966 v.val = !!sock_flag(sk, SOCK_RXQ_OVFL);
962 break; 967 break;
963 968
969 case SO_WIFI_STATUS:
970 v.val = !!sock_flag(sk, SOCK_WIFI_STATUS);
971 break;
972
964 default: 973 default:
965 return -ENOPROTOOPT; 974 return -ENOPROTOOPT;
966 } 975 }
diff --git a/net/socket.c b/net/socket.c
index 2877647f347b..425ef4270460 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -538,6 +538,8 @@ int sock_tx_timestamp(struct sock *sk, __u8 *tx_flags)
538 *tx_flags |= SKBTX_HW_TSTAMP; 538 *tx_flags |= SKBTX_HW_TSTAMP;
539 if (sock_flag(sk, SOCK_TIMESTAMPING_TX_SOFTWARE)) 539 if (sock_flag(sk, SOCK_TIMESTAMPING_TX_SOFTWARE))
540 *tx_flags |= SKBTX_SW_TSTAMP; 540 *tx_flags |= SKBTX_SW_TSTAMP;
541 if (sock_flag(sk, SOCK_WIFI_STATUS))
542 *tx_flags |= SKBTX_WIFI_STATUS;
541 return 0; 543 return 0;
542} 544}
543EXPORT_SYMBOL(sock_tx_timestamp); 545EXPORT_SYMBOL(sock_tx_timestamp);
@@ -674,6 +676,22 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
674} 676}
675EXPORT_SYMBOL_GPL(__sock_recv_timestamp); 677EXPORT_SYMBOL_GPL(__sock_recv_timestamp);
676 678
679void __sock_recv_wifi_status(struct msghdr *msg, struct sock *sk,
680 struct sk_buff *skb)
681{
682 int ack;
683
684 if (!sock_flag(sk, SOCK_WIFI_STATUS))
685 return;
686 if (!skb->wifi_acked_valid)
687 return;
688
689 ack = skb->wifi_acked;
690
691 put_cmsg(msg, SOL_SOCKET, SCM_WIFI_STATUS, sizeof(ack), &ack);
692}
693EXPORT_SYMBOL_GPL(__sock_recv_wifi_status);
694
677static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk, 695static inline void sock_recv_drops(struct msghdr *msg, struct sock *sk,
678 struct sk_buff *skb) 696 struct sk_buff *skb)
679{ 697{