net/cnxk: support Tx security offload on cn9k
[dpdk.git] / drivers / net / cnxk / cnxk_rte_flow.c
index 1695d4f..32c1b5d 100644 (file)
@@ -15,8 +15,8 @@ const struct cnxk_rte_flow_term_info term[] = {
        [RTE_FLOW_ITEM_TYPE_IPV6] = {ROC_NPC_ITEM_TYPE_IPV6,
                                     sizeof(struct rte_flow_item_ipv6)},
        [RTE_FLOW_ITEM_TYPE_ARP_ETH_IPV4] = {
-               ROC_NPC_ITEM_TYPE_ARP_ETH_IPV4,
-               sizeof(struct rte_flow_item_arp_eth_ipv4)},
+                       ROC_NPC_ITEM_TYPE_ARP_ETH_IPV4,
+                       sizeof(struct rte_flow_item_arp_eth_ipv4)},
        [RTE_FLOW_ITEM_TYPE_MPLS] = {ROC_NPC_ITEM_TYPE_MPLS,
                                     sizeof(struct rte_flow_item_mpls)},
        [RTE_FLOW_ITEM_TYPE_ICMP] = {ROC_NPC_ITEM_TYPE_ICMP,
@@ -50,20 +50,70 @@ const struct cnxk_rte_flow_term_info term[] = {
        [RTE_FLOW_ITEM_TYPE_ANY] = {ROC_NPC_ITEM_TYPE_ANY, 0},
        [RTE_FLOW_ITEM_TYPE_GRE_KEY] = {ROC_NPC_ITEM_TYPE_GRE_KEY,
                                        sizeof(uint32_t)},
-       [RTE_FLOW_ITEM_TYPE_HIGIG2] = {
-               ROC_NPC_ITEM_TYPE_HIGIG2,
-               sizeof(struct rte_flow_item_higig2_hdr)}
-};
+       [RTE_FLOW_ITEM_TYPE_HIGIG2] = {ROC_NPC_ITEM_TYPE_HIGIG2,
+                                      sizeof(struct rte_flow_item_higig2_hdr)},
+       [RTE_FLOW_ITEM_TYPE_RAW] = {ROC_NPC_ITEM_TYPE_RAW,
+                                   sizeof(struct rte_flow_item_raw)}};
+
+static int
+npc_rss_action_validate(struct rte_eth_dev *eth_dev,
+                       const struct rte_flow_attr *attr,
+                       const struct rte_flow_action *act)
+{
+       const struct rte_flow_action_rss *rss;
+
+       rss = (const struct rte_flow_action_rss *)act->conf;
+
+       if (attr->egress) {
+               plt_err("No support of RSS in egress");
+               return -EINVAL;
+       }
+
+       if (eth_dev->data->dev_conf.rxmode.mq_mode != ETH_MQ_RX_RSS) {
+               plt_err("multi-queue mode is disabled");
+               return -ENOTSUP;
+       }
+
+       if (!rss || !rss->queue_num) {
+               plt_err("no valid queues");
+               return -EINVAL;
+       }
+
+       if (rss->func != RTE_ETH_HASH_FUNCTION_DEFAULT) {
+               plt_err("non-default RSS hash functions are not supported");
+               return -ENOTSUP;
+       }
+
+       if (rss->key_len && rss->key_len > ROC_NIX_RSS_KEY_LEN) {
+               plt_err("RSS hash key too large");
+               return -ENOTSUP;
+       }
+
+       return 0;
+}
+
+static void
+npc_rss_flowkey_get(struct cnxk_eth_dev *eth_dev,
+                   const struct roc_npc_action *rss_action,
+                   uint32_t *flowkey_cfg)
+{
+       const struct roc_npc_action_rss *rss;
+
+       rss = (const struct roc_npc_action_rss *)rss_action->conf;
+
+       *flowkey_cfg = cnxk_rss_ethdev_to_nix(eth_dev, rss->types, rss->level);
+}
 
 static int
