kern/127815: if_gif does not set vlan attributes from EtherIP
encapsulated 802.1 packets
Serge Potapov
sp at smartspb.net
Fri Oct 3 12:00:11 UTC 2008
>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 at 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:
More information about the freebsd-bugs
mailing list