diff options
author | Chris Cappuccio <chris@cvs.openbsd.org> | 2001-08-03 23:21:21 +0000 |
---|---|---|
committer | Chris Cappuccio <chris@cvs.openbsd.org> | 2001-08-03 23:21:21 +0000 |
commit | f5a456948912fe2334de6af3556c036bf63c117f (patch) | |
tree | f06b5d8fb896c08a1f6771233f64ceb45f2a4d5d | |
parent | 2b31e82237dabc508cbc2df2c9a840ed81cab1cc (diff) |
Use IFCAP_VLAN_MTU and IFCAP_VLAN_HWTAGGING capabilities:
LINK0 disappears; we now set IFCAP_VLAN_HWTAGGING at ifnet->if_capabilities
in the Ethernet driver for cards/drivers which support hardware tagging.
MTU ambiguity disppears; we now set IFCAP_VLAN_MTU in the Ethernet driver
when we know the chip will not truncate/discard vlan-sized frames.
Only allow the MTU to be changed within the scope of the parent interface's
MTU. (Here we also take into account IFCAP_VLAN_MTU)
Propagate hardware-assisted IP/TCP/UDP checksumming flags to the vlan interface
if the card supports hardware tagging (from NetBSD)
-rw-r--r-- | share/man/man4/vlan.4 | 96 | ||||
-rw-r--r-- | sys/net/if_vlan.c | 82 |
2 files changed, 115 insertions, 63 deletions
diff --git a/share/man/man4/vlan.4 b/share/man/man4/vlan.4 index 60c113a023a..26b0a088c3a 100644 --- a/share/man/man4/vlan.4 +++ b/share/man/man4/vlan.4 @@ -1,4 +1,4 @@ -.\" $OpenBSD: vlan.4,v 1.11 2001/08/03 15:21:16 mpech Exp $ +.\" $OpenBSD: vlan.4,v 1.12 2001/08/03 23:21:20 chris Exp $ .\" .Dd January 9, 2000 .Dt VLAN 4 @@ -54,15 +54,48 @@ Set the vlan tag and parent for a given vlan interface. Get the vlan tag and parent for a given vlan interface. .Pp .El -The operation mode can be given as -.Bl -tag -width bbb -.It link0 -The parent interface supports VLAN tagging/untagging in hardware, -this requires support from the Ethernet driver as well. +.Xr vlan 4 +interfaces use the following interface capabilities: +.Bl -tag -width aaa +.It IFCAP_VLAN_MTU: +The parent interface can handle full sized frames, plus the size +of the vlan tag. +.It IFCAP_VLAN_HWTAGGING: +The parent interface will participate in the tagging and untagging of frames. .El +.Sh DIAGNOSTICS +.Bl -diag +.It "vlan%d: initialized with non-standard mtu %d (parent %s)" +The IFCAP_VLAN_MTU capability was not set on the parent interface. +We assume in this event that the parent interface is not capable of handling +frames larger then its MTU. This will generally result in a non-compliant +802.1Q implementation. .Pp -to -.Xr ifconfig 8 . +Some Ethernet chips will either discard or truncate +Ethernet frames that are larger then 1514 bytes. This causes a problem as +802.1Q tagged frames can be up to 1518 bytes. +Most controller chips can be told not to discard large frames +and/or to increase the allowed frame size. Refer to the hardware manual +for your chip to do this. +.El +.Pp +If the IFCAP_VLAN_MTU capability is set on a vlan parent, +.Xr vlan 4 +assumes that Ethernet chip on the parent can handle +oversized frames. +Either the chip allows 1518 byte frames by default (such as +.Xr rl 4 ), +the driver has instructed the chip to do so (such as +.Xr fxp 4 +and +.Xr dc 4 ), +or the driver also takes advantage of a hardware tagging capability, +and thus oversized frames are never actually sent or received by +.Ox +(such as +.Xr txp 4 +and +.Xr ti 4 .) .Sh SEE ALSO .Xr bridge 4 , .Xr inet 4 , @@ -70,42 +103,33 @@ to .Xr netintro 4 , .Xr ifconfig 8 .Pp -All aspects of the vlan interface can be configured with -.Xr ifconfig 8 ; -see its manual page for more information. +.Rs +.%T IEEE 802.1Q standard +.%O http://standards.ieee.org/getieee802/802.1.html +.Re .Pp -A draft of IEEE 802.1Q standard can be obtained from -http://grouper.ieee.org/groups/802/1/pages/802.1Q.html -or the final version can be purchased from the -Institute of Electrical and Electronic Engineers, Inc. +The vlan interface is to be configured with +.Xr ifconfig 8 , +see its manual page for more information. .Sh BUGS The 802.1Q specification allows for operation over FDDI and Token Ring as well as Ethernet. This driver only supports such operation with Ethernet devices. .Pp -Some Ethernet chips (notably the Intel 82558 and 82559) automatically -discard frames that are larger then 1514 bytes. -All Ethernet -chips supporting this sort of feature should allow for it to be turned off. -Optimally, upon loading, the chip's driver would do this (The -.Xr fxp 4 -driver currently does for the Intel 82558/82559 chips.) -Refer to the hardware manual for your Ethernet chip to determine -if it has this feature, and if so, for information on how to turn it off. -A symptom of this problem is that small frames pass through the VLAN -(such as a frame carrying an ICMP packet), but frames which are at MTU size -are dropped. -When these frames are dropped, the TCP session will hang. -A temporary kludge is to set the MTU for each machine behind each VLAN to -1496 or less. -.Pp -Some Ethernet chips support 802.1Q tagging/untagging in hardware, but -do not have the appropriate hooks in their driver to pass the frame -directly to if_vlan. -The PCI device driver if_ti is able to do this, use it as a reference. +When the IFCAP_VLAN_HWTAGGING capability is set on the parent interface, +.Xr vlan 4 +does not participate in the actual tagging or untagging of Ethernet frames. +It simply passes the vlan ID on to the parent interface for tagging on transmit, +and gets a vlan ID for each packet on receive. +The vlan tagged packet is not actually visible to +.Ox . +Thus, +.Xr bpf 4 +will show untagged packets on the parent interface, although frames +are actually being transmitted and received with tags on the wire. .Pp This driver could be the basis for support of the Cisco ISL VLAN protocol, -detailed at http://www.cisco.com/warp/public/741/4.html. +detailed at http://www.cisco.com/warp/public/741/4.html . Unfortunately, public reimplementation of this protocol is currently prevented by patent (at least in the USA). .Sh AUTHORS diff --git a/sys/net/if_vlan.c b/sys/net/if_vlan.c index 5f7546803fa..53b1457c7b6 100644 --- a/sys/net/if_vlan.c +++ b/sys/net/if_vlan.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_vlan.c,v 1.24 2001/06/27 06:07:46 kjc Exp $ */ +/* $OpenBSD: if_vlan.c,v 1.25 2001/08/03 23:21:19 chris Exp $ */ /* * Copyright 1998 Massachusetts Institute of Technology * @@ -41,16 +41,10 @@ * if_start(), rewrite them for use by the real outgoing interface, * and ask it to send them. * - * - * XXX It's incorrect to assume that we must always kludge up - * headers on the physical device's behalf: some devices support - * VLAN tag insersion and extraction in firmware. For these cases, - * one can change the behavior of the vlan interface by setting - * the LINK0 flag on it (that is setting the vlan interface's LINK0 - * flag, _not_ the parent's LINK0 flag; we try to leave the parent - * alone). If the interface has the LINK0 flag set, then it will - * not modify the ethernet header on output because the parent - * can do that for itself. On input, the parent can call vlan_input_tag() + * Some devices support 802.1Q tag insertion and extraction in firmware. + * The vlan interface behavior changes when the IFCAP_VLAN_HWTAGGING + * capability is set on the parent. In this case, vlan_start() will not + * modify the ethernet header. On input, the parent can call vlan_input_tag() * directly in order to supply us with an incoming mbuf and the vlan * tag value that goes with it. */ @@ -230,9 +224,9 @@ vlan_start(struct ifnet *ifp) #endif /* - * If the LINK0 flag is set, it means the underlying interface - * can do VLAN tag insertion itself and doesn't require us to - * create a special header for it. In this case, we just pass + * If the IFCAP_VLAN_HWTAGGING capability is set on the parent, + * it can do VLAN tag insertion itself and doesn't require us + * to create a special header for it. In this case, we just pass * the packet along. However, we need some way to tell the * interface where the packet came from so that it knows how * to find the VLAN tag to use, so we set the rcvif in the @@ -247,7 +241,7 @@ vlan_start(struct ifnet *ifp) * following potentially bogus rcvif pointers off into * never-never land. */ - if (ifp->if_flags & IFF_LINK0) { + if (p->if_capabilities & IFCAP_VLAN_HWTAGGING) { m->m_pkthdr.rcvif = ifp; m->m_flags |= M_PROTO1; } else { @@ -444,7 +438,22 @@ vlan_config(struct ifvlan *ifv, struct ifnet *p) if (ifv->ifv_p) return EBUSY; ifv->ifv_p = p; - ifv->ifv_if.if_mtu = p->if_data.ifi_mtu; + + if (p->if_capabilities & IFCAP_VLAN_MTU) + ifv->ifv_if.if_mtu = p->if_mtu; + else { + /* + * This will be incompatible with strict + * 802.1Q implementations + */ + ifv->ifv_if.if_mtu = p->if_mtu - EVL_ENCAPLEN; +#ifdef DIAGNOSTIC + printf("%s: initialized with non-standard mtu %d (parent %s)\n", + ifv->ifv_if.if_xname, ifv->ifv_if.if_mtu, + ifv->ifv_p->if_xname); +#endif + } + ifv->ifv_if.if_flags = p->if_flags & (IFF_UP | IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST); @@ -455,6 +464,23 @@ vlan_config(struct ifvlan *ifv, struct ifnet *p) ifv->ifv_if.if_type = p->if_type; /* + * If the parent interface can do hardware-assisted + * VLAN encapsulation, then propagate its hardware- + * assisted checksumming flags. + * + * If the card cannot handle hardware tagging, it cannot + * possibly compute the correct checksums for tagged packets. + * + * This brings up another possibility, do cards exist which + * have all of these capabilities but cannot utilize them together? + */ + if (p->if_capabilities & IFCAP_VLAN_HWTAGGING) + ifv->ifv_if.if_capabilities = p->if_capabilities & + (IFCAP_CSUM_IPv4|IFCAP_CSUM_TCPv4| + IFCAP_CSUM_UDPv4); + /* (IFCAP_CSUM_TCPv6|IFCAP_CSUM_UDPv6); */ + + /* * Set up our ``Ethernet address'' to reflect the underlying * physical interface's. */ @@ -549,7 +575,7 @@ vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) struct ifreq *ifr; struct ifvlan *ifv; struct vlanreq vlr; - int error = 0; + int error = 0, p_mtu = 0; ifr = (struct ifreq *)data; ifa = (struct ifaddr *)data; @@ -585,17 +611,19 @@ vlan_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) break; case SIOCSIFMTU: - /* - * XXX Set the interface MTU. - * This is bogus. The underlying interface might support - * jumbo frames. It would be nice to replace ETHERMTU - * with the parent interface's MTU in the following statement. - */ - if (ifr->ifr_mtu > ETHERMTU || ifr->ifr_mtu < ETHERMIN) { + if (ifv->ifv_p != NULL) { + if (ifv->ifv_p->if_capabilities & IFCAP_VLAN_MTU) + p_mtu = ifv->ifv_p->if_mtu; + else + p_mtu = ifv->ifv_p->if_mtu - EVL_ENCAPLEN; + + if (ifr->ifr_mtu > p_mtu || ifr->ifr_mtu < ETHERMIN) + error = EINVAL; + else + ifp->if_mtu = ifr->ifr_mtu; + } else error = EINVAL; - } else { - ifp->if_mtu = ifr->ifr_mtu; - } + break; case SIOCSETVLAN: |