Commit 9742f866 authored by Yuval Mintz's avatar Yuval Mintz Committed by David S. Miller

mlxsw: spectrum_router: Support IPv6 multicast to host CPU

A step toward offloading IPv6 routing, this adds an additional
multicast routing table meant for IPv6 [with its underlying TCAM
region] and populates the default rule for IPv6 multicast packets.

Following this, ingress IPv6 multicast packets would be trapped and
delivered to the host CPU.
Signed-off-by: default avatarYuval Mintz <yuvalm@mellanox.com>
Signed-off-by: default avatarIdo Schimmel <idosch@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a3b66866
...@@ -51,7 +51,7 @@ struct mlxsw_sp_mr_tcam_region { ...@@ -51,7 +51,7 @@ struct mlxsw_sp_mr_tcam_region {
}; };
struct mlxsw_sp_mr_tcam { struct mlxsw_sp_mr_tcam {
struct mlxsw_sp_mr_tcam_region ipv4_tcam_region; struct mlxsw_sp_mr_tcam_region tcam_regions[MLXSW_SP_L3_PROTO_MAX];
}; };
/* This struct maps to one RIGR2 register entry */ /* This struct maps to one RIGR2 register entry */
...@@ -316,20 +316,37 @@ static int mlxsw_sp_mr_tcam_route_replace(struct mlxsw_sp *mlxsw_sp, ...@@ -316,20 +316,37 @@ static int mlxsw_sp_mr_tcam_route_replace(struct mlxsw_sp *mlxsw_sp,
mlxsw_afa_block_first_set(afa_block)); mlxsw_afa_block_first_set(afa_block));
break; break;
case MLXSW_SP_L3_PROTO_IPV6: case MLXSW_SP_L3_PROTO_IPV6:
default: mlxsw_reg_rmft2_ipv6_pack(rmft2_pl, true, parman_item->index,
WARN_ON_ONCE(1); key->vrid,
MLXSW_REG_RMFT2_IRIF_MASK_IGNORE, 0,
key->group.addr6,
key->group_mask.addr6,
key->source.addr6,
key->source_mask.addr6,
mlxsw_afa_block_first_set(afa_block));
} }
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rmft2), rmft2_pl); return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rmft2), rmft2_pl);
} }
static int mlxsw_sp_mr_tcam_route_remove(struct mlxsw_sp *mlxsw_sp, int vrid, static int mlxsw_sp_mr_tcam_route_remove(struct mlxsw_sp *mlxsw_sp, int vrid,
struct mlxsw_sp_mr_route_key *key,
struct parman_item *parman_item) struct parman_item *parman_item)
{ {
struct in6_addr zero_addr = IN6ADDR_ANY_INIT;
char rmft2_pl[MLXSW_REG_RMFT2_LEN]; char rmft2_pl[MLXSW_REG_RMFT2_LEN];
mlxsw_reg_rmft2_ipv4_pack(rmft2_pl, false, parman_item->index, vrid, switch (key->proto) {
0, 0, 0, 0, 0, 0, NULL); case MLXSW_SP_L3_PROTO_IPV4:
mlxsw_reg_rmft2_ipv4_pack(rmft2_pl, false, parman_item->index,
vrid, 0, 0, 0, 0, 0, 0, NULL);
break;
case MLXSW_SP_L3_PROTO_IPV6:
mlxsw_reg_rmft2_ipv6_pack(rmft2_pl, false, parman_item->index,
vrid, 0, 0, zero_addr, zero_addr,
zero_addr, zero_addr, NULL);
break;
}
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rmft2), rmft2_pl); return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rmft2), rmft2_pl);
} }
...@@ -353,27 +370,30 @@ mlxsw_sp_mr_tcam_erif_populate(struct mlxsw_sp *mlxsw_sp, ...@@ -353,27 +370,30 @@ mlxsw_sp_mr_tcam_erif_populate(struct mlxsw_sp *mlxsw_sp,
return 0; return 0;
} }
static struct mlxsw_sp_mr_tcam_region *
mlxsw_sp_mr_tcam_protocol_region(struct mlxsw_sp_mr_tcam *mr_tcam,
enum mlxsw_sp_l3proto proto)
{
return &mr_tcam->tcam_regions[proto];
}
static int static int
mlxsw_sp_mr_tcam_route_parman_item_add(struct mlxsw_sp_mr_tcam *mr_tcam, mlxsw_sp_mr_tcam_route_parman_item_add(struct mlxsw_sp_mr_tcam *mr_tcam,
struct mlxsw_sp_mr_tcam_route *route, struct mlxsw_sp_mr_tcam_route *route,
enum mlxsw_sp_mr_route_prio prio) enum mlxsw_sp_mr_route_prio prio)
{ {
struct parman_prio *parman_prio = NULL; struct mlxsw_sp_mr_tcam_region *tcam_region;
int err; int err;
switch (route->key.proto) { tcam_region = mlxsw_sp_mr_tcam_protocol_region(mr_tcam,
case MLXSW_SP_L3_PROTO_IPV4: route->key.proto);
parman_prio = &mr_tcam->ipv4_tcam_region.parman_prios[prio]; err = parman_item_add(tcam_region->parman,
err = parman_item_add(mr_tcam->ipv4_tcam_region.parman, &tcam_region->parman_prios[prio],
parman_prio, &route->parman_item); &route->parman_item);
if (err) if (err)
return err; return err;
break;
case MLXSW_SP_L3_PROTO_IPV6: route->parman_prio = &tcam_region->parman_prios[prio];
default:
WARN_ON_ONCE(1);
}
route->parman_prio = parman_prio;
return 0; return 0;
} }
...@@ -381,15 +401,13 @@ static void ...@@ -381,15 +401,13 @@ static void
mlxsw_sp_mr_tcam_route_parman_item_remove(struct mlxsw_sp_mr_tcam *mr_tcam, mlxsw_sp_mr_tcam_route_parman_item_remove(struct mlxsw_sp_mr_tcam *mr_tcam,
struct mlxsw_sp_mr_tcam_route *route) struct mlxsw_sp_mr_tcam_route *route)
{ {
switch (route->key.proto) { struct mlxsw_sp_mr_tcam_region *tcam_region;
case MLXSW_SP_L3_PROTO_IPV4:
parman_item_remove(mr_tcam->ipv4_tcam_region.parman, tcam_region = mlxsw_sp_mr_tcam_protocol_region(mr_tcam,
route->parman_prio, &route->parman_item); route->key.proto);
break;
case MLXSW_SP_L3_PROTO_IPV6: parman_item_remove(tcam_region->parman,
default: route->parman_prio, &route->parman_item);
WARN_ON_ONCE(1);
}
} }
static int static int
...@@ -462,7 +480,7 @@ static void mlxsw_sp_mr_tcam_route_destroy(struct mlxsw_sp *mlxsw_sp, ...@@ -462,7 +480,7 @@ static void mlxsw_sp_mr_tcam_route_destroy(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_mr_tcam *mr_tcam = priv; struct mlxsw_sp_mr_tcam *mr_tcam = priv;
mlxsw_sp_mr_tcam_route_remove(mlxsw_sp, route->key.vrid, mlxsw_sp_mr_tcam_route_remove(mlxsw_sp, route->key.vrid,
&route->parman_item); &route->key, &route->parman_item);
mlxsw_sp_mr_tcam_route_parman_item_remove(mr_tcam, route); mlxsw_sp_mr_tcam_route_parman_item_remove(mr_tcam, route);
mlxsw_sp_mr_tcam_afa_block_destroy(route->afa_block); mlxsw_sp_mr_tcam_afa_block_destroy(route->afa_block);
mlxsw_sp_flow_counter_free(mlxsw_sp, route->counter_index); mlxsw_sp_flow_counter_free(mlxsw_sp, route->counter_index);
...@@ -806,21 +824,42 @@ mlxsw_sp_mr_tcam_region_fini(struct mlxsw_sp_mr_tcam_region *mr_tcam_region) ...@@ -806,21 +824,42 @@ mlxsw_sp_mr_tcam_region_fini(struct mlxsw_sp_mr_tcam_region *mr_tcam_region)
static int mlxsw_sp_mr_tcam_init(struct mlxsw_sp *mlxsw_sp, void *priv) static int mlxsw_sp_mr_tcam_init(struct mlxsw_sp *mlxsw_sp, void *priv)
{ {
struct mlxsw_sp_mr_tcam *mr_tcam = priv; struct mlxsw_sp_mr_tcam *mr_tcam = priv;
struct mlxsw_sp_mr_tcam_region *region = &mr_tcam->tcam_regions[0];
u32 rtar_key;
int err;
if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MC_ERIF_LIST_ENTRIES) || if (!MLXSW_CORE_RES_VALID(mlxsw_sp->core, MC_ERIF_LIST_ENTRIES) ||
!MLXSW_CORE_RES_VALID(mlxsw_sp->core, ACL_MAX_TCAM_RULES)) !MLXSW_CORE_RES_VALID(mlxsw_sp->core, ACL_MAX_TCAM_RULES))
return -EIO; return -EIO;
return mlxsw_sp_mr_tcam_region_init(mlxsw_sp, rtar_key = MLXSW_REG_RTAR_KEY_TYPE_IPV4_MULTICAST;
&mr_tcam->ipv4_tcam_region, err = mlxsw_sp_mr_tcam_region_init(mlxsw_sp,
MLXSW_REG_RTAR_KEY_TYPE_IPV4_MULTICAST); &region[MLXSW_SP_L3_PROTO_IPV4],
rtar_key);
if (err)
return err;
rtar_key = MLXSW_REG_RTAR_KEY_TYPE_IPV6_MULTICAST;
err = mlxsw_sp_mr_tcam_region_init(mlxsw_sp,
&region[MLXSW_SP_L3_PROTO_IPV6],
rtar_key);
if (err)
goto err_ipv6_region_init;
return 0;
err_ipv6_region_init:
mlxsw_sp_mr_tcam_region_fini(&region[MLXSW_SP_L3_PROTO_IPV4]);
return err;
} }
static void mlxsw_sp_mr_tcam_fini(void *priv) static void mlxsw_sp_mr_tcam_fini(void *priv)
{ {
struct mlxsw_sp_mr_tcam *mr_tcam = priv; struct mlxsw_sp_mr_tcam *mr_tcam = priv;
struct mlxsw_sp_mr_tcam_region *region = &mr_tcam->tcam_regions[0];
mlxsw_sp_mr_tcam_region_fini(&mr_tcam->ipv4_tcam_region); mlxsw_sp_mr_tcam_region_fini(&region[MLXSW_SP_L3_PROTO_IPV6]);
mlxsw_sp_mr_tcam_region_fini(&region[MLXSW_SP_L3_PROTO_IPV4]);
} }
const struct mlxsw_sp_mr_ops mlxsw_sp_mr_tcam_ops = { const struct mlxsw_sp_mr_ops mlxsw_sp_mr_tcam_ops = {
......
...@@ -467,7 +467,7 @@ struct mlxsw_sp_vr { ...@@ -467,7 +467,7 @@ struct mlxsw_sp_vr {
unsigned int rif_count; unsigned int rif_count;
struct mlxsw_sp_fib *fib4; struct mlxsw_sp_fib *fib4;
struct mlxsw_sp_fib *fib6; struct mlxsw_sp_fib *fib6;
struct mlxsw_sp_mr_table *mr4_table; struct mlxsw_sp_mr_table *mr_table[MLXSW_SP_L3_PROTO_MAX];
}; };
static const struct rhashtable_params mlxsw_sp_fib_ht_params; static const struct rhashtable_params mlxsw_sp_fib_ht_params;
...@@ -711,7 +711,9 @@ static void mlxsw_sp_lpm_fini(struct mlxsw_sp *mlxsw_sp) ...@@ -711,7 +711,9 @@ static void mlxsw_sp_lpm_fini(struct mlxsw_sp *mlxsw_sp)
static bool mlxsw_sp_vr_is_used(const struct mlxsw_sp_vr *vr) static bool mlxsw_sp_vr_is_used(const struct mlxsw_sp_vr *vr)
{ {
return !!vr->fib4 || !!vr->fib6 || !!vr->mr4_table; return !!vr->fib4 || !!vr->fib6 ||
!!vr->mr_table[MLXSW_SP_L3_PROTO_IPV4] ||
!!vr->mr_table[MLXSW_SP_L3_PROTO_IPV6];
} }
static struct mlxsw_sp_vr *mlxsw_sp_vr_find_unused(struct mlxsw_sp *mlxsw_sp) static struct mlxsw_sp_vr *mlxsw_sp_vr_find_unused(struct mlxsw_sp *mlxsw_sp)
...@@ -789,7 +791,7 @@ static struct mlxsw_sp_vr *mlxsw_sp_vr_create(struct mlxsw_sp *mlxsw_sp, ...@@ -789,7 +791,7 @@ static struct mlxsw_sp_vr *mlxsw_sp_vr_create(struct mlxsw_sp *mlxsw_sp,
u32 tb_id, u32 tb_id,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct mlxsw_sp_mr_table *mr4_table; struct mlxsw_sp_mr_table *mr4_table, *mr6_table;
struct mlxsw_sp_fib *fib4; struct mlxsw_sp_fib *fib4;
struct mlxsw_sp_fib *fib6; struct mlxsw_sp_fib *fib6;
struct mlxsw_sp_vr *vr; struct mlxsw_sp_vr *vr;
...@@ -812,15 +814,25 @@ static struct mlxsw_sp_vr *mlxsw_sp_vr_create(struct mlxsw_sp *mlxsw_sp, ...@@ -812,15 +814,25 @@ static struct mlxsw_sp_vr *mlxsw_sp_vr_create(struct mlxsw_sp *mlxsw_sp,
MLXSW_SP_L3_PROTO_IPV4); MLXSW_SP_L3_PROTO_IPV4);
if (IS_ERR(mr4_table)) { if (IS_ERR(mr4_table)) {
err = PTR_ERR(mr4_table); err = PTR_ERR(mr4_table);
goto err_mr_table_create; goto err_mr4_table_create;
} }
mr6_table = mlxsw_sp_mr_table_create(mlxsw_sp, vr->id,
MLXSW_SP_L3_PROTO_IPV6);
if (IS_ERR(mr6_table)) {
err = PTR_ERR(mr6_table);
goto err_mr6_table_create;
}
vr->fib4 = fib4; vr->fib4 = fib4;
vr->fib6 = fib6; vr->fib6 = fib6;
vr->mr4_table = mr4_table; vr->mr_table[MLXSW_SP_L3_PROTO_IPV4] = mr4_table;
vr->mr_table[MLXSW_SP_L3_PROTO_IPV6] = mr6_table;
vr->tb_id = tb_id; vr->tb_id = tb_id;
return vr; return vr;
err_mr_table_create: err_mr6_table_create:
mlxsw_sp_mr_table_destroy(mr4_table);
err_mr4_table_create:
mlxsw_sp_fib_destroy(mlxsw_sp, fib6); mlxsw_sp_fib_destroy(mlxsw_sp, fib6);
err_fib6_create: err_fib6_create:
mlxsw_sp_fib_destroy(mlxsw_sp, fib4); mlxsw_sp_fib_destroy(mlxsw_sp, fib4);
...@@ -830,8 +842,10 @@ static struct mlxsw_sp_vr *mlxsw_sp_vr_create(struct mlxsw_sp *mlxsw_sp, ...@@ -830,8 +842,10 @@ static struct mlxsw_sp_vr *mlxsw_sp_vr_create(struct mlxsw_sp *mlxsw_sp,
static void mlxsw_sp_vr_destroy(struct mlxsw_sp *mlxsw_sp, static void mlxsw_sp_vr_destroy(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_vr *vr) struct mlxsw_sp_vr *vr)
{ {
mlxsw_sp_mr_table_destroy(vr->mr4_table); mlxsw_sp_mr_table_destroy(vr->mr_table[MLXSW_SP_L3_PROTO_IPV6]);
vr->mr4_table = NULL; vr->mr_table[MLXSW_SP_L3_PROTO_IPV6] = NULL;
mlxsw_sp_mr_table_destroy(vr->mr_table[MLXSW_SP_L3_PROTO_IPV4]);
vr->mr_table[MLXSW_SP_L3_PROTO_IPV4] = NULL;
mlxsw_sp_fib_destroy(mlxsw_sp, vr->fib6); mlxsw_sp_fib_destroy(mlxsw_sp, vr->fib6);
vr->fib6 = NULL; vr->fib6 = NULL;
mlxsw_sp_fib_destroy(mlxsw_sp, vr->fib4); mlxsw_sp_fib_destroy(mlxsw_sp, vr->fib4);
...@@ -854,7 +868,8 @@ static void mlxsw_sp_vr_put(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_vr *vr) ...@@ -854,7 +868,8 @@ static void mlxsw_sp_vr_put(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_vr *vr)
{ {
if (!vr->rif_count && list_empty(&vr->fib4->node_list) && if (!vr->rif_count && list_empty(&vr->fib4->node_list) &&
list_empty(&vr->fib6->node_list) && list_empty(&vr->fib6->node_list) &&
mlxsw_sp_mr_table_empty(vr->mr4_table)) mlxsw_sp_mr_table_empty(vr->mr_table[MLXSW_SP_L3_PROTO_IPV4]) &&
mlxsw_sp_mr_table_empty(vr->mr_table[MLXSW_SP_L3_PROTO_IPV6]))
mlxsw_sp_vr_destroy(mlxsw_sp, vr); mlxsw_sp_vr_destroy(mlxsw_sp, vr);
} }
...@@ -5391,7 +5406,7 @@ static int mlxsw_sp_router_fibmr_add(struct mlxsw_sp *mlxsw_sp, ...@@ -5391,7 +5406,7 @@ static int mlxsw_sp_router_fibmr_add(struct mlxsw_sp *mlxsw_sp,
if (IS_ERR(vr)) if (IS_ERR(vr))
return PTR_ERR(vr); return PTR_ERR(vr);
return mlxsw_sp_mr_route4_add(vr->mr4_table, return mlxsw_sp_mr_route4_add(vr->mr_table[MLXSW_SP_L3_PROTO_IPV4],
(struct mfc_cache *) men_info->mfc, (struct mfc_cache *) men_info->mfc,
replace); replace);
} }
...@@ -5408,7 +5423,7 @@ static void mlxsw_sp_router_fibmr_del(struct mlxsw_sp *mlxsw_sp, ...@@ -5408,7 +5423,7 @@ static void mlxsw_sp_router_fibmr_del(struct mlxsw_sp *mlxsw_sp,
if (WARN_ON(!vr)) if (WARN_ON(!vr))
return; return;
mlxsw_sp_mr_route4_del(vr->mr4_table, mlxsw_sp_mr_route4_del(vr->mr_table[MLXSW_SP_L3_PROTO_IPV4],
(struct mfc_cache *) men_info->mfc); (struct mfc_cache *) men_info->mfc);
mlxsw_sp_vr_put(mlxsw_sp, vr); mlxsw_sp_vr_put(mlxsw_sp, vr);
} }
...@@ -5428,7 +5443,8 @@ mlxsw_sp_router_fibmr_vif_add(struct mlxsw_sp *mlxsw_sp, ...@@ -5428,7 +5443,8 @@ mlxsw_sp_router_fibmr_vif_add(struct mlxsw_sp *mlxsw_sp,
return PTR_ERR(vr); return PTR_ERR(vr);
rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, ven_info->dev); rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, ven_info->dev);
return mlxsw_sp_mr_vif_add(vr->mr4_table, ven_info->dev, return mlxsw_sp_mr_vif_add(vr->mr_table[MLXSW_SP_L3_PROTO_IPV4],
ven_info->dev,
ven_info->vif_index, ven_info->vif_index,
ven_info->vif_flags, rif); ven_info->vif_flags, rif);
} }
...@@ -5446,7 +5462,8 @@ mlxsw_sp_router_fibmr_vif_del(struct mlxsw_sp *mlxsw_sp, ...@@ -5446,7 +5462,8 @@ mlxsw_sp_router_fibmr_vif_del(struct mlxsw_sp *mlxsw_sp,
if (WARN_ON(!vr)) if (WARN_ON(!vr))
return; return;
mlxsw_sp_mr_vif_del(vr->mr4_table, ven_info->vif_index); mlxsw_sp_mr_vif_del(vr->mr_table[MLXSW_SP_L3_PROTO_IPV4],
ven_info->vif_index);
mlxsw_sp_vr_put(mlxsw_sp, vr); mlxsw_sp_vr_put(mlxsw_sp, vr);
} }
...@@ -5538,7 +5555,7 @@ static void mlxsw_sp_vr_fib_flush(struct mlxsw_sp *mlxsw_sp, ...@@ -5538,7 +5555,7 @@ static void mlxsw_sp_vr_fib_flush(struct mlxsw_sp *mlxsw_sp,
static void mlxsw_sp_router_fib_flush(struct mlxsw_sp *mlxsw_sp) static void mlxsw_sp_router_fib_flush(struct mlxsw_sp *mlxsw_sp)
{ {
int i; int i, j;
for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) { for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_VRS); i++) {
struct mlxsw_sp_vr *vr = &mlxsw_sp->router->vrs[i]; struct mlxsw_sp_vr *vr = &mlxsw_sp->router->vrs[i];
...@@ -5546,7 +5563,8 @@ static void mlxsw_sp_router_fib_flush(struct mlxsw_sp *mlxsw_sp) ...@@ -5546,7 +5563,8 @@ static void mlxsw_sp_router_fib_flush(struct mlxsw_sp *mlxsw_sp)
if (!mlxsw_sp_vr_is_used(vr)) if (!mlxsw_sp_vr_is_used(vr))
continue; continue;
mlxsw_sp_mr_table_flush(vr->mr4_table); for (j = 0; j < MLXSW_SP_L3_PROTO_MAX; j++)
mlxsw_sp_mr_table_flush(vr->mr_table[j]);
mlxsw_sp_vr_fib_flush(mlxsw_sp, vr, MLXSW_SP_L3_PROTO_IPV4); mlxsw_sp_vr_fib_flush(mlxsw_sp, vr, MLXSW_SP_L3_PROTO_IPV4);
/* If virtual router was only used for IPv4, then it's no /* If virtual router was only used for IPv4, then it's no
...@@ -6041,7 +6059,7 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp, ...@@ -6041,7 +6059,7 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_rif *rif; struct mlxsw_sp_rif *rif;
struct mlxsw_sp_vr *vr; struct mlxsw_sp_vr *vr;
u16 rif_index; u16 rif_index;
int err; int i, err;
type = mlxsw_sp_dev_rif_type(mlxsw_sp, params->dev); type = mlxsw_sp_dev_rif_type(mlxsw_sp, params->dev);
ops = mlxsw_sp->router->rif_ops_arr[type]; ops = mlxsw_sp->router->rif_ops_arr[type];
...@@ -6081,9 +6099,11 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp, ...@@ -6081,9 +6099,11 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
if (err) if (err)
goto err_configure; goto err_configure;
err = mlxsw_sp_mr_rif_add(vr->mr4_table, rif); for (i = 0; i < MLXSW_SP_L3_PROTO_MAX; i++) {
if (err) err = mlxsw_sp_mr_rif_add(vr->mr_table[i], rif);
goto err_mr_rif_add; if (err)
goto err_mr_rif_add;
}
mlxsw_sp_rif_counters_alloc(rif); mlxsw_sp_rif_counters_alloc(rif);
mlxsw_sp->router->rifs[rif_index] = rif; mlxsw_sp->router->rifs[rif_index] = rif;
...@@ -6091,6 +6111,8 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp, ...@@ -6091,6 +6111,8 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp,
return rif; return rif;
err_mr_rif_add: err_mr_rif_add:
for (i--; i >= 0; i--)
mlxsw_sp_mr_rif_del(vr->mr_table[i], rif);
ops->deconfigure(rif); ops->deconfigure(rif);
err_configure: err_configure:
if (fid) if (fid)
...@@ -6110,13 +6132,15 @@ void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif) ...@@ -6110,13 +6132,15 @@ void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif)
struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp; struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
struct mlxsw_sp_fid *fid = rif->fid; struct mlxsw_sp_fid *fid = rif->fid;
struct mlxsw_sp_vr *vr; struct mlxsw_sp_vr *vr;
int i;
mlxsw_sp_router_rif_gone_sync(mlxsw_sp, rif); mlxsw_sp_router_rif_gone_sync(mlxsw_sp, rif);
vr = &mlxsw_sp->router->vrs[rif->vr_id]; vr = &mlxsw_sp->router->vrs[rif->vr_id];
mlxsw_sp->router->rifs[rif->rif_index] = NULL; mlxsw_sp->router->rifs[rif->rif_index] = NULL;
mlxsw_sp_rif_counters_free(rif); mlxsw_sp_rif_counters_free(rif);
mlxsw_sp_mr_rif_del(vr->mr4_table, rif); for (i = 0; i < MLXSW_SP_L3_PROTO_MAX; i++)
mlxsw_sp_mr_rif_del(vr->mr_table[i], rif);
ops->deconfigure(rif); ops->deconfigure(rif);
if (fid) if (fid)
/* Loopback RIFs are not associated with a FID. */ /* Loopback RIFs are not associated with a FID. */
...@@ -6523,13 +6547,16 @@ int mlxsw_sp_netdevice_router_port_event(struct net_device *dev) ...@@ -6523,13 +6547,16 @@ int mlxsw_sp_netdevice_router_port_event(struct net_device *dev)
if (rif->mtu != dev->mtu) { if (rif->mtu != dev->mtu) {
struct mlxsw_sp_vr *vr; struct mlxsw_sp_vr *vr;
int i;
/* The RIF is relevant only to its mr_table instance, as unlike /* The RIF is relevant only to its mr_table instance, as unlike
* unicast routing, in multicast routing a RIF cannot be shared * unicast routing, in multicast routing a RIF cannot be shared
* between several multicast routing tables. * between several multicast routing tables.
*/ */
vr = &mlxsw_sp->router->vrs[rif->vr_id]; vr = &mlxsw_sp->router->vrs[rif->vr_id];
mlxsw_sp_mr_rif_mtu_update(vr->mr4_table, rif, dev->mtu); for (i = 0; i < MLXSW_SP_L3_PROTO_MAX; i++)
mlxsw_sp_mr_rif_mtu_update(vr->mr_table[i],
rif, dev->mtu);
} }
ether_addr_copy(rif->addr, dev->dev_addr); ether_addr_copy(rif->addr, dev->dev_addr);
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
enum mlxsw_sp_l3proto { enum mlxsw_sp_l3proto {
MLXSW_SP_L3_PROTO_IPV4, MLXSW_SP_L3_PROTO_IPV4,
MLXSW_SP_L3_PROTO_IPV6, MLXSW_SP_L3_PROTO_IPV6,
#define MLXSW_SP_L3_PROTO_MAX (MLXSW_SP_L3_PROTO_IPV6 + 1)
}; };
union mlxsw_sp_l3addr { union mlxsw_sp_l3addr {
......
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