cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

spectrum2_mr_tcam.c (9812B)


      1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
      2/* Copyright (c) 2018 Mellanox Technologies. All rights reserved */
      3
      4#include <linux/kernel.h>
      5
      6#include "core_acl_flex_actions.h"
      7#include "spectrum.h"
      8#include "spectrum_mr.h"
      9
     10struct mlxsw_sp2_mr_tcam {
     11	struct mlxsw_sp *mlxsw_sp;
     12	struct mlxsw_sp_flow_block *flow_block;
     13	struct mlxsw_sp_acl_ruleset *ruleset4;
     14	struct mlxsw_sp_acl_ruleset *ruleset6;
     15};
     16
     17struct mlxsw_sp2_mr_route {
     18	struct mlxsw_sp2_mr_tcam *mr_tcam;
     19};
     20
     21static struct mlxsw_sp_acl_ruleset *
     22mlxsw_sp2_mr_tcam_proto_ruleset(struct mlxsw_sp2_mr_tcam *mr_tcam,
     23				enum mlxsw_sp_l3proto proto)
     24{
     25	switch (proto) {
     26	case MLXSW_SP_L3_PROTO_IPV4:
     27		return mr_tcam->ruleset4;
     28	case MLXSW_SP_L3_PROTO_IPV6:
     29		return mr_tcam->ruleset6;
     30	}
     31	return NULL;
     32}
     33
     34static int mlxsw_sp2_mr_tcam_bind_group(struct mlxsw_sp *mlxsw_sp,
     35					enum mlxsw_reg_pemrbt_protocol protocol,
     36					struct mlxsw_sp_acl_ruleset *ruleset)
     37{
     38	char pemrbt_pl[MLXSW_REG_PEMRBT_LEN];
     39	u16 group_id;
     40
     41	group_id = mlxsw_sp_acl_ruleset_group_id(ruleset);
     42
     43	mlxsw_reg_pemrbt_pack(pemrbt_pl, protocol, group_id);
     44	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pemrbt), pemrbt_pl);
     45}
     46
     47static const enum mlxsw_afk_element mlxsw_sp2_mr_tcam_usage_ipv4[] = {
     48		MLXSW_AFK_ELEMENT_VIRT_ROUTER_MSB,
     49		MLXSW_AFK_ELEMENT_VIRT_ROUTER_LSB,
     50		MLXSW_AFK_ELEMENT_SRC_IP_0_31,
     51		MLXSW_AFK_ELEMENT_DST_IP_0_31,
     52};
     53
     54static int mlxsw_sp2_mr_tcam_ipv4_init(struct mlxsw_sp2_mr_tcam *mr_tcam)
     55{
     56	struct mlxsw_afk_element_usage elusage;
     57	int err;
     58
     59	/* Initialize IPv4 ACL group. */
     60	mlxsw_afk_element_usage_fill(&elusage,
     61				     mlxsw_sp2_mr_tcam_usage_ipv4,
     62				     ARRAY_SIZE(mlxsw_sp2_mr_tcam_usage_ipv4));
     63	mr_tcam->ruleset4 = mlxsw_sp_acl_ruleset_get(mr_tcam->mlxsw_sp,
     64						     mr_tcam->flow_block,
     65						     MLXSW_SP_L3_PROTO_IPV4,
     66						     MLXSW_SP_ACL_PROFILE_MR,
     67						     &elusage);
     68
     69	if (IS_ERR(mr_tcam->ruleset4))
     70		return PTR_ERR(mr_tcam->ruleset4);
     71
     72	/* MC Router groups should be bound before routes are inserted. */
     73	err = mlxsw_sp2_mr_tcam_bind_group(mr_tcam->mlxsw_sp,
     74					   MLXSW_REG_PEMRBT_PROTO_IPV4,
     75					   mr_tcam->ruleset4);
     76	if (err)
     77		goto err_bind_group;
     78
     79	return 0;
     80
     81err_bind_group:
     82	mlxsw_sp_acl_ruleset_put(mr_tcam->mlxsw_sp, mr_tcam->ruleset4);
     83	return err;
     84}
     85
     86static void mlxsw_sp2_mr_tcam_ipv4_fini(struct mlxsw_sp2_mr_tcam *mr_tcam)
     87{
     88	mlxsw_sp_acl_ruleset_put(mr_tcam->mlxsw_sp, mr_tcam->ruleset4);
     89}
     90
     91static const enum mlxsw_afk_element mlxsw_sp2_mr_tcam_usage_ipv6[] = {
     92		MLXSW_AFK_ELEMENT_VIRT_ROUTER_MSB,
     93		MLXSW_AFK_ELEMENT_VIRT_ROUTER_LSB,
     94		MLXSW_AFK_ELEMENT_SRC_IP_96_127,
     95		MLXSW_AFK_ELEMENT_SRC_IP_64_95,
     96		MLXSW_AFK_ELEMENT_SRC_IP_32_63,
     97		MLXSW_AFK_ELEMENT_SRC_IP_0_31,
     98		MLXSW_AFK_ELEMENT_DST_IP_96_127,
     99		MLXSW_AFK_ELEMENT_DST_IP_64_95,
    100		MLXSW_AFK_ELEMENT_DST_IP_32_63,
    101		MLXSW_AFK_ELEMENT_DST_IP_0_31,
    102};
    103
    104static int mlxsw_sp2_mr_tcam_ipv6_init(struct mlxsw_sp2_mr_tcam *mr_tcam)
    105{
    106	struct mlxsw_afk_element_usage elusage;
    107	int err;
    108
    109	/* Initialize IPv6 ACL group */
    110	mlxsw_afk_element_usage_fill(&elusage,
    111				     mlxsw_sp2_mr_tcam_usage_ipv6,
    112				     ARRAY_SIZE(mlxsw_sp2_mr_tcam_usage_ipv6));
    113	mr_tcam->ruleset6 = mlxsw_sp_acl_ruleset_get(mr_tcam->mlxsw_sp,
    114						     mr_tcam->flow_block,
    115						     MLXSW_SP_L3_PROTO_IPV6,
    116						     MLXSW_SP_ACL_PROFILE_MR,
    117						     &elusage);
    118
    119	if (IS_ERR(mr_tcam->ruleset6))
    120		return PTR_ERR(mr_tcam->ruleset6);
    121
    122	/* MC Router groups should be bound before routes are inserted. */
    123	err = mlxsw_sp2_mr_tcam_bind_group(mr_tcam->mlxsw_sp,
    124					   MLXSW_REG_PEMRBT_PROTO_IPV6,
    125					   mr_tcam->ruleset6);
    126	if (err)
    127		goto err_bind_group;
    128
    129	return 0;
    130
    131err_bind_group:
    132	mlxsw_sp_acl_ruleset_put(mr_tcam->mlxsw_sp, mr_tcam->ruleset6);
    133	return err;
    134}
    135
    136static void mlxsw_sp2_mr_tcam_ipv6_fini(struct mlxsw_sp2_mr_tcam *mr_tcam)
    137{
    138	mlxsw_sp_acl_ruleset_put(mr_tcam->mlxsw_sp, mr_tcam->ruleset6);
    139}
    140
    141static void
    142mlxsw_sp2_mr_tcam_rule_parse4(struct mlxsw_sp_acl_rule_info *rulei,
    143			      struct mlxsw_sp_mr_route_key *key)
    144{
    145	mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_SRC_IP_0_31,
    146				       (char *) &key->source.addr4,
    147				       (char *) &key->source_mask.addr4, 4);
    148	mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_DST_IP_0_31,
    149				       (char *) &key->group.addr4,
    150				       (char *) &key->group_mask.addr4, 4);
    151}
    152
    153static void
    154mlxsw_sp2_mr_tcam_rule_parse6(struct mlxsw_sp_acl_rule_info *rulei,
    155			      struct mlxsw_sp_mr_route_key *key)
    156{
    157	mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_SRC_IP_96_127,
    158				       &key->source.addr6.s6_addr[0x0],
    159				       &key->source_mask.addr6.s6_addr[0x0], 4);
    160	mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_SRC_IP_64_95,
    161				       &key->source.addr6.s6_addr[0x4],
    162				       &key->source_mask.addr6.s6_addr[0x4], 4);
    163	mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_SRC_IP_32_63,
    164				       &key->source.addr6.s6_addr[0x8],
    165				       &key->source_mask.addr6.s6_addr[0x8], 4);
    166	mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_SRC_IP_0_31,
    167				       &key->source.addr6.s6_addr[0xc],
    168				       &key->source_mask.addr6.s6_addr[0xc], 4);
    169	mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_DST_IP_96_127,
    170				       &key->group.addr6.s6_addr[0x0],
    171				       &key->group_mask.addr6.s6_addr[0x0], 4);
    172	mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_DST_IP_64_95,
    173				       &key->group.addr6.s6_addr[0x4],
    174				       &key->group_mask.addr6.s6_addr[0x4], 4);
    175	mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_DST_IP_32_63,
    176				       &key->group.addr6.s6_addr[0x8],
    177				       &key->group_mask.addr6.s6_addr[0x8], 4);
    178	mlxsw_sp_acl_rulei_keymask_buf(rulei, MLXSW_AFK_ELEMENT_DST_IP_0_31,
    179				       &key->group.addr6.s6_addr[0xc],
    180				       &key->group_mask.addr6.s6_addr[0xc], 4);
    181}
    182
    183static void
    184mlxsw_sp2_mr_tcam_rule_parse(struct mlxsw_sp_acl_rule *rule,
    185			     struct mlxsw_sp_mr_route_key *key,
    186			     unsigned int priority)
    187{
    188	struct mlxsw_sp_acl_rule_info *rulei;
    189
    190	rulei = mlxsw_sp_acl_rule_rulei(rule);
    191	rulei->priority = priority;
    192	mlxsw_sp_acl_rulei_keymask_u32(rulei, MLXSW_AFK_ELEMENT_VIRT_ROUTER_LSB,
    193				       key->vrid, GENMASK(7, 0));
    194	mlxsw_sp_acl_rulei_keymask_u32(rulei,
    195				       MLXSW_AFK_ELEMENT_VIRT_ROUTER_MSB,
    196				       key->vrid >> 8, GENMASK(2, 0));
    197	switch (key->proto) {
    198	case MLXSW_SP_L3_PROTO_IPV4:
    199		return mlxsw_sp2_mr_tcam_rule_parse4(rulei, key);
    200	case MLXSW_SP_L3_PROTO_IPV6:
    201		return mlxsw_sp2_mr_tcam_rule_parse6(rulei, key);
    202	}
    203}
    204
    205static int
    206mlxsw_sp2_mr_tcam_route_create(struct mlxsw_sp *mlxsw_sp, void *priv,
    207			       void *route_priv,
    208			       struct mlxsw_sp_mr_route_key *key,
    209			       struct mlxsw_afa_block *afa_block,
    210			       enum mlxsw_sp_mr_route_prio prio)
    211{
    212	struct mlxsw_sp2_mr_route *mr_route = route_priv;
    213	struct mlxsw_sp2_mr_tcam *mr_tcam = priv;
    214	struct mlxsw_sp_acl_ruleset *ruleset;
    215	struct mlxsw_sp_acl_rule *rule;
    216	int err;
    217
    218	mr_route->mr_tcam = mr_tcam;
    219	ruleset = mlxsw_sp2_mr_tcam_proto_ruleset(mr_tcam, key->proto);
    220	if (WARN_ON(!ruleset))
    221		return -EINVAL;
    222
    223	rule = mlxsw_sp_acl_rule_create(mlxsw_sp, ruleset,
    224					(unsigned long) route_priv, afa_block,
    225					NULL);
    226	if (IS_ERR(rule))
    227		return PTR_ERR(rule);
    228
    229	mlxsw_sp2_mr_tcam_rule_parse(rule, key, prio);
    230	err = mlxsw_sp_acl_rule_add(mlxsw_sp, rule);
    231	if (err)
    232		goto err_rule_add;
    233
    234	return 0;
    235
    236err_rule_add:
    237	mlxsw_sp_acl_rule_destroy(mlxsw_sp, rule);
    238	return err;
    239}
    240
    241static void
    242mlxsw_sp2_mr_tcam_route_destroy(struct mlxsw_sp *mlxsw_sp, void *priv,
    243				void *route_priv,
    244				struct mlxsw_sp_mr_route_key *key)
    245{
    246	struct mlxsw_sp2_mr_tcam *mr_tcam = priv;
    247	struct mlxsw_sp_acl_ruleset *ruleset;
    248	struct mlxsw_sp_acl_rule *rule;
    249
    250	ruleset = mlxsw_sp2_mr_tcam_proto_ruleset(mr_tcam, key->proto);
    251	if (WARN_ON(!ruleset))
    252		return;
    253
    254	rule = mlxsw_sp_acl_rule_lookup(mlxsw_sp, ruleset,
    255					(unsigned long) route_priv);
    256	if (WARN_ON(!rule))
    257		return;
    258
    259	mlxsw_sp_acl_rule_del(mlxsw_sp, rule);
    260	mlxsw_sp_acl_rule_destroy(mlxsw_sp, rule);
    261}
    262
    263static int
    264mlxsw_sp2_mr_tcam_route_update(struct mlxsw_sp *mlxsw_sp,
    265			       void *route_priv,
    266			       struct mlxsw_sp_mr_route_key *key,
    267			       struct mlxsw_afa_block *afa_block)
    268{
    269	struct mlxsw_sp2_mr_route *mr_route = route_priv;
    270	struct mlxsw_sp2_mr_tcam *mr_tcam = mr_route->mr_tcam;
    271	struct mlxsw_sp_acl_ruleset *ruleset;
    272	struct mlxsw_sp_acl_rule *rule;
    273
    274	ruleset = mlxsw_sp2_mr_tcam_proto_ruleset(mr_tcam, key->proto);
    275	if (WARN_ON(!ruleset))
    276		return -EINVAL;
    277
    278	rule = mlxsw_sp_acl_rule_lookup(mlxsw_sp, ruleset,
    279					(unsigned long) route_priv);
    280	if (WARN_ON(!rule))
    281		return -EINVAL;
    282
    283	return mlxsw_sp_acl_rule_action_replace(mlxsw_sp, rule, afa_block);
    284}
    285
    286static int mlxsw_sp2_mr_tcam_init(struct mlxsw_sp *mlxsw_sp, void *priv)
    287{
    288	struct mlxsw_sp2_mr_tcam *mr_tcam = priv;
    289	int err;
    290
    291	mr_tcam->mlxsw_sp = mlxsw_sp;
    292	mr_tcam->flow_block = mlxsw_sp_flow_block_create(mlxsw_sp, NULL);
    293	if (!mr_tcam->flow_block)
    294		return -ENOMEM;
    295
    296	err = mlxsw_sp2_mr_tcam_ipv4_init(mr_tcam);
    297	if (err)
    298		goto err_ipv4_init;
    299
    300	err = mlxsw_sp2_mr_tcam_ipv6_init(mr_tcam);
    301	if (err)
    302		goto err_ipv6_init;
    303
    304	return 0;
    305
    306err_ipv6_init:
    307	mlxsw_sp2_mr_tcam_ipv4_fini(mr_tcam);
    308err_ipv4_init:
    309	mlxsw_sp_flow_block_destroy(mr_tcam->flow_block);
    310	return err;
    311}
    312
    313static void mlxsw_sp2_mr_tcam_fini(void *priv)
    314{
    315	struct mlxsw_sp2_mr_tcam *mr_tcam = priv;
    316
    317	mlxsw_sp2_mr_tcam_ipv6_fini(mr_tcam);
    318	mlxsw_sp2_mr_tcam_ipv4_fini(mr_tcam);
    319	mlxsw_sp_flow_block_destroy(mr_tcam->flow_block);
    320}
    321
    322const struct mlxsw_sp_mr_tcam_ops mlxsw_sp2_mr_tcam_ops = {
    323	.priv_size = sizeof(struct mlxsw_sp2_mr_tcam),
    324	.init = mlxsw_sp2_mr_tcam_init,
    325	.fini = mlxsw_sp2_mr_tcam_fini,
    326	.route_priv_size = sizeof(struct mlxsw_sp2_mr_route),
    327	.route_create = mlxsw_sp2_mr_tcam_route_create,
    328	.route_destroy = mlxsw_sp2_mr_tcam_route_destroy,
    329	.route_update = mlxsw_sp2_mr_tcam_route_update,
    330};