#include <arpa/inet.h>
-#ifdef container_of
-#undef container_of
-#endif
-
-#include "mrvl_ethdev.h"
+#include "mrvl_flow.h"
#include "mrvl_qos.h"
-#include "env/mv_common.h" /* for BIT() */
/** Number of rules in the classifier table. */
#define MRVL_CLS_MAX_NUM_RULES 20
/** 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
*
* @param spec Pointer to the specific flow item.
* @param mask Pointer to the specific flow item's mask.
- * @param mask Pointer to the flow.
+ * @param parse_dst Parse either destination or source mac address.
+ * @param flow Pointer to the flow.
* @return 0 in case of success, negative error value otherwise.
*/
static int
*
* @param spec Pointer to the specific flow item.
* @param mask Pointer to the specific flow item's mask.
+ * @param parse_dst Parse either destination or source ip address.
* @param flow Pointer to the flow.
* @return 0 in case of success, negative error value otherwise.
*/
*
* @param spec Pointer to the specific flow item.
* @param mask Pointer to the specific flow item's mask.
+ * @param parse_dst Parse either destination or source ipv6 address.
* @param flow Pointer to the flow.
* @return 0 in case of success, negative error value otherwise.
*/
*
* @param spec Pointer to the specific flow item.
* @param mask Pointer to the specific flow item's mask.
+ * @param parse_dst Parse either destination or source port.
* @param flow Pointer to the flow.
* @return 0 in case of success, negative error value otherwise.
*/
*
* @param spec Pointer to the specific flow item.
* @param mask Pointer to the specific flow item's mask.
+ * @param parse_dst Parse either destination or source port.
* @param flow Pointer to the flow.
* @return 0 in case of success, negative error value otherwise.
*/
* @param item Pointer to the flow item.
* @param flow Pointer to the flow.
* @param error Pointer to the flow error.
- * @param fields Pointer to the parsed parsed fields enum.
* @returns 0 on success, negative value otherwise.
*/
static int
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,
}
if (mask->type) {
- RTE_LOG(WARNING, PMD, "eth type mask is ignored\n");
+ MRVL_LOG(WARNING, "eth type mask is ignored");
ret = mrvl_parse_type(spec, mask, flow);
if (ret)
goto out;
* @param item Pointer to the flow item.
* @param flow Pointer to the flow.
* @param error Pointer to the flow error.
- * @param fields Pointer to the parsed parsed fields enum.
* @returns 0 on success, negative value otherwise.
*/
static int
m = rte_be_to_cpu_16(mask->tci);
if (m & MRVL_VLAN_ID_MASK) {
- RTE_LOG(WARNING, PMD, "vlan id mask is ignored\n");
+ MRVL_LOG(WARNING, "vlan id mask is ignored");
ret = mrvl_parse_vlan_id(spec, mask, flow);
if (ret)
goto out;
}
if (m & MRVL_VLAN_PRI_MASK) {
- RTE_LOG(WARNING, PMD, "vlan pri mask is ignored\n");
+ MRVL_LOG(WARNING, "vlan pri mask is ignored");
ret = mrvl_parse_vlan_pri(spec, mask, flow);
if (ret)
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\n");
+ "VLAN TPID matching is not supported");
return -rte_errno;
}
if (mask->inner_type) {
.type = mask->inner_type,
};
- RTE_LOG(WARNING, PMD, "inner eth type mask is ignored\n");
+ MRVL_LOG(WARNING, "inner eth type mask is ignored");
ret = mrvl_parse_type(&spec_eth, &mask_eth, flow);
if (ret)
goto out;
* @param item Pointer to the flow item.
* @param flow Pointer to the flow.
* @param error Pointer to the flow error.
- * @param fields Pointer to the parsed parsed fields enum.
* @returns 0 on success, negative value otherwise.
*/
static int
}
if (mask->hdr.next_proto_id) {
- RTE_LOG(WARNING, PMD, "next proto id mask is ignored\n");
+ MRVL_LOG(WARNING, "next proto id mask is ignored");
ret = mrvl_parse_ip4_proto(spec, mask, flow);
if (ret)
goto out;
* @param item Pointer to the flow item.
* @param flow Pointer to the flow.
* @param error Pointer to the flow error.
- * @param fields Pointer to the parsed parsed fields enum.
* @returns 0 on success, negative value otherwise.
*/
static int
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;
}
if (mask->hdr.proto) {
- RTE_LOG(WARNING, PMD, "next header mask is ignored\n");
+ MRVL_LOG(WARNING, "next header mask is ignored");
ret = mrvl_parse_ip6_next_hdr(spec, mask, flow);
if (ret)
goto out;
* @param item Pointer to the flow item.
* @param flow Pointer to the flow.
* @param error Pointer to the flow error.
- * @param fields Pointer to the parsed parsed fields enum.
* @returns 0 on success, negative value otherwise.
*/
static int
}
if (mask->hdr.src_port) {
- RTE_LOG(WARNING, PMD, "tcp sport mask is ignored\n");
+ MRVL_LOG(WARNING, "tcp sport mask is ignored");
ret = mrvl_parse_tcp_sport(spec, mask, flow);
if (ret)
goto out;
}
if (mask->hdr.dst_port) {
- RTE_LOG(WARNING, PMD, "tcp dport mask is ignored\n");
+ MRVL_LOG(WARNING, "tcp dport mask is ignored");
ret = mrvl_parse_tcp_dport(spec, mask, flow);
if (ret)
goto out;
* @param item Pointer to the flow item.
* @param flow Pointer to the flow.
* @param error Pointer to the flow error.
- * @param fields Pointer to the parsed parsed fields enum.
* @returns 0 on success, negative value otherwise.
*/
static int
}
if (mask->hdr.src_port) {
- RTE_LOG(WARNING, PMD, "udp sport mask is ignored\n");
+ MRVL_LOG(WARNING, "udp sport mask is ignored");
ret = mrvl_parse_udp_sport(spec, mask, flow);
if (ret)
goto out;
}
if (mask->hdr.dst_port) {
- RTE_LOG(WARNING, PMD, "udp dport mask is ignored\n");
+ MRVL_LOG(WARNING, "udp dport mask is ignored");
ret = mrvl_parse_udp_dport(spec, mask, flow);
if (ret)
goto out;
* @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
* Unknown TC mapping, mapping will not have
* a correct queue.
*/
- RTE_LOG(ERR, PMD,
- "Unknown TC mapping for queue %hu eth%hhu\n",
+ MRVL_LOG(ERR,
+ "Unknown TC mapping for queue %hu eth%hhu",
q->index, priv->ppio_id);
rte_flow_error_set(error, EFAULT,
return -rte_errno;
}
- RTE_LOG(DEBUG, PMD,
- "Action: Assign packets to queue %d, tc:%d, q:%d\n",
+ MRVL_LOG(DEBUG,
+ "Action: Assign packets to queue %d, tc:%d, q:%d",
q->index, priv->rxq_map[q->index].tc,
priv->rxq_map[q->index].inq);
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;
}
return mrvl_flow_parse_actions(priv, actions, flow, error);
}
+/**
+ * Get engine type for the given flow.
+ *
+ * @param field Pointer to the flow.
+ * @returns The type of the engine.
+ */
static inline enum pp2_cls_tbl_type
mrvl_engine_type(const struct rte_flow *flow)
{
return PP2_CLS_TBL_MASKABLE;
}
+/**
+ * Create classifier table.
+ *
+ * @param dev Pointer to the device.
+ * @param flow Pointer to the very first flow.
+ * @returns 0 in case of success, negative value otherwise.
+ */
static int
mrvl_create_cls_table(struct rte_eth_dev *dev, struct rte_flow *first_flow)
{
memset(&priv->cls_tbl_params, 0, sizeof(priv->cls_tbl_params));
priv->cls_tbl_params.type = mrvl_engine_type(first_flow);
- RTE_LOG(INFO, PMD, "Setting cls search engine type to %s\n",
+ MRVL_LOG(INFO, "Setting cls search engine type to %s",
priv->cls_tbl_params.type == PP2_CLS_TBL_EXACT_MATCH ?
"exact" : "maskable");
priv->cls_tbl_params.max_num_rules = MRVL_CLS_MAX_NUM_RULES;
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->proto_field[key->num_fields].field.ipv4 =
+ MV_NET_IP4_F_DSCP;
key->key_size += 1;
key->num_fields += 1;
}
mrvl_free_all_key_mask(&flow->rule);
+ if (flow->mtr) {
+ flow->mtr->refcnt--;
+ flow->mtr = NULL;
+ }
+
return 0;
}
/**
* DPDK flow destroy callback called when flow is to be removed.
*
- * @param priv Pointer to the port's private data.
+ * @param dev Pointer to the device.
* @param flow Pointer to the flow.
* @param error Pointer to the flow error.
* @returns 0 in case of success, negative value otherwise.
.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)
+{
+ struct mrvl_priv *priv = dev->data->dev_private;
+
+ mrvl_flow_flush(dev, NULL);
+
+ if (priv->cls_tbl) {
+ pp2_cls_tbl_deinit(priv->cls_tbl);
+ priv->cls_tbl = NULL;
+ }
+}