Commit e5fe4946 authored by Aya Levin's avatar Aya Levin Committed by Saeed Mahameed

net/mlx5e: Add PTP Flow Steering support

When opening PTP channel with MLX5E_PTP_STATE_RX set, add the
corresponding flow steering rules. Capture UDP packets with destination
port 319 and L2 packets with ethertype 0x88F7 and steer them into the RQ
of the PTP channel.
Add API that manages the flow steering rules to be used in the following
patches via safe_reopen_channels mechanism.
Signed-off-by: default avatarAya Levin <ayal@nvidia.com>
Reviewed-by: default avatarTariq Toukan <tariqt@nvidia.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@nvidia.com>
parent 0f575c20
......@@ -245,6 +245,7 @@ struct mlx5e_accel_fs_tcp;
struct mlx5e_fs_udp;
struct mlx5e_fs_any;
struct mlx5e_ptp_fs;
struct mlx5e_flow_steering {
struct mlx5_flow_namespace *ns;
......@@ -266,6 +267,7 @@ struct mlx5e_flow_steering {
#endif
struct mlx5e_fs_udp *udp;
struct mlx5e_fs_any *any;
struct mlx5e_ptp_fs *ptp_fs;
};
struct ttc_params {
......
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
// Copyright (c) 2020 Mellanox Technologies
#include <linux/ptp_classify.h>
#include "en/ptp.h"
#include "en/txrx.h"
#include "en/params.h"
#include "en/fs_tt_redirect.h"
struct mlx5e_ptp_fs {
struct mlx5_flow_handle *l2_rule;
struct mlx5_flow_handle *udp_v4_rule;
struct mlx5_flow_handle *udp_v6_rule;
bool valid;
};
#define MLX5E_PTP_CHANNEL_IX 0
......@@ -573,6 +582,78 @@ static int mlx5e_ptp_set_state(struct mlx5e_ptp *c, struct mlx5e_params *params)
return bitmap_empty(c->state, MLX5E_PTP_STATE_NUM_STATES) ? -EINVAL : 0;
}
static void mlx5e_ptp_rx_unset_fs(struct mlx5e_priv *priv)
{
struct mlx5e_ptp_fs *ptp_fs = priv->fs.ptp_fs;
if (!ptp_fs->valid)
return;
mlx5e_fs_tt_redirect_del_rule(ptp_fs->l2_rule);
mlx5e_fs_tt_redirect_any_destroy(priv);
mlx5e_fs_tt_redirect_del_rule(ptp_fs->udp_v6_rule);
mlx5e_fs_tt_redirect_del_rule(ptp_fs->udp_v4_rule);
mlx5e_fs_tt_redirect_udp_destroy(priv);
ptp_fs->valid = false;
}
static int mlx5e_ptp_rx_set_fs(struct mlx5e_priv *priv)
{
struct mlx5e_ptp_fs *ptp_fs = priv->fs.ptp_fs;
struct mlx5_flow_handle *rule;
u32 tirn = priv->ptp_tir.tirn;
int err;
if (ptp_fs->valid)
return 0;
err = mlx5e_fs_tt_redirect_udp_create(priv);
if (err)
goto out_free;
rule = mlx5e_fs_tt_redirect_udp_add_rule(priv, MLX5E_TT_IPV4_UDP,
tirn, PTP_EV_PORT);
if (IS_ERR(rule)) {
err = PTR_ERR(rule);
goto out_destroy_fs_udp;
}
ptp_fs->udp_v4_rule = rule;
rule = mlx5e_fs_tt_redirect_udp_add_rule(priv, MLX5E_TT_IPV6_UDP,
tirn, PTP_EV_PORT);
if (IS_ERR(rule)) {
err = PTR_ERR(rule);
goto out_destroy_udp_v4_rule;
}
ptp_fs->udp_v6_rule = rule;
err = mlx5e_fs_tt_redirect_any_create(priv);
if (err)
goto out_destroy_udp_v6_rule;
rule = mlx5e_fs_tt_redirect_any_add_rule(priv, tirn, ETH_P_1588);
if (IS_ERR(rule)) {
err = PTR_ERR(rule);
goto out_destroy_fs_any;
}
ptp_fs->l2_rule = rule;
ptp_fs->valid = true;
return 0;
out_destroy_fs_any:
mlx5e_fs_tt_redirect_any_destroy(priv);
out_destroy_udp_v6_rule:
mlx5e_fs_tt_redirect_del_rule(ptp_fs->udp_v6_rule);
out_destroy_udp_v4_rule:
mlx5e_fs_tt_redirect_del_rule(ptp_fs->udp_v4_rule);
out_destroy_fs_udp:
mlx5e_fs_tt_redirect_udp_destroy(priv);
out_free:
return err;
}
int mlx5e_ptp_open(struct mlx5e_priv *priv, struct mlx5e_params *params,
u8 lag_port, struct mlx5e_ptp **cp)
{
......@@ -645,8 +726,10 @@ void mlx5e_ptp_activate_channel(struct mlx5e_ptp *c)
for (tc = 0; tc < c->num_tc; tc++)
mlx5e_activate_txqsq(&c->ptpsq[tc].txqsq);
}
if (test_bit(MLX5E_PTP_STATE_RX, c->state))
if (test_bit(MLX5E_PTP_STATE_RX, c->state)) {
mlx5e_ptp_rx_set_fs(c->priv);
mlx5e_activate_rq(&c->rq);
}
}
void mlx5e_ptp_deactivate_channel(struct mlx5e_ptp *c)
......@@ -672,3 +755,52 @@ int mlx5e_ptp_get_rqn(struct mlx5e_ptp *c, u32 *rqn)
*rqn = c->rq.rqn;
return 0;
}
int mlx5e_ptp_alloc_rx_fs(struct mlx5e_priv *priv)
{
struct mlx5e_ptp_fs *ptp_fs;
if (!priv->profile->rx_ptp_support)
return 0;
ptp_fs = kzalloc(sizeof(*ptp_fs), GFP_KERNEL);
if (!ptp_fs)
return -ENOMEM;
priv->fs.ptp_fs = ptp_fs;
return 0;
}
void mlx5e_ptp_free_rx_fs(struct mlx5e_priv *priv)
{
struct mlx5e_ptp_fs *ptp_fs = priv->fs.ptp_fs;
if (!priv->profile->rx_ptp_support)
return;
mlx5e_ptp_rx_unset_fs(priv);
kfree(ptp_fs);
}
int mlx5e_ptp_rx_manage_fs(struct mlx5e_priv *priv, bool set)
{
struct mlx5e_ptp *c = priv->channels.ptp;
if (!priv->profile->rx_ptp_support)
return 0;
if (set) {
if (!c || !test_bit(MLX5E_PTP_STATE_RX, c->state)) {
netdev_WARN_ONCE(priv->netdev, "Don't try to add PTP RX-FS rules");
return -EINVAL;
}
return mlx5e_ptp_rx_set_fs(priv);
}
/* set == false */
if (c && test_bit(MLX5E_PTP_STATE_RX, c->state)) {
netdev_WARN_ONCE(priv->netdev, "Don't try to remove PTP RX-FS rules");
return -EINVAL;
}
mlx5e_ptp_rx_unset_fs(priv);
return 0;
}
......@@ -49,6 +49,9 @@ void mlx5e_ptp_close(struct mlx5e_ptp *c);
void mlx5e_ptp_activate_channel(struct mlx5e_ptp *c);
void mlx5e_ptp_deactivate_channel(struct mlx5e_ptp *c);
int mlx5e_ptp_get_rqn(struct mlx5e_ptp *c, u32 *rqn);
int mlx5e_ptp_alloc_rx_fs(struct mlx5e_priv *priv);
void mlx5e_ptp_free_rx_fs(struct mlx5e_priv *priv);
int mlx5e_ptp_rx_manage_fs(struct mlx5e_priv *priv, bool set);
enum {
MLX5E_SKB_CB_CQE_HWTSTAMP = BIT(0),
......
......@@ -38,6 +38,7 @@
#include "en.h"
#include "en_rep.h"
#include "lib/mpfs.h"
#include "en/ptp.h"
static int mlx5e_add_l2_flow_rule(struct mlx5e_priv *priv,
struct mlx5e_l2_rule *ai, int type);
......@@ -1792,10 +1793,16 @@ int mlx5e_create_flow_steering(struct mlx5e_priv *priv)
goto err_destroy_l2_table;
}
err = mlx5e_ptp_alloc_rx_fs(priv);
if (err)
goto err_destory_vlan_table;
mlx5e_ethtool_init_steering(priv);
return 0;
err_destory_vlan_table:
mlx5e_destroy_vlan_table(priv);
err_destroy_l2_table:
mlx5e_destroy_l2_table(priv);
err_destroy_ttc_table:
......@@ -1810,6 +1817,7 @@ int mlx5e_create_flow_steering(struct mlx5e_priv *priv)
void mlx5e_destroy_flow_steering(struct mlx5e_priv *priv)
{
mlx5e_ptp_free_rx_fs(priv);
mlx5e_destroy_vlan_table(priv);
mlx5e_destroy_l2_table(priv);
mlx5e_destroy_ttc_table(priv, &priv->fs.ttc);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment