common/sfc_efx/base: apply mask to value on match field set
authorIvan Malov <ivan.malov@oktetlabs.ru>
Sun, 17 Jan 2021 22:21:11 +0000 (01:21 +0300)
committerFerruh Yigit <ferruh.yigit@intel.com>
Tue, 19 Jan 2021 02:30:32 +0000 (03:30 +0100)
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>
drivers/common/sfc_efx/base/efx_mae.c

index cc5d8cf..338a001 100644 (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;