summaryrefslogtreecommitdiffstats
path: root/sys/net/if_vlan.c
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 /sys/net/if_vlan.c
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
Diffstat (limited to 'sys/net/if_vlan.c')
-rw-r--r--sys/net/if_vlan.c33
1 files changed, 33 insertions, 0 deletions
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