From owner-dev-commits-src-all@freebsd.org  Thu Feb  4 22:34:52 2021
Return-Path: <owner-dev-commits-src-all@freebsd.org>
Delivered-To: dev-commits-src-all@mailman.nyi.freebsd.org
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1])
 by mailman.nyi.freebsd.org (Postfix) with ESMTP id 06B1D53149B;
 Thu,  4 Feb 2021 22:34:52 +0000 (UTC) (envelope-from git@FreeBSD.org)
Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org
 [IPv6:2610:1c1:1:606c::19:3])
 (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
 key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256
 client-signature RSA-PSS (4096 bits) client-digest SHA256)
 (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK))
 by mx1.freebsd.org (Postfix) with ESMTPS id 4DWtf36qL9z3H0S;
 Thu,  4 Feb 2021 22:34:51 +0000 (UTC) (envelope-from git@FreeBSD.org)
Received: from gitrepo.freebsd.org (gitrepo.freebsd.org
 [IPv6:2610:1c1:1:6068::e6a:5])
 (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
 key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256)
 (Client did not present a certificate)
 by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id DD02513E21;
 Thu,  4 Feb 2021 22:34:51 +0000 (UTC) (envelope-from git@FreeBSD.org)
Received: from gitrepo.freebsd.org ([127.0.1.44])
 by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 114MYp2R007480;
 Thu, 4 Feb 2021 22:34:51 GMT (envelope-from git@gitrepo.freebsd.org)
Received: (from git@localhost)
 by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 114MYpAI007479;
 Thu, 4 Feb 2021 22:34:51 GMT (envelope-from git)
Date: Thu, 4 Feb 2021 22:34:51 GMT
Message-Id: <202102042234.114MYpAI007479@gitrepo.freebsd.org>
To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org,
 dev-commits-src-branches@FreeBSD.org
From: "Alexander V. Chernikov" <melifaro@FreeBSD.org>
Subject: git: 8efe1ef1c741 - stable/13 - MFC 53729367d388: Fix subinterface
 vlan creation.
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit
X-Git-Committer: melifaro
X-Git-Repository: src
X-Git-Refname: refs/heads/stable/13
X-Git-Reftype: branch
X-Git-Commit: 8efe1ef1c7415c17899e6d1b5e1984bb3a95c55b
Auto-Submitted: auto-generated
X-BeenThere: dev-commits-src-all@freebsd.org
X-Mailman-Version: 2.1.34
Precedence: list
List-Id: Commit messages for all branches of the src repository
 <dev-commits-src-all.freebsd.org>
List-Unsubscribe: <https://lists.freebsd.org/mailman/options/dev-commits-src-all>, 
 <mailto:dev-commits-src-all-request@freebsd.org?subject=unsubscribe>
List-Archive: <http://lists.freebsd.org/pipermail/dev-commits-src-all/>
List-Post: <mailto:dev-commits-src-all@freebsd.org>
List-Help: <mailto:dev-commits-src-all-request@freebsd.org?subject=help>
List-Subscribe: <https://lists.freebsd.org/mailman/listinfo/dev-commits-src-all>, 
 <mailto:dev-commits-src-all-request@freebsd.org?subject=subscribe>
X-List-Received-Date: Thu, 04 Feb 2021 22:34:52 -0000

The branch stable/13 has been updated by melifaro:

URL: https://cgit.FreeBSD.org/src/commit/?id=8efe1ef1c7415c17899e6d1b5e1984bb3a95c55b

commit 8efe1ef1c7415c17899e6d1b5e1984bb3a95c55b
Author:     Alexander V. Chernikov <melifaro@FreeBSD.org>
AuthorDate: 2021-01-26 07:22:23 +0000
Commit:     Alexander V. Chernikov <melifaro@FreeBSD.org>
CommitDate: 2021-02-04 22:21:00 +0000

    MFC 53729367d388: Fix subinterface vlan creation.
    
    D26436 introduced support for stacked vlans that changed the way vlans
     are configured.  In particular, this change broke setups that have
     same-number vlans as subinterfaces.
    
    Vlan support was initially created assuming "vlanX" semantics. In this paradigm,
     automatic number assignment supported by cloning (ifconfig vlan create) was a
     natural fit.
    When "ifaceX.Y" support was added, allowing to have the same vlan number on
     multiple devices, cloning code became more complex, as the is no
    unified "vlan" namespace anymore. Such interfaces got the first spare
    index from "vlan" cloner. This, in turn, led to the following problem:
     ifconfig ix0.333 create -> index 1
     ifconfig ix0.444 create -> index 2
     ifconfig vlan2 create -> allocation failure
    
    This change fixes such allocations by using cloning indexes only for
     "vlanX" interfaces.
    
    Reviewed by:            hselasky
    Differential Revision:  https://reviews.freebsd.org/D27505
---
 sys/net/if_clone.c |  7 +++--
 sys/net/if_vlan.c  | 75 +++++++++++++++++++++++++++++++++++++-----------------
 2 files changed, 54 insertions(+), 28 deletions(-)

diff --git a/sys/net/if_clone.c b/sys/net/if_clone.c
index a55ce9c3005d..a98e43328e0c 100644
--- a/sys/net/if_clone.c
+++ b/sys/net/if_clone.c
@@ -571,7 +571,7 @@ if_clone_addgroup(struct ifnet *ifp, struct if_clone *ifc)
 
 /*
  * A utility function to extract unit numbers from interface names of
- * the form name###[.###].
+ * the form name###.
  *
  * Returns 0 on success and an error on failure.
  */
@@ -582,9 +582,8 @@ ifc_name2unit(const char *name, int *unit)
 	int		cutoff = INT_MAX / 10;
 	int		cutlim = INT_MAX % 10;
 
