X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=vswitchd%2Fbridge.c;fp=vswitchd%2Fbridge.c;h=adc3e9f07b1c7d30bda0051b9e5b636cc51b29a3;hb=6cd1fd9128bb9719fad0a0f210308069f71fafd6;hp=e43af3c90aa42e2237c7a99e2ad560d1da164989;hpb=ab8cea8c8980cd27669967a78385c989133ee4ce;p=sliver-openvswitch.git diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index e43af3c90..adc3e9f07 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -2656,6 +2656,47 @@ port_get_an_iface(const struct port *port) return CONTAINER_OF(list_front(&port->ifaces), struct iface, port_elem); } +/* 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, @@ -2698,7 +2739,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)) { struct port *port; HMAP_FOR_EACH (port, hmap_node, &br->ports) {