X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=ofproto%2Fofproto-dpif-xlate.c;h=ffcfdf9be6ff1973ae3d3276aa8e9fa8b668e654;hb=c56fac1b678101b189e16f0462556c992feeffdc;hp=a880376fbb33ae0643156e73a86dfd4cca3ea9e3;hpb=276e2864c517a13f9a3ba33086b091743096d30c;p=sliver-openvswitch.git diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index a880376fb..ffcfdf9be 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -2911,6 +2911,7 @@ xlate_actions__(struct xlate_in *xin, struct xlate_out *xout) struct xlate_ctx ctx; size_t ofpacts_len; bool tnl_may_send; + bool is_icmp; COVERAGE_INC(xlate_actions); @@ -2965,6 +2966,7 @@ xlate_actions__(struct xlate_in *xin, struct xlate_out *xout) if (is_ip_any(flow)) { wc->masks.nw_frag |= FLOW_NW_FRAG_MASK; } + is_icmp = is_icmpv4(flow) || is_icmpv6(flow); tnl_may_send = tnl_xlate_init(&ctx.base_flow, flow, wc); if (ctx.xbridge->netflow) { @@ -3124,6 +3126,21 @@ xlate_actions__(struct xlate_in *xin, struct xlate_out *xout) * use non-header fields as part of the cache. */ flow_wildcards_clear_non_packet_fields(wc); + /* ICMPv4 and ICMPv6 have 8-bit "type" and "code" fields. struct flow uses + * the low 8 bits of the 16-bit tp_src and tp_dst members to represent + * these fields. The datapath interface, on the other hand, represents + * them with just 8 bits each. This means that if the high 8 bits of the + * masks for these fields somehow become set, then they will get chopped + * off by a round trip through the datapath, and revalidation will spot + * that as an inconsistency and delete the flow. Avoid the problem here by + * making sure that only the low 8 bits of either field can be unwildcarded + * for ICMP. + */ + if (is_icmp) { + wc->masks.tp_src &= htons(UINT8_MAX); + wc->masks.tp_dst &= htons(UINT8_MAX); + } + out: rule_actions_unref(actions); rule_dpif_unref(rule);