-	if ((cp = strrchr(name, '.')) == NULL)
-		cp = name;
-	for (; *cp != '\0' && (*cp < '0' || *cp > '9'); cp++);
+	for (cp = name; *cp != '\0' && (*cp < '0' || *cp > '9'); cp++)
+		;
 	if (*cp == '\0') {
 		*unit = -1;
 	} else if (cp[0] == '0' && cp[1] != '\0') {
diff --git a/sys/net/if_vlan.c b/sys/net/if_vlan.c
index 9358724844cb..26fb48257c11 100644
--- a/sys/net/if_vlan.c
+++ b/sys/net/if_vlan.c
@@ -977,63 +977,86 @@ static int
 vlan_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
 {
 	char *dp;
-	int wildcard;
+	bool wildcard = false;
+	bool subinterface = false;
 	int unit;
 	int error;
-	int vid;
-	uint16_t proto;
+	int vid = 0;
+	uint16_t proto = ETHERTYPE_VLAN;
 	struct ifvlan *ifv;
 	struct ifnet *ifp;
-	struct ifnet *p;
+	struct ifnet *p = NULL;
 	struct ifaddr *ifa;
 	struct sockaddr_dl *sdl;
 	struct vlanreq vlr;
 	static const u_char eaddr[ETHER_ADDR_LEN];	/* 00:00:00:00:00:00 */
 
-	proto = ETHERTYPE_VLAN;
 
 	/*
-	 * There are two ways to specify the cloned device:
+	 * There are three ways to specify the cloned device:
 	 * o pass a parameter block with the clone request.
+	 * o specify parameters in the text of the clone device name
 	 * o specify no parameters and get an unattached device that
 	 *   must be configured separately.
-	 * The first technique is preferred; the latter is supported
+	 * The first technique is preferred; the latter two are supported
 	 * for backwards compatibility.
 	 *
 	 * XXXRW: Note historic use of the word "tag" here.  New ioctls may be
 	 * called for.
 	 */
+
 	if (params) {
 		error = copyin(params, &vlr, sizeof(vlr));
 		if (error)
 			return error;
+		vid = vlr.vlr_tag;
+		proto = vlr.vlr_proto;
+
 		p = ifunit_ref(vlr.vlr_parent);
 		if (p == NULL)
 			return (ENXIO);
-		error = ifc_name2unit(name, &unit);
-		if (error != 0) {
-			if_rele(p);
-			return (error);
-		}
-		vid = vlr.vlr_tag;
-		proto = vlr.vlr_proto;
-		wildcard = (unit < 0);
-	} else {
-		p = NULL;
-		error = ifc_name2unit(name, &unit);
-		if (error != 0)
-			return (error);
+	}
+
+	if ((error = ifc_name2unit(name, &unit)) == 0) {
 
+		/*
+		 * vlanX interface. Set wildcard to true if the unit number
+		 * is not fixed (-1)
+		 */
 		wildcard = (unit < 0);
+	} else {
+		struct ifnet *p_tmp = vlan_clone_match_ethervid(name, &vid);
+		if (p_tmp != NULL) {
+			error = 0;
+			subinterface = true;
+			unit = IF_DUNIT_NONE;
+			wildcard = false;
+			if (p != NULL) {
+				if_rele(p_tmp);
+				if (p != p_tmp)
+					error = EINVAL;
+			} else
+				p = p_tmp;
+		} else
+			error = ENXIO;
 	}
 
-	error = ifc_alloc_unit(ifc, &unit);
 	if (error != 0) {
 		if (p != NULL)
 			if_rele(p);
 		return (error);
 	}
 
+	if (!subinterface) {
+		/* vlanX interface, mark X as busy or allocate new unit # */
+		error = ifc_alloc_unit(ifc, &unit);
+		if (error != 0) {
+			if (p != NULL)
+				if_rele(p);
+			return (error);
+		}
+	}
+
 	/* In the wildcard case, we need to update the name. */
 	if (wildcard) {
 		for (dp = name; *dp != '\0'; dp++);
@@ -1046,7 +1069,8 @@ vlan_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
 	ifv = malloc(sizeof(struct ifvlan), M_VLAN, M_WAITOK | M_ZERO);
 	ifp = ifv->ifv_ifp = if_alloc(IFT_ETHER);
 	if (ifp == NULL) {
-		ifc_free_unit(ifc, unit);
+		if (!subinterface)
+			ifc_free_unit(ifc, unit);
 		free(ifv, M_VLAN);
 		if (p != NULL)
 			if_rele(p);
@@ -1094,7 +1118,8 @@ vlan_clone_create(struct if_clone *ifc, char *name, size_t len, caddr_t params)
 			ether_ifdetach(ifp);
 			vlan_unconfig(ifp);
 			if_free(ifp);
-			ifc_free_unit(ifc, unit);
+			if (!subinterface)
+				ifc_free_unit(ifc, unit);
 			free(ifv, M_VLAN);
 
 			return (error);
@@ -1108,6 +1133,7 @@ static int
 vlan_clone_destroy(struct if_clone *ifc, struct ifnet *ifp)
 {
 	struct ifvlan *ifv = ifp->if_softc;
+	int unit = ifp->if_dunit;
 
 	if (ifp->if_vlantrunk)
 		return (EBUSY);
@@ -1123,7 +1149,8 @@ vlan_clone_destroy(struct if_clone *ifc, struct ifnet *ifp)
 	NET_EPOCH_WAIT();
 	if_free(ifp);
 	free(ifv, M_VLAN);
-	ifc_free_unit(ifc, ifp->if_dunit);
+	if (unit != IF_DUNIT_NONE)
+		ifc_free_unit(ifc, unit);
 
 	return (0);
 }