diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c --- a/sys/net/if_bridge.c +++ b/sys/net/if_bridge.c @@ -2778,22 +2778,19 @@ do { GRAB_OUR_PACKETS(bifp) } while (0); /* - * We only need to check members interfaces if member_ifaddrs is - * enabled; otherwise we should have never traffic destined for a - * member's lladdr. + * Check the interface the packet arrived on. For tagged frames, + * we need to do this even if member_ifaddrs is disabled because + * vlan(4) might need to handle the traffic. */ - - if (V_member_ifaddrs) { - /* - * Give a chance for ifp at first priority. This will help when - * the packet comes through the interface like VLAN's with the - * same MACs on several interfaces from the same bridge. This - * also will save some CPU cycles in case the destination - * interface and the input interface (eq ifp) are the same. - */ + if (V_member_ifaddrs || (vlan && ifp->if_vlantrunk)) do { GRAB_OUR_PACKETS(ifp) } while (0); - /* Now check the all bridge members. */ + /* + * We only need to check other members interface if member_ifaddrs + * is enabled; otherwise we should have never traffic destined for + * a member's lladdr. + */ + if (V_member_ifaddrs) { CK_LIST_FOREACH(bif2, &sc->sc_iflist, bif_next) { GRAB_OUR_PACKETS(bif2->bif_ifp) } diff --git a/tests/sys/net/if_bridge_test.sh b/tests/sys/net/if_bridge_test.sh --- a/tests/sys/net/if_bridge_test.sh +++ b/tests/sys/net/if_bridge_test.sh @@ -779,6 +779,56 @@ vnet_cleanup } +# +# Test kern/287150: when member_ifaddrs=0, and a physical interface which is in +# a bridge also has a vlan(4) on it, tagged packets are not correctly passed to +# vlan(4). +atf_test_case "member_ifaddrs_vlan" "cleanup" +member_ifaddrs_vlan_head() +{ + atf_set descr 'kern/287150: vlan and bridge on the same interface' + atf_set require.user root +} + +member_ifaddrs_vlan_body() +{ + vnet_init + vnet_init_bridge + + epone=$(vnet_mkepair) + eptwo=$(vnet_mkepair) + + # The first jail has an epair with an IP address on vlan 20. + vnet_mkjail one ${epone}a + atf_check -s exit:0 jexec one ifconfig ${epone}a up + atf_check -s exit:0 jexec one \ + ifconfig ${epone}a.20 create inet 192.0.2.1/24 up + + # The second jail has an epair with an IP address on vlan 20, + # which is also in a bridge. + vnet_mkjail two ${epone}b + + jexec two ifconfig + atf_check -s exit:0 -o save:bridge jexec two ifconfig bridge create + bridge=$(cat bridge) + atf_check -s exit:0 jexec two ifconfig ${bridge} addm ${epone}b up + + atf_check -s exit:0 -o ignore jexec two \ + sysctl net.link.bridge.member_ifaddrs=0 + atf_check -s exit:0 jexec two ifconfig ${epone}b up + atf_check -s exit:0 jexec two \ + ifconfig ${epone}b.20 create inet 192.0.2.2/24 up + + # Make sure the two jails can communicate over the vlan. + atf_check -s exit:0 -o ignore jexec one ping -c 3 -t 1 192.0.2.2 + atf_check -s exit:0 -o ignore jexec two ping -c 3 -t 1 192.0.2.1 +} + +member_ifaddrs_vlan_cleanup() +{ + vnet_cleanup +} + atf_init_test_cases() { atf_add_test_case "bridge_transmit_ipv4_unicast" @@ -796,4 +846,5 @@ atf_add_test_case "many_bridge_members" atf_add_test_case "member_ifaddrs_enabled" atf_add_test_case "member_ifaddrs_disabled" + atf_add_test_case "member_ifaddrs_vlan" }