Mindspeed kernel: add new UDP socket option to report RX queue level
(this is the exact same change already applied to the bruno kernel via
https://gfiber-internal-review.googlesource.com/54693)
This adds a new socket option “SO_RXQ_ALLOC” that enables providing
the RX queue buffer allocation as ancillary data from the recvmsg()
system call. The value reported is a byte number and together with the
RX queue size (obtained via getsockopt(SO_RCVBUF) can be used to
calculate a percentage value.
Change-Id: I4fbadc6b9ef7549cb526cf78b7e432d8054370f5
diff --git a/arch/arm/include/asm/socket.h b/arch/arm/include/asm/socket.h
index 90ffd04..23061f7 100644
--- a/arch/arm/include/asm/socket.h
+++ b/arch/arm/include/asm/socket.h
@@ -61,5 +61,6 @@
#define SO_DOMAIN 39
#define SO_RXQ_OVFL 40
+#define SO_RXQ_ALLOC 41
#endif /* _ASM_SOCKET_H */
diff --git a/include/asm-generic/socket.h b/include/asm-generic/socket.h
index 9a6115e..56d2b13 100644
--- a/include/asm-generic/socket.h
+++ b/include/asm-generic/socket.h
@@ -64,4 +64,5 @@
#define SO_DOMAIN 39
#define SO_RXQ_OVFL 40
+#define SO_RXQ_ALLOC 41
#endif /* __ASM_GENERIC_SOCKET_H */
diff --git a/include/net/sock.h b/include/net/sock.h
index 32e3937..80ed0da 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -562,6 +562,7 @@
SOCK_TIMESTAMPING_SYS_HARDWARE, /* %SOF_TIMESTAMPING_SYS_HARDWARE */
SOCK_FASYNC, /* fasync() active */
SOCK_RXQ_OVFL,
+ SOCK_RXQ_ALLOC,
SOCK_ZEROCOPY, /* buffers from userspace */
};
@@ -1764,6 +1765,14 @@
sk->sk_stamp = skb->tstamp;
}
+extern void __sock_recv_alloc(struct msghdr *msg, struct sock *sk);
+
+static inline void sock_recv_alloc(struct msghdr *msg, struct sock *sk)
+{
+ if (sock_flag(sk, SOCK_RXQ_ALLOC))
+ __sock_recv_alloc(msg, sk);
+}
+
/**
* sock_tx_timestamp - checks whether the outgoing packet is to be time stamped
* @sk: socket sending this packet
diff --git a/net/core/sock.c b/net/core/sock.c
index 8d095b9..2d19e4e 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -736,6 +736,12 @@
case SO_RXQ_OVFL:
sock_valbool_flag(sk, SOCK_RXQ_OVFL, valbool);
break;
+ case SO_RXQ_ALLOC:
+ if (valbool)
+ sock_set_flag(sk, SOCK_RXQ_ALLOC);
+ else
+ sock_reset_flag(sk, SOCK_RXQ_ALLOC);
+ break;
default:
ret = -ENOPROTOOPT;
break;
@@ -957,6 +963,10 @@
v.val = !!sock_flag(sk, SOCK_RXQ_OVFL);
break;
+ case SO_RXQ_ALLOC:
+ v.val = !!sock_flag(sk, SOCK_RXQ_ALLOC);
+ break;
+
default:
return -ENOPROTOOPT;
}
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 5a65eea..0ec2542 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1223,6 +1223,7 @@
UDP_MIB_INDATAGRAMS, is_udplite);
sock_recv_ts_and_drops(msg, sk, skb);
+ sock_recv_alloc(msg, sk);
/* Copy the address. */
if (sin) {
diff --git a/net/socket.c b/net/socket.c
index 273cbce..9ba4f71 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -690,6 +690,18 @@
}
EXPORT_SYMBOL_GPL(__sock_recv_ts_and_drops);
+void __sock_recv_alloc(struct msghdr *msg, struct sock *sk)
+{
+ __u32 rmem_alloc;
+
+ if (sock_flag(sk, SOCK_RXQ_ALLOC)) {
+ rmem_alloc = atomic_read(&sk->sk_rmem_alloc);
+ put_cmsg(msg, SOL_SOCKET, SO_RXQ_ALLOC,
+ sizeof(rmem_alloc), &rmem_alloc);
+ }
+}
+EXPORT_SYMBOL_GPL(__sock_recv_alloc);
+
static inline int __sock_recvmsg_nosec(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, size_t size, int flags)
{