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 /sys/net | |
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)
Diffstat (limited to 'sys/net')
-rw-r--r-- | sys/net/if_vlan.c | 82 |
1 files changed, 55 insertions, 27 deletions
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: |