summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryar <yar@FreeBSD.org>2006-08-11 17:09:27 +0000
committeryar <yar@FreeBSD.org>2006-08-11 17:09:27 +0000
commitfb2ee0939714f521f2fc39af715edfff27073086 (patch)
tree9acd1af35499174f6b31b4dd88f0731210a9ac1f
parent55b6d867eaa0f17178123f720a006cca67b0c14e (diff)
downloadFreeBSD-src-fb2ee0939714f521f2fc39af715edfff27073086.zip
FreeBSD-src-fb2ee0939714f521f2fc39af715edfff27073086.tar.gz
Optionally pad outgoing frames to the minimum of 60 bytes (excl. FCS)
before tagging them. This can help to work around brain-damage in some switches that fail to pad a frame after untagging it if its length drops below the minimum. This option is blessed by IEEE Std 802.1Q (2003 Ed.), paragraph C.4.4.3.b. It's controlled by sysctl net.link.vlan.soft_pad. Idea by: az MFC after: 1 week
-rw-r--r--share/man/man4/vlan.426
-rw-r--r--sys/net/if_vlan.c33
2 files changed, 57 insertions, 2 deletions
diff --git a/share/man/man4/vlan.4 b/share/man/man4/vlan.4
index 91dc78c..622620d 100644
--- a/share/man/man4/vlan.4
+++ b/share/man/man4/vlan.4
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd July 25, 2006
+.Dd August 11, 2006
.Dt VLAN 4
.Os
.Sh NAME
@@ -79,6 +79,27 @@ The parent interface is likely to be an Ethernet card connected
to a properly configured switch port.
The VLAN tag should match one of those set up in the switched
network.
+.Pp
+Initially
+.Nm
+assumes the same minimum length for tagged and untagged frames.
+This mode is selected by the
+.Xr sysctl(8)
+variable
+.Va net.link.vlan.soft_pad
+set to 0 (default).
+However, there are network devices that fail to adjust frame length,
+should it fall below the allowed minimum due to untagging.
+Such devices should be able to interoperate with
+.Nm
+after changing the value of
+.Va net.link.vlan.soft_pad
+to 1.
+In the latter mode,
+.Nm
+will pad short frames before tagging them
+so that their length stays not less than the minimum value
+after untagging by the non-compliant devices.
.Sh HARDWARE
The
.Nm
@@ -205,7 +226,8 @@ can be corrected manually if used in conjunction with such parent interface.
.Sh SEE ALSO
.Xr kqueue 2 ,
.Xr miibus 4 ,
-.Xr ifconfig 8
+.Xr ifconfig 8 ,
+.Xr sysctl 8
.Sh BUGS
No 802.1Q features except VLAN tagging are implemented.
.Pp
diff --git a/sys/net/if_vlan.c b/sys/net/if_vlan.c
index 9883066..498d2a2 100644
--- a/sys/net/if_vlan.c
+++ b/sys/net/if_vlan.c
@@ -132,6 +132,10 @@ SYSCTL_DECL(_net_link);
SYSCTL_NODE(_net_link, IFT_L2VLAN, vlan, CTLFLAG_RW, 0, "IEEE 802.1Q VLAN");
SYSCTL_NODE(_net_link_vlan, PF_LINK, link, CTLFLAG_RW, 0, "for consistency");
+static int soft_pad = 0;
+SYSCTL_INT(_net_link_vlan, OID_AUTO, soft_pad, CTLFLAG_RW, &soft_pad, 0,
+ "pad short frames before tagging");
+
static MALLOC_DEFINE(M_VLAN, VLANNAME, "802.1Q Virtual LAN Interface");
static eventhandler_tag ifdetach_tag;
@@ -809,6 +813,35 @@ vlan_start(struct ifnet *ifp)
}
/*
+ * Pad the frame to the minimum size allowed if told to.
+ * This option is in accord with IEEE Std 802.1Q, 2003 Ed.,
+ * paragraph C.4.4.3.b. It can help to work around buggy
+ * bridges that violate paragraph C.4.4.3.a from the same
+ * document, i.e., fail to pad short frames after untagging.
+ * E.g., a tagged frame 66 bytes long (incl. FCS) is OK, but
+ * untagging it will produce a 62-byte frame, which is a runt
+ * and requires padding. There are VLAN-enabled network
+ * devices that just discard such runts instead or mishandle
+ * them somehow.
+ */
+ if (soft_pad) {
+ static char pad[8]; /* just zeros */
+ int n;
+
+ for (n = ETHERMIN + ETHER_HDR_LEN - m->m_pkthdr.len;
+ n > 0; n -= sizeof(pad))
+ if (!m_append(m, min(n, sizeof(pad)), pad))
+ break;
+
+ if (n > 0) {
+ if_printf(ifp, "cannot pad short frame\n");
+ ifp->if_oerrors++;
+ m_freem(m);
+ continue;
+ }
+ }
+
+ /*
* If underlying interface can do VLAN tag insertion itself,
* just pass the packet along. However, we need some way to
* tell the interface where the packet came from so that it
OpenPOWER on IntegriCloud