diff options
Diffstat (limited to 'vswitchd/bridge.c')
-rw-r--r-- | vswitchd/bridge.c | 43 |
1 files changed, 42 insertions, 1 deletions
diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index 928d03ce3..86c50407e 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -2702,6 +2702,47 @@ port_is_floodable(const struct port *port) return true; } +/* Returns true if a packet with Ethernet destination MAC 'dst' may be mirrored + * to a VLAN. In general most packets may be mirrored but we want to drop + * protocols that may confuse switches. */ +static bool +eth_dst_may_rspan(const uint8_t dst[ETH_ADDR_LEN]) +{ + /* If you change this function's behavior, please update corresponding + * documentation in vswitch.xml at the same time. */ + if (dst[0] != 0x01) { + /* All the currently banned MACs happen to start with 01 currently, so + * this is a quick way to eliminate most of the good ones. */ + } else { + if (eth_addr_is_reserved(dst)) { + /* Drop STP, IEEE pause frames, and other reserved protocols + * (01-80-c2-00-00-0x). */ + return false; + } + + if (dst[0] == 0x01 && dst[1] == 0x00 && dst[2] == 0x0c) { + /* Cisco OUI. */ + if ((dst[3] & 0xfe) == 0xcc && + (dst[4] & 0xfe) == 0xcc && + (dst[5] & 0xfe) == 0xcc) { + /* Drop the following protocols plus others following the same + pattern: + + CDP, VTP, DTP, PAgP (01-00-0c-cc-cc-cc) + Spanning Tree PVSTP+ (01-00-0c-cc-cc-cd) + STP Uplink Fast (01-00-0c-cd-cd-cd) */ + return false; + } + + if (!(dst[3] | dst[4] | dst[5])) { + /* Drop Inter Switch Link packets (01-00-0c-00-00-00). */ + return false; + } + } + } + return true; +} + static void compose_dsts(const struct bridge *br, const struct flow *flow, uint16_t vlan, const struct port *in_port, const struct port *out_port, @@ -2744,7 +2785,7 @@ compose_dsts(const struct bridge *br, const struct flow *flow, uint16_t vlan, && !dst_is_duplicate(set, &dst)) { dst_set_add(set, &dst); } - } else { + } else if (eth_dst_may_rspan(flow->dl_dst)) { for (i = 0; i < br->n_ports; i++) { struct port *port = br->ports[i]; if (port_includes_vlan(port, m->out_vlan) |