On Sun, Nov 23, 2014 at 02:10:24AM +0100, Mike Belopuhov wrote:
> Hi,
> 
> This removes the system wide if_slowtimo timeout and lets every
> interface with a valid if_watchdog method register it's own.
> The rational is to get rid of the ifnet loop in the softclock
> context to avoid further complications with concurrent access
> to the ifnet list.  This might also save some cpu cycles in the
> runtime if number of interfaces is large while only a fraction
> all of them have a watchdog routine.
> 
> This has originally come up on NetBSD mailing lists with some
> rather complicated locking strategy.  Masao Uebayashi has later
> proposed a similar solution.
> 
> The diff was looked at and corrected by mpi@.  I've tested the
> trunk and a system build as well.  OK?
> 
> Index: sys/net/if.c
> ===================================================================
> RCS file: /home/cvs/src/sys/net/if.c,v
> retrieving revision 1.303
> diff -u -p -r1.303 if.c
> --- sys/net/if.c      3 Nov 2014 11:02:08 -0000       1.303
> +++ sys/net/if.c      22 Nov 2014 16:25:34 -0000
> @@ -135,7 +135,6 @@ void      if_attach_common(struct ifnet *);
>  void if_detach_queues(struct ifnet *, struct ifqueue *);
>  void if_detached_start(struct ifnet *);
>  int  if_detached_ioctl(struct ifnet *, u_long, caddr_t);
> -void if_detached_watchdog(struct ifnet *);
>  
>  int  if_getgroup(caddr_t, struct ifnet *);
>  int  if_getgroupmembers(caddr_t);
> @@ -171,12 +170,8 @@ int      net_livelocked(void);
>  void
>  ifinit()
>  {
> -     static struct timeout if_slowtim;
> -
> -     timeout_set(&if_slowtim, if_slowtimo, &if_slowtim);
>       timeout_set(&net_tick_to, net_tick, &net_tick_to);
>  
> -     if_slowtimo(&if_slowtim);
>       net_tick(&net_tick_to);
>  }
>  
> @@ -272,6 +267,11 @@ if_attachsetup(struct ifnet *ifp)
>       pfi_attach_ifnet(ifp);
>  #endif
>  
> +     ifp->if_wdtimo = malloc(sizeof(*ifp->if_wdtimo), M_TEMP,
> +         M_WAITOK|M_ZERO);
> +     timeout_set(ifp->if_wdtimo, if_slowtimo, ifp);
> +     if_slowtimo(ifp);
> +

Please do not use M_TEMP for this (this is not a temporary buffer).
Maybe even remove the need to allocate the struct timeout (which requires
if_var.h to include sys/timeout.h and adds 24 / 40 bytes to ifnet even
when there is no watchdog used (like on vlan)).

In any case I think M_DEVBUF is the right type.

We could also rename if_slowtimo to something more concrete like
if_watchdog_timeout but that's just a bikeshed.

