static inline bool incompatible_128(uint8_t *a, uint8_t *b, uint8_t *am, uint8_t *bm) { return (incompatible_64(a, b, am, bm) || incompatible_64(a+8, b+8, am+8, bm+8)); }
/* Two flow matches overlap if there exists a packet which both match structures match on. * Conversely, two flow matches do not overlap if they share at least one match field with * incompatible value/mask fields that can't match any packet. */ bool match_std_overlap(struct ofl_match *a, struct ofl_match *b, struct ofl_exp *exp) { uint64_t all_mask[2] = {~0L, ~0L}; struct ofl_match_tlv *f_a; struct ofl_match_tlv *f_b; int header, header_m; int field_len; uint8_t *val_a, *mask_a; uint8_t *val_b, *mask_b; /* Loop through the match fields in flow entry a */ HMAP_FOR_EACH(f_a, struct ofl_match_tlv, hmap_node, &a->match_fields) { val_a = f_a->value; switch (OXM_VENDOR(f_a->header)) { case (OFPXMC_OPENFLOW_BASIC): field_len = OXM_LENGTH(f_a->header); if (OXM_HASMASK(f_a->header)) { field_len /= 2; header = (f_a->header & 0xfffffe00) | field_len; header_m = f_a->header; mask_a = f_a->value + field_len; } else { header = f_a->header; header_m = (f_a->header & 0xfffffe00) | 0x100 | (field_len << 1); /* Set a dummy mask with all bits set to 0 (valid) */ mask_a = (uint8_t *) all_mask; } break; case (OFPXMC_EXPERIMENTER): if (exp == NULL || exp->field == NULL || exp->field->overlap_a == NULL) { VLOG_WARN(LOG_MODULE,"Received match is experimental, but no callback was given."); ofl_error(OFPET_BAD_MATCH, OFPBMC_BAD_TYPE); } exp->field->overlap_a(f_a, &field_len, &val_a, &mask_a, &header, &header_m, all_mask); break; default: break; } /*switch class*/ /* Check presence of corresponding match field in flow entry b * Need to check for both masked and non-masked field */ f_b = oxm_match_lookup(header, b); if (!f_b) f_b = oxm_match_lookup(header_m, b); if (f_b) { switch (OXM_VENDOR(f_b->header)) { case (OFPXMC_OPENFLOW_BASIC): val_b = f_b->value; if (OXM_HASMASK(f_b->header)) { mask_b = f_b->value + field_len; } else { /* Set a dummy mask with all bits set to 0 (valid) */ mask_b = (uint8_t *) all_mask; } break; case (OFPXMC_EXPERIMENTER): if (exp == NULL || exp->field == NULL || exp->field->overlap_b == NULL) { VLOG_WARN(LOG_MODULE,"Received match is experimental, but no callback was given."); ofl_error(OFPET_BAD_MATCH, OFPBMC_BAD_TYPE); } exp->field->overlap_b(f_b, &field_len, &val_b, &mask_b, all_mask); break; default: break; } /*switch class*/ switch (field_len) { case 1: if (incompatible_8(val_a, val_b, mask_a, mask_b)) { return false; } break; case 2: if (incompatible_16(val_a, val_b, mask_a, mask_b)) { return false; } break; case 4: if (incompatible_32(val_a, val_b, mask_a, mask_b)) { return false; } break; case 6: if (incompatible_48(val_a, val_b, mask_a, mask_b)) { return false; } break; case 8: if (incompatible_64(val_a, val_b, mask_a, mask_b)) { return false; } break; case 16: if (incompatible_128(val_a, val_b, mask_a, mask_b)) { return false; } break; default: /* Should never happen */ break; } /* switch (field_len) */ } /* if (f_b) */ } /* HMAP_FOR_EACH */ /* If we get here, none of the common match fields in a and b were found incompatible. * The flow entries overlap */ return true; }
bool match_std_overlap(struct ofl_match *a, struct ofl_match *b) { uint64_t all_mask[2] = {0, 0}; struct ofl_match_tlv *f_a; struct ofl_match_tlv *f_b; int header, header_m; int field_len; uint8_t *val_a, *mask_a; uint8_t *val_b, *mask_b; /* Loop through the match fields in flow entry a */ HMAP_FOR_EACH(f_a, struct ofl_match_tlv, hmap_node, &a->match_fields) { field_len = OXM_LENGTH(f_a->header); val_a = f_a->value; if (OXM_HASMASK(f_a->header)) { field_len /= 2; header = (f_a->header & 0xfffffe00) | field_len; header_m = f_a->header; mask_a = f_a->value + field_len; } else { header = f_a->header; header_m = (f_a->header & 0xfffffe00) | 0x100 | (field_len << 1); /* Set a dummy mask with all bits set to 0 (valid) */ mask_a = (uint8_t *) all_mask; } /* Check presence of corresponding match field in flow entry b * Need to check for both masked and non-masked field */ f_b = oxm_match_lookup(header, b); if (!f_b) f_b = oxm_match_lookup(header_m, b); if (f_b) { val_b = f_b->value; if (OXM_HASMASK(f_b->header)) { mask_b = f_b->value + field_len; } else { /* Set a dummy mask with all bits set to 0 (valid) */ mask_b = (uint8_t *) all_mask; } switch (field_len) { case 1: if (incompatible_8(val_a, val_b, mask_a, mask_b)) { return false; } break; case 2: if (incompatible_16(val_a, val_b, mask_a, mask_b)) { return false; } break; case 4: if (incompatible_32(val_a, val_b, mask_a, mask_b)) { return false; } break; case 6: if (incompatible_48(val_a, val_b, mask_a, mask_b)) { return false; } break; case 8: if (incompatible_64(val_a, val_b, mask_a, mask_b)) { return false; } break; case 16: if (incompatible_128(val_a, val_b, mask_a, mask_b)) { return false; } break; default: /* Should never happen */ break; } /* switch (field_len) */ } /* if (f_b) */ } /* HMAP_FOR_EACH */ /* If we get here, none of the common match fields in a and b were found incompatible. * The flow entries overlap */ return true; }