summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/raw.c27
-rw-r--r--net/ipv4/tcp.c36
-rw-r--r--net/ipv4/tcp_ipv4.c1
-rw-r--r--net/ipv4/udp.c18
-rw-r--r--net/ipv6/raw.c1
-rw-r--r--net/ipv6/tcp_ipv6.c1
-rw-r--r--net/ipv6/udp.c1
7 files changed, 85 insertions, 0 deletions
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index bb446e60cf58..d54a044f98ab 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -75,6 +75,7 @@
#include <linux/netfilter_ipv4.h>
#include <linux/compat.h>
#include <linux/uio.h>
+#include <linux/io_uring.h>
struct raw_frag_vec {
struct msghdr *msg;
@@ -878,6 +879,31 @@ static int raw_getsockopt(struct sock *sk, int level, int optname,
return do_raw_getsockopt(sk, level, optname, optval, optlen);
}
+int raw_uring_cmd(struct sock *sk, struct io_uring_cmd *cmd,
+ enum io_uring_cmd_flags issue_flags)
+{
+ struct sock_uring_cmd *scmd = (struct sock_uring_cmd *)&cmd->pdu;
+
+ switch (scmd->op) {
+ case SOCKET_URING_OP_SIOCOUTQ:
+ return sk_wmem_alloc_get(sk);
+ case SOCKET_URING_OP_SIOCINQ: {
+ struct sk_buff *skb;
+ int amount = 0;
+
+ spin_lock_bh(&sk->sk_receive_queue.lock);
+ skb = skb_peek(&sk->sk_receive_queue);
+ if (skb)
+ amount = skb->len;
+ spin_unlock_bh(&sk->sk_receive_queue.lock);
+ return amount;
+ }
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+EXPORT_SYMBOL_GPL(raw_uring_cmd);
+
static int raw_ioctl(struct sock *sk, int cmd, unsigned long arg)
{
switch (cmd) {
@@ -956,6 +982,7 @@ struct proto raw_prot = {
.release_cb = ip4_datagram_release_cb,
.hash = raw_hash_sk,
.unhash = raw_unhash_sk,
+ .uring_cmd = raw_uring_cmd,
.obj_size = sizeof(struct raw_sock),
.useroffset = offsetof(struct raw_sock, filter),
.usersize = sizeof_field(struct raw_sock, filter),
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 8cb44040ec68..0b703a373593 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -280,6 +280,7 @@
#include <linux/uaccess.h>
#include <asm/ioctls.h>
#include <net/busy_poll.h>
+#include <linux/io_uring.h>
/* Track pending CMSGs. */
enum {
@@ -601,6 +602,41 @@ __poll_t tcp_poll(struct file *file, struct socket *sock, poll_table *wait)
}
EXPORT_SYMBOL(tcp_poll);
+int tcp_uring_cmd(struct sock *sk, struct io_uring_cmd *cmd,
+ enum io_uring_cmd_flags issue_flags)
+{
+ struct sock_uring_cmd *scmd = (struct sock_uring_cmd *)&cmd->pdu;
+ struct tcp_sock *tp = tcp_sk(sk);
+ bool slow;
+ int ret;
+
+ switch (scmd->op) {
+ case SOCKET_URING_OP_SIOCINQ:
+ if (sk->sk_state == TCP_LISTEN)
+ return -EINVAL;
+
+ slow = lock_sock_fast(sk);
+ ret = tcp_inq(sk);
+ unlock_sock_fast(sk, slow);
+ break;
+ case SOCKET_URING_OP_SIOCOUTQ:
+ if (sk->sk_state == TCP_LISTEN)
+ return -EINVAL;
+
+ if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV))
+ ret = 0;
+ else
+ ret = READ_ONCE(tp->write_seq) - tp->snd_una;
+ break;
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(tcp_uring_cmd);
+
int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
{
struct tcp_sock *tp = tcp_sk(sk);
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index a692626c19e4..0169d50671f8 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -2817,6 +2817,7 @@ struct proto tcp_prot = {
.disconnect = tcp_disconnect,
.accept = inet_csk_accept,
.ioctl = tcp_ioctl,
+ .uring_cmd = tcp_uring_cmd,
.init = tcp_v4_init_sock,
.destroy = tcp_v4_destroy_sock,
.shutdown = tcp_shutdown,
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 1a742b710e54..e407d3a3e952 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -113,6 +113,7 @@
#include <net/sock_reuseport.h>
#include <net/addrconf.h>
#include <net/udp_tunnel.h>
+#include <linux/io_uring.h>
#if IS_ENABLED(CONFIG_IPV6)
#include <net/ipv6_stubs.h>
#endif
@@ -1695,6 +1696,22 @@ static int first_packet_length(struct sock *sk)
return res;
}
+int udp_uring_cmd(struct sock *sk, struct io_uring_cmd *cmd,
+ enum io_uring_cmd_flags issue_flags)
+{
+ struct sock_uring_cmd *scmd = (struct sock_uring_cmd *)&cmd->pdu;
+
+ switch (scmd->op) {
+ case SOCKET_URING_OP_SIOCINQ:
+ return max_t(int, 0, first_packet_length(sk));
+ case SOCKET_URING_OP_SIOCOUTQ:
+ return sk_wmem_alloc_get(sk);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+EXPORT_SYMBOL_GPL(udp_uring_cmd);
+
/*
* IOCTL requests applicable to the UDP protocol
*/
@@ -2900,6 +2917,7 @@ struct proto udp_prot = {
.connect = ip4_datagram_connect,
.disconnect = udp_disconnect,
.ioctl = udp_ioctl,
+ .uring_cmd = udp_uring_cmd,
.init = udp_init_sock,
.destroy = udp_destroy_sock,
.setsockopt = udp_setsockopt,
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 60f1e4f5be5a..4cdaa055737d 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -1235,6 +1235,7 @@ struct proto rawv6_prot = {
.connect = ip6_datagram_connect_v6_only,
.disconnect = __udp_disconnect,
.ioctl = rawv6_ioctl,
+ .uring_cmd = raw_uring_cmd,
.init = rawv6_init_sk,
.setsockopt = rawv6_setsockopt,
.getsockopt = rawv6_getsockopt,
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 0ce52d46e4f8..6990d166e2d9 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -2161,6 +2161,7 @@ struct proto tcpv6_prot = {
.disconnect = tcp_disconnect,
.accept = inet_csk_accept,
.ioctl = tcp_ioctl,
+ .uring_cmd = tcp_uring_cmd,
.init = tcp_v6_init_sock,
.destroy = tcp_v6_destroy_sock,
.shutdown = tcp_shutdown,
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index c5e15e94bb00..2f9afd230de7 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -1719,6 +1719,7 @@ struct proto udpv6_prot = {
.connect = ip6_datagram_connect,
.disconnect = udp_disconnect,
.ioctl = udp_ioctl,
+ .uring_cmd = udp_uring_cmd,
.init = udp_init_sock,
.destroy = udpv6_destroy_sock,
.setsockopt = udpv6_setsockopt,