[dpdk-dev] [PATCH 10/24] ethdev: parse ethertype filter
Beilei Xing
beilei.xing at intel.com
Fri Dec 2 12:53:31 CET 2016
Check if the rule is a ethertype rule, and get the ethertype
info BTW.
Signed-off-by: Wenzhuo Lu <wenzhuo.lu at intel.com>
Signed-off-by: Beilei Xing <beilei.xing at 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
More information about the dev
mailing list