Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /* Copyright (c) 2017-2018 Mellanox Technologies. All rights reserved */
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     /* The first action set of a TCAM entry is stored directly in TCAM,
0017      * not KVD linear area.
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                     &params, 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, &params,
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 }