net/ixgbe: enable flex bytes for generic flow API

Add fdir flex byte support for rte_flow APIs.

Signed-off-by: Qi Zhang <qi.z.zhang@intel.com>
Acked-by: Wenzhuo Lu <wenzhuo.lu@intel.com>
This commit is contained in:
Qi Zhang 2017-06-01 13:36:45 -04:00 committed by Ferruh Yigit
parent 8d702249d5
commit f35fec63dd
3 changed files with 167 additions and 4 deletions

View File

@ -189,6 +189,7 @@ struct ixgbe_fdir_rule {
uint32_t fdirflags; /* drop or forward */
uint32_t soft_id; /* an unique value for this rule */
uint8_t queue; /* assigned rx queue */
uint8_t flex_bytes_offset;
};
struct ixgbe_hw_fdir_info {
@ -621,6 +622,8 @@ void ixgbe_filterlist_flush(void);
*/
int ixgbe_fdir_configure(struct rte_eth_dev *dev);
int ixgbe_fdir_set_input_mask(struct rte_eth_dev *dev);
int ixgbe_fdir_set_flexbytes_offset(struct rte_eth_dev *dev,
uint16_t offset);
int ixgbe_fdir_filter_program(struct rte_eth_dev *dev,
struct ixgbe_fdir_rule *rule,
bool del, bool update);

View File

@ -302,7 +302,7 @@ fdir_set_input_mask_82599(struct rte_eth_dev *dev)
* mask VM pool and DIPv6 since there are currently not supported
* mask FLEX byte, it will be set in flex_conf
*/
uint32_t fdirm = IXGBE_FDIRM_POOL | IXGBE_FDIRM_DIPv6 | IXGBE_FDIRM_FLEX;
uint32_t fdirm = IXGBE_FDIRM_POOL | IXGBE_FDIRM_DIPv6;
uint32_t fdirtcpm; /* TCP source and destination port masks. */
uint32_t fdiripv6m; /* IPv6 source and destination masks. */
volatile uint32_t *reg;
@ -333,6 +333,10 @@ fdir_set_input_mask_82599(struct rte_eth_dev *dev)
return -EINVAL;
}
/* flex byte mask */
if (info->mask.flex_bytes_mask == 0)
fdirm |= IXGBE_FDIRM_FLEX;
IXGBE_WRITE_REG(hw, IXGBE_FDIRM, fdirm);
/* store the TCP/UDP port masks, bit reversed from port layout */
@ -533,6 +537,31 @@ ixgbe_fdir_set_input_mask(struct rte_eth_dev *dev)
return -ENOTSUP;
}
int
ixgbe_fdir_set_flexbytes_offset(struct rte_eth_dev *dev,
uint16_t offset)
{
struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
uint32_t fdirctrl;
int i;
fdirctrl = IXGBE_READ_REG(hw, IXGBE_FDIRCTRL);
fdirctrl &= ~IXGBE_FDIRCTRL_FLEX_MASK;
fdirctrl |= ((offset >> 1) /* convert to word offset */
<< IXGBE_FDIRCTRL_FLEX_SHIFT);
IXGBE_WRITE_REG(hw, IXGBE_FDIRCTRL, fdirctrl);
IXGBE_WRITE_FLUSH(hw);
for (i = 0; i < IXGBE_FDIR_INIT_DONE_POLL; i++) {
if (IXGBE_READ_REG(hw, IXGBE_FDIRCTRL) &
IXGBE_FDIRCTRL_INIT_DONE)
break;
msec_delay(1);
}
return 0;
}
static int
fdir_set_input_mask(struct rte_eth_dev *dev,
const struct rte_eth_fdir_masks *input_mask)

View File

