common/sfc_efx/base: apply mask to value on match field set

An application may submit all-zeros masks for a given field
to be used in two given specifications and, in the meantime,
use different unmasked values. Later on, when compared, the
two specifications will prove unequal, and, if the rules in
question are outer, the client driver will have to allocate
a separate rule for the second specification. Provided that
all other match criteria are the same, the HW will deem the
two outer rules being duplicates, which is in fact the case.

Apply masks to values in efx_mae_match_spec_field_set() API
to fix the issue and avoid duplicate outer rule allocations.

Fixes: 370ed675a952 ("common/sfc_efx/base: support setting PPORT in match spec")
Cc: stable@dpdk.org

Reported-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
Signed-off-by: Ivan Malov <ivan.malov@oktetlabs.ru>
Reviewed-by: Andrew Rybchenko <andrew.rybchenko@oktetlabs.ru>
Reviewed-by: Andy Moreton <amoreton@xilinx.com>
This commit is contained in:
Ivan Malov 2021-01-18 01:21:11 +03:00 committed by Ferruh Yigit
parent 24e1a5e39d
commit f80487b9c7

View File

@ -707,12 +707,32 @@ efx_mae_match_spec_field_set(
}
if (descp->emmd_endianness == EFX_MAE_FIELD_BE) {
unsigned int i;
/*
* The mask/value are in network (big endian) order.
* The MCDI request field is also big endian.
*/
memcpy(mvp + descp->emmd_value_offset, value, value_size);
memcpy(mvp + descp->emmd_mask_offset, mask, mask_size);
EFSYS_ASSERT3U(value_size, ==, mask_size);
for (i = 0; i < value_size; ++i) {
uint8_t *v_bytep = mvp + descp->emmd_value_offset + i;
uint8_t *m_bytep = mvp + descp->emmd_mask_offset + i;
/*
* Apply the mask (which may be all-zeros) to the value.
*
* If this API is provided with some value to set for a
* given field in one specification and with some other
* value to set for this field in another specification,
* then, if the two masks are all-zeros, the field will
* avoid being counted as a mismatch when comparing the
* specifications using efx_mae_match_specs_equal() API.
*/
*v_bytep = value[i] & mask[i];
*m_bytep = mask[i];
}
} else {
efx_dword_t dword;