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 */