Hello,

just in case there is yet another brave soul running the diff below:

    Hrvoje has managed to trip the ASSERT() in ip_send() function at
    line 1843. I assume the ip6_send() is prone to same error.

I'll try to figure out what's going on and send updated diff shortly.

Big thanks to Hrvoje for hitting the problem before the change made it to tree.

regards
sasha

> --------8<---------------8<---------------8<------------------8<--------
> diff --git a/sys/net/if.c b/sys/net/if.c
> index e9e9f07add1..6ef5d2f6e3b 100644
> --- a/sys/net/if.c
> +++ b/sys/net/if.c
> @@ -224,7 +224,9 @@ int       net_livelocked(void);
>  int  ifq_congestion;
>  
>  int           netisr;
> -struct taskq *softnettq;
> +
> +#define      SOFTNET_TASKS   1
> +struct taskq *softnettq[SOFTNET_TASKS];
>  
>  struct task if_input_task_locked = TASK_INITIALIZER(if_netisr, NULL);
>  
> @@ -240,6 +242,8 @@ struct rwlock netlock = RWLOCK_INITIALIZER("netlock");
>  void
>  ifinit(void)
>  {
> +     unsigned int    i;
> +
>       /*
>        * most machines boot with 4 or 5 interfaces, so size the initial map
>        * to accomodate this
> @@ -248,9 +252,11 @@ ifinit(void)
>  
>       timeout_set(&net_tick_to, net_tick, &net_tick_to);
>  
> -     softnettq = taskq_create("softnet", 1, IPL_NET, TASKQ_MPSAFE);
> -     if (softnettq == NULL)
> -             panic("unable to create softnet taskq");
> +     for (i = 0; i < SOFTNET_TASKS; i++) {
> +             softnettq[i] = taskq_create("softnet", 1, IPL_NET, 
> TASKQ_MPSAFE);
> +             if (softnettq[i] == NULL)
> +                     panic("unable to create softnet taskq");
> +     }
>  
>       net_tick(&net_tick_to);
>  }
> @@ -725,7 +731,7 @@ if_input(struct ifnet *ifp, struct mbuf_list *ml)
>  #endif
>  
>       if (mq_enlist(&ifp->if_inputqueue, ml) == 0)
> -             task_add(softnettq, ifp->if_inputtask);
> +             task_add(net_tq(ifp->if_index), ifp->if_inputtask);
>  }
>  
>  int
> @@ -1025,15 +1031,15 @@ if_detach(struct ifnet *ifp)
>       ifp->if_watchdog = NULL;
>  
>       /* Remove the input task */
> -     task_del(softnettq, ifp->if_inputtask);
> +     task_del(net_tq(ifp->if_index), ifp->if_inputtask);
>       mq_purge(&ifp->if_inputqueue);
>  
>       /* Remove the watchdog timeout & task */
>       timeout_del(ifp->if_slowtimo);
> -     task_del(softnettq, ifp->if_watchdogtask);
> +     task_del(net_tq(ifp->if_index), ifp->if_watchdogtask);
>  
>       /* Remove the link state task */
> -     task_del(softnettq, ifp->if_linkstatetask);
> +     task_del(net_tq(ifp->if_index), ifp->if_linkstatetask);
>  
>  #if NBPFILTER > 0
>       bpfdetach(ifp);
> @@ -1583,7 +1589,7 @@ if_linkstate(struct ifnet *ifp)
>  void
>  if_link_state_change(struct ifnet *ifp)
>  {
> -     task_add(softnettq, ifp->if_linkstatetask);
> +     task_add(net_tq(ifp->if_index), ifp->if_linkstatetask);
>  }
>  
>  /*
> @@ -1599,7 +1605,7 @@ if_slowtimo(void *arg)
>  
>       if (ifp->if_watchdog) {
>               if (ifp->if_timer > 0 && --ifp->if_timer == 0)
> -                     task_add(softnettq, ifp->if_watchdogtask);
> +                     task_add(net_tq(ifp->if_index), ifp->if_watchdogtask);
>               timeout_add(ifp->if_slowtimo, hz / IFNET_SLOWHZ);
>       }
>       splx(s);
> @@ -2881,3 +2887,13 @@ unhandled_af(int af)
>  {
>       panic("unhandled af %d", af);
>  }
> +
> +struct taskq *
> +net_tq(unsigned int ifindex)
> +{
> +     struct taskq *t = NULL;
> +
> +     t = softnettq[ifindex % SOFTNET_TASKS];
> +
> +     return (t);
> +}
> diff --git a/sys/net/if.h b/sys/net/if.h
> index 89867eac340..6a0770a8ea0 100644
> --- a/sys/net/if.h
> +++ b/sys/net/if.h
> @@ -489,6 +489,7 @@ void      if_congestion(void);
>  int  if_congested(void);
>  __dead void  unhandled_af(int);
>  int  if_setlladdr(struct ifnet *, const uint8_t *);
> +struct taskq * net_tq(unsigned int);
>  
>  #endif /* _KERNEL */
>  
> diff --git a/sys/net/if_loop.c b/sys/net/if_loop.c
> index 277e7f966a2..e9f58a4ee52 100644
> --- a/sys/net/if_loop.c
> +++ b/sys/net/if_loop.c
> @@ -244,7 +244,7 @@ looutput(struct ifnet *ifp, struct mbuf *m, struct 
> sockaddr *dst,
>       m->m_pkthdr.ph_family = dst->sa_family;
>       if (mq_enqueue(&ifp->if_inputqueue, m))
>               return ENOBUFS;
> -     task_add(softnettq, ifp->if_inputtask);
> +     task_add(net_tq(ifp->if_index), ifp->if_inputtask);
>  
>       return (0);
>  }
> diff --git a/sys/net/if_pflow.c b/sys/net/if_pflow.c
> index 38efb02be7e..91a61fe4c15 100644
> --- a/sys/net/if_pflow.c
> +++ b/sys/net/if_pflow.c
> @@ -286,7 +286,7 @@ pflow_clone_destroy(struct ifnet *ifp)
>       if (timeout_initialized(&sc->sc_tmo_tmpl))
>               timeout_del(&sc->sc_tmo_tmpl);
>       pflow_flush(sc);
> -     task_del(softnettq, &sc->sc_outputtask);
> +     task_del(net_tq(ifp->if_index), &sc->sc_outputtask);
>       mq_purge(&sc->sc_outputqueue);
>       m_freem(sc->send_nam);
>       if (sc->so != NULL) {
> @@ -1087,7 +1087,7 @@ pflow_sendout_v5(struct pflow_softc *sc)
>       h->time_sec = htonl(tv.tv_sec);                 /* XXX 2038 */
>       h->time_nanosec = htonl(tv.tv_nsec);
>       if (mq_enqueue(&sc->sc_outputqueue, m) == 0)
> -             task_add(softnettq, &sc->sc_outputtask);
> +             task_add(net_tq(ifp->if_index), &sc->sc_outputtask);
>       return (0);
>  }
>  
> @@ -1149,7 +1149,7 @@ pflow_sendout_ipfix(struct pflow_softc *sc, sa_family_t 
> af)
>       sc->sc_sequence += count;
>       h10->observation_dom = htonl(PFLOW_ENGINE_TYPE);
>       if (mq_enqueue(&sc->sc_outputqueue, m) == 0)
> -             task_add(softnettq, &sc->sc_outputtask);
> +             task_add(net_tq(ifp->if_index), &sc->sc_outputtask);
>       return (0);
>  }
>  
> @@ -1191,7 +1191,7 @@ pflow_sendout_ipfix_tmpl(struct pflow_softc *sc)
>  
>       timeout_add_sec(&sc->sc_tmo_tmpl, PFLOW_TMPL_TIMEOUT);
>       if (mq_enqueue(&sc->sc_outputqueue, m) == 0)
> -             task_add(softnettq, &sc->sc_outputtask);
> +             task_add(net_tq(ifp->if_index), &sc->sc_outputtask);
>       return (0);
>  }
>  
> diff --git a/sys/net/if_var.h b/sys/net/if_var.h
> index 85c4836255f..7ca5e60f1c1 100644
> --- a/sys/net/if_var.h
> +++ b/sys/net/if_var.h
> @@ -298,7 +298,6 @@ int               niq_enlist(struct niqueue *, struct 
> mbuf_list *);
>      sysctl_mq((_n), (_l), (_op), (_olp), (_np), (_nl), &(_niq)->ni_q)
>  
>  extern struct ifnet_head ifnet;
> -extern struct taskq *softnettq;
>  
>  void if_start(struct ifnet *);
>  int  if_enqueue_try(struct ifnet *, struct mbuf *);
> diff --git a/sys/net/netisr.h b/sys/net/netisr.h
> index 813ddd6d2bb..7df2c6faa47 100644
> --- a/sys/net/netisr.h
> +++ b/sys/net/netisr.h
> @@ -75,7 +75,7 @@ void        pipexintr(void);
>  #define      schednetisr(anisr)                                              
> \
>  do {                                                                 \
>       atomic_setbits_int(&netisr, (1 << (anisr)));                    \
> -     task_add(softnettq, &if_input_task_locked);                     \
> +     task_add(net_tq(0), &if_input_task_locked);                     \
>  } while (/* CONSTCOND */0)
>  
>  #endif /* _KERNEL */
> diff --git a/sys/net/pf.c b/sys/net/pf.c
> index 0133aeeb63c..20f2c0a3f13 100644
> --- a/sys/net/pf.c
> +++ b/sys/net/pf.c
> @@ -1222,7 +1222,7 @@ pf_purge_expired_rules(void)
>  void
>  pf_purge_timeout(void *unused)
>  {
> -     task_add(softnettq, &pf_purge_task);
> +     task_add(net_tq(0), &pf_purge_task);
>  }
>  
>  void
> diff --git a/sys/net/pf_ioctl.c b/sys/net/pf_ioctl.c
> index de40e934112..18eecaf9647 100644
> --- a/sys/net/pf_ioctl.c
> +++ b/sys/net/pf_ioctl.c
> @@ -2310,7 +2310,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, 
> struct proc *p)
>                           pf_default_rule_new.timeout[i];
>                       if (pf_default_rule.timeout[i] == PFTM_INTERVAL &&
>                           pf_default_rule.timeout[i] < old)
> -                             task_add(softnettq, &pf_purge_task);
> +                             task_add(net_tq(0), &pf_purge_task);
>               }
>               pfi_xcommit();
>               pf_trans_set_commit();
> diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
> index 95c9194efcb..e8c43d4022f 100644
> --- a/sys/netinet/ip_input.c
> +++ b/sys/netinet/ip_input.c
> @@ -1839,5 +1839,6 @@ void
>  ip_send(struct mbuf *m)
>  {
>       mq_enqueue(&ipsend_mq, m);
> -     task_add(softnettq, &ipsend_task);
> +     KASSERT((m->m_flags & M_PKTHDR) == M_PKTHDR);
> +     task_add(net_tq(m->m_pkthdr.ph_ifidx), &ipsend_task);
>  }
> diff --git a/sys/netinet6/ip6_input.c b/sys/netinet6/ip6_input.c
> index d62aa8a429b..67c7b18a881 100644
> --- a/sys/netinet6/ip6_input.c
> +++ b/sys/netinet6/ip6_input.c
> @@ -1477,5 +1477,6 @@ void
>  ip6_send(struct mbuf *m)
>  {
>       mq_enqueue(&ip6send_mq, m);
> -     task_add(softnettq, &ip6send_task);
> +     KASSERT((m->m_flags & M_PKTHDR) == M_PKTHDR);
> +     task_add(net_tq(m->m_pkthdr.ph_ifidx), &ip6send_task);
>  }
> diff --git a/sys/netinet6/nd6.c b/sys/netinet6/nd6.c
> index 9a94a753a6d..b27b5c1b708 100644
> --- a/sys/netinet6/nd6.c
> +++ b/sys/netinet6/nd6.c
> @@ -486,7 +486,7 @@ nd6_expire(void *unused)
>  void
>  nd6_expire_timer(void *unused)
>  {
> -     task_add(softnettq, &nd6_expire_task);
> +     task_add(net_tq(0), &nd6_expire_task);
>  }
>  
>  /*
> 

Reply via email to