0001
0002
0003
0004 #include "spectrum_acl_flex_actions.h"
0005 #include "core_acl_flex_actions.h"
0006 #include "spectrum_span.h"
0007
0008 static int mlxsw_sp_act_kvdl_set_add(void *priv, u32 *p_kvdl_index,
0009 char *enc_actions, bool is_first, bool ca)
0010 {
0011 struct mlxsw_sp *mlxsw_sp = priv;
0012 char pefa_pl[MLXSW_REG_PEFA_LEN];
0013 u32 kvdl_index;
0014 int err;
0015
0016
0017
0018
0019 if (is_first)
0020 return 0;
0021
0022 err = mlxsw_sp_kvdl_alloc(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ACTSET,
0023 1, &kvdl_index);
0024 if (err)
0025 return err;
0026 mlxsw_reg_pefa_pack(pefa_pl, kvdl_index, ca, enc_actions);
0027 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pefa), pefa_pl);
0028 if (err)
0029 goto err_pefa_write;
0030 *p_kvdl_index = kvdl_index;
0031 return 0;
0032
0033 err_pefa_write:
0034 mlxsw_sp_kvdl_free(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ACTSET,
0035 1, kvdl_index);
0036 return err;
0037 }
0038
0039 static int mlxsw_sp1_act_kvdl_set_add(void *priv, u32 *p_kvdl_index,
0040 char *enc_actions, bool is_first)
0041 {
0042 return mlxsw_sp_act_kvdl_set_add(priv, p_kvdl_index, enc_actions,
0043 is_first, false);
0044 }
0045
0046 static int mlxsw_sp2_act_kvdl_set_add(void *priv, u32 *p_kvdl_index,
0047 char *enc_actions, bool is_first)
0048 {
0049 return mlxsw_sp_act_kvdl_set_add(priv, p_kvdl_index, enc_actions,
0050 is_first, true);
0051 }
0052
0053 static void mlxsw_sp_act_kvdl_set_del(void *priv, u32 kvdl_index,
0054 bool is_first)
0055 {
0056 struct mlxsw_sp *mlxsw_sp = priv;
0057
0058 if (is_first)
0059 return;
0060 mlxsw_sp_kvdl_free(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_ACTSET,
0061 1, kvdl_index);
0062 }
0063
0064 static int mlxsw_sp1_act_kvdl_set_activity_get(void *priv, u32 kvdl_index,
0065 bool *activity)
0066 {
0067 return -EOPNOTSUPP;
0068 }
0069
0070 static int mlxsw_sp2_act_kvdl_set_activity_get(void *priv, u32 kvdl_index,
0071 bool *activity)
0072 {
0073 struct mlxsw_sp *mlxsw_sp = priv;
0074 char pefa_pl[MLXSW_REG_PEFA_LEN];
0075 int err;
0076
0077 mlxsw_reg_pefa_pack(pefa_pl, kvdl_index, true, NULL);
0078 err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(pefa), pefa_pl);
0079 if (err)
0080 return err;
0081 mlxsw_reg_pefa_unpack(pefa_pl, activity);
0082 return 0;
0083 }
0084
0085 static int mlxsw_sp_act_kvdl_fwd_entry_add(void *priv, u32 *p_kvdl_index,
0086 u16 local_port)
0087 {
0088 struct mlxsw_sp *mlxsw_sp = priv;
0089 char ppbs_pl[MLXSW_REG_PPBS_LEN];
0090 u32 kvdl_index;
0091 int err;
0092
0093 err = mlxsw_sp_kvdl_alloc(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_PBS,
0094 1, &kvdl_index);
0095 if (err)
0096 return err;
0097 mlxsw_reg_ppbs_pack(ppbs_pl, kvdl_index, local_port);
0098 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ppbs), ppbs_pl);
0099 if (err)
0100 goto err_ppbs_write;
0101 *p_kvdl_index = kvdl_index;
0102 return 0;
0103
0104 err_ppbs_write:
0105 mlxsw_sp_kvdl_free(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_PBS,
0106 1, kvdl_index);
0107 return err;
0108 }
0109
0110 static void mlxsw_sp_act_kvdl_fwd_entry_del(void *priv, u32 kvdl_index)
0111 {
0112 struct mlxsw_sp *mlxsw_sp = priv;
0113
0114 mlxsw_sp_kvdl_free(mlxsw_sp, MLXSW_SP_KVDL_ENTRY_TYPE_PBS,
0115 1, kvdl_index);
0116 }
0117
0118 static int
0119 mlxsw_sp_act_counter_index_get(void *priv, unsigned int *p_counter_index)
0120 {
0121 struct mlxsw_sp *mlxsw_sp = priv;
0122
0123 return mlxsw_sp_flow_counter_alloc(mlxsw_sp, p_counter_index);
0124 }
0125
0126 static void
0127 mlxsw_sp_act_counter_index_put(void *priv, unsigned int counter_index)
0128 {
0129 struct mlxsw_sp *mlxsw_sp = priv;
0130
0131 mlxsw_sp_flow_counter_free(mlxsw_sp, counter_index);
0132 }
0133
0134 static int
0135 mlxsw_sp_act_mirror_add(void *priv, u16 local_in_port,
0136 const struct net_device *out_dev,
0137 bool ingress, int *p_span_id)
0138 {
0139 struct mlxsw_sp_span_agent_parms agent_parms = {};
0140 struct mlxsw_sp_port *mlxsw_sp_port;
0141 struct mlxsw_sp *mlxsw_sp = priv;
0142 int err;
0143
0144 agent_parms.to_dev = out_dev;
0145 err = mlxsw_sp_span_agent_get(mlxsw_sp, p_span_id, &agent_parms);
0146 if (err)
0147 return err;
0148
0149 mlxsw_sp_port = mlxsw_sp->ports[local_in_port];
0150 err = mlxsw_sp_span_analyzed_port_get(mlxsw_sp_port, ingress);
0151 if (err)
0152 goto err_analyzed_port_get;
0153
0154 return 0;
0155
0156 err_analyzed_port_get:
0157 mlxsw_sp_span_agent_put(mlxsw_sp, *p_span_id);
0158 return err;
0159 }
0160
0161 static void
0162 mlxsw_sp_act_mirror_del(void *priv, u16 local_in_port, int span_id, bool ingress)
0163 {
0164 struct mlxsw_sp_port *mlxsw_sp_port;
0165 struct mlxsw_sp *mlxsw_sp = priv;
0166
0167 mlxsw_sp_port = mlxsw_sp->ports[local_in_port];
0168 mlxsw_sp_span_analyzed_port_put(mlxsw_sp_port, ingress);
0169 mlxsw_sp_span_agent_put(mlxsw_sp, span_id);
0170 }
0171
0172 static int mlxsw_sp_act_policer_add(void *priv, u64 rate_bytes_ps, u32 burst,
0173 u16 *p_policer_index,
0174 struct netlink_ext_ack *extack)
0175 {
0176 struct mlxsw_sp_policer_params params;
0177 struct mlxsw_sp *mlxsw_sp = priv;
0178
0179 params.rate = rate_bytes_ps;
0180 params.burst = burst;
0181 params.bytes = true;
0182 return mlxsw_sp_policer_add(mlxsw_sp,
0183 MLXSW_SP_POLICER_TYPE_SINGLE_RATE,
0184 ¶ms, extack, p_policer_index);
0185 }
0186
0187 static void mlxsw_sp_act_policer_del(void *priv, u16 policer_index)
0188 {
0189 struct mlxsw_sp *mlxsw_sp = priv;
0190
0191 mlxsw_sp_policer_del(mlxsw_sp, MLXSW_SP_POLICER_TYPE_SINGLE_RATE,
0192 policer_index);
0193 }
0194
0195 static int mlxsw_sp1_act_sampler_add(void *priv, u16 local_port,
0196 struct psample_group *psample_group,
0197 u32 rate, u32 trunc_size, bool truncate,
0198 bool ingress, int *p_span_id,
0199 struct netlink_ext_ack *extack)
0200 {
0201 NL_SET_ERR_MSG_MOD(extack, "Sampling action is not supported on Spectrum-1");
0202 return -EOPNOTSUPP;
0203 }
0204
0205 static void mlxsw_sp1_act_sampler_del(void *priv, u16 local_port, int span_id,
0206 bool ingress)
0207 {
0208 WARN_ON_ONCE(1);
0209 }
0210
0211 const struct mlxsw_afa_ops mlxsw_sp1_act_afa_ops = {
0212 .kvdl_set_add = mlxsw_sp1_act_kvdl_set_add,
0213 .kvdl_set_del = mlxsw_sp_act_kvdl_set_del,
0214 .kvdl_set_activity_get = mlxsw_sp1_act_kvdl_set_activity_get,
0215 .kvdl_fwd_entry_add = mlxsw_sp_act_kvdl_fwd_entry_add,
0216 .kvdl_fwd_entry_del = mlxsw_sp_act_kvdl_fwd_entry_del,
0217 .counter_index_get = mlxsw_sp_act_counter_index_get,
0218 .counter_index_put = mlxsw_sp_act_counter_index_put,
0219 .mirror_add = mlxsw_sp_act_mirror_add,
0220 .mirror_del = mlxsw_sp_act_mirror_del,
0221 .policer_add = mlxsw_sp_act_policer_add,
0222 .policer_del = mlxsw_sp_act_policer_del,
0223 .sampler_add = mlxsw_sp1_act_sampler_add,
0224 .sampler_del = mlxsw_sp1_act_sampler_del,
0225 };
0226
0227 static int mlxsw_sp2_act_sampler_add(void *priv, u16 local_port,
0228 struct psample_group *psample_group,
0229 u32 rate, u32 trunc_size, bool truncate,
0230 bool ingress, int *p_span_id,
0231 struct netlink_ext_ack *extack)
0232 {
0233 struct mlxsw_sp_span_agent_parms agent_parms = {
0234 .session_id = MLXSW_SP_SPAN_SESSION_ID_SAMPLING,
0235 };
0236 struct mlxsw_sp_sample_trigger trigger = {
0237 .type = MLXSW_SP_SAMPLE_TRIGGER_TYPE_POLICY_ENGINE,
0238 };
0239 struct mlxsw_sp_sample_params params;
0240 struct mlxsw_sp_port *mlxsw_sp_port;
0241 struct mlxsw_sp *mlxsw_sp = priv;
0242 int err;
0243
0244 params.psample_group = psample_group;
0245 params.trunc_size = trunc_size;
0246 params.rate = rate;
0247 params.truncate = truncate;
0248 err = mlxsw_sp_sample_trigger_params_set(mlxsw_sp, &trigger, ¶ms,
0249 extack);
0250 if (err)
0251 return err;
0252
0253 err = mlxsw_sp_span_agent_get(mlxsw_sp, p_span_id, &agent_parms);
0254 if (err) {
0255 NL_SET_ERR_MSG_MOD(extack, "Failed to get SPAN agent");
0256 goto err_span_agent_get;
0257 }
0258
0259 mlxsw_sp_port = mlxsw_sp->ports[local_port];
0260 err = mlxsw_sp_span_analyzed_port_get(mlxsw_sp_port, ingress);
0261 if (err) {
0262 NL_SET_ERR_MSG_MOD(extack, "Failed to get analyzed port");
0263 goto err_analyzed_port_get;
0264 }
0265
0266 return 0;
0267
0268 err_analyzed_port_get:
0269 mlxsw_sp_span_agent_put(mlxsw_sp, *p_span_id);
0270 err_span_agent_get:
0271 mlxsw_sp_sample_trigger_params_unset(mlxsw_sp, &trigger);
0272 return err;
0273 }
0274
0275 static void mlxsw_sp2_act_sampler_del(void *priv, u16 local_port, int span_id,
0276 bool ingress)
0277 {
0278 struct mlxsw_sp_sample_trigger trigger = {
0279 .type = MLXSW_SP_SAMPLE_TRIGGER_TYPE_POLICY_ENGINE,
0280 };
0281 struct mlxsw_sp_port *mlxsw_sp_port;
0282 struct mlxsw_sp *mlxsw_sp = priv;
0283
0284 mlxsw_sp_port = mlxsw_sp->ports[local_port];
0285 mlxsw_sp_span_analyzed_port_put(mlxsw_sp_port, ingress);
0286 mlxsw_sp_span_agent_put(mlxsw_sp, span_id);
0287 mlxsw_sp_sample_trigger_params_unset(mlxsw_sp, &trigger);
0288 }
0289
0290 const struct mlxsw_afa_ops mlxsw_sp2_act_afa_ops = {
0291 .kvdl_set_add = mlxsw_sp2_act_kvdl_set_add,
0292 .kvdl_set_del = mlxsw_sp_act_kvdl_set_del,
0293 .kvdl_set_activity_get = mlxsw_sp2_act_kvdl_set_activity_get,
0294 .kvdl_fwd_entry_add = mlxsw_sp_act_kvdl_fwd_entry_add,
0295 .kvdl_fwd_entry_del = mlxsw_sp_act_kvdl_fwd_entry_del,
0296 .counter_index_get = mlxsw_sp_act_counter_index_get,
0297 .counter_index_put = mlxsw_sp_act_counter_index_put,
0298 .mirror_add = mlxsw_sp_act_mirror_add,
0299 .mirror_del = mlxsw_sp_act_mirror_del,
0300 .policer_add = mlxsw_sp_act_policer_add,
0301 .policer_del = mlxsw_sp_act_policer_del,
0302 .sampler_add = mlxsw_sp2_act_sampler_add,
0303 .sampler_del = mlxsw_sp2_act_sampler_del,
0304 .dummy_first_set = true,
0305 };
0306
0307 int mlxsw_sp_afa_init(struct mlxsw_sp *mlxsw_sp)
0308 {
0309 mlxsw_sp->afa = mlxsw_afa_create(MLXSW_CORE_RES_GET(mlxsw_sp->core,
0310 ACL_ACTIONS_PER_SET),
0311 mlxsw_sp->afa_ops, mlxsw_sp);
0312 return PTR_ERR_OR_ZERO(mlxsw_sp->afa);
0313 }
0314
0315 void mlxsw_sp_afa_fini(struct mlxsw_sp *mlxsw_sp)
0316 {
0317 mlxsw_afa_destroy(mlxsw_sp->afa);
0318 }