From c50d7e174f60dae6ea7c1fddbcfab2d1b4e699a1 Mon Sep 17 00:00:00 2001 From: zhanghongyu Date: Thu, 31 Mar 2022 11:40:08 +0800 Subject: [PATCH] net: tcp/udp/icmp/icmpv6 add FIONSPACE support Signed-off-by: zhanghongyu --- net/icmp/Make.defs | 2 +- net/icmp/icmp.h | 19 ++++++++ net/icmp/icmp_ioctl.c | 90 +++++++++++++++++++++++++++++++++++ net/icmp/icmp_sockif.c | 3 +- net/icmpv6/Make.defs | 2 +- net/icmpv6/icmpv6.h | 19 ++++++++ net/icmpv6/icmpv6_ioctl.c | 90 +++++++++++++++++++++++++++++++++++ net/icmpv6/icmpv6_sockif.c | 3 +- net/tcp/tcp.h | 18 +++++++ net/tcp/tcp_ioctl.c | 13 +++++ net/tcp/tcp_send_buffered.c | 42 +--------------- net/tcp/tcp_wrbuffer.c | 40 ++++++++++++++++ net/udp/udp.h | 18 +++++++ net/udp/udp_ioctl.c | 13 +++++ net/udp/udp_sendto_buffered.c | 36 +------------- net/udp/udp_wrbuffer.c | 34 +++++++++++++ 16 files changed, 362 insertions(+), 80 deletions(-) create mode 100644 net/icmp/icmp_ioctl.c create mode 100644 net/icmpv6/icmpv6_ioctl.c diff --git a/net/icmp/Make.defs b/net/icmp/Make.defs index 0a0c23082a..6586ca3f91 100644 --- a/net/icmp/Make.defs +++ b/net/icmp/Make.defs @@ -27,7 +27,7 @@ NET_CSRCS += icmp_input.c icmp_reply.c ifeq ($(CONFIG_NET_ICMP_SOCKET),y) SOCK_CSRCS += icmp_sockif.c icmp_poll.c icmp_conn.c icmp_sendmsg.c -SOCK_CSRCS += icmp_recvmsg.c icmp_netpoll.c +SOCK_CSRCS += icmp_recvmsg.c icmp_netpoll.c icmp_ioctl.c endif # Include ICMP build support diff --git a/net/icmp/icmp.h b/net/icmp/icmp.h index 7c6a36862a..6015804abb 100644 --- a/net/icmp/icmp.h +++ b/net/icmp/icmp.h @@ -380,6 +380,25 @@ int icmp_pollteardown(FAR struct socket *psock, FAR struct pollfd *fds); void icmp_reply(FAR struct net_driver_s *dev, int type, int code); +/**************************************************************************** + * Name: icmp_ioctl + * + * Description: + * This function performs icmp specific ioctl() operations. + * + * Parameters: + * conn The ICMP connection of interest + * cmd The ioctl command + * arg The argument of the ioctl cmd + * arglen The length of 'arg' + * + ****************************************************************************/ + +#ifdef CONFIG_NET_ICMP_SOCKET +int icmp_ioctl(FAR struct socket *psock, + int cmd, FAR void *arg, size_t arglen); +#endif + #undef EXTERN #ifdef __cplusplus } diff --git a/net/icmp/icmp_ioctl.c b/net/icmp/icmp_ioctl.c new file mode 100644 index 0000000000..dba9be4256 --- /dev/null +++ b/net/icmp/icmp_ioctl.c @@ -0,0 +1,90 @@ +/**************************************************************************** + * net/icmp/icmp_ioctl.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include "icmp/icmp.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: icmp_ioctl + * + * Description: + * This function performs icmp specific ioctl() operations. + * + * Parameters: + * conn The ICMP connection of interest + * cmd The ioctl command + * arg The argument of the ioctl cmd + * arglen The length of 'arg' + * + ****************************************************************************/ + +int icmp_ioctl(FAR struct socket *psock, + int cmd, FAR void *arg, size_t arglen) +{ + FAR struct icmp_conn_s *conn = psock->s_conn; + int ret = OK; + + net_lock(); + + switch (cmd) + { + case FIONREAD: + if (iob_peek_queue(&conn->readahead) != NULL) + { + *(FAR int *)((uintptr_t)arg) = + iob_peek_queue(&conn->readahead)->io_pktlen; + } + else + { + *(FAR int *)((uintptr_t)arg) = 0; + } + break; + case FIONSPACE: + *(FAR int *)((uintptr_t)arg) = MIN_UDP_MSS; + break; + default: + ret = -ENOTTY; + break; + } + + net_unlock(); + + return ret; +} diff --git a/net/icmp/icmp_sockif.c b/net/icmp/icmp_sockif.c index 6985ada6da..8e1e596ac6 100644 --- a/net/icmp/icmp_sockif.c +++ b/net/icmp/icmp_sockif.c @@ -81,7 +81,8 @@ const struct sock_intf_s g_icmp_sockif = icmp_netpoll, /* si_poll */ icmp_sendmsg, /* si_sendmsg */ icmp_recvmsg, /* si_recvmsg */ - icmp_close /* si_close */ + icmp_close, /* si_close */ + icmp_ioctl /* si_ioctl */ }; /**************************************************************************** diff --git a/net/icmpv6/Make.defs b/net/icmpv6/Make.defs index 4f71904235..6bf01acf5a 100644 --- a/net/icmpv6/Make.defs +++ b/net/icmpv6/Make.defs @@ -28,7 +28,7 @@ NET_CSRCS += icmpv6_linkipaddr.c icmpv6_reply.c ifeq ($(CONFIG_NET_ICMPv6_SOCKET),y) SOCK_CSRCS += icmpv6_sockif.c icmpv6_conn.c icmpv6_sendmsg.c -SOCK_CSRCS += icmpv6_recvmsg.c icmpv6_netpoll.c +SOCK_CSRCS += icmpv6_recvmsg.c icmpv6_netpoll.c icmpv6_ioctl.c endif ifeq ($(CONFIG_NET_ICMPv6_NEIGHBOR),y) diff --git a/net/icmpv6/icmpv6.h b/net/icmpv6/icmpv6.h index 38e1170107..1e3fbbe2e0 100644 --- a/net/icmpv6/icmpv6.h +++ b/net/icmpv6/icmpv6.h @@ -746,6 +746,25 @@ void icmpv6_linkipaddr(FAR struct net_driver_s *dev, net_ipv6addr_t ipaddr); void icmpv6_reply(FAR struct net_driver_s *dev, int type, int code, int data); +/**************************************************************************** + * Name: icmpv6_ioctl + * + * Description: + * This function performs icmp specific ioctl() operations. + * + * Parameters: + * conn The ICMP connection of interest + * cmd The ioctl command + * arg The argument of the ioctl cmd + * arglen The length of 'arg' + * + ****************************************************************************/ + +#ifdef CONFIG_NET_ICMPv6_SOCKET +int icmpv6_ioctl(FAR struct socket *psock, + int cmd, FAR void *arg, size_t arglen); +#endif + #undef EXTERN #ifdef __cplusplus } diff --git a/net/icmpv6/icmpv6_ioctl.c b/net/icmpv6/icmpv6_ioctl.c new file mode 100644 index 0000000000..28cd658b27 --- /dev/null +++ b/net/icmpv6/icmpv6_ioctl.c @@ -0,0 +1,90 @@ +/**************************************************************************** + * net/icmpv6/icmpv6_ioctl.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include "icmpv6/icmpv6.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: icmpv6_ioctl + * + * Description: + * This function performs icmpv6 specific ioctl() operations. + * + * Parameters: + * conn The icmpv6 connection of interest + * cmd The ioctl command + * arg The argument of the ioctl cmd + * arglen The length of 'arg' + * + ****************************************************************************/ + +int icmpv6_ioctl(FAR struct socket *psock, + int cmd, FAR void *arg, size_t arglen) +{ + FAR struct icmpv6_conn_s *conn = psock->s_conn; + int ret = OK; + + net_lock(); + + switch (cmd) + { + case FIONREAD: + if (iob_peek_queue(&conn->readahead) != NULL) + { + *(FAR int *)((uintptr_t)arg) = + iob_peek_queue(&conn->readahead)->io_pktlen; + } + else + { + *(FAR int *)((uintptr_t)arg) = 0; + } + break; + case FIONSPACE: + *(FAR int *)((uintptr_t)arg) = MIN_UDP_MSS; + break; + default: + ret = -ENOTTY; + break; + } + + net_unlock(); + + return ret; +} diff --git a/net/icmpv6/icmpv6_sockif.c b/net/icmpv6/icmpv6_sockif.c index a0a5456673..dc28d27920 100644 --- a/net/icmpv6/icmpv6_sockif.c +++ b/net/icmpv6/icmpv6_sockif.c @@ -81,7 +81,8 @@ const struct sock_intf_s g_icmpv6_sockif = icmpv6_netpoll, /* si_poll */ icmpv6_sendmsg, /* si_sendmsg */ icmpv6_recvmsg, /* si_recvmsg */ - icmpv6_close /* si_close */ + icmpv6_close, /* si_close */ + icmpv6_ioctl /* si_ioctl */ }; /**************************************************************************** diff --git a/net/tcp/tcp.h b/net/tcp/tcp.h index b45e888ba9..308885ddd3 100644 --- a/net/tcp/tcp.h +++ b/net/tcp/tcp.h @@ -1617,6 +1617,24 @@ FAR struct tcp_wrbuffer_s *tcp_wrbuffer_tryalloc(void); void tcp_wrbuffer_release(FAR struct tcp_wrbuffer_s *wrb); #endif /* CONFIG_NET_TCP_WRITE_BUFFERS */ +/**************************************************************************** + * Name: tcp_wrbuffer_inqueue_size + * + * Description: + * Get the in-queued write buffer size from connection + * + * Input Parameters: + * conn - The TCP connection of interest + * + * Assumptions: + * Called from user logic with the network locked. + * + ****************************************************************************/ + +#if CONFIG_NET_SEND_BUFSIZE > 0 +uint32_t tcp_wrbuffer_inqueue_size(FAR struct tcp_conn_s *conn); +#endif + /**************************************************************************** * Name: tcp_wrbuffer_test * diff --git a/net/tcp/tcp_ioctl.c b/net/tcp/tcp_ioctl.c index af5bb985e0..9ebd4b50a3 100644 --- a/net/tcp/tcp_ioctl.c +++ b/net/tcp/tcp_ioctl.c @@ -74,6 +74,19 @@ int tcp_ioctl(FAR struct tcp_conn_s *conn, *(FAR int *)((uintptr_t)arg) = 0; } break; + case FIONSPACE: +#ifdef CONFIG_NET_TCP_WRITE_BUFFERS +# if CONFIG_NET_SEND_BUFSIZE == 0 + *(FAR int *)((uintptr_t)arg) = + iob_navail(true) * CONFIG_IOB_BUFSIZE; +# else + *(FAR int *)((uintptr_t)arg) = + conn->snd_bufs - tcp_wrbuffer_inqueue_size(conn); +# endif +#else + *(FAR int *)((uintptr_t)arg) = MIN_TCP_MSS; +#endif + break; default: ret = -ENOTTY; break; diff --git a/net/tcp/tcp_send_buffered.c b/net/tcp/tcp_send_buffered.c index cb5c62fb7c..c5aac33db8 100644 --- a/net/tcp/tcp_send_buffered.c +++ b/net/tcp/tcp_send_buffered.c @@ -94,46 +94,6 @@ * Private Functions ****************************************************************************/ -/**************************************************************************** - * Name: tcp_inqueue_wrb_size - * - * Description: - * Get the in-queued write buffer size from connection - * - * Input Parameters: - * conn - The TCP connection of interest - * - * Assumptions: - * Called from user logic with the network locked. - * - ****************************************************************************/ - -#if CONFIG_NET_SEND_BUFSIZE > 0 -static uint32_t tcp_inqueue_wrb_size(FAR struct tcp_conn_s *conn) -{ - FAR struct tcp_wrbuffer_s *wrb; - FAR sq_entry_t *entry; - uint32_t total = 0; - - if (conn) - { - for (entry = sq_peek(&conn->unacked_q); entry; entry = sq_next(entry)) - { - wrb = (FAR struct tcp_wrbuffer_s *)entry; - total += TCP_WBPKTLEN(wrb); - } - - for (entry = sq_peek(&conn->write_q); entry; entry = sq_next(entry)) - { - wrb = (FAR struct tcp_wrbuffer_s *)entry; - total += TCP_WBPKTLEN(wrb); - } - } - - return total; -} -#endif /* CONFIG_NET_SEND_BUFSIZE */ - /**************************************************************************** * Name: psock_insert_segment * @@ -1223,7 +1183,7 @@ ssize_t psock_tcp_send(FAR struct socket *psock, FAR const void *buf, * wait for the write buffer to be released */ - while (tcp_inqueue_wrb_size(conn) >= conn->snd_bufs) + while (tcp_wrbuffer_inqueue_size(conn) >= conn->snd_bufs) { if (nonblock) { diff --git a/net/tcp/tcp_wrbuffer.c b/net/tcp/tcp_wrbuffer.c index bc2644f1e1..f3e7beee6d 100644 --- a/net/tcp/tcp_wrbuffer.c +++ b/net/tcp/tcp_wrbuffer.c @@ -249,6 +249,46 @@ void tcp_wrbuffer_release(FAR struct tcp_wrbuffer_s *wrb) nxsem_post(&g_wrbuffer.sem); } +/**************************************************************************** + * Name: tcp_wrbuffer_inqueue_size + * + * Description: + * Get the in-queued write buffer size from connection + * + * Input Parameters: + * conn - The TCP connection of interest + * + * Assumptions: + * Called from user logic with the network locked. + * + ****************************************************************************/ + +#if CONFIG_NET_SEND_BUFSIZE > 0 +uint32_t tcp_wrbuffer_inqueue_size(FAR struct tcp_conn_s *conn) +{ + FAR struct tcp_wrbuffer_s *wrb; + FAR sq_entry_t *entry; + uint32_t total = 0; + + if (conn) + { + for (entry = sq_peek(&conn->unacked_q); entry; entry = sq_next(entry)) + { + wrb = (FAR struct tcp_wrbuffer_s *)entry; + total += TCP_WBPKTLEN(wrb); + } + + for (entry = sq_peek(&conn->write_q); entry; entry = sq_next(entry)) + { + wrb = (FAR struct tcp_wrbuffer_s *)entry; + total += TCP_WBPKTLEN(wrb); + } + } + + return total; +} +#endif /* CONFIG_NET_SEND_BUFSIZE */ + /**************************************************************************** * Name: tcp_wrbuffer_test * diff --git a/net/udp/udp.h b/net/udp/udp.h index 4f6ce5973d..03daa0ae25 100644 --- a/net/udp/udp.h +++ b/net/udp/udp.h @@ -510,6 +510,24 @@ FAR struct udp_wrbuffer_s *udp_wrbuffer_tryalloc(void); void udp_wrbuffer_release(FAR struct udp_wrbuffer_s *wrb); #endif /* CONFIG_NET_UDP_WRITE_BUFFERS */ +/**************************************************************************** + * Name: udp_wrbuffer_inqueue_size + * + * Description: + * Get the in-queued write buffer size from connection + * + * Input Parameters: + * conn - The UDP connection of interest + * + * Assumptions: + * Called from user logic with the network locked. + * + ****************************************************************************/ + +#if CONFIG_NET_SEND_BUFSIZE > 0 +uint32_t udp_wrbuffer_inqueue_size(FAR struct udp_conn_s *conn); +#endif /* CONFIG_NET_SEND_BUFSIZE */ + /**************************************************************************** * Name: udp_wrbuffer_test * diff --git a/net/udp/udp_ioctl.c b/net/udp/udp_ioctl.c index bb458f38bb..9968c608f9 100644 --- a/net/udp/udp_ioctl.c +++ b/net/udp/udp_ioctl.c @@ -76,6 +76,19 @@ int udp_ioctl(FAR struct udp_conn_s *conn, *(FAR int *)((uintptr_t)arg) = 0; } break; + case FIONSPACE: +#ifdef CONFIG_NET_UDP_WRITE_BUFFERS +# if CONFIG_NET_SEND_BUFSIZE == 0 + *(FAR int *)((uintptr_t)arg) = + iob_navail(true) * CONFIG_IOB_BUFSIZE; +# else + *(FAR int *)((uintptr_t)arg) = + conn->sndbufs - udp_wrbuffer_inqueue_size(conn); +# endif +#else + *(FAR int *)((uintptr_t)arg) = MIN_UDP_MSS; +#endif + break; default: ret = -ENOTTY; break; diff --git a/net/udp/udp_sendto_buffered.c b/net/udp/udp_sendto_buffered.c index 0f2b2fc749..470451ca55 100644 --- a/net/udp/udp_sendto_buffered.c +++ b/net/udp/udp_sendto_buffered.c @@ -104,40 +104,6 @@ static uint16_t sendto_eventhandler(FAR struct net_driver_s *dev, * Private Functions ****************************************************************************/ -/**************************************************************************** - * Name: udp_inqueue_wrb_size - * - * Description: - * Get the in-queued write buffer size from connection - * - * Input Parameters: - * conn - The UDP connection of interest - * - * Assumptions: - * Called from user logic with the network locked. - * - ****************************************************************************/ - -#if CONFIG_NET_SEND_BUFSIZE > 0 -static uint32_t udp_inqueue_wrb_size(FAR struct udp_conn_s *conn) -{ - FAR struct udp_wrbuffer_s *wrb; - FAR sq_entry_t *entry; - uint32_t total = 0; - - if (conn) - { - for (entry = sq_peek(&conn->write_q); entry; entry = sq_next(entry)) - { - wrb = (FAR struct udp_wrbuffer_s *)entry; - total += wrb->wb_iob->io_pktlen; - } - } - - return total; -} -#endif /* CONFIG_NET_SEND_BUFSIZE */ - /**************************************************************************** * Name: sendto_writebuffer_release * @@ -676,7 +642,7 @@ ssize_t psock_udp_sendto(FAR struct socket *psock, FAR const void *buf, * wait for the write buffer to be released */ - while (udp_inqueue_wrb_size(conn) + len > conn->sndbufs) + while (udp_wrbuffer_inqueue_size(conn) + len > conn->sndbufs) { if (nonblock) { diff --git a/net/udp/udp_wrbuffer.c b/net/udp/udp_wrbuffer.c index 9e7b7c7fdb..c8aa2f8e4a 100644 --- a/net/udp/udp_wrbuffer.c +++ b/net/udp/udp_wrbuffer.c @@ -243,6 +243,40 @@ void udp_wrbuffer_release(FAR struct udp_wrbuffer_s *wrb) nxsem_post(&g_wrbuffer.sem); } +/**************************************************************************** + * Name: udp_wrbuffer_inqueue_size + * + * Description: + * Get the in-queued write buffer size from connection + * + * Input Parameters: + * conn - The UDP connection of interest + * + * Assumptions: + * Called from user logic with the network locked. + * + ****************************************************************************/ + +#if CONFIG_NET_SEND_BUFSIZE > 0 +uint32_t udp_wrbuffer_inqueue_size(FAR struct udp_conn_s *conn) +{ + FAR struct udp_wrbuffer_s *wrb; + FAR sq_entry_t *entry; + uint32_t total = 0; + + if (conn) + { + for (entry = sq_peek(&conn->write_q); entry; entry = sq_next(entry)) + { + wrb = (FAR struct udp_wrbuffer_s *)entry; + total += wrb->wb_iob->io_pktlen; + } + } + + return total; +} +#endif /* CONFIG_NET_SEND_BUFSIZE */ + /**************************************************************************** * Name: udp_wrbuffer_test *