@ -78,6 +78,7 @@
#define IXGBE_MIN_N_TUPLE_PRIO 1
#define IXGBE_MAX_N_TUPLE_PRIO 7
#define IXGBE_MAX_FLX_SOURCE_OFF 62
#define NEXT_ITEM_OF_PATTERN(item, pattern, index)\
do { \
item = pattern + index;\
@ -1316,7 +1317,8 @@ ixgbe_parse_fdir_act_attr(const struct rte_flow_attr *attr,
* UDP/TCP/SCTP PATTERN:
* The first not void item can be ETH or IPV4.
* The second not void item must be IPV4 if the first one is ETH.
* The third not void item must be UDP or TCP or SCTP.
* The next not void item could be UDP or TCP or SCTP (optional)
* The next not void item could be RAW (for flexbyte, optional)
* The next not void item must be END.
* MAC VLAN PATTERN:
* The first not void item must be ETH.
@ -1334,6 +1336,14 @@ ixgbe_parse_fdir_act_attr(const struct rte_flow_attr *attr,
* dst_addr 192.167.3.50 0xFFFFFFFF
* UDP/TCP/SCTP src_port 80 0xFFFF
* dst_port 80 0xFFFF
* FLEX relative 0 0x1
* search 0 0x1
* reserved 0 0
* offset 12 0xFFFFFFFF
* limit 0 0xFFFF
* length 2 0xFFFF
* pattern[0] 0x86 0xFF
* pattern[1] 0xDD 0xFF
* END
* MAC VLAN pattern example:
* ITEM Spec Mask
@ -1365,6 +1375,8 @@ ixgbe_parse_fdir_filter_normal(const struct rte_flow_attr *attr,
const struct rte_flow_item_sctp *sctp_mask;
const struct rte_flow_item_vlan *vlan_spec;
const struct rte_flow_item_vlan *vlan_mask;
const struct rte_flow_item_raw *raw_mask;
const struct rte_flow_item_raw *raw_spec;
uint32_t index, j;
@ -1396,6 +1408,7 @@ ixgbe_parse_fdir_filter_normal(const struct rte_flow_attr *attr,
memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
memset(&rule->mask, 0xFF, sizeof(struct ixgbe_hw_fdir_mask));
rule->mask.vlan_tci_mask = 0;
rule->mask.flex_bytes_mask = 0;
/* parse pattern */
index = 0;
@ -1621,7 +1634,8 @@ ixgbe_parse_fdir_filter_normal(const struct rte_flow_attr *attr,
if (item->type != RTE_FLOW_ITEM_TYPE_TCP &&
item->type != RTE_FLOW_ITEM_TYPE_UDP &&
item->type != RTE_FLOW_ITEM_TYPE_SCTP &&
item->type != RTE_FLOW_ITEM_TYPE_END) {
item->type != RTE_FLOW_ITEM_TYPE_END &&
item->type != RTE_FLOW_ITEM_TYPE_RAW) {
memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ITEM,
@ -1682,6 +1696,18 @@ ixgbe_parse_fdir_filter_normal(const struct rte_flow_attr *attr,
rule->ixgbe_fdir.formatted.dst_port =
tcp_spec->hdr.dst_port;
}
index++;
NEXT_ITEM_OF_PATTERN(item, pattern, index);
if (item->type != RTE_FLOW_ITEM_TYPE_RAW &&
item->type != RTE_FLOW_ITEM_TYPE_END) {
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;
}
}
/* Get the UDP info */
@ -1731,6 +1757,18 @@ ixgbe_parse_fdir_filter_normal(const struct rte_flow_attr *attr,
rule->ixgbe_fdir.formatted.dst_port =
udp_spec->hdr.dst_port;
}
index++;
NEXT_ITEM_OF_PATTERN(item, pattern, index);
if (item->type != RTE_FLOW_ITEM_TYPE_RAW &&
item->type != RTE_FLOW_ITEM_TYPE_END) {
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;
}
}
/* Get the SCTP info */
@ -1782,6 +1820,88 @@ ixgbe_parse_fdir_filter_normal(const struct rte_flow_attr *attr,
rule->ixgbe_fdir.formatted.dst_port =
sctp_spec->hdr.dst_port;
}
index++;
NEXT_ITEM_OF_PATTERN(item, pattern, index);
if (item->type != RTE_FLOW_ITEM_TYPE_RAW &&
item->type != RTE_FLOW_ITEM_TYPE_END) {
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;
}
}
/* Get the flex byte info */
if (item->type == RTE_FLOW_ITEM_TYPE_RAW) {
/* Not supported last point for range*/
if (item->last) {
rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
item, "Not supported last point for range");
return -rte_errno;
}
/* mask should not be null */
if (!item->mask || !item->spec) {
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;
}
raw_mask = (const struct rte_flow_item_raw *)item->mask;
/* check mask */
if (raw_mask->relative != 0x1 ||
raw_mask->search != 0x1 ||
raw_mask->reserved != 0x0 ||
(uint32_t)raw_mask->offset != 0xffffffff ||
raw_mask->limit != 0xffff ||
raw_mask->length != 0xffff) {
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;
}
raw_spec = (const struct rte_flow_item_raw *)item->spec;
/* check spec */
if (raw_spec->relative != 0 ||
raw_spec->search != 0 ||
raw_spec->reserved != 0 ||
raw_spec->offset > IXGBE_MAX_FLX_SOURCE_OFF ||
raw_spec->offset % 2 ||
raw_spec->limit != 0 ||
raw_spec->length != 2 ||
/* pattern can't be 0xffff */
(raw_spec->pattern[0] == 0xff &&
raw_spec->pattern[1] == 0xff)) {
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;
}
/* check pattern mask */
if (raw_mask->pattern[0] != 0xff ||
raw_mask->pattern[1] != 0xff) {
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->mask.flex_bytes_mask = 0xffff;
rule->ixgbe_fdir.formatted.flex_bytes =
(((uint16_t)raw_spec->pattern[1]) << 8) |
raw_spec->pattern[0];
rule->flex_bytes_offset = raw_spec->offset;
}
if (item->type != RTE_FLOW_ITEM_TYPE_END) {
@ -1919,7 +2039,7 @@ ixgbe_parse_fdir_filter_tunnel(const struct rte_flow_attr *attr,
item, "Not supported by fdir filter");
return -rte_errno;
}
/*Not supported last point for range*/
/* Not supported last point for range*/
if (item->last) {
rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
@ -2497,6 +2617,13 @@ ixgbe_flow_create(struct rte_eth_dev *dev,
rte_memcpy(&fdir_info->mask,
&fdir_rule.mask,
sizeof(struct ixgbe_hw_fdir_mask));
fdir_info->flex_bytes_offset =
fdir_rule.flex_bytes_offset;
if (fdir_rule.mask.flex_bytes_mask)
ixgbe_fdir_set_flexbytes_offset(dev,
fdir_rule.flex_bytes_offset);
ret = ixgbe_fdir_set_input_mask(dev);
if (ret)
goto out;
@ -2512,6 +2639,10 @@ ixgbe_flow_create(struct rte_eth_dev *dev,
sizeof(struct ixgbe_hw_fdir_mask));
if (ret)
goto out;
if (fdir_info->flex_bytes_offset !=
fdir_rule.flex_bytes_offset)
goto out;
}
}