Module Name: src Committed By: christos Date: Thu Nov 19 16:23:54 UTC 2015
Modified Files: src/sys/net: if_bridge.c if_ether.h if_ethersubr.c if_vlan.c Log Message: Add handling of VLAN packets in if_bridge where the parent interface supports them (jean-jacques.p...@espci.fr). Factor out the vlan_mtu enabling and disabling code. To generate a diff of this commit: cvs rdiff -u -r1.104 -r1.105 src/sys/net/if_bridge.c cvs rdiff -u -r1.64 -r1.65 src/sys/net/if_ether.h cvs rdiff -u -r1.214 -r1.215 src/sys/net/if_ethersubr.c cvs rdiff -u -r1.82 -r1.83 src/sys/net/if_vlan.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/net/if_bridge.c diff -u src/sys/net/if_bridge.c:1.104 src/sys/net/if_bridge.c:1.105 --- src/sys/net/if_bridge.c:1.104 Tue Oct 20 10:46:45 2015 +++ src/sys/net/if_bridge.c Thu Nov 19 11:23:54 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: if_bridge.c,v 1.104 2015/10/20 14:46:45 maxv Exp $ */ +/* $NetBSD: if_bridge.c,v 1.105 2015/11/19 16:23:54 christos Exp $ */ /* * Copyright 2001 Wasabi Systems, Inc. @@ -80,7 +80,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_bridge.c,v 1.104 2015/10/20 14:46:45 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_bridge.c,v 1.105 2015/11/19 16:23:54 christos Exp $"); #ifdef _KERNEL_OPT #include "opt_bridge_ipf.h" @@ -893,6 +893,8 @@ bridge_ioctl_add(struct bridge_softc *sc switch (ifs->if_type) { case IFT_ETHER: + if ((error = ether_enable_vlan_mtu(ifs)) > 0) + goto out; /* * Place the interface into promiscuous mode. */ @@ -970,6 +972,7 @@ bridge_ioctl_del(struct bridge_softc *sc * Don't call it with holding a spin lock. */ (void) ifpromisc(ifs, 0); + (void) ether_disable_vlan_mtu(ifs); break; default: #ifdef DIAGNOSTIC Index: src/sys/net/if_ether.h diff -u src/sys/net/if_ether.h:1.64 src/sys/net/if_ether.h:1.65 --- src/sys/net/if_ether.h:1.64 Mon Jul 28 10:24:48 2014 +++ src/sys/net/if_ether.h Thu Nov 19 11:23:54 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: if_ether.h,v 1.64 2014/07/28 14:24:48 ozaki-r Exp $ */ +/* $NetBSD: if_ether.h,v 1.65 2015/11/19 16:23:54 christos Exp $ */ /* * Copyright (c) 1982, 1986, 1993 @@ -337,6 +337,8 @@ uint32_t ether_crc32_le(const uint8_t *, uint32_t ether_crc32_be(const uint8_t *, size_t); int ether_aton_r(u_char *, size_t, const char *); +int ether_enable_vlan_mtu(struct ifnet *); +int ether_disable_vlan_mtu(struct ifnet *); #else /* * Prototype ethers(3) functions. Index: src/sys/net/if_ethersubr.c diff -u src/sys/net/if_ethersubr.c:1.214 src/sys/net/if_ethersubr.c:1.215 --- src/sys/net/if_ethersubr.c:1.214 Tue Oct 13 08:33:07 2015 +++ src/sys/net/if_ethersubr.c Thu Nov 19 11:23:54 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: if_ethersubr.c,v 1.214 2015/10/13 12:33:07 roy Exp $ */ +/* $NetBSD: if_ethersubr.c,v 1.215 2015/11/19 16:23:54 christos Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -61,7 +61,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_ethersubr.c,v 1.214 2015/10/13 12:33:07 roy Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_ethersubr.c,v 1.215 2015/11/19 16:23:54 christos Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -1416,6 +1416,75 @@ ether_ioctl(struct ifnet *ifp, u_long cm return 0; } +/* + * Enable/disable passing VLAN packets if the parent interface supports it. + * Return: + * 0: Ok + * -1: Parent interface does not support vlans + * >0: Error + */ +int +ether_enable_vlan_mtu(struct ifnet *ifp) +{ + int error; + struct ethercom *ec = (void *)ifp; + + /* Already have VLAN's do nothing. */ + if (ec->ec_nvlans != 0) + return 0; + + /* Parent does not support VLAN's */ + if ((ec->ec_capabilities & ETHERCAP_VLAN_MTU) == 0) + return -1; + + /* + * Parent supports the VLAN_MTU capability, + * i.e. can Tx/Rx larger than ETHER_MAX_LEN frames; + * enable it. + */ + ec->ec_capenable |= ETHERCAP_VLAN_MTU; + + /* Interface is down, defer for later */ + if ((ifp->if_flags & IFF_UP) == 0) + return 0; + + if ((error = if_flags_set(ifp, ifp->if_flags)) == 0) + return 0; + + ec->ec_capenable &= ~ETHERCAP_VLAN_MTU; + return error; +} + +int +ether_disable_vlan_mtu(struct ifnet *ifp) +{ + int error; + struct ethercom *ec = (void *)ifp; + + /* We still have VLAN's, defer for later */ + if (ec->ec_nvlans != 0) + return 0; + + /* Parent does not support VLAB's, nothing to do. */ + if ((ec->ec_capenable & ETHERCAP_VLAN_MTU) == 0) + return -1; + + /* + * Disable Tx/Rx of VLAN-sized frames. + */ + ec->ec_capenable &= ~ETHERCAP_VLAN_MTU; + + /* Interface is down, defer for later */ + if ((ifp->if_flags & IFF_UP) == 0) + return 0; + + if ((error = if_flags_set(ifp, ifp->if_flags)) == 0) + return 0; + + ec->ec_capenable |= ETHERCAP_VLAN_MTU; + return error; +} + static int ether_multicast_sysctl(SYSCTLFN_ARGS) { Index: src/sys/net/if_vlan.c diff -u src/sys/net/if_vlan.c:1.82 src/sys/net/if_vlan.c:1.83 --- src/sys/net/if_vlan.c:1.82 Thu Aug 20 10:40:19 2015 +++ src/sys/net/if_vlan.c Thu Nov 19 11:23:54 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: if_vlan.c,v 1.82 2015/08/20 14:40:19 christos Exp $ */ +/* $NetBSD: if_vlan.c,v 1.83 2015/11/19 16:23:54 christos Exp $ */ /*- * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc. @@ -78,7 +78,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_vlan.c,v 1.82 2015/08/20 14:40:19 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_vlan.c,v 1.83 2015/11/19 16:23:54 christos Exp $"); #ifdef _KERNEL_OPT #include "opt_inet.h" @@ -284,36 +284,22 @@ vlan_config(struct ifvlan *ifv, struct i ifv->ifv_encaplen = ETHER_VLAN_ENCAP_LEN; ifv->ifv_mintu = ETHERMIN; - /* - * If the parent supports the VLAN_MTU capability, - * i.e. can Tx/Rx larger than ETHER_MAX_LEN frames, - * enable it. - */ - if (ec->ec_nvlans++ == 0 && - (ec->ec_capabilities & ETHERCAP_VLAN_MTU) != 0) { - /* - * Enable Tx/Rx of VLAN-sized frames. - */ - ec->ec_capenable |= ETHERCAP_VLAN_MTU; - if (p->if_flags & IFF_UP) { - error = if_flags_set(p, p->if_flags); - if (error) { - if (ec->ec_nvlans-- == 1) - ec->ec_capenable &= - ~ETHERCAP_VLAN_MTU; - return (error); - } + if (ec->ec_nvlans == 0) { + if ((error = ether_enable_vlan_mtu(p)) >= 0) { + if (error) + return error; + ifv->ifv_mtufudge = 0; + } else { + /* + * Fudge the MTU by the encapsulation size. This + * makes us incompatible with strictly compliant + * 802.1Q implementations, but allows us to use + * the feature with other NetBSD + * implementations, which might still be useful. + */ + ifv->ifv_mtufudge = ifv->ifv_encaplen; } - ifv->ifv_mtufudge = 0; - } else if ((ec->ec_capabilities & ETHERCAP_VLAN_MTU) == 0) { - /* - * Fudge the MTU by the encapsulation size. This - * makes us incompatible with strictly compliant - * 802.1Q implementations, but allows us to use - * the feature with other NetBSD implementations, - * which might still be useful. - */ - ifv->ifv_mtufudge = ifv->ifv_encaplen; + ec->ec_nvlans++; } /* @@ -386,16 +372,9 @@ vlan_unconfig(struct ifnet *ifp) switch (p->if_type) { case IFT_ETHER: { - struct ethercom *ec = (void *) p; - - if (ec->ec_nvlans-- == 1) { - /* - * Disable Tx/Rx of VLAN-sized frames. - */ - ec->ec_capenable &= ~ETHERCAP_VLAN_MTU; - if (p->if_flags & IFF_UP) - (void)if_flags_set(p, p->if_flags); - } + struct ethercom *ec = (void *)p; + if (--ec->ec_nvlans == 0) + (void)ether_disable_vlan_mtu(p); ether_ifdetach(ifp); /* Restore vlan_ioctl overwritten by ether_ifdetach */