From 4bcbbb430fc999c3980f07d4490b2a0dfabb059c Mon Sep 17 00:00:00 2001 From: Hyong Youb Kim Date: Tue, 14 Apr 2020 18:06:37 -0700 Subject: [PATCH] net/enic: fix flow action reordering The current implementation produces wrong ordering for several cases like these: 1. mark, decap, steer Current: steer, mark, decap Correct: mark, steer, decap 2. decap, steer, steer Current: steer, steer, decap Correct: steer, decap, steer Simplify the logic and swap 1st steer and decap. Also, allow just one decap action per flow. Fixes: ea7768b5bba8 ("net/enic: add flow implementation based on Flow Manager API") Cc: stable@dpdk.org Signed-off-by: Hyong Youb Kim Signed-off-by: John Daley --- drivers/net/enic/enic_fm_flow.c | 63 +++++++++++++++------------------ 1 file changed, 29 insertions(+), 34 deletions(-) diff --git a/drivers/net/enic/enic_fm_flow.c b/drivers/net/enic/enic_fm_flow.c index d815f369ed..8d715fc436 100644 --- a/drivers/net/enic/enic_fm_flow.c +++ b/drivers/net/enic/enic_fm_flow.c @@ -870,46 +870,36 @@ enic_fm_append_action_op(struct enic_flowman *fm, return 0; } -/* Steer operations need to appear before other ops */ +/* NIC requires that 1st steer appear before decap. + * Correct example: steer, decap, steer, steer, ... + */ static void enic_fm_reorder_action_op(struct enic_flowman *fm) { - struct fm_action_op *dst, *dst_head, *src, *src_head; + struct fm_action_op *op, *steer, *decap; + struct fm_action_op tmp_op; ENICPMD_FUNC_TRACE(); - /* Move steer ops to the front. */ - src = fm->action.fma_action_ops; - src_head = src; - dst = fm->action_tmp.fma_action_ops; - dst_head = dst; - /* Copy steer ops to tmp */ - while (src->fa_op != FMOP_END) { - if (src->fa_op == FMOP_RQ_STEER) { - ENICPMD_LOG(DEBUG, "move op: %ld -> dst %ld", - (long)(src - src_head), - (long)(dst - dst_head)); - *dst = *src; - dst++; - } - src++; - } - /* Then append non-steer ops */ - src = src_head; - while (src->fa_op != FMOP_END) { - if (src->fa_op != FMOP_RQ_STEER) { - ENICPMD_LOG(DEBUG, "move op: %ld -> dst %ld", - (long)(src - src_head), - (long)(dst - dst_head)); - *dst = *src; - dst++; - } - src++; + /* Find 1st steer and decap */ + op = fm->action.fma_action_ops; + steer = NULL; + decap = NULL; + while (op->fa_op != FMOP_END) { + if (!decap && op->fa_op == FMOP_DECAP_NOSTRIP) + decap = op; + else if (!steer && op->fa_op == FMOP_RQ_STEER) + steer = op; + op++; + } + /* If decap is before steer, swap */ + if (steer && decap && decap < steer) { + op = fm->action.fma_action_ops; + ENICPMD_LOG(DEBUG, "swap decap %ld <-> steer %ld", + (long)(decap - op), (long)(steer - op)); + tmp_op = *decap; + *decap = *steer; + *steer = tmp_op; } - /* Copy END */ - *dst = *src; - /* Finally replace the original action with the reordered one */ - memcpy(fm->action.fma_action_ops, fm->action_tmp.fma_action_ops, - sizeof(fm->action.fma_action_ops)); } /* VXLAN decap is done via flowman compound action */ @@ -1100,6 +1090,7 @@ enic_fm_copy_action(struct enic_flowman *fm, PASSTHRU = 1 << 2, COUNT = 1 << 3, ENCAP = 1 << 4, + DECAP = 1 << 5, }; struct fm_tcam_match_entry *fmt; struct fm_action_op fm_op; @@ -1282,6 +1273,10 @@ enic_fm_copy_action(struct enic_flowman *fm, break; } case RTE_FLOW_ACTION_TYPE_VXLAN_DECAP: { + if (overlap & DECAP) + goto unsupported; + overlap |= DECAP; + ret = enic_fm_copy_vxlan_decap(fm, fmt, actions, error); if (ret != 0) -- 2.20.1