>       /* Announce the interface. */
>       rt_ifannouncemsg(ifp, IFAN_ARRIVAL);
>  }
> @@ -483,7 +483,7 @@ if_detach(struct ifnet *ifp)
>       ifp->if_flags &= ~IFF_OACTIVE;
>       ifp->if_start = if_detached_start;
>       ifp->if_ioctl = if_detached_ioctl;
> -     ifp->if_watchdog = if_detached_watchdog;
> +     ifp->if_watchdog = NULL;
>  
>       /*
>        * Call detach hooks from head to tail.  To make sure detach
> @@ -492,6 +492,10 @@ if_detach(struct ifnet *ifp)
>        */
>       dohooks(ifp->if_detachhooks, HOOK_REMOVE | HOOK_FREE);
>  
> +     /* Remove the watchdog timeout */
> +     timeout_del(ifp->if_wdtimo);
> +     free(ifp->if_wdtimo, M_TEMP, sizeof(*ifp->if_wdtimo));
> +
>  #if NBRIDGE > 0
>       /* Remove the interface from any bridge it is part of.  */
>       if (ifp->if_bridgeport)
> @@ -1162,25 +1166,22 @@ if_link_state_change_task(void *arg, voi
>  }
>  
>  /*
> - * Handle interface watchdog timer routines.  Called
> - * from softclock, we decrement timers (if set) and
> + * Handle interface watchdog timer routine.  Called
> + * from softclock, we decrement timer (if set) and
>   * call the appropriate interface routine on expiration.
>   */
>  void
>  if_slowtimo(void *arg)
>  {
> -     struct timeout *to = (struct timeout *)arg;
> -     struct ifnet *ifp;
> +     struct ifnet *ifp = arg;
>       int s = splnet();
>  
> -     TAILQ_FOREACH(ifp, &ifnet, if_list) {
> -             if (ifp->if_timer == 0 || --ifp->if_timer)
> -                     continue;
> -             if (ifp->if_watchdog)
> +     if (ifp->if_watchdog) {
> +             if (ifp->if_timer > 0 && --ifp->if_timer == 0)
>                       (*ifp->if_watchdog)(ifp);
> +             timeout_add(ifp->if_wdtimo, hz / IFNET_SLOWHZ);
>       }
>       splx(s);
> -     timeout_add(to, hz / IFNET_SLOWHZ);
>  }
>  
>  /*
> @@ -1824,12 +1825,6 @@ int
>  if_detached_ioctl(struct ifnet *ifp, u_long a, caddr_t b)
>  {
>       return ENODEV;
> -}
> -
> -void
> -if_detached_watchdog(struct ifnet *ifp)
> -{
> -     /* nothing */
>  }
>  
>  /*
> Index: sys/net/if_trunk.c
> ===================================================================
> RCS file: /home/cvs/src/sys/net/if_trunk.c,v
> retrieving revision 1.91
> diff -u -p -r1.91 if_trunk.c
> --- sys/net/if_trunk.c        18 Nov 2014 02:37:31 -0000      1.91
> +++ sys/net/if_trunk.c        22 Nov 2014 16:25:34 -0000
> @@ -344,11 +344,13 @@ trunk_port_create(struct trunk_softc *tr
>       tp->tp_iftype = ifp->if_type;
>       ifp->if_type = IFT_IEEE8023ADLAG;
>       ifp->if_tp = (caddr_t)tp;
> -     tp->tp_watchdog = ifp->if_watchdog;
> -     ifp->if_watchdog = trunk_port_watchdog;
>       tp->tp_ioctl = ifp->if_ioctl;
>       ifp->if_ioctl = trunk_port_ioctl;
>  
> +     timeout_del(ifp->if_wdtimo);
> +     tp->tp_watchdog = ifp->if_watchdog;
> +     ifp->if_watchdog = trunk_port_watchdog;
> +
>       tp->tp_if = ifp;
>       tp->tp_trunk = tr;
>  
> @@ -427,8 +429,8 @@ trunk_port_destroy(struct trunk_port *tp
>  
>       /* Restore interface */
>       ifp->if_type = tp->tp_iftype;
> -     ifp->if_watchdog = tp->tp_watchdog;
>       ifp->if_ioctl = tp->tp_ioctl;
> +     ifp->if_watchdog = tp->tp_watchdog;
>       ifp->if_tp = NULL;
>  
>       hook_disestablish(ifp->if_linkstatehooks, tp->lh_cookie);
> @@ -464,6 +466,9 @@ trunk_port_destroy(struct trunk_port *tp
>  
>       /* Update trunk capabilities */
>       tr->tr_capabilities = trunk_capabilities(tr);
> +
> +     /* Reestablish watchdog timeout */
> +     if_slowtimo(ifp);
>  
>       return (0);
>  }
> Index: sys/net/if_var.h
> ===================================================================
> RCS file: /home/cvs/src/sys/net/if_var.h,v
> retrieving revision 1.12
> diff -u -p -r1.12 if_var.h
> --- sys/net/if_var.h  8 Jul 2014 04:02:14 -0000       1.12
> +++ sys/net/if_var.h  22 Nov 2014 16:25:34 -0000
> @@ -72,6 +72,7 @@ struct mbuf;
>  struct proc;
>  struct rtentry;
>  struct socket;
> +struct timeout;
>  struct ether_header;
>  struct arpcom;
>  struct rt_addrinfo;
> @@ -147,6 +148,7 @@ struct ifnet {                            /* and the 
> entries */
>       char    if_description[IFDESCRSIZE]; /* interface description */
>       u_short if_rtlabelid;           /* next route label */
>       u_int8_t if_priority;
> +     struct  timeout *if_wdtimo;     /* watchdog timeout */
>  
>       /* procedure handles */
>                                       /* output routine (enqueue) */
> 

-- 
:wq Claudio

Reply via email to