[BACK]Return to if.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / net

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/net/if.c between version 1.394 and 1.394.2.18

version 1.394, 2017/06/01 02:45:14 version 1.394.2.18, 2019/09/24 18:27:09
Line 95  __KERNEL_RCSID(0, "$NetBSD$");
Line 95  __KERNEL_RCSID(0, "$NetBSD$");
 #if defined(_KERNEL_OPT)  #if defined(_KERNEL_OPT)
 #include "opt_inet.h"  #include "opt_inet.h"
 #include "opt_ipsec.h"  #include "opt_ipsec.h"
   
 #include "opt_atalk.h"  #include "opt_atalk.h"
 #include "opt_natm.h"  #include "opt_natm.h"
 #include "opt_wlan.h"  #include "opt_wlan.h"
 #include "opt_net_mpsafe.h"  #include "opt_net_mpsafe.h"
   #include "opt_mrouting.h"
 #endif  #endif
   
 #include <sys/param.h>  #include <sys/param.h>
Line 209  static int if_transmit(struct ifnet *, s
Line 209  static int if_transmit(struct ifnet *, s
 static int if_clone_create(const char *);  static int if_clone_create(const char *);
 static int if_clone_destroy(const char *);  static int if_clone_destroy(const char *);
 static void if_link_state_change_si(void *);  static void if_link_state_change_si(void *);
   static void if_up_locked(struct ifnet *);
   static void _if_down(struct ifnet *);
   static void if_down_deactivated(struct ifnet *);
   
 struct if_percpuq {  struct if_percpuq {
         struct ifnet    *ipq_ifp;          struct ifnet    *ipq_ifp;
Line 288  void
Line 291  void
 ifinit(void)  ifinit(void)
 {  {
   
         if_sysctl_setup(NULL);  
   
 #if (defined(INET) || defined(INET6))  #if (defined(INET) || defined(INET6))
         encapinit();          encapinit();
 #endif  #endif
Line 308  ifinit(void)
Line 309  ifinit(void)
 void  void
 ifinit1(void)  ifinit1(void)
 {  {
   
   #ifdef NET_MPSAFE
           printf("NET_MPSAFE enabled\n");
   #endif
   
         mutex_init(&if_clone_mtx, MUTEX_DEFAULT, IPL_NONE);          mutex_init(&if_clone_mtx, MUTEX_DEFAULT, IPL_NONE);
   
         TAILQ_INIT(&ifnet_list);          TAILQ_INIT(&ifnet_list);
Line 327  ifinit1(void)
Line 333  ifinit1(void)
 #endif  #endif
 }  }
   
   /* XXX must be after domaininit() */
   void
   ifinit_post(void)
   {
   
           if_sysctl_setup(NULL);
   }
   
 ifnet_t *  ifnet_t *
 if_alloc(u_char type)  if_alloc(u_char type)
 {  {
Line 447  if_dl_create(const struct ifnet *ifp, co
Line 461  if_dl_create(const struct ifnet *ifp, co
         addrlen = ifp->if_addrlen;          addrlen = ifp->if_addrlen;
         socksize = roundup(sockaddr_dl_measure(namelen, addrlen), sizeof(long));          socksize = roundup(sockaddr_dl_measure(namelen, addrlen), sizeof(long));
         ifasize = sizeof(*ifa) + 2 * socksize;          ifasize = sizeof(*ifa) + 2 * socksize;
         ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK|M_ZERO);          ifa = malloc(ifasize, M_IFADDR, M_WAITOK|M_ZERO);
   
         sdl = (struct sockaddr_dl *)(ifa + 1);          sdl = (struct sockaddr_dl *)(ifa + 1);
         mask = (struct sockaddr_dl *)(socksize + (char *)sdl);          mask = (struct sockaddr_dl *)(socksize + (char *)sdl);
   
         sockaddr_dl_init(sdl, socksize, ifp->if_index, ifp->if_type,          sockaddr_dl_init(sdl, socksize, ifp->if_index, ifp->if_type,
             ifp->if_xname, namelen, NULL, addrlen);              ifp->if_xname, namelen, NULL, addrlen);
           mask->sdl_family = AF_LINK;
         mask->sdl_len = sockaddr_dl_measure(namelen, 0);          mask->sdl_len = sockaddr_dl_measure(namelen, 0);
         memset(&mask->sdl_data[0], 0xff, namelen);          memset(&mask->sdl_data[0], 0xff, namelen);
         ifa->ifa_rtrequest = link_rtrequest;          ifa->ifa_rtrequest = link_rtrequest;
Line 670  skip:
Line 685  skip:
  *     ether_ifattach(ifp, enaddr);   *     ether_ifattach(ifp, enaddr);
  *     if_register(ifp);   *     if_register(ifp);
  */   */
 void  int
 if_initialize(ifnet_t *ifp)  if_initialize(ifnet_t *ifp)
 {  {
           int rv = 0;
   
         KASSERT(if_indexlim > 0);          KASSERT(if_indexlim > 0);
         TAILQ_INIT(&ifp->if_addrlist);          TAILQ_INIT(&ifp->if_addrlist);
   
Line 709  if_initialize(ifnet_t *ifp)
Line 726  if_initialize(ifnet_t *ifp)
         IF_AFDATA_LOCK_INIT(ifp);          IF_AFDATA_LOCK_INIT(ifp);
   
         if (if_is_link_state_changeable(ifp)) {          if (if_is_link_state_changeable(ifp)) {
                 ifp->if_link_si = softint_establish(SOFTINT_NET,                  u_int flags = SOFTINT_NET;
                   flags |= if_is_mpsafe(ifp) ? SOFTINT_MPSAFE : 0;
                   ifp->if_link_si = softint_establish(flags,
                     if_link_state_change_si, ifp);                      if_link_state_change_si, ifp);
                 if (ifp->if_link_si == NULL)                  if (ifp->if_link_si == NULL) {
                         panic("%s: softint_establish() failed", __func__);                          rv = ENOMEM;
                           goto fail;
                   }
         }          }
   
         PSLIST_ENTRY_INIT(ifp, if_pslist_entry);          PSLIST_ENTRY_INIT(ifp, if_pslist_entry);
Line 721  if_initialize(ifnet_t *ifp)
Line 742  if_initialize(ifnet_t *ifp)
         ifp->if_ioctl_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE);          ifp->if_ioctl_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE);
         LIST_INIT(&ifp->if_multiaddrs);          LIST_INIT(&ifp->if_multiaddrs);
   
         IFNET_LOCK();          IFNET_GLOBAL_LOCK();
         if_getindex(ifp);          if_getindex(ifp);
         IFNET_UNLOCK();          IFNET_GLOBAL_UNLOCK();
   
           return 0;
   
   fail:
           IF_AFDATA_LOCK_DESTROY(ifp);
   
           pfil_run_ifhooks(if_pfil, PFIL_IFNET_DETACH, ifp);
           (void)pfil_head_destroy(ifp->if_pfil);
   
           IFQ_LOCK_DESTROY(&ifp->if_snd);
   
           return rv;
 }  }
   
 /*  /*
Line 758  if_register(ifnet_t *ifp)
Line 791  if_register(ifnet_t *ifp)
         if (ifp->if_transmit == NULL || ifp->if_transmit == if_nulltransmit)          if (ifp->if_transmit == NULL || ifp->if_transmit == if_nulltransmit)
                 ifp->if_transmit = if_transmit;                  ifp->if_transmit = if_transmit;
   
         IFNET_LOCK();          IFNET_GLOBAL_LOCK();
         TAILQ_INSERT_TAIL(&ifnet_list, ifp, if_list);          TAILQ_INSERT_TAIL(&ifnet_list, ifp, if_list);
         IFNET_WRITER_INSERT_TAIL(ifp);          IFNET_WRITER_INSERT_TAIL(ifp);
         IFNET_UNLOCK();          IFNET_GLOBAL_UNLOCK();
 }  }
   
 /*  /*
Line 811  struct if_percpuq *
Line 844  struct if_percpuq *
 if_percpuq_create(struct ifnet *ifp)  if_percpuq_create(struct ifnet *ifp)
 {  {
         struct if_percpuq *ipq;          struct if_percpuq *ipq;
           u_int flags = SOFTINT_NET;
   
           flags |= if_is_mpsafe(ifp) ? SOFTINT_MPSAFE : 0;
   
         ipq = kmem_zalloc(sizeof(*ipq), KM_SLEEP);          ipq = kmem_zalloc(sizeof(*ipq), KM_SLEEP);
         ipq->ipq_ifp = ifp;          ipq->ipq_ifp = ifp;
         ipq->ipq_si = softint_establish(SOFTINT_NET|SOFTINT_MPSAFE,          ipq->ipq_si = softint_establish(flags, if_percpuq_softint, ipq);
             if_percpuq_softint, ipq);  
         ipq->ipq_ifqs = percpu_alloc(sizeof(struct ifqueue));          ipq->ipq_ifqs = percpu_alloc(sizeof(struct ifqueue));
         percpu_foreach(ipq->ipq_ifqs, &if_percpuq_init_ifq, NULL);          percpu_foreach(ipq->ipq_ifqs, &if_percpuq_init_ifq, NULL);
   
Line 1043  void
Line 1078  void
 if_deferred_start_init(struct ifnet *ifp, void (*func)(struct ifnet *))  if_deferred_start_init(struct ifnet *ifp, void (*func)(struct ifnet *))
 {  {
         struct if_deferred_start *ids;          struct if_deferred_start *ids;
           u_int flags = SOFTINT_NET;
   
           flags |= if_is_mpsafe(ifp) ? SOFTINT_MPSAFE : 0;
   
         ids = kmem_zalloc(sizeof(*ids), KM_SLEEP);          ids = kmem_zalloc(sizeof(*ids), KM_SLEEP);
         ids->ids_ifp = ifp;          ids->ids_ifp = ifp;
         ids->ids_si = softint_establish(SOFTINT_NET|SOFTINT_MPSAFE,          ids->ids_si = softint_establish(flags, if_deferred_start_softint, ids);
             if_deferred_start_softint, ids);  
         if (func != NULL)          if (func != NULL)
                 ids->ids_if_start = func;                  ids->ids_if_start = func;
         else          else
Line 1094  if_input(struct ifnet *ifp, struct mbuf 
Line 1131  if_input(struct ifnet *ifp, struct mbuf 
  * migrate softint-based if_input without much changes. If you don't   * migrate softint-based if_input without much changes. If you don't
  * want to enable it, use if_initialize instead.   * want to enable it, use if_initialize instead.
  */   */
 void  int
 if_attach(ifnet_t *ifp)  if_attach(ifnet_t *ifp)
 {  {
           int rv;
   
           rv = if_initialize(ifp);
           if (rv != 0)
                   return rv;
   
         if_initialize(ifp);  
         ifp->if_percpuq = if_percpuq_create(ifp);          ifp->if_percpuq = if_percpuq_create(ifp);
         if_register(ifp);          if_register(ifp);
   
           return 0;
 }  }
   
 void  void
Line 1284  if_detach(struct ifnet *ifp)
Line 1327  if_detach(struct ifnet *ifp)
         s = splnet();          s = splnet();
   
         sysctl_teardown(&ifp->if_sysctl_log);          sysctl_teardown(&ifp->if_sysctl_log);
         mutex_enter(ifp->if_ioctl_lock);          IFNET_LOCK(ifp);
         if_deactivate(ifp);          if_deactivate(ifp);
         mutex_exit(ifp->if_ioctl_lock);          IFNET_UNLOCK(ifp);
   
         IFNET_LOCK();  
         ifindex2ifnet[ifp->if_index] = NULL;  
         TAILQ_REMOVE(&ifnet_list, ifp, if_list);  
         IFNET_WRITER_REMOVE(ifp);  
         pserialize_perform(ifnet_psz);  
         IFNET_UNLOCK();  
   
         /* Wait for all readers to drain before freeing.  */  
         psref_target_destroy(&ifp->if_psref, ifnet_psref_class);  
         PSLIST_ENTRY_DESTROY(ifp, if_pslist_entry);  
   
         mutex_obj_free(ifp->if_ioctl_lock);  
         ifp->if_ioctl_lock = NULL;  
   
         if (ifp->if_slowtimo != NULL && ifp->if_slowtimo_ch != NULL) {          if (ifp->if_slowtimo != NULL && ifp->if_slowtimo_ch != NULL) {
                 ifp->if_slowtimo = NULL;                  ifp->if_slowtimo = NULL;
Line 1313  if_detach(struct ifnet *ifp)
Line 1342  if_detach(struct ifnet *ifp)
         /*          /*
          * Do an if_down() to give protocols a chance to do something.           * Do an if_down() to give protocols a chance to do something.
          */           */
         if_down(ifp);          if_down_deactivated(ifp);
   
 #ifdef ALTQ  #ifdef ALTQ
         if (ALTQ_IS_ENABLED(&ifp->if_snd))          if (ALTQ_IS_ENABLED(&ifp->if_snd))
Line 1322  if_detach(struct ifnet *ifp)
Line 1351  if_detach(struct ifnet *ifp)
                 altq_detach(&ifp->if_snd);                  altq_detach(&ifp->if_snd);
 #endif  #endif
   
         mutex_obj_free(ifp->if_snd.ifq_lock);  
   
 #if NCARP > 0  #if NCARP > 0
         /* Remove the interface from any carp group it is a part of.  */          /* Remove the interface from any carp group it is a part of.  */
         if (ifp->if_carp != NULL && ifp->if_type != IFT_CARP)          if (ifp->if_carp != NULL && ifp->if_type != IFT_CARP)
Line 1346  if_detach(struct ifnet *ifp)
Line 1373  if_detach(struct ifnet *ifp)
 again:  again:
         /*          /*
          * At this point, no other one tries to remove ifa in the list,           * At this point, no other one tries to remove ifa in the list,
          * so we don't need to take a lock or psref.           * so we don't need to take a lock or psref.  Avoid using
            * IFADDR_READER_FOREACH to pass over an inspection of contract
            * violations of pserialize.
          */           */
         IFADDR_READER_FOREACH(ifa, ifp) {          IFADDR_WRITER_FOREACH(ifa, ifp) {
                 family = ifa->ifa_addr->sa_family;                  family = ifa->ifa_addr->sa_family;
 #ifdef IFAREF_DEBUG  #ifdef IFAREF_DEBUG
                 printf("if_detach: ifaddr %p, family %d, refcnt %d\n",                  printf("if_detach: ifaddr %p, family %d, refcnt %d\n",
Line 1425  again:
Line 1454  again:
                 }                  }
         }          }
   
           /* Wait for all readers to drain before freeing.  */
           IFNET_GLOBAL_LOCK();
           ifindex2ifnet[ifp->if_index] = NULL;
           TAILQ_REMOVE(&ifnet_list, ifp, if_list);
           IFNET_WRITER_REMOVE(ifp);
           pserialize_perform(ifnet_psz);
           IFNET_GLOBAL_UNLOCK();
   
           psref_target_destroy(&ifp->if_psref, ifnet_psref_class);
           PSLIST_ENTRY_DESTROY(ifp, if_pslist_entry);
   
         pfil_run_ifhooks(if_pfil, PFIL_IFNET_DETACH, ifp);          pfil_run_ifhooks(if_pfil, PFIL_IFNET_DETACH, ifp);
         (void)pfil_head_destroy(ifp->if_pfil);          (void)pfil_head_destroy(ifp->if_pfil);
   
Line 1471  again:
Line 1511  again:
                 ifp->if_percpuq = NULL;                  ifp->if_percpuq = NULL;
         }          }
   
           mutex_obj_free(ifp->if_ioctl_lock);
           ifp->if_ioctl_lock = NULL;
           mutex_obj_free(ifp->if_snd.ifq_lock);
   
         splx(s);          splx(s);
   
 #ifdef IFAREF_DEBUG  #ifdef IFAREF_DEBUG
Line 1557  if_clone_destroy(const char *name)
Line 1601  if_clone_destroy(const char *name)
         struct if_clone *ifc;          struct if_clone *ifc;
         struct ifnet *ifp;          struct ifnet *ifp;
         struct psref psref;          struct psref psref;
           int error;
           int (*if_ioctl)(struct ifnet *, u_long, void *);
   
         KASSERT(mutex_owned(&if_clone_mtx));          KASSERT(mutex_owned(&if_clone_mtx));
   
Line 1572  if_clone_destroy(const char *name)
Line 1618  if_clone_destroy(const char *name)
                 return ENXIO;                  return ENXIO;
   
         /* We have to disable ioctls here */          /* We have to disable ioctls here */
         mutex_enter(ifp->if_ioctl_lock);          IFNET_LOCK(ifp);
           if_ioctl = ifp->if_ioctl;
         ifp->if_ioctl = if_nullioctl;          ifp->if_ioctl = if_nullioctl;
         mutex_exit(ifp->if_ioctl_lock);          IFNET_UNLOCK(ifp);
   
         /*          /*
          * We cannot call ifc_destroy with holding ifp.           * We cannot call ifc_destroy with holding ifp.
Line 1582  if_clone_destroy(const char *name)
Line 1629  if_clone_destroy(const char *name)
          */           */
         if_put(ifp, &psref);          if_put(ifp, &psref);
   
         return (*ifc->ifc_destroy)(ifp);          error = (*ifc->ifc_destroy)(ifp);
   
           if (error != 0) {
                   /* We have to restore if_ioctl on error */
                   IFNET_LOCK(ifp);
                   ifp->if_ioctl = if_ioctl;
                   IFNET_UNLOCK(ifp);
           }
   
           return error;
 }  }
   
 static bool  static bool
Line 1733  ifa_psref_init(struct ifaddr *ifa)
Line 1789  ifa_psref_init(struct ifaddr *ifa)
 void  void
 ifaref(struct ifaddr *ifa)  ifaref(struct ifaddr *ifa)
 {  {
         KASSERT(!ISSET(ifa->ifa_flags, IFA_DESTROYING));  
         ifa->ifa_refcnt++;          atomic_inc_uint(&ifa->ifa_refcnt);
 }  }
   
 void  void
Line 1743  ifafree(struct ifaddr *ifa)
Line 1799  ifafree(struct ifaddr *ifa)
         KASSERT(ifa != NULL);          KASSERT(ifa != NULL);
         KASSERT(ifa->ifa_refcnt > 0);          KASSERT(ifa->ifa_refcnt > 0);
   
         if (--ifa->ifa_refcnt == 0) {          if (atomic_dec_uint_nv(&ifa->ifa_refcnt) == 0) {
                 free(ifa, M_IFADDR);                  free(ifa, M_IFADDR);
         }          }
 }  }
Line 1761  ifa_insert(struct ifnet *ifp, struct ifa
Line 1817  ifa_insert(struct ifnet *ifp, struct ifa
   
         ifa->ifa_ifp = ifp;          ifa->ifa_ifp = ifp;
   
         IFNET_LOCK();          /*
            * Check MP-safety for IFEF_MPSAFE drivers.
            * Check !IFF_RUNNING for initialization routines that normally don't
            * take IFNET_LOCK but it's safe because there is no competitor.
            * XXX there are false positive cases because IFF_RUNNING can be off on
            * if_stop.
            */
           KASSERT(!if_is_mpsafe(ifp) || !ISSET(ifp->if_flags, IFF_RUNNING) ||
               IFNET_LOCKED(ifp));
   
         TAILQ_INSERT_TAIL(&ifp->if_addrlist, ifa, ifa_list);          TAILQ_INSERT_TAIL(&ifp->if_addrlist, ifa, ifa_list);
         IFADDR_ENTRY_INIT(ifa);          IFADDR_ENTRY_INIT(ifa);
         IFADDR_WRITER_INSERT_TAIL(ifp, ifa);          IFADDR_WRITER_INSERT_TAIL(ifp, ifa);
         IFNET_UNLOCK();  
   
         ifaref(ifa);          ifaref(ifa);
 }  }
Line 1775  ifa_remove(struct ifnet *ifp, struct ifa
Line 1839  ifa_remove(struct ifnet *ifp, struct ifa
 {  {
   
         KASSERT(ifa->ifa_ifp == ifp);          KASSERT(ifa->ifa_ifp == ifp);
           /*
            * Check MP-safety for IFEF_MPSAFE drivers.
            * if_is_deactivated indicates ifa_remove is called form if_detach
            * where is safe even if IFNET_LOCK isn't held.
            */
           KASSERT(!if_is_mpsafe(ifp) || if_is_deactivated(ifp) || IFNET_LOCKED(ifp));
   
         IFNET_LOCK();  
         TAILQ_REMOVE(&ifp->if_addrlist, ifa, ifa_list);          TAILQ_REMOVE(&ifp->if_addrlist, ifa, ifa_list);
         IFADDR_WRITER_REMOVE(ifa);          IFADDR_WRITER_REMOVE(ifa);
 #ifdef NET_MPSAFE  #ifdef NET_MPSAFE
           IFNET_GLOBAL_LOCK();
         pserialize_perform(ifnet_psz);          pserialize_perform(ifnet_psz);
           IFNET_GLOBAL_UNLOCK();
 #endif  #endif
         IFNET_UNLOCK();  
   
 #ifdef NET_MPSAFE  #ifdef NET_MPSAFE
         psref_target_destroy(&ifa->ifa_psref, ifa_psref_class);          psref_target_destroy(&ifa->ifa_psref, ifa_psref_class);
Line 2119  link_rtrequest(int cmd, struct rtentry *
Line 2189  link_rtrequest(int cmd, struct rtentry *
         struct psref psref;          struct psref psref;
   
         if (cmd != RTM_ADD || (ifa = rt->rt_ifa) == NULL ||          if (cmd != RTM_ADD || (ifa = rt->rt_ifa) == NULL ||
             (ifp = ifa->ifa_ifp) == NULL || (dst = rt_getkey(rt)) == NULL)              (ifp = ifa->ifa_ifp) == NULL || (dst = rt_getkey(rt)) == NULL ||
               ISSET(info->rti_flags, RTF_DONTCHANGEIFA))
                 return;                  return;
         if ((ifa = ifaof_ifpforaddr_psref(dst, ifp, &psref)) != NULL) {          if ((ifa = ifaof_ifpforaddr_psref(dst, ifp, &psref)) != NULL) {
                 rt_replace_ifa(rt, ifa);                  rt_replace_ifa(rt, ifa);
Line 2162  link_rtrequest(int cmd, struct rtentry *
Line 2233  link_rtrequest(int cmd, struct rtentry *
                 if (LQ_ITEM((q), (i)) == LINK_STATE_UNSET)                    \                  if (LQ_ITEM((q), (i)) == LINK_STATE_UNSET)                    \
                         break;                                                \                          break;                                                \
         }          }
   
   /*
    * XXX reusing (ifp)->if_snd->ifq_lock rather than having another spin mutex
    * for each ifnet.  It doesn't matter because:
    * - if IFEF_MPSAFE is enabled, if_snd isn't used and lock contentions on
    *   ifq_lock don't happen
    * - if IFEF_MPSAFE is disabled, there is no lock contention on ifq_lock
    *   because if_snd, if_link_state_change and if_link_state_change_softint
    *   are all called with KERNEL_LOCK
    */
   #define IF_LINK_STATE_CHANGE_LOCK(ifp)          \
           mutex_enter((ifp)->if_snd.ifq_lock)
   #define IF_LINK_STATE_CHANGE_UNLOCK(ifp)        \
           mutex_exit((ifp)->if_snd.ifq_lock)
   
 /*  /*
  * Handle a change in the interface link state and   * Handle a change in the interface link state and
  * queue notifications.   * queue notifications.
Line 2169  link_rtrequest(int cmd, struct rtentry *
Line 2255  link_rtrequest(int cmd, struct rtentry *
 void  void
 if_link_state_change(struct ifnet *ifp, int link_state)  if_link_state_change(struct ifnet *ifp, int link_state)
 {  {
         int s, idx;          int idx;
   
         KASSERTMSG(if_is_link_state_changeable(ifp),          KASSERTMSG(if_is_link_state_changeable(ifp),
             "%s: IFEF_NO_LINK_STATE_CHANGE must not be set, but if_extflags=0x%x",              "%s: IFEF_NO_LINK_STATE_CHANGE must not be set, but if_extflags=0x%x",
Line 2189  if_link_state_change(struct ifnet *ifp, 
Line 2275  if_link_state_change(struct ifnet *ifp, 
                 return;                  return;
         }          }
   
         s = splnet();          IF_LINK_STATE_CHANGE_LOCK(ifp);
   
         /* Find the last unset event in the queue. */          /* Find the last unset event in the queue. */
         LQ_FIND_UNSET(ifp->if_link_queue, idx);          LQ_FIND_UNSET(ifp->if_link_queue, idx);
Line 2233  if_link_state_change(struct ifnet *ifp, 
Line 2319  if_link_state_change(struct ifnet *ifp, 
         softint_schedule(ifp->if_link_si);          softint_schedule(ifp->if_link_si);
   
 out:  out:
         splx(s);          IF_LINK_STATE_CHANGE_UNLOCK(ifp);
 }  }
   
 /*  /*
Line 2244  if_link_state_change_softint(struct ifne
Line 2330  if_link_state_change_softint(struct ifne
 {  {
         struct domain *dp;          struct domain *dp;
         int s = splnet();          int s = splnet();
           bool notify;
   
         KASSERT(!cpu_intr_p());          KASSERT(!cpu_intr_p());
   
           IF_LINK_STATE_CHANGE_LOCK(ifp);
   
         /* Ensure the change is still valid. */          /* Ensure the change is still valid. */
         if (ifp->if_link_state == link_state) {          if (ifp->if_link_state == link_state) {
                   IF_LINK_STATE_CHANGE_UNLOCK(ifp);
                 splx(s);                  splx(s);
                 return;                  return;
         }          }
Line 2272  if_link_state_change_softint(struct ifne
Line 2362  if_link_state_change_softint(struct ifne
          * listeners would have an address and expect it to work right           * listeners would have an address and expect it to work right
          * away.           * away.
          */           */
         if (link_state == LINK_STATE_UP &&          notify = (link_state == LINK_STATE_UP &&
             ifp->if_link_state == LINK_STATE_UNKNOWN)              ifp->if_link_state == LINK_STATE_UNKNOWN);
         {          ifp->if_link_state = link_state;
           /* The following routines may sleep so release the spin mutex */
           IF_LINK_STATE_CHANGE_UNLOCK(ifp);
   
           KERNEL_LOCK_UNLESS_NET_MPSAFE();
           if (notify) {
                 DOMAIN_FOREACH(dp) {                  DOMAIN_FOREACH(dp) {
                         if (dp->dom_if_link_state_change != NULL)                          if (dp->dom_if_link_state_change != NULL)
                                 dp->dom_if_link_state_change(ifp,                                  dp->dom_if_link_state_change(ifp,
Line 2282  if_link_state_change_softint(struct ifne
Line 2377  if_link_state_change_softint(struct ifne
                 }                  }
         }          }
   
         ifp->if_link_state = link_state;  
   
         /* Notify that the link state has changed. */          /* Notify that the link state has changed. */
         rt_ifmsg(ifp);          rt_ifmsg(ifp);
   
Line 2296  if_link_state_change_softint(struct ifne
Line 2389  if_link_state_change_softint(struct ifne
                 if (dp->dom_if_link_state_change != NULL)                  if (dp->dom_if_link_state_change != NULL)
                         dp->dom_if_link_state_change(ifp, link_state);                          dp->dom_if_link_state_change(ifp, link_state);
         }          }
           KERNEL_UNLOCK_UNLESS_NET_MPSAFE();
         splx(s);          splx(s);
 }  }
   
Line 2308  if_link_state_change_si(void *arg)
Line 2402  if_link_state_change_si(void *arg)
         struct ifnet *ifp = arg;          struct ifnet *ifp = arg;
         int s;          int s;
         uint8_t state;          uint8_t state;
           bool schedule;
   
 #ifndef NET_MPSAFE          SOFTNET_KERNEL_LOCK_UNLESS_NET_MPSAFE();
         mutex_enter(softnet_lock);  
         KERNEL_LOCK(1, NULL);  
 #endif  
         s = splnet();          s = splnet();
   
         /* Pop a link state change from the queue and process it. */          /* Pop a link state change from the queue and process it. */
           IF_LINK_STATE_CHANGE_LOCK(ifp);
         LQ_POP(ifp->if_link_queue, state);          LQ_POP(ifp->if_link_queue, state);
           IF_LINK_STATE_CHANGE_UNLOCK(ifp);
   
         if_link_state_change_softint(ifp, state);          if_link_state_change_softint(ifp, state);
   
         /* If there is a link state change to come, schedule it. */          /* If there is a link state change to come, schedule it. */
         if (LQ_ITEM(ifp->if_link_queue, 0) != LINK_STATE_UNSET)          IF_LINK_STATE_CHANGE_LOCK(ifp);
           schedule = (LQ_ITEM(ifp->if_link_queue, 0) != LINK_STATE_UNSET);
           IF_LINK_STATE_CHANGE_UNLOCK(ifp);
           if (schedule)
                 softint_schedule(ifp->if_link_si);                  softint_schedule(ifp->if_link_si);
   
         splx(s);          splx(s);
 #ifndef NET_MPSAFE          SOFTNET_KERNEL_UNLOCK_UNLESS_NET_MPSAFE();
         KERNEL_UNLOCK_ONE(NULL);  
         mutex_exit(softnet_lock);  
 #endif  
 }  }
   
 /*  /*
Line 2349  p2p_rtrequest(int req, struct rtentry *r
Line 2444  p2p_rtrequest(int req, struct rtentry *r
   
                 rt->rt_ifp = lo0ifp;                  rt->rt_ifp = lo0ifp;
   
                   if (ISSET(info->rti_flags, RTF_DONTCHANGEIFA))
                           break;
   
                 IFADDR_READER_FOREACH(ifa, ifp) {                  IFADDR_READER_FOREACH(ifa, ifp) {
                         if (equal(rt_getkey(rt), ifa->ifa_addr))                          if (equal(rt_getkey(rt), ifa->ifa_addr))
                                 break;                                  break;
Line 2382  p2p_rtrequest(int req, struct rtentry *r
Line 2480  p2p_rtrequest(int req, struct rtentry *r
         pserialize_read_exit(s);          pserialize_read_exit(s);
 }  }
   
 /*  static void
  * Mark an interface down and notify protocols of  _if_down(struct ifnet *ifp)
  * the transition.  
  * NOTE: must be called at splsoftnet or equivalent.  
  */  
 void  
 if_down(struct ifnet *ifp)  
 {  {
         struct ifaddr *ifa;          struct ifaddr *ifa;
         struct domain *dp;          struct domain *dp;
Line 2424  if_down(struct ifnet *ifp)
Line 2517  if_down(struct ifnet *ifp)
         }          }
 }  }
   
   static void
   if_down_deactivated(struct ifnet *ifp)
   {
   
           KASSERT(if_is_deactivated(ifp));
           _if_down(ifp);
   }
   
   void
   if_down_locked(struct ifnet *ifp)
   {
   
           KASSERT(IFNET_LOCKED(ifp));
           _if_down(ifp);
   }
   
 /*  /*
  * Mark an interface up and notify protocols of   * Mark an interface down and notify protocols of
  * the transition.   * the transition.
  * NOTE: must be called at splsoftnet or equivalent.   * NOTE: must be called at splsoftnet or equivalent.
  */   */
 void  void
 if_up(struct ifnet *ifp)  if_down(struct ifnet *ifp)
   {
   
           IFNET_LOCK(ifp);
           if_down_locked(ifp);
           IFNET_UNLOCK(ifp);
   }
   
   /*
    * Must be called with holding if_ioctl_lock.
    */
   static void
   if_up_locked(struct ifnet *ifp)
 {  {
 #ifdef notyet  #ifdef notyet
         struct ifaddr *ifa;          struct ifaddr *ifa;
 #endif  #endif
         struct domain *dp;          struct domain *dp;
   
           KASSERT(IFNET_LOCKED(ifp));
   
           KASSERT(!if_is_deactivated(ifp));
         ifp->if_flags |= IFF_UP;          ifp->if_flags |= IFF_UP;
         nanotime(&ifp->if_lastchange);          nanotime(&ifp->if_lastchange);
 #ifdef notyet  #ifdef notyet
Line 2482  if_slowtimo(void *arg)
Line 2606  if_slowtimo(void *arg)
 }  }
   
 /*  /*
    * Mark an interface up and notify protocols of
    * the transition.
    * NOTE: must be called at splsoftnet or equivalent.
    */
   void
   if_up(struct ifnet *ifp)
   {
   
           IFNET_LOCK(ifp);
           if_up_locked(ifp);
           IFNET_UNLOCK(ifp);
   }
   
   /*
  * Set/clear promiscuous mode on interface ifp based on the truth value   * Set/clear promiscuous mode on interface ifp based on the truth value
  * of pswitch.  The calls are reference counted so that only the first   * of pswitch.  The calls are reference counted so that only the first
  * "on" request actually has an effect, as does the final "off" request.   * "on" request actually has an effect, as does the final "off" request.
  * Results are undefined if the "off" and "on" requests are not matched.   * Results are undefined if the "off" and "on" requests are not matched.
  */   */
 int  int
 ifpromisc(struct ifnet *ifp, int pswitch)  ifpromisc_locked(struct ifnet *ifp, int pswitch)
 {  {
         int pcount, ret;          int pcount, ret = 0;
         short nflags;          short nflags;
   
           KASSERT(IFNET_LOCKED(ifp));
   
         pcount = ifp->if_pcount;          pcount = ifp->if_pcount;
         if (pswitch) {          if (pswitch) {
                 /*                  /*
Line 2501  ifpromisc(struct ifnet *ifp, int pswitch
Line 2641  ifpromisc(struct ifnet *ifp, int pswitch
                  * consult IFF_PROMISC when it is brought up.                   * consult IFF_PROMISC when it is brought up.
                  */                   */
                 if (ifp->if_pcount++ != 0)                  if (ifp->if_pcount++ != 0)
                         return 0;                          goto out;
                 nflags = ifp->if_flags | IFF_PROMISC;                  nflags = ifp->if_flags | IFF_PROMISC;
         } else {          } else {
                 if (--ifp->if_pcount > 0)                  if (--ifp->if_pcount > 0)
                         return 0;                          goto out;
                 nflags = ifp->if_flags & ~IFF_PROMISC;                  nflags = ifp->if_flags & ~IFF_PROMISC;
         }          }
         ret = if_flags_set(ifp, nflags);          ret = if_flags_set(ifp, nflags);
Line 2513  ifpromisc(struct ifnet *ifp, int pswitch
Line 2653  ifpromisc(struct ifnet *ifp, int pswitch
         if (ret != 0) {          if (ret != 0) {
                 ifp->if_pcount = pcount;                  ifp->if_pcount = pcount;
         }          }
   out:
         return ret;          return ret;
 }  }
   
   int
   ifpromisc(struct ifnet *ifp, int pswitch)
   {
           int e;
   
           IFNET_LOCK(ifp);
           e = ifpromisc_locked(ifp, pswitch);
           IFNET_UNLOCK(ifp);
   
           return e;
   }
   
 /*  /*
  * Map interface name to   * Map interface name to
  * interface structure pointer.   * interface structure pointer.
Line 2599  out:
Line 2752  out:
 }  }
   
 /*  /*
  * Release a reference of an ifnet object given by if_get or   * Release a reference of an ifnet object given by if_get, if_get_byindex
  * if_get_byindex.   * or if_get_bylla.
  */   */
 void  void
 if_put(const struct ifnet *ifp, struct psref *psref)  if_put(const struct ifnet *ifp, struct psref *psref)
Line 2612  if_put(const struct ifnet *ifp, struct p
Line 2765  if_put(const struct ifnet *ifp, struct p
         psref_release(psref, &ifp->if_psref, ifnet_psref_class);          psref_release(psref, &ifp->if_psref, ifnet_psref_class);
 }  }
   
   /*
    * Return ifp having idx. Return NULL if not found.  Normally if_byindex
    * should be used.
    */
   ifnet_t *
   _if_byindex(u_int idx)
   {
   
           return (__predict_true(idx < if_indexlim)) ? ifindex2ifnet[idx] : NULL;
   }
   
   /*
    * Return ifp having idx. Return NULL if not found or the found ifp is
    * already deactivated.
    */
 ifnet_t *  ifnet_t *
 if_byindex(u_int idx)  if_byindex(u_int idx)
 {  {
         ifnet_t *ifp;          ifnet_t *ifp;
   
         ifp = (__predict_true(idx < if_indexlim)) ? ifindex2ifnet[idx] : NULL;          ifp = _if_byindex(idx);
         if (ifp != NULL && if_is_deactivated(ifp))          if (ifp != NULL && if_is_deactivated(ifp))
                 ifp = NULL;                  ifp = NULL;
         return ifp;          return ifp;
Line 2643  if_get_byindex(u_int idx, struct psref *
Line 2811  if_get_byindex(u_int idx, struct psref *
         return ifp;          return ifp;
 }  }
   
   ifnet_t *
   if_get_bylla(const void *lla, unsigned char lla_len, struct psref *psref)
   {
           ifnet_t *ifp;
           int s;
   
           s = pserialize_read_enter();
           IFNET_READER_FOREACH(ifp) {
                   if (if_is_deactivated(ifp))
                           continue;
                   if (ifp->if_addrlen != lla_len)
                           continue;
                   if (memcmp(lla, CLLADDR(ifp->if_sadl), lla_len) == 0) {
                           psref_acquire(psref, &ifp->if_psref,
                               ifnet_psref_class);
                           break;
                   }
           }
           pserialize_read_exit(s);
   
           return ifp;
   }
   
 /*  /*
  * Note that it's safe only if the passed ifp is guaranteed to not be freed,   * Note that it's safe only if the passed ifp is guaranteed to not be freed,
  * for example using pserialize or the ifp is already held or some other   * for example using pserialize or the ifp is already held or some other
Line 2663  if_held(struct ifnet *ifp)
Line 2854  if_held(struct ifnet *ifp)
         return psref_held(&ifp->if_psref, ifnet_psref_class);          return psref_held(&ifp->if_psref, ifnet_psref_class);
 }  }
   
   /*
    * Some tunnel interfaces can nest, e.g. IPv4 over IPv4 gif(4) tunnel over IPv4.
    * Check the tunnel nesting count.
    * Return > 0, if tunnel nesting count is more than limit.
    * Return 0, if tunnel nesting count is equal or less than limit.
    */
   int
   if_tunnel_check_nesting(struct ifnet *ifp, struct mbuf *m, int limit)
   {
           struct m_tag *mtag;
           int *count;
   
           mtag = m_tag_find(m, PACKET_TAG_TUNNEL_INFO, NULL);
           if (mtag != NULL) {
                   count = (int *)(mtag + 1);
                   if (++(*count) > limit) {
                           log(LOG_NOTICE,
                               "%s: recursively called too many times(%d)\n",
                               ifp->if_xname, *count);
                           return EIO;
                   }
           } else {
                   mtag = m_tag_get(PACKET_TAG_TUNNEL_INFO, sizeof(*count),
                       M_NOWAIT);
                   if (mtag != NULL) {
                           m_tag_prepend(m, mtag);
                           count = (int *)(mtag + 1);
                           *count = 0;
                   } else {
                           log(LOG_DEBUG,
                               "%s: m_tag_get() failed, recursion calls are not prevented.\n",
                               ifp->if_xname);
                   }
           }
   
           return 0;
   }
   
   static void
   if_tunnel_ro_init_pc(void *p, void *arg __unused, struct cpu_info *ci __unused)
   {
           struct tunnel_ro *tro = p;
   
           tro->tr_ro = kmem_zalloc(sizeof(*tro->tr_ro), KM_SLEEP);
           tro->tr_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NONE);
   }
   
   percpu_t *
   if_tunnel_alloc_ro_percpu(void)
   {
           percpu_t *ro_percpu;
   
           ro_percpu = percpu_alloc(sizeof(struct tunnel_ro));
           percpu_foreach(ro_percpu, if_tunnel_ro_init_pc, NULL);
   
           return ro_percpu;
   }
   
   static void
   if_tunnel_ro_fini_pc(void *p, void *arg __unused, struct cpu_info *ci __unused)
   {
           struct tunnel_ro *tro = p;
   
           rtcache_free(tro->tr_ro);
           kmem_free(tro->tr_ro, sizeof(*tro->tr_ro));
   
           mutex_obj_free(tro->tr_lock);
   }
   
   void
   if_tunnel_free_ro_percpu(percpu_t *ro_percpu)
   {
   
           percpu_foreach(ro_percpu, if_tunnel_ro_fini_pc, NULL);
           percpu_free(ro_percpu, sizeof(struct tunnel_ro));
   }
   
   
   static void
   if_tunnel_rtcache_free_pc(void *p, void *arg __unused, struct cpu_info *ci __unused)
   {
           struct tunnel_ro *tro = p;
   
           mutex_enter(tro->tr_lock);
           rtcache_free(tro->tr_ro);
           mutex_exit(tro->tr_lock);
   }
   
   void if_tunnel_ro_percpu_rtcache_free(percpu_t *ro_percpu)
   {
   
           percpu_foreach(ro_percpu, if_tunnel_rtcache_free_pc, NULL);
   }
   
   
 /* common */  /* common */
 int  int
Line 2726  ifioctl_common(struct ifnet *ifp, u_long
Line 3011  ifioctl_common(struct ifnet *ifp, u_long
                 return 0;                  return 0;
         case SIOCSIFFLAGS:          case SIOCSIFFLAGS:
                 ifr = data;                  ifr = data;
                   /*
                    * If if_is_mpsafe(ifp), KERNEL_LOCK isn't held here, but if_up
                    * and if_down aren't MP-safe yet, so we must hold the lock.
                    */
                   KERNEL_LOCK_IF_IFP_MPSAFE(ifp);
                 if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {                  if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
                         s = splsoftnet();                          s = splsoftnet();
                         if_down(ifp);                          if_down_locked(ifp);
                         splx(s);                          splx(s);
                 }                  }
                 if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) {                  if (ifr->ifr_flags & IFF_UP && (ifp->if_flags & IFF_UP) == 0) {
                         s = splsoftnet();                          s = splsoftnet();
                         if_up(ifp);                          if_up_locked(ifp);
                         splx(s);                          splx(s);
                 }                  }
                   KERNEL_UNLOCK_IF_IFP_MPSAFE(ifp);
                 ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |                  ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
                         (ifr->ifr_flags &~ IFF_CANTCHANGE);                          (ifr->ifr_flags &~ IFF_CANTCHANGE);
                 break;                  break;
Line 2807  ifioctl_common(struct ifnet *ifp, u_long
Line 3098  ifioctl_common(struct ifnet *ifp, u_long
                  * If the link MTU changed, do network layer specific procedure.                   * If the link MTU changed, do network layer specific procedure.
                  */                   */
 #ifdef INET6  #ifdef INET6
                   KERNEL_LOCK_UNLESS_NET_MPSAFE();
                 if (in6_present)                  if (in6_present)
                         nd6_setmtu(ifp);                          nd6_setmtu(ifp);
                   KERNEL_UNLOCK_UNLESS_NET_MPSAFE();
 #endif  #endif
                 return ENETRESET;                  return ENETRESET;
         default:          default:
Line 2952  doifioctl(struct socket *so, u_long cmd,
Line 3245  doifioctl(struct socket *so, u_long cmd,
                                 return error;                                  return error;
                         }                          }
                 }                  }
                   KERNEL_LOCK_UNLESS_NET_MPSAFE();
                 mutex_enter(&if_clone_mtx);                  mutex_enter(&if_clone_mtx);
                 r = (cmd == SIOCIFCREATE) ?                  r = (cmd == SIOCIFCREATE) ?
                         if_clone_create(ifr->ifr_name) :                          if_clone_create(ifr->ifr_name) :
                         if_clone_destroy(ifr->ifr_name);                          if_clone_destroy(ifr->ifr_name);
                 mutex_exit(&if_clone_mtx);                  mutex_exit(&if_clone_mtx);
                   KERNEL_UNLOCK_UNLESS_NET_MPSAFE();
                 curlwp_bindx(bound);                  curlwp_bindx(bound);
                 return r;                  return r;
   
Line 3014  doifioctl(struct socket *so, u_long cmd,
Line 3309  doifioctl(struct socket *so, u_long cmd,
   
         oif_flags = ifp->if_flags;          oif_flags = ifp->if_flags;
   
         mutex_enter(ifp->if_ioctl_lock);          KERNEL_LOCK_UNLESS_IFP_MPSAFE(ifp);
           IFNET_LOCK(ifp);
   
         error = (*ifp->if_ioctl)(ifp, cmd, data);          error = (*ifp->if_ioctl)(ifp, cmd, data);
         if (error != ENOTTY)          if (error != ENOTTY)
Line 3022  doifioctl(struct socket *so, u_long cmd,
Line 3318  doifioctl(struct socket *so, u_long cmd,
         else if (so->so_proto == NULL)          else if (so->so_proto == NULL)
                 error = EOPNOTSUPP;                  error = EOPNOTSUPP;
         else {          else {
                   KERNEL_LOCK_IF_IFP_MPSAFE(ifp);
 #ifdef COMPAT_OSOCK  #ifdef COMPAT_OSOCK
                 if (vec_compat_ifioctl != NULL)                  if (vec_compat_ifioctl != NULL)
                         error = (*vec_compat_ifioctl)(so, ocmd, cmd, data, l);                          error = (*vec_compat_ifioctl)(so, ocmd, cmd, data, l);
Line 3029  doifioctl(struct socket *so, u_long cmd,
Line 3326  doifioctl(struct socket *so, u_long cmd,
 #endif  #endif
                         error = (*so->so_proto->pr_usrreqs->pr_ioctl)(so,                          error = (*so->so_proto->pr_usrreqs->pr_ioctl)(so,
                             cmd, data, ifp);                              cmd, data, ifp);
                   KERNEL_UNLOCK_IF_IFP_MPSAFE(ifp);
         }          }
   
         if (((oif_flags ^ ifp->if_flags) & IFF_UP) != 0) {          if (((oif_flags ^ ifp->if_flags) & IFF_UP) != 0) {
                 if ((ifp->if_flags & IFF_UP) != 0) {                  if ((ifp->if_flags & IFF_UP) != 0) {
                         int s = splsoftnet();                          int s = splsoftnet();
                         if_up(ifp);                          if_up_locked(ifp);
                         splx(s);                          splx(s);
                 }                  }
         }          }
Line 3043  doifioctl(struct socket *so, u_long cmd,
Line 3341  doifioctl(struct socket *so, u_long cmd,
                 ifreqn2o(oifr, ifr);                  ifreqn2o(oifr, ifr);
 #endif  #endif
   
         mutex_exit(ifp->if_ioctl_lock);          IFNET_UNLOCK(ifp);
           KERNEL_UNLOCK_UNLESS_IFP_MPSAFE(ifp);
 out:  out:
         if_put(ifp, &psref);          if_put(ifp, &psref);
         curlwp_bindx(bound);          curlwp_bindx(bound);
Line 3093  ifconf(u_long cmd, void *data)
Line 3392  ifconf(u_long cmd, void *data)
         int bound;          int bound;
         struct psref psref;          struct psref psref;
   
           memset(&ifr, 0, sizeof(ifr));
         if (docopy) {          if (docopy) {
                 space = ifc->ifc_len;                  space = ifc->ifc_len;
                 ifrp = ifc->ifc_req;                  ifrp = ifc->ifc_req;
Line 3115  ifconf(u_long cmd, void *data)
Line 3415  ifconf(u_long cmd, void *data)
                         memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));                          memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
                         if (!docopy) {                          if (!docopy) {
                                 space += sz;                                  space += sz;
                                 continue;                                  goto next;
                         }                          }
                         if (space >= sz) {                          if (space >= sz) {
                                 error = copyout(&ifr, ifrp, sz);                                  error = copyout(&ifr, ifrp, sz);
Line 3126  ifconf(u_long cmd, void *data)
Line 3426  ifconf(u_long cmd, void *data)
                         }                          }
                 }                  }
   
                   s = pserialize_read_enter();
                 IFADDR_READER_FOREACH(ifa, ifp) {                  IFADDR_READER_FOREACH(ifa, ifp) {
                         struct sockaddr *sa = ifa->ifa_addr;                          struct sockaddr *sa = ifa->ifa_addr;
                         /* all sockaddrs must fit in sockaddr_storage */                          /* all sockaddrs must fit in sockaddr_storage */
Line 3136  ifconf(u_long cmd, void *data)
Line 3437  ifconf(u_long cmd, void *data)
                                 continue;                                  continue;
                         }                          }
                         memcpy(&ifr.ifr_space, sa, sa->sa_len);                          memcpy(&ifr.ifr_space, sa, sa->sa_len);
                           pserialize_read_exit(s);
   
                         if (space >= sz) {                          if (space >= sz) {
                                 error = copyout(&ifr, ifrp, sz);                                  error = copyout(&ifr, ifrp, sz);
                                 if (error != 0)                                  if (error != 0)
                                         goto release_exit;                                          goto release_exit;
                                 ifrp++; space -= sz;                                  ifrp++; space -= sz;
                         }                          }
                           s = pserialize_read_enter();
                 }                  }
                   pserialize_read_exit(s);
   
           next:
                 s = pserialize_read_enter();                  s = pserialize_read_enter();
                 psref_release(&psref, &ifp->if_psref, ifnet_psref_class);                  psref_release(&psref, &ifp->if_psref, ifnet_psref_class);
         }          }
Line 3294  if_addr_init(ifnet_t *ifp, struct ifaddr
Line 3600  if_addr_init(ifnet_t *ifp, struct ifaddr
 {  {
         int rc;          int rc;
   
           KASSERT(IFNET_LOCKED(ifp));
         if (ifp->if_initaddr != NULL)          if (ifp->if_initaddr != NULL)
                 rc = (*ifp->if_initaddr)(ifp, ifa, src);                  rc = (*ifp->if_initaddr)(ifp, ifa, src);
         else if (src ||          else if (src ||
                 /* FIXME: may not hold if_ioctl_lock */  
                  (rc = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ifa)) == ENOTTY)                   (rc = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ifa)) == ENOTTY)
                 rc = (*ifp->if_ioctl)(ifp, SIOCINITIFADDR, ifa);                  rc = (*ifp->if_ioctl)(ifp, SIOCINITIFADDR, ifa);
   
Line 3342  if_flags_set(ifnet_t *ifp, const short f
Line 3648  if_flags_set(ifnet_t *ifp, const short f
 {  {
         int rc;          int rc;
   
           KASSERT(IFNET_LOCKED(ifp));
   
         if (ifp->if_setflags != NULL)          if (ifp->if_setflags != NULL)
                 rc = (*ifp->if_setflags)(ifp, flags);                  rc = (*ifp->if_setflags)(ifp, flags);
         else {          else {
Line 3364  if_flags_set(ifnet_t *ifp, const short f
Line 3672  if_flags_set(ifnet_t *ifp, const short f
                 memset(&ifr, 0, sizeof(ifr));                  memset(&ifr, 0, sizeof(ifr));
   
                 ifr.ifr_flags = flags & ~IFF_CANTCHANGE;                  ifr.ifr_flags = flags & ~IFF_CANTCHANGE;
                 /* FIXME: may not hold if_ioctl_lock */  
                 rc = (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, &ifr);                  rc = (*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, &ifr);
   
                 if (rc != 0 && cantflags != 0)                  if (rc != 0 && cantflags != 0)
Line 3380  if_mcast_op(ifnet_t *ifp, const unsigned
Line 3687  if_mcast_op(ifnet_t *ifp, const unsigned
         int rc;          int rc;
         struct ifreq ifr;          struct ifreq ifr;
   
           /* There remain some paths that don't hold IFNET_LOCK yet */
   #ifdef NET_MPSAFE
           /* CARP and MROUTING still don't deal with the lock yet */
   #if (!defined(NCARP) || (NCARP == 0)) && !defined(MROUTING)
           KASSERT(IFNET_LOCKED(ifp));
   #endif
   #endif
         if (ifp->if_mcastop != NULL)          if (ifp->if_mcastop != NULL)
                 rc = (*ifp->if_mcastop)(ifp, cmd, sa);                  rc = (*ifp->if_mcastop)(ifp, cmd, sa);
         else {          else {

Legend:
Removed from v.1.394  
changed lines
  Added in v.1.394.2.18

CVSweb <webmaster@jp.NetBSD.org>