Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 13 Jan 2015 08:24:38 +0000 (UTC)
From:      Gleb Smirnoff <glebius@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r277118 - projects/ifnet/sys/net
Message-ID:  <201501130824.t0D8OcWN058373@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: glebius
Date: Tue Jan 13 08:24:37 2015
New Revision: 277118
URL: https://svnweb.freebsd.org/changeset/base/277118

Log:
  - Allow drivers to specify a if_cloner for unit allocation.
  - Allow drivers to specify a specific name when attaching an interface.
  
  Sponsored by:	Nginx, Inc.

Modified:
  projects/ifnet/sys/net/if.c
  projects/ifnet/sys/net/if.h
  projects/ifnet/sys/net/if_mib.c
  projects/ifnet/sys/net/if_var.h

Modified: projects/ifnet/sys/net/if.c
==============================================================================
--- projects/ifnet/sys/net/if.c	Tue Jan 13 07:49:47 2015	(r277117)
+++ projects/ifnet/sys/net/if.c	Tue Jan 13 08:24:37 2015	(r277118)
@@ -492,6 +492,9 @@ ifdriver_bless(struct ifdriver *ifdrv, s
  * Allocate a struct ifnet and an index for an interface.  A layer 2
  * common structure will also be allocated if an allocation routine is
  * registered for the passed type.
+ *
+ * The only reason for this function to fail is failure to allocate a
+ * unit number, which is possible only if driver does cloning.
  */
 if_t
 if_attach(struct if_attach_args *ifat)
@@ -507,6 +510,23 @@ if_attach(struct if_attach_args *ifat)
 	    ("%s: version %d, expected %d",
 	    __func__, ifat->ifat_version, IF_ATTACH_VERSION));
 
+	ifdrv = ifat->ifat_drv;
+	ift = iftype_find(ifdrv->ifdrv_type);
+	if ((ifdrv->ifdrv_flags & IFDRV_BLESSED) == 0)
+		ifdriver_bless(ifdrv, ift);
+
+	if (ifdrv->ifdrv_clone != NULL) {
+		int error;
+
+		error = ifc_alloc_unit(ifdrv->ifdrv_clone, &ifat->ifat_dunit);
+		if (error) {
+			log(LOG_WARNING, "%s unit allocation failure: %d\n",
+			    ifdrv->ifdrv_name, error);
+			ifat->ifat_error = error;
+			return (NULL);
+		}
+	}
+
 	ifp = malloc(sizeof(struct ifnet), M_IFNET, M_WAITOK | M_ZERO);
 	for (int i = 0; i < IFCOUNTERS; i++)
 		ifp->if_counters[i] = counter_u64_alloc(M_WAITOK);
@@ -515,12 +535,6 @@ if_attach(struct if_attach_args *ifat)
 	mac_ifnet_create(ifp);
 #endif
 
-	ifdrv = ifat->ifat_drv;
-	ift = iftype_find(ifdrv->ifdrv_type);
-
-	if ((ifdrv->ifdrv_flags & IFDRV_BLESSED) == 0)
-		ifdriver_bless(ifdrv, ift);
-
 	ifp->if_ops = &ifdrv->ifdrv_ops;
 	ifp->if_drv = ifdrv;
 	ifp->if_type = ift;
@@ -564,7 +578,9 @@ if_attach(struct if_attach_args *ifat)
 
 	/* XXXGL: there is no check that name is unique. */
 	ifp->if_dunit = ifat->ifat_dunit;
-	if (ifat->ifat_dunit != IF_DUNIT_NONE)
+	if (ifat->ifat_name)
+		strlcpy(ifp->if_xname, ifat->ifat_name, IFNAMSIZ);
+	else if (ifat->ifat_dunit != IFAT_DUNIT_NONE)
 		snprintf(ifp->if_xname, IFNAMSIZ, "%s%d",
 		    ifdrv->ifdrv_name, ifat->ifat_dunit);
 	else
@@ -918,6 +934,9 @@ if_detach(if_t ifp)
 	ifindex_free(ifp->if_index);
 	IFNET_WUNLOCK();
 
+	if (ifp->if_drv->ifdrv_clone != NULL)
+		ifc_free_unit(ifp->if_drv->ifdrv_clone, ifp->if_dunit);
+
 	if (refcount_release(&ifp->if_refcount))
 		if_free_internal(ifp);
 	CURVNET_RESTORE();

Modified: projects/ifnet/sys/net/if.h
==============================================================================
--- projects/ifnet/sys/net/if.h	Tue Jan 13 07:49:47 2015	(r277117)
+++ projects/ifnet/sys/net/if.h	Tue Jan 13 08:24:37 2015	(r277118)
@@ -648,6 +648,7 @@ struct ifdriver {
 	 * static string works well.
 	 */
 	const char *	ifdrv_name;
+	struct if_clone *ifdrv_clone;
 	ifType		ifdrv_type;	/* from if_types.h */
 	uint8_t		ifdrv_hdrlen;	/* media header length */
 	uint8_t		ifdrv_addrlen;	/* media address length */
@@ -671,11 +672,14 @@ struct if_attach_args {
 	uint8_t		ifat_spare8;
 	uint16_t	ifat_spare16;
 	uint32_t	ifat_spare32;
+	int		ifat_error;	/* Filled on return. */
 
 	struct ifdriver	*ifat_drv;
 	void 		*ifat_softc;	/* Driver private softc. */
 	const uint8_t	*ifat_lla;	/* Link-level address. */
-	int32_t		ifat_dunit;	/* unit or IF_DUNIT_NONE */
+	int32_t		ifat_dunit;	/* Specific unit or a hint. */
+#define	IFAT_DUNIT_NONE	(-1)
+	char *		ifat_name;	/* If driver wants a specific name. */
 	/*
 	 * Variables that may differ between two instances of a same
 	 * driver, but are constant within instance lifetime.

Modified: projects/ifnet/sys/net/if_mib.c
==============================================================================
--- projects/ifnet/sys/net/if_mib.c	Tue Jan 13 07:49:47 2015	(r277117)
+++ projects/ifnet/sys/net/if_mib.c	Tue Jan 13 08:24:37 2015	(r277118)
@@ -129,7 +129,7 @@ sysctl_ifdata(SYSCTL_HANDLER_ARGS) /* XX
 			error = ENOMEM;
 			goto out;
 		}
-		if (ifp->if_dunit == IF_DUNIT_NONE)
+		if (ifp->if_dunit == IFAT_DUNIT_NONE)
 			strcpy(dbuf, ifp->if_drv->ifdrv_name);
 		else
 			sprintf(dbuf, "%s%d", ifp->if_drv->ifdrv_name,

Modified: projects/ifnet/sys/net/if_var.h
==============================================================================
--- projects/ifnet/sys/net/if_var.h	Tue Jan 13 07:49:47 2015	(r277117)
+++ projects/ifnet/sys/net/if_var.h	Tue Jan 13 08:24:37 2015	(r277118)
@@ -53,9 +53,6 @@ struct	netmap_adapter;
 #include <sys/rwlock.h>		/* XXX */
 #include <sys/sx.h>		/* XXX */
 #include <sys/_task.h>		/* if_link_task */
-
-#define	IF_DUNIT_NONE	-1
-
 #include <altq/if_altq.h>
 
 TAILQ_HEAD(ifnethead, ifnet);	/* we use TAILQs so that the order of */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201501130824.t0D8OcWN058373>