Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys add API to manipulate ifa->ia_hash and ia_hash_pslist_en...



details:   https://anonhg.NetBSD.org/src/rev/bdfe1085d0e6
branches:  trunk
changeset: 819458:bdfe1085d0e6
user:      knakahara <knakahara%NetBSD.org@localhost>
date:      Tue Dec 06 07:01:47 2016 +0000

description:
add API to manipulate ifa->ia_hash and ia_hash_pslist_entry, and fix ia_hash_pslist_entry race by using them.

in_ifaddr_lock is required before writing ifa->ia_hash and
ia_hash_pslist_entry to serialize writer processings.

reviewed by ozaki-r@n.o.

diffstat:

 sys/net/if_spppsubr.c |  28 +++------------
 sys/netinet/in.c      |  92 ++++++++++++++++++++++++++++++--------------------
 sys/netinet/in_var.h  |   4 +-
 3 files changed, 64 insertions(+), 60 deletions(-)

diffs (237 lines):

diff -r 9bd0b1ba19e0 -r bdfe1085d0e6 sys/net/if_spppsubr.c
--- a/sys/net/if_spppsubr.c     Tue Dec 06 06:41:14 2016 +0000
+++ b/sys/net/if_spppsubr.c     Tue Dec 06 07:01:47 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_spppsubr.c,v 1.161 2016/12/01 02:30:54 knakahara Exp $       */
+/*     $NetBSD: if_spppsubr.c,v 1.162 2016/12/06 07:01:47 knakahara Exp $       */
 
 /*
  * Synchronous PPP/Cisco link level subroutines.
@@ -41,7 +41,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_spppsubr.c,v 1.161 2016/12/01 02:30:54 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_spppsubr.c,v 1.162 2016/12/06 07:01:47 knakahara Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_inet.h"
@@ -4921,19 +4921,11 @@
                                sp->ipcp.saved_hisaddr = dest->sin_addr.s_addr;
                }
 
-               LIST_REMOVE(ifatoia(ifa), ia_hash);
-               IN_ADDRHASH_WRITER_REMOVE(ifatoia(ifa));
-#ifdef NET_MPSAFE
-               pserialize_perform(in_ifaddrhash_psz);
-#endif
-               IN_ADDRHASH_ENTRY_DESTROY(ifatoia(ifa));
+               in_addrhash_remove(ifatoia(ifa));
 
                error = in_ifinit(ifp, ifatoia(ifa), &new_sin, &new_dst, 0);
 
-               IN_ADDRHASH_ENTRY_INIT(ifatoia(ifa));
-               LIST_INSERT_HEAD(&IN_IFADDR_HASH(ifatoia(ifa)->ia_addr.sin_addr.s_addr),
-                   ifatoia(ifa), ia_hash);
-               IN_ADDRHASH_WRITER_INSERT_HEAD(ifatoia(ifa));
+               in_addrhash_insert(ifatoia(ifa));
 
                if (debug && error)
                {
@@ -5012,19 +5004,11 @@
                if (sp->ipcp.flags & IPCP_HISADDR_DYN)
                        new_dst.sin_addr.s_addr = sp->ipcp.saved_hisaddr;
 
-               LIST_REMOVE(ifatoia(ifa), ia_hash);
-               IN_ADDRHASH_WRITER_REMOVE(ifatoia(ifa));
-#ifdef NET_MPSAFE
-               pserialize_perform(in_ifaddrhash_psz);
-#endif
-               IN_ADDRHASH_ENTRY_DESTROY(ifatoia(ifa));
+               in_addrhash_remove(ifatoia(ifa));
 
                error = in_ifinit(ifp, ifatoia(ifa), &new_sin, &new_dst, 0);
 
-               IN_ADDRHASH_ENTRY_INIT(ifatoia(ifa));
-               LIST_INSERT_HEAD(&IN_IFADDR_HASH(ifatoia(ifa)->ia_addr.sin_addr.s_addr),
-                   ifatoia(ifa), ia_hash);
-               IN_ADDRHASH_WRITER_INSERT_HEAD(ifatoia(ifa));
+               in_addrhash_insert(ifatoia(ifa));
 
                if (debug && error)
                {
diff -r 9bd0b1ba19e0 -r bdfe1085d0e6 sys/netinet/in.c
--- a/sys/netinet/in.c  Tue Dec 06 06:41:14 2016 +0000
+++ b/sys/netinet/in.c  Tue Dec 06 07:01:47 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: in.c,v 1.188 2016/11/18 10:38:55 knakahara Exp $       */
+/*     $NetBSD: in.c,v 1.189 2016/12/06 07:01:47 knakahara Exp $       */
 
 /*
  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@@ -91,7 +91,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: in.c,v 1.188 2016/11/18 10:38:55 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: in.c,v 1.189 2016/12/06 07:01:47 knakahara Exp $");
 
 #include "arp.h"
 
@@ -149,6 +149,9 @@
 static int     in_lifaddr_ioctl(struct socket *, u_long, void *,
        struct ifnet *);
 
+static void    in_addrhash_insert_locked(struct in_ifaddr *);
+static void    in_addrhash_remove_locked(struct in_ifaddr *);
+
 static int     in_addprefix(struct in_ifaddr *, int);
 static void    in_scrubaddr(struct in_ifaddr *);
 static int     in_scrubprefix(struct in_ifaddr *);
@@ -598,14 +601,7 @@
 
        case SIOCSIFADDR:
                if (!newifaddr) {
-                       mutex_enter(&in_ifaddr_lock);
-                       LIST_REMOVE(ia, ia_hash);
-                       IN_ADDRHASH_WRITER_REMOVE(ia);
-                       mutex_exit(&in_ifaddr_lock);
-#ifdef NET_MPSAFE
-                       pserialize_perform(in_ifaddrhash_psz);
-#endif
-                       IN_ADDRHASH_ENTRY_DESTROY(ia);
+                       in_addrhash_remove(ia);
                        need_reinsert = true;
                }
                error = in_ifinit(ifp, ia, satocsin(ifreq_getaddr(cmd, ifr)),
@@ -619,14 +615,7 @@
                ia->ia_sockmask = *satocsin(ifreq_getaddr(cmd, ifr));
                ia->ia_subnetmask = ia->ia_sockmask.sin_addr.s_addr;
                if (!newifaddr) {
-                       mutex_enter(&in_ifaddr_lock);
-                       LIST_REMOVE(ia, ia_hash);
-                       IN_ADDRHASH_WRITER_REMOVE(ia);
-                       mutex_exit(&in_ifaddr_lock);
-#ifdef NET_MPSAFE
-                       pserialize_perform(in_ifaddrhash_psz);
-#endif
-                       IN_ADDRHASH_ENTRY_DESTROY(ia);
+                       in_addrhash_remove(ia);
                        need_reinsert = true;
                }
                error = in_ifinit(ifp, ia, NULL, NULL, 0);
@@ -649,14 +638,7 @@
                if (ifra->ifra_addr.sin_family == AF_INET &&
                    (hostIsNew || maskIsNew)) {
                        if (!newifaddr) {
-                               mutex_enter(&in_ifaddr_lock);
-                               LIST_REMOVE(ia, ia_hash);
-                               IN_ADDRHASH_WRITER_REMOVE(ia);
-                               mutex_exit(&in_ifaddr_lock);
-#ifdef NET_MPSAFE
-                               pserialize_perform(in_ifaddrhash_psz);
-#endif
-                               IN_ADDRHASH_ENTRY_DESTROY(ia);
+                               in_addrhash_remove(ia);
                                need_reinsert = true;
                        }
                        error = in_ifinit(ifp, ia, &ifra->ifra_addr,
@@ -715,17 +697,10 @@
                mutex_enter(&in_ifaddr_lock);
                TAILQ_INSERT_TAIL(&in_ifaddrhead, ia, ia_list);
                IN_ADDRLIST_WRITER_INSERT_TAIL(ia);
-               LIST_INSERT_HEAD(&IN_IFADDR_HASH(ia->ia_addr.sin_addr.s_addr),
-                   ia, ia_hash);
-               IN_ADDRHASH_WRITER_INSERT_HEAD(ia);
+               in_addrhash_insert_locked(ia);
                mutex_exit(&in_ifaddr_lock);
        } else if (need_reinsert) {
-               mutex_enter(&in_ifaddr_lock);
-               LIST_INSERT_HEAD(&IN_IFADDR_HASH(ia->ia_addr.sin_addr.s_addr),
-                   ia, ia_hash);
-               IN_ADDRHASH_ENTRY_INIT(ia);
-               IN_ADDRHASH_WRITER_INSERT_HEAD(ia);
-               mutex_exit(&in_ifaddr_lock);
+               in_addrhash_insert(ia);
        }
 
        if (error == 0) {
@@ -851,8 +826,7 @@
        in_scrubaddr(ia);
 
        mutex_enter(&in_ifaddr_lock);
-       LIST_REMOVE(ia, ia_hash);
-       IN_ADDRHASH_WRITER_REMOVE(ia);
+       in_addrhash_remove_locked(ia);
        TAILQ_REMOVE(&in_ifaddrhead, ia, ia_list);
        IN_ADDRLIST_WRITER_REMOVE(ia);
        ifa_remove(ifp, &ia->ia_ifa);
@@ -867,6 +841,50 @@
        in_setmaxmtu();
 }
 
+static void
+in_addrhash_insert_locked(struct in_ifaddr *ia)
+{
+
+       KASSERT(mutex_owned(&in_ifaddr_lock));
+
+       LIST_INSERT_HEAD(&IN_IFADDR_HASH(ia->ia_addr.sin_addr.s_addr), ia,
+           ia_hash);
+       IN_ADDRHASH_ENTRY_INIT(ia);
+       IN_ADDRHASH_WRITER_INSERT_HEAD(ia);
+}
+
+void
+in_addrhash_insert(struct in_ifaddr *ia)
+{
+
+       mutex_enter(&in_ifaddr_lock);
+       in_addrhash_insert_locked(ia);
+       mutex_exit(&in_ifaddr_lock);
+}
+
+static void
+in_addrhash_remove_locked(struct in_ifaddr *ia)
+{
+
+       KASSERT(mutex_owned(&in_ifaddr_lock));
+
+       LIST_REMOVE(ia, ia_hash);
+       IN_ADDRHASH_WRITER_REMOVE(ia);
+}
+
+void
+in_addrhash_remove(struct in_ifaddr *ia)
+{
+
+       mutex_enter(&in_ifaddr_lock);
+       in_addrhash_remove_locked(ia);
+       mutex_exit(&in_ifaddr_lock);
+#ifdef NET_MPSAFE
+       pserialize_perform(in_ifaddrhash_psz);
+#endif
+       IN_ADDRHASH_ENTRY_DESTROY(ia);
+}
+
 void
 in_purgeif(struct ifnet *ifp)          /* MUST be called at splsoftnet() */
 {
diff -r 9bd0b1ba19e0 -r bdfe1085d0e6 sys/netinet/in_var.h
--- a/sys/netinet/in_var.h      Tue Dec 06 06:41:14 2016 +0000
+++ b/sys/netinet/in_var.h      Tue Dec 06 07:01:47 2016 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: in_var.h,v 1.89 2016/11/18 10:38:55 knakahara Exp $    */
+/*     $NetBSD: in_var.h,v 1.90 2016/12/06 07:01:47 knakahara Exp $    */
 
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -420,6 +420,8 @@
 int    in_control(struct socket *, u_long, void *, struct ifnet *);
 void   in_purgeaddr(struct ifaddr *);
 void   in_purgeif(struct ifnet *);
+void   in_addrhash_insert(struct in_ifaddr *);
+void   in_addrhash_remove(struct in_ifaddr *);
 int    ipflow_fastforward(struct mbuf *);
 
 struct ipid_state;



Home | Main Index | Thread Index | Old Index