diff options
author | yar <yar@FreeBSD.org> | 2006-08-11 17:09:27 +0000 |
---|---|---|
committer | yar <yar@FreeBSD.org> | 2006-08-11 17:09:27 +0000 |
commit | fb2ee0939714f521f2fc39af715edfff27073086 (patch) | |
tree | 9acd1af35499174f6b31b4dd88f0731210a9ac1f /sys/net/if_vlan.c | |
parent | 55b6d867eaa0f17178123f720a006cca67b0c14e (diff) | |
download | FreeBSD-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.c | 33 |
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 |