net: tcp/udp/icmp/icmpv6 add FIONSPACE support

Signed-off-by: zhanghongyu <zhanghongyu@xiaomi.com>
This commit is contained in:
zhanghongyu 2022-03-31 11:40:08 +08:00 committed by Xiang Xiao
parent 931a64717a
commit c50d7e174f
16 changed files with 362 additions and 80 deletions

View file

@ -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

View file

@ -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
}

90
net/icmp/icmp_ioctl.c Normal file
View file

@ -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 <nuttx/config.h>
#include <stdint.h>
#include <stdbool.h>
#include <debug.h>
#include <errno.h>
#include <net/if.h>
#include <nuttx/fs/ioctl.h>
#include <nuttx/mm/iob.h>
#include <nuttx/net/net.h>
#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;
}

View file

@ -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 */
};
/****************************************************************************

View file

@ -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)

View file

@ -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
}

90
net/icmpv6/icmpv6_ioctl.c Normal file
View file

@ -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 <nuttx/config.h>
#include <stdint.h>
#include <stdbool.h>
#include <debug.h>
#include <errno.h>
#include <net/if.h>
#include <nuttx/fs/ioctl.h>
#include <nuttx/mm/iob.h>
#include <nuttx/net/net.h>
#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;
}

View file

@ -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 */
};
/****************************************************************************

View file

@ -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
*

View file

@ -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;

View file

@ -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)
{

View file

@ -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
*

View file

@ -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
*

View file

@ -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;

View file

@ -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)
{

View file

@ -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
*