net/sfc: support VLAN in flow API filters
Exact match of VLAN ID bits is supported only and required in VLAN item. Mask to match VLAN ID bits only is required, default mask to match entire TCI is not supported. Signed-off-by: Roman Zhukov <roman.zhukov@oktetlabs.ru> Signed-off-by: Andrew Rybchenko <arybchenko@solarflare.com> Reviewed-by: Andrew Lee <alee@solarflare.com>
This commit is contained in:
parent
a9825ccf5b
commit
894080975e
@ -129,6 +129,8 @@ Supported pattern items:
|
||||
|
||||
- ETH (exact match of source/destination addresses, EtherType)
|
||||
|
||||
- VLAN (exact match of VID, double-tagging is supported)
|
||||
|
||||
Supported actions:
|
||||
|
||||
- VOID
|
||||
|
@ -70,6 +70,7 @@ struct sfc_flow_item {
|
||||
|
||||
static sfc_flow_item_parse sfc_flow_parse_void;
|
||||
static sfc_flow_item_parse sfc_flow_parse_eth;
|
||||
static sfc_flow_item_parse sfc_flow_parse_vlan;
|
||||
|
||||
static boolean_t
|
||||
sfc_flow_is_zero(const uint8_t *buf, unsigned int size)
|
||||
@ -269,6 +270,73 @@ sfc_flow_parse_eth(const struct rte_flow_item *item,
|
||||
return -rte_errno;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert VLAN item to EFX filter specification.
|
||||
*
|
||||
* @param item[in]
|
||||
* Item specification. Only VID field is supported.
|
||||
* The mask can not be NULL. Ranging is not supported.
|
||||
* @param efx_spec[in, out]
|
||||
* EFX filter specification to update.
|
||||
* @param[out] error
|
||||
* Perform verbose error reporting if not NULL.
|
||||
*/
|
||||
static int
|
||||
sfc_flow_parse_vlan(const struct rte_flow_item *item,
|
||||
efx_filter_spec_t *efx_spec,
|
||||
struct rte_flow_error *error)
|
||||
{
|
||||
int rc;
|
||||
uint16_t vid;
|
||||
const struct rte_flow_item_vlan *spec = NULL;
|
||||
const struct rte_flow_item_vlan *mask = NULL;
|
||||
const struct rte_flow_item_vlan supp_mask = {
|
||||
.tci = rte_cpu_to_be_16(ETH_VLAN_ID_MAX),
|
||||
};
|
||||
|
||||
rc = sfc_flow_parse_init(item,
|
||||
(const void **)&spec,
|
||||
(const void **)&mask,
|
||||
&supp_mask,
|
||||
NULL,
|
||||
sizeof(struct rte_flow_item_vlan),
|
||||
error);
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
|
||||
/*
|
||||
* VID is in big-endian byte order in item and
|
||||
* in little-endian in efx_spec, so byte swap is used.
|
||||
* If two VLAN items are included, the first matches
|
||||
* the outer tag and the next matches the inner tag.
|
||||
*/
|
||||
if (mask->tci == supp_mask.tci) {
|
||||
vid = rte_bswap16(spec->tci);
|
||||
|
||||
if (!(efx_spec->efs_match_flags &
|
||||
EFX_FILTER_MATCH_OUTER_VID)) {
|
||||
efx_spec->efs_match_flags |= EFX_FILTER_MATCH_OUTER_VID;
|
||||
efx_spec->efs_outer_vid = vid;
|
||||
} else if (!(efx_spec->efs_match_flags &
|
||||
EFX_FILTER_MATCH_INNER_VID)) {
|
||||
efx_spec->efs_match_flags |= EFX_FILTER_MATCH_INNER_VID;
|
||||
efx_spec->efs_inner_vid = vid;
|
||||
} else {
|
||||
rte_flow_error_set(error, EINVAL,
|
||||
RTE_FLOW_ERROR_TYPE_ITEM, item,
|
||||
"More than two VLAN items");
|
||||
return -rte_errno;
|
||||
}
|
||||
} else {
|
||||
rte_flow_error_set(error, EINVAL,
|
||||
RTE_FLOW_ERROR_TYPE_ITEM, item,
|
||||
"VLAN ID in TCI match is required");
|
||||
return -rte_errno;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct sfc_flow_item sfc_flow_items[] = {
|
||||
{
|
||||
.type = RTE_FLOW_ITEM_TYPE_VOID,
|
||||
@ -282,6 +350,12 @@ static const struct sfc_flow_item sfc_flow_items[] = {
|
||||
.layer = SFC_FLOW_ITEM_L2,
|
||||
.parse = sfc_flow_parse_eth,
|
||||
},
|
||||
{
|
||||
.type = RTE_FLOW_ITEM_TYPE_VLAN,
|
||||
.prev_layer = SFC_FLOW_ITEM_L2,
|
||||
.layer = SFC_FLOW_ITEM_L2,
|
||||
.parse = sfc_flow_parse_vlan,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user