if (flow->tp_dst == htons(0)
&& (flow->tp_src == htons(ND_NEIGHBOR_SOLICIT)
|| flow->tp_src == htons(ND_NEIGHBOR_ADVERT))
- && (!export_mask || (data->tp_src == htons(0xffff)
- && data->tp_dst == htons(0xffff)))) {
+ /* Even though 'tp_src' and 'tp_dst' are 16 bits wide, ICMP
+ * type and code are 8 bits wide. Therefore, an exact match
+ * looks like htons(0xff), not htons(0xffff). See
+ * xlate_wc_finish() for details. */
+ && (!export_mask || (data->tp_src == htons(0xff)
+ && data->tp_dst == htons(0xff)))) {
struct ovs_key_nd *nd_key;
flow->arp_sha = nd_key->nd_sll;
flow->arp_tha = nd_key->nd_tll;
if (is_mask) {
+ /* Even though 'tp_src' and 'tp_dst' are 16 bits wide,
+ * ICMP type and code are 8 bits wide. Therefore, an
+ * exact match looks like htons(0xff), not
+ * htons(0xffff). See xlate_wc_finish() for details.
+ * */
if (!is_all_zeros(nd_key, sizeof *nd_key) &&
- (flow->tp_src != htons(0xffff) ||
- flow->tp_dst != htons(0xffff))) {
+ (flow->tp_src != htons(0xff) ||
+ flow->tp_dst != htons(0xff))) {
return ODP_FIT_ERROR;
} else {
expected_attrs |= UINT64_C(1) << OVS_KEY_ATTR_ND;