#include <arpa/inet.h>
-#include "mrvl_ethdev.h"
+#include "mrvl_flow.h"
#include "mrvl_qos.h"
/** Number of rules in the classifier table. */
/** Size of the classifier key and mask strings. */
#define MRVL_CLS_STR_SIZE_MAX 40
-/** Parsed fields in processed rte_flow_item. */
-enum mrvl_parsed_fields {
- /* eth flags */
- F_DMAC = BIT(0),
- F_SMAC = BIT(1),
- F_TYPE = BIT(2),
- /* vlan flags */
- F_VLAN_ID = BIT(3),
- F_VLAN_PRI = BIT(4),
- F_VLAN_TCI = BIT(5), /* not supported by MUSDK yet */
- /* ip4 flags */
- F_IP4_TOS = BIT(6),
- F_IP4_SIP = BIT(7),
- F_IP4_DIP = BIT(8),
- F_IP4_PROTO = BIT(9),
- /* ip6 flags */
- F_IP6_TC = BIT(10), /* not supported by MUSDK yet */
- F_IP6_SIP = BIT(11),
- F_IP6_DIP = BIT(12),
- F_IP6_FLOW = BIT(13),
- F_IP6_NEXT_HDR = BIT(14),
- /* tcp flags */
- F_TCP_SPORT = BIT(15),
- F_TCP_DPORT = BIT(16),
- /* udp flags */
- F_UDP_SPORT = BIT(17),
- F_UDP_DPORT = BIT(18),
-};
-
-/** PMD-specific definition of a flow rule handle. */
-struct rte_flow {
- LIST_ENTRY(rte_flow) next;
-
- enum mrvl_parsed_fields pattern;
-
- struct pp2_cls_tbl_rule rule;
- struct pp2_cls_cos_desc cos;
- struct pp2_cls_tbl_action action;
-};
-
-static const enum rte_flow_item_type pattern_eth[] = {
- RTE_FLOW_ITEM_TYPE_ETH,
- RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_eth_vlan[] = {
- RTE_FLOW_ITEM_TYPE_ETH,
- RTE_FLOW_ITEM_TYPE_VLAN,
- RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_eth_vlan_ip[] = {
- RTE_FLOW_ITEM_TYPE_ETH,
- RTE_FLOW_ITEM_TYPE_VLAN,
- RTE_FLOW_ITEM_TYPE_IPV4,
- RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_eth_vlan_ip6[] = {
- RTE_FLOW_ITEM_TYPE_ETH,
- RTE_FLOW_ITEM_TYPE_VLAN,
- RTE_FLOW_ITEM_TYPE_IPV6,
- RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_eth_ip4[] = {
- RTE_FLOW_ITEM_TYPE_ETH,
- RTE_FLOW_ITEM_TYPE_IPV4,
- RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_eth_ip4_tcp[] = {
- RTE_FLOW_ITEM_TYPE_ETH,
- RTE_FLOW_ITEM_TYPE_IPV4,
- RTE_FLOW_ITEM_TYPE_TCP,
- RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_eth_ip4_udp[] = {
- RTE_FLOW_ITEM_TYPE_ETH,
- RTE_FLOW_ITEM_TYPE_IPV4,
- RTE_FLOW_ITEM_TYPE_UDP,
- RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_eth_ip6[] = {
- RTE_FLOW_ITEM_TYPE_ETH,
- RTE_FLOW_ITEM_TYPE_IPV6,
- RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_eth_ip6_tcp[] = {
- RTE_FLOW_ITEM_TYPE_ETH,
- RTE_FLOW_ITEM_TYPE_IPV6,
- RTE_FLOW_ITEM_TYPE_TCP,
- RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_eth_ip6_udp[] = {
- RTE_FLOW_ITEM_TYPE_ETH,
- RTE_FLOW_ITEM_TYPE_IPV6,
- RTE_FLOW_ITEM_TYPE_UDP,
- RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_vlan[] = {
- RTE_FLOW_ITEM_TYPE_VLAN,
- RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_vlan_ip[] = {
- RTE_FLOW_ITEM_TYPE_VLAN,
- RTE_FLOW_ITEM_TYPE_IPV4,
- RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_vlan_ip_tcp[] = {
- RTE_FLOW_ITEM_TYPE_VLAN,
- RTE_FLOW_ITEM_TYPE_IPV4,
- RTE_FLOW_ITEM_TYPE_TCP,
- RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_vlan_ip_udp[] = {
- RTE_FLOW_ITEM_TYPE_VLAN,
- RTE_FLOW_ITEM_TYPE_IPV4,
- RTE_FLOW_ITEM_TYPE_UDP,
- RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_vlan_ip6[] = {
- RTE_FLOW_ITEM_TYPE_VLAN,
- RTE_FLOW_ITEM_TYPE_IPV6,
- RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_vlan_ip6_tcp[] = {
- RTE_FLOW_ITEM_TYPE_VLAN,
- RTE_FLOW_ITEM_TYPE_IPV6,
- RTE_FLOW_ITEM_TYPE_TCP,
- RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_vlan_ip6_udp[] = {
- RTE_FLOW_ITEM_TYPE_VLAN,
- RTE_FLOW_ITEM_TYPE_IPV6,
- RTE_FLOW_ITEM_TYPE_UDP,
- RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_ip[] = {
- RTE_FLOW_ITEM_TYPE_IPV4,
- RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_ip6[] = {
- RTE_FLOW_ITEM_TYPE_IPV6,
- RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_ip_tcp[] = {
- RTE_FLOW_ITEM_TYPE_IPV4,
- RTE_FLOW_ITEM_TYPE_TCP,
- RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_ip6_tcp[] = {
- RTE_FLOW_ITEM_TYPE_IPV6,
- RTE_FLOW_ITEM_TYPE_TCP,
- RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_ip_udp[] = {
- RTE_FLOW_ITEM_TYPE_IPV4,
- RTE_FLOW_ITEM_TYPE_UDP,
- RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_ip6_udp[] = {
- RTE_FLOW_ITEM_TYPE_IPV6,
- RTE_FLOW_ITEM_TYPE_UDP,
- RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_tcp[] = {
- RTE_FLOW_ITEM_TYPE_TCP,
- RTE_FLOW_ITEM_TYPE_END
-};
-
-static const enum rte_flow_item_type pattern_udp[] = {
- RTE_FLOW_ITEM_TYPE_UDP,
- RTE_FLOW_ITEM_TYPE_END
-};
-
#define MRVL_VLAN_ID_MASK 0x0fff
#define MRVL_VLAN_PRI_MASK 0x7000
#define MRVL_IPV4_DSCP_MASK 0xfc
#define MRVL_IPV4_ADDR_MASK 0xffffffff
#define MRVL_IPV6_FLOW_MASK 0x0fffff
-/**
- * Given a flow item, return the next non-void one.
- *
- * @param items Pointer to the item in the table.
- * @returns Next not-void item, NULL otherwise.
- */
-static const struct rte_flow_item *
-mrvl_next_item(const struct rte_flow_item *items)
-{
- const struct rte_flow_item *item = items;
-
- for (; item->type != RTE_FLOW_ITEM_TYPE_END; item++) {
- if (item->type != RTE_FLOW_ITEM_TYPE_VOID)
- return item;
- }
-
- return NULL;
-}
-
/**
* Allocate memory for classifier rule key and mask fields.
*
struct pp2_cls_rule_key_field *key_field;
const uint8_t *k, *m;
- if (flow->rule.num_fields >= PP2_CLS_TBL_MAX_NUM_FIELDS)
- return -ENOSPC;
-
if (parse_dst) {
k = spec->dst.addr_bytes;
m = mask->dst.addr_bytes;
- flow->pattern |= F_DMAC;
+ flow->table_key.proto_field[flow->rule.num_fields].field.eth =
+ MV_NET_ETH_F_DA;
} else {
k = spec->src.addr_bytes;
m = mask->src.addr_bytes;
- flow->pattern |= F_SMAC;
+ flow->table_key.proto_field[flow->rule.num_fields].field.eth =
+ MV_NET_ETH_F_SA;
}
key_field = &flow->rule.fields[flow->rule.num_fields];
"%02x:%02x:%02x:%02x:%02x:%02x",
m[0], m[1], m[2], m[3], m[4], m[5]);
+ flow->table_key.proto_field[flow->rule.num_fields].proto =
+ MV_NET_PROTO_ETH;
+ flow->table_key.key_size += key_field->size;
+
flow->rule.num_fields += 1;
return 0;
struct pp2_cls_rule_key_field *key_field;
uint16_t k;
- if (flow->rule.num_fields >= PP2_CLS_TBL_MAX_NUM_FIELDS)
- return -ENOSPC;
-
key_field = &flow->rule.fields[flow->rule.num_fields];
mrvl_alloc_key_mask(key_field);
key_field->size = 2;
k = rte_be_to_cpu_16(spec->type);
snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);
- flow->pattern |= F_TYPE;
+ flow->table_key.proto_field[flow->rule.num_fields].proto =
+ MV_NET_PROTO_ETH;
+ flow->table_key.proto_field[flow->rule.num_fields].field.eth =
+ MV_NET_ETH_F_TYPE;
+ flow->table_key.key_size += key_field->size;
+
flow->rule.num_fields += 1;
return 0;
struct pp2_cls_rule_key_field *key_field;
uint16_t k;
- if (flow->rule.num_fields >= PP2_CLS_TBL_MAX_NUM_FIELDS)
- return -ENOSPC;
-
key_field = &flow->rule.fields[flow->rule.num_fields];
mrvl_alloc_key_mask(key_field);
key_field->size = 2;
k = rte_be_to_cpu_16(spec->tci) & MRVL_VLAN_ID_MASK;
snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);
- flow->pattern |= F_VLAN_ID;
+ flow->table_key.proto_field[flow->rule.num_fields].proto =
+ MV_NET_PROTO_VLAN;
+ flow->table_key.proto_field[flow->rule.num_fields].field.vlan =
+ MV_NET_VLAN_F_ID;
+ flow->table_key.key_size += key_field->size;
+
flow->rule.num_fields += 1;
return 0;
struct pp2_cls_rule_key_field *key_field;
uint16_t k;
- if (flow->rule.num_fields >= PP2_CLS_TBL_MAX_NUM_FIELDS)
- return -ENOSPC;
-
key_field = &flow->rule.fields[flow->rule.num_fields];
mrvl_alloc_key_mask(key_field);
key_field->size = 1;
k = (rte_be_to_cpu_16(spec->tci) & MRVL_VLAN_PRI_MASK) >> 13;
snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);
- flow->pattern |= F_VLAN_PRI;
+ flow->table_key.proto_field[flow->rule.num_fields].proto =
+ MV_NET_PROTO_VLAN;
+ flow->table_key.proto_field[flow->rule.num_fields].field.vlan =
+ MV_NET_VLAN_F_PRI;
+ flow->table_key.key_size += key_field->size;
+
flow->rule.num_fields += 1;
return 0;
struct pp2_cls_rule_key_field *key_field;
uint8_t k, m;
- if (flow->rule.num_fields >= PP2_CLS_TBL_MAX_NUM_FIELDS)
- return -ENOSPC;
-
key_field = &flow->rule.fields[flow->rule.num_fields];
mrvl_alloc_key_mask(key_field);
key_field->size = 1;
snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);
snprintf((char *)key_field->mask, MRVL_CLS_STR_SIZE_MAX, "%u", m);
- flow->pattern |= F_IP4_TOS;
+ flow->table_key.proto_field[flow->rule.num_fields].proto =
+ MV_NET_PROTO_IP4;
+ flow->table_key.proto_field[flow->rule.num_fields].field.ipv4 =
+ MV_NET_IP4_F_DSCP;
+ flow->table_key.key_size += key_field->size;
+
flow->rule.num_fields += 1;
return 0;
struct in_addr k;
uint32_t m;
- if (flow->rule.num_fields >= PP2_CLS_TBL_MAX_NUM_FIELDS)
- return -ENOSPC;
-
memset(&k, 0, sizeof(k));
if (parse_dst) {
k.s_addr = spec->hdr.dst_addr;
m = rte_be_to_cpu_32(mask->hdr.dst_addr);
- flow->pattern |= F_IP4_DIP;
+ flow->table_key.proto_field[flow->rule.num_fields].field.ipv4 =
+ MV_NET_IP4_F_DA;
} else {
k.s_addr = spec->hdr.src_addr;
m = rte_be_to_cpu_32(mask->hdr.src_addr);
- flow->pattern |= F_IP4_SIP;
+ flow->table_key.proto_field[flow->rule.num_fields].field.ipv4 =
+ MV_NET_IP4_F_SA;
}
key_field = &flow->rule.fields[flow->rule.num_fields];
inet_ntop(AF_INET, &k, (char *)key_field->key, MRVL_CLS_STR_SIZE_MAX);
snprintf((char *)key_field->mask, MRVL_CLS_STR_SIZE_MAX, "0x%x", m);
+ flow->table_key.proto_field[flow->rule.num_fields].proto =
+ MV_NET_PROTO_IP4;
+ flow->table_key.key_size += key_field->size;
+
flow->rule.num_fields += 1;
return 0;
struct pp2_cls_rule_key_field *key_field;
uint8_t k = spec->hdr.next_proto_id;
- if (flow->rule.num_fields >= PP2_CLS_TBL_MAX_NUM_FIELDS)
- return -ENOSPC;
-
key_field = &flow->rule.fields[flow->rule.num_fields];
mrvl_alloc_key_mask(key_field);
key_field->size = 1;
snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);
- flow->pattern |= F_IP4_PROTO;
+ flow->table_key.proto_field[flow->rule.num_fields].proto =
+ MV_NET_PROTO_IP4;
+ flow->table_key.proto_field[flow->rule.num_fields].field.ipv4 =
+ MV_NET_IP4_F_PROTO;
+ flow->table_key.key_size += key_field->size;
+
flow->rule.num_fields += 1;
return 0;
int size = sizeof(spec->hdr.dst_addr);
struct in6_addr k, m;
- if (flow->rule.num_fields >= PP2_CLS_TBL_MAX_NUM_FIELDS)
- return -ENOSPC;
-
memset(&k, 0, sizeof(k));
if (parse_dst) {
memcpy(k.s6_addr, spec->hdr.dst_addr, size);
memcpy(m.s6_addr, mask->hdr.dst_addr, size);
- flow->pattern |= F_IP6_DIP;
+ flow->table_key.proto_field[flow->rule.num_fields].field.ipv6 =
+ MV_NET_IP6_F_DA;
} else {
memcpy(k.s6_addr, spec->hdr.src_addr, size);
memcpy(m.s6_addr, mask->hdr.src_addr, size);
- flow->pattern |= F_IP6_SIP;
+ flow->table_key.proto_field[flow->rule.num_fields].field.ipv6 =
+ MV_NET_IP6_F_SA;
}
key_field = &flow->rule.fields[flow->rule.num_fields];
inet_ntop(AF_INET6, &k, (char *)key_field->key, MRVL_CLS_STR_SIZE_MAX);
inet_ntop(AF_INET6, &m, (char *)key_field->mask, MRVL_CLS_STR_SIZE_MAX);
+ flow->table_key.proto_field[flow->rule.num_fields].proto =
+ MV_NET_PROTO_IP6;
+ flow->table_key.key_size += key_field->size;
+
flow->rule.num_fields += 1;
return 0;
uint32_t k = rte_be_to_cpu_32(spec->hdr.vtc_flow) & MRVL_IPV6_FLOW_MASK,
m = rte_be_to_cpu_32(mask->hdr.vtc_flow) & MRVL_IPV6_FLOW_MASK;
- if (flow->rule.num_fields >= PP2_CLS_TBL_MAX_NUM_FIELDS)
- return -ENOSPC;
-
key_field = &flow->rule.fields[flow->rule.num_fields];
mrvl_alloc_key_mask(key_field);
key_field->size = 3;
snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);
snprintf((char *)key_field->mask, MRVL_CLS_STR_SIZE_MAX, "%u", m);
- flow->pattern |= F_IP6_FLOW;
+ flow->table_key.proto_field[flow->rule.num_fields].proto =
+ MV_NET_PROTO_IP6;
+ flow->table_key.proto_field[flow->rule.num_fields].field.ipv6 =
+ MV_NET_IP6_F_FLOW;
+ flow->table_key.key_size += key_field->size;
+
flow->rule.num_fields += 1;
return 0;
struct pp2_cls_rule_key_field *key_field;
uint8_t k = spec->hdr.proto;
- if (flow->rule.num_fields >= PP2_CLS_TBL_MAX_NUM_FIELDS)
- return -ENOSPC;
-
key_field = &flow->rule.fields[flow->rule.num_fields];
mrvl_alloc_key_mask(key_field);
key_field->size = 1;
snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);
- flow->pattern |= F_IP6_NEXT_HDR;
+ flow->table_key.proto_field[flow->rule.num_fields].proto =
+ MV_NET_PROTO_IP6;
+ flow->table_key.proto_field[flow->rule.num_fields].field.ipv6 =
+ MV_NET_IP6_F_NEXT_HDR;
+ flow->table_key.key_size += key_field->size;
+
flow->rule.num_fields += 1;
return 0;
struct pp2_cls_rule_key_field *key_field;
uint16_t k;
- if (flow->rule.num_fields >= PP2_CLS_TBL_MAX_NUM_FIELDS)
- return -ENOSPC;
-
key_field = &flow->rule.fields[flow->rule.num_fields];
mrvl_alloc_key_mask(key_field);
key_field->size = 2;
if (parse_dst) {
k = rte_be_to_cpu_16(spec->hdr.dst_port);
- flow->pattern |= F_TCP_DPORT;
+ flow->table_key.proto_field[flow->rule.num_fields].field.tcp =
+ MV_NET_TCP_F_DP;
} else {
k = rte_be_to_cpu_16(spec->hdr.src_port);
- flow->pattern |= F_TCP_SPORT;
+ flow->table_key.proto_field[flow->rule.num_fields].field.tcp =
+ MV_NET_TCP_F_SP;
}
snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);
+ flow->table_key.proto_field[flow->rule.num_fields].proto =
+ MV_NET_PROTO_TCP;
+ flow->table_key.key_size += key_field->size;
+
flow->rule.num_fields += 1;
return 0;
struct pp2_cls_rule_key_field *key_field;
uint16_t k;
- if (flow->rule.num_fields >= PP2_CLS_TBL_MAX_NUM_FIELDS)
- return -ENOSPC;
-
key_field = &flow->rule.fields[flow->rule.num_fields];
mrvl_alloc_key_mask(key_field);
key_field->size = 2;
if (parse_dst) {
k = rte_be_to_cpu_16(spec->hdr.dst_port);
- flow->pattern |= F_UDP_DPORT;
+ flow->table_key.proto_field[flow->rule.num_fields].field.udp =
+ MV_NET_UDP_F_DP;
} else {
k = rte_be_to_cpu_16(spec->hdr.src_port);
- flow->pattern |= F_UDP_SPORT;
+ flow->table_key.proto_field[flow->rule.num_fields].field.udp =
+ MV_NET_UDP_F_SP;
}
snprintf((char *)key_field->key, MRVL_CLS_STR_SIZE_MAX, "%u", k);
+ flow->table_key.proto_field[flow->rule.num_fields].proto =
+ MV_NET_PROTO_UDP;
+ flow->table_key.key_size += key_field->size;
+
flow->rule.num_fields += 1;
return 0;
struct rte_flow_error *error)
{
const struct rte_flow_item_eth *spec = NULL, *mask = NULL;
- struct ether_addr zero;
+ struct rte_ether_addr zero;
int ret;
ret = mrvl_parse_init(item, (const void **)&spec, (const void **)&mask,
{
const struct rte_flow_item_vlan *spec = NULL, *mask = NULL;
uint16_t m;
- int ret;
+ int ret, i;
ret = mrvl_parse_init(item, (const void **)&spec, (const void **)&mask,
&rte_flow_item_vlan_mask,
goto out;
}
- if (flow->pattern & F_TYPE) {
- rte_flow_error_set(error, ENOTSUP,
- RTE_FLOW_ERROR_TYPE_ITEM, item,
- "VLAN TPID matching is not supported");
- return -rte_errno;
- }
if (mask->inner_type) {
struct rte_flow_item_eth spec_eth = {
.type = spec->inner_type,
.type = mask->inner_type,
};
+ /* TPID is not supported so if ETH_TYPE was selected,
+ * error is return. else, classify eth-type with the tpid value
+ */
+ for (i = 0; i < flow->rule.num_fields; i++)
+ if (flow->table_key.proto_field[i].proto ==
+ MV_NET_PROTO_ETH &&
+ flow->table_key.proto_field[i].field.eth ==
+ MV_NET_ETH_F_TYPE) {
+ rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_ITEM,
+ item,
+ "VLAN TPID matching is not supported");
+ return -rte_errno;
+ }
+
MRVL_LOG(WARNING, "inner eth type mask is ignored");
ret = mrvl_parse_type(&spec_eth, &mask_eth, flow);
if (ret)
struct rte_flow_error *error)
{
const struct rte_flow_item_ipv6 *spec = NULL, *mask = NULL;
- struct ipv6_hdr zero;
+ struct rte_ipv6_hdr zero;
uint32_t flow_mask;
int ret;
int ret;
ret = mrvl_parse_init(item, (const void **)&spec, (const void **)&mask,
- &rte_flow_item_ipv4_mask,
- sizeof(struct rte_flow_item_ipv4), error);
+ &rte_flow_item_tcp_mask,
+ sizeof(struct rte_flow_item_tcp), error);
if (ret)
return ret;
int ret;
ret = mrvl_parse_init(item, (const void **)&spec, (const void **)&mask,
- &rte_flow_item_ipv4_mask,
- sizeof(struct rte_flow_item_ipv4), error);
+ &rte_flow_item_udp_mask,
+ sizeof(struct rte_flow_item_udp), error);
if (ret)
return ret;
return -rte_errno;
}
-/**
- * Parse flow pattern composed of the the eth item.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
static int
-mrvl_parse_pattern_eth(const struct rte_flow_item pattern[],
- struct rte_flow *flow,
- struct rte_flow_error *error)
+mrvl_string_to_hex_values(const uint8_t *input_string,
+ uint8_t *hex_key,
+ uint8_t *length)
{
- return mrvl_parse_eth(pattern, flow, error);
-}
+ char tmp_arr[3], tmp_string[MRVL_CLS_STR_SIZE_MAX], *string_iter;
+ int i;
-/**
- * Parse flow pattern composed of the eth and vlan items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static int
-mrvl_parse_pattern_eth_vlan(const struct rte_flow_item pattern[],
- struct rte_flow *flow,
- struct rte_flow_error *error)
-{
- const struct rte_flow_item *item = mrvl_next_item(pattern);
- int ret;
+ strcpy(tmp_string, (const char *)input_string);
+ string_iter = tmp_string;
- ret = mrvl_parse_eth(item, flow, error);
- if (ret)
- return ret;
+ string_iter += 2; /* skip the '0x' */
+ *length = ((*length - 2) + 1) / 2;
- item = mrvl_next_item(item + 1);
+ for (i = 0; i < *length; i++) {
+ strncpy(tmp_arr, string_iter, 2);
+ tmp_arr[2] = '\0';
+ if (get_val_securely8(tmp_arr, 16,
+ &hex_key[*length - 1 - i]) < 0)
+ return -1;
+ string_iter += 2;
+ }
- return mrvl_parse_vlan(item, flow, error);
+ return 0;
}
/**
- * Parse flow pattern composed of the eth, vlan and ip4/ip6 items.
+ * Parse raw flow item.
*
- * @param pattern Pointer to the flow pattern table.
+ * @param item Pointer to the flow item.
* @param flow Pointer to the flow.
* @param error Pointer to the flow error.
- * @param ip6 1 to parse ip6 item, 0 to parse ip4 item.
- * @returns 0 in case of success, negative value otherwise.
+ * @returns 0 on success, negative value otherwise.
*/
static int
-mrvl_parse_pattern_eth_vlan_ip4_ip6(const struct rte_flow_item pattern[],
- struct rte_flow *flow,
- struct rte_flow_error *error, int ip6)
+mrvl_parse_raw(const struct rte_flow_item *item,
+ struct rte_flow *flow,
+ struct rte_flow_error *error)
{
- const struct rte_flow_item *item = mrvl_next_item(pattern);
+ const struct rte_flow_item_raw *spec = NULL, *mask = NULL;
+ struct pp2_cls_rule_key_field *key_field;
+ struct mv_net_udf *udf_params;
+ uint8_t length;
int ret;
- ret = mrvl_parse_eth(item, flow, error);
+ ret = mrvl_parse_init(item, (const void **)&spec, (const void **)&mask,
+ &rte_flow_item_raw_mask,
+ sizeof(struct rte_flow_item_raw), error);
if (ret)
return ret;
- item = mrvl_next_item(item + 1);
- ret = mrvl_parse_vlan(item, flow, error);
- if (ret)
- return ret;
+ if (!spec->pattern) {
+ rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
+ NULL, "pattern pointer MUST be given\n");
+ return -rte_errno;
+ }
+
+ /* Only hex string is supported; so, it must start with '0x' */
+ if (strncmp((const char *)spec->pattern, "0x", 2) != 0) {
+ rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
+ NULL, "'pattern' string must start with '0x'\n");
+ return -rte_errno;
+ }
+
+ if (mask->pattern &&
+ strncmp((const char *)mask->pattern, "0x", 2) != 0) {
+ rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
+ NULL, "'mask-pattern' string must start with '0x'\n");
+ return -rte_errno;
+ }
+
+ if (mask->search && spec->search) {
+ rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
+ NULL, "'search' option must be '0'\n");
+ return -rte_errno;
+ }
+
+ if (mask->offset && spec->offset != 0) {
+ rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
+ NULL, "'offset' option must be '0'\n");
+ return -rte_errno;
+ }
+
+ if (!mask->relative || !spec->relative) {
+ rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
+ NULL, "'relative' option must be given and enabled\n");
+ return -rte_errno;
+ }
+
+ length = spec->length & mask->length;
+ if (!length) {
+ rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
+ NULL, "'length' option must be given bigger than '0'\n");
+ return -rte_errno;
+ }
+
+ key_field = &flow->rule.fields[flow->rule.num_fields];
+ mrvl_alloc_key_mask(key_field);
+
+ /* pattern and length refer to string bytes. we need to convert it to
+ * values.
+ */
+ key_field->size = length;
+ ret = mrvl_string_to_hex_values(spec->pattern, key_field->key,
+ &key_field->size);
+ if (ret) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
+ NULL,
+ "can't convert pattern from string to hex\n");
+ return -rte_errno;
+ }
+ if (mask->pattern) {
+ ret = mrvl_string_to_hex_values(mask->pattern, key_field->mask,
+ &length);
+ if (ret) {
+ rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ITEM_SPEC,
+ NULL,
+ "can't convert mask-pattern from string to hex\n");
+ return -rte_errno;
+ }
+ } else {
+ rte_free(key_field->mask);
+ key_field->mask = NULL;
+ }
- item = mrvl_next_item(item + 1);
+ flow->table_key.proto_field[flow->rule.num_fields].proto =
+ MV_NET_UDF;
+ udf_params =
+ &flow->table_key.proto_field[flow->rule.num_fields].field.udf;
+ udf_params->id = flow->next_udf_id++;
+ udf_params->size = key_field->size;
+ flow->table_key.key_size += key_field->size;
+
+ flow->rule.num_fields += 1;
- return ip6 ? mrvl_parse_ip6(item, flow, error) :
- mrvl_parse_ip4(item, flow, error);
+ return 0;
}
/**
- * Parse flow pattern composed of the eth, vlan and ipv4 items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
+ * Structure used to map specific flow pattern to the pattern parse callback
+ * which will iterate over each pattern item and extract relevant data.
*/
-static int
-mrvl_parse_pattern_eth_vlan_ip4(const struct rte_flow_item pattern[],
- struct rte_flow *flow,
- struct rte_flow_error *error)
-{
- return mrvl_parse_pattern_eth_vlan_ip4_ip6(pattern, flow, error, 0);
-}
+static const struct {
+ const enum rte_flow_item_type pattern_type;
+ int (*parse)(const struct rte_flow_item *pattern,
+ struct rte_flow *flow,
+ struct rte_flow_error *error);
+} mrvl_patterns[] = {
+ { RTE_FLOW_ITEM_TYPE_ETH, mrvl_parse_eth },
+ { RTE_FLOW_ITEM_TYPE_VLAN, mrvl_parse_vlan },
+ { RTE_FLOW_ITEM_TYPE_IPV4, mrvl_parse_ip4 },
+ { RTE_FLOW_ITEM_TYPE_IPV6, mrvl_parse_ip6 },
+ { RTE_FLOW_ITEM_TYPE_TCP, mrvl_parse_tcp },
+ { RTE_FLOW_ITEM_TYPE_UDP, mrvl_parse_udp },
+ { RTE_FLOW_ITEM_TYPE_RAW, mrvl_parse_raw },
+ { RTE_FLOW_ITEM_TYPE_END, NULL }
+};
/**
- * Parse flow pattern composed of the eth, vlan and ipv6 items.
+ * Parse flow attribute.
*
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
+ * This will check whether the provided attribute's flags are supported.
+ *
+ * @param priv Unused
+ * @param attr Pointer to the flow attribute.
+ * @param flow Unused
* @param error Pointer to the flow error.
* @returns 0 in case of success, negative value otherwise.
*/
static int
-mrvl_parse_pattern_eth_vlan_ip6(const struct rte_flow_item pattern[],
- struct rte_flow *flow,
- struct rte_flow_error *error)
+mrvl_flow_parse_attr(struct mrvl_priv *priv __rte_unused,
+ const struct rte_flow_attr *attr,
+ struct rte_flow *flow __rte_unused,
+ struct rte_flow_error *error)
{
- return mrvl_parse_pattern_eth_vlan_ip4_ip6(pattern, flow, error, 1);
+ if (!attr) {
+ rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ATTR,
+ NULL, "NULL attribute");
+ return -rte_errno;
+ }
+
+ if (attr->group) {
+ rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_ATTR_GROUP, NULL,
+ "Groups are not supported");
+ return -rte_errno;
+ }
+ if (attr->priority) {
+ rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, NULL,
+ "Priorities are not supported");
+ return -rte_errno;
+ }
+ if (!attr->ingress) {
+ rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, NULL,
+ "Only ingress is supported");
+ return -rte_errno;
+ }
+ if (attr->egress) {
+ rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
+ "Egress is not supported");
+ return -rte_errno;
+ }
+ if (attr->transfer) {
+ rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER, NULL,
+ "Transfer is not supported");
+ return -rte_errno;
+ }
+
+ return 0;
}
/**
- * Parse flow pattern composed of the eth and ip4/ip6 items.
+ * Parse flow pattern.
+ *
+ * Specific classifier rule will be created as well.
*
- * @param pattern Pointer to the flow pattern table.
+ * @param priv Unused
+ * @param pattern Pointer to the flow pattern.
* @param flow Pointer to the flow.
* @param error Pointer to the flow error.
- * @param ip6 1 to parse ip6 item, 0 to parse ip4 item.
* @returns 0 in case of success, negative value otherwise.
*/
static int
-mrvl_parse_pattern_eth_ip4_ip6(const struct rte_flow_item pattern[],
- struct rte_flow *flow,
- struct rte_flow_error *error, int ip6)
+mrvl_flow_parse_pattern(struct mrvl_priv *priv __rte_unused,
+ const struct rte_flow_item pattern[],
+ struct rte_flow *flow,
+ struct rte_flow_error *error)
{
- const struct rte_flow_item *item = mrvl_next_item(pattern);
+ unsigned int i, j;
int ret;
- ret = mrvl_parse_eth(item, flow, error);
- if (ret)
- return ret;
+ for (i = 0; pattern[i].type != RTE_FLOW_ITEM_TYPE_END; i++) {
+ if (pattern[i].type == RTE_FLOW_ITEM_TYPE_VOID)
+ continue;
+ for (j = 0; mrvl_patterns[j].pattern_type !=
+ RTE_FLOW_ITEM_TYPE_END; j++) {
+ if (mrvl_patterns[j].pattern_type != pattern[i].type)
+ continue;
+
+ if (flow->rule.num_fields >=
+ PP2_CLS_TBL_MAX_NUM_FIELDS) {
+ rte_flow_error_set(error, ENOSPC,
+ RTE_FLOW_ERROR_TYPE_ITEM_NUM,
+ NULL,
+ "too many pattern (max %d)");
+ return -rte_errno;
+ }
+
+ ret = mrvl_patterns[j].parse(&pattern[i], flow, error);
+ if (ret) {
+ mrvl_free_all_key_mask(&flow->rule);
+ return ret;
+ }
+ break;
+ }
+ if (mrvl_patterns[j].pattern_type == RTE_FLOW_ITEM_TYPE_END) {
+ rte_flow_error_set(error, ENOTSUP,
+ RTE_FLOW_ERROR_TYPE_ITEM, NULL,
+ "Unsupported pattern");
+ return -rte_errno;
+ }
+ }
- item = mrvl_next_item(item + 1);
+ flow->table_key.num_fields = flow->rule.num_fields;
- return ip6 ? mrvl_parse_ip6(item, flow, error) :
- mrvl_parse_ip4(item, flow, error);
-}
-
-/**
- * Parse flow pattern composed of the eth and ipv4 items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static inline int
-mrvl_parse_pattern_eth_ip4(const struct rte_flow_item pattern[],
- struct rte_flow *flow,
- struct rte_flow_error *error)
-{
- return mrvl_parse_pattern_eth_ip4_ip6(pattern, flow, error, 0);
-}
-
-/**
- * Parse flow pattern composed of the eth and ipv6 items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static inline int
-mrvl_parse_pattern_eth_ip6(const struct rte_flow_item pattern[],
- struct rte_flow *flow,
- struct rte_flow_error *error)
-{
- return mrvl_parse_pattern_eth_ip4_ip6(pattern, flow, error, 1);
-}
-
-/**
- * Parse flow pattern composed of the eth, ip4 and tcp/udp items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @param tcp 1 to parse tcp item, 0 to parse udp item.
- * @returns 0 in case of success, negative value otherwise.
- */
-static int
-mrvl_parse_pattern_eth_ip4_tcp_udp(const struct rte_flow_item pattern[],
- struct rte_flow *flow,
- struct rte_flow_error *error, int tcp)
-{
- const struct rte_flow_item *item = mrvl_next_item(pattern);
- int ret;
-
- ret = mrvl_parse_pattern_eth_ip4_ip6(pattern, flow, error, 0);
- if (ret)
- return ret;
-
- item = mrvl_next_item(item + 1);
- item = mrvl_next_item(item + 1);
-
- if (tcp)
- return mrvl_parse_tcp(item, flow, error);
-
- return mrvl_parse_udp(item, flow, error);
-}
-
-/**
- * Parse flow pattern composed of the eth, ipv4 and tcp items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static inline int
-mrvl_parse_pattern_eth_ip4_tcp(const struct rte_flow_item pattern[],
- struct rte_flow *flow,
- struct rte_flow_error *error)
-{
- return mrvl_parse_pattern_eth_ip4_tcp_udp(pattern, flow, error, 1);
-}
-
-/**
- * Parse flow pattern composed of the eth, ipv4 and udp items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static inline int
-mrvl_parse_pattern_eth_ip4_udp(const struct rte_flow_item pattern[],
- struct rte_flow *flow,
- struct rte_flow_error *error)
-{
- return mrvl_parse_pattern_eth_ip4_tcp_udp(pattern, flow, error, 0);
-}
-
-/**
- * Parse flow pattern composed of the eth, ipv6 and tcp/udp items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @param tcp 1 to parse tcp item, 0 to parse udp item.
- * @returns 0 in case of success, negative value otherwise.
- */
-static int
-mrvl_parse_pattern_eth_ip6_tcp_udp(const struct rte_flow_item pattern[],
- struct rte_flow *flow,
- struct rte_flow_error *error, int tcp)
-{
- const struct rte_flow_item *item = mrvl_next_item(pattern);
- int ret;
-
- ret = mrvl_parse_pattern_eth_ip4_ip6(pattern, flow, error, 1);
- if (ret)
- return ret;
-
- item = mrvl_next_item(item + 1);
- item = mrvl_next_item(item + 1);
-
- if (tcp)
- return mrvl_parse_tcp(item, flow, error);
-
- return mrvl_parse_udp(item, flow, error);
-}
-
-/**
- * Parse flow pattern composed of the eth, ipv6 and tcp items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static inline int
-mrvl_parse_pattern_eth_ip6_tcp(const struct rte_flow_item pattern[],
- struct rte_flow *flow,
- struct rte_flow_error *error)
-{
- return mrvl_parse_pattern_eth_ip6_tcp_udp(pattern, flow, error, 1);
-}
-
-/**
- * Parse flow pattern composed of the eth, ipv6 and udp items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static inline int
-mrvl_parse_pattern_eth_ip6_udp(const struct rte_flow_item pattern[],
- struct rte_flow *flow,
- struct rte_flow_error *error)
-{
- return mrvl_parse_pattern_eth_ip6_tcp_udp(pattern, flow, error, 0);
-}
-
-/**
- * Parse flow pattern composed of the vlan item.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static int
-mrvl_parse_pattern_vlan(const struct rte_flow_item pattern[],
- struct rte_flow *flow,
- struct rte_flow_error *error)
-{
- const struct rte_flow_item *item = mrvl_next_item(pattern);
-
- return mrvl_parse_vlan(item, flow, error);
-}
-
-/**
- * Parse flow pattern composed of the vlan and ip4/ip6 items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @param ip6 1 to parse ip6 item, 0 to parse ip4 item.
- * @returns 0 in case of success, negative value otherwise.
- */
-static int
-mrvl_parse_pattern_vlan_ip4_ip6(const struct rte_flow_item pattern[],
- struct rte_flow *flow,
- struct rte_flow_error *error, int ip6)
-{
- const struct rte_flow_item *item = mrvl_next_item(pattern);
- int ret;
-
- ret = mrvl_parse_vlan(item, flow, error);
- if (ret)
- return ret;
-
- item = mrvl_next_item(item + 1);
-
- return ip6 ? mrvl_parse_ip6(item, flow, error) :
- mrvl_parse_ip4(item, flow, error);
-}
-
-/**
- * Parse flow pattern composed of the vlan and ipv4 items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static inline int
-mrvl_parse_pattern_vlan_ip4(const struct rte_flow_item pattern[],
- struct rte_flow *flow,
- struct rte_flow_error *error)
-{
- return mrvl_parse_pattern_vlan_ip4_ip6(pattern, flow, error, 0);
-}
-
-/**
- * Parse flow pattern composed of the vlan, ipv4 and tcp/udp items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static int
-mrvl_parse_pattern_vlan_ip_tcp_udp(const struct rte_flow_item pattern[],
- struct rte_flow *flow,
- struct rte_flow_error *error, int tcp)
-{
- const struct rte_flow_item *item = mrvl_next_item(pattern);
- int ret;
-
- ret = mrvl_parse_pattern_vlan_ip4_ip6(pattern, flow, error, 0);
- if (ret)
- return ret;
-
- item = mrvl_next_item(item + 1);
- item = mrvl_next_item(item + 1);
-
- if (tcp)
- return mrvl_parse_tcp(item, flow, error);
-
- return mrvl_parse_udp(item, flow, error);
-}
-
-/**
- * Parse flow pattern composed of the vlan, ipv4 and tcp items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static inline int
-mrvl_parse_pattern_vlan_ip_tcp(const struct rte_flow_item pattern[],
- struct rte_flow *flow,
- struct rte_flow_error *error)
-{
- return mrvl_parse_pattern_vlan_ip_tcp_udp(pattern, flow, error, 1);
-}
-
-/**
- * Parse flow pattern composed of the vlan, ipv4 and udp items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static inline int
-mrvl_parse_pattern_vlan_ip_udp(const struct rte_flow_item pattern[],
- struct rte_flow *flow,
- struct rte_flow_error *error)
-{
- return mrvl_parse_pattern_vlan_ip_tcp_udp(pattern, flow, error, 0);
-}
-
-/**
- * Parse flow pattern composed of the vlan and ipv6 items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static inline int
-mrvl_parse_pattern_vlan_ip6(const struct rte_flow_item pattern[],
- struct rte_flow *flow,
- struct rte_flow_error *error)
-{
- return mrvl_parse_pattern_vlan_ip4_ip6(pattern, flow, error, 1);
-}
-
-/**
- * Parse flow pattern composed of the vlan, ipv6 and tcp/udp items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static int
-mrvl_parse_pattern_vlan_ip6_tcp_udp(const struct rte_flow_item pattern[],
- struct rte_flow *flow,
- struct rte_flow_error *error, int tcp)
-{
- const struct rte_flow_item *item = mrvl_next_item(pattern);
- int ret;
-
- ret = mrvl_parse_pattern_vlan_ip4_ip6(pattern, flow, error, 1);
- if (ret)
- return ret;
-
- item = mrvl_next_item(item + 1);
- item = mrvl_next_item(item + 1);
-
- if (tcp)
- return mrvl_parse_tcp(item, flow, error);
-
- return mrvl_parse_udp(item, flow, error);
-}
-
-/**
- * Parse flow pattern composed of the vlan, ipv6 and tcp items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static inline int
-mrvl_parse_pattern_vlan_ip6_tcp(const struct rte_flow_item pattern[],
- struct rte_flow *flow,
- struct rte_flow_error *error)
-{
- return mrvl_parse_pattern_vlan_ip6_tcp_udp(pattern, flow, error, 1);
-}
-
-/**
- * Parse flow pattern composed of the vlan, ipv6 and udp items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static inline int
-mrvl_parse_pattern_vlan_ip6_udp(const struct rte_flow_item pattern[],
- struct rte_flow *flow,
- struct rte_flow_error *error)
-{
- return mrvl_parse_pattern_vlan_ip6_tcp_udp(pattern, flow, error, 0);
-}
-
-/**
- * Parse flow pattern composed of the ip4/ip6 item.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @param ip6 1 to parse ip6 item, 0 to parse ip4 item.
- * @returns 0 in case of success, negative value otherwise.
- */
-static int
-mrvl_parse_pattern_ip4_ip6(const struct rte_flow_item pattern[],
- struct rte_flow *flow,
- struct rte_flow_error *error, int ip6)
-{
- const struct rte_flow_item *item = mrvl_next_item(pattern);
-
- return ip6 ? mrvl_parse_ip6(item, flow, error) :
- mrvl_parse_ip4(item, flow, error);
-}
-
-/**
- * Parse flow pattern composed of the ipv4 item.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static inline int
-mrvl_parse_pattern_ip4(const struct rte_flow_item pattern[],
- struct rte_flow *flow,
- struct rte_flow_error *error)
-{
- return mrvl_parse_pattern_ip4_ip6(pattern, flow, error, 0);
-}
-
-/**
- * Parse flow pattern composed of the ipv6 item.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static inline int
-mrvl_parse_pattern_ip6(const struct rte_flow_item pattern[],
- struct rte_flow *flow,
- struct rte_flow_error *error)
-{
- return mrvl_parse_pattern_ip4_ip6(pattern, flow, error, 1);
-}
-
-/**
- * Parse flow pattern composed of the ip4/ip6 and tcp items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @param ip6 1 to parse ip6 item, 0 to parse ip4 item.
- * @returns 0 in case of success, negative value otherwise.
- */
-static int
-mrvl_parse_pattern_ip4_ip6_tcp(const struct rte_flow_item pattern[],
- struct rte_flow *flow,
- struct rte_flow_error *error, int ip6)
-{
- const struct rte_flow_item *item = mrvl_next_item(pattern);
- int ret;
-
- ret = ip6 ? mrvl_parse_ip6(item, flow, error) :
- mrvl_parse_ip4(item, flow, error);
- if (ret)
- return ret;
-
- item = mrvl_next_item(item + 1);
-
- return mrvl_parse_tcp(item, flow, error);
-}
-
-/**
- * Parse flow pattern composed of the ipv4 and tcp items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static inline int
-mrvl_parse_pattern_ip4_tcp(const struct rte_flow_item pattern[],
- struct rte_flow *flow,
- struct rte_flow_error *error)
-{
- return mrvl_parse_pattern_ip4_ip6_tcp(pattern, flow, error, 0);
-}
-
-/**
- * Parse flow pattern composed of the ipv6 and tcp items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static inline int
-mrvl_parse_pattern_ip6_tcp(const struct rte_flow_item pattern[],
- struct rte_flow *flow,
- struct rte_flow_error *error)
-{
- return mrvl_parse_pattern_ip4_ip6_tcp(pattern, flow, error, 1);
-}
-
-/**
- * Parse flow pattern composed of the ipv4/ipv6 and udp items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @param ip6 1 to parse ip6 item, 0 to parse ip4 item.
- * @returns 0 in case of success, negative value otherwise.
- */
-static int
-mrvl_parse_pattern_ip4_ip6_udp(const struct rte_flow_item pattern[],
- struct rte_flow *flow,
- struct rte_flow_error *error, int ip6)
-{
- const struct rte_flow_item *item = mrvl_next_item(pattern);
- int ret;
-
- ret = ip6 ? mrvl_parse_ip6(item, flow, error) :
- mrvl_parse_ip4(item, flow, error);
- if (ret)
- return ret;
-
- item = mrvl_next_item(item + 1);
-
- return mrvl_parse_udp(item, flow, error);
-}
-
-/**
- * Parse flow pattern composed of the ipv4 and udp items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static inline int
-mrvl_parse_pattern_ip4_udp(const struct rte_flow_item pattern[],
- struct rte_flow *flow,
- struct rte_flow_error *error)
-{
- return mrvl_parse_pattern_ip4_ip6_udp(pattern, flow, error, 0);
-}
-
-/**
- * Parse flow pattern composed of the ipv6 and udp items.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static inline int
-mrvl_parse_pattern_ip6_udp(const struct rte_flow_item pattern[],
- struct rte_flow *flow,
- struct rte_flow_error *error)
-{
- return mrvl_parse_pattern_ip4_ip6_udp(pattern, flow, error, 1);
-}
-
-/**
- * Parse flow pattern composed of the tcp item.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static int
-mrvl_parse_pattern_tcp(const struct rte_flow_item pattern[],
- struct rte_flow *flow,
- struct rte_flow_error *error)
-{
- const struct rte_flow_item *item = mrvl_next_item(pattern);
-
- return mrvl_parse_tcp(item, flow, error);
-}
-
-/**
- * Parse flow pattern composed of the udp item.
- *
- * @param pattern Pointer to the flow pattern table.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static int
-mrvl_parse_pattern_udp(const struct rte_flow_item pattern[],
- struct rte_flow *flow,
- struct rte_flow_error *error)
-{
- const struct rte_flow_item *item = mrvl_next_item(pattern);
-
- return mrvl_parse_udp(item, flow, error);
-}
-
-/**
- * Structure used to map specific flow pattern to the pattern parse callback
- * which will iterate over each pattern item and extract relevant data.
- */
-static const struct {
- const enum rte_flow_item_type *pattern;
- int (*parse)(const struct rte_flow_item pattern[],
- struct rte_flow *flow,
- struct rte_flow_error *error);
-} mrvl_patterns[] = {
- { pattern_eth, mrvl_parse_pattern_eth },
- { pattern_eth_vlan, mrvl_parse_pattern_eth_vlan },
- { pattern_eth_vlan_ip, mrvl_parse_pattern_eth_vlan_ip4 },
- { pattern_eth_vlan_ip6, mrvl_parse_pattern_eth_vlan_ip6 },
- { pattern_eth_ip4, mrvl_parse_pattern_eth_ip4 },
- { pattern_eth_ip4_tcp, mrvl_parse_pattern_eth_ip4_tcp },
- { pattern_eth_ip4_udp, mrvl_parse_pattern_eth_ip4_udp },
- { pattern_eth_ip6, mrvl_parse_pattern_eth_ip6 },
- { pattern_eth_ip6_tcp, mrvl_parse_pattern_eth_ip6_tcp },
- { pattern_eth_ip6_udp, mrvl_parse_pattern_eth_ip6_udp },
- { pattern_vlan, mrvl_parse_pattern_vlan },
- { pattern_vlan_ip, mrvl_parse_pattern_vlan_ip4 },
- { pattern_vlan_ip_tcp, mrvl_parse_pattern_vlan_ip_tcp },
- { pattern_vlan_ip_udp, mrvl_parse_pattern_vlan_ip_udp },
- { pattern_vlan_ip6, mrvl_parse_pattern_vlan_ip6 },
- { pattern_vlan_ip6_tcp, mrvl_parse_pattern_vlan_ip6_tcp },
- { pattern_vlan_ip6_udp, mrvl_parse_pattern_vlan_ip6_udp },
- { pattern_ip, mrvl_parse_pattern_ip4 },
- { pattern_ip_tcp, mrvl_parse_pattern_ip4_tcp },
- { pattern_ip_udp, mrvl_parse_pattern_ip4_udp },
- { pattern_ip6, mrvl_parse_pattern_ip6 },
- { pattern_ip6_tcp, mrvl_parse_pattern_ip6_tcp },
- { pattern_ip6_udp, mrvl_parse_pattern_ip6_udp },
- { pattern_tcp, mrvl_parse_pattern_tcp },
- { pattern_udp, mrvl_parse_pattern_udp }
-};
-
-/**
- * Check whether provided pattern matches any of the supported ones.
- *
- * @param type_pattern Pointer to the pattern type.
- * @param item_pattern Pointer to the flow pattern.
- * @returns 1 in case of success, 0 value otherwise.
- */
-static int
-mrvl_patterns_match(const enum rte_flow_item_type *type_pattern,
- const struct rte_flow_item *item_pattern)
-{
- const enum rte_flow_item_type *type = type_pattern;
- const struct rte_flow_item *item = item_pattern;
-
- for (;;) {
- if (item->type == RTE_FLOW_ITEM_TYPE_VOID) {
- item++;
- continue;
- }
-
- if (*type == RTE_FLOW_ITEM_TYPE_END ||
- item->type == RTE_FLOW_ITEM_TYPE_END)
- break;
-
- if (*type != item->type)
- break;
-
- item++;
- type++;
- }
-
- return *type == item->type;
-}
-
-/**
- * Parse flow attribute.
- *
- * This will check whether the provided attribute's flags are supported.
- *
- * @param priv Unused
- * @param attr Pointer to the flow attribute.
- * @param flow Unused
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static int
-mrvl_flow_parse_attr(struct mrvl_priv *priv __rte_unused,
- const struct rte_flow_attr *attr,
- struct rte_flow *flow __rte_unused,
- struct rte_flow_error *error)
-{
- if (!attr) {
- rte_flow_error_set(error, EINVAL, RTE_FLOW_ERROR_TYPE_ATTR,
- NULL, "NULL attribute");
- return -rte_errno;
- }
-
- if (attr->group) {
- rte_flow_error_set(error, ENOTSUP,
- RTE_FLOW_ERROR_TYPE_ATTR_GROUP, NULL,
- "Groups are not supported");
- return -rte_errno;
- }
- if (attr->priority) {
- rte_flow_error_set(error, ENOTSUP,
- RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY, NULL,
- "Priorities are not supported");
- return -rte_errno;
- }
- if (!attr->ingress) {
- rte_flow_error_set(error, ENOTSUP,
- RTE_FLOW_ERROR_TYPE_ATTR_INGRESS, NULL,
- "Only ingress is supported");
- return -rte_errno;
- }
- if (attr->egress) {
- rte_flow_error_set(error, ENOTSUP,
- RTE_FLOW_ERROR_TYPE_ATTR_EGRESS, NULL,
- "Egress is not supported");
- return -rte_errno;
- }
- if (attr->transfer) {
- rte_flow_error_set(error, ENOTSUP,
- RTE_FLOW_ERROR_TYPE_ATTR_TRANSFER, NULL,
- "Transfer is not supported");
- return -rte_errno;
- }
-
- return 0;
-}
-
-/**
- * Parse flow pattern.
- *
- * Specific classifier rule will be created as well.
- *
- * @param priv Unused
- * @param pattern Pointer to the flow pattern.
- * @param flow Pointer to the flow.
- * @param error Pointer to the flow error.
- * @returns 0 in case of success, negative value otherwise.
- */
-static int
-mrvl_flow_parse_pattern(struct mrvl_priv *priv __rte_unused,
- const struct rte_flow_item pattern[],
- struct rte_flow *flow,
- struct rte_flow_error *error)
-{
- unsigned int i;
- int ret;
-
- for (i = 0; i < RTE_DIM(mrvl_patterns); i++) {
- if (!mrvl_patterns_match(mrvl_patterns[i].pattern, pattern))
- continue;
-
- ret = mrvl_patterns[i].parse(pattern, flow, error);
- if (ret)
- mrvl_free_all_key_mask(&flow->rule);
-
- return ret;
- }
-
- rte_flow_error_set(error, ENOTSUP, RTE_FLOW_ERROR_TYPE_ITEM, NULL,
- "Unsupported pattern");
-
- return -rte_errno;
+ return 0;
}
/**
flow->action.type = PP2_CLS_TBL_ACT_DONE;
flow->action.cos = &flow->cos;
specified++;
+ } else if (action->type == RTE_FLOW_ACTION_TYPE_METER) {
+ const struct rte_flow_action_meter *meter;
+ struct mrvl_mtr *mtr;
+
+ meter = action->conf;
+ if (!meter)
+ return -rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ NULL, "Invalid meter\n");
+
+ LIST_FOREACH(mtr, &priv->mtrs, next)
+ if (mtr->mtr_id == meter->mtr_id)
+ break;
+
+ if (!mtr)
+ return -rte_flow_error_set(error, EINVAL,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ NULL,
+ "Meter id does not exist\n");
+
+ if (!mtr->shared && mtr->refcnt)
+ return -rte_flow_error_set(error, EPERM,
+ RTE_FLOW_ERROR_TYPE_ACTION,
+ NULL,
+ "Meter cannot be shared\n");
+
+ /*
+ * In case cos has already been set
+ * do not modify it.
+ */
+ if (!flow->cos.ppio) {
+ flow->cos.ppio = priv->ppio;
+ flow->cos.tc = 0;
+ }
+
+ flow->action.type = PP2_CLS_TBL_ACT_DONE;
+ flow->action.cos = &flow->cos;
+ flow->action.plcr = mtr->enabled ? mtr->plcr : NULL;
+ flow->mtr = mtr;
+ mtr->refcnt++;
+ specified++;
} else {
rte_flow_error_set(error, ENOTSUP,
RTE_FLOW_ERROR_TYPE_ACTION, NULL,
"Action not supported");
return -rte_errno;
}
-
}
if (!specified) {
rte_flow_error_set(error, EINVAL,
- RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
- NULL, "Action not specified");
+ RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+ "Action not specified");
return -rte_errno;
}
priv->cls_tbl_params.max_num_rules = MRVL_CLS_MAX_NUM_RULES;
priv->cls_tbl_params.default_act.type = PP2_CLS_TBL_ACT_DONE;
priv->cls_tbl_params.default_act.cos = &first_flow->cos;
-
- if (first_flow->pattern & F_DMAC) {
- key->proto_field[key->num_fields].proto = MV_NET_PROTO_ETH;
- key->proto_field[key->num_fields].field.eth = MV_NET_ETH_F_DA;
- key->key_size += 6;
- key->num_fields += 1;
- }
-
- if (first_flow->pattern & F_SMAC) {
- key->proto_field[key->num_fields].proto = MV_NET_PROTO_ETH;
- key->proto_field[key->num_fields].field.eth = MV_NET_ETH_F_SA;
- key->key_size += 6;
- key->num_fields += 1;
- }
-
- if (first_flow->pattern & F_TYPE) {
- key->proto_field[key->num_fields].proto = MV_NET_PROTO_ETH;
- key->proto_field[key->num_fields].field.eth = MV_NET_ETH_F_TYPE;
- key->key_size += 2;
- key->num_fields += 1;
- }
-
- if (first_flow->pattern & F_VLAN_ID) {
- key->proto_field[key->num_fields].proto = MV_NET_PROTO_VLAN;
- key->proto_field[key->num_fields].field.vlan = MV_NET_VLAN_F_ID;
- key->key_size += 2;
- key->num_fields += 1;
- }
-
- if (first_flow->pattern & F_VLAN_PRI) {
- key->proto_field[key->num_fields].proto = MV_NET_PROTO_VLAN;
- key->proto_field[key->num_fields].field.vlan =
- MV_NET_VLAN_F_PRI;
- key->key_size += 1;
- key->num_fields += 1;
- }
-
- if (first_flow->pattern & F_IP4_TOS) {
- key->proto_field[key->num_fields].proto = MV_NET_PROTO_IP4;
- key->proto_field[key->num_fields].field.ipv4 = MV_NET_IP4_F_TOS;
- key->key_size += 1;
- key->num_fields += 1;
- }
-
- if (first_flow->pattern & F_IP4_SIP) {
- key->proto_field[key->num_fields].proto = MV_NET_PROTO_IP4;
- key->proto_field[key->num_fields].field.ipv4 = MV_NET_IP4_F_SA;
- key->key_size += 4;
- key->num_fields += 1;
- }
-
- if (first_flow->pattern & F_IP4_DIP) {
- key->proto_field[key->num_fields].proto = MV_NET_PROTO_IP4;
- key->proto_field[key->num_fields].field.ipv4 = MV_NET_IP4_F_DA;
- key->key_size += 4;
- key->num_fields += 1;
- }
-
- if (first_flow->pattern & F_IP4_PROTO) {
- key->proto_field[key->num_fields].proto = MV_NET_PROTO_IP4;
- key->proto_field[key->num_fields].field.ipv4 =
- MV_NET_IP4_F_PROTO;
- key->key_size += 1;
- key->num_fields += 1;
- }
-
- if (first_flow->pattern & F_IP6_SIP) {
- key->proto_field[key->num_fields].proto = MV_NET_PROTO_IP6;
- key->proto_field[key->num_fields].field.ipv6 = MV_NET_IP6_F_SA;
- key->key_size += 16;
- key->num_fields += 1;
- }
-
- if (first_flow->pattern & F_IP6_DIP) {
- key->proto_field[key->num_fields].proto = MV_NET_PROTO_IP6;
- key->proto_field[key->num_fields].field.ipv6 = MV_NET_IP6_F_DA;
- key->key_size += 16;
- key->num_fields += 1;
- }
-
- if (first_flow->pattern & F_IP6_FLOW) {
- key->proto_field[key->num_fields].proto = MV_NET_PROTO_IP6;
- key->proto_field[key->num_fields].field.ipv6 =
- MV_NET_IP6_F_FLOW;
- key->key_size += 3;
- key->num_fields += 1;
- }
-
- if (first_flow->pattern & F_IP6_NEXT_HDR) {
- key->proto_field[key->num_fields].proto = MV_NET_PROTO_IP6;
- key->proto_field[key->num_fields].field.ipv6 =
- MV_NET_IP6_F_NEXT_HDR;
- key->key_size += 1;
- key->num_fields += 1;
- }
-
- if (first_flow->pattern & F_TCP_SPORT) {
- key->proto_field[key->num_fields].proto = MV_NET_PROTO_TCP;
- key->proto_field[key->num_fields].field.tcp = MV_NET_TCP_F_SP;
- key->key_size += 2;
- key->num_fields += 1;
- }
-
- if (first_flow->pattern & F_TCP_DPORT) {
- key->proto_field[key->num_fields].proto = MV_NET_PROTO_TCP;
- key->proto_field[key->num_fields].field.tcp = MV_NET_TCP_F_DP;
- key->key_size += 2;
- key->num_fields += 1;
- }
-
- if (first_flow->pattern & F_UDP_SPORT) {
- key->proto_field[key->num_fields].proto = MV_NET_PROTO_UDP;
- key->proto_field[key->num_fields].field.tcp = MV_NET_TCP_F_SP;
- key->key_size += 2;
- key->num_fields += 1;
- }
-
- if (first_flow->pattern & F_UDP_DPORT) {
- key->proto_field[key->num_fields].proto = MV_NET_PROTO_UDP;
- key->proto_field[key->num_fields].field.udp = MV_NET_TCP_F_DP;
- key->key_size += 2;
- key->num_fields += 1;
- }
+ memcpy(key, &first_flow->table_key, sizeof(struct pp2_cls_tbl_key));
ret = pp2_cls_tbl_init(&priv->cls_tbl_params, &priv->cls_tbl);
- if (!ret)
- priv->cls_tbl_pattern = first_flow->pattern;
return ret;
}
static inline int
mrvl_flow_can_be_added(struct mrvl_priv *priv, const struct rte_flow *flow)
{
- return flow->pattern == priv->cls_tbl_pattern &&
- mrvl_engine_type(flow) == priv->cls_tbl_params.type;
+ int same = memcmp(&flow->table_key, &priv->cls_tbl_params.key,
+ sizeof(struct pp2_cls_tbl_key)) == 0;
+
+ return same && mrvl_engine_type(flow) == priv->cls_tbl_params.type;
}
/**
mrvl_free_all_key_mask(&flow->rule);
+ if (flow->mtr) {
+ flow->mtr->refcnt--;
+ flow->mtr = NULL;
+ }
+
return 0;
}
rte_free(flow);
}
+ if (priv->cls_tbl) {
+ pp2_cls_tbl_deinit(priv->cls_tbl);
+ priv->cls_tbl = NULL;
+ }
+
return 0;
}
.flush = mrvl_flow_flush,
.isolate = mrvl_flow_isolate
};
+
+/**
+ * Initialize flow resources.
+ *
+ * @param dev Pointer to the device.
+ */
+void
+mrvl_flow_init(struct rte_eth_dev *dev)
+{
+ struct mrvl_priv *priv = dev->data->dev_private;
+
+ LIST_INIT(&priv->flows);
+}
+
+/**
+ * Cleanup flow resources.
+ *
+ * @param dev Pointer to the device.
+ */
+void
+mrvl_flow_deinit(struct rte_eth_dev *dev)
+{
+ mrvl_flow_flush(dev, NULL);
+}