Commit af3f4a85 authored by David S. Miller's avatar David S. Miller

Merge branch 'mlxsw-Misc-updates'

Ido Schimmel says:

====================
mlxsw: Misc updates

This patchset contains miscellaneous patches we gathered in our queue.
Some of them are dependencies of larger patchsets that I will submit
later this cycle.

Patches #1-#3 perform small non-functional changes in mlxsw.

Patch #4 adds more extended ack messages in mlxsw.

Patch #5 adds devlink parameters documentation for mlxsw. To be extended
with more parameters this cycle.

Patches #6-#7 perform small changes in forwarding selftests
infrastructure.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 4054eebf acde33bf
...@@ -160,6 +160,7 @@ struct mlxsw_rx_listener_item { ...@@ -160,6 +160,7 @@ struct mlxsw_rx_listener_item {
struct mlxsw_event_listener_item { struct mlxsw_event_listener_item {
struct list_head list; struct list_head list;
struct mlxsw_core *mlxsw_core;
struct mlxsw_event_listener el; struct mlxsw_event_listener el;
void *priv; void *priv;
}; };
...@@ -2171,11 +2172,16 @@ static void mlxsw_core_event_listener_func(struct sk_buff *skb, u8 local_port, ...@@ -2171,11 +2172,16 @@ static void mlxsw_core_event_listener_func(struct sk_buff *skb, u8 local_port,
void *priv) void *priv)
{ {
struct mlxsw_event_listener_item *event_listener_item = priv; struct mlxsw_event_listener_item *event_listener_item = priv;
struct mlxsw_core *mlxsw_core;
struct mlxsw_reg_info reg; struct mlxsw_reg_info reg;
char *payload; char *payload;
char *reg_tlv; char *reg_tlv;
char *op_tlv; char *op_tlv;
mlxsw_core = event_listener_item->mlxsw_core;
trace_devlink_hwmsg(priv_to_devlink(mlxsw_core), true, 0,
skb->data, skb->len);
mlxsw_emad_tlv_parse(skb); mlxsw_emad_tlv_parse(skb);
op_tlv = mlxsw_emad_op_tlv(skb); op_tlv = mlxsw_emad_op_tlv(skb);
reg_tlv = mlxsw_emad_reg_tlv(skb); reg_tlv = mlxsw_emad_reg_tlv(skb);
...@@ -2225,6 +2231,7 @@ int mlxsw_core_event_listener_register(struct mlxsw_core *mlxsw_core, ...@@ -2225,6 +2231,7 @@ int mlxsw_core_event_listener_register(struct mlxsw_core *mlxsw_core,
el_item = kmalloc(sizeof(*el_item), GFP_KERNEL); el_item = kmalloc(sizeof(*el_item), GFP_KERNEL);
if (!el_item) if (!el_item)
return -ENOMEM; return -ENOMEM;
el_item->mlxsw_core = mlxsw_core;
el_item->el = *el; el_item->el = *el;
el_item->priv = priv; el_item->priv = priv;
......
...@@ -133,10 +133,8 @@ mlxsw_afk_key_info_find(struct mlxsw_afk *mlxsw_afk, ...@@ -133,10 +133,8 @@ mlxsw_afk_key_info_find(struct mlxsw_afk *mlxsw_afk,
} }
struct mlxsw_afk_picker { struct mlxsw_afk_picker {
struct { DECLARE_BITMAP(element, MLXSW_AFK_ELEMENT_MAX);
DECLARE_BITMAP(element, MLXSW_AFK_ELEMENT_MAX); unsigned int total;
unsigned int total;
} hits[0];
}; };
static void mlxsw_afk_picker_count_hits(struct mlxsw_afk *mlxsw_afk, static void mlxsw_afk_picker_count_hits(struct mlxsw_afk *mlxsw_afk,
...@@ -154,8 +152,8 @@ static void mlxsw_afk_picker_count_hits(struct mlxsw_afk *mlxsw_afk, ...@@ -154,8 +152,8 @@ static void mlxsw_afk_picker_count_hits(struct mlxsw_afk *mlxsw_afk,
elinst = &block->instances[j]; elinst = &block->instances[j];
if (elinst->element == element) { if (elinst->element == element) {
__set_bit(element, picker->hits[i].element); __set_bit(element, picker[i].element);
picker->hits[i].total++; picker[i].total++;
} }
} }
} }
...@@ -169,13 +167,13 @@ static void mlxsw_afk_picker_subtract_hits(struct mlxsw_afk *mlxsw_afk, ...@@ -169,13 +167,13 @@ static void mlxsw_afk_picker_subtract_hits(struct mlxsw_afk *mlxsw_afk,
int i; int i;
int j; int j;
memcpy(&hits_element, &picker->hits[block_index].element, memcpy(&hits_element, &picker[block_index].element,
sizeof(hits_element)); sizeof(hits_element));
for (i = 0; i < mlxsw_afk->blocks_count; i++) { for (i = 0; i < mlxsw_afk->blocks_count; i++) {
for_each_set_bit(j, hits_element, MLXSW_AFK_ELEMENT_MAX) { for_each_set_bit(j, hits_element, MLXSW_AFK_ELEMENT_MAX) {
if (__test_and_clear_bit(j, picker->hits[i].element)) if (__test_and_clear_bit(j, picker[i].element))
picker->hits[i].total--; picker[i].total--;
} }
} }
} }
...@@ -188,8 +186,8 @@ static int mlxsw_afk_picker_most_hits_get(struct mlxsw_afk *mlxsw_afk, ...@@ -188,8 +186,8 @@ static int mlxsw_afk_picker_most_hits_get(struct mlxsw_afk *mlxsw_afk,
int i; int i;
for (i = 0; i < mlxsw_afk->blocks_count; i++) { for (i = 0; i < mlxsw_afk->blocks_count; i++) {
if (picker->hits[i].total > most_hits) { if (picker[i].total > most_hits) {
most_hits = picker->hits[i].total; most_hits = picker[i].total;
most_index = i; most_index = i;
} }
} }
...@@ -206,7 +204,7 @@ static int mlxsw_afk_picker_key_info_add(struct mlxsw_afk *mlxsw_afk, ...@@ -206,7 +204,7 @@ static int mlxsw_afk_picker_key_info_add(struct mlxsw_afk *mlxsw_afk,
if (key_info->blocks_count == mlxsw_afk->max_blocks) if (key_info->blocks_count == mlxsw_afk->max_blocks)
return -EINVAL; return -EINVAL;
for_each_set_bit(element, picker->hits[block_index].element, for_each_set_bit(element, picker[block_index].element,
MLXSW_AFK_ELEMENT_MAX) { MLXSW_AFK_ELEMENT_MAX) {
key_info->element_to_block[element] = key_info->blocks_count; key_info->element_to_block[element] = key_info->blocks_count;
mlxsw_afk_element_usage_add(&key_info->elusage, element); mlxsw_afk_element_usage_add(&key_info->elusage, element);
...@@ -224,11 +222,9 @@ static int mlxsw_afk_picker(struct mlxsw_afk *mlxsw_afk, ...@@ -224,11 +222,9 @@ static int mlxsw_afk_picker(struct mlxsw_afk *mlxsw_afk,
{ {
struct mlxsw_afk_picker *picker; struct mlxsw_afk_picker *picker;
enum mlxsw_afk_element element; enum mlxsw_afk_element element;
size_t alloc_size;
int err; int err;
alloc_size = sizeof(picker->hits[0]) * mlxsw_afk->blocks_count; picker = kcalloc(mlxsw_afk->blocks_count, sizeof(*picker), GFP_KERNEL);
picker = kzalloc(alloc_size, GFP_KERNEL);
if (!picker) if (!picker)
return -ENOMEM; return -ENOMEM;
......
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
#define MLXSW_SP1_FWREV_MAJOR 13 #define MLXSW_SP1_FWREV_MAJOR 13
#define MLXSW_SP1_FWREV_MINOR 2008 #define MLXSW_SP1_FWREV_MINOR 2008
#define MLXSW_SP1_FWREV_SUBMINOR 1310 #define MLXSW_SP1_FWREV_SUBMINOR 2018
#define MLXSW_SP1_FWREV_CAN_RESET_MINOR 1702 #define MLXSW_SP1_FWREV_CAN_RESET_MINOR 1702
static const struct mlxsw_fw_rev mlxsw_sp1_fw_rev = { static const struct mlxsw_fw_rev mlxsw_sp1_fw_rev = {
...@@ -62,7 +62,7 @@ static const struct mlxsw_fw_rev mlxsw_sp1_fw_rev = { ...@@ -62,7 +62,7 @@ static const struct mlxsw_fw_rev mlxsw_sp1_fw_rev = {
#define MLXSW_SP2_FWREV_MAJOR 29 #define MLXSW_SP2_FWREV_MAJOR 29
#define MLXSW_SP2_FWREV_MINOR 2008 #define MLXSW_SP2_FWREV_MINOR 2008
#define MLXSW_SP2_FWREV_SUBMINOR 1310 #define MLXSW_SP2_FWREV_SUBMINOR 2018
static const struct mlxsw_fw_rev mlxsw_sp2_fw_rev = { static const struct mlxsw_fw_rev mlxsw_sp2_fw_rev = {
.major = MLXSW_SP2_FWREV_MAJOR, .major = MLXSW_SP2_FWREV_MAJOR,
...@@ -77,7 +77,7 @@ static const struct mlxsw_fw_rev mlxsw_sp2_fw_rev = { ...@@ -77,7 +77,7 @@ static const struct mlxsw_fw_rev mlxsw_sp2_fw_rev = {
#define MLXSW_SP3_FWREV_MAJOR 30 #define MLXSW_SP3_FWREV_MAJOR 30
#define MLXSW_SP3_FWREV_MINOR 2008 #define MLXSW_SP3_FWREV_MINOR 2008
#define MLXSW_SP3_FWREV_SUBMINOR 1310 #define MLXSW_SP3_FWREV_SUBMINOR 2018
static const struct mlxsw_fw_rev mlxsw_sp3_fw_rev = { static const struct mlxsw_fw_rev mlxsw_sp3_fw_rev = {
.major = MLXSW_SP3_FWREV_MAJOR, .major = MLXSW_SP3_FWREV_MAJOR,
...@@ -3595,7 +3595,8 @@ static int mlxsw_sp_port_lag_index_get(struct mlxsw_sp *mlxsw_sp, ...@@ -3595,7 +3595,8 @@ static int mlxsw_sp_port_lag_index_get(struct mlxsw_sp *mlxsw_sp,
} }
static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port, static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port,
struct net_device *lag_dev) struct net_device *lag_dev,
struct netlink_ext_ack *extack)
{ {
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
struct mlxsw_sp_upper *lag; struct mlxsw_sp_upper *lag;
...@@ -3631,8 +3632,20 @@ static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -3631,8 +3632,20 @@ static int mlxsw_sp_port_lag_join(struct mlxsw_sp_port *mlxsw_sp_port,
if (mlxsw_sp_port->default_vlan->fid) if (mlxsw_sp_port->default_vlan->fid)
mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port->default_vlan); mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port->default_vlan);
/* Join a router interface configured on the LAG, if exists */
err = mlxsw_sp_port_vlan_router_join(mlxsw_sp_port->default_vlan,
lag_dev, extack);
if (err)
goto err_router_join;
return 0; return 0;
err_router_join:
lag->ref_count--;
mlxsw_sp_port->lagged = 0;
mlxsw_core_lag_mapping_clear(mlxsw_sp->core, lag_id,
mlxsw_sp_port->local_port);
mlxsw_sp_lag_col_port_remove(mlxsw_sp_port, lag_id);
err_col_port_add: err_col_port_add:
if (!lag->ref_count) if (!lag->ref_count)
mlxsw_sp_lag_destroy(mlxsw_sp, lag_id); mlxsw_sp_lag_destroy(mlxsw_sp, lag_id);
...@@ -3997,7 +4010,7 @@ static int mlxsw_sp_netdevice_port_upper_event(struct net_device *lower_dev, ...@@ -3997,7 +4010,7 @@ static int mlxsw_sp_netdevice_port_upper_event(struct net_device *lower_dev,
} else if (netif_is_lag_master(upper_dev)) { } else if (netif_is_lag_master(upper_dev)) {
if (info->linking) { if (info->linking) {
err = mlxsw_sp_port_lag_join(mlxsw_sp_port, err = mlxsw_sp_port_lag_join(mlxsw_sp_port,
upper_dev); upper_dev, extack);
} else { } else {
mlxsw_sp_port_lag_col_dist_disable(mlxsw_sp_port); mlxsw_sp_port_lag_col_dist_disable(mlxsw_sp_port);
mlxsw_sp_port_lag_leave(mlxsw_sp_port, mlxsw_sp_port_lag_leave(mlxsw_sp_port,
......
...@@ -656,6 +656,10 @@ mlxsw_sp_netdevice_ipip_ul_event(struct mlxsw_sp *mlxsw_sp, ...@@ -656,6 +656,10 @@ mlxsw_sp_netdevice_ipip_ul_event(struct mlxsw_sp *mlxsw_sp,
struct net_device *l3_dev, struct net_device *l3_dev,
unsigned long event, unsigned long event,
struct netdev_notifier_info *info); struct netdev_notifier_info *info);
int
mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan,
struct net_device *l3_dev,
struct netlink_ext_ack *extack);
void void
mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan); mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan);
void mlxsw_sp_rif_destroy_by_dev(struct mlxsw_sp *mlxsw_sp, void mlxsw_sp_rif_destroy_by_dev(struct mlxsw_sp *mlxsw_sp,
......
...@@ -142,9 +142,9 @@ mlxsw_sp_ipip_nexthop_update_gre4(struct mlxsw_sp *mlxsw_sp, u32 adj_index, ...@@ -142,9 +142,9 @@ mlxsw_sp_ipip_nexthop_update_gre4(struct mlxsw_sp *mlxsw_sp, u32 adj_index,
} }
static int static int
mlxsw_sp_ipip_fib_entry_op_gre4_rtdp(struct mlxsw_sp *mlxsw_sp, mlxsw_sp_ipip_decap_config_gre4(struct mlxsw_sp *mlxsw_sp,
u32 tunnel_index, struct mlxsw_sp_ipip_entry *ipip_entry,
struct mlxsw_sp_ipip_entry *ipip_entry) u32 tunnel_index)
{ {
u16 rif_index = mlxsw_sp_ipip_lb_rif_index(ipip_entry->ol_lb); u16 rif_index = mlxsw_sp_ipip_lb_rif_index(ipip_entry->ol_lb);
u16 ul_rif_id = mlxsw_sp_ipip_lb_ul_rif_id(ipip_entry->ol_lb); u16 ul_rif_id = mlxsw_sp_ipip_lb_ul_rif_id(ipip_entry->ol_lb);
...@@ -180,43 +180,6 @@ mlxsw_sp_ipip_fib_entry_op_gre4_rtdp(struct mlxsw_sp *mlxsw_sp, ...@@ -180,43 +180,6 @@ mlxsw_sp_ipip_fib_entry_op_gre4_rtdp(struct mlxsw_sp *mlxsw_sp,
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rtdp), rtdp_pl); return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rtdp), rtdp_pl);
} }
static int
mlxsw_sp_ipip_fib_entry_op_gre4_do(struct mlxsw_sp *mlxsw_sp,
const struct mlxsw_sp_router_ll_ops *ll_ops,
struct mlxsw_sp_fib_entry_op_ctx *op_ctx,
u32 dip, u8 prefix_len, u16 ul_vr_id,
enum mlxsw_sp_fib_entry_op op,
u32 tunnel_index,
struct mlxsw_sp_fib_entry_priv *priv)
{
ll_ops->fib_entry_pack(op_ctx, MLXSW_SP_L3_PROTO_IPV4, op, ul_vr_id,
prefix_len, (unsigned char *) &dip, priv);
ll_ops->fib_entry_act_ip2me_tun_pack(op_ctx, tunnel_index);
return mlxsw_sp_fib_entry_commit(mlxsw_sp, op_ctx, ll_ops);
}
static int mlxsw_sp_ipip_fib_entry_op_gre4(struct mlxsw_sp *mlxsw_sp,
const struct mlxsw_sp_router_ll_ops *ll_ops,
struct mlxsw_sp_fib_entry_op_ctx *op_ctx,
struct mlxsw_sp_ipip_entry *ipip_entry,
enum mlxsw_sp_fib_entry_op op, u32 tunnel_index,
struct mlxsw_sp_fib_entry_priv *priv)
{
u16 ul_vr_id = mlxsw_sp_ipip_lb_ul_vr_id(ipip_entry->ol_lb);
__be32 dip;
int err;
err = mlxsw_sp_ipip_fib_entry_op_gre4_rtdp(mlxsw_sp, tunnel_index,
ipip_entry);
if (err)
return err;
dip = mlxsw_sp_ipip_netdev_saddr(MLXSW_SP_L3_PROTO_IPV4,
ipip_entry->ol_dev).addr4;
return mlxsw_sp_ipip_fib_entry_op_gre4_do(mlxsw_sp, ll_ops, op_ctx, be32_to_cpu(dip),
32, ul_vr_id, op, tunnel_index, priv);
}
static bool mlxsw_sp_ipip_tunnel_complete(enum mlxsw_sp_l3proto proto, static bool mlxsw_sp_ipip_tunnel_complete(enum mlxsw_sp_l3proto proto,
const struct net_device *ol_dev) const struct net_device *ol_dev)
{ {
...@@ -332,7 +295,7 @@ static const struct mlxsw_sp_ipip_ops mlxsw_sp_ipip_gre4_ops = { ...@@ -332,7 +295,7 @@ static const struct mlxsw_sp_ipip_ops mlxsw_sp_ipip_gre4_ops = {
.dev_type = ARPHRD_IPGRE, .dev_type = ARPHRD_IPGRE,
.ul_proto = MLXSW_SP_L3_PROTO_IPV4, .ul_proto = MLXSW_SP_L3_PROTO_IPV4,
.nexthop_update = mlxsw_sp_ipip_nexthop_update_gre4, .nexthop_update = mlxsw_sp_ipip_nexthop_update_gre4,
.fib_entry_op = mlxsw_sp_ipip_fib_entry_op_gre4, .decap_config = mlxsw_sp_ipip_decap_config_gre4,
.can_offload = mlxsw_sp_ipip_can_offload_gre4, .can_offload = mlxsw_sp_ipip_can_offload_gre4,
.ol_loopback_config = mlxsw_sp_ipip_ol_loopback_config_gre4, .ol_loopback_config = mlxsw_sp_ipip_ol_loopback_config_gre4,
.ol_netdev_change = mlxsw_sp_ipip_ol_netdev_change_gre4, .ol_netdev_change = mlxsw_sp_ipip_ol_netdev_change_gre4,
......
...@@ -50,13 +50,9 @@ struct mlxsw_sp_ipip_ops { ...@@ -50,13 +50,9 @@ struct mlxsw_sp_ipip_ops {
(*ol_loopback_config)(struct mlxsw_sp *mlxsw_sp, (*ol_loopback_config)(struct mlxsw_sp *mlxsw_sp,
const struct net_device *ol_dev); const struct net_device *ol_dev);
int (*fib_entry_op)(struct mlxsw_sp *mlxsw_sp, int (*decap_config)(struct mlxsw_sp *mlxsw_sp,
const struct mlxsw_sp_router_ll_ops *ll_ops,
struct mlxsw_sp_fib_entry_op_ctx *op_ctx,
struct mlxsw_sp_ipip_entry *ipip_entry, struct mlxsw_sp_ipip_entry *ipip_entry,
enum mlxsw_sp_fib_entry_op op, u32 tunnel_index);
u32 tunnel_index,
struct mlxsw_sp_fib_entry_priv *priv);
int (*ol_netdev_change)(struct mlxsw_sp *mlxsw_sp, int (*ol_netdev_change)(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_ipip_entry *ipip_entry, struct mlxsw_sp_ipip_entry *ipip_entry,
......
...@@ -15,7 +15,7 @@ struct mlxsw_sp_mr { ...@@ -15,7 +15,7 @@ struct mlxsw_sp_mr {
struct list_head table_list; struct list_head table_list;
struct mutex table_list_lock; /* Protects table_list */ struct mutex table_list_lock; /* Protects table_list */
#define MLXSW_SP_MR_ROUTES_COUNTER_UPDATE_INTERVAL 5000 /* ms */ #define MLXSW_SP_MR_ROUTES_COUNTER_UPDATE_INTERVAL 5000 /* ms */
unsigned long priv[0]; unsigned long priv[];
/* priv has to be always the last item */ /* priv has to be always the last item */
}; };
......
...@@ -5142,9 +5142,9 @@ static void mlxsw_sp_fib_entry_pack(struct mlxsw_sp_fib_entry_op_ctx *op_ctx, ...@@ -5142,9 +5142,9 @@ static void mlxsw_sp_fib_entry_pack(struct mlxsw_sp_fib_entry_op_ctx *op_ctx,
fib_entry->priv); fib_entry->priv);
} }
int mlxsw_sp_fib_entry_commit(struct mlxsw_sp *mlxsw_sp, static int mlxsw_sp_fib_entry_commit(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_fib_entry_op_ctx *op_ctx, struct mlxsw_sp_fib_entry_op_ctx *op_ctx,
const struct mlxsw_sp_router_ll_ops *ll_ops) const struct mlxsw_sp_router_ll_ops *ll_ops)
{ {
bool postponed_for_bulk = false; bool postponed_for_bulk = false;
int err; int err;
...@@ -5307,13 +5307,21 @@ mlxsw_sp_fib_entry_op_ipip_decap(struct mlxsw_sp *mlxsw_sp, ...@@ -5307,13 +5307,21 @@ mlxsw_sp_fib_entry_op_ipip_decap(struct mlxsw_sp *mlxsw_sp,
const struct mlxsw_sp_router_ll_ops *ll_ops = fib_entry->fib_node->fib->ll_ops; const struct mlxsw_sp_router_ll_ops *ll_ops = fib_entry->fib_node->fib->ll_ops;
struct mlxsw_sp_ipip_entry *ipip_entry = fib_entry->decap.ipip_entry; struct mlxsw_sp_ipip_entry *ipip_entry = fib_entry->decap.ipip_entry;
const struct mlxsw_sp_ipip_ops *ipip_ops; const struct mlxsw_sp_ipip_ops *ipip_ops;
int err;
if (WARN_ON(!ipip_entry)) if (WARN_ON(!ipip_entry))
return -EINVAL; return -EINVAL;
ipip_ops = mlxsw_sp->router->ipip_ops_arr[ipip_entry->ipipt]; ipip_ops = mlxsw_sp->router->ipip_ops_arr[ipip_entry->ipipt];
return ipip_ops->fib_entry_op(mlxsw_sp, ll_ops, op_ctx, ipip_entry, op, err = ipip_ops->decap_config(mlxsw_sp, ipip_entry,
fib_entry->decap.tunnel_index, fib_entry->priv); fib_entry->decap.tunnel_index);
if (err)
return err;
mlxsw_sp_fib_entry_pack(op_ctx, fib_entry, op);
ll_ops->fib_entry_act_ip2me_tun_pack(op_ctx,
fib_entry->decap.tunnel_index);
return mlxsw_sp_fib_entry_commit(mlxsw_sp, op_ctx, ll_ops);
} }
static int mlxsw_sp_fib_entry_op_nve_decap(struct mlxsw_sp *mlxsw_sp, static int mlxsw_sp_fib_entry_op_nve_decap(struct mlxsw_sp *mlxsw_sp,
...@@ -7697,9 +7705,9 @@ static void mlxsw_sp_rif_subport_put(struct mlxsw_sp_rif *rif) ...@@ -7697,9 +7705,9 @@ static void mlxsw_sp_rif_subport_put(struct mlxsw_sp_rif *rif)
} }
static int static int
mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan, __mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan,
struct net_device *l3_dev, struct net_device *l3_dev,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp_port_vlan->mlxsw_sp_port; struct mlxsw_sp_port *mlxsw_sp_port = mlxsw_sp_port_vlan->mlxsw_sp_port;
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
...@@ -7764,6 +7772,27 @@ __mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan) ...@@ -7764,6 +7772,27 @@ __mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan)
mlxsw_sp_rif_subport_put(rif); mlxsw_sp_rif_subport_put(rif);
} }
int
mlxsw_sp_port_vlan_router_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan,
struct net_device *l3_dev,
struct netlink_ext_ack *extack)
{
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port_vlan->mlxsw_sp_port->mlxsw_sp;
struct mlxsw_sp_rif *rif;
int err = 0;
mutex_lock(&mlxsw_sp->router->lock);
rif = mlxsw_sp_rif_find_by_dev(mlxsw_sp, l3_dev);
if (!rif)
goto out;
err = __mlxsw_sp_port_vlan_router_join(mlxsw_sp_port_vlan, l3_dev,
extack);
out:
mutex_unlock(&mlxsw_sp->router->lock);
return err;
}
void void
mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan) mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan)
{ {
...@@ -7788,8 +7817,8 @@ static int mlxsw_sp_inetaddr_port_vlan_event(struct net_device *l3_dev, ...@@ -7788,8 +7817,8 @@ static int mlxsw_sp_inetaddr_port_vlan_event(struct net_device *l3_dev,
switch (event) { switch (event) {
case NETDEV_UP: case NETDEV_UP:
return mlxsw_sp_port_vlan_router_join(mlxsw_sp_port_vlan, return __mlxsw_sp_port_vlan_router_join(mlxsw_sp_port_vlan,
l3_dev, extack); l3_dev, extack);
case NETDEV_DOWN: case NETDEV_DOWN:
__mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port_vlan); __mlxsw_sp_port_vlan_router_leave(mlxsw_sp_port_vlan);
break; break;
......
...@@ -118,10 +118,6 @@ struct mlxsw_sp_router_ll_ops { ...@@ -118,10 +118,6 @@ struct mlxsw_sp_router_ll_ops {
bool (*fib_entry_is_committed)(struct mlxsw_sp_fib_entry_priv *priv); bool (*fib_entry_is_committed)(struct mlxsw_sp_fib_entry_priv *priv);
}; };
int mlxsw_sp_fib_entry_commit(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_fib_entry_op_ctx *op_ctx,
const struct mlxsw_sp_router_ll_ops *ll_ops);
struct mlxsw_sp_rif_ipip_lb; struct mlxsw_sp_rif_ipip_lb;
struct mlxsw_sp_rif_ipip_lb_config { struct mlxsw_sp_rif_ipip_lb_config {
enum mlxsw_reg_ritr_loopback_ipip_type lb_ipipt; enum mlxsw_reg_ritr_loopback_ipip_type lb_ipipt;
......
...@@ -22,6 +22,7 @@ ALL_TESTS=" ...@@ -22,6 +22,7 @@ ALL_TESTS="
duplicate_vlans_test duplicate_vlans_test
vlan_rif_refcount_test vlan_rif_refcount_test
subport_rif_refcount_test subport_rif_refcount_test
subport_rif_lag_join_test
vlan_dev_deletion_test vlan_dev_deletion_test
lag_unlink_slaves_test lag_unlink_slaves_test
lag_dev_deletion_test lag_dev_deletion_test
...@@ -440,6 +441,48 @@ subport_rif_refcount_test() ...@@ -440,6 +441,48 @@ subport_rif_refcount_test()
ip link del dev bond1 ip link del dev bond1
} }
subport_rif_lag_join_test()
{
# Test that the reference count of a RIF configured for a LAG is
# incremented / decremented when ports join / leave the LAG. We use the
# offload indication on routes configured on the RIF to understand if
# it was created / destroyed
RET=0
ip link add name bond1 type bond mode 802.3ad
ip link set dev $swp1 down
ip link set dev $swp2 down
ip link set dev $swp1 master bond1
ip link set dev $swp2 master bond1
ip link set dev bond1 up
ip -6 address add 2001:db8:1::1/64 dev bond1
busywait "$TIMEOUT" wait_for_offload \
ip -6 route get fibmatch 2001:db8:1::2 dev bond1
check_err $? "subport rif was not created on lag device"
ip link set dev $swp1 nomaster
busywait "$TIMEOUT" wait_for_offload \
ip -6 route get fibmatch 2001:db8:1::2 dev bond1
check_err $? "subport rif of lag device was destroyed after removing one port"
ip link set dev $swp1 master bond1
ip link set dev $swp2 nomaster
busywait "$TIMEOUT" wait_for_offload \
ip -6 route get fibmatch 2001:db8:1::2 dev bond1
check_err $? "subport rif of lag device was destroyed after re-adding a port and removing another"
ip link set dev $swp1 nomaster
busywait "$TIMEOUT" not wait_for_offload \
ip -6 route get fibmatch 2001:db8:1::2 dev bond1
check_err $? "subport rif of lag device was not destroyed when should"
log_test "subport rif lag join"
ip link del dev bond1
}
vlan_dev_deletion_test() vlan_dev_deletion_test()
{ {
# Test that VLAN devices are correctly deleted / unlinked when enslaved # Test that VLAN devices are correctly deleted / unlinked when enslaved
......
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