On Tue, Apr 18, 2023 at 03:15:54PM +0200, Alexander Bluhm wrote:
> On Mon, Apr 17, 2023 at 03:16:36AM +0300, Vitaliy Makkoveev wrote:
> > Index: sys/dev/usb/if_umb.c
> This umb chunk is OK bluhm@
> 
> > Index: sys/net/if.c
> > ===================================================================
> > RCS file: /cvs/src/sys/net/if.c,v
> > retrieving revision 1.688
> > diff -u -p -r1.688 if.c
> > --- sys/net/if.c    8 Apr 2023 13:49:38 -0000       1.688
> > +++ sys/net/if.c    17 Apr 2023 00:09:17 -0000
> > @@ -1409,8 +1409,9 @@ ifa_ifwithaddr(struct sockaddr *addr, u_
> 
> ifa_ifwithdstaddr() is iterating over the same loops.  It should
> be changed together.
> 

Done.

> if_unit() is iterating over if_list.  There should be a NET_LOCK().
> 
>         TAILQ_ENTRY(ifnet) if_list;     /* [K] all struct ifnets are chained 
> */
>         TAILQ_ENTRY(ifaddr) ifa_list;   /* list of addresses for interface */
> 
> Could you put an [N] there?

No. As I said in the "Call sysctl_ifnames()..." thread, we use both
kernel and net locks to protect `if_list'. This means we do
modification with both locks held, but for read only access only one
lock required. We need to do this because some places protected by
kernel lock do `if_list' foreach loops and we can't introduce context
switch. So, I proposed in the "Call sysctl_ifnames()..." thread mark
`if_list'  as [NK] and add "XXXSMP:" comment above `ifnetlist'
definition. I posted the diff to that thread.

I have no objections to mark `ifa_list' as [N].

> 
> Can we put an NET_ASSERT_LOCKED_EXCLUSIVE() in ifa_add() and ifa_del()?
> 

Done.

> > Index: sys/net/rtsock.c
> > ===================================================================
> > RCS file: /cvs/src/sys/net/rtsock.c,v
> > retrieving revision 1.359
> > diff -u -p -r1.359 rtsock.c
> > --- sys/net/rtsock.c        22 Jan 2023 12:05:44 -0000      1.359
> > +++ sys/net/rtsock.c        17 Apr 2023 00:09:17 -0000
> > @@ -2374,18 +2374,18 @@ rt_setsource(unsigned int rtableid, stru
> >             return (EAFNOSUPPORT);
> >     }
> >  
> > -   KERNEL_LOCK();
> > +   NET_LOCK();
> >     /*
> >      * Check if source address is assigned to an interface in the
> >      * same rdomain
> >      */
> >     if ((ifa = ifa_ifwithaddr(src, rtableid)) == NULL) {
> > -           KERNEL_UNLOCK();
> > +           NET_UNLOCK();
> >             return (EINVAL);
> >     }
> >  
> >     error = rtable_setsource(rtableid, src->sa_family, ifa->ifa_addr);
> > -   KERNEL_UNLOCK();
> > +   NET_UNLOCK();
> >  
> >     return (error);
> >  }
> 
> I would perfer to put the NET_LOCK() into the caller.  There are
> two more rtable_setsource() in this function which should be net
> locked.
> 

rtable_setsource(... , NULL) actually doesn't destroy object pointed by
`ar_source', so for this call netlock is not required. However this
optimisation doesn't produce any visible effect, so no objections to 
call rt_setsource() with netlock held.

ok?

Index: sys/dev/usb/if_umb.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/if_umb.c,v
retrieving revision 1.50
diff -u -p -r1.50 if_umb.c
--- sys/dev/usb/if_umb.c        31 Mar 2023 23:53:49 -0000      1.50
+++ sys/dev/usb/if_umb.c        18 Apr 2023 15:45:04 -0000
@@ -1829,6 +1829,7 @@ umb_add_inet_config(struct umb_softc *sc
        default_sin.sin_len = sizeof (default_sin);
 
        memset(&info, 0, sizeof(info));
+       NET_LOCK();
        info.rti_flags = RTF_GATEWAY /* maybe | RTF_STATIC */;
        info.rti_ifa = ifa_ifwithaddr(sintosa(&ifra.ifra_addr),
            ifp->if_rdomain);
@@ -1836,7 +1837,6 @@ umb_add_inet_config(struct umb_softc *sc
        info.rti_info[RTAX_NETMASK] = sintosa(&default_sin);
        info.rti_info[RTAX_GATEWAY] = sintosa(&ifra.ifra_dstaddr);
 
-       NET_LOCK();
        rv = rtrequest(RTM_ADD, &info, 0, &rt, ifp->if_rdomain);
        NET_UNLOCK();
        if (rv) {
@@ -1910,6 +1910,7 @@ umb_add_inet6_config(struct umb_softc *s
        default_sin6.sin6_len = sizeof (default_sin6);
 
        memset(&info, 0, sizeof(info));
+       NET_LOCK();
        info.rti_flags = RTF_GATEWAY /* maybe | RTF_STATIC */;
        info.rti_ifa = ifa_ifwithaddr(sin6tosa(&ifra.ifra_addr),
            ifp->if_rdomain);
@@ -1917,7 +1918,6 @@ umb_add_inet6_config(struct umb_softc *s
        info.rti_info[RTAX_NETMASK] = sin6tosa(&default_sin6);
        info.rti_info[RTAX_GATEWAY] = sin6tosa(&ifra.ifra_dstaddr);
 
-       NET_LOCK();
        rv = rtrequest(RTM_ADD, &info, 0, &rt, ifp->if_rdomain);
        NET_UNLOCK();
        if (rv) {
Index: sys/net/if.c
===================================================================
RCS file: /cvs/src/sys/net/if.c,v
retrieving revision 1.688
diff -u -p -r1.688 if.c
--- sys/net/if.c        8 Apr 2023 13:49:38 -0000       1.688
+++ sys/net/if.c        18 Apr 2023 15:45:04 -0000
@@ -1409,8 +1409,9 @@ ifa_ifwithaddr(struct sockaddr *addr, u_
        struct ifaddr *ifa;
        u_int rdomain;
 
+       NET_ASSERT_LOCKED();
+
        rdomain = rtable_l2(rtableid);
-       KERNEL_LOCK();
        TAILQ_FOREACH(ifp, &ifnetlist, if_list) {
                if (ifp->if_rdomain != rdomain)
                        continue;
@@ -1420,12 +1421,10 @@ ifa_ifwithaddr(struct sockaddr *addr, u_
                                continue;
 
                        if (equal(addr, ifa->ifa_addr)) {
-                               KERNEL_UNLOCK();
                                return (ifa);
                        }
                }
        }
-       KERNEL_UNLOCK();
        return (NULL);
 }
 
@@ -1438,8 +1437,9 @@ ifa_ifwithdstaddr(struct sockaddr *addr,
        struct ifnet *ifp;
        struct ifaddr *ifa;
 
+       NET_ASSERT_LOCKED();
+
        rdomain = rtable_l2(rdomain);
-       KERNEL_LOCK();
        TAILQ_FOREACH(ifp, &ifnetlist, if_list) {
                if (ifp->if_rdomain != rdomain)
                        continue;
@@ -1449,13 +1449,11 @@ ifa_ifwithdstaddr(struct sockaddr *addr,
                                    addr->sa_family || ifa->ifa_dstaddr == NULL)
                                        continue;
                                if (equal(addr, ifa->ifa_dstaddr)) {
-                                       KERNEL_UNLOCK();
                                        return (ifa);
                                }
                        }
                }
        }
-       KERNEL_UNLOCK();
        return (NULL);
 }
 
@@ -3167,12 +3165,14 @@ ifsettso(struct ifnet *ifp, int on)
 void
 ifa_add(struct ifnet *ifp, struct ifaddr *ifa)
 {
+       NET_ASSERT_LOCKED_EXCLUSIVE();
        TAILQ_INSERT_TAIL(&ifp->if_addrlist, ifa, ifa_list);
 }
 
 void
 ifa_del(struct ifnet *ifp, struct ifaddr *ifa)
 {
+       NET_ASSERT_LOCKED_EXCLUSIVE();
        TAILQ_REMOVE(&ifp->if_addrlist, ifa, ifa_list);
 }
 
Index: sys/net/if_var.h
===================================================================
RCS file: /cvs/src/sys/net/if_var.h,v
retrieving revision 1.123
diff -u -p -r1.123 if_var.h
--- sys/net/if_var.h    5 Apr 2023 19:35:23 -0000       1.123
+++ sys/net/if_var.h    18 Apr 2023 15:45:04 -0000
@@ -240,7 +240,8 @@ struct ifaddr {
 #define        ifa_broadaddr   ifa_dstaddr     /* broadcast address interface 
*/
        struct  sockaddr *ifa_netmask;  /* used to determine subnet */
        struct  ifnet *ifa_ifp;         /* back-pointer to interface */
-       TAILQ_ENTRY(ifaddr) ifa_list;   /* list of addresses for interface */
+       TAILQ_ENTRY(ifaddr) ifa_list;   /* [N] list of addresses for
+                                           interface */
        u_int   ifa_flags;              /* interface flags, see below */
        struct  refcnt ifa_refcnt;      /* number of `rt_ifa` references */
        int     ifa_metric;             /* cost of going out this interface */
Index: sys/net/rtsock.c
===================================================================
RCS file: /cvs/src/sys/net/rtsock.c,v
retrieving revision 1.362
diff -u -p -r1.362 rtsock.c
--- sys/net/rtsock.c    18 Apr 2023 09:56:54 -0000      1.362
+++ sys/net/rtsock.c    18 Apr 2023 15:45:04 -0000
@@ -853,8 +853,10 @@ route_output(struct mbuf *m, struct sock
                        error = EINVAL;
                        goto fail;
                }
-               if ((error =
-                   rt_setsource(tableid, info.rti_info[RTAX_IFA])) != 0)
+               NET_LOCK();
+               error = rt_setsource(tableid, info.rti_info[RTAX_IFA]);
+               NET_UNLOCK();
+               if (error)
                        goto fail;
        } else {
                error = rtm_output(rtm, &rt, &info, prio, tableid);
@@ -2350,7 +2352,6 @@ int
 rt_setsource(unsigned int rtableid, struct sockaddr *src)
 {
        struct ifaddr   *ifa;
-       int             error;
        /*
         * If source address is 0.0.0.0 or ::
         * use automatic source selection
@@ -2374,20 +2375,14 @@ rt_setsource(unsigned int rtableid, stru
                return (EAFNOSUPPORT);
        }
 
-       KERNEL_LOCK();
        /*
         * Check if source address is assigned to an interface in the
         * same rdomain
         */
-       if ((ifa = ifa_ifwithaddr(src, rtableid)) == NULL) {
-               KERNEL_UNLOCK();
+       if ((ifa = ifa_ifwithaddr(src, rtableid)) == NULL)
                return (EINVAL);
-       }
 
-       error = rtable_setsource(rtableid, src->sa_family, ifa->ifa_addr);
-       KERNEL_UNLOCK();
-
-       return (error);
+       return rtable_setsource(rtableid, src->sa_family, ifa->ifa_addr);
 }
 
 /*

Reply via email to