On Wed, Dec 27, 2017 at 04:55:49PM +0100, Martin Pieuchot wrote: > Updated diff below.
OK bluhm@ > Index: net/if.c > =================================================================== > RCS file: /cvs/src/sys/net/if.c,v > retrieving revision 1.531 > diff -u -p -r1.531 if.c > --- net/if.c 15 Dec 2017 01:37:30 -0000 1.531 > +++ net/if.c 27 Dec 2017 15:54:18 -0000 > @@ -1854,13 +1854,12 @@ ifioctl(struct socket *so, u_long cmd, c > oif_flags = ifp->if_flags; > oif_xflags = ifp->if_xflags; > > - NET_LOCK(); > - > switch (cmd) { > case SIOCIFAFATTACH: > case SIOCIFAFDETACH: > if ((error = suser(p, 0)) != 0) > break; > + NET_LOCK(); > switch (ifar->ifar_af) { > case AF_INET: > /* attach is a noop for AF_INET */ > @@ -1878,22 +1877,21 @@ ifioctl(struct socket *so, u_long cmd, c > default: > error = EAFNOSUPPORT; > } > + NET_UNLOCK(); > break; > > case SIOCSIFFLAGS: > if ((error = suser(p, 0)) != 0) > break; > > + NET_LOCK(); > ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) | > (ifr->ifr_flags & ~IFF_CANTCHANGE); > > error = (*ifp->if_ioctl)(ifp, cmd, data); > if (error != 0) { > ifp->if_flags = oif_flags; > - break; > - } > - > - if (ISSET(oif_flags ^ ifp->if_flags, IFF_UP)) { > + } else if (ISSET(oif_flags ^ ifp->if_flags, IFF_UP)) { > s = splnet(); > if (ISSET(ifp->if_flags, IFF_UP)) > if_up(ifp); > @@ -1901,17 +1899,21 @@ ifioctl(struct socket *so, u_long cmd, c > if_down(ifp); > splx(s); > } > + NET_UNLOCK(); > break; > > case SIOCSIFXFLAGS: > if ((error = suser(p, 0)) != 0) > break; > > + NET_LOCK(); > #ifdef INET6 > if (ISSET(ifr->ifr_flags, IFXF_AUTOCONF6)) { > error = in6_ifattach(ifp); > - if (error != 0) > + if (error != 0) { > + NET_UNLOCK(); > break; > + } > } > #endif /* INET6 */ > > @@ -1942,8 +1944,6 @@ ifioctl(struct socket *so, u_long cmd, c > ifp->if_xflags |= IFXF_WOL; > error = ifp->if_wol(ifp, 1); > splx(s); > - if (error) > - break; > } > if (ISSET(ifp->if_xflags, IFXF_WOL) && > !ISSET(ifr->ifr_flags, IFXF_WOL)) { > @@ -1951,8 +1951,6 @@ ifioctl(struct socket *so, u_long cmd, c > ifp->if_xflags &= ~IFXF_WOL; > error = ifp->if_wol(ifp, 0); > splx(s); > - if (error) > - break; > } > } else if (ISSET(ifr->ifr_flags, IFXF_WOL)) { > ifr->ifr_flags &= ~IFXF_WOL; > @@ -1960,20 +1958,26 @@ ifioctl(struct socket *so, u_long cmd, c > } > #endif > > - ifp->if_xflags = (ifp->if_xflags & IFXF_CANTCHANGE) | > - (ifr->ifr_flags & ~IFXF_CANTCHANGE); > + if (error == 0) > + ifp->if_xflags = (ifp->if_xflags & IFXF_CANTCHANGE) | > + (ifr->ifr_flags & ~IFXF_CANTCHANGE); > + NET_UNLOCK(); > break; > > case SIOCSIFMETRIC: > if ((error = suser(p, 0)) != 0) > break; > + NET_LOCK(); > ifp->if_metric = ifr->ifr_metric; > + NET_UNLOCK(); > break; > > case SIOCSIFMTU: > if ((error = suser(p, 0)) != 0) > break; > + NET_LOCK(); > error = (*ifp->if_ioctl)(ifp, cmd, data); > + NET_UNLOCK(); > if (!error) > rtm_ifchg(ifp); > break; > @@ -2013,27 +2017,34 @@ ifioctl(struct socket *so, u_long cmd, c > case SIOCSIFRDOMAIN: > if ((error = suser(p, 0)) != 0) > break; > + NET_LOCK(); > error = if_setrdomain(ifp, ifr->ifr_rdomainid); > + NET_UNLOCK(); > break; > > case SIOCAIFGROUP: > if ((error = suser(p, 0))) > break; > - if ((error = if_addgroup(ifp, ifgr->ifgr_group))) > - break; > - error = (*ifp->if_ioctl)(ifp, cmd, data); > - if (error == ENOTTY) > - error = 0; > + NET_LOCK(); > + error = if_addgroup(ifp, ifgr->ifgr_group); > + if (error == 0) { > + error = (*ifp->if_ioctl)(ifp, cmd, data); > + if (error == ENOTTY) > + error = 0; > + } > + NET_UNLOCK(); > break; > > case SIOCDIFGROUP: > if ((error = suser(p, 0))) > break; > + NET_LOCK(); > error = (*ifp->if_ioctl)(ifp, cmd, data); > if (error == ENOTTY) > error = 0; > if (error == 0) > error = if_delgroup(ifp, ifgr->ifgr_group); > + NET_UNLOCK(); > break; > > case SIOCSIFLLADDR: > @@ -2045,6 +2056,7 @@ ifioctl(struct socket *so, u_long cmd, c > error = EINVAL; > break; > } > + NET_LOCK(); > switch (ifp->if_type) { > case IFT_ETHER: > case IFT_CARP: > @@ -2063,6 +2075,7 @@ ifioctl(struct socket *so, u_long cmd, c > > if (error == 0) > ifnewlladdr(ifp); > + NET_UNLOCK(); > break; > > case SIOCSIFLLPRIO: > @@ -2072,7 +2085,9 @@ ifioctl(struct socket *so, u_long cmd, c > error = EINVAL; > break; > } > + NET_LOCK(); > ifp->if_llprio = ifr->ifr_llprio; > + NET_UNLOCK(); > break; > > case SIOCDIFPHYADDR: > @@ -2090,11 +2105,13 @@ ifioctl(struct socket *so, u_long cmd, c > break; > /* FALLTHROUGH */ > default: > + NET_LOCK(); > error = ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL, > (struct mbuf *) cmd, (struct mbuf *) data, > (struct mbuf *) ifp, p)); > if (error == EOPNOTSUPP) > error = ((*ifp->if_ioctl)(ifp, cmd, data)); > + NET_UNLOCK(); > break; > } > > @@ -2103,8 +2120,6 @@ ifioctl(struct socket *so, u_long cmd, c > > if (((oif_flags ^ ifp->if_flags) & IFF_UP) != 0) > getmicrotime(&ifp->if_lastchange); > - > - NET_UNLOCK(); > > return (error); > } > Index: net/if_var.h > =================================================================== > RCS file: /cvs/src/sys/net/if_var.h,v > retrieving revision 1.85 > diff -u -p -r1.85 if_var.h > --- net/if_var.h 15 Dec 2017 01:37:30 -0000 1.85 > +++ net/if_var.h 27 Dec 2017 15:39:36 -0000 > @@ -91,7 +91,14 @@ struct if_clone { > > #define IF_CLONE_INITIALIZER(name, create, destroy) > \ > { { 0 }, name, sizeof(name) - 1, create, destroy } > - > +/* > + * Locks used to protect struct members in this file: > + * I immutable after creation > + * d protection left do the driver > + * c only used in ioctl or routing socket contexts (kernel lock) > + * k kernel lock > + * N net lock > + */ > /* > * Structure defining a queue for a network interface. > * > @@ -102,17 +109,17 @@ TAILQ_HEAD(ifnet_head, ifnet); /* the a > struct ifnet { /* and the entries */ > void *if_softc; /* lower-level data for this if */ > struct refcnt if_refcnt; > - TAILQ_ENTRY(ifnet) if_list; /* all struct ifnets are chained */ > - TAILQ_HEAD(, ifaddr) if_addrlist; /* linked list of addresses per if */ > - TAILQ_HEAD(, ifmaddr) if_maddrlist; /* list of multicast records */ > - TAILQ_HEAD(, ifg_list) if_groups; /* linked list of groups per if */ > - struct hook_desc_head *if_addrhooks; /* address change callbacks */ > - struct hook_desc_head *if_linkstatehooks; /* link change callbacks */ > - struct hook_desc_head *if_detachhooks; /* detach callbacks */ > - /* check or clean routes (+ or -)'d */ > + TAILQ_ENTRY(ifnet) if_list; /* [k] all struct ifnets are chained */ > + TAILQ_HEAD(, ifaddr) if_addrlist; /* [N] list of addresses per if */ > + TAILQ_HEAD(, ifmaddr) if_maddrlist; /* [N] list of multicast records */ > + TAILQ_HEAD(, ifg_list) if_groups; /* [N] list of groups per if */ > + struct hook_desc_head *if_addrhooks; /* [I] address change callbacks */ > + struct hook_desc_head *if_linkstatehooks; /* [I] link change callbacks*/ > + struct hook_desc_head *if_detachhooks; /* [I] detach callbacks */ > + /* [I] check or clean routes (+ or -)'d */ > void (*if_rtrequest)(struct ifnet *, int, struct rtentry *); > - char if_xname[IFNAMSIZ]; /* external name (name + unit) */ > - int if_pcount; /* number of promiscuous listeners */ > + char if_xname[IFNAMSIZ]; /* [I] external name (name + unit) */ > + int if_pcount; /* [k] # of promiscuous listeners */ > caddr_t if_bpf; /* packet filter structure */ > caddr_t if_bridgeport; /* used by bridge ports */ > caddr_t if_switchport; /* used by switch ports */ > @@ -125,48 +132,43 @@ struct ifnet { /* and the > entries */ > } if_carp_ptr; > #define if_carp if_carp_ptr.carp_s > #define if_carpdev if_carp_ptr.carp_d > - unsigned int if_index; /* numeric abbreviation for this if */ > + unsigned int if_index; /* [I] unique index for this if */ > short if_timer; /* time 'til if_watchdog called */ > - unsigned short if_flags; /* up/down, broadcast, etc. */ > - int if_xflags; /* extra softnet flags */ > + unsigned short if_flags; /* [N] up/down, broadcast, etc. */ > + int if_xflags; /* [N] extra softnet flags */ > struct if_data if_data; /* stats and other data about if */ > - u_int32_t if_hardmtu; /* maximum MTU device supports */ > - char if_description[IFDESCRSIZE]; /* interface description */ > - u_short if_rtlabelid; /* next route label */ > - u_int8_t if_priority; > - u_int8_t if_llprio; /* link layer priority */ > - struct timeout *if_slowtimo; /* watchdog timeout */ > - struct task *if_watchdogtask; /* watchdog task */ > - struct task *if_linkstatetask; /* task to do route updates */ > + uint32_t if_hardmtu; /* [d] maximum MTU device supports */ > + char if_description[IFDESCRSIZE]; /* [c] interface description */ > + u_short if_rtlabelid; /* [c] next route label */ > + uint8_t if_priority; /* [c] route priority offset */ > + uint8_t if_llprio; /* [N] link layer priority */ > + struct timeout *if_slowtimo; /* [I] watchdog timeout */ > + struct task *if_watchdogtask; /* [I] watchdog task */ > + struct task *if_linkstatetask; /* [I] task to do route updates */ > > /* procedure handles */ > SRPL_HEAD(, ifih) if_inputs; /* input routines (dequeue) */ > - > - /* output routine (enqueue) */ > int (*if_output)(struct ifnet *, struct mbuf *, struct sockaddr *, > - struct rtentry *); > - > + struct rtentry *); /* output routine (enqueue) */ > /* link level output function */ > int (*if_ll_output)(struct ifnet *, struct mbuf *, > struct sockaddr *, struct rtentry *); > - /* initiate output routine */ > - void (*if_start)(struct ifnet *); > - /* ioctl routine */ > - int (*if_ioctl)(struct ifnet *, u_long, caddr_t); > - /* timer routine */ > - void (*if_watchdog)(struct ifnet *); > - int (*if_wol)(struct ifnet *, int); > + void (*if_start)(struct ifnet *); /* initiate output */ > + int (*if_ioctl)(struct ifnet *, u_long, caddr_t); /* ioctl hook */ > + void (*if_watchdog)(struct ifnet *); /* timer routine */ > + int (*if_wol)(struct ifnet *, int); /* WoL routine **/ > > + /* queues */ > struct ifqueue if_snd; /* transmit queue */ > - struct ifqueue **if_ifqs; /* pointer to an array of sndqs */ > + struct ifqueue **if_ifqs; /* [I] pointer to an array of sndqs */ > void (*if_qstart)(struct ifqueue *); > - unsigned int if_nifqs; > + unsigned int if_nifqs; /* [I] number of output queues */ > > struct ifiqueue if_rcv; /* rx/input queue */ > - struct ifiqueue **if_iqs; /* pointer to the array of iqs */ > - unsigned int if_niqs; > + struct ifiqueue **if_iqs; /* [I] pointer to the array of iqs */ > + unsigned int if_niqs; /* [I] number of input queues */ > > - struct sockaddr_dl *if_sadl; /* pointer to our sockaddr_dl */ > + struct sockaddr_dl *if_sadl; /* [N] pointer to our sockaddr_dl */ > > void *if_afdata[AF_MAX]; > }; > @@ -189,7 +191,7 @@ struct ifnet { /* and the > entries */ > #define if_iqdrops if_data.ifi_iqdrops > #define if_oqdrops if_data.ifi_oqdrops > #define if_noproto if_data.ifi_noproto > -#define if_lastchange if_data.ifi_lastchange > +#define if_lastchange if_data.ifi_lastchange /* [c] last op. state > change */ > #define if_capabilities if_data.ifi_capabilities > #define if_rdomain if_data.ifi_rdomain >