diff options
Diffstat (limited to 'sys/net')
-rw-r--r-- | sys/net/ieee8023ad_lacp.c | 81 | ||||
-rw-r--r-- | sys/net/if.c | 9 | ||||
-rw-r--r-- | sys/net/if_arp.h | 30 | ||||
-rw-r--r-- | sys/net/if_gif.c | 14 | ||||
-rw-r--r-- | sys/net/if_lagg.c | 30 | ||||
-rw-r--r-- | sys/net/if_lagg.h | 5 | ||||
-rw-r--r-- | sys/net/if_var.h | 2 | ||||
-rw-r--r-- | sys/net/rtsock.c | 15 | ||||
-rw-r--r-- | sys/net/vnet.h | 50 |
9 files changed, 200 insertions, 36 deletions
diff --git a/sys/net/ieee8023ad_lacp.c b/sys/net/ieee8023ad_lacp.c index 87c4e9b..a2d42e0 100644 --- a/sys/net/ieee8023ad_lacp.c +++ b/sys/net/ieee8023ad_lacp.c @@ -188,29 +188,43 @@ static void lacp_dprintf(const struct lacp_port *, const char *, ...) __attribute__((__format__(__printf__, 2, 3))); static int lacp_debug = 0; -SYSCTL_INT(_net, OID_AUTO, lacp_debug, CTLFLAG_RW | CTLFLAG_TUN, +SYSCTL_NODE(_net_link_lagg, OID_AUTO, lacp, CTLFLAG_RD, 0, "ieee802.3ad"); +SYSCTL_INT(_net_link_lagg_lacp, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_TUN, &lacp_debug, 0, "Enable LACP debug logging (1=debug, 2=trace)"); -TUNABLE_INT("net.lacp_debug", &lacp_debug); +TUNABLE_INT("net.link.lagg.lacp.debug", &lacp_debug); -#define LACP_DPRINTF(a) if (lacp_debug > 0) { lacp_dprintf a ; } -#define LACP_TRACE(a) if (lacp_debug > 1) { lacp_dprintf(a,"%s\n",__func__); } +/* bitmap of ports */ +static int lacp_rx_test = 0; +static int lacp_tx_test = 0; +SYSCTL_INT(_net_link_lagg_lacp, OID_AUTO, rxtest, CTLFLAG_RW, &lacp_rx_test, 0, + "RXTest"); +SYSCTL_INT(_net_link_lagg_lacp, OID_AUTO, txtest, CTLFLAG_RW, &lacp_tx_test, 0, + "TXTest"); + +static int lacp_strict = 1; +SYSCTL_INT(_net_link_lagg_lacp, OID_AUTO, strict, CTLFLAG_RW, &lacp_strict, + 0, "Strict spec compliance"); + +#define LACP_DPRINTF(a) if (lacp_debug & 0x01) { lacp_dprintf a ; } +#define LACP_TRACE(a) if (lacp_debug & 0x02) { lacp_dprintf(a,"%s\n",__func__); } +#define LACP_TPRINTF(a) if (lacp_debug & 0x04) { lacp_dprintf a ; } /* * partner administration variables. * XXX should be configurable. */ -static const struct lacp_peerinfo lacp_partner_admin = { +static const struct lacp_peerinfo lacp_partner_admin_optimistic = { .lip_systemid = { .lsi_prio = 0xffff }, .lip_portid = { .lpi_prio = 0xffff }, -#if 1 - /* optimistic */ .lip_state = LACP_STATE_SYNC | LACP_STATE_AGGREGATION | LACP_STATE_COLLECTING | LACP_STATE_DISTRIBUTING, -#else - /* pessimistic */ +}; + +static const struct lacp_peerinfo lacp_partner_admin_strict = { + .lip_systemid = { .lsi_prio = 0xffff }, + .lip_portid = { .lpi_prio = 0xffff }, .lip_state = 0, -#endif }; static const lacp_timer_func_t lacp_timer_funcs[LACP_NTIMER] = { @@ -301,6 +315,11 @@ lacp_pdu_input(struct lacp_port *lp, struct mbuf *m) lacp_dump_lacpdu(du); } + if ((1 << lp->lp_ifp->if_dunit) & lacp_rx_test) { + LACP_TPRINTF((lp, "Dropping RX PDU\n")); + goto bad; + } + LACP_LOCK(lsc); lacp_sm_rx(lp, du); LACP_UNLOCK(lsc); @@ -653,6 +672,7 @@ lacp_disable_distributing(struct lacp_port *lp) { struct lacp_aggregator *la = lp->lp_aggregator; struct lacp_softc *lsc = lp->lp_lsc; + struct lagg_softc *sc = lsc->lsc_softc; char buf[LACP_LAGIDSTR_MAX+1]; LACP_LOCK_ASSERT(lsc); @@ -672,6 +692,7 @@ lacp_disable_distributing(struct lacp_port *lp) TAILQ_REMOVE(&la->la_ports, lp, lp_dist_q); la->la_nports--; + sc->sc_active = la->la_nports; if (lsc->lsc_active_aggregator == la) { lacp_suppress_distributing(lsc, la); @@ -688,6 +709,7 @@ lacp_enable_distributing(struct lacp_port *lp) { struct lacp_aggregator *la = lp->lp_aggregator; struct lacp_softc *lsc = lp->lp_lsc; + struct lagg_softc *sc = lsc->lsc_softc; char buf[LACP_LAGIDSTR_MAX+1]; LACP_LOCK_ASSERT(lsc); @@ -704,6 +726,7 @@ lacp_enable_distributing(struct lacp_port *lp) KASSERT(la->la_refcnt > la->la_nports, ("aggregator refcnt invalid")); TAILQ_INSERT_HEAD(&la->la_ports, lp, lp_dist_q); la->la_nports++; + sc->sc_active = la->la_nports; lp->lp_state |= LACP_STATE_DISTRIBUTING; @@ -908,7 +931,6 @@ lacp_aggregator_bandwidth(struct lacp_aggregator *la) static void lacp_select_active_aggregator(struct lacp_softc *lsc) { - struct lagg_softc *sc = lsc->lsc_softc; struct lacp_aggregator *la; struct lacp_aggregator *best_la = NULL; uint64_t best_speed = 0; @@ -960,7 +982,6 @@ lacp_select_active_aggregator(struct lacp_softc *lsc) lacp_format_lagid_aggregator(best_la, buf, sizeof(buf)))); if (lsc->lsc_active_aggregator != best_la) { - sc->sc_ifp->if_baudrate = best_speed; lsc->lsc_active_aggregator = best_la; lacp_update_portmap(lsc); if (best_la) { @@ -976,15 +997,18 @@ lacp_select_active_aggregator(struct lacp_softc *lsc) static void lacp_update_portmap(struct lacp_softc *lsc) { + struct lagg_softc *sc = lsc->lsc_softc; struct lacp_aggregator *la; struct lacp_portmap *p; struct lacp_port *lp; + uint64_t speed; u_int newmap; int i; newmap = lsc->lsc_activemap == 0 ? 1 : 0; p = &lsc->lsc_pmap[newmap]; la = lsc->lsc_active_aggregator; + speed = 0; bzero(p, sizeof(struct lacp_portmap)); if (la != NULL && la->la_nports > 0) { @@ -993,7 +1017,9 @@ lacp_update_portmap(struct lacp_softc *lsc) TAILQ_FOREACH(lp, &la->la_ports, lp_dist_q) p->pm_map[i++] = lp; KASSERT(i == p->pm_count, ("Invalid port count")); + speed = lacp_aggregator_bandwidth(la); } + sc->sc_ifp->if_baudrate = speed; /* switch the active portmap over */ atomic_store_rel_int(&lsc->lsc_activemap, newmap); @@ -1264,6 +1290,8 @@ lacp_unselect(struct lacp_port *lp) static void lacp_sm_mux(struct lacp_port *lp) { + struct lagg_port *lgp = lp->lp_lagg; + struct lagg_softc *sc = lgp->lp_softc; enum lacp_mux_state new_state; boolean_t p_sync = (lp->lp_partner.lip_state & LACP_STATE_SYNC) != 0; @@ -1273,7 +1301,9 @@ lacp_sm_mux(struct lacp_port *lp) struct lacp_aggregator *la; if (lacp_debug > 1) - lacp_dprintf(lp, "%s: state %d\n", __func__, lp->lp_mux_state); + lacp_dprintf(lp, "%s: state= 0x%x, selected= 0x%x, " + "p_sync= 0x%x, p_collecting= 0x%x\n", __func__, + lp->lp_mux_state, selected, p_sync, p_collecting); re_eval: la = lp->lp_aggregator; @@ -1313,6 +1343,8 @@ re_eval: case LACP_MUX_DISTRIBUTING: if (selected != LACP_SELECTED || !p_sync || !p_collecting) { new_state = LACP_MUX_COLLECTING; + lacp_dprintf(lp, "Interface stopped DISTRIBUTING, possible flaping\n"); + sc->sc_flapping++; } break; default: @@ -1561,6 +1593,10 @@ lacp_sm_rx_record_pdu(struct lacp_port *lp, const struct lacpdu *du) sizeof(buf)))); } + /* XXX Hack, still need to implement 5.4.9 para 2,3,4 */ + if (lacp_strict) + lp->lp_partner.lip_state |= LACP_STATE_SYNC; + lacp_sm_ptx_update_timeout(lp, oldpstate); } @@ -1586,7 +1622,10 @@ lacp_sm_rx_record_default(struct lacp_port *lp) LACP_TRACE(lp); oldpstate = lp->lp_partner.lip_state; - lp->lp_partner = lacp_partner_admin; + if (lacp_strict) + lp->lp_partner = lacp_partner_admin_strict; + else + lp->lp_partner = lacp_partner_admin_optimistic;; lp->lp_state |= LACP_STATE_DEFAULTED; lacp_sm_ptx_update_timeout(lp, oldpstate); } @@ -1621,7 +1660,12 @@ lacp_sm_rx_update_default_selected(struct lacp_port *lp) LACP_TRACE(lp); - lacp_sm_rx_update_selected_from_peerinfo(lp, &lacp_partner_admin); + if (lacp_strict) + lacp_sm_rx_update_selected_from_peerinfo(lp, + &lacp_partner_admin_strict); + else + lacp_sm_rx_update_selected_from_peerinfo(lp, + &lacp_partner_admin_optimistic); } /* transmit machine */ @@ -1629,7 +1673,7 @@ lacp_sm_rx_update_default_selected(struct lacp_port *lp) static void lacp_sm_tx(struct lacp_port *lp) { - int error; + int error = 0; if (!(lp->lp_state & LACP_STATE_AGGREGATION) #if 1 @@ -1651,7 +1695,10 @@ lacp_sm_tx(struct lacp_port *lp) return; } - error = lacp_xmit_lacpdu(lp); + if (((1 << lp->lp_ifp->if_dunit) & lacp_tx_test) == 0) + error = lacp_xmit_lacpdu(lp); + else + LACP_TPRINTF((lp, "Dropping TX PDU\n")); if (error == 0) { lp->lp_flags &= ~LACP_PORT_NTT; diff --git a/sys/net/if.c b/sys/net/if.c index 326860d..2cb3da0 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -505,6 +505,7 @@ if_free(struct ifnet *ifp) ifp->if_flags |= IFF_DYING; /* XXX: Locking */ + CURVNET_SET_QUIET(ifp->if_vnet); IFNET_WLOCK(); KASSERT(ifp == ifnet_byindex_locked(ifp->if_index), ("%s: freeing unallocated ifnet", ifp->if_xname)); @@ -512,9 +513,9 @@ if_free(struct ifnet *ifp) ifindex_free_locked(ifp->if_index); IFNET_WUNLOCK(); - if (!refcount_release(&ifp->if_refcount)) - return; - if_free_internal(ifp); + if (refcount_release(&ifp->if_refcount)) + if_free_internal(ifp); + CURVNET_RESTORE(); } /* @@ -803,7 +804,9 @@ void if_detach(struct ifnet *ifp) { + CURVNET_SET_QUIET(ifp->if_vnet); if_detach_internal(ifp, 0); + CURVNET_RESTORE(); } static void diff --git a/sys/net/if_arp.h b/sys/net/if_arp.h index 38c6402..2dd8c32 100644 --- a/sys/net/if_arp.h +++ b/sys/net/if_arp.h @@ -113,27 +113,35 @@ struct arpcom { struct arpstat { /* Normal things that happen: */ - u_long txrequests; /* # of ARP requests sent by this host. */ - u_long txreplies; /* # of ARP replies sent by this host. */ - u_long rxrequests; /* # of ARP requests received by this host. */ - u_long rxreplies; /* # of ARP replies received by this host. */ - u_long received; /* # of ARP packets received by this host. */ + uint64_t txrequests; /* # of ARP requests sent by this host. */ + uint64_t txreplies; /* # of ARP replies sent by this host. */ + uint64_t rxrequests; /* # of ARP requests received by this host. */ + uint64_t rxreplies; /* # of ARP replies received by this host. */ + uint64_t received; /* # of ARP packets received by this host. */ - u_long arp_spares[4]; /* For either the upper or lower half. */ + uint64_t arp_spares[4]; /* For either the upper or lower half. */ /* Abnormal event and error counting: */ - u_long dropped; /* # of packets dropped waiting for a reply. */ - u_long timeouts; /* # of times with entries removed */ + uint64_t dropped; /* # of packets dropped waiting for a reply. */ + uint64_t timeouts; /* # of times with entries removed */ /* due to timeout. */ - u_long dupips; /* # of duplicate IPs detected. */ + uint64_t dupips; /* # of duplicate IPs detected. */ }; +#ifdef _KERNEL +#include <sys/counter.h> +#include <net/vnet.h> + +VNET_PCPUSTAT_DECLARE(struct arpstat, arpstat); /* * In-kernel consumers can use these accessor macros directly to update * stats. */ -#define ARPSTAT_ADD(name, val) V_arpstat.name += (val) -#define ARPSTAT_SUB(name, val) V_arpstat.name -= (val) +#define ARPSTAT_ADD(name, val) \ + VNET_PCPUSTAT_ADD(struct arpstat, arpstat, name, (val)) +#define ARPSTAT_SUB(name, val) ARPSTAT_ADD(name, -(val)) #define ARPSTAT_INC(name) ARPSTAT_ADD(name, 1) #define ARPSTAT_DEC(name) ARPSTAT_SUB(name, 1) +#endif /* _KERNEL */ + #endif /* !_NET_IF_ARP_H_ */ diff --git a/sys/net/if_gif.c b/sys/net/if_gif.c index 2a6f890..874bbc00 100644 --- a/sys/net/if_gif.c +++ b/sys/net/if_gif.c @@ -173,7 +173,7 @@ gif_clone_create(ifc, unit, params) if_initname(GIF2IFP(sc), gifname, unit); sc->encap_cookie4 = sc->encap_cookie6 = NULL; - sc->gif_options = GIF_ACCEPT_REVETHIP; + sc->gif_options = 0; GIF2IFP(sc)->if_addrlen = 0; GIF2IFP(sc)->if_mtu = GIF_MTU; @@ -437,6 +437,11 @@ gif_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, goto end; } #endif + if ((ifp->if_flags & IFF_MONITOR) != 0) { + error = ENETDOWN; + m_freem(m); + goto end; + } /* * gif may cause infinite recursion calls when misconfigured. @@ -551,6 +556,13 @@ gif_input(m, af, ifp) bpf_mtap2(ifp->if_bpf, &af1, sizeof(af1), m); } + if ((ifp->if_flags & IFF_MONITOR) != 0) { + ifp->if_ipackets++; + ifp->if_ibytes += m->m_pkthdr.len; + m_freem(m); + return; + } + if (ng_gif_input_p != NULL) { (*ng_gif_input_p)(ifp, &m, af); if (m == NULL) diff --git a/sys/net/if_lagg.c b/sys/net/if_lagg.c index 9867c97..bc2127c 100644 --- a/sys/net/if_lagg.c +++ b/sys/net/if_lagg.c @@ -122,6 +122,7 @@ static void lagg_media_status(struct ifnet *, struct ifmediareq *); static struct lagg_port *lagg_link_active(struct lagg_softc *, struct lagg_port *); static const void *lagg_gethdr(struct mbuf *, u_int, u_int, void *); +static int lagg_sysctl_active(SYSCTL_HANDLER_ARGS); /* Simple round robin */ static int lagg_rr_attach(struct lagg_softc *); @@ -171,7 +172,7 @@ static const struct { }; SYSCTL_DECL(_net_link); -static SYSCTL_NODE(_net_link, OID_AUTO, lagg, CTLFLAG_RW, 0, +SYSCTL_NODE(_net_link, OID_AUTO, lagg, CTLFLAG_RW, 0, "Link Aggregation"); static int lagg_failover_rx_all = 0; /* Allow input on any failover links */ @@ -298,6 +299,12 @@ lagg_clone_create(struct if_clone *ifc, int unit, caddr_t params) SYSCTL_ADD_INT(&sc->ctx, SYSCTL_CHILDREN(oid), OID_AUTO, "count", CTLTYPE_INT|CTLFLAG_RD, &sc->sc_count, sc->sc_count, "Total number of ports"); + SYSCTL_ADD_PROC(&sc->ctx, SYSCTL_CHILDREN(oid), OID_AUTO, + "active", CTLTYPE_INT|CTLFLAG_RD, sc, 0, lagg_sysctl_active, + "I", "Total number of active ports"); + SYSCTL_ADD_INT(&sc->ctx, SYSCTL_CHILDREN(oid), OID_AUTO, + "flapping", CTLTYPE_INT|CTLFLAG_RD, &sc->sc_flapping, + sc->sc_flapping, "Total number of port change events"); /* Hash all layers by default */ sc->sc_flags = LAGG_F_HASHL2|LAGG_F_HASHL3|LAGG_F_HASHL4; @@ -1488,6 +1495,27 @@ lagg_gethdr(struct mbuf *m, u_int off, u_int len, void *buf) return (mtod(m, char *) + off); } +static int +lagg_sysctl_active(SYSCTL_HANDLER_ARGS) +{ + struct lagg_softc *sc = (struct lagg_softc *)arg1; + struct lagg_port *lp; + int error; + + /* LACP tracks active links automatically, the others do not */ + if (sc->sc_proto != LAGG_PROTO_LACP) { + sc->sc_active = 0; + SLIST_FOREACH(lp, &sc->sc_ports, lp_entries) + sc->sc_active += LAGG_PORTACTIVE(lp); + } + + error = sysctl_handle_int(oidp, &sc->sc_active, 0, req); + if ((error) || (req->newptr == NULL)) + return (error); + + return (0); +} + uint32_t lagg_hashmbuf(struct lagg_softc *sc, struct mbuf *m, uint32_t key) { diff --git a/sys/net/if_lagg.h b/sys/net/if_lagg.h index fe3365b..cbec8d6 100644 --- a/sys/net/if_lagg.h +++ b/sys/net/if_lagg.h @@ -190,6 +190,9 @@ struct lagg_softc { struct rwlock sc_mtx; int sc_proto; /* lagg protocol */ u_int sc_count; /* number of ports */ + u_int sc_active; /* active port count */ + u_int sc_flapping; /* number of flapping + * events */ struct lagg_port *sc_primary; /* primary port */ struct ifmedia sc_media; /* media config */ caddr_t sc_psc; /* protocol data */ @@ -266,6 +269,8 @@ extern void (*lagg_linkstate_p)(struct ifnet *, int ); int lagg_enqueue(struct ifnet *, struct mbuf *); uint32_t lagg_hashmbuf(struct lagg_softc *, struct mbuf *, uint32_t); +SYSCTL_DECL(_net_link_lagg); + #endif /* _KERNEL */ #endif /* _NET_LAGG_H */ diff --git a/sys/net/if_var.h b/sys/net/if_var.h index 3babc22..3288a4f 100644 --- a/sys/net/if_var.h +++ b/sys/net/if_var.h @@ -204,7 +204,7 @@ struct ifnet { u_int if_fib; /* interface FIB */ u_char if_alloctype; /* if_type at time of allocation */ - u_int if_hw_tsomax; /* tso burst length limit, the minmum + u_int if_hw_tsomax; /* tso burst length limit, the minimum * is (IP_MAXPACKET / 8). * XXXAO: Have to find a better place * for it eventually. */ diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c index d665280..928d2ab 100644 --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -1905,6 +1905,7 @@ sysctl_rtsock(SYSCTL_HANDLER_ARGS) u_int namelen = arg2; struct radix_node_head *rnh = NULL; /* silence compiler. */ int i, lim, error = EINVAL; + int fib = 0; u_char af; struct walkarg w; @@ -1912,7 +1913,17 @@ sysctl_rtsock(SYSCTL_HANDLER_ARGS) namelen--; if (req->newptr) return (EPERM); - if (namelen != 3) + if (name[1] == NET_RT_DUMP) { + if (namelen == 3) + fib = req->td->td_proc->p_fibnum; + else if (namelen == 4) + fib = (name[3] == -1) ? + req->td->td_proc->p_fibnum : name[3]; + else + return ((namelen < 3) ? EISDIR : ENOTDIR); + if (fib < 0 || fib >= rt_numfibs) + return (EINVAL); + } else if (namelen != 3) return ((namelen < 3) ? EISDIR : ENOTDIR); af = name[0]; if (af > AF_MAX) @@ -1951,7 +1962,7 @@ sysctl_rtsock(SYSCTL_HANDLER_ARGS) * take care of routing entries */ for (error = 0; error == 0 && i <= lim; i++) { - rnh = rt_tables_get_rnh(req->td->td_proc->p_fibnum, i); + rnh = rt_tables_get_rnh(fib, i); if (rnh != NULL) { RADIX_NODE_HEAD_RLOCK(rnh); error = rnh->rnh_walktree(rnh, diff --git a/sys/net/vnet.h b/sys/net/vnet.h index 6bdf163..4e9de11 100644 --- a/sys/net/vnet.h +++ b/sys/net/vnet.h @@ -85,6 +85,56 @@ struct vnet { #ifdef _KERNEL +#define VNET_PCPUSTAT_DECLARE(type, name) \ + VNET_DECLARE(counter_u64_t, name[sizeof(type) / sizeof(uint64_t)]) + +#define VNET_PCPUSTAT_DEFINE(type, name) \ + VNET_DEFINE(counter_u64_t, name[sizeof(type) / sizeof(uint64_t)]) + +#define VNET_PCPUSTAT_ALLOC(name, wait) \ + COUNTER_ARRAY_ALLOC(VNET(name), \ + sizeof(VNET(name)) / sizeof(counter_u64_t), (wait)) + +#define VNET_PCPUSTAT_FREE(name) \ + COUNTER_ARRAY_FREE(VNET(name), sizeof(VNET(name)) / sizeof(counter_u64_t)) + +#define VNET_PCPUSTAT_ADD(type, name, f, v) \ + counter_u64_add(VNET(name)[offsetof(type, f) / sizeof(uint64_t)], (v)) + +#define VNET_PCPUSTAT_SYSINIT(name) \ +static void \ +vnet_##name##_init(const void *unused) \ +{ \ + VNET_PCPUSTAT_ALLOC(name, M_WAITOK); \ +} \ +VNET_SYSINIT(vnet_ ## name ## _init, SI_SUB_PROTO_IFATTACHDOMAIN, \ + SI_ORDER_ANY, vnet_ ## name ## _init, NULL) + +#define VNET_PCPUSTAT_SYSUNINIT(name) \ +static void \ +vnet_##name##_uninit(const void *unused) \ +{ \ + VNET_PCPUSTAT_FREE(name); \ +} \ +VNET_SYSUNINIT(vnet_ ## name ## _uninit, SI_SUB_PROTO_IFATTACHDOMAIN, \ + SI_ORDER_ANY, vnet_ ## name ## _uninit, NULL) + +#define SYSCTL_VNET_PCPUSTAT(parent, nbr, name, type, array, desc) \ +static int \ +array##_sysctl(SYSCTL_HANDLER_ARGS) \ +{ \ + type s; \ + CTASSERT((sizeof(type) / sizeof(uint64_t)) == \ + (sizeof(VNET(array)) / sizeof(counter_u64_t))); \ + COUNTER_ARRAY_COPY(VNET(array), &s, sizeof(type) / sizeof(uint64_t));\ + if (req->newptr) \ + COUNTER_ARRAY_ZERO(VNET(array), \ + sizeof(type) / sizeof(uint64_t)); \ + return (SYSCTL_OUT(req, &s, sizeof(type))); \ +} \ +SYSCTL_VNET_PROC(parent, nbr, name, CTLTYPE_OPAQUE | CTLFLAG_RW, NULL, \ + 0, array ## _sysctl, "I", desc) + #ifdef VIMAGE #include <sys/lock.h> #include <sys/proc.h> /* for struct thread */ |