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