Subject: Sample patch for sysctl access to protocol input-queue state
To: None <tech-net@netbsd.org>
From: Jonathan Stone <jonathan@DSG.Stanford.EDU>
List: tech-net
Date: 09/18/2003 16:09:56
Some weeks back, I suggested adding sysctl access to protocol input
queues (e.g., ipintrq).

The following patch implements that, plus Matt Thomas' suggestion to
add an explicit ".ifq." node to the namespace.  After thinking about
it, I agree with Matt: that's a much cleaner way to do the same thing
for IPv6 and othe protocols.

For the record, Jason Thorpe looked at this too, and suggested ifq_*
names (rather than ifq.*).  Jason has been heard, but after
reflection, I agree with Matt.  The point is not code savings or
reuse, but for uniformity and consistency of the sysctl namespace.


The changes to src/sbin/sysctl/sysctl.c are ugly (I couldn't find any
other cases of adding nonterminal nodes as peers of otherwise terminal
nodes). Same goes for the check in ip_input. Any suggestions on how to
make that cleaner *and* clear are welcome; if I dont get any I'll do
something about the check in ip_input myself (I tried, but I found the
obvious flattening of the if statements was less clear).

The name entry for a peak value (high-watermark) is reserved as
future-prooging. Once you start using the ifq.* names, the desire to
track and show the peak quickly makes itself felt.

Other comments welcomed.


Index: ./sys/net/if.h
===================================================================
RCS file: /cvsroot/src/sys/net/if.h,v
retrieving revision 1.92
diff -u -r1.92 if.h
--- ./sys/net/if.h	2003/08/07 16:32:49	1.92
+++ ./sys/net/if.h	2003/09/18 22:23:03
@@ -725,6 +725,30 @@
 #define	IFQ_INC_DROPS(ifq)		((ifq)->ifq_drops++)
 #define	IFQ_SET_MAXLEN(ifq, len)	((ifq)->ifq_maxlen = (len))
 
+/*
+ * sysctl on (protocol-input) ifq 
+ */
+#define IFQ_NAMES  { \
+	{ 0, 0 }, \
+	{ "len", CTLTYPE_INT }, \
+	{ "maxlen", CTLTYPE_INT }, \
+	{ "peak", CTLTYPE_INT }, \
+	{ "drops", CTLTYPE_INT }, \
+}
+
+#ifdef _KERNEL
+#define IFQCTL_LEN 1
+#define IFQCTL_MAXLEN 2
+#define IFQCTL_PEAK 3
+#define IFQCTL_DROPS 4
+#define	IFQCTL_MAXID 5
+int	sysctl_ifq __P((int *name, u_int namelen, void *oldp,
+		       size_t *oldlenp, void *newp, size_t newlen,
+		       struct ifqueue *ifq));
+
+#endif
+
+
 #ifdef _KERNEL
 #include <sys/mallocvar.h>
 MALLOC_DECLARE(M_IFADDR);
Index: ./sys/net/if.c
===================================================================
RCS file: /cvsroot/src/sys/net/if.c,v
retrieving revision 1.130
diff -u -r1.130 if.c
--- ./sys/net/if.c	2003/08/14 07:39:22	1.130
+++ ./sys/net/if.c	2003/09/18 22:23:04
@@ -121,6 +121,7 @@
 #include <sys/protosw.h>
 #include <sys/kernel.h>
 #include <sys/ioctl.h>
+#include <sys/sysctl.h>
 
 #include <net/if.h>
 #include <net/if_dl.h>
@@ -1688,3 +1689,40 @@
 		ifc->ifc_len = space;
 	return (error);
 }
+
+int
+sysctl_ifq(name, namelen, oldp, oldlenp, newp, newlen, ifq)
+	int *name;
+	u_int namelen;
+	void *oldp;
+	size_t *oldlenp;
+	void *newp;
+	size_t newlen;
+	struct ifqueue *ifq;
+{
+	/* All sysctl names at this level are terminal. */
+	if (namelen != 1)
+		return (ENOTDIR);
+
+	switch (name[0]) {
+	case IFQCTL_LEN:
+		return (sysctl_rdint(oldp, oldlenp, newp,
+			ifq->ifq_len));
+#ifdef ifq_peak
+	case IFQCTL_PEAK:
+		return (sysctl_rdint(oldp, oldlenp, newp,
+			ifq->ifq_peak));
+#endif
+	case IFQCTL_MAXLEN:
+		return (sysctl_int(oldp, oldlenp, newp, newlen,
+			&ifq->ifq_maxlen));
+
+	case IFQCTL_DROPS:
+		return (sysctl_rdint(oldp, oldlenp, newp,
+			ifq->ifq_drops));
+	default:
+		return (EOPNOTSUPP);
+	}
+  	/* NOTREACHED */
+}
+
Index: ./sys/netinet/in.h
===================================================================
RCS file: /cvsroot/src/sys/netinet/in.h,v
retrieving revision 1.62
diff -u -r1.62 in.h
--- ./sys/netinet/in.h	2003/08/07 16:33:09	1.62
+++ ./sys/netinet/in.h	2003/09/18 22:23:04
@@ -380,7 +380,8 @@
 #define	IPCTL_MAXFRAGPACKETS   18	/* max packets reassembly queue */
 #define	IPCTL_GRE_TTL          19	/* default TTL for gre encap packet */
 #define	IPCTL_CHECKINTERFACE   20	/* drop pkts in from 'wrong' iface */
-#define	IPCTL_MAXID	       21
+#define	IPCTL_IFQ	       21	/* ipintrq node */
+#define	IPCTL_MAXID	       22
 
 #define	IPCTL_NAMES { \
 	{ 0, 0 }, \
Index: ./sys/netinet/ip_input.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/ip_input.c,v
retrieving revision 1.178
diff -u -r1.178 ip_input.c
--- ./sys/netinet/ip_input.c	2003/09/06 03:36:30	1.178
+++ ./sys/netinet/ip_input.c	2003/09/18 22:23:05
@@ -1932,8 +1932,10 @@
 
 	int error, old;
 
-	/* All sysctl names at this level are terminal. */
-	if (namelen != 1)
+	/* All sysctl names (except ifq.*) at this level are terminal. */
+	if (name[0] == IPCTL_IFQ && namelen == 2)
+		(void)0;	/* do nothing */
+	else if (namelen != 1)
 		return (ENOTDIR);
 
 	switch (name[0]) {
@@ -2069,6 +2071,11 @@
 	case IPCTL_CHECKINTERFACE:
 		return (sysctl_int(oldp, oldlenp, newp, newlen,
 		    &ip_checkinterface));
+	case IPCTL_IFQ:
+		return(sysctl_ifq(name+1, namelen-1,
+				  oldp, oldlenp, newp, newlen,
+				  &ipintrq));
+
 	default:
 		return (EOPNOTSUPP);
 	}