tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Xen, Bridge, VLANs



Hi,

I submit the attached patch to your consideration for inclusion
(possibly with amendments) to the kernel source.

It deals with an old issue raised on the port-xen ML on the 2008/06/21
(http://mail-index.netbsd.org/port-xen/2008/06/21/msg003915.html).

* Summary:
Where VLAN interfaces are required in a domU, Ethernet frames (sent and
received) on these interfaces are limited to a 1496 bytes MTU, because
xennet interface does not currently support the VLAN_MTU capability.

Furthermore, the frame size check on dom0's xen interface does not
account for the possibility of an extended MTU for VLAN traffic and does
not support the capability either.

This patch adds the VLAN_MTU capability to these interfaces. In
particular, the frame size check takes ETHER_VLAN_ENCAP_LEN into
consideration *if the capability is enabled*.

Where a VLAN interface is attached to such interfaces, the VLAN_MTU
capability will be enabled. Most probable use for this configuration is
on the domU side. On the dom0 side, however, xen interfaces are usually
members of a bridge interface.

This patch also modifies the bridge interface in order to enable the
VLAN_MTU capability on interfaces added to the bridge and to disable
this capability on interfaces removed from the bridge, only if they do
not already deal with VLAN traffic as the result of another
configuration.

This does not actually change the traffic processing operations on the
bridge side (but may on the member interface side as a result of the
capability being enabled), because a bridge interface sets promiscuous
mode on member interfaces. In this mode, received frames bigger than
member interface's configured MTU actually get through; this is why
tcpdump can show frames that are actually dropped by normal
(non-promiscuous) receiving routines on the interface.

* Background:
This patch was developped to address MTU issues on a wireless LAN
infrastructure, where multiple SSIDs (currently eduroam and eduspot) and
management traffic are each mapped on a different VLAN, as is often
mandatory while dealing with enterprise class access-points. Tagged VLAN
traffic is then bridged to a domU which acts as the wireless LAN
gateway. Alternatives involved a mix of DHCP interface-mtu option
(ignored by many clients), MSS clamping, RADIUS framed-mtu property and
kernel tcp.mss_ifmtu state and still could not resolve issues with some
traffics.

We've been using a first version of this patch since Oct 29, and current
version since Nov. 16.

-- 
Jean-Jacques Puig
Service Informatique ESPCI ParisTech
--- net/if_bridge.c.orig	2015-11-10 14:17:33.000000000 +0100
+++ net/if_bridge.c	2015-11-10 16:48:24.000000000 +0100
@@ -595,11 +595,26 @@
 
 	switch (ifs->if_type) {
 	case IFT_ETHER:
+	    {
+		struct ethercom *ec = (void *) ifs;
+
 		/*
 		 * Take the interface out of promiscuous mode.
 		 */
 		(void) ifpromisc(ifs, 0);
+
+		if (ec->ec_nvlans == 0 &&
+		    (ec->ec_capenable & ETHERCAP_VLAN_MTU) != 0) {
+			/*
+			 * Disable Tx/Rx of VLAN-sized frames.
+			 */
+			ec->ec_capenable &= ~ETHERCAP_VLAN_MTU;
+			if (ifs->if_flags & IFF_UP) {
+				(void) if_flags_set(ifs, ifs->if_flags);
+			}
+		}
 		break;
+	    }
 	default:
 #ifdef DIAGNOSTIC
 		panic("bridge_delete_member: impossible");
@@ -645,13 +660,35 @@
 
 	switch (ifs->if_type) {
 	case IFT_ETHER:
-		/*
-		 * Place the interface into promiscuous mode.
-		 */
-		error = ifpromisc(ifs, 1);
-		if (error)
-			goto out;
-		break;
+		{
+			struct ethercom *ec = (void *) ifs;
+
+			if (ec->ec_nvlans == 0 &&
+		    	    (ec->ec_capabilities & ETHERCAP_VLAN_MTU) != 0) {
+				/*
+				 * Enable Tx/Rx of VLAN-sized frames.
+				 */
+				ec->ec_capenable |= ETHERCAP_VLAN_MTU;
+				if (ifs->if_flags & IFF_UP) {
+					error = if_flags_set(ifs,
+							     ifs->if_flags);
+					if (error) {
+						if (ec->ec_nvlans == 0)
+							ec->ec_capenable &=
+							    ~ETHERCAP_VLAN_MTU;
+					       
+						goto out;
+					}
+				}
+			}
+			/*
+			 * Place the interface into promiscuous mode.
+			 */
+			error = ifpromisc(ifs, 1);
+			if (error)
+				goto out;
+			break;
+		}
 	default:
 		error = EINVAL;
 		goto out;
--- arch/xen/xen/xennetback_xenbus.c.orig	2015-11-10 15:52:02.000000000 +0100
+++ arch/xen/xen/xennetback_xenbus.c	2015-11-10 16:01:14.000000000 +0100
@@ -300,6 +300,7 @@
 	/* create pseudo-interface */
 	aprint_verbose_ifnet(ifp, "Ethernet address %s\n",
 	    ether_sprintf(xneti->xni_enaddr));
+	xneti->xni_ec.ec_capabilities |= ETHERCAP_VLAN_MTU;
 	ifp->if_flags =
 	    IFF_BROADCAST|IFF_SIMPLEX|IFF_NOTRAILERS|IFF_MULTICAST;
 	ifp->if_snd.ifq_maxlen =
@@ -748,7 +749,11 @@
 		 * Do some sanity checks, and map the packet's page.
 		 */
 		if (__predict_false(txreq->size < ETHER_HDR_LEN ||
-		   txreq->size > (ETHER_MAX_LEN - ETHER_CRC_LEN))) {
+		   txreq->size > ((
+			(xneti->xni_ec.ec_capenable & ETHERCAP_VLAN_MTU) ?
+				ETHER_VLAN_ENCAP_LEN + ETHER_MAX_LEN :
+				ETHER_MAX_LEN
+			) - ETHER_CRC_LEN))) {
 			printf("%s: packet size %d too big\n",
 			    ifp->if_xname, txreq->size);
 			xennetback_tx_response(xneti, txreq->id,
--- arch/xen/xen/if_xennet_xenbus.c.orig	2015-11-10 15:49:22.000000000 +0100
+++ arch/xen/xen/if_xennet_xenbus.c	2015-11-10 15:49:07.000000000 +0100
@@ -362,6 +362,7 @@
 	    ether_sprintf(sc->sc_enaddr));
 	/* Initialize ifnet structure and attach interface */
 	strlcpy(ifp->if_xname, device_xname(self), IFNAMSIZ);
+	sc->sc_ethercom.ec_capabilities |= ETHERCAP_VLAN_MTU;
 	ifp->if_softc = sc;
 	ifp->if_start = xennet_start;
 	ifp->if_ioctl = xennet_ioctl;


Home | Main Index | Thread Index | Old Index