return header;
}
+/* Given NXM/OXM value 'value' and mask 'mask', each 'width' bytes long,
+ * checks for any 1-bit in the value where there is a 0-bit in the mask. If it
+ * finds one, logs a warning. */
+static void
+check_mask_consistency(const uint8_t *p, const struct mf_field *mf)
+{
+ unsigned int width = mf->n_bytes;
+ const uint8_t *value = p + 4;
+ const uint8_t *mask = p + 4 + width;
+ unsigned int i;
+
+ for (i = 0; i < width; i++) {
+ if (value[i] & ~mask[i]) {
+ if (!VLOG_DROP_WARN(&rl)) {
+ char *s = nx_match_to_string(p, width * 2 + 4);
+ VLOG_WARN_RL(&rl, "NXM/OXM entry %s has 1-bits in value for "
+ "bits wildcarded by the mask. (Future versions "
+ "of OVS may report this as an OpenFlow error.)",
+ s);
+ break;
+ }
+ }
+ }
+}
+
static enum ofperr
nx_pull_raw(const uint8_t *p, unsigned int match_len, bool strict,
struct match *match, ovs_be64 *cookie, ovs_be64 *cookie_mask)
{
uint32_t header;
- assert((cookie != NULL) == (cookie_mask != NULL));
+ ovs_assert((cookie != NULL) == (cookie_mask != NULL));
match_init_catchall(match);
if (cookie) {
error = OFPERR_OFPBMC_BAD_MASK;
} else {
error = 0;
+ check_mask_consistency(p, mf);
mf_set(mf, &value, &mask, match);
}
}
int match_len;
int i;
- BUILD_ASSERT_DECL(FLOW_WC_SEQ == 17);
+ BUILD_ASSERT_DECL(FLOW_WC_SEQ == 18);
/* Metadata. */
if (match->wc.masks.in_port) {
flow->arp_tha, match->wc.masks.arp_tha);
}
}
- } else if (flow->dl_type == htons(ETH_TYPE_ARP)) {
+ } else if (flow->dl_type == htons(ETH_TYPE_ARP) ||
+ flow->dl_type == htons(ETH_TYPE_RARP)) {
/* ARP. */
if (match->wc.masks.nw_proto) {
nxm_put_16(b, oxm ? OXM_OF_ARP_OP : NXM_OF_ARP_OP,
}
/* Tunnel ID. */
- nxm_put_64m(b, NXM_NX_TUN_ID, flow->tun_id, match->wc.masks.tun_id);
+ nxm_put_64m(b, oxm ? OXM_OF_TUNNEL_ID : NXM_NX_TUN_ID,
+ flow->tunnel.tun_id, match->wc.masks.tunnel.tun_id);
/* Registers. */
for (i = 0; i < FLOW_N_REGS; i++) {
const struct mf_field *mf = load->dst.field;
union mf_value value;
- assert(load->ofpact.compat == OFPUTIL_OFPAT12_SET_FIELD);
+ ovs_assert(load->ofpact.compat == OFPUTIL_OFPAT12_SET_FIELD);
ds_put_format(s, "set_field:");
memset(&value, 0, sizeof value);
bitwise_copy(&load->subvalue, sizeof load->subvalue, 0,
struct ofp_header *oh = (struct ofp_header *)openflow->l2;
switch(oh->version) {
+ case OFP13_VERSION:
case OFP12_VERSION:
set_field_to_ofast(load, openflow);
break;