This is an automated email from the ASF dual-hosted git repository. xiaoxiang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit eb60667561f918b6b60471a3609b89ac087b13fb Author: zhanghongyu <[email protected]> AuthorDate: Fri Jul 4 16:51:08 2025 +0800 net/utils/net_lock.c: add api to lock conn and netdev add new api to protect access and operation to conn and dev Signed-off-by: zhanghongyu <[email protected]> --- drivers/net/netdev_upperhalf.c | 12 ++++++--- include/nuttx/net/net.h | 27 +++++++++++++++++++ include/nuttx/net/netdev.h | 2 ++ net/netdev/CMakeLists.txt | 3 ++- net/netdev/Make.defs | 2 +- net/netdev/netdev_ioctl.c | 18 ++++++------- net/netdev/netdev_lock.c | 59 ++++++++++++++++++++++++++++++++++++++++++ net/netdev/netdev_register.c | 2 ++ net/netdev/netdev_unregister.c | 2 ++ net/utils/net_lock.c | 40 ++++++++++++++++++++++++++++ net/utils/utils.h | 17 ++++++++++++ 11 files changed, 168 insertions(+), 16 deletions(-) diff --git a/drivers/net/netdev_upperhalf.c b/drivers/net/netdev_upperhalf.c index 4a0ac06e3c2..04cac299730 100644 --- a/drivers/net/netdev_upperhalf.c +++ b/drivers/net/netdev_upperhalf.c @@ -382,7 +382,7 @@ static void netdev_upper_txavail_work(FAR struct netdev_upperhalf_s *upper) /* Ignore the notification if the interface is not yet up */ - net_lock(); + netdev_lock(dev); if (IFF_IS_UP(dev->d_flags) && !upper->txing) { DEBUGASSERT(dev->d_buf == NULL); /* Make sure: IOB only. */ @@ -392,7 +392,7 @@ static void netdev_upper_txavail_work(FAR struct netdev_upperhalf_s *upper) upper->txing = false; } - net_unlock(); + netdev_unlock(dev); } /**************************************************************************** @@ -708,7 +708,7 @@ static void netdev_upper_rxpoll_work(FAR struct netdev_upperhalf_s *upper) /* Loop while receive() successfully retrieves valid Ethernet frames. */ - net_lock(); + netdev_lock(dev); while ((pkt = lower->ops->receive(lower)) != NULL) { if (!IFF_IS_UP(dev->d_flags)) @@ -763,7 +763,7 @@ static void netdev_upper_rxpoll_work(FAR struct netdev_upperhalf_s *upper) } } - net_unlock(); + netdev_unlock(dev); } /**************************************************************************** @@ -1532,7 +1532,9 @@ void netdev_lower_carrier_on(FAR struct netdev_lowerhalf_s *dev) netdev_upper_vlan_foreach(upper, netdev_lower_carrier_on); #endif + netdev_lock(&dev->netdev); netdev_carrier_on(&dev->netdev); + netdev_unlock(&dev->netdev); } /**************************************************************************** @@ -1554,7 +1556,9 @@ void netdev_lower_carrier_off(FAR struct netdev_lowerhalf_s *dev) netdev_upper_vlan_foreach(upper, netdev_lower_carrier_off); #endif + netdev_lock(&dev->netdev); netdev_carrier_off(&dev->netdev); + netdev_unlock(&dev->netdev); } /**************************************************************************** diff --git a/include/nuttx/net/net.h b/include/nuttx/net/net.h index af2af577b3e..c16c4c38f2e 100644 --- a/include/nuttx/net/net.h +++ b/include/nuttx/net/net.h @@ -206,6 +206,13 @@ struct socket_conn_s FAR struct devif_callback_s *list; FAR struct devif_callback_s *list_tail; + /* This lock protects the connection structure. It is used to prevent + * re-entrance into the connection structure while it is being modified. + * This mutex is also used to protect the list of callbacks. + */ + + mutex_t s_lock; /* Protect the connection structure */ + /* Socket options */ #ifdef CONFIG_NET_SOCKOPTS @@ -1498,6 +1505,26 @@ int netdev_register(FAR struct net_driver_s *dev, enum net_lltype_e lltype); int netdev_unregister(FAR struct net_driver_s *dev); +/**************************************************************************** + * Name: netdev_lock + * + * Description: + * Lock the network device. + * + ****************************************************************************/ + +void netdev_lock(FAR struct net_driver_s *dev); + +/**************************************************************************** + * Name: netdev_unlock + * + * Description: + * Unlock the network device. + * + ****************************************************************************/ + +void netdev_unlock(FAR struct net_driver_s *dev); + #undef EXTERN #ifdef __cplusplus } diff --git a/include/nuttx/net/netdev.h b/include/nuttx/net/netdev.h index c69e670d3fb..291aa853a0f 100644 --- a/include/nuttx/net/netdev.h +++ b/include/nuttx/net/netdev.h @@ -335,6 +335,8 @@ struct net_driver_s char d_ifname[IFNAMSIZ]; #endif + rmutex_t d_lock; + /* Drivers interface flags. See IFF_* definitions in include/net/if.h */ uint32_t d_flags; diff --git a/net/netdev/CMakeLists.txt b/net/netdev/CMakeLists.txt index 1ecdc0b9249..ac4e60ebf17 100644 --- a/net/netdev/CMakeLists.txt +++ b/net/netdev/CMakeLists.txt @@ -34,7 +34,8 @@ set(SRCS netdev_carrier.c netdev_default.c netdev_verify.c - netdev_lladdrsize.c) + netdev_lladdrsize.c + netdev_lock.c) if(CONFIG_MM_IOB) list(APPEND SRCS netdev_input.c netdev_iob.c) diff --git a/net/netdev/Make.defs b/net/netdev/Make.defs index 44a8c26533a..14bbe04fe97 100644 --- a/net/netdev/Make.defs +++ b/net/netdev/Make.defs @@ -26,7 +26,7 @@ NETDEV_CSRCS += netdev_register.c netdev_ioctl.c netdev_txnotify.c NETDEV_CSRCS += netdev_findbyname.c netdev_findbyaddr.c netdev_findbyindex.c NETDEV_CSRCS += netdev_count.c netdev_ifconf.c netdev_foreach.c NETDEV_CSRCS += netdev_unregister.c netdev_carrier.c netdev_default.c -NETDEV_CSRCS += netdev_verify.c netdev_lladdrsize.c +NETDEV_CSRCS += netdev_verify.c netdev_lladdrsize.c netdev_lock.c ifeq ($(CONFIG_MM_IOB),y) NETDEV_CSRCS += netdev_input.c netdev_iob.c diff --git a/net/netdev/netdev_ioctl.c b/net/netdev/netdev_ioctl.c index 2945744e06d..61efcac5f0f 100644 --- a/net/netdev/netdev_ioctl.c +++ b/net/netdev/netdev_ioctl.c @@ -581,18 +581,18 @@ static int netdev_cell_ioctl(FAR struct socket *psock, int cmd, int ret = -ENOTTY; ninfo("cmd: %d\n", cmd); - net_lock(); if (_CELLIOCVALID(cmd)) { dev = netdev_findbyname(req->ifr_name); if (dev && dev->d_ioctl) { + netdev_lock(dev); ret = dev->d_ioctl(dev, cmd, (unsigned long)(uintptr_t)req); + netdev_unlock(dev); } } - net_unlock(); return ret; } #endif @@ -830,8 +830,6 @@ static int netdev_ifr_ioctl(FAR struct socket *psock, int cmd, ninfo("cmd: %d\n", cmd); - net_lock(); - /* Execute commands that do not need ifr_name or lifr_name */ switch (cmd) @@ -886,7 +884,6 @@ static int netdev_ifr_ioctl(FAR struct socket *psock, int cmd, default: if (req == NULL) { - net_unlock(); return -ENOTTY; } @@ -913,10 +910,11 @@ static int netdev_ifr_ioctl(FAR struct socket *psock, int cmd, if (dev == NULL) { - net_unlock(); return ret; } + netdev_lock(dev); + /* Execute commands that need ifr_name or lifr_name */ switch (cmd) @@ -1322,7 +1320,7 @@ static int netdev_ifr_ioctl(FAR struct socket *psock, int cmd, break; } - net_unlock(); + netdev_unlock(dev); return ret; } @@ -1383,8 +1381,6 @@ static int netdev_imsf_ioctl(FAR struct socket *psock, int cmd, ninfo("cmd: %d\n", cmd); - net_lock(); - /* Execute the command */ switch (cmd) @@ -1394,6 +1390,7 @@ static int netdev_imsf_ioctl(FAR struct socket *psock, int cmd, dev = netdev_imsfdev(imsf); if (dev) { + netdev_lock(dev); if (imsf->imsf_fmode == MCAST_INCLUDE) { ret = igmp_joingroup(dev, &imsf->imsf_multiaddr); @@ -1403,6 +1400,8 @@ static int netdev_imsf_ioctl(FAR struct socket *psock, int cmd, DEBUGASSERT(imsf->imsf_fmode == MCAST_EXCLUDE); ret = igmp_leavegroup(dev, &imsf->imsf_multiaddr); } + + netdev_unlock(dev); } } break; @@ -1413,7 +1412,6 @@ static int netdev_imsf_ioctl(FAR struct socket *psock, int cmd, break; } - net_unlock(); return ret; } #endif diff --git a/net/netdev/netdev_lock.c b/net/netdev/netdev_lock.c new file mode 100644 index 00000000000..69b80918719 --- /dev/null +++ b/net/netdev/netdev_lock.c @@ -0,0 +1,59 @@ +/**************************************************************************** + * net/netdev/netdev_lock.c + * + * SPDX-License-Identifier: Apache-2.0 + * + * 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 <nuttx/net/netdev.h> + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: netdev_lock + * + * Description: + * Lock the network device. + * + ****************************************************************************/ + +void netdev_lock(FAR struct net_driver_s *dev) +{ + nxrmutex_lock(&dev->d_lock); +} + +/**************************************************************************** + * Name: netdev_unlock + * + * Description: + * Unlock the network device. + * + ****************************************************************************/ + +void netdev_unlock(FAR struct net_driver_s *dev) +{ + nxrmutex_unlock(&dev->d_lock); +} diff --git a/net/netdev/netdev_register.c b/net/netdev/netdev_register.c index 07d388ecca5..e23daa44082 100644 --- a/net/netdev/netdev_register.c +++ b/net/netdev/netdev_register.c @@ -425,6 +425,8 @@ int netdev_register(FAR struct net_driver_s *dev, enum net_lltype_e lltype) dev->d_conncb_tail = NULL; dev->d_devcb = NULL; + nxrmutex_init(&dev->d_lock); + /* We need exclusive access for the following operations */ netdev_list_lock(); diff --git a/net/netdev/netdev_unregister.c b/net/netdev/netdev_unregister.c index 1ef46c95a0e..c07d8070559 100644 --- a/net/netdev/netdev_unregister.c +++ b/net/netdev/netdev_unregister.c @@ -163,6 +163,8 @@ int netdev_unregister(FAR struct net_driver_s *dev) netdev_list_unlock(); + nxrmutex_destroy(&dev->d_lock); + #if CONFIG_NETDEV_STATISTICS_LOG_PERIOD > 0 work_cancel_sync(NETDEV_STATISTICS_WORK, &dev->d_statistics.logwork); #endif diff --git a/net/utils/net_lock.c b/net/utils/net_lock.c index de27e3bc44d..0a2037ca431 100644 --- a/net/utils/net_lock.c +++ b/net/utils/net_lock.c @@ -465,3 +465,43 @@ FAR struct iob_s *net_ioballoc(bool throttled) return net_iobtimedalloc(throttled, UINT_MAX); } #endif + +/**************************************************************************** + * Name: conn_lock, conn_unlock, conn_dev_lock, conn_dev_unlock + * + * Description: + * Lock and unlock the connection and device. + * + ****************************************************************************/ + +void conn_lock(FAR struct socket_conn_s *sconn) +{ + nxmutex_lock(&sconn->s_lock); +} + +void conn_unlock(FAR struct socket_conn_s *sconn) +{ + nxmutex_unlock(&sconn->s_lock); +} + +void conn_dev_lock(FAR struct socket_conn_s *sconn, + FAR struct net_driver_s *dev) +{ + if (dev != NULL) + { + netdev_lock(dev); + } + + nxmutex_lock(&sconn->s_lock); +} + +void conn_dev_unlock(FAR struct socket_conn_s *sconn, + FAR struct net_driver_s *dev) +{ + nxmutex_unlock(&sconn->s_lock); + + if (dev != NULL) + { + netdev_unlock(dev); + } +} diff --git a/net/utils/utils.h b/net/utils/utils.h index 2aec120b1ed..0eacf0a59b7 100644 --- a/net/utils/utils.h +++ b/net/utils/utils.h @@ -606,6 +606,23 @@ uint16_t icmpv6_chksum(FAR struct net_driver_s *dev, unsigned int iplen); FAR void *cmsg_append(FAR struct msghdr *msg, int level, int type, FAR void *value, int value_len); +/**************************************************************************** + * Name: conn_lock, conn_unlock, conn_dev_lock, conn_dev_unlock + * + * Description: + * Lock and unlock the connection and device. + * + ****************************************************************************/ + +void conn_lock(FAR struct socket_conn_s *sconn); +void conn_unlock(FAR struct socket_conn_s *sconn); + +void conn_dev_lock(FAR struct socket_conn_s *sconn, + FAR struct net_driver_s *dev); + +void conn_dev_unlock(FAR struct socket_conn_s *sconn, + FAR struct net_driver_s *dev); + #undef EXTERN #ifdef __cplusplus }
