Dear all,
I have been using the new API rte_flow to program filtering on an X540 (ixgbe)
NIC. My goal is to send packets from different VLANs to different queues
(filtering which should be supported by flow director as far as I understand).
I enclosed the setup code at the bottom of this email. However, the code in
ixgbe rejects the request I formulated. I looked at the rte_flow related code
in ixgbe and I found some weird checkings in function
ixgbe_parse_fdir_filter_normal. The code verifies that vlan_spec->tpid ==
ETHER_TYPE_VLAN, which should never happen on real packets, as it is
eth_spec->type which has this value in typical setups. The same comment applies
to the mask, only eth_mask->tpid should be required to be 0xffff. Overall,
unless I misunderstood the rte_flow API, the checks should be done on
eth_spec/eth_mask rather than vlan_spec/vlan_mask.
I also have a side comment which might be more related to the general rte_flow
API than to the specific implementation in ixgbe. The rte_flow_error returned
is not very useful for it does return the error of the last tried filter-type
(L2 tunnel in ixgbe), and not the error of the filter-type that my setup should
use (flow director). As NICs can have several filter-types, It would be be
useful to the user if rte_flow_validate/create could return the errors for all
filter types tried although that would require to change the rte_flow API and
returning an array of rte_flow_error and not a single struct.
Excerpt of the code that reject my filtering rule:
if (vlan_spec->tpid != rte_cpu_to_be_16(ETHER_TYPE_VLAN)) {
memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ITEM,
item, "Not supported by fdir filter");
return -rte_errno;
}
rule->ixgbe_fdir.formatted.vlan_id = vlan_spec->tci;
if (vlan_mask->tpid != (uint16_t)~0U) {
memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ITEM,
item, "Not supported by fdir filter");
return -rte_errno;
}
For reference, here is the setup code I use
struct rte_flow_attr attr;
attr.group = 0;
attr.priority = 0;
attr.egress = 0;
attr.ingress = 1;
struct rte_flow_item_eth eth_mask;
struct rte_flow_item_eth eth_spec;
struct rte_flow_item_vlan vlan_mask;
struct rte_flow_item_vlan vlan_spec;
struct rte_flow_action_queue queue;
struct rte_flow_item items[3];
items[0].type = RTE_FLOW_ITEM_TYPE_ETH;
items[1].type = RTE_FLOW_ITEM_TYPE_VLAN;
items[0].last = NULL;
items[0].spec = ð_spec;
items[0].mask = ð_mask;
items[1].last = NULL;
items[1].spec = &vlan_spec;
items[1].mask = &vlan_mask;
items[2].type = RTE_FLOW_ITEM_TYPE_END;
eth_mask.src = ETH(00,00,00,00,00,00);
eth_mask.dst = ETH(ff,ff,ff,ff,ff,ff);
eth_mask.type = 0xffff;
eth_spec.src = ETH(00,00,00,00,00,00);
eth_spec.dst = *dst;
eth_spec.type = rte_cpu_to_be_16(ETHER_TYPE_VLAN);
vlan_spec.tci = vlan_be;
vlan_spec.tpid = 0;
vlan_mask.tci = rte_cpu_to_be_16(0x0fff);
vlan_mask.tpid = 0;
struct rte_flow_action actions[2];
actions[0].type = RTE_FLOW_ACTION_TYPE_QUEUE;
actions[0].conf = &queue;
actions[1].type = RTE_FLOW_ACTION_TYPE_END;
actions[1].conf = NULL;
queue.index = queue_id;
struct rte_flow_error error;
printf("%p %p %p %p %p\n", &items[0], &items[1], &items[2],
&actions[0], &actions[1]);
if(rte_flow_validate(port_id, &attr, items, actions, &error) < 0){
...
Best regards,
Nicolas Le Scouarnec
This e-mail and any files transmitted with it are confidential and are
intended solely for the use of the individual or entity to whom they are
addressed. If you are not the intended recipient or the person responsible
for delivering this communication to the intended recipient, please be advised
that you have received this communication in error and that any use,
dissemination, printing or copying of this communication (including any
attachments) is strictly prohibited.