To manage and configure flow rules, implements operations to
validate, create, destroy and flush the flow rules.
Signed-off-by: Jasvinder Singh <jasvinder.si...@intel.com>
---
 drivers/net/softnic/rte_eth_softnic_fc.c | 311 ++++++++++++++++++++++++++++++-
 1 file changed, 307 insertions(+), 4 deletions(-)

diff --git a/drivers/net/softnic/rte_eth_softnic_fc.c 
b/drivers/net/softnic/rte_eth_softnic_fc.c
index 83f7fd3..e41eb57 100644
--- a/drivers/net/softnic/rte_eth_softnic_fc.c
+++ b/drivers/net/softnic/rte_eth_softnic_fc.c
@@ -330,6 +330,9 @@ fc_flow_uninit(struct pmd_internals *p)
                        break;
 
                TAILQ_REMOVE(&p->soft.fc.flow_list, flow, node);
+
+               free(flow->pattern);
+               free(flow->actions);
                free(flow);
        }
 }
@@ -369,9 +372,309 @@ fc_free(struct pmd_internals *p)
        rte_free(p->soft.fc.pkts);
 }
 
+static struct rte_flow *
+fc_flow_search(struct pmd_internals *p,
+       const struct rte_flow_attr *attr,
+       const struct rte_flow_item pattern[],
+       const struct rte_flow_action actions[])
+{
+       struct fc_flow_list *fl = &p->soft.fc.flow_list;
+       struct rte_flow *f;
+       uint32_t n_item, n_act, n_match_params;
+
+       TAILQ_FOREACH(f, fl, node) {
+               n_item = 0;
+               n_act = 0;
+               n_match_params = 0;
+
+               /* Check: Flow attr */
+               if (memcmp(&f->attr,
+                       (const void *)attr, sizeof(*attr)))
+                       continue;
+               else
+                       n_match_params += 1;
+
+               /* Check: Flow pattern */
+               while (pattern[n_item].type != RTE_FLOW_ITEM_TYPE_END) {
+                       if (pattern[n_item].type != f->pattern[n_item].type)
+                               n_match_params = 0;
+
+                       n_item++;
+               }
+
+               if (n_match_params)
+                       n_match_params += 1;
+               else
+                       continue;
+
+               /* Check: Flow action */
+               while (actions[n_act].type != RTE_FLOW_ACTION_TYPE_END) {
+                       if (actions[n_act].type != f->actions[n_act].type)
+                               n_match_params = 0;
+
+                       n_act++;
+               }
+
+               if (n_match_params)
+                       n_match_params += 1;
+               else
+                       continue;
+
+               if (n_match_params == 3)
+                       return f;
+       }
+       return NULL;
+}
+
+static int rule_add_check(struct pmd_internals *p,
+       const struct rte_flow_attr *attr,
+       const struct rte_flow_item pattern[],
+       const struct rte_flow_action actions[],
+       struct rte_flow_error *error)
+{
+       struct rte_flow *flow;
+       uint32_t n_flow_rules;
+
+       /** Check: Number of rules */
+       n_flow_rules = p->soft.fc.n_flow_rules;
+       if (n_flow_rules >= p->params.soft.fc.nb_rules) {
+               rte_flow_error_set(error,
+               EINVAL,
+               RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+               NULL,
+               "Number of Flow rule exceeds.");
+               return -EINVAL;
+       }
+
+       flow = fc_flow_search(p, attr, pattern, actions);
+       if (flow != NULL) {
+               rte_flow_error_set(error,
+               EEXIST,
+               RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+               NULL,
+               "Flow rule exists.");
+               return -EEXIST;
+       }
+
+       return 0;
+}
+
+/* Flow rule validate */
+static int
+pmd_flow_validate(__rte_unused struct rte_eth_dev *dev,
+       const struct rte_flow_attr *attr,
+       const struct rte_flow_item pattern[],
+       const struct rte_flow_action actions[],
+       struct rte_flow_error *error)
+{
+       if (!pattern) {
+               rte_flow_error_set(error,
+                       EINVAL,
+                       RTE_FLOW_ERROR_TYPE_ITEM_NUM,
+                       NULL,
+                       "NULL pattern.");
+               return -rte_errno;
+       }
+
+       if (!actions) {
+               rte_flow_error_set(error,
+                       EINVAL,
+                       RTE_FLOW_ERROR_TYPE_ACTION_NUM,
+                       NULL,
+                       "NULL action.");
+               return -rte_errno;
+       }
+
+       if (!attr) {
+               rte_flow_error_set(error,
+                       EINVAL,
+                       RTE_FLOW_ERROR_TYPE_ATTR,
+                       NULL,
+                       "NULL attribute.");
+               return -rte_errno;
+       }
+
+       /* Add validate function */
+
+       return 0;
+}
+
+/* Create flow rule */
+static struct rte_flow *
+pmd_flow_create(struct rte_eth_dev *dev,
+       const struct rte_flow_attr *attr,
+       const struct rte_flow_item pattern[],
+       const struct rte_flow_action actions[],
+       struct rte_flow_error *error)
+{
+       struct pmd_internals *p = dev->data->dev_private;
+       struct fc_flow_list *fl = &p->soft.fc.flow_list;
+       struct rte_flow *f;
+       uint32_t n_item = 0, n_act = 0;
+       int status;
+
+       /** Check: Attributes */
+       if (!attr) {
+               rte_flow_error_set(error,
+                       EINVAL,
+                       RTE_FLOW_ERROR_TYPE_ATTR,
+                       NULL,
+                       "NULL attribute.");
+               return NULL;
+       }
+
+       /** Check: Pattern */
+       if (!pattern) {
+               rte_flow_error_set(error,
+                       EINVAL,
+                       RTE_FLOW_ERROR_TYPE_ITEM_NUM,
+                       NULL,
+                       "NULL pattern.");
+               return NULL;
+       }
+
+       /** Check: Actions */
+       if (!actions) {
+               rte_flow_error_set(error,
+                       EINVAL,
+                       RTE_FLOW_ERROR_TYPE_ACTION_NUM,
+                       NULL,
+                       "NULL action.");
+               return NULL;
+       }
+
+       /** Check: Rule */
+       status = rule_add_check(p, attr, pattern, actions, error);
+       if (status)
+               return NULL;
+
+       /** Add rule to the table */
+
+       /* Memory allocation */
+       f = calloc(1, sizeof(struct rte_flow));
+       if (f == NULL) {
+               rte_flow_error_set(error,
+               ENOMEM,
+               RTE_TM_ERROR_TYPE_UNSPECIFIED,
+               NULL,
+               "Failed to create flow.");
+               return NULL;
+       }
+
+       /** Add attr to list */
+       memcpy((void *)&f->attr, (const void *)attr,  sizeof(*attr));
+
+       /** Allocate for pattern */
+       while ((pattern + n_item)->type != RTE_FLOW_ITEM_TYPE_END)
+               n_item++;
+
+       n_item++;
+
+       f->pattern = calloc(n_item, sizeof(struct rte_flow_item));
+       if (f->pattern) {
+               rte_flow_error_set(error,
+               ENOMEM,
+               RTE_TM_ERROR_TYPE_UNSPECIFIED,
+               NULL,
+               "Failed to create flow.");
+               return NULL;
+       }
+
+       /** Add pattern */
+       memcpy((void *)f->pattern, (const void *)pattern,  sizeof(*f->pattern));
+
+       /** Allocate for action */
+       while ((actions + n_act)->type != RTE_FLOW_ACTION_TYPE_END)
+               n_act++;
+
+       n_act++;
+
+       f->actions = calloc(n_act, sizeof(struct rte_flow_action));
+       if (f->actions) {
+               rte_flow_error_set(error,
+               ENOMEM,
+               RTE_TM_ERROR_TYPE_UNSPECIFIED,
+               NULL,
+               "Failed to create flow.");
+               return NULL;
+       }
+
+       /** Add actions */
+       memcpy((void *)f->actions, (const void *)actions,  sizeof(*f->actions));
+
+       TAILQ_INSERT_TAIL(fl, f, node);
+       p->soft.fc.n_flow_rules++;
+
+       return f;
+}
+
+/* Destroy flow rule */
+static int
+pmd_flow_destroy(struct rte_eth_dev *dev,
+       struct rte_flow *flow,
+       struct rte_flow_error *error)
+{
+       struct pmd_internals *p = dev->data->dev_private;
+       struct fc_flow_list *fl = &p->soft.fc.flow_list;
+       struct rte_flow *f;
+
+       /** Check: flow */
+       if (!flow) {
+               rte_flow_error_set(error,
+                       EINVAL,
+                       RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+                       NULL,
+                       "NULL flow.");
+               return -EINVAL;
+       }
+       /* Check existing */
+       f = fc_flow_search(p, &flow->attr, flow->pattern, flow->actions);
+       if (f == NULL) {
+               rte_flow_error_set(error,
+                       EINVAL,
+                       RTE_FLOW_ERROR_TYPE_UNSPECIFIED,
+                       NULL,
+                       "Flow not exist");
+                       return -EINVAL;
+       }
+
+       /** Remove from Classifier table */
+
+       /** Remove from list */
+       TAILQ_REMOVE(fl, f, node);
+       p->soft.fc.n_flow_rules--;
+       free(f);
+
+       return 0;
+}
+
+/* Destroy flow rules */
+static int
+pmd_flow_flush(struct rte_eth_dev *dev,
+       __rte_unused struct rte_flow_error *error)
+{
+       struct pmd_internals *p = dev->data->dev_private;
+
+       for ( ; ; ) {
+               struct rte_flow *f;
+
+               f = TAILQ_FIRST(&p->soft.fc.flow_list);
+               if (f == NULL)
+                       break;
+
+               /** Remove from Classifier table */
+
+               /** Remove from list */
+               TAILQ_REMOVE(&p->soft.fc.flow_list, f, node);
+               free(f);
+       }
+
+       return 0;
+}
+
 const struct rte_flow_ops pmd_flow_ops = {
-       .validate = NULL,
-       .create = NULL,
-       .destroy = NULL,
-       .flush = NULL,
+       .validate = pmd_flow_validate,
+       .create = pmd_flow_create,
+       .destroy = pmd_flow_destroy,
+       .flush = pmd_flow_flush,
 };
-- 
2.9.3

Reply via email to