Module Name: src Committed By: dyoung Date: Thu Aug 13 00:23:32 UTC 2009
Modified Files: src/sys/net: if.c if.h Log Message: Use sysctl(9) to expose to userland each interface transmission queue's maximum length, current length, and number of drops. E.g., % sysctl net.interfaces.bnx0 net.interfaces.bnx0.sndq.len = 0 net.interfaces.bnx0.sndq.maxlen = 509 net.interfaces.bnx0.sndq.drops = 0 Let userland adjust the maximum queue length. While I'm here, add a 64-bit generation number, if_index_gen, to ifnet; the pair [ifp->if_index, ifp->if_index_gen] can serve to identify an ifnet for the lifetime of the system. I will use this in an upcoming change. Ok m...@. To generate a diff of this commit: cvs rdiff -u -r1.233 -r1.234 src/sys/net/if.c cvs rdiff -u -r1.142 -r1.143 src/sys/net/if.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/net/if.c diff -u src/sys/net/if.c:1.233 src/sys/net/if.c:1.234 --- src/sys/net/if.c:1.233 Thu Feb 12 19:05:36 2009 +++ src/sys/net/if.c Thu Aug 13 00:23:31 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: if.c,v 1.233 2009/02/12 19:05:36 christos Exp $ */ +/* $NetBSD: if.c,v 1.234 2009/08/13 00:23:31 dyoung Exp $ */ /*- * Copyright (c) 1999, 2000, 2001, 2008 The NetBSD Foundation, Inc. @@ -90,7 +90,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.233 2009/02/12 19:05:36 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.234 2009/08/13 00:23:31 dyoung Exp $"); #include "opt_inet.h" @@ -159,11 +159,16 @@ static LIST_HEAD(, if_clone) if_cloners = LIST_HEAD_INITIALIZER(if_cloners); static int if_cloners_count; +static uint64_t index_gen; +static kmutex_t index_gen_mtx; + #ifdef PFIL_HOOKS struct pfil_head if_pfil; /* packet filtering hook for interfaces */ #endif static void if_detach_queues(struct ifnet *, struct ifqueue *); +static void sysctl_sndq_setup(struct sysctllog **, const char *, + struct ifaltq *); /* * Network interface utility routines. @@ -175,6 +180,7 @@ ifinit(void) { + mutex_init(&index_gen_mtx, MUTEX_DEFAULT, IPL_NONE); callout_init(&if_slowtimo_ch, 0); if_slowtimo(NULL); } @@ -447,6 +453,10 @@ if (ifp->if_ioctl == NULL) ifp->if_ioctl = ifioctl_common; + mutex_enter(&index_gen_mtx); + ifp->if_index_gen = index_gen++; + mutex_exit(&index_gen_mtx); + ifp->if_index = if_index; if (ifindex2ifnet == NULL) if_index++; @@ -524,6 +534,9 @@ if (ifp->if_snd.ifq_maxlen == 0) ifp->if_snd.ifq_maxlen = ifqmaxlen; + + sysctl_sndq_setup(&ifp->if_sysctl_log, ifp->if_xname, &ifp->if_snd); + ifp->if_broadcastaddr = 0; /* reliably crash if used uninitialized */ ifp->if_link_state = LINK_STATE_UNKNOWN; @@ -666,6 +679,7 @@ altq_detach(&ifp->if_snd); #endif + sysctl_teardown(&ifp->if_sysctl_log); #if NCARP > 0 /* Remove the interface from any carp group it is a part of. */ @@ -1874,6 +1888,73 @@ } +static void +sysctl_sndq_setup(struct sysctllog **clog, const char *ifname, + struct ifaltq *ifq) +{ + const struct sysctlnode *cnode, *rnode; + + if (sysctl_createv(clog, 0, NULL, &rnode, + CTLFLAG_PERMANENT, + CTLTYPE_NODE, "net", NULL, + NULL, 0, NULL, 0, + CTL_NET, CTL_EOL) != 0) + goto bad; + + if (sysctl_createv(clog, 0, &rnode, &rnode, + CTLFLAG_PERMANENT, + CTLTYPE_NODE, "interfaces", + SYSCTL_DESCR("Per-interface controls"), + NULL, 0, NULL, 0, + CTL_CREATE, CTL_EOL) != 0) + goto bad; + + if (sysctl_createv(clog, 0, &rnode, &rnode, + CTLFLAG_PERMANENT, + CTLTYPE_NODE, ifname, + SYSCTL_DESCR("Interface controls"), + NULL, 0, NULL, 0, + CTL_CREATE, CTL_EOL) != 0) + goto bad; + + if (sysctl_createv(clog, 0, &rnode, &rnode, + CTLFLAG_PERMANENT, + CTLTYPE_NODE, "sndq", + SYSCTL_DESCR("Interface output queue controls"), + NULL, 0, NULL, 0, + CTL_CREATE, CTL_EOL) != 0) + goto bad; + + if (sysctl_createv(clog, 0, &rnode, &cnode, + CTLFLAG_PERMANENT, + CTLTYPE_INT, "len", + SYSCTL_DESCR("Current output queue length"), + NULL, 0, &ifq->ifq_len, 0, + CTL_CREATE, CTL_EOL) != 0) + goto bad; + + if (sysctl_createv(clog, 0, &rnode, &cnode, + CTLFLAG_PERMANENT|CTLFLAG_READWRITE, + CTLTYPE_INT, "maxlen", + SYSCTL_DESCR("Maximum allowed output queue length"), + NULL, 0, &ifq->ifq_maxlen, 0, + CTL_CREATE, CTL_EOL) != 0) + goto bad; + + if (sysctl_createv(clog, 0, &rnode, &cnode, + CTLFLAG_PERMANENT, + CTLTYPE_INT, "drops", + SYSCTL_DESCR("Packets dropped due to full output queue"), + NULL, 0, &ifq->ifq_drops, 0, + CTL_CREATE, CTL_EOL) != 0) + goto bad; + + return; +bad: + printf("%s: could not attach sysctl nodes\n", ifname); + return; +} + #if defined(INET) || defined(INET6) static void sysctl_net_ifq_setup(struct sysctllog **clog, Index: src/sys/net/if.h diff -u src/sys/net/if.h:1.142 src/sys/net/if.h:1.143 --- src/sys/net/if.h:1.142 Sun Jan 11 02:45:54 2009 +++ src/sys/net/if.h Thu Aug 13 00:23:32 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: if.h,v 1.142 2009/01/11 02:45:54 christos Exp $ */ +/* $NetBSD: if.h,v 1.143 2009/08/13 00:23:32 dyoung Exp $ */ /*- * Copyright (c) 1999, 2000, 2001 The NetBSD Foundation, Inc. @@ -282,6 +282,21 @@ */ void *if_pf_kif; /* pf interface abstraction */ void *if_pf_groups; /* pf interface groups */ + /* + * During an ifnet's lifetime, it has only one if_index, but + * and if_index is not sufficient to identify an ifnet + * because during the lifetime of the system, many ifnets may occupy a + * given if_index. Let us tell different ifnets at the same + * if_index apart by their if_index_gen, a unique number that each ifnet + * is assigned when it if_attach()s. Now, the kernel can use the + * pair (if_index, if_index_gen) as a weak reference to an ifnet. + */ + uint64_t if_index_gen; /* generation number for the ifnet + * at if_index: if two ifnets' index + * and generation number are both the + * same, they are the same ifnet. + */ + struct sysctllog *if_sysctl_log; }; #define if_mtu if_data.ifi_mtu #define if_type if_data.ifi_type