[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.354.2.6 and 1.355

version 1.354.2.6, 2017/04/26 02:53:29 version 1.355, 2016/07/22 07:09:40
Line 138  __KERNEL_RCSID(0, "$NetBSD$");
Line 138  __KERNEL_RCSID(0, "$NetBSD$");
 #include <net/pfil.h>  #include <net/pfil.h>
 #include <netinet/in.h>  #include <netinet/in.h>
 #include <netinet/in_var.h>  #include <netinet/in_var.h>
   #ifndef IPSEC
 #include <netinet/ip_encap.h>  #include <netinet/ip_encap.h>
 #include <net/bpf.h>  #endif
   
 #ifdef INET6  #ifdef INET6
 #include <netinet6/in6_var.h>  #include <netinet6/in6_var.h>
Line 174  static size_t   if_indexlim = 0;
Line 175  static size_t   if_indexlim = 0;
 static uint64_t                 index_gen;  static uint64_t                 index_gen;
 /* Mutex to protect the above objects. */  /* Mutex to protect the above objects. */
 kmutex_t                        ifnet_mtx __cacheline_aligned;  kmutex_t                        ifnet_mtx __cacheline_aligned;
 static struct psref_class       *ifnet_psref_class __read_mostly;  struct psref_class              *ifnet_psref_class __read_mostly;
 static pserialize_t             ifnet_psz;  static pserialize_t             ifnet_psz;
   
 static kmutex_t                 if_clone_mtx;  static kmutex_t                 if_clone_mtx;
Line 182  static kmutex_t   if_clone_mtx;
Line 183  static kmutex_t   if_clone_mtx;
 struct ifnet *lo0ifp;  struct ifnet *lo0ifp;
 int     ifqmaxlen = IFQ_MAXLEN;  int     ifqmaxlen = IFQ_MAXLEN;
   
 struct psref_class              *ifa_psref_class __read_mostly;  static int      if_rt_walktree(struct rtentry *, void *);
   
 static int      if_delroute_matcher(struct rtentry *, void *);  
   
 static bool if_is_unit(const char *);  
 static struct if_clone *if_clone_lookup(const char *, int *);  static struct if_clone *if_clone_lookup(const char *, int *);
   
 static LIST_HEAD(, if_clone) if_cloners = LIST_HEAD_INITIALIZER(if_cloners);  static LIST_HEAD(, if_clone) if_cloners = LIST_HEAD_INITIALIZER(if_cloners);
 static int if_cloners_count;  static int if_cloners_count;
   
 /* Packet filtering hook for interfaces. */  /* Packet filtering hook for interfaces. */
 pfil_head_t *                   if_pfil __read_mostly;  pfil_head_t *   if_pfil;
   
 static kauth_listener_t if_listener;  static kauth_listener_t if_listener;
   
Line 223  static int sysctl_percpuq_drops_handler(
Line 221  static int sysctl_percpuq_drops_handler(
 static void sysctl_percpuq_setup(struct sysctllog **, const char *,  static void sysctl_percpuq_setup(struct sysctllog **, const char *,
     struct if_percpuq *);      struct if_percpuq *);
   
 struct if_deferred_start {  
         struct ifnet    *ids_ifp;  
         void            (*ids_if_start)(struct ifnet *);  
         void            *ids_si;  
 };  
   
 static void if_deferred_start_softint(void *);  
 static void if_deferred_start_common(struct ifnet *);  
 static void if_deferred_start_destroy(struct ifnet *);  
   
 #if defined(INET) || defined(INET6)  #if defined(INET) || defined(INET6)
 static void sysctl_net_pktq_setup(struct sysctllog **, int);  static void sysctl_net_pktq_setup(struct sysctllog **, int);
 #endif  #endif
   
 static void if_sysctl_setup(struct sysctllog **);  
   
 /*  
  * Pointer to stub or real compat_cvtcmd() depending on presence of  
  * the compat module  
  */  
 u_long stub_compat_cvtcmd(u_long);  
 u_long (*vec_compat_cvtcmd)(u_long) = stub_compat_cvtcmd;  
   
 /* Similarly, pointer to compat_ifioctl() if it is present */  
   
 int (*vec_compat_ifioctl)(struct socket *, u_long, u_long, void *,  
         struct lwp *) = NULL;  
   
 /* The stub version of compat_cvtcmd() */  
 u_long stub_compat_cvtcmd(u_long cmd)  
 {  
   
         return cmd;  
 }  
   
 static int  static int
 if_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie,  if_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie,
     void *arg0, void *arg1, void *arg2, void *arg3)      void *arg0, void *arg1, void *arg2, void *arg3)
Line 287  if_listener_cb(kauth_cred_t cred, kauth_
Line 254  if_listener_cb(kauth_cred_t cred, kauth_
 void  void
 ifinit(void)  ifinit(void)
 {  {
   #if defined(INET)
           sysctl_net_pktq_setup(NULL, PF_INET);
   #endif
   #ifdef INET6
           if (in6_present)
                   sysctl_net_pktq_setup(NULL, PF_INET6);
   #endif
   
         if_sysctl_setup(NULL);  #if (defined(INET) || defined(INET6)) && !defined(IPSEC)
   
 #if (defined(INET) || defined(INET6))  
         encapinit();          encapinit();
 #endif  #endif
   
Line 309  void
Line 281  void
 ifinit1(void)  ifinit1(void)
 {  {
         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);
         mutex_init(&ifnet_mtx, MUTEX_DEFAULT, IPL_NONE);          mutex_init(&ifnet_mtx, MUTEX_DEFAULT, IPL_NONE);
         ifnet_psz = pserialize_create();          ifnet_psz = pserialize_create();
         ifnet_psref_class = psref_class_create("ifnet", IPL_SOFTNET);          ifnet_psref_class = psref_class_create("ifnet", IPL_SOFTNET);
         ifa_psref_class = psref_class_create("ifa", IPL_SOFTNET);  
         PSLIST_INIT(&ifnet_pslist);          PSLIST_INIT(&ifnet_pslist);
   
         if_indexlim = 8;          if_indexlim = 8;
   
         if_pfil = pfil_head_create(PFIL_TYPE_IFNET, NULL);          if_pfil = pfil_head_create(PFIL_TYPE_IFNET, NULL);
Line 377  int
Line 346  int
 if_nulltransmit(struct ifnet *ifp, struct mbuf *m)  if_nulltransmit(struct ifnet *ifp, struct mbuf *m)
 {  {
   
         m_freem(m);  
         return ENXIO;          return ENXIO;
 }  }
   
Line 459  if_dl_create(const struct ifnet *ifp, co
Line 427  if_dl_create(const struct ifnet *ifp, co
         ifa->ifa_rtrequest = link_rtrequest;          ifa->ifa_rtrequest = link_rtrequest;
         ifa->ifa_addr = (struct sockaddr *)sdl;          ifa->ifa_addr = (struct sockaddr *)sdl;
         ifa->ifa_netmask = (struct sockaddr *)mask;          ifa->ifa_netmask = (struct sockaddr *)mask;
         ifa_psref_init(ifa);  
   
         *sdlp = sdl;          *sdlp = sdl;
   
Line 518  if_deactivate_sadl(struct ifnet *ifp)
Line 485  if_deactivate_sadl(struct ifnet *ifp)
         ifafree(ifa);          ifafree(ifa);
 }  }
   
 static void  
 if_replace_sadl(struct ifnet *ifp, struct ifaddr *ifa)  
 {  
         struct ifaddr *old;  
   
         KASSERT(ifp->if_dl != NULL);  
   
         old = ifp->if_dl;  
   
         ifaref(ifa);  
         /* XXX Update if_dl and if_sadl atomically */  
         ifp->if_dl = ifa;  
         ifp->if_sadl = satosdl(ifa->ifa_addr);  
   
         ifafree(old);  
 }  
   
 void  void
 if_activate_sadl(struct ifnet *ifp, struct ifaddr *ifa0,  if_activate_sadl(struct ifnet *ifp, struct ifaddr *ifa,
     const struct sockaddr_dl *sdl)      const struct sockaddr_dl *sdl)
 {  {
         int s, ss;          int s;
         struct ifaddr *ifa;  
         int bound = curlwp_bind();  
   
         KASSERT(ifa_held(ifa0));  
   
         s = splsoftnet();  
   
         if_replace_sadl(ifp, ifa0);          s = splnet();
   
         ss = pserialize_read_enter();          if_deactivate_sadl(ifp);
         IFADDR_READER_FOREACH(ifa, ifp) {  
                 struct psref psref;  
                 ifa_acquire(ifa, &psref);  
                 pserialize_read_exit(ss);  
   
           if_sadl_setrefs(ifp, ifa);
           IFADDR_READER_FOREACH(ifa, ifp)
                 rtinit(ifa, RTM_LLINFO_UPD, 0);                  rtinit(ifa, RTM_LLINFO_UPD, 0);
   
                 ss = pserialize_read_enter();  
                 ifa_release(ifa, &psref);  
         }  
         pserialize_read_exit(ss);  
   
         splx(s);          splx(s);
         curlwp_bindx(bound);  
 }  }
   
 /*  /*
Line 584  if_free_sadl(struct ifnet *ifp)
Line 520  if_free_sadl(struct ifnet *ifp)
   
         KASSERT(ifp->if_sadl != NULL);          KASSERT(ifp->if_sadl != NULL);
   
         s = splsoftnet();          s = splnet();
         rtinit(ifa, RTM_DELETE, 0);          rtinit(ifa, RTM_DELETE, 0);
         ifa_remove(ifp, ifa);          ifa_remove(ifp, ifa);
         if_deactivate_sadl(ifp);          if_deactivate_sadl(ifp);
Line 701  if_initialize(ifnet_t *ifp)
Line 637  if_initialize(ifnet_t *ifp)
         ifp->if_snd.altq_ifp  = ifp;          ifp->if_snd.altq_ifp  = ifp;
 #endif  #endif
   
         IFQ_LOCK_INIT(&ifp->if_snd);          ifp->if_snd.ifq_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_NET);
   
         ifp->if_pfil = pfil_head_create(PFIL_TYPE_IFNET, ifp);          ifp->if_pfil = pfil_head_create(PFIL_TYPE_IFNET, ifp);
         pfil_run_ifhooks(if_pfil, PFIL_IFNET_ATTACH, ifp);          (void)pfil_run_hooks(if_pfil,
               (struct mbuf **)PFIL_IFNET_ATTACH, ifp, PFIL_IFNET);
   
         IF_AFDATA_LOCK_INIT(ifp);          IF_AFDATA_LOCK_INIT(ifp);
   
Line 719  if_initialize(ifnet_t *ifp)
Line 656  if_initialize(ifnet_t *ifp)
         PSLIST_INIT(&ifp->if_addr_pslist);          PSLIST_INIT(&ifp->if_addr_pslist);
         psref_target_init(&ifp->if_psref, ifnet_psref_class);          psref_target_init(&ifp->if_psref, ifnet_psref_class);
         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);  
   
         IFNET_LOCK();          IFNET_LOCK();
         if_getindex(ifp);          if_getindex(ifp);
Line 790  if_percpuq_softint(void *arg)
Line 726  if_percpuq_softint(void *arg)
         struct ifnet *ifp = ipq->ipq_ifp;          struct ifnet *ifp = ipq->ipq_ifp;
         struct mbuf *m;          struct mbuf *m;
   
         while ((m = if_percpuq_dequeue(ipq)) != NULL) {          while ((m = if_percpuq_dequeue(ipq)) != NULL)
                 ifp->if_ipackets++;  
                 bpf_mtap(ifp, m);  
   
                 ifp->_if_input(ifp, m);                  ifp->_if_input(ifp, m);
         }  
 }  }
   
 static void  static void
Line 862  if_percpuq_destroy(struct if_percpuq *ip
Line 794  if_percpuq_destroy(struct if_percpuq *ip
         softint_disestablish(ipq->ipq_si);          softint_disestablish(ipq->ipq_si);
         percpu_foreach(ipq->ipq_ifqs, &if_percpuq_purge_ifq, NULL);          percpu_foreach(ipq->ipq_ifqs, &if_percpuq_purge_ifq, NULL);
         percpu_free(ipq->ipq_ifqs, sizeof(struct ifqueue));          percpu_free(ipq->ipq_ifqs, sizeof(struct ifqueue));
         kmem_free(ipq, sizeof(*ipq));  
 }  }
   
 void  void
Line 982  bad:
Line 913  bad:
         return;          return;
 }  }
   
 /*  
  * The deferred if_start framework  
  *  
  * The common APIs to defer if_start to softint when if_start is requested  
  * from a device driver running in hardware interrupt context.  
  */  
 /*  
  * Call ifp->if_start (or equivalent) in a dedicated softint for  
  * deferred if_start.  
  */  
 static void  
 if_deferred_start_softint(void *arg)  
 {  
         struct if_deferred_start *ids = arg;  
         struct ifnet *ifp = ids->ids_ifp;  
   
         ids->ids_if_start(ifp);  
 }  
   
 /*  
  * The default callback function for deferred if_start.  
  */  
 static void  
 if_deferred_start_common(struct ifnet *ifp)  
 {  
         int s;  
   
         s = splnet();  
         if_start_lock(ifp);  
         splx(s);  
 }  
   
 static inline bool  
 if_snd_is_used(struct ifnet *ifp)  
 {  
   
         return ifp->if_transmit == NULL || ifp->if_transmit == if_nulltransmit ||  
             ALTQ_IS_ENABLED(&ifp->if_snd);  
 }  
   
 /*  
  * Schedule deferred if_start.  
  */  
 void  
 if_schedule_deferred_start(struct ifnet *ifp)  
 {  
   
         KASSERT(ifp->if_deferred_start != NULL);  
   
         if (if_snd_is_used(ifp) && IFQ_IS_EMPTY(&ifp->if_snd))  
                 return;  
   
         softint_schedule(ifp->if_deferred_start->ids_si);  
 }  
   
 /*  
  * Create an instance of deferred if_start. A driver should call the function  
  * only if the driver needs deferred if_start. Drivers can setup their own  
  * deferred if_start function via 2nd argument.  
  */  
 void  
 if_deferred_start_init(struct ifnet *ifp, void (*func)(struct ifnet *))  
 {  
         struct if_deferred_start *ids;  
   
         ids = kmem_zalloc(sizeof(*ids), KM_SLEEP);  
         if (ids == NULL)  
                 panic("kmem_zalloc failed");  
   
         ids->ids_ifp = ifp;  
         ids->ids_si = softint_establish(SOFTINT_NET|SOFTINT_MPSAFE,  
             if_deferred_start_softint, ids);  
         if (func != NULL)  
                 ids->ids_if_start = func;  
         else  
                 ids->ids_if_start = if_deferred_start_common;  
   
         ifp->if_deferred_start = ids;  
 }  
   
 static void  
 if_deferred_start_destroy(struct ifnet *ifp)  
 {  
   
         if (ifp->if_deferred_start == NULL)  
                 return;  
   
         softint_disestablish(ifp->if_deferred_start->ids_si);  
         kmem_free(ifp->if_deferred_start, sizeof(*ifp->if_deferred_start));  
         ifp->if_deferred_start = NULL;  
 }  
   
 /*  /*
  * The common interface input routine that is called by device drivers,   * The common interface input routine that is called by device drivers,
Line 1086  if_input(struct ifnet *ifp, struct mbuf 
Line 926  if_input(struct ifnet *ifp, struct mbuf 
         KASSERT(ifp->if_percpuq == NULL);          KASSERT(ifp->if_percpuq == NULL);
         KASSERT(!cpu_intr_p());          KASSERT(!cpu_intr_p());
   
         ifp->if_ipackets++;  
         bpf_mtap(ifp, m);  
   
         ifp->_if_input(ifp, m);          ifp->_if_input(ifp, m);
 }  }
   
Line 1135  if_attachdomain1(struct ifnet *ifp)
Line 972  if_attachdomain1(struct ifnet *ifp)
         struct domain *dp;          struct domain *dp;
         int s;          int s;
   
         s = splsoftnet();          s = splnet();
   
         /* address family dependent data region */          /* address family dependent data region */
         memset(ifp->if_afdata, 0, sizeof(ifp->if_afdata));          memset(ifp->if_afdata, 0, sizeof(ifp->if_afdata));
Line 1157  if_deactivate(struct ifnet *ifp)
Line 994  if_deactivate(struct ifnet *ifp)
 {  {
         int s;          int s;
   
         s = splsoftnet();          s = splnet();
   
         ifp->if_output   = if_nulloutput;          ifp->if_output   = if_nulloutput;
         ifp->_if_input   = if_nullinput;          ifp->_if_input   = if_nullinput;
Line 1176  if_deactivate(struct ifnet *ifp)
Line 1013  if_deactivate(struct ifnet *ifp)
 }  }
   
 bool  bool
 if_is_deactivated(const struct ifnet *ifp)  if_is_deactivated(struct ifnet *ifp)
 {  {
   
         return ifp->if_output == if_nulloutput;          return ifp->if_output == if_nulloutput;
Line 1186  void
Line 1023  void
 if_purgeaddrs(struct ifnet *ifp, int family, void (*purgeaddr)(struct ifaddr *))  if_purgeaddrs(struct ifnet *ifp, int family, void (*purgeaddr)(struct ifaddr *))
 {  {
         struct ifaddr *ifa, *nifa;          struct ifaddr *ifa, *nifa;
         int s;  
   
         s = pserialize_read_enter();  
         for (ifa = IFADDR_READER_FIRST(ifp); ifa; ifa = nifa) {          for (ifa = IFADDR_READER_FIRST(ifp); ifa; ifa = nifa) {
                 nifa = IFADDR_READER_NEXT(ifa);                  nifa = IFADDR_READER_NEXT(ifa);
                 if (ifa->ifa_addr->sa_family != family)                  if (ifa->ifa_addr->sa_family != family)
                         continue;                          continue;
                 pserialize_read_exit(s);  
   
                 (*purgeaddr)(ifa);                  (*purgeaddr)(ifa);
   
                 s = pserialize_read_enter();  
         }          }
         pserialize_read_exit(s);  
 }  }
   
 #ifdef IFAREF_DEBUG  #ifdef IFAREF_DEBUG
Line 1304  if_detach(struct ifnet *ifp)
Line 1134  if_detach(struct ifnet *ifp)
         pserialize_perform(ifnet_psz);          pserialize_perform(ifnet_psz);
         IFNET_UNLOCK();          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);          mutex_obj_free(ifp->if_ioctl_lock);
         ifp->if_ioctl_lock = NULL;          ifp->if_ioctl_lock = NULL;
   
Line 1317  if_detach(struct ifnet *ifp)
Line 1143  if_detach(struct ifnet *ifp)
                 callout_destroy(ifp->if_slowtimo_ch);                  callout_destroy(ifp->if_slowtimo_ch);
                 kmem_free(ifp->if_slowtimo_ch, sizeof(*ifp->if_slowtimo_ch));                  kmem_free(ifp->if_slowtimo_ch, sizeof(*ifp->if_slowtimo_ch));
         }          }
         if_deferred_start_destroy(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.
Line 1353  if_detach(struct ifnet *ifp)
Line 1178  if_detach(struct ifnet *ifp)
          * least one ifaddr.           * least one ifaddr.
          */           */
 again:  again:
         /*  
          * At this point, no other one tries to remove ifa in the list,  
          * so we don't need to take a lock or psref.  
          */  
         IFADDR_READER_FOREACH(ifa, ifp) {          IFADDR_READER_FOREACH(ifa, ifp) {
                 family = ifa->ifa_addr->sa_family;                  family = ifa->ifa_addr->sa_family;
 #ifdef IFAREF_DEBUG  #ifdef IFAREF_DEBUG
Line 1369  again:
Line 1190  again:
                 if (family == AF_LINK)                  if (family == AF_LINK)
                         continue;                          continue;
                 dp = pffinddomain(family);                  dp = pffinddomain(family);
                 KASSERTMSG(dp != NULL, "no domain for AF %d", family);  #ifdef DIAGNOSTIC
                   if (dp == NULL)
                           panic("if_detach: no domain for AF %d",
                               family);
   #endif
                 /*                  /*
                  * XXX These PURGEIF calls are redundant with the                   * XXX These PURGEIF calls are redundant with the
                  * purge-all-families calls below, but are left in for                   * purge-all-families calls below, but are left in for
Line 1400  again:
Line 1225  again:
   
         if_free_sadl(ifp);          if_free_sadl(ifp);
   
         /* Delete stray routes from the routing table. */          /* Walk the routing table looking for stragglers. */
         for (i = 0; i <= AF_MAX; i++)          for (i = 0; i <= AF_MAX; i++) {
                 rt_delete_matched_entries(i, if_delroute_matcher, ifp);                  while (rt_walktree(i, if_rt_walktree, ifp) == ERESTART)
                           continue;
           }
   
         DOMAIN_FOREACH(dp) {          DOMAIN_FOREACH(dp) {
                 if (dp->dom_ifdetach != NULL && ifp->if_afdata[dp->dom_family])                  if (dp->dom_ifdetach != NULL && ifp->if_afdata[dp->dom_family])
Line 1434  again:
Line 1261  again:
                 }                  }
         }          }
   
         pfil_run_ifhooks(if_pfil, PFIL_IFNET_DETACH, ifp);          (void)pfil_run_hooks(if_pfil,
               (struct mbuf **)PFIL_IFNET_DETACH, ifp, PFIL_IFNET);
         (void)pfil_head_destroy(ifp->if_pfil);          (void)pfil_head_destroy(ifp->if_pfil);
   
         /* Announce that the interface is gone. */          /* Announce that the interface is gone. */
Line 1475  again:
Line 1303  again:
         xc = xc_broadcast(0, (xcfunc_t)nullop, NULL, NULL);          xc = xc_broadcast(0, (xcfunc_t)nullop, NULL, NULL);
         xc_wait(xc);          xc_wait(xc);
   
           /* Wait for all readers to drain before freeing.  */
           psref_target_destroy(&ifp->if_psref, ifnet_psref_class);
           PSLIST_ENTRY_DESTROY(ifp, if_pslist_entry);
   
         if (ifp->if_percpuq != NULL) {          if (ifp->if_percpuq != NULL) {
                 if_percpuq_destroy(ifp->if_percpuq);                  if_percpuq_destroy(ifp->if_percpuq);
                 ifp->if_percpuq = NULL;                  ifp->if_percpuq = NULL;
Line 1521  if_detach_queues(struct ifnet *ifp, stru
Line 1353  if_detach_queues(struct ifnet *ifp, stru
  * ifnet.   * ifnet.
  */   */
 static int  static int
 if_delroute_matcher(struct rtentry *rt, void *v)  if_rt_walktree(struct rtentry *rt, void *v)
 {  {
         struct ifnet *ifp = (struct ifnet *)v;          struct ifnet *ifp = (struct ifnet *)v;
           int error;
           struct rtentry *retrt;
   
         if (rt->rt_ifp == ifp)          if (rt->rt_ifp != ifp)
                 return 1;  
         else  
                 return 0;                  return 0;
   
           /* Delete the entry. */
           error = rtrequest(RTM_DELETE, rt_getkey(rt), rt->rt_gateway,
               rt_mask(rt), rt->rt_flags, &retrt);
           if (error == 0) {
                   KASSERT(retrt == rt);
                   KASSERT((retrt->rt_flags & RTF_UP) == 0);
                   retrt->rt_ifp = NULL;
                   rtfree(retrt);
           } else {
                   printf("%s: warning: unable to delete rtentry @ %p, "
                       "error = %d\n", ifp->if_xname, rt, error);
           }
           return ERESTART;
 }  }
   
 /*  /*
Line 1542  if_clone_create(const char *name)
Line 1388  if_clone_create(const char *name)
         struct ifnet *ifp;          struct ifnet *ifp;
         struct psref psref;          struct psref psref;
   
         KASSERT(mutex_owned(&if_clone_mtx));  
   
         ifc = if_clone_lookup(name, &unit);          ifc = if_clone_lookup(name, &unit);
         if (ifc == NULL)          if (ifc == NULL)
                 return EINVAL;                  return EINVAL;
Line 1567  if_clone_destroy(const char *name)
Line 1411  if_clone_destroy(const char *name)
         struct ifnet *ifp;          struct ifnet *ifp;
         struct psref psref;          struct psref psref;
   
         KASSERT(mutex_owned(&if_clone_mtx));  
   
         ifc = if_clone_lookup(name, NULL);          ifc = if_clone_lookup(name, NULL);
         if (ifc == NULL)          if (ifc == NULL)
                 return EINVAL;                  return EINVAL;
Line 1594  if_clone_destroy(const char *name)
Line 1436  if_clone_destroy(const char *name)
         return (*ifc->ifc_destroy)(ifp);          return (*ifc->ifc_destroy)(ifp);
 }  }
   
 static bool  
 if_is_unit(const char *name)  
 {  
   
         while(*name != '\0') {  
                 if (*name < '0' || *name > '9')  
                         return false;  
                 name++;  
         }  
   
         return true;  
 }  
   
 /*  /*
  * Look up a network interface cloner.   * Look up a network interface cloner.
  */   */
Line 1618  if_clone_lookup(const char *name, int *u
Line 1447  if_clone_lookup(const char *name, int *u
         char *dp, ifname[IFNAMSIZ + 3];          char *dp, ifname[IFNAMSIZ + 3];
         int unit;          int unit;
   
         KASSERT(mutex_owned(&if_clone_mtx));  
   
         strcpy(ifname, "if_");          strcpy(ifname, "if_");
         /* separate interface name from unit */          /* separate interface name from unit */
         /* TODO: search unit number from backward */  
         for (dp = ifname + 3, cp = name; cp - name < IFNAMSIZ &&          for (dp = ifname + 3, cp = name; cp - name < IFNAMSIZ &&
             *cp && !if_is_unit(cp);)              *cp && (*cp < '0' || *cp > '9');)
                 *dp++ = *cp++;                  *dp++ = *cp++;
   
         if (cp == name || cp - name == IFNAMSIZ || !*cp)          if (cp == name || cp - name == IFNAMSIZ || !*cp)
Line 1638  again:
Line 1464  again:
         }          }
   
         if (ifc == NULL) {          if (ifc == NULL) {
                 int error;                  if (*ifname == '\0' ||
                 if (*ifname == '\0')                      module_autoload(ifname, MODULE_CLASS_DRIVER))
                         return NULL;  
                 mutex_exit(&if_clone_mtx);  
                 error = module_autoload(ifname, MODULE_CLASS_DRIVER);  
                 mutex_enter(&if_clone_mtx);  
                 if (error)  
                         return NULL;                          return NULL;
                 *ifname = '\0';                  *ifname = '\0';
                 goto again;                  goto again;
Line 1671  void
Line 1492  void
 if_clone_attach(struct if_clone *ifc)  if_clone_attach(struct if_clone *ifc)
 {  {
   
         mutex_enter(&if_clone_mtx);  
         LIST_INSERT_HEAD(&if_cloners, ifc, ifc_list);          LIST_INSERT_HEAD(&if_cloners, ifc, ifc_list);
         if_cloners_count++;          if_cloners_count++;
         mutex_exit(&if_clone_mtx);  
 }  }
   
 /*  /*
Line 1684  void
Line 1503  void
 if_clone_detach(struct if_clone *ifc)  if_clone_detach(struct if_clone *ifc)
 {  {
   
         mutex_enter(&if_clone_mtx);  
         LIST_REMOVE(ifc, ifc_list);          LIST_REMOVE(ifc, ifc_list);
         if_cloners_count--;          if_cloners_count--;
         mutex_exit(&if_clone_mtx);  
 }  }
   
 /*  /*
Line 1700  if_clone_list(int buf_count, char *buffe
Line 1517  if_clone_list(int buf_count, char *buffe
         struct if_clone *ifc;          struct if_clone *ifc;
         int count, error = 0;          int count, error = 0;
   
         mutex_enter(&if_clone_mtx);  
         *total = if_cloners_count;          *total = if_cloners_count;
         if ((dst = buffer) == NULL) {          if ((dst = buffer) == NULL) {
                 /* Just asking how many there are. */                  /* Just asking how many there are. */
                 goto out;                  return 0;
         }          }
   
         if (buf_count < 0) {          if (buf_count < 0)
                 error = EINVAL;                  return EINVAL;
                 goto out;  
         }  
   
         count = (if_cloners_count < buf_count) ?          count = (if_cloners_count < buf_count) ?
             if_cloners_count : buf_count;              if_cloners_count : buf_count;
Line 1718  if_clone_list(int buf_count, char *buffe
Line 1532  if_clone_list(int buf_count, char *buffe
         for (ifc = LIST_FIRST(&if_cloners); ifc != NULL && count != 0;          for (ifc = LIST_FIRST(&if_cloners); ifc != NULL && count != 0;
              ifc = LIST_NEXT(ifc, ifc_list), count--, dst += IFNAMSIZ) {               ifc = LIST_NEXT(ifc, ifc_list), count--, dst += IFNAMSIZ) {
                 (void)strncpy(outbuf, ifc->ifc_name, sizeof(outbuf));                  (void)strncpy(outbuf, ifc->ifc_name, sizeof(outbuf));
                 if (outbuf[sizeof(outbuf) - 1] != '\0') {                  if (outbuf[sizeof(outbuf) - 1] != '\0')
                         error = ENAMETOOLONG;                          return ENAMETOOLONG;
                         goto out;  
                 }  
                 error = copyout(outbuf, dst, sizeof(outbuf));                  error = copyout(outbuf, dst, sizeof(outbuf));
                 if (error != 0)                  if (error != 0)
                         break;                          break;
         }          }
   
 out:  
         mutex_exit(&if_clone_mtx);  
         return error;          return error;
 }  }
   
 void  void
 ifa_psref_init(struct ifaddr *ifa)  
 {  
   
         psref_target_init(&ifa->ifa_psref, ifa_psref_class);  
 }  
   
 void  
 ifaref(struct ifaddr *ifa)  ifaref(struct ifaddr *ifa)
 {  {
         KASSERT(!ISSET(ifa->ifa_flags, IFA_DESTROYING));  
         ifa->ifa_refcnt++;          ifa->ifa_refcnt++;
 }  }
   
Line 1757  ifafree(struct ifaddr *ifa)
Line 1559  ifafree(struct ifaddr *ifa)
         }          }
 }  }
   
 bool  
 ifa_is_destroying(struct ifaddr *ifa)  
 {  
   
         return ISSET(ifa->ifa_flags, IFA_DESTROYING);  
 }  
   
 void  void
 ifa_insert(struct ifnet *ifp, struct ifaddr *ifa)  ifa_insert(struct ifnet *ifp, struct ifaddr *ifa)
 {  {
   
         ifa->ifa_ifp = ifp;          ifa->ifa_ifp = ifp;
   
         IFNET_LOCK();  
         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);
 }  }
   
 void  void
 ifa_remove(struct ifnet *ifp, struct ifaddr *ifa)  ifa_remove(struct ifnet *ifp, struct ifaddr *ifa)
 {  {
   
         KASSERT(ifa->ifa_ifp == ifp);          KASSERT(ifa->ifa_ifp == 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          /* TODO psref_target_destroy */
         pserialize_perform(ifnet_psz);  
 #endif  
         IFNET_UNLOCK();  
   
 #ifdef NET_MPSAFE  
         psref_target_destroy(&ifa->ifa_psref, ifa_psref_class);  
 #endif  
         IFADDR_ENTRY_DESTROY(ifa);          IFADDR_ENTRY_DESTROY(ifa);
         ifafree(ifa);          ifafree(ifa);
 }  }
   
 void  
 ifa_acquire(struct ifaddr *ifa, struct psref *psref)  
 {  
   
         psref_acquire(psref, &ifa->ifa_psref, ifa_psref_class);  
 }  
   
 void  
 ifa_release(struct ifaddr *ifa, struct psref *psref)  
 {  
   
         if (ifa == NULL)  
                 return;  
   
         psref_release(psref, &ifa->ifa_psref, ifa_psref_class);  
 }  
   
 bool  
 ifa_held(struct ifaddr *ifa)  
 {  
   
         return psref_held(&ifa->ifa_psref, ifa_psref_class);  
 }  
   
 static inline int  static inline int
 equal(const struct sockaddr *sa1, const struct sockaddr *sa2)  equal(const struct sockaddr *sa1, const struct sockaddr *sa2)
 {  {
Line 1839  ifa_ifwithaddr(const struct sockaddr *ad
Line 1595  ifa_ifwithaddr(const struct sockaddr *ad
 {  {
         struct ifnet *ifp;          struct ifnet *ifp;
         struct ifaddr *ifa;          struct ifaddr *ifa;
           int s;
   
           s = pserialize_read_enter();
         IFNET_READER_FOREACH(ifp) {          IFNET_READER_FOREACH(ifp) {
                 if (if_is_deactivated(ifp))                  if (if_is_deactivated(ifp))
                         continue;                          continue;
Line 1856  ifa_ifwithaddr(const struct sockaddr *ad
Line 1614  ifa_ifwithaddr(const struct sockaddr *ad
                                 return ifa;                                  return ifa;
                 }                  }
         }          }
         return NULL;  
 }  
   
 struct ifaddr *  
 ifa_ifwithaddr_psref(const struct sockaddr *addr, struct psref *psref)  
 {  
         struct ifaddr *ifa;  
         int s = pserialize_read_enter();  
   
         ifa = ifa_ifwithaddr(addr);  
         if (ifa != NULL)  
                 ifa_acquire(ifa, psref);  
         pserialize_read_exit(s);          pserialize_read_exit(s);
           return NULL;
         return ifa;  
 }  }
   
 /*  /*
Line 1882  ifa_ifwithdstaddr(const struct sockaddr 
Line 1627  ifa_ifwithdstaddr(const struct sockaddr 
 {  {
         struct ifnet *ifp;          struct ifnet *ifp;
         struct ifaddr *ifa;          struct ifaddr *ifa;
           int s;
   
           s = pserialize_read_enter();
         IFNET_READER_FOREACH(ifp) {          IFNET_READER_FOREACH(ifp) {
                 if (if_is_deactivated(ifp))                  if (if_is_deactivated(ifp))
                         continue;                          continue;
Line 1896  ifa_ifwithdstaddr(const struct sockaddr 
Line 1643  ifa_ifwithdstaddr(const struct sockaddr 
                                 return ifa;                                  return ifa;
                 }                  }
         }          }
   
         return NULL;  
 }  
   
 struct ifaddr *  
 ifa_ifwithdstaddr_psref(const struct sockaddr *addr, struct psref *psref)  
 {  
         struct ifaddr *ifa;  
         int s;  
   
         s = pserialize_read_enter();  
         ifa = ifa_ifwithdstaddr(addr);  
         if (ifa != NULL)  
                 ifa_acquire(ifa, psref);  
         pserialize_read_exit(s);          pserialize_read_exit(s);
           return NULL;
         return ifa;  
 }  }
   
 /*  /*
Line 1923  struct ifaddr *
Line 1655  struct ifaddr *
 ifa_ifwithnet(const struct sockaddr *addr)  ifa_ifwithnet(const struct sockaddr *addr)
 {  {
         struct ifnet *ifp;          struct ifnet *ifp;
         struct ifaddr *ifa, *ifa_maybe = NULL;          struct ifaddr *ifa;
         const struct sockaddr_dl *sdl;          const struct sockaddr_dl *sdl;
           struct ifaddr *ifa_maybe = 0;
         u_int af = addr->sa_family;          u_int af = addr->sa_family;
         const char *addr_data = addr->sa_data, *cplim;          const char *addr_data = addr->sa_data, *cplim;
           int s;
   
         if (af == AF_LINK) {          if (af == AF_LINK) {
                 sdl = satocsdl(addr);                  sdl = satocsdl(addr);
Line 1940  ifa_ifwithnet(const struct sockaddr *add
Line 1674  ifa_ifwithnet(const struct sockaddr *add
         if (af == AF_APPLETALK) {          if (af == AF_APPLETALK) {
                 const struct sockaddr_at *sat, *sat2;                  const struct sockaddr_at *sat, *sat2;
                 sat = (const struct sockaddr_at *)addr;                  sat = (const struct sockaddr_at *)addr;
                   s = pserialize_read_enter();
                 IFNET_READER_FOREACH(ifp) {                  IFNET_READER_FOREACH(ifp) {
                         if (if_is_deactivated(ifp))                          if (if_is_deactivated(ifp))
                                 continue;                                  continue;
Line 1954  ifa_ifwithnet(const struct sockaddr *add
Line 1689  ifa_ifwithnet(const struct sockaddr *add
                                 ifa_maybe = ifa;                                  ifa_maybe = ifa;
                         }                          }
                 }                  }
                   pserialize_read_exit(s);
                 return ifa_maybe;                  return ifa_maybe;
         }          }
 #endif  #endif
           s = pserialize_read_enter();
         IFNET_READER_FOREACH(ifp) {          IFNET_READER_FOREACH(ifp) {
                 if (if_is_deactivated(ifp))                  if (if_is_deactivated(ifp))
                         continue;                          continue;
Line 1983  ifa_ifwithnet(const struct sockaddr *add
Line 1720  ifa_ifwithnet(const struct sockaddr *add
                                 ifa_maybe = ifa;                                  ifa_maybe = ifa;
                 }                  }
         }          }
         return ifa_maybe;  
 }  
   
 struct ifaddr *  
 ifa_ifwithnet_psref(const struct sockaddr *addr, struct psref *psref)  
 {  
         struct ifaddr *ifa;  
         int s;  
   
         s = pserialize_read_enter();  
         ifa = ifa_ifwithnet(addr);  
         if (ifa != NULL)  
                 ifa_acquire(ifa, psref);  
         pserialize_read_exit(s);          pserialize_read_exit(s);
           return ifa_maybe;
         return ifa;  
 }  }
   
 /*  /*
Line 2015  ifa_ifwithladdr(const struct sockaddr *a
Line 1738  ifa_ifwithladdr(const struct sockaddr *a
         return NULL;          return NULL;
 }  }
   
 struct ifaddr *  
 ifa_ifwithladdr_psref(const struct sockaddr *addr, struct psref *psref)  
 {  
         struct ifaddr *ifa;  
         int s;  
   
         s = pserialize_read_enter();  
         ifa = ifa_ifwithladdr(addr);  
         if (ifa != NULL)  
                 ifa_acquire(ifa, psref);  
         pserialize_read_exit(s);  
   
         return ifa;  
 }  
   
 /*  /*
  * Find an interface using a specific address family   * Find an interface using a specific address family
  */   */
Line 2098  ifaof_ifpforaddr(const struct sockaddr *
Line 1806  ifaof_ifpforaddr(const struct sockaddr *
         return ifa_maybe;          return ifa_maybe;
 }  }
   
 struct ifaddr *  
 ifaof_ifpforaddr_psref(const struct sockaddr *addr, struct ifnet *ifp,  
     struct psref *psref)  
 {  
         struct ifaddr *ifa;  
         int s;  
   
         s = pserialize_read_enter();  
         ifa = ifaof_ifpforaddr(addr, ifp);  
         if (ifa != NULL)  
                 ifa_acquire(ifa, psref);  
         pserialize_read_exit(s);  
   
         return ifa;  
 }  
   
 /*  /*
  * Default action when installing a route with a Link Level gateway.   * Default action when installing a route with a Link Level gateway.
  * Lookup an appropriate real ifa to point to.   * Lookup an appropriate real ifa to point to.
Line 2125  link_rtrequest(int cmd, struct rtentry *
Line 1817  link_rtrequest(int cmd, struct rtentry *
         struct ifaddr *ifa;          struct ifaddr *ifa;
         const struct sockaddr *dst;          const struct sockaddr *dst;
         struct ifnet *ifp;          struct ifnet *ifp;
         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)
                 return;                  return;
         if ((ifa = ifaof_ifpforaddr_psref(dst, ifp, &psref)) != NULL) {          if ((ifa = ifaof_ifpforaddr(dst, ifp)) != NULL) {
                 rt_replace_ifa(rt, ifa);                  rt_replace_ifa(rt, ifa);
                 if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)                  if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
                         ifa->ifa_rtrequest(cmd, rt, info);                          ifa->ifa_rtrequest(cmd, rt, info);
                 ifa_release(ifa, &psref);  
         }          }
 }  }
   
Line 2313  if_link_state_change_si(void *arg)
Line 2003  if_link_state_change_si(void *arg)
         int s;          int s;
         uint8_t state;          uint8_t state;
   
 #ifndef 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. */
Line 2328  if_link_state_change_si(void *arg)
Line 2014  if_link_state_change_si(void *arg)
                 softint_schedule(ifp->if_link_si);                  softint_schedule(ifp->if_link_si);
   
         splx(s);          splx(s);
 #ifndef NET_MPSAFE  
         KERNEL_UNLOCK_ONE(NULL);  
         mutex_exit(softnet_lock);  
 #endif  
 }  }
   
 /*  /*
Line 2344  p2p_rtrequest(int req, struct rtentry *r
Line 2026  p2p_rtrequest(int req, struct rtentry *r
 {  {
         struct ifnet *ifp = rt->rt_ifp;          struct ifnet *ifp = rt->rt_ifp;
         struct ifaddr *ifa, *lo0ifa;          struct ifaddr *ifa, *lo0ifa;
         int s = pserialize_read_enter();  
   
         switch (req) {          switch (req) {
         case RTM_ADD:          case RTM_ADD:
Line 2383  p2p_rtrequest(int req, struct rtentry *r
Line 2064  p2p_rtrequest(int req, struct rtentry *r
         default:          default:
                 break;                  break;
         }          }
         pserialize_read_exit(s);  
 }  }
   
 /*  /*
Line 2396  if_down(struct ifnet *ifp)
Line 2076  if_down(struct ifnet *ifp)
 {  {
         struct ifaddr *ifa;          struct ifaddr *ifa;
         struct domain *dp;          struct domain *dp;
         int s, bound;  
         struct psref psref;  
   
         ifp->if_flags &= ~IFF_UP;          ifp->if_flags &= ~IFF_UP;
         nanotime(&ifp->if_lastchange);          nanotime(&ifp->if_lastchange);
           IFADDR_READER_FOREACH(ifa, ifp)
         bound = curlwp_bind();  
         s = pserialize_read_enter();  
         IFADDR_READER_FOREACH(ifa, ifp) {  
                 ifa_acquire(ifa, &psref);  
                 pserialize_read_exit(s);  
   
                 pfctlinput(PRC_IFDOWN, ifa->ifa_addr);                  pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
   
                 s = pserialize_read_enter();  
                 ifa_release(ifa, &psref);  
         }  
         pserialize_read_exit(s);  
         curlwp_bindx(bound);  
   
         IFQ_PURGE(&ifp->if_snd);          IFQ_PURGE(&ifp->if_snd);
 #if NCARP > 0  #if NCARP > 0
         if (ifp->if_carp)          if (ifp->if_carp)
Line 2543  ifunit(const char *name)
Line 2208  ifunit(const char *name)
         /*          /*
          * If the number took all of the name, then it's a valid ifindex.           * If the number took all of the name, then it's a valid ifindex.
          */           */
         if (i == IFNAMSIZ || (cp != name && *cp == '\0'))          if (i == IFNAMSIZ || (cp != name && *cp == '\0')) {
                 return if_byindex(unit);                  if (unit >= if_indexlim)
                           return NULL;
                   ifp = ifindex2ifnet[unit];
                   if (ifp == NULL || if_is_deactivated(ifp))
                           return NULL;
                   return ifp;
           }
   
         ifp = NULL;          ifp = NULL;
         s = pserialize_read_enter();          s = pserialize_read_enter();
Line 2583  if_get(const char *name, struct psref *p
Line 2254  if_get(const char *name, struct psref *p
         /*          /*
          * If the number took all of the name, then it's a valid ifindex.           * If the number took all of the name, then it's a valid ifindex.
          */           */
         if (i == IFNAMSIZ || (cp != name && *cp == '\0'))          if (i == IFNAMSIZ || (cp != name && *cp == '\0')) {
                 return if_get_byindex(unit, psref);                  if (unit >= if_indexlim)
                           return NULL;
                   ifp = ifindex2ifnet[unit];
                   if (ifp == NULL || if_is_deactivated(ifp))
                           return NULL;
                   return ifp;
           }
   
         ifp = NULL;          ifp = NULL;
         s = pserialize_read_enter();          s = pserialize_read_enter();
Line 2619  if_put(const struct ifnet *ifp, struct p
Line 2296  if_put(const struct ifnet *ifp, struct p
 ifnet_t *  ifnet_t *
 if_byindex(u_int idx)  if_byindex(u_int idx)
 {  {
         ifnet_t *ifp;          return (idx < if_indexlim) ? ifindex2ifnet[idx] : NULL;
   
         ifp = (__predict_true(idx < if_indexlim)) ? ifindex2ifnet[idx] : NULL;  
         if (ifp != NULL && if_is_deactivated(ifp))  
                 ifp = NULL;  
         return ifp;  
 }  }
   
 /*  /*
Line 2639  if_get_byindex(u_int idx, struct psref *
Line 2311  if_get_byindex(u_int idx, struct psref *
         int s;          int s;
   
         s = pserialize_read_enter();          s = pserialize_read_enter();
         ifp = if_byindex(idx);          ifp = (__predict_true(idx < if_indexlim)) ? ifindex2ifnet[idx] : NULL;
         if (__predict_true(ifp != NULL))          if (__predict_true(ifp != NULL))
                 psref_acquire(psref, &ifp->if_psref, ifnet_psref_class);                  psref_acquire(psref, &ifp->if_psref, ifnet_psref_class);
         pserialize_read_exit(s);          pserialize_read_exit(s);
Line 2648  if_get_byindex(u_int idx, struct psref *
Line 2320  if_get_byindex(u_int idx, struct psref *
 }  }
   
 /*  /*
  * Note that it's safe only if the passed ifp is guaranteed to not be freed,   * XXX 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 the ifp is already held or some other object is held which
  * object is held which guarantes the ifp to not be freed indirectly.   * guarantes the ifp to not be freed indirectly.
  */   */
 void  void
 if_acquire(struct ifnet *ifp, struct psref *psref)  if_acquire_NOMPSAFE(struct ifnet *ifp, struct psref *psref)
 {  {
   
         KASSERT(ifp->if_index != 0);          KASSERT(ifp->if_index != 0);
Line 2731  ifioctl_common(struct ifnet *ifp, u_long
Line 2403  ifioctl_common(struct ifnet *ifp, u_long
         case SIOCSIFFLAGS:          case SIOCSIFFLAGS:
                 ifr = data;                  ifr = data;
                 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 = splnet();
                         if_down(ifp);                          if_down(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 = splnet();
                         if_up(ifp);                          if_up(ifp);
                         splx(s);                          splx(s);
                 }                  }
Line 2831  ifaddrpref_ioctl(struct socket *so, u_lo
Line 2503  ifaddrpref_ioctl(struct socket *so, u_lo
                 struct sockaddr sa;                  struct sockaddr sa;
                 struct sockaddr_storage ss;                  struct sockaddr_storage ss;
         } u, v;          } u, v;
         int s, error = 0;  
   
         switch (cmd) {          switch (cmd) {
         case SIOCSIFADDRPREF:          case SIOCSIFADDRPREF:
Line 2860  ifaddrpref_ioctl(struct socket *so, u_lo
Line 2531  ifaddrpref_ioctl(struct socket *so, u_lo
   
         sockaddr_externalize(&v.sa, sizeof(v.ss), sa);          sockaddr_externalize(&v.sa, sizeof(v.ss), sa);
   
         s = pserialize_read_enter();  
         IFADDR_READER_FOREACH(ifa, ifp) {          IFADDR_READER_FOREACH(ifa, ifp) {
                 if (ifa->ifa_addr->sa_family != sa->sa_family)                  if (ifa->ifa_addr->sa_family != sa->sa_family)
                         continue;                          continue;
Line 2868  ifaddrpref_ioctl(struct socket *so, u_lo
Line 2538  ifaddrpref_ioctl(struct socket *so, u_lo
                 if (sockaddr_cmp(&u.sa, &v.sa) == 0)                  if (sockaddr_cmp(&u.sa, &v.sa) == 0)
                         break;                          break;
         }          }
         if (ifa == NULL) {          if (ifa == NULL)
                 error = EADDRNOTAVAIL;                  return EADDRNOTAVAIL;
                 goto out;  
         }  
   
         switch (cmd) {          switch (cmd) {
         case SIOCSIFADDRPREF:          case SIOCSIFADDRPREF:
                 ifa->ifa_preference = ifap->ifap_preference;                  ifa->ifa_preference = ifap->ifap_preference;
                 goto out;                  return 0;
         case SIOCGIFADDRPREF:          case SIOCGIFADDRPREF:
                 /* fill in the if_laddrreq structure */                  /* fill in the if_laddrreq structure */
                 (void)sockaddr_copy(sstosa(&ifap->ifap_addr),                  (void)sockaddr_copy(sstosa(&ifap->ifap_addr),
                     sizeof(ifap->ifap_addr), ifa->ifa_addr);                      sizeof(ifap->ifap_addr), ifa->ifa_addr);
                 ifap->ifap_preference = ifa->ifa_preference;                  ifap->ifap_preference = ifa->ifa_preference;
                 goto out;                  return 0;
         default:          default:
                 error = EOPNOTSUPP;                  return EOPNOTSUPP;
         }          }
 out:  
         pserialize_read_exit(s);  
         return error;  
 }  }
   
 /*  /*
Line 2930  doifioctl(struct socket *so, u_long cmd,
Line 2595  doifioctl(struct socket *so, u_long cmd,
         }          }
   
 #ifdef COMPAT_OIFREQ  #ifdef COMPAT_OIFREQ
         cmd = (*vec_compat_cvtcmd)(cmd);          cmd = compat_cvtcmd(cmd);
         if (cmd != ocmd) {          if (cmd != ocmd) {
                 oifr = data;                  oifr = data;
                 data = ifr = &ifrb;                  data = ifr = &ifrb;
Line 3027  doifioctl(struct socket *so, u_long cmd,
Line 2692  doifioctl(struct socket *so, u_long cmd,
                 error = EOPNOTSUPP;                  error = EOPNOTSUPP;
         else {          else {
 #ifdef COMPAT_OSOCK  #ifdef COMPAT_OSOCK
                 if (vec_compat_ifioctl != NULL)                  error = compat_ifioctl(so, ocmd, cmd, data, l);
                         error = (*vec_compat_ifioctl)(so, ocmd, cmd, data, l);  #else
                 else                  error = (*so->so_proto->pr_usrreqs->pr_ioctl)(so,
                       cmd, data, ifp);
 #endif  #endif
                         error = (*so->so_proto->pr_usrreqs->pr_ioctl)(so,  
                             cmd, data, 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 = splnet();
                         if_up(ifp);                          if_up(ifp);
                         splx(s);                          splx(s);
                 }                  }
Line 3177  ifreq_setaddr(u_long cmd, struct ifreq *
Line 2841  ifreq_setaddr(u_long cmd, struct ifreq *
         struct ifreq ifrb;          struct ifreq ifrb;
         struct oifreq *oifr = NULL;          struct oifreq *oifr = NULL;
         u_long ocmd = cmd;          u_long ocmd = cmd;
         cmd = (*vec_compat_cvtcmd)(cmd);          cmd = compat_cvtcmd(cmd);
         if (cmd != ocmd) {          if (cmd != ocmd) {
                 oifr = (struct oifreq *)(void *)ifr;                  oifr = (struct oifreq *)(void *)ifr;
                 ifr = &ifrb;                  ifr = &ifrb;
Line 3207  static int
Line 2871  static int
 if_transmit(struct ifnet *ifp, struct mbuf *m)  if_transmit(struct ifnet *ifp, struct mbuf *m)
 {  {
         int s, error;          int s, error;
         size_t pktlen = m->m_pkthdr.len;  
         bool mcast = (m->m_flags & M_MCAST) != 0;  
   
         s = splnet();          s = splnet();
   
           /*
            * If NET_MPSAFE is not defined , IFQ_LOCK() is nop.
            * use KERNEL_LOCK instead of ifq_lock.
            */
   #ifndef NET_MPSAFE
           KERNEL_LOCK(1, NULL);
   #endif
         IFQ_ENQUEUE(&ifp->if_snd, m, error);          IFQ_ENQUEUE(&ifp->if_snd, m, error);
   #ifndef NET_MPSAFE
           KERNEL_UNLOCK_ONE(NULL);
   #endif
         if (error != 0) {          if (error != 0) {
                 /* mbuf is already freed */                  /* mbuf is already freed */
                 goto out;                  goto out;
         }          }
   
         ifp->if_obytes += pktlen;          ifp->if_obytes += m->m_pkthdr.len;;
         if (mcast)          if (m->m_flags & M_MCAST)
                 ifp->if_omcasts++;                  ifp->if_omcasts++;
   
         if ((ifp->if_flags & IFF_OACTIVE) == 0)          if ((ifp->if_flags & IFF_OACTIVE) == 0)
Line 3243  if_transmit_lock(struct ifnet *ifp, stru
Line 2915  if_transmit_lock(struct ifnet *ifp, stru
         } else {          } else {
                 KERNEL_UNLOCK_ONE(NULL);                  KERNEL_UNLOCK_ONE(NULL);
                 error = (*ifp->if_transmit)(ifp, m);                  error = (*ifp->if_transmit)(ifp, m);
                 /* mbuf is alredy freed */  
         }          }
 #else /* !ALTQ */  #else /* !ALTQ */
         error = (*ifp->if_transmit)(ifp, m);          error = (*ifp->if_transmit)(ifp, m);
         /* mbuf is alredy freed */  
 #endif /* !ALTQ */  #endif /* !ALTQ */
   
         return error;          return error;
Line 3591  out0:
Line 3261  out0:
         return error;          return error;
 }  }
   
 static void  SYSCTL_SETUP(sysctl_net_sdl_setup, "sysctl net.sdl subtree setup")
 if_sysctl_setup(struct sysctllog **clog)  
 {  {
         const struct sysctlnode *rnode = NULL;          const struct sysctlnode *rnode = NULL;
   
Line 3602  if_sysctl_setup(struct sysctllog **clog)
Line 3271  if_sysctl_setup(struct sysctllog **clog)
                        SYSCTL_DESCR("Get active link-layer address"),                         SYSCTL_DESCR("Get active link-layer address"),
                        if_sdl_sysctl, 0, NULL, 0,                         if_sdl_sysctl, 0, NULL, 0,
                        CTL_NET, CTL_CREATE, CTL_EOL);                         CTL_NET, CTL_CREATE, CTL_EOL);
   
 #if defined(INET)  
         sysctl_net_pktq_setup(NULL, PF_INET);  
 #endif  
 #ifdef INET6  
         if (in6_present)  
                 sysctl_net_pktq_setup(NULL, PF_INET6);  
 #endif  
 }  }

Legend:
Removed from v.1.354.2.6  
changed lines
  Added in v.1.355

CVSweb <webmaster@jp.NetBSD.org>