mlx5e-updates-2018-05-14
Misc update for mlx5e netdevice driver From Gal Pressman: - Remove MLX5E_TEST_BIT macros and use test_bit instead - Use __set_bit when possible From Eran Ben Elisha: - Improve debug print on initial RX posting timeout From Or Gerlitz: - Support offloaded TC flows with no matches on headers - mlx5e TC cleanups Trivial cleanups From Roi, Tariq and Saeed: - Use bool as return type for mlx5e_xdp_handle - Use u8 instead of int for LRO number of segments - Skip redundant checks when providing NUD lastuse feedback - Remove redundant vport context vlan update -----BEGIN PGP SIGNATURE----- iQEcBAABAgAGBQJa+gseAAoJEEg/ir3gV/o+m54H/1dMnavEL5kBr4KlLMO1AYrI PL+BeOyVyOkXE5h4IJm070SPukV79SoC3ntjj3KsRBw65WhLmo0Lw10GeDwXove1 BZ+mvNG7kvTZgXG1LfR2R6wvFrum2bcj1h5A4+/BQA9Zur0PusWbZvQ+5s3vQRRX TqapkcitAKPxeWPm8YOGsKxiVfnwVgX1C/gE2Jr05aV8veuWF2QlmrAkm38oOasG 5rZ5fM3YQwaXJrBRg2uI5merIi5sU0GTVbMCdQ8gcS3YHVXDNJxOm60QnT6cVGPi eZzIPrU7iksWvYdZ7AR3mqnuoobbgBbbPu36qTyQNJJR+28JJpaTVshnpEhvg1Y= =9qrA -----END PGP SIGNATURE----- Merge tag 'mlx5e-updates-2018-05-14' of git://git.kernel.org/pub/scm/linux/kernel/git/saeed/linux Saeed Mahameed says: ==================== mlx5e-updates-2018-05-14 Misc update for mlx5e netdevice driver From Gal Pressman: - Remove MLX5E_TEST_BIT macros and use test_bit instead - Use __set_bit when possible From Eran Ben Elisha: - Improve debug print on initial RX posting timeout From Or Gerlitz: - Support offloaded TC flows with no matches on headers - mlx5e TC cleanups Trivial cleanups From Roi, Tariq and Saeed: - Use bool as return type for mlx5e_xdp_handle - Use u8 instead of int for LRO number of segments - Skip redundant checks when providing NUD lastuse feedback - Remove redundant vport context vlan update ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
7d6541fba1
@ -288,8 +288,6 @@ enum {
|
|||||||
MLX5E_RQ_STATE_AM,
|
MLX5E_RQ_STATE_AM,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MLX5E_TEST_BIT(state, nr) (state & BIT(nr))
|
|
||||||
|
|
||||||
struct mlx5e_cq {
|
struct mlx5e_cq {
|
||||||
/* data path - accessed per cqe */
|
/* data path - accessed per cqe */
|
||||||
struct mlx5_cqwq wq;
|
struct mlx5_cqwq wq;
|
||||||
|
@ -49,7 +49,7 @@ static inline struct sk_buff *mlx5e_accel_handle_tx(struct sk_buff *skb,
|
|||||||
u16 *pi)
|
u16 *pi)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_MLX5_EN_TLS
|
#ifdef CONFIG_MLX5_EN_TLS
|
||||||
if (sq->state & BIT(MLX5E_SQ_STATE_TLS)) {
|
if (test_bit(MLX5E_SQ_STATE_TLS, &sq->state)) {
|
||||||
skb = mlx5e_tls_handle_tx_skb(dev, sq, skb, wqe, pi);
|
skb = mlx5e_tls_handle_tx_skb(dev, sq, skb, wqe, pi);
|
||||||
if (unlikely(!skb))
|
if (unlikely(!skb))
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -57,7 +57,7 @@ static inline struct sk_buff *mlx5e_accel_handle_tx(struct sk_buff *skb,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_MLX5_EN_IPSEC
|
#ifdef CONFIG_MLX5_EN_IPSEC
|
||||||
if (sq->state & BIT(MLX5E_SQ_STATE_IPSEC)) {
|
if (test_bit(MLX5E_SQ_STATE_IPSEC, &sq->state)) {
|
||||||
skb = mlx5e_ipsec_handle_tx_skb(dev, *wqe, skb);
|
skb = mlx5e_ipsec_handle_tx_skb(dev, *wqe, skb);
|
||||||
if (unlikely(!skb))
|
if (unlikely(!skb))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -277,7 +277,6 @@ static void mlx5e_del_vlan_rule(struct mlx5e_priv *priv,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MLX5E_VLAN_RULE_TYPE_MATCH_CTAG_VID:
|
case MLX5E_VLAN_RULE_TYPE_MATCH_CTAG_VID:
|
||||||
mlx5e_vport_context_update_vlans(priv);
|
|
||||||
if (priv->fs.vlan.active_cvlans_rule[vid]) {
|
if (priv->fs.vlan.active_cvlans_rule[vid]) {
|
||||||
mlx5_del_flow_rules(priv->fs.vlan.active_cvlans_rule[vid]);
|
mlx5_del_flow_rules(priv->fs.vlan.active_cvlans_rule[vid]);
|
||||||
priv->fs.vlan.active_cvlans_rule[vid] = NULL;
|
priv->fs.vlan.active_cvlans_rule[vid] = NULL;
|
||||||
|
@ -747,23 +747,24 @@ static void mlx5e_destroy_rq(struct mlx5e_rq *rq)
|
|||||||
mlx5_core_destroy_rq(rq->mdev, rq->rqn);
|
mlx5_core_destroy_rq(rq->mdev, rq->rqn);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mlx5e_wait_for_min_rx_wqes(struct mlx5e_rq *rq)
|
static int mlx5e_wait_for_min_rx_wqes(struct mlx5e_rq *rq, int wait_time)
|
||||||
{
|
{
|
||||||
unsigned long exp_time = jiffies + msecs_to_jiffies(20000);
|
unsigned long exp_time = jiffies + msecs_to_jiffies(wait_time);
|
||||||
struct mlx5e_channel *c = rq->channel;
|
struct mlx5e_channel *c = rq->channel;
|
||||||
|
|
||||||
struct mlx5_wq_ll *wq = &rq->wq;
|
struct mlx5_wq_ll *wq = &rq->wq;
|
||||||
u16 min_wqes = mlx5_min_rx_wqes(rq->wq_type, mlx5_wq_ll_get_size(wq));
|
u16 min_wqes = mlx5_min_rx_wqes(rq->wq_type, mlx5_wq_ll_get_size(wq));
|
||||||
|
|
||||||
while (time_before(jiffies, exp_time)) {
|
do {
|
||||||
if (wq->cur_sz >= min_wqes)
|
if (wq->cur_sz >= min_wqes)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
msleep(20);
|
msleep(20);
|
||||||
}
|
} while (time_before(jiffies, exp_time));
|
||||||
|
|
||||||
|
netdev_warn(c->netdev, "Failed to get min RX wqes on Channel[%d] RQN[0x%x] wq cur_sz(%d) min_rx_wqes(%d)\n",
|
||||||
|
c->ix, rq->rqn, wq->cur_sz, min_wqes);
|
||||||
|
|
||||||
netdev_warn(c->netdev, "Failed to get min RX wqes on RQN[0x%x] wq cur_sz(%d) min_rx_wqes(%d)\n",
|
|
||||||
rq->rqn, wq->cur_sz, min_wqes);
|
|
||||||
return -ETIMEDOUT;
|
return -ETIMEDOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -819,7 +820,7 @@ static int mlx5e_open_rq(struct mlx5e_channel *c,
|
|||||||
goto err_destroy_rq;
|
goto err_destroy_rq;
|
||||||
|
|
||||||
if (params->rx_dim_enabled)
|
if (params->rx_dim_enabled)
|
||||||
c->rq.state |= BIT(MLX5E_RQ_STATE_AM);
|
__set_bit(MLX5E_RQ_STATE_AM, &c->rq.state);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -2128,13 +2129,11 @@ static int mlx5e_wait_channels_min_rx_wqes(struct mlx5e_channels *chs)
|
|||||||
int err = 0;
|
int err = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < chs->num; i++) {
|
for (i = 0; i < chs->num; i++)
|
||||||
err = mlx5e_wait_for_min_rx_wqes(&chs->c[i]->rq);
|
err |= mlx5e_wait_for_min_rx_wqes(&chs->c[i]->rq,
|
||||||
if (err)
|
err ? 0 : 20000);
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return err;
|
return err ? -ETIMEDOUT : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mlx5e_deactivate_channels(struct mlx5e_channels *chs)
|
static void mlx5e_deactivate_channels(struct mlx5e_channels *chs)
|
||||||
|
@ -681,8 +681,8 @@ static int mlx5e_rep_open(struct net_device *dev)
|
|||||||
goto unlock;
|
goto unlock;
|
||||||
|
|
||||||
if (!mlx5_modify_vport_admin_state(priv->mdev,
|
if (!mlx5_modify_vport_admin_state(priv->mdev,
|
||||||
MLX5_QUERY_VPORT_STATE_IN_OP_MOD_ESW_VPORT,
|
MLX5_QUERY_VPORT_STATE_IN_OP_MOD_ESW_VPORT,
|
||||||
rep->vport, MLX5_ESW_VPORT_ADMIN_STATE_UP))
|
rep->vport, MLX5_ESW_VPORT_ADMIN_STATE_UP))
|
||||||
netif_carrier_on(dev);
|
netif_carrier_on(dev);
|
||||||
|
|
||||||
unlock:
|
unlock:
|
||||||
@ -699,8 +699,8 @@ static int mlx5e_rep_close(struct net_device *dev)
|
|||||||
|
|
||||||
mutex_lock(&priv->state_lock);
|
mutex_lock(&priv->state_lock);
|
||||||
mlx5_modify_vport_admin_state(priv->mdev,
|
mlx5_modify_vport_admin_state(priv->mdev,
|
||||||
MLX5_QUERY_VPORT_STATE_IN_OP_MOD_ESW_VPORT,
|
MLX5_QUERY_VPORT_STATE_IN_OP_MOD_ESW_VPORT,
|
||||||
rep->vport, MLX5_ESW_VPORT_ADMIN_STATE_DOWN);
|
rep->vport, MLX5_ESW_VPORT_ADMIN_STATE_DOWN);
|
||||||
ret = mlx5e_close_locked(dev);
|
ret = mlx5e_close_locked(dev);
|
||||||
mutex_unlock(&priv->state_lock);
|
mutex_unlock(&priv->state_lock);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -450,7 +450,7 @@ bool mlx5e_post_rx_wqes(struct mlx5e_rq *rq)
|
|||||||
struct mlx5_wq_ll *wq = &rq->wq;
|
struct mlx5_wq_ll *wq = &rq->wq;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (unlikely(!MLX5E_TEST_BIT(rq->state, MLX5E_RQ_STATE_ENABLED)))
|
if (unlikely(!test_bit(MLX5E_RQ_STATE_ENABLED, &rq->state)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (mlx5_wq_ll_is_full(wq))
|
if (mlx5_wq_ll_is_full(wq))
|
||||||
@ -508,7 +508,7 @@ static void mlx5e_poll_ico_cq(struct mlx5e_cq *cq, struct mlx5e_rq *rq)
|
|||||||
struct mlx5e_icosq *sq = container_of(cq, struct mlx5e_icosq, cq);
|
struct mlx5e_icosq *sq = container_of(cq, struct mlx5e_icosq, cq);
|
||||||
struct mlx5_cqe64 *cqe;
|
struct mlx5_cqe64 *cqe;
|
||||||
|
|
||||||
if (unlikely(!MLX5E_TEST_BIT(sq->state, MLX5E_SQ_STATE_ENABLED)))
|
if (unlikely(!test_bit(MLX5E_SQ_STATE_ENABLED, &sq->state)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cqe = mlx5_cqwq_get_cqe(&cq->wq);
|
cqe = mlx5_cqwq_get_cqe(&cq->wq);
|
||||||
@ -525,7 +525,7 @@ bool mlx5e_post_rx_mpwqes(struct mlx5e_rq *rq)
|
|||||||
{
|
{
|
||||||
struct mlx5_wq_ll *wq = &rq->wq;
|
struct mlx5_wq_ll *wq = &rq->wq;
|
||||||
|
|
||||||
if (unlikely(!MLX5E_TEST_BIT(rq->state, MLX5E_RQ_STATE_ENABLED)))
|
if (unlikely(!test_bit(MLX5E_RQ_STATE_ENABLED, &rq->state)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
mlx5e_poll_ico_cq(&rq->channel->icosq.cq, rq);
|
mlx5e_poll_ico_cq(&rq->channel->icosq.cq, rq);
|
||||||
@ -681,11 +681,10 @@ static inline void mlx5e_build_rx_skb(struct mlx5_cqe64 *cqe,
|
|||||||
struct mlx5e_rq *rq,
|
struct mlx5e_rq *rq,
|
||||||
struct sk_buff *skb)
|
struct sk_buff *skb)
|
||||||
{
|
{
|
||||||
|
u8 lro_num_seg = be32_to_cpu(cqe->srqn) >> 24;
|
||||||
struct net_device *netdev = rq->netdev;
|
struct net_device *netdev = rq->netdev;
|
||||||
int lro_num_seg;
|
|
||||||
|
|
||||||
skb->mac_len = ETH_HLEN;
|
skb->mac_len = ETH_HLEN;
|
||||||
lro_num_seg = be32_to_cpu(cqe->srqn) >> 24;
|
|
||||||
if (lro_num_seg > 1) {
|
if (lro_num_seg > 1) {
|
||||||
mlx5e_lro_update_hdr(skb, cqe, cqe_bcnt);
|
mlx5e_lro_update_hdr(skb, cqe, cqe_bcnt);
|
||||||
skb_shinfo(skb)->gso_size = DIV_ROUND_UP(cqe_bcnt, lro_num_seg);
|
skb_shinfo(skb)->gso_size = DIV_ROUND_UP(cqe_bcnt, lro_num_seg);
|
||||||
@ -808,9 +807,9 @@ static inline bool mlx5e_xmit_xdp_frame(struct mlx5e_rq *rq,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* returns true if packet was consumed by xdp */
|
/* returns true if packet was consumed by xdp */
|
||||||
static inline int mlx5e_xdp_handle(struct mlx5e_rq *rq,
|
static inline bool mlx5e_xdp_handle(struct mlx5e_rq *rq,
|
||||||
struct mlx5e_dma_info *di,
|
struct mlx5e_dma_info *di,
|
||||||
void *va, u16 *rx_headroom, u32 *len)
|
void *va, u16 *rx_headroom, u32 *len)
|
||||||
{
|
{
|
||||||
struct bpf_prog *prog = READ_ONCE(rq->xdp_prog);
|
struct bpf_prog *prog = READ_ONCE(rq->xdp_prog);
|
||||||
struct xdp_buff xdp;
|
struct xdp_buff xdp;
|
||||||
@ -1133,7 +1132,7 @@ int mlx5e_poll_rx_cq(struct mlx5e_cq *cq, int budget)
|
|||||||
struct mlx5_cqe64 *cqe;
|
struct mlx5_cqe64 *cqe;
|
||||||
int work_done = 0;
|
int work_done = 0;
|
||||||
|
|
||||||
if (unlikely(!MLX5E_TEST_BIT(rq->state, MLX5E_RQ_STATE_ENABLED)))
|
if (unlikely(!test_bit(MLX5E_RQ_STATE_ENABLED, &rq->state)))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (cq->decmprs_left)
|
if (cq->decmprs_left)
|
||||||
@ -1186,7 +1185,7 @@ bool mlx5e_poll_xdpsq_cq(struct mlx5e_cq *cq)
|
|||||||
|
|
||||||
sq = container_of(cq, struct mlx5e_xdpsq, cq);
|
sq = container_of(cq, struct mlx5e_xdpsq, cq);
|
||||||
|
|
||||||
if (unlikely(!MLX5E_TEST_BIT(sq->state, MLX5E_SQ_STATE_ENABLED)))
|
if (unlikely(!test_bit(MLX5E_SQ_STATE_ENABLED, &sq->state)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
cqe = mlx5_cqwq_get_cqe(&cq->wq);
|
cqe = mlx5_cqwq_get_cqe(&cq->wq);
|
||||||
|
@ -58,6 +58,7 @@ struct mlx5_nic_flow_attr {
|
|||||||
u32 flow_tag;
|
u32 flow_tag;
|
||||||
u32 mod_hdr_id;
|
u32 mod_hdr_id;
|
||||||
u32 hairpin_tirn;
|
u32 hairpin_tirn;
|
||||||
|
u8 match_level;
|
||||||
struct mlx5_flow_table *hairpin_ft;
|
struct mlx5_flow_table *hairpin_ft;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -97,7 +98,7 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#define MLX5E_TC_TABLE_NUM_GROUPS 4
|
#define MLX5E_TC_TABLE_NUM_GROUPS 4
|
||||||
#define MLX5E_TC_TABLE_MAX_GROUP_SIZE (1 << 16)
|
#define MLX5E_TC_TABLE_MAX_GROUP_SIZE BIT(16)
|
||||||
|
|
||||||
struct mlx5e_hairpin {
|
struct mlx5e_hairpin {
|
||||||
struct mlx5_hairpin *pair;
|
struct mlx5_hairpin *pair;
|
||||||
@ -753,7 +754,9 @@ mlx5e_tc_add_nic_flow(struct mlx5e_priv *priv,
|
|||||||
table_created = true;
|
table_created = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
parse_attr->spec.match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
|
if (attr->match_level != MLX5_MATCH_NONE)
|
||||||
|
parse_attr->spec.match_criteria_enable = MLX5_MATCH_OUTER_HEADERS;
|
||||||
|
|
||||||
rule = mlx5_add_flow_rules(priv->fs.tc.t, &parse_attr->spec,
|
rule = mlx5_add_flow_rules(priv->fs.tc.t, &parse_attr->spec,
|
||||||
&flow_act, dest, dest_ix);
|
&flow_act, dest, dest_ix);
|
||||||
|
|
||||||
@ -789,7 +792,7 @@ static void mlx5e_tc_del_nic_flow(struct mlx5e_priv *priv,
|
|||||||
mlx5_del_flow_rules(flow->rule);
|
mlx5_del_flow_rules(flow->rule);
|
||||||
mlx5_fc_destroy(priv->mdev, counter);
|
mlx5_fc_destroy(priv->mdev, counter);
|
||||||
|
|
||||||
if (!mlx5e_tc_num_filters(priv) && (priv->fs.tc.t)) {
|
if (!mlx5e_tc_num_filters(priv) && priv->fs.tc.t) {
|
||||||
mlx5_destroy_flow_table(priv->fs.tc.t);
|
mlx5_destroy_flow_table(priv->fs.tc.t);
|
||||||
priv->fs.tc.t = NULL;
|
priv->fs.tc.t = NULL;
|
||||||
}
|
}
|
||||||
@ -982,6 +985,8 @@ void mlx5e_tc_update_neigh_used_value(struct mlx5e_neigh_hash_entry *nhe)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (neigh_used)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (neigh_used) {
|
if (neigh_used) {
|
||||||
@ -1190,7 +1195,7 @@ vxlan_match_offload_err:
|
|||||||
static int __parse_cls_flower(struct mlx5e_priv *priv,
|
static int __parse_cls_flower(struct mlx5e_priv *priv,
|
||||||
struct mlx5_flow_spec *spec,
|
struct mlx5_flow_spec *spec,
|
||||||
struct tc_cls_flower_offload *f,
|
struct tc_cls_flower_offload *f,
|
||||||
u8 *min_inline)
|
u8 *match_level)
|
||||||
{
|
{
|
||||||
void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
|
void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
|
||||||
outer_headers);
|
outer_headers);
|
||||||
@ -1199,7 +1204,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
|
|||||||
u16 addr_type = 0;
|
u16 addr_type = 0;
|
||||||
u8 ip_proto = 0;
|
u8 ip_proto = 0;
|
||||||
|
|
||||||
*min_inline = MLX5_INLINE_MODE_L2;
|
*match_level = MLX5_MATCH_NONE;
|
||||||
|
|
||||||
if (f->dissector->used_keys &
|
if (f->dissector->used_keys &
|
||||||
~(BIT(FLOW_DISSECTOR_KEY_CONTROL) |
|
~(BIT(FLOW_DISSECTOR_KEY_CONTROL) |
|
||||||
@ -1249,58 +1254,6 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
|
|||||||
inner_headers);
|
inner_headers);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_CONTROL)) {
|
|
||||||
struct flow_dissector_key_control *key =
|
|
||||||
skb_flow_dissector_target(f->dissector,
|
|
||||||
FLOW_DISSECTOR_KEY_CONTROL,
|
|
||||||
f->key);
|
|
||||||
|
|
||||||
struct flow_dissector_key_control *mask =
|
|
||||||
skb_flow_dissector_target(f->dissector,
|
|
||||||
FLOW_DISSECTOR_KEY_CONTROL,
|
|
||||||
f->mask);
|
|
||||||
addr_type = key->addr_type;
|
|
||||||
|
|
||||||
/* the HW doesn't support frag first/later */
|
|
||||||
if (mask->flags & FLOW_DIS_FIRST_FRAG)
|
|
||||||
return -EOPNOTSUPP;
|
|
||||||
|
|
||||||
if (mask->flags & FLOW_DIS_IS_FRAGMENT) {
|
|
||||||
MLX5_SET(fte_match_set_lyr_2_4, headers_c, frag, 1);
|
|
||||||
MLX5_SET(fte_match_set_lyr_2_4, headers_v, frag,
|
|
||||||
key->flags & FLOW_DIS_IS_FRAGMENT);
|
|
||||||
|
|
||||||
/* the HW doesn't need L3 inline to match on frag=no */
|
|
||||||
if (key->flags & FLOW_DIS_IS_FRAGMENT)
|
|
||||||
*min_inline = MLX5_INLINE_MODE_IP;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_BASIC)) {
|
|
||||||
struct flow_dissector_key_basic *key =
|
|
||||||
skb_flow_dissector_target(f->dissector,
|
|
||||||
FLOW_DISSECTOR_KEY_BASIC,
|
|
||||||
f->key);
|
|
||||||
struct flow_dissector_key_basic *mask =
|
|
||||||
skb_flow_dissector_target(f->dissector,
|
|
||||||
FLOW_DISSECTOR_KEY_BASIC,
|
|
||||||
f->mask);
|
|
||||||
ip_proto = key->ip_proto;
|
|
||||||
|
|
||||||
MLX5_SET(fte_match_set_lyr_2_4, headers_c, ethertype,
|
|
||||||
ntohs(mask->n_proto));
|
|
||||||
MLX5_SET(fte_match_set_lyr_2_4, headers_v, ethertype,
|
|
||||||
ntohs(key->n_proto));
|
|
||||||
|
|
||||||
MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_protocol,
|
|
||||||
mask->ip_proto);
|
|
||||||
MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
|
|
||||||
key->ip_proto);
|
|
||||||
|
|
||||||
if (mask->ip_proto)
|
|
||||||
*min_inline = MLX5_INLINE_MODE_IP;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
|
if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
|
||||||
struct flow_dissector_key_eth_addrs *key =
|
struct flow_dissector_key_eth_addrs *key =
|
||||||
skb_flow_dissector_target(f->dissector,
|
skb_flow_dissector_target(f->dissector,
|
||||||
@ -1324,6 +1277,9 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
|
|||||||
ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
|
ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v,
|
||||||
smac_47_16),
|
smac_47_16),
|
||||||
key->src);
|
key->src);
|
||||||
|
|
||||||
|
if (!is_zero_ether_addr(mask->src) || !is_zero_ether_addr(mask->dst))
|
||||||
|
*match_level = MLX5_MATCH_L2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_VLAN)) {
|
if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_VLAN)) {
|
||||||
@ -1344,9 +1300,79 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
|
|||||||
|
|
||||||
MLX5_SET(fte_match_set_lyr_2_4, headers_c, first_prio, mask->vlan_priority);
|
MLX5_SET(fte_match_set_lyr_2_4, headers_c, first_prio, mask->vlan_priority);
|
||||||
MLX5_SET(fte_match_set_lyr_2_4, headers_v, first_prio, key->vlan_priority);
|
MLX5_SET(fte_match_set_lyr_2_4, headers_v, first_prio, key->vlan_priority);
|
||||||
|
|
||||||
|
*match_level = MLX5_MATCH_L2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_BASIC)) {
|
||||||
|
struct flow_dissector_key_basic *key =
|
||||||
|
skb_flow_dissector_target(f->dissector,
|
||||||
|
FLOW_DISSECTOR_KEY_BASIC,
|
||||||
|
f->key);
|
||||||
|
struct flow_dissector_key_basic *mask =
|
||||||
|
skb_flow_dissector_target(f->dissector,
|
||||||
|
FLOW_DISSECTOR_KEY_BASIC,
|
||||||
|
f->mask);
|
||||||
|
MLX5_SET(fte_match_set_lyr_2_4, headers_c, ethertype,
|
||||||
|
ntohs(mask->n_proto));
|
||||||
|
MLX5_SET(fte_match_set_lyr_2_4, headers_v, ethertype,
|
||||||
|
ntohs(key->n_proto));
|
||||||
|
|
||||||
|
if (mask->n_proto)
|
||||||
|
*match_level = MLX5_MATCH_L2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_CONTROL)) {
|
||||||
|
struct flow_dissector_key_control *key =
|
||||||
|
skb_flow_dissector_target(f->dissector,
|
||||||
|
FLOW_DISSECTOR_KEY_CONTROL,
|
||||||
|
f->key);
|
||||||
|
|
||||||
|
struct flow_dissector_key_control *mask =
|
||||||
|
skb_flow_dissector_target(f->dissector,
|
||||||
|
FLOW_DISSECTOR_KEY_CONTROL,
|
||||||
|
f->mask);
|
||||||
|
addr_type = key->addr_type;
|
||||||
|
|
||||||
|
/* the HW doesn't support frag first/later */
|
||||||
|
if (mask->flags & FLOW_DIS_FIRST_FRAG)
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
if (mask->flags & FLOW_DIS_IS_FRAGMENT) {
|
||||||
|
MLX5_SET(fte_match_set_lyr_2_4, headers_c, frag, 1);
|
||||||
|
MLX5_SET(fte_match_set_lyr_2_4, headers_v, frag,
|
||||||
|
key->flags & FLOW_DIS_IS_FRAGMENT);
|
||||||
|
|
||||||
|
/* the HW doesn't need L3 inline to match on frag=no */
|
||||||
|
if (!(key->flags & FLOW_DIS_IS_FRAGMENT))
|
||||||
|
*match_level = MLX5_INLINE_MODE_L2;
|
||||||
|
/* *** L2 attributes parsing up to here *** */
|
||||||
|
else
|
||||||
|
*match_level = MLX5_INLINE_MODE_IP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_BASIC)) {
|
||||||
|
struct flow_dissector_key_basic *key =
|
||||||
|
skb_flow_dissector_target(f->dissector,
|
||||||
|
FLOW_DISSECTOR_KEY_BASIC,
|
||||||
|
f->key);
|
||||||
|
struct flow_dissector_key_basic *mask =
|
||||||
|
skb_flow_dissector_target(f->dissector,
|
||||||
|
FLOW_DISSECTOR_KEY_BASIC,
|
||||||
|
f->mask);
|
||||||
|
ip_proto = key->ip_proto;
|
||||||
|
|
||||||
|
MLX5_SET(fte_match_set_lyr_2_4, headers_c, ip_protocol,
|
||||||
|
mask->ip_proto);
|
||||||
|
MLX5_SET(fte_match_set_lyr_2_4, headers_v, ip_protocol,
|
||||||
|
key->ip_proto);
|
||||||
|
|
||||||
|
if (mask->ip_proto)
|
||||||
|
*match_level = MLX5_MATCH_L3;
|
||||||
|
}
|
||||||
|
|
||||||
if (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) {
|
if (addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) {
|
||||||
struct flow_dissector_key_ipv4_addrs *key =
|
struct flow_dissector_key_ipv4_addrs *key =
|
||||||
skb_flow_dissector_target(f->dissector,
|
skb_flow_dissector_target(f->dissector,
|
||||||
@ -1371,7 +1397,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
|
|||||||
&key->dst, sizeof(key->dst));
|
&key->dst, sizeof(key->dst));
|
||||||
|
|
||||||
if (mask->src || mask->dst)
|
if (mask->src || mask->dst)
|
||||||
*min_inline = MLX5_INLINE_MODE_IP;
|
*match_level = MLX5_MATCH_L3;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) {
|
if (addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) {
|
||||||
@ -1400,7 +1426,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
|
|||||||
|
|
||||||
if (ipv6_addr_type(&mask->src) != IPV6_ADDR_ANY ||
|
if (ipv6_addr_type(&mask->src) != IPV6_ADDR_ANY ||
|
||||||
ipv6_addr_type(&mask->dst) != IPV6_ADDR_ANY)
|
ipv6_addr_type(&mask->dst) != IPV6_ADDR_ANY)
|
||||||
*min_inline = MLX5_INLINE_MODE_IP;
|
*match_level = MLX5_MATCH_L3;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_IP)) {
|
if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_IP)) {
|
||||||
@ -1428,9 +1454,11 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
|
|||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
if (mask->tos || mask->ttl)
|
if (mask->tos || mask->ttl)
|
||||||
*min_inline = MLX5_INLINE_MODE_IP;
|
*match_level = MLX5_MATCH_L3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* *** L3 attributes parsing up to here *** */
|
||||||
|
|
||||||
if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_PORTS)) {
|
if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_PORTS)) {
|
||||||
struct flow_dissector_key_ports *key =
|
struct flow_dissector_key_ports *key =
|
||||||
skb_flow_dissector_target(f->dissector,
|
skb_flow_dissector_target(f->dissector,
|
||||||
@ -1471,7 +1499,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mask->src || mask->dst)
|
if (mask->src || mask->dst)
|
||||||
*min_inline = MLX5_INLINE_MODE_TCP_UDP;
|
*match_level = MLX5_MATCH_L4;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_TCP)) {
|
if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_TCP)) {
|
||||||
@ -1490,7 +1518,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
|
|||||||
ntohs(key->flags));
|
ntohs(key->flags));
|
||||||
|
|
||||||
if (mask->flags)
|
if (mask->flags)
|
||||||
*min_inline = MLX5_INLINE_MODE_TCP_UDP;
|
*match_level = MLX5_MATCH_L4;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -1505,23 +1533,28 @@ static int parse_cls_flower(struct mlx5e_priv *priv,
|
|||||||
struct mlx5_eswitch *esw = dev->priv.eswitch;
|
struct mlx5_eswitch *esw = dev->priv.eswitch;
|
||||||
struct mlx5e_rep_priv *rpriv = priv->ppriv;
|
struct mlx5e_rep_priv *rpriv = priv->ppriv;
|
||||||
struct mlx5_eswitch_rep *rep;
|
struct mlx5_eswitch_rep *rep;
|
||||||
u8 min_inline;
|
u8 match_level;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
err = __parse_cls_flower(priv, spec, f, &min_inline);
|
err = __parse_cls_flower(priv, spec, f, &match_level);
|
||||||
|
|
||||||
if (!err && (flow->flags & MLX5E_TC_FLOW_ESWITCH)) {
|
if (!err && (flow->flags & MLX5E_TC_FLOW_ESWITCH)) {
|
||||||
rep = rpriv->rep;
|
rep = rpriv->rep;
|
||||||
if (rep->vport != FDB_UPLINK_VPORT &&
|
if (rep->vport != FDB_UPLINK_VPORT &&
|
||||||
(esw->offloads.inline_mode != MLX5_INLINE_MODE_NONE &&
|
(esw->offloads.inline_mode != MLX5_INLINE_MODE_NONE &&
|
||||||
esw->offloads.inline_mode < min_inline)) {
|
esw->offloads.inline_mode < match_level)) {
|
||||||
netdev_warn(priv->netdev,
|
netdev_warn(priv->netdev,
|
||||||
"Flow is not offloaded due to min inline setting, required %d actual %d\n",
|
"Flow is not offloaded due to min inline setting, required %d actual %d\n",
|
||||||
min_inline, esw->offloads.inline_mode);
|
match_level, esw->offloads.inline_mode);
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (flow->flags & MLX5E_TC_FLOW_ESWITCH)
|
||||||
|
flow->esw_attr->match_level = match_level;
|
||||||
|
else
|
||||||
|
flow->nic_attr->match_level = match_level;
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1577,7 +1610,6 @@ struct mlx5_fields {
|
|||||||
{MLX5_ACTION_IN_FIELD_OUT_ ## fw_field, size, offsetof(struct pedit_headers, field) + (off)}
|
{MLX5_ACTION_IN_FIELD_OUT_ ## fw_field, size, offsetof(struct pedit_headers, field) + (off)}
|
||||||
|
|
||||||
static struct mlx5_fields fields[] = {
|
static struct mlx5_fields fields[] = {
|
||||||
OFFLOAD(DMAC_47_16, 4, eth.h_dest[0], 0),
|
|
||||||
OFFLOAD(DMAC_47_16, 4, eth.h_dest[0], 0),
|
OFFLOAD(DMAC_47_16, 4, eth.h_dest[0], 0),
|
||||||
OFFLOAD(DMAC_15_0, 2, eth.h_dest[4], 0),
|
OFFLOAD(DMAC_15_0, 2, eth.h_dest[4], 0),
|
||||||
OFFLOAD(SMAC_47_16, 4, eth.h_source[0], 0),
|
OFFLOAD(SMAC_47_16, 4, eth.h_source[0], 0),
|
||||||
@ -1764,12 +1796,12 @@ static int parse_tc_pedit_action(struct mlx5e_priv *priv,
|
|||||||
err = -EOPNOTSUPP; /* can't be all optimistic */
|
err = -EOPNOTSUPP; /* can't be all optimistic */
|
||||||
|
|
||||||
if (htype == TCA_PEDIT_KEY_EX_HDR_TYPE_NETWORK) {
|
if (htype == TCA_PEDIT_KEY_EX_HDR_TYPE_NETWORK) {
|
||||||
printk(KERN_WARNING "mlx5: legacy pedit isn't offloaded\n");
|
netdev_warn(priv->netdev, "legacy pedit isn't offloaded\n");
|
||||||
goto out_err;
|
goto out_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmd != TCA_PEDIT_KEY_EX_CMD_SET && cmd != TCA_PEDIT_KEY_EX_CMD_ADD) {
|
if (cmd != TCA_PEDIT_KEY_EX_CMD_SET && cmd != TCA_PEDIT_KEY_EX_CMD_ADD) {
|
||||||
printk(KERN_WARNING "mlx5: pedit cmd %d isn't offloaded\n", cmd);
|
netdev_warn(priv->netdev, "pedit cmd %d isn't offloaded\n", cmd);
|
||||||
goto out_err;
|
goto out_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1793,8 +1825,7 @@ static int parse_tc_pedit_action(struct mlx5e_priv *priv,
|
|||||||
for (cmd = 0; cmd < __PEDIT_CMD_MAX; cmd++) {
|
for (cmd = 0; cmd < __PEDIT_CMD_MAX; cmd++) {
|
||||||
cmd_masks = &masks[cmd];
|
cmd_masks = &masks[cmd];
|
||||||
if (memcmp(cmd_masks, &zero_masks, sizeof(zero_masks))) {
|
if (memcmp(cmd_masks, &zero_masks, sizeof(zero_masks))) {
|
||||||
printk(KERN_WARNING "mlx5: attempt to offload an unsupported field (cmd %d)\n",
|
netdev_warn(priv->netdev, "attempt to offload an unsupported field (cmd %d)\n", cmd);
|
||||||
cmd);
|
|
||||||
print_hex_dump(KERN_WARNING, "mask: ", DUMP_PREFIX_ADDRESS,
|
print_hex_dump(KERN_WARNING, "mask: ", DUMP_PREFIX_ADDRESS,
|
||||||
16, 1, cmd_masks, sizeof(zero_masks), true);
|
16, 1, cmd_masks, sizeof(zero_masks), true);
|
||||||
err = -EOPNOTSUPP;
|
err = -EOPNOTSUPP;
|
||||||
@ -1917,21 +1948,21 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
|
|||||||
struct mlx5_nic_flow_attr *attr = flow->nic_attr;
|
struct mlx5_nic_flow_attr *attr = flow->nic_attr;
|
||||||
const struct tc_action *a;
|
const struct tc_action *a;
|
||||||
LIST_HEAD(actions);
|
LIST_HEAD(actions);
|
||||||
|
u32 action = 0;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
if (!tcf_exts_has_actions(exts))
|
if (!tcf_exts_has_actions(exts))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
attr->flow_tag = MLX5_FS_DEFAULT_FLOW_TAG;
|
attr->flow_tag = MLX5_FS_DEFAULT_FLOW_TAG;
|
||||||
attr->action = 0;
|
|
||||||
|
|
||||||
tcf_exts_to_list(exts, &actions);
|
tcf_exts_to_list(exts, &actions);
|
||||||
list_for_each_entry(a, &actions, list) {
|
list_for_each_entry(a, &actions, list) {
|
||||||
if (is_tcf_gact_shot(a)) {
|
if (is_tcf_gact_shot(a)) {
|
||||||
attr->action |= MLX5_FLOW_CONTEXT_ACTION_DROP;
|
action |= MLX5_FLOW_CONTEXT_ACTION_DROP;
|
||||||
if (MLX5_CAP_FLOWTABLE(priv->mdev,
|
if (MLX5_CAP_FLOWTABLE(priv->mdev,
|
||||||
flow_table_properties_nic_receive.flow_counter))
|
flow_table_properties_nic_receive.flow_counter))
|
||||||
attr->action |= MLX5_FLOW_CONTEXT_ACTION_COUNT;
|
action |= MLX5_FLOW_CONTEXT_ACTION_COUNT;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1941,13 +1972,13 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
|
|||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
attr->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR |
|
action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR |
|
||||||
MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
|
MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_tcf_csum(a)) {
|
if (is_tcf_csum(a)) {
|
||||||
if (csum_offload_supported(priv, attr->action,
|
if (csum_offload_supported(priv, action,
|
||||||
tcf_csum_update_flags(a)))
|
tcf_csum_update_flags(a)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -1961,8 +1992,8 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
|
|||||||
same_hw_devs(priv, netdev_priv(peer_dev))) {
|
same_hw_devs(priv, netdev_priv(peer_dev))) {
|
||||||
parse_attr->mirred_ifindex = peer_dev->ifindex;
|
parse_attr->mirred_ifindex = peer_dev->ifindex;
|
||||||
flow->flags |= MLX5E_TC_FLOW_HAIRPIN;
|
flow->flags |= MLX5E_TC_FLOW_HAIRPIN;
|
||||||
attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
|
action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
|
||||||
MLX5_FLOW_CONTEXT_ACTION_COUNT;
|
MLX5_FLOW_CONTEXT_ACTION_COUNT;
|
||||||
} else {
|
} else {
|
||||||
netdev_warn(priv->netdev, "device %s not on same HW, can't offload\n",
|
netdev_warn(priv->netdev, "device %s not on same HW, can't offload\n",
|
||||||
peer_dev->name);
|
peer_dev->name);
|
||||||
@ -1981,13 +2012,14 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
|
|||||||
}
|
}
|
||||||
|
|
||||||
attr->flow_tag = mark;
|
attr->flow_tag = mark;
|
||||||
attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
|
action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
attr->action = action;
|
||||||
if (!actions_match_supported(priv, exts, parse_attr, flow))
|
if (!actions_match_supported(priv, exts, parse_attr, flow))
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
@ -2459,34 +2491,35 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
|
|||||||
const struct tc_action *a;
|
const struct tc_action *a;
|
||||||
LIST_HEAD(actions);
|
LIST_HEAD(actions);
|
||||||
bool encap = false;
|
bool encap = false;
|
||||||
int err = 0;
|
u32 action = 0;
|
||||||
|
|
||||||
if (!tcf_exts_has_actions(exts))
|
if (!tcf_exts_has_actions(exts))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
memset(attr, 0, sizeof(*attr));
|
|
||||||
attr->in_rep = rpriv->rep;
|
attr->in_rep = rpriv->rep;
|
||||||
|
|
||||||
tcf_exts_to_list(exts, &actions);
|
tcf_exts_to_list(exts, &actions);
|
||||||
list_for_each_entry(a, &actions, list) {
|
list_for_each_entry(a, &actions, list) {
|
||||||
if (is_tcf_gact_shot(a)) {
|
if (is_tcf_gact_shot(a)) {
|
||||||
attr->action |= MLX5_FLOW_CONTEXT_ACTION_DROP |
|
action |= MLX5_FLOW_CONTEXT_ACTION_DROP |
|
||||||
MLX5_FLOW_CONTEXT_ACTION_COUNT;
|
MLX5_FLOW_CONTEXT_ACTION_COUNT;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_tcf_pedit(a)) {
|
if (is_tcf_pedit(a)) {
|
||||||
|
int err;
|
||||||
|
|
||||||
err = parse_tc_pedit_action(priv, a, MLX5_FLOW_NAMESPACE_FDB,
|
err = parse_tc_pedit_action(priv, a, MLX5_FLOW_NAMESPACE_FDB,
|
||||||
parse_attr);
|
parse_attr);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
attr->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
|
action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_tcf_csum(a)) {
|
if (is_tcf_csum(a)) {
|
||||||
if (csum_offload_supported(priv, attr->action,
|
if (csum_offload_supported(priv, action,
|
||||||
tcf_csum_update_flags(a)))
|
tcf_csum_update_flags(a)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -2501,8 +2534,8 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
|
|||||||
|
|
||||||
if (switchdev_port_same_parent_id(priv->netdev,
|
if (switchdev_port_same_parent_id(priv->netdev,
|
||||||
out_dev)) {
|
out_dev)) {
|
||||||
attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
|
action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
|
||||||
MLX5_FLOW_CONTEXT_ACTION_COUNT;
|
MLX5_FLOW_CONTEXT_ACTION_COUNT;
|
||||||
out_priv = netdev_priv(out_dev);
|
out_priv = netdev_priv(out_dev);
|
||||||
rpriv = out_priv->ppriv;
|
rpriv = out_priv->ppriv;
|
||||||
attr->out_rep = rpriv->rep;
|
attr->out_rep = rpriv->rep;
|
||||||
@ -2510,9 +2543,9 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
|
|||||||
parse_attr->mirred_ifindex = out_dev->ifindex;
|
parse_attr->mirred_ifindex = out_dev->ifindex;
|
||||||
parse_attr->tun_info = *info;
|
parse_attr->tun_info = *info;
|
||||||
attr->parse_attr = parse_attr;
|
attr->parse_attr = parse_attr;
|
||||||
attr->action |= MLX5_FLOW_CONTEXT_ACTION_ENCAP |
|
action |= MLX5_FLOW_CONTEXT_ACTION_ENCAP |
|
||||||
MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
|
MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
|
||||||
MLX5_FLOW_CONTEXT_ACTION_COUNT;
|
MLX5_FLOW_CONTEXT_ACTION_COUNT;
|
||||||
/* attr->out_rep is resolved when we handle encap */
|
/* attr->out_rep is resolved when we handle encap */
|
||||||
} else {
|
} else {
|
||||||
pr_err("devices %s %s not on same switch HW, can't offload forwarding\n",
|
pr_err("devices %s %s not on same switch HW, can't offload forwarding\n",
|
||||||
@ -2533,9 +2566,9 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
|
|||||||
|
|
||||||
if (is_tcf_vlan(a)) {
|
if (is_tcf_vlan(a)) {
|
||||||
if (tcf_vlan_action(a) == TCA_VLAN_ACT_POP) {
|
if (tcf_vlan_action(a) == TCA_VLAN_ACT_POP) {
|
||||||
attr->action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_POP;
|
action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_POP;
|
||||||
} else if (tcf_vlan_action(a) == TCA_VLAN_ACT_PUSH) {
|
} else if (tcf_vlan_action(a) == TCA_VLAN_ACT_PUSH) {
|
||||||
attr->action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH;
|
action |= MLX5_FLOW_CONTEXT_ACTION_VLAN_PUSH;
|
||||||
attr->vlan_vid = tcf_vlan_push_vid(a);
|
attr->vlan_vid = tcf_vlan_push_vid(a);
|
||||||
if (mlx5_eswitch_vlan_actions_supported(priv->mdev)) {
|
if (mlx5_eswitch_vlan_actions_supported(priv->mdev)) {
|
||||||
attr->vlan_prio = tcf_vlan_push_prio(a);
|
attr->vlan_prio = tcf_vlan_push_prio(a);
|
||||||
@ -2553,17 +2586,18 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (is_tcf_tunnel_release(a)) {
|
if (is_tcf_tunnel_release(a)) {
|
||||||
attr->action |= MLX5_FLOW_CONTEXT_ACTION_DECAP;
|
action |= MLX5_FLOW_CONTEXT_ACTION_DECAP;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
attr->action = action;
|
||||||
if (!actions_match_supported(priv, exts, parse_attr, flow))
|
if (!actions_match_supported(priv, exts, parse_attr, flow))
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
return err;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mlx5e_configure_flower(struct mlx5e_priv *priv,
|
int mlx5e_configure_flower(struct mlx5e_priv *priv,
|
||||||
|
@ -450,7 +450,7 @@ bool mlx5e_poll_tx_cq(struct mlx5e_cq *cq, int napi_budget)
|
|||||||
|
|
||||||
sq = container_of(cq, struct mlx5e_txqsq, cq);
|
sq = container_of(cq, struct mlx5e_txqsq, cq);
|
||||||
|
|
||||||
if (unlikely(!MLX5E_TEST_BIT(sq->state, MLX5E_SQ_STATE_ENABLED)))
|
if (unlikely(!test_bit(MLX5E_SQ_STATE_ENABLED, &sq->state)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
cqe = mlx5_cqwq_get_cqe(&cq->wq);
|
cqe = mlx5_cqwq_get_cqe(&cq->wq);
|
||||||
|
@ -48,7 +48,7 @@ static void mlx5e_handle_tx_dim(struct mlx5e_txqsq *sq)
|
|||||||
{
|
{
|
||||||
struct net_dim_sample dim_sample;
|
struct net_dim_sample dim_sample;
|
||||||
|
|
||||||
if (unlikely(!MLX5E_TEST_BIT(sq->state, MLX5E_SQ_STATE_AM)))
|
if (unlikely(!test_bit(MLX5E_SQ_STATE_AM, &sq->state)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
net_dim_sample(sq->cq.event_ctr, sq->stats.packets, sq->stats.bytes,
|
net_dim_sample(sq->cq.event_ctr, sq->stats.packets, sq->stats.bytes,
|
||||||
@ -60,7 +60,7 @@ static void mlx5e_handle_rx_dim(struct mlx5e_rq *rq)
|
|||||||
{
|
{
|
||||||
struct net_dim_sample dim_sample;
|
struct net_dim_sample dim_sample;
|
||||||
|
|
||||||
if (unlikely(!MLX5E_TEST_BIT(rq->state, MLX5E_RQ_STATE_AM)))
|
if (unlikely(!test_bit(MLX5E_RQ_STATE_AM, &rq->state)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
net_dim_sample(rq->cq.event_ctr, rq->stats.packets, rq->stats.bytes,
|
net_dim_sample(rq->cq.event_ctr, rq->stats.packets, rq->stats.bytes,
|
||||||
|
@ -227,6 +227,13 @@ enum {
|
|||||||
SET_VLAN_INSERT = BIT(1)
|
SET_VLAN_INSERT = BIT(1)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum mlx5_flow_match_level {
|
||||||
|
MLX5_MATCH_NONE = MLX5_INLINE_MODE_NONE,
|
||||||
|
MLX5_MATCH_L2 = MLX5_INLINE_MODE_L2,
|
||||||
|
MLX5_MATCH_L3 = MLX5_INLINE_MODE_IP,
|
||||||
|
MLX5_MATCH_L4 = MLX5_INLINE_MODE_TCP_UDP,
|
||||||
|
};
|
||||||
|
|
||||||
struct mlx5_esw_flow_attr {
|
struct mlx5_esw_flow_attr {
|
||||||
struct mlx5_eswitch_rep *in_rep;
|
struct mlx5_eswitch_rep *in_rep;
|
||||||
struct mlx5_eswitch_rep *out_rep;
|
struct mlx5_eswitch_rep *out_rep;
|
||||||
@ -238,6 +245,7 @@ struct mlx5_esw_flow_attr {
|
|||||||
bool vlan_handled;
|
bool vlan_handled;
|
||||||
u32 encap_id;
|
u32 encap_id;
|
||||||
u32 mod_hdr_id;
|
u32 mod_hdr_id;
|
||||||
|
u8 match_level;
|
||||||
struct mlx5e_tc_flow_parse_attr *parse_attr;
|
struct mlx5e_tc_flow_parse_attr *parse_attr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -91,8 +91,12 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw,
|
|||||||
misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters);
|
misc = MLX5_ADDR_OF(fte_match_param, spec->match_criteria, misc_parameters);
|
||||||
MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
|
MLX5_SET_TO_ONES(fte_match_set_misc, misc, source_port);
|
||||||
|
|
||||||
spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS |
|
if (attr->match_level == MLX5_MATCH_NONE)
|
||||||
MLX5_MATCH_MISC_PARAMETERS;
|
spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
|
||||||
|
else
|
||||||
|
spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS |
|
||||||
|
MLX5_MATCH_MISC_PARAMETERS;
|
||||||
|
|
||||||
if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_DECAP)
|
if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_DECAP)
|
||||||
spec->match_criteria_enable |= MLX5_MATCH_INNER_HEADERS;
|
spec->match_criteria_enable |= MLX5_MATCH_INNER_HEADERS;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user