Before this patch, when a tunnel is configured with key=flow, CFM didn't verify that incoming packets had the appropriate key of zero. This could cause the CFM module to consume packets which weren't actually intended for it.
Bug #13542. Signed-off-by: Ethan Jackson <[email protected]> --- lib/cfm.c | 5 ++++- lib/cfm.h | 2 ++ vswitchd/bridge.c | 12 ++++++++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/lib/cfm.c b/lib/cfm.c index fc999ab..b71c242 100644 --- a/lib/cfm.c +++ b/lib/cfm.c @@ -86,6 +86,7 @@ struct cfm { struct hmap_node hmap_node; /* Node in all_cfms list. */ uint64_t mpid; + bool check_tnl_key; /* Verify the tunnel key of inbound packets? */ bool extended; /* Extended mode. */ bool booted; /* A full fault interval has occured. */ enum cfm_fault_reason fault; /* Connectivity fault status. */ @@ -505,6 +506,7 @@ cfm_configure(struct cfm *cfm, const struct cfm_settings *s) } cfm->mpid = s->mpid; + cfm->check_tnl_key = s->check_tnl_key; cfm->extended = s->extended; cfm->opup = s->opup; interval = ms_to_ccm_interval(s->interval); @@ -533,7 +535,8 @@ bool cfm_should_process_flow(const struct cfm *cfm, const struct flow *flow) { return (ntohs(flow->dl_type) == ETH_TYPE_CFM - && eth_addr_equals(flow->dl_dst, cfm_ccm_addr(cfm))); + && eth_addr_equals(flow->dl_dst, cfm_ccm_addr(cfm)) + && (!cfm->check_tnl_key || flow->tunnel.tun_id == htonll(0))); } /* Updates internal statistics relevant to packet 'p'. Should be called on diff --git a/lib/cfm.h b/lib/cfm.h index de4c299..8bb6778 100644 --- a/lib/cfm.h +++ b/lib/cfm.h @@ -57,6 +57,8 @@ struct cfm_settings { uint16_t ccm_vlan; /* CCM Vlan tag. Zero if none. CFM_RANDOM_VLAN if random. */ uint8_t ccm_pcp; /* CCM Priority. Zero if none. */ + + bool check_tnl_key; /* Verify inbound packet key? */ }; void cfm_init(void); diff --git a/vswitchd/bridge.c b/vswitchd/bridge.c index d161c4c..5908e10 100644 --- a/vswitchd/bridge.c +++ b/vswitchd/bridge.c @@ -3312,12 +3312,24 @@ iface_configure_cfm(struct iface *iface) const char *opstate_str; const char *cfm_ccm_vlan; struct cfm_settings s; + struct smap netdev_args; if (!cfg->n_cfm_mpid) { ofproto_port_clear_cfm(iface->port->bridge->ofproto, iface->ofp_port); return; } + s.check_tnl_key = false; + smap_init(&netdev_args); + if (!netdev_get_config(iface->netdev, &netdev_args)) { + const char *key = smap_get(&netdev_args, "key"); + const char *in_key = smap_get(&netdev_args, "in_key"); + + s.check_tnl_key = (key && !strcmp(key, "flow")) + || (in_key && !strcmp(in_key, "flow")); + } + smap_destroy(&netdev_args); + s.mpid = *cfg->cfm_mpid; s.interval = smap_get_int(&iface->cfg->other_config, "cfm_interval", 0); cfm_ccm_vlan = smap_get(&iface->cfg->other_config, "cfm_ccm_vlan"); -- 1.7.12 _______________________________________________ dev mailing list [email protected] http://openvswitch.org/mailman/listinfo/dev