-cnxk_map_actions(struct rte_eth_dev *eth_dev,
+cnxk_map_actions(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
                 const struct rte_flow_action actions[],
-                struct roc_npc_action in_actions[])
+                struct roc_npc_action in_actions[], uint32_t *flowkey_cfg)
 {
+       struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
        const struct rte_flow_action_count *act_count;
        const struct rte_flow_action_queue *act_q;
+       int i = 0, rc = 0;
        int rq;
-       int i = 0;
 
        for (; actions->type != RTE_FLOW_ACTION_TYPE_END; actions++) {
                switch (actions->type) {
@@ -117,12 +167,34 @@ cnxk_map_actions(struct rte_eth_dev *eth_dev,
                        break;
 
                case RTE_FLOW_ACTION_TYPE_RSS:
+                       rc = npc_rss_action_validate(eth_dev, attr, actions);
+                       if (rc)
+                               goto err_exit;
                        in_actions[i].type = ROC_NPC_ACTION_TYPE_RSS;
+                       in_actions[i].conf = actions->conf;
+                       npc_rss_flowkey_get(dev, &in_actions[i], flowkey_cfg);
                        break;
 
                case RTE_FLOW_ACTION_TYPE_SECURITY:
                        in_actions[i].type = ROC_NPC_ACTION_TYPE_SEC;
                        break;
+               case RTE_FLOW_ACTION_TYPE_OF_POP_VLAN:
+                       in_actions[i].type = ROC_NPC_ACTION_TYPE_VLAN_STRIP;
+                       break;
+               case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_VID:
+                       in_actions[i].type = ROC_NPC_ACTION_TYPE_VLAN_INSERT;
+                       in_actions[i].conf = actions->conf;
+                       break;
+               case RTE_FLOW_ACTION_TYPE_OF_PUSH_VLAN:
+                       in_actions[i].type =
+                               ROC_NPC_ACTION_TYPE_VLAN_ETHTYPE_INSERT;
+                       in_actions[i].conf = actions->conf;
+                       break;
+               case RTE_FLOW_ACTION_TYPE_OF_SET_VLAN_PCP:
+                       in_actions[i].type =
+                               ROC_NPC_ACTION_TYPE_VLAN_PCP_INSERT;
+                       in_actions[i].conf = actions->conf;
+                       break;
                default:
                        plt_npc_dbg("Action is not supported = %d",
                                    actions->type);
@@ -144,7 +216,7 @@ cnxk_map_flow_data(struct rte_eth_dev *eth_dev,
                   const struct rte_flow_action actions[],
                   struct roc_npc_attr *in_attr,
                   struct roc_npc_item_info in_pattern[],
-                  struct roc_npc_action in_actions[])
+                  struct roc_npc_action in_actions[], uint32_t *flowkey_cfg)
 {
        int i = 0;
 
@@ -163,7 +235,8 @@ cnxk_map_flow_data(struct rte_eth_dev *eth_dev,
        }
        in_pattern[i].type = ROC_NPC_ITEM_TYPE_END;
 
-       return cnxk_map_actions(eth_dev, actions, in_actions);
+       return cnxk_map_actions(eth_dev, attr, actions, in_actions,
+                               flowkey_cfg);
 }
 
 static int
@@ -179,12 +252,13 @@ cnxk_flow_validate(struct rte_eth_dev *eth_dev,
        struct roc_npc *npc = &dev->npc;
        struct roc_npc_attr in_attr;
        struct roc_npc_flow flow;
+       uint32_t flowkey_cfg = 0;
        int rc;
 
        memset(&flow, 0, sizeof(flow));
 
        rc = cnxk_map_flow_data(eth_dev, attr, pattern, actions, &in_attr,
-                               in_pattern, in_actions);
+                               in_pattern, in_actions, &flowkey_cfg);
        if (rc) {
                rte_flow_error_set(error, 0, RTE_FLOW_ERROR_TYPE_ACTION_NUM,
                                   NULL, "Failed to map flow data");
@@ -206,11 +280,12 @@ cnxk_flow_create(struct rte_eth_dev *eth_dev, const struct rte_flow_attr *attr,
        struct roc_npc *npc = &dev->npc;
        struct roc_npc_attr in_attr;
        struct roc_npc_flow *flow;
-       int errcode;
+       int errcode = 0;
        int rc;
 
        rc = cnxk_map_flow_data(eth_dev, attr, pattern, actions, &in_attr,
-                               in_pattern, in_actions);
+                               in_pattern, in_actions,
+                               &npc->flowkey_cfg_state);
        if (rc) {
                rte_flow_error_set(error, 0, RTE_FLOW_ERROR_TYPE_ACTION_NUM,
                                   NULL, "Failed to map flow data");
@@ -322,9 +397,37 @@ cnxk_flow_isolate(struct rte_eth_dev *eth_dev __rte_unused,
        return -rte_errno;
 }
 
+static int
+cnxk_flow_dev_dump(struct rte_eth_dev *eth_dev, struct rte_flow *flow,
+                  FILE *file, struct rte_flow_error *error)
+{
+       struct cnxk_eth_dev *dev = cnxk_eth_pmd_priv(eth_dev);
+       struct roc_npc *npc = &dev->npc;
+
+       if (file == NULL) {
+               rte_flow_error_set(error, EINVAL,
+                                  RTE_FLOW_ERROR_TYPE_UNSPECIFIED, NULL,
+                                  "Invalid file");
+               return -rte_errno;
+       }
+
+       if (flow != NULL) {
+               rte_flow_error_set(error, EINVAL,
+                                  RTE_FLOW_ERROR_TYPE_HANDLE,
+                                  NULL,
+                                  "Invalid argument");
+               return -EINVAL;
+       }
+
+       roc_npc_flow_dump(file, npc);
+
+       return 0;
+}
+
 struct rte_flow_ops cnxk_flow_ops = {
        .validate = cnxk_flow_validate,
        .flush = cnxk_flow_flush,
        .query = cnxk_flow_query,
        .isolate = cnxk_flow_isolate,
+       .dev_dump = cnxk_flow_dev_dump,
 };