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 | |
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
-rw-r--r-- | share/man/man4/vlan.4 | 26 | ||||
-rw-r--r-- | sys/net/if_vlan.c | 33 |
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 |