Date: Fri, 3 Oct 2008 11:57:20 GMT From: Serge Potapov <sp@smartspb.net> To: freebsd-gnats-submit@FreeBSD.org Subject: kern/127815: if_gif does not set vlan attributes from EtherIP encapsulated 802.1 packets Message-ID: <200810031157.m93BvK5x039706@www.freebsd.org> Resent-Message-ID: <200810031200.m93C0B9S072056@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 127815 >Category: kern >Synopsis: if_gif does not set vlan attributes from EtherIP encapsulated 802.1 packets >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Fri Oct 03 12:00:10 UTC 2008 >Closed-Date: >Last-Modified: >Originator: Serge Potapov >Release: 7.1-BETA1 >Organization: Smart Telecom >Environment: FreeBSD test89.smartspb.net 7.1-BETA FreeBSD 7.1-BETA #1: Thu Oct 2 12:36:03 MSD 2008 root@test89.smartspb.net:/usr/obj/usr/src/sys/K7_LINAS_SRV_SMP i386 >Description: vlan2, mac2 -> interface2 vlan3, mac1 -> interface1 and so on. When gif interface receives EtherIP encapsulating 802.1Q packet it does not set m->m_pkthdr.ether_vtag and m->m_flags |= M_VLANTAG. Chain: ether<->if_bridge<->gif<->gif<->if_bridge<->ether transmits vlan tagged packets properly, but if_bridge bridge stores all MAC addresses learned from gif side in vlan1. In point-to-multipoint environment unicast 802.1Q (vlan_tag != 1) packets received from physical ethernet interface will be always sent over all gif interfaces attached to if_bridge. >How-To-Repeat: Simple, but need a lot of equipment. = | em0 +------+ em1 fxp0 +-------+ +--------+ CPE1 +-----------+ HOST1 | | $ip1 +------+ +-------+ | | em0 +------+ em1 fxp0 +-------+ +--------+ CPE2 +-----------+ HOST2 | | $ip3 +------+ +-------+ | | em0 +------+ em1 fxp0 +-------+ +--------+ CPE3 +-----------| HOST3 | | $ip3 +------+ +-------+ = CPE1: ifconfig bridge0 create; ifconfig em1 up; ifconfig bridge0 addm em1 up ifconfig gif2 create; ifconfig gif2 tunnel $ip1 $ip2 ifconfig bridge0 addm gif2; ifconfig bridge0 private gif2 ifconfig gif3 create; ifconfig gif3 tunnel $ip1 $ip3 ifconfig bridge0 addm gif3; ifconfig bridge0 private gif3 CPE2: ifconfig bridge0 create ifconfig em1 up; ifconfig bridge0 addm1 up ifconfig gif1 create; ifconfig gif1 tunnel $ip2 $ip1 ifconfig bridge0 addm gif1; ifconfig bridge0 private gif1 ifconfig gif3 create; ifconfig gif3 tunnel $ip2 $ip3 ifconfig bridge0 addm gif3; ifconfig bridge0 private gif3 CPE3: ifconfig bridge0 create ifconfig em1 up; ifconfig bridge0 addm1 up ifconfig gif1 create; ifconfig gif1 tunnel $ip3 $ip1 ifconfig bridge0 addm gif1; ifconfig bridge0 private gif1 ifconfig gif2 create; ifconfig gif2 tunnel $ip3 $ip2 ifconfig bridge0 addm gif2; ifconfig bridge0 private gif2 =================================================================== With plain 802.1 ethernet all works fine (thanks for private flag). No extra traffic, no loops. Almost poor man's VPLS. But after: HOST1: ifconfig fxp0 up ifconfig vlan5 create ifconfig vlan5 10.10.10.1/24 vlan 5 vlandev fxp0 HOST2: ifconfig fxp0 up ifconfig vlan5 create ifconfig vlan5 10.10.10.2/24 vlan 5 vlandev fxp0 ping 10.10.10.1 CPE2 will send all icmp requests received on em1 over gif1 and gif3 [waste] CPE1 will sens all icmp replies received on em0 over gif2 and gif3 [waste] CPE3 will receive icmp requests on gif2 and replies on gif1 and send all packets to em1. >Fix: Patch attached. Not sure about proper place. After patching vlan MACs stored properly and bridge woriking right. Not tested too much. Patch attached with submission follows: --- /sys/net/if_gif.c.orig 2008-10-03 14:18:50.000000000 +0400 +++ /sys/net/if_gif.c 2008-10-03 11:43:48.000000000 +0400 @@ -81,6 +81,7 @@ #include <netinet/ip_encap.h> #include <net/ethernet.h> +#include <net/if_vlan_var.h> #include <net/if_bridgevar.h> #include <net/if_gif.h> @@ -560,6 +561,31 @@ m->m_flags |= M_MCAST; ifp->if_imcasts++; } + /* Check vlan tagging on received frame. */ + /* Probably should be moved somewhere up. */ + if (ntohs(eh->ether_type) == ETHERTYPE_VLAN) { + /* Copy from if_ethersubr.c */ + struct ether_vlan_header *evl; + if (m->m_len < sizeof(*evl) && + (m = m_pullup(m, sizeof(*evl))) == NULL) { +#ifdef DIAGNOSTIC + if_printf(ifp, "cannot pullup VLAN header\n"); +#endif + ifp->if_ierrors++; + m_freem(m); + return; + } + + evl = mtod(m, struct ether_vlan_header *); + m->m_pkthdr.ether_vtag = ntohs(evl->evl_tag); + m->m_flags |= M_VLANTAG; + + bcopy((char *)evl, (char *)evl + ETHER_VLAN_ENCAP_LEN, + ETHER_HDR_LEN - ETHER_TYPE_LEN); + m_adj(m, ETHER_VLAN_ENCAP_LEN); + /* End of copy */ + } + BRIDGE_INPUT(ifp, m); if (m != NULL && ifp != oldifp) { >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200810031157.m93BvK5x039706>