#define IXGBE_MIN_N_TUPLE_PRIO 1
#define IXGBE_MAX_N_TUPLE_PRIO 7
#define IXGBE_MAX_FLX_SOURCE_OFF 62
-#define NEXT_ITEM_OF_PATTERN(item, pattern, index)\
- do { \
- item = pattern + index;\
- while (item->type == RTE_FLOW_ITEM_TYPE_VOID) {\
- index++; \
- item = pattern + index; \
- } \
- } while (0)
-
-#define NEXT_ITEM_OF_ACTION(act, actions, index)\
- do { \
- act = actions + index; \
- while (act->type == RTE_FLOW_ACTION_TYPE_VOID) {\
- index++; \
- act = actions + index; \
- } \
- } while (0)
+
+/**
+ * Endless loop will never happen with below assumption
+ * 1. there is at least one no-void item(END)
+ * 2. cur is before END.
+ */
+static inline
+const struct rte_flow_item *next_no_void_pattern(
+ const struct rte_flow_item pattern[],
+ const struct rte_flow_item *cur)
+{
+ const struct rte_flow_item *next =
+ cur ? cur + 1 : &pattern[0];
+ while (1) {
+ if (next->type != RTE_FLOW_ITEM_TYPE_VOID)
+ return next;
+ next++;
+ }
+}
+
+static inline
+const struct rte_flow_action *next_no_void_action(
+ const struct rte_flow_action actions[],
+ const struct rte_flow_action *cur)
+{
+ const struct rte_flow_action *next =
+ cur ? cur + 1 : &actions[0];
+ while (1) {
+ if (next->type != RTE_FLOW_ACTION_TYPE_VOID)
+ return next;
+ next++;
+ }
+}
/**
* Please aware there's an asumption for all the parsers.
const struct rte_flow_item_udp *udp_mask;
const struct rte_flow_item_sctp *sctp_spec;
const struct rte_flow_item_sctp *sctp_mask;
- uint32_t index;
if (!pattern) {
rte_flow_error_set(error,
return -rte_errno;
}
- /* parse pattern */
- index = 0;
-
/* the first not void item can be MAC or IPv4 */
- NEXT_ITEM_OF_PATTERN(item, pattern, index);
+ item = next_no_void_pattern(pattern, NULL);
if (item->type != RTE_FLOW_ITEM_TYPE_ETH &&
item->type != RTE_FLOW_ITEM_TYPE_IPV4) {
return -rte_errno;
}
/* check if the next not void item is IPv4 */
- index++;
- NEXT_ITEM_OF_PATTERN(item, pattern, index);
+ item = next_no_void_pattern(pattern, item);
if (item->type != RTE_FLOW_ITEM_TYPE_IPV4) {
rte_flow_error_set(error,
EINVAL, RTE_FLOW_ERROR_TYPE_ITEM,
filter->proto = ipv4_spec->hdr.next_proto_id;
/* check if the next not void item is TCP or UDP */
- index++;
- NEXT_ITEM_OF_PATTERN(item, pattern, index);
+ item = next_no_void_pattern(pattern, item);
if (item->type != RTE_FLOW_ITEM_TYPE_TCP &&
item->type != RTE_FLOW_ITEM_TYPE_UDP &&
item->type != RTE_FLOW_ITEM_TYPE_SCTP) {
}
/* check if the next not void item is END */
- index++;
- NEXT_ITEM_OF_PATTERN(item, pattern, index);
+ item = next_no_void_pattern(pattern, item);
if (item->type != RTE_FLOW_ITEM_TYPE_END) {
memset(filter, 0, sizeof(struct rte_eth_ntuple_filter));
rte_flow_error_set(error, EINVAL,
return -rte_errno;
}
- /* parse action */
- index = 0;
-
/**
* n-tuple only supports forwarding,
* check if the first not void action is QUEUE.
*/
- NEXT_ITEM_OF_ACTION(act, actions, index);
+ act = next_no_void_action(actions, NULL);
if (act->type != RTE_FLOW_ACTION_TYPE_QUEUE) {
memset(filter, 0, sizeof(struct rte_eth_ntuple_filter));
rte_flow_error_set(error, EINVAL,
((const struct rte_flow_action_queue *)act->conf)->index;
/* check if the next not void item is END */
- index++;
- NEXT_ITEM_OF_ACTION(act, actions, index);
+ act = next_no_void_action(actions, act);
if (act->type != RTE_FLOW_ACTION_TYPE_END) {
memset(filter, 0, sizeof(struct rte_eth_ntuple_filter));
rte_flow_error_set(error, EINVAL,
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 index;
if (!pattern) {
rte_flow_error_set(error, EINVAL,
return -rte_errno;
}
- /* Parse pattern */
- index = 0;
-
+ item = next_no_void_pattern(pattern, NULL);
/* The first non-void item should be MAC. */
- item = pattern + index;
- while (item->type == RTE_FLOW_ITEM_TYPE_VOID) {
- index++;
- item = pattern + index;
- }
if (item->type != RTE_FLOW_ITEM_TYPE_ETH) {
rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ITEM,
filter->ether_type = rte_be_to_cpu_16(eth_spec->type);
/* Check if the next non-void item is END. */
- index++;
- item = pattern + index;
- while (item->type == RTE_FLOW_ITEM_TYPE_VOID) {
- index++;
- item = pattern + index;
- }
+ item = next_no_void_pattern(pattern, item);
if (item->type != RTE_FLOW_ITEM_TYPE_END) {
rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ITEM,
/* Parse action */
- index = 0;
- /* Check if the first non-void action is QUEUE or DROP. */
- act = actions + index;
- while (act->type == RTE_FLOW_ACTION_TYPE_VOID) {
- index++;
- act = actions + index;
- }
+ act = next_no_void_action(actions, NULL);
if (act->type != RTE_FLOW_ACTION_TYPE_QUEUE &&
act->type != RTE_FLOW_ACTION_TYPE_DROP) {
rte_flow_error_set(error, EINVAL,
}
/* Check if the next non-void item is END */
- index++;
- act = actions + index;
- while (act->type == RTE_FLOW_ACTION_TYPE_VOID) {
- index++;
- act = actions + index;
- }
+ act = next_no_void_action(actions, act);
if (act->type != RTE_FLOW_ACTION_TYPE_END) {
rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ACTION,
const struct rte_flow_item_tcp *tcp_spec;
const struct rte_flow_item_tcp *tcp_mask;
const struct rte_flow_action_queue *act_q;
- uint32_t index;
if (!pattern) {
rte_flow_error_set(error, EINVAL,
return -rte_errno;
}
- /* parse pattern */
- index = 0;
/* the first not void item should be MAC or IPv4 or IPv6 or TCP */
- NEXT_ITEM_OF_PATTERN(item, pattern, index);
+ item = next_no_void_pattern(pattern, NULL);
if (item->type != RTE_FLOW_ITEM_TYPE_ETH &&
item->type != RTE_FLOW_ITEM_TYPE_IPV4 &&
item->type != RTE_FLOW_ITEM_TYPE_IPV6 &&
}
/* check if the next not void item is IPv4 or IPv6 */
- index++;
- NEXT_ITEM_OF_PATTERN(item, pattern, index);
+ item = next_no_void_pattern(pattern, item);
if (item->type != RTE_FLOW_ITEM_TYPE_IPV4 &&
item->type != RTE_FLOW_ITEM_TYPE_IPV6) {
rte_flow_error_set(error, EINVAL,
}
/* check if the next not void item is TCP */
- index++;
- NEXT_ITEM_OF_PATTERN(item, pattern, index);
+ item = next_no_void_pattern(pattern, item);
if (item->type != RTE_FLOW_ITEM_TYPE_TCP) {
rte_flow_error_set(error, EINVAL,
RTE_FLOW_ERROR_TYPE_ITEM,
}
/* check if the next not void item is END */
- index++;
- NEXT_ITEM_OF_PATTERN(item, pattern, index);
+ item = next_no_void_pattern(pattern, item);
if (item->type != RTE_FLOW_ITEM_TYPE_END) {
memset(filter, 0, sizeof(struct rte_eth_syn_filter));
rte_flow_error_set(error, EINVAL,
return -rte_errno;
}
- /* parse action */
- index = 0;
-
/* check if the first not void action is QUEUE. */
- NEXT_ITEM_OF_ACTION(act, actions, index);
+ act = next_no_void_action(actions, NULL);
if (act->type != RTE_FLOW_ACTION_TYPE_QUEUE) {
memset(filter, 0, sizeof(struct rte_eth_syn_filter));
rte_flow_error_set(error, EINVAL,
}
/* check if the next not void item is END */
- index++;
- NEXT_ITEM_OF_ACTION(act, actions, index);
+ act = next_no_void_action(actions, act);
if (act->type != RTE_FLOW_ACTION_TYPE_END) {
memset(filter, 0, sizeof(struct rte_eth_syn_filter));
rte_flow_error_set(error, EINVAL,
const struct rte_flow_item_e_tag *e_tag_mask;
const struct rte_flow_action *act;
const struct rte_flow_action_queue *act_q;
- uint32_t index;
if (!pattern) {
rte_flow_error_set(error, EINVAL,
NULL, "NULL attribute.");
return -rte_errno;
}
- /* parse pattern */
- index = 0;
/* The first not void item should be e-tag. */
- NEXT_ITEM_OF_PATTERN(item, pattern, index);
+ item = next_no_void_pattern(pattern, NULL);
if (item->type != RTE_FLOW_ITEM_TYPE_E_TAG) {
memset(filter, 0, sizeof(struct rte_eth_l2_tunnel_conf));
rte_flow_error_set(error, EINVAL,
filter->tunnel_id = rte_be_to_cpu_16(e_tag_spec->rsvd_grp_ecid_b);
/* check if the next not void item is END */
- index++;
- NEXT_ITEM_OF_PATTERN(item, pattern, index);
+ item = next_no_void_pattern(pattern, item);
if (item->type != RTE_FLOW_ITEM_TYPE_END) {
memset(filter, 0, sizeof(struct rte_eth_l2_tunnel_conf));
rte_flow_error_set(error, EINVAL,
return -rte_errno;
}
- /* parse action */
- index = 0;
-
/* check if the first not void action is QUEUE. */
- NEXT_ITEM_OF_ACTION(act, actions, index);
+ act = next_no_void_action(actions, NULL);
if (act->type != RTE_FLOW_ACTION_TYPE_QUEUE) {
memset(filter, 0, sizeof(struct rte_eth_l2_tunnel_conf));
rte_flow_error_set(error, EINVAL,
filter->pool = act_q->index;
/* check if the next not void item is END */
- index++;
- NEXT_ITEM_OF_ACTION(act, actions, index);
+ act = next_no_void_action(actions, act);
if (act->type != RTE_FLOW_ACTION_TYPE_END) {
memset(filter, 0, sizeof(struct rte_eth_l2_tunnel_conf));
rte_flow_error_set(error, EINVAL,
const struct rte_flow_action *act;
const struct rte_flow_action_queue *act_q;
const struct rte_flow_action_mark *mark;
- uint32_t index;
/* parse attr */
/* must be input direction */
return -rte_errno;
}
- /* parse action */
- index = 0;
-
/* check if the first not void action is QUEUE or DROP. */
- NEXT_ITEM_OF_ACTION(act, actions, index);
+ act = next_no_void_action(actions, NULL);
if (act->type != RTE_FLOW_ACTION_TYPE_QUEUE &&
act->type != RTE_FLOW_ACTION_TYPE_DROP) {
memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
}
/* check if the next not void item is MARK */
- index++;
- NEXT_ITEM_OF_ACTION(act, actions, index);
+ act = next_no_void_action(actions, act);
if ((act->type != RTE_FLOW_ACTION_TYPE_MARK) &&
(act->type != RTE_FLOW_ACTION_TYPE_END)) {
memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
if (act->type == RTE_FLOW_ACTION_TYPE_MARK) {
mark = (const struct rte_flow_action_mark *)act->conf;
rule->soft_id = mark->id;
- index++;
- NEXT_ITEM_OF_ACTION(act, actions, index);
+ act = next_no_void_action(actions, act);
}
/* check if the next not void item is END */
const struct rte_flow_item_raw *raw_mask;
const struct rte_flow_item_raw *raw_spec;
- uint32_t index, j;
+ uint32_t j;
if (!pattern) {
rte_flow_error_set(error, EINVAL,
rule->mask.vlan_tci_mask = 0;
rule->mask.flex_bytes_mask = 0;
- /* parse pattern */
- index = 0;
-
/**
* The first not void item should be
* MAC or IPv4 or TCP or UDP or SCTP.
*/
- NEXT_ITEM_OF_PATTERN(item, pattern, index);
+ item = next_no_void_pattern(pattern, NULL);
if (item->type != RTE_FLOW_ITEM_TYPE_ETH &&
item->type != RTE_FLOW_ITEM_TYPE_IPV4 &&
item->type != RTE_FLOW_ITEM_TYPE_TCP &&
* Check if the next not void item is vlan or ipv4.
* IPv6 is not supported.
*/
- index++;
- NEXT_ITEM_OF_PATTERN(item, pattern, index);
+ item = next_no_void_pattern(pattern, item);
if (rule->mode == RTE_FDIR_MODE_PERFECT_MAC_VLAN) {
if (item->type != RTE_FLOW_ITEM_TYPE_VLAN) {
memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
/* More than one tags are not supported. */
/* Next not void item must be END */
- index++;
- NEXT_ITEM_OF_PATTERN(item, pattern, index);
+ item = next_no_void_pattern(pattern, item);
if (item->type != RTE_FLOW_ITEM_TYPE_END) {
memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
rte_flow_error_set(error, EINVAL,
* Check if the next not void item is
* TCP or UDP or SCTP or END.
*/
- index++;
- NEXT_ITEM_OF_PATTERN(item, pattern, index);
+ item = next_no_void_pattern(pattern, item);
if (item->type != RTE_FLOW_ITEM_TYPE_TCP &&
item->type != RTE_FLOW_ITEM_TYPE_UDP &&
item->type != RTE_FLOW_ITEM_TYPE_SCTP &&
tcp_spec->hdr.dst_port;
}
- index++;
- NEXT_ITEM_OF_PATTERN(item, pattern, index);
+ item = next_no_void_pattern(pattern, item);
if (item->type != RTE_FLOW_ITEM_TYPE_RAW &&
item->type != RTE_FLOW_ITEM_TYPE_END) {
memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
udp_spec->hdr.dst_port;
}
- index++;
- NEXT_ITEM_OF_PATTERN(item, pattern, index);
+ item = next_no_void_pattern(pattern, item);
if (item->type != RTE_FLOW_ITEM_TYPE_RAW &&
item->type != RTE_FLOW_ITEM_TYPE_END) {
memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
sctp_spec->hdr.dst_port;
}
- index++;
- NEXT_ITEM_OF_PATTERN(item, pattern, index);
+ item = next_no_void_pattern(pattern, item);
if (item->type != RTE_FLOW_ITEM_TYPE_RAW &&
item->type != RTE_FLOW_ITEM_TYPE_END) {
memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
if (item->type != RTE_FLOW_ITEM_TYPE_END) {
/* check if the next not void item is END */
- index++;
- NEXT_ITEM_OF_PATTERN(item, pattern, index);
+ item = next_no_void_pattern(pattern, item);
if (item->type != RTE_FLOW_ITEM_TYPE_END) {
memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
rte_flow_error_set(error, EINVAL,
const struct rte_flow_item_eth *eth_mask;
const struct rte_flow_item_vlan *vlan_spec;
const struct rte_flow_item_vlan *vlan_mask;
- uint32_t index, j;
+ uint32_t j;
if (!pattern) {
rte_flow_error_set(error, EINVAL,
memset(&rule->mask, 0xFF, sizeof(struct ixgbe_hw_fdir_mask));
rule->mask.vlan_tci_mask = 0;
- /* parse pattern */
- index = 0;
-
/**
* The first not void item should be
* MAC or IPv4 or IPv6 or UDP or VxLAN.
*/
- NEXT_ITEM_OF_PATTERN(item, pattern, index);
+ item = next_no_void_pattern(pattern, NULL);
if (item->type != RTE_FLOW_ITEM_TYPE_ETH &&
item->type != RTE_FLOW_ITEM_TYPE_IPV4 &&
item->type != RTE_FLOW_ITEM_TYPE_IPV6 &&
}
/* Check if the next not void item is IPv4 or IPv6. */
- index++;
- NEXT_ITEM_OF_PATTERN(item, pattern, index);
+ item = next_no_void_pattern(pattern, item);
if (item->type != RTE_FLOW_ITEM_TYPE_IPV4 &&
item->type != RTE_FLOW_ITEM_TYPE_IPV6) {
memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
}
/* Check if the next not void item is UDP or NVGRE. */
- index++;
- NEXT_ITEM_OF_PATTERN(item, pattern, index);
+ item = next_no_void_pattern(pattern, item);
if (item->type != RTE_FLOW_ITEM_TYPE_UDP &&
item->type != RTE_FLOW_ITEM_TYPE_NVGRE) {
memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
}
/* Check if the next not void item is VxLAN. */
- index++;
- NEXT_ITEM_OF_PATTERN(item, pattern, index);
+ item = next_no_void_pattern(pattern, item);
if (item->type != RTE_FLOW_ITEM_TYPE_VXLAN) {
memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
rte_flow_error_set(error, EINVAL,
}
/* check if the next not void item is MAC */
- index++;
- NEXT_ITEM_OF_PATTERN(item, pattern, index);
+ item = next_no_void_pattern(pattern, item);
if (item->type != RTE_FLOW_ITEM_TYPE_ETH) {
memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
rte_flow_error_set(error, EINVAL,
* Check if the next not void item is vlan or ipv4.
* IPv6 is not supported.
*/
- index++;
- NEXT_ITEM_OF_PATTERN(item, pattern, index);
+ item = next_no_void_pattern(pattern, item);
if ((item->type != RTE_FLOW_ITEM_TYPE_VLAN) &&
(item->type != RTE_FLOW_ITEM_TYPE_IPV4)) {
memset(rule, 0, sizeof(struct ixgbe_fdir_rule));
/* More than one tags are not supported. */
/* check if the next not void item is END */
- index++;
- NEXT_ITEM_OF_PATTERN(item, pattern, index);
+ item = next_no_void_pattern(pattern, item);
if (item->type != RTE_FLOW_ITEM_TYPE_END) {
memset(rule, 0, sizeof(struct ixgbe_fdir_rule));