Check if the rule is a ethertype rule, and get the ethertype
info BTW.

Signed-off-by: Wenzhuo Lu <wenzhuo...@intel.com>
Signed-off-by: Beilei Xing <beilei.x...@intel.com>
---
 lib/librte_ether/rte_flow.c        | 136 +++++++++++++++++++++++++++++++++++++
 lib/librte_ether/rte_flow_driver.h |  34 ++++++++++
 2 files changed, 170 insertions(+)

diff --git a/lib/librte_ether/rte_flow.c b/lib/librte_ether/rte_flow.c
index 064963d..acc9057 100644
--- a/lib/librte_ether/rte_flow.c
+++ b/lib/librte_ether/rte_flow.c
@@ -157,3 +157,139 @@ rte_flow_query(uint8_t port_id,
                           NULL, rte_strerror(ENOTSUP));
        return -rte_errno;
 }
+
+/**
+ * Parse the rule to see if it is a ethertype rule.
+ * And get the ethertype filter info BTW.
+ */
+int
+cons_parse_ethertype_filter(const struct rte_flow_attr *attr,
+                           const struct rte_flow_item *pattern,
+                           const struct rte_flow_action *actions,
+                           struct rte_eth_ethertype_filter *filter,
+                           struct rte_flow_error *error)
+{
+       const struct rte_flow_item *item;
+       const struct rte_flow_action *act;
+       const struct rte_flow_item_eth *eth_spec;
+       const struct rte_flow_item_eth *eth_mask;
+       const struct rte_flow_action_queue *act_q;
+       uint32_t i, j;
+
+       /************************************************
+        * parse pattern
+        ************************************************/
+       i = 0;
+
+       /* The first not void item should be MAC. */
+       PATTERN_SKIP_VOID(filter, struct rte_eth_ethertype_filter,
+                         RTE_FLOW_ERROR_TYPE_ITEM_NUM);
+       if (item->type != RTE_FLOW_ITEM_TYPE_ETH) {
+               error->type = RTE_FLOW_ERROR_TYPE_ITEM;
+               return -EINVAL;
+       }
+
+       /* Get the MAC info. */
+       if (!item->spec || !item->mask) {
+               error->type = RTE_FLOW_ERROR_TYPE_ITEM;
+               return -EINVAL;
+       }
+
+       eth_spec = (const struct rte_flow_item_eth *)item->spec;
+       eth_mask = (const struct rte_flow_item_eth *)item->mask;
+       /**
+        * Source MAC address must be masked.
+        * Destination MAC address must be totally masked or not.
+        */
+       if (eth_mask->src.addr_bytes[0] ||
+           (eth_mask->dst.addr_bytes[0] != 0xFF &&
+            eth_mask->dst.addr_bytes[0])) {
+               error->type = RTE_FLOW_ERROR_TYPE_ITEM;
+               return -EINVAL;
+       }
+
+       for (j = 1; j < ETHER_ADDR_LEN; j++) {
+               if (eth_mask->src.addr_bytes[j] !=
+                   eth_mask->src.addr_bytes[0] ||
+                   eth_mask->dst.addr_bytes[j] !=
+                   eth_mask->dst.addr_bytes[0]) {
+                       error->type = RTE_FLOW_ERROR_TYPE_ITEM;
+                       return -EINVAL;
+               }
+       }
+
+       if ((eth_mask->type & 0xFFFF) != 0xFFFF) {
+               error->type = RTE_FLOW_ERROR_TYPE_ITEM;
+               return -EINVAL;
+       }
+
+       if (eth_mask->dst.addr_bytes[0]) {
+               filter->mac_addr = eth_spec->dst;
+               filter->flags |= RTE_ETHTYPE_FLAGS_MAC;
+       } else {
+               filter->flags &= ~RTE_ETHTYPE_FLAGS_MAC;
+       }
+       filter->ether_type = (uint16_t)eth_spec->type;
+
+       /* Check if the next not void item is END. */
+       i++;
+       PATTERN_SKIP_VOID(filter, struct rte_eth_ethertype_filter,
+                         RTE_FLOW_ERROR_TYPE_ITEM_NUM);
+       if (item->type != RTE_FLOW_ITEM_TYPE_END) {
+               error->type = RTE_FLOW_ERROR_TYPE_ITEM;
+               return -EINVAL;
+       }
+
+       /************************************************
+        * parse action
+        ************************************************/
+       i = 0;
+
+       /* Check if the first not void action is QUEUE or DROP. */
+       ACTION_SKIP_VOID(filter, struct rte_eth_ethertype_filter,
+                        RTE_FLOW_ERROR_TYPE_ACTION_NUM);
+       if (act->type != RTE_FLOW_ACTION_TYPE_QUEUE &&
+           act->type != RTE_FLOW_ACTION_TYPE_DROP) {
+               error->type = RTE_FLOW_ERROR_TYPE_ACTION;
+               return -EINVAL;
+       }
+
+       if (act->type == RTE_FLOW_ACTION_TYPE_QUEUE) {
+               act_q = (const struct rte_flow_action_queue *)act->conf;
+               filter->queue = act_q->index;
+       } else {
+               filter->flags |= RTE_ETHTYPE_FLAGS_DROP;
+       }
+
+       /* Check if the next not void item is END */
+       i++;
+       ACTION_SKIP_VOID(filter, struct rte_eth_ethertype_filter,
+                        RTE_FLOW_ERROR_TYPE_ACTION_NUM);
+       if (act->type != RTE_FLOW_ACTION_TYPE_END) {
+               error->type = RTE_FLOW_ERROR_TYPE_ACTION;
+               return -EINVAL;
+       }
+
+       /************************************************
+        * parse attr
+        ************************************************/
+       /* Must be input direction */
+       if (!attr->ingress) {
+               error->type = RTE_FLOW_ERROR_TYPE_ATTR_INGRESS;
+               return -EINVAL;
+       }
+
+       /* Not supported */
+       if (attr->egress) {
+               error->type = RTE_FLOW_ERROR_TYPE_ATTR_EGRESS;
+               return -EINVAL;
+       }
+
+       /* Not supported */
+       if (attr->priority) {
+               error->type = RTE_FLOW_ERROR_TYPE_ATTR_PRIORITY;
+               return -EINVAL;
+       }
+
+       return 0;
+}
diff --git a/lib/librte_ether/rte_flow_driver.h 
b/lib/librte_ether/rte_flow_driver.h
index a88c621..2760c74 100644
--- a/lib/librte_ether/rte_flow_driver.h
+++ b/lib/librte_ether/rte_flow_driver.h
@@ -170,6 +170,40 @@ rte_flow_error_set(struct rte_flow_error *error,
 const struct rte_flow_ops *
 rte_flow_ops_get(uint8_t port_id, struct rte_flow_error *error);
 
+int cons_parse_ethertype_filter(const struct rte_flow_attr *attr,
+                           const struct rte_flow_item *pattern,
+                           const struct rte_flow_action *actions,
+                           struct rte_eth_ethertype_filter *filter,
+                           struct rte_flow_error *error);
+
+#define PATTERN_SKIP_VOID(filter, filter_struct, error_type)           \
+       do {                                                            \
+               if (!pattern) {                                         \
+                       memset(filter, 0, sizeof(filter_struct));       \
+                       error->type = error_type;                       \
+                       return -EINVAL;                                 \
+               }                                                       \
+               item = pattern + i;                                     \
+               while (item->type == RTE_FLOW_ITEM_TYPE_VOID) {         \
+                       i++;                                            \
+                       item = pattern + i;                             \
+               }                                                       \
+       } while (0)
+
+#define ACTION_SKIP_VOID(filter, filter_struct, error_type)            \
+       do {                                                            \
+               if (!actions) {                                         \
+                       memset(filter, 0, sizeof(filter_struct));       \
+                       error->type = error_type;                       \
+                       return -EINVAL;                                 \
+               }                                                       \
+               act = actions + i;                                      \
+               while (act->type == RTE_FLOW_ACTION_TYPE_VOID) {        \
+                       i++;                                            \
+                       act = actions + i;                              \
+               }                                                       \
+       } while (0)
+
 #ifdef __cplusplus
 }
 #endif
-- 
2.5.5

Reply via email to