summaryrefslogtreecommitdiff
path: root/sys/net/if_vlan.c
diff options
context:
space:
mode:
authorChris Cappuccio <chris@cvs.openbsd.org>2001-08-03 23:21:21 +0000
committerChris Cappuccio <chris@cvs.openbsd.org>2001-08-03 23:21:21 +0000
commitf5a456948912fe2334de6af3556c036bf63c117f (patch)
treef06b5d8fb896c08a1f6771233f64ceb45f2a4d5d /sys/net/if_vlan.c
parent2b31e82237dabc508cbc2df2c9a840ed81cab1cc (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/if_vlan.c')
-rw-r--r--sys/net/if_vlan.c82
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: