Module Name:    src
Committed By:   ozaki-r
Date:           Mon May 16 01:06:31 UTC 2016

Modified Files:
        src/sys/net: if.c if.h

Log Message:
Introduce if_get, if_get_byindex and if_put

The new API enables to obtain an ifnet object with protected by psref(9).
It is intended to be used where an obtained ifnet object is used over
sleepable operations.


To generate a diff of this commit:
cvs rdiff -u -r1.334 -r1.335 src/sys/net/if.c
cvs rdiff -u -r1.204 -r1.205 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.334 src/sys/net/if.c:1.335
--- src/sys/net/if.c:1.334	Thu May 12 02:24:16 2016
+++ src/sys/net/if.c	Mon May 16 01:06:31 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: if.c,v 1.334 2016/05/12 02:24:16 ozaki-r Exp $	*/
+/*	$NetBSD: if.c,v 1.335 2016/05/16 01:06:31 ozaki-r 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.334 2016/05/12 02:24:16 ozaki-r Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if.c,v 1.335 2016/05/16 01:06:31 ozaki-r Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_inet.h"
@@ -2119,12 +2119,92 @@ out:
 	return ifp;
 }
 
+/*
+ * Get a reference of an ifnet object by an interface name.
+ * The returned reference is protected by psref(9). The caller
+ * must release a returned reference by if_put after use.
+ */
+struct ifnet *
+if_get(const char *name, struct psref *psref)
+{
+	struct ifnet *ifp;
+	const char *cp = name;
+	u_int unit = 0;
+	u_int i;
+	int s;
+
+	/*
+	 * If the entire name is a number, treat it as an ifindex.
+	 */
+	for (i = 0; i < IFNAMSIZ && *cp >= '0' && *cp <= '9'; i++, cp++) {
+		unit = unit * 10 + (*cp - '0');
+	}
+
+	/*
+	 * If the number took all of the name, then it's a valid ifindex.
+	 */
+	if (i == IFNAMSIZ || (cp != name && *cp == '\0')) {
+		if (unit >= if_indexlim)
+			return NULL;
+		ifp = ifindex2ifnet[unit];
+		if (ifp == NULL || ifp->if_output == if_nulloutput)
+			return NULL;
+		return ifp;
+	}
+
+	ifp = NULL;
+	s = pserialize_read_enter();
+	IFNET_READER_FOREACH(ifp) {
+		if (ifp->if_output == if_nulloutput)
+			continue;
+		if (strcmp(ifp->if_xname, name) == 0) {
+			psref_acquire(psref, &ifp->if_psref,
+			    ifnet_psref_class);
+			goto out;
+		}
+	}
+out:
+	pserialize_read_exit(s);
+	return ifp;
+}
+
+/*
+ * Release a reference of an ifnet object given by if_get or
+ * if_get_byindex.
+ */
+void
+if_put(const struct ifnet *ifp, struct psref *psref)
+{
+
+	psref_release(psref, &ifp->if_psref, ifnet_psref_class);
+}
+
 ifnet_t *
 if_byindex(u_int idx)
 {
 	return (idx < if_indexlim) ? ifindex2ifnet[idx] : NULL;
 }
 
+/*
+ * Get a reference of an ifnet object by an interface index.
+ * The returned reference is protected by psref(9). The caller
+ * must release a returned reference by if_put after use.
+ */
+ifnet_t *
+if_get_byindex(u_int idx, struct psref *psref)
+{
+	ifnet_t *ifp;
+	int s;
+
+	s = pserialize_read_enter();
+	ifp = (idx < if_indexlim) ? ifindex2ifnet[idx] : NULL;
+	if (ifp != NULL)
+		psref_acquire(psref, &ifp->if_psref, ifnet_psref_class);
+	pserialize_read_exit(s);
+
+	return ifp;
+}
+
 /* common */
 int
 ifioctl_common(struct ifnet *ifp, u_long cmd, void *data)

Index: src/sys/net/if.h
diff -u src/sys/net/if.h:1.204 src/sys/net/if.h:1.205
--- src/sys/net/if.h:1.204	Thu May 12 02:24:16 2016
+++ src/sys/net/if.h	Mon May 16 01:06:31 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: if.h,v 1.204 2016/05/12 02:24:16 ozaki-r Exp $	*/
+/*	$NetBSD: if.h,v 1.205 2016/05/16 01:06:31 ozaki-r Exp $	*/
 
 /*-
  * Copyright (c) 1999, 2000, 2001 The NetBSD Foundation, Inc.
@@ -912,6 +912,10 @@ extern int (*ifioctl)(struct socket *, u
 int	ifioctl_common(struct ifnet *, u_long, void *);
 int	ifpromisc(struct ifnet *, int);
 struct	ifnet *ifunit(const char *);
+struct	ifnet *if_get(const char *, struct psref *);
+ifnet_t *if_byindex(u_int);
+ifnet_t *if_get_byindex(u_int, struct psref *);
+void	if_put(const struct ifnet *, struct psref *);
 int	if_addr_init(ifnet_t *, struct ifaddr *, bool);
 int	if_do_dad(struct ifnet *);
 int	if_mcast_op(ifnet_t *, const unsigned long, const struct sockaddr *);
@@ -1047,8 +1051,6 @@ extern kmutex_t ifnet_mtx;
 
 extern struct ifnet *lo0ifp;
 
-ifnet_t *	if_byindex(u_int);
-
 /*
  * ifq sysctl support
  */

Reply via email to