net: add rte prefix to ether structures
[dpdk.git] / drivers / net / mvpp2 / mrvl_flow.c
index 13295e6..7389865 100644 (file)
 
 #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
@@ -1034,7 +989,7 @@ mrvl_parse_eth(const struct rte_flow_item *item, struct rte_flow *flow,
               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,
@@ -2300,19 +2255,59 @@ mrvl_flow_parse_actions(struct mrvl_priv *priv,
                        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;
        }
 
@@ -2442,7 +2437,8 @@ mrvl_create_cls_table(struct rte_eth_dev *dev, struct rte_flow *first_flow)
 
        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;
        }
@@ -2662,6 +2658,11 @@ mrvl_flow_remove(struct mrvl_priv *priv, struct rte_flow *flow,
 
        mrvl_free_all_key_mask(&flow->rule);
 
+       if (flow->mtr) {
+               flow->mtr->refcnt--;
+               flow->mtr = NULL;
+       }
+
        return 0;
 }
 
@@ -2790,3 +2791,34 @@ const struct rte_flow_ops mrvl_flow_ops = {
        .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;
+       }
+}