From: Jesse Gross Date: Sun, 6 Nov 2011 00:18:04 +0000 (-0700) Subject: tunneling: Reduce priority of multicast tunnels. X-Git-Tag: v1.4.0~200 X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=859ad376132e1eb13d0a1a28cae2c477300fd45f;p=sliver-openvswitch.git tunneling: Reduce priority of multicast tunnels. It's possible to have an incoming packet that matches both a unicast and multicast tunnel if the source address corresponds to the remote_ip of a unicast tunnel and the destination is multicast. Currently this will match the multicast tunnel but in reality the unicast tunnel should probably be considered more specific. This is actually a common situation in protocols that use a combination of multicast for flooding and unicast for responses. Signed-off-by: Jesse Gross Acked-by: Ben Pfaff --- diff --git a/datapath/tunnel.c b/datapath/tunnel.c index 9bb9cef3a..6c0e9b7e3 100644 --- a/datapath/tunnel.c +++ b/datapath/tunnel.c @@ -288,26 +288,7 @@ struct vport *tnl_find_port(__be32 saddr, __be32 daddr, __be64 key, { struct port_lookup_key lookup; struct vport *vport; - - if (ipv4_is_multicast(saddr)) { - lookup.saddr = 0; - lookup.daddr = saddr; - if (key_remote_ports) { - lookup.tunnel_type = tunnel_type | TNL_T_KEY_EXACT; - lookup.in_key = key; - vport = port_table_lookup(&lookup, mutable); - if (vport) - return vport; - } - if (remote_ports) { - lookup.tunnel_type = tunnel_type | TNL_T_KEY_MATCH; - lookup.in_key = 0; - vport = port_table_lookup(&lookup, mutable); - if (vport) - return vport; - } - return NULL; - } + bool is_multicast = ipv4_is_multicast(saddr); lookup.saddr = saddr; lookup.daddr = daddr; @@ -315,7 +296,7 @@ struct vport *tnl_find_port(__be32 saddr, __be32 daddr, __be64 key, /* First try for exact match on in_key. */ lookup.in_key = key; lookup.tunnel_type = tunnel_type | TNL_T_KEY_EXACT; - if (key_local_remote_ports) { + if (!is_multicast && key_local_remote_ports) { vport = port_table_lookup(&lookup, mutable); if (vport) return vport; @@ -332,7 +313,7 @@ struct vport *tnl_find_port(__be32 saddr, __be32 daddr, __be64 key, /* Then try matches that wildcard in_key. */ lookup.in_key = 0; lookup.tunnel_type = tunnel_type | TNL_T_KEY_MATCH; - if (local_remote_ports) { + if (!is_multicast && local_remote_ports) { vport = port_table_lookup(&lookup, mutable); if (vport) return vport; @@ -344,6 +325,25 @@ struct vport *tnl_find_port(__be32 saddr, __be32 daddr, __be64 key, return vport; } + if (is_multicast) { + lookup.saddr = 0; + lookup.daddr = saddr; + if (key_remote_ports) { + lookup.tunnel_type = tunnel_type | TNL_T_KEY_EXACT; + lookup.in_key = key; + vport = port_table_lookup(&lookup, mutable); + if (vport) + return vport; + } + if (remote_ports) { + lookup.tunnel_type = tunnel_type | TNL_T_KEY_MATCH; + lookup.in_key = 0; + vport = port_table_lookup(&lookup, mutable); + if (vport) + return vport; + } + } + return NULL; }