mirror of
https://github.com/FEX-Emu/linux.git
synced 2025-01-03 07:41:40 +00:00
Merge branch 'mlxsw-IPv6-and-reference-counting-fixes'
Ido Schimmel says:
====================
mlxsw: IPv6 and reference counting fixes
The first three patches fix a mismatch between the new IPv6 behavior
introduced in commit f34436a430
("net/ipv6: Simplify route replace and
appending into multipath route") and mlxsw. The patches allow the driver
to support multipathing in IPv6 overlays with GRE tunnel devices. A
selftest will be submitted when net-next opens.
The last patch fixes a reference count problem of the port_vlan struct.
I plan to simplify the code in net-next, so that reference counting is
not necessary anymore.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
eab9a2d5f3
@ -4756,12 +4756,6 @@ static void mlxsw_sp_rt6_destroy(struct mlxsw_sp_rt6 *mlxsw_sp_rt6)
|
|||||||
kfree(mlxsw_sp_rt6);
|
kfree(mlxsw_sp_rt6);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool mlxsw_sp_fib6_rt_can_mp(const struct fib6_info *rt)
|
|
||||||
{
|
|
||||||
/* RTF_CACHE routes are ignored */
|
|
||||||
return (rt->fib6_flags & (RTF_GATEWAY | RTF_ADDRCONF)) == RTF_GATEWAY;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct fib6_info *
|
static struct fib6_info *
|
||||||
mlxsw_sp_fib6_entry_rt(const struct mlxsw_sp_fib6_entry *fib6_entry)
|
mlxsw_sp_fib6_entry_rt(const struct mlxsw_sp_fib6_entry *fib6_entry)
|
||||||
{
|
{
|
||||||
@ -4771,11 +4765,11 @@ mlxsw_sp_fib6_entry_rt(const struct mlxsw_sp_fib6_entry *fib6_entry)
|
|||||||
|
|
||||||
static struct mlxsw_sp_fib6_entry *
|
static struct mlxsw_sp_fib6_entry *
|
||||||
mlxsw_sp_fib6_node_mp_entry_find(const struct mlxsw_sp_fib_node *fib_node,
|
mlxsw_sp_fib6_node_mp_entry_find(const struct mlxsw_sp_fib_node *fib_node,
|
||||||
const struct fib6_info *nrt, bool replace)
|
const struct fib6_info *nrt, bool append)
|
||||||
{
|
{
|
||||||
struct mlxsw_sp_fib6_entry *fib6_entry;
|
struct mlxsw_sp_fib6_entry *fib6_entry;
|
||||||
|
|
||||||
if (!mlxsw_sp_fib6_rt_can_mp(nrt) || replace)
|
if (!append)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
list_for_each_entry(fib6_entry, &fib_node->entry_list, common.list) {
|
list_for_each_entry(fib6_entry, &fib_node->entry_list, common.list) {
|
||||||
@ -4790,8 +4784,7 @@ mlxsw_sp_fib6_node_mp_entry_find(const struct mlxsw_sp_fib_node *fib_node,
|
|||||||
break;
|
break;
|
||||||
if (rt->fib6_metric < nrt->fib6_metric)
|
if (rt->fib6_metric < nrt->fib6_metric)
|
||||||
continue;
|
continue;
|
||||||
if (rt->fib6_metric == nrt->fib6_metric &&
|
if (rt->fib6_metric == nrt->fib6_metric)
|
||||||
mlxsw_sp_fib6_rt_can_mp(rt))
|
|
||||||
return fib6_entry;
|
return fib6_entry;
|
||||||
if (rt->fib6_metric > nrt->fib6_metric)
|
if (rt->fib6_metric > nrt->fib6_metric)
|
||||||
break;
|
break;
|
||||||
@ -5170,7 +5163,7 @@ static struct mlxsw_sp_fib6_entry *
|
|||||||
mlxsw_sp_fib6_node_entry_find(const struct mlxsw_sp_fib_node *fib_node,
|
mlxsw_sp_fib6_node_entry_find(const struct mlxsw_sp_fib_node *fib_node,
|
||||||
const struct fib6_info *nrt, bool replace)
|
const struct fib6_info *nrt, bool replace)
|
||||||
{
|
{
|
||||||
struct mlxsw_sp_fib6_entry *fib6_entry, *fallback = NULL;
|
struct mlxsw_sp_fib6_entry *fib6_entry;
|
||||||
|
|
||||||
list_for_each_entry(fib6_entry, &fib_node->entry_list, common.list) {
|
list_for_each_entry(fib6_entry, &fib_node->entry_list, common.list) {
|
||||||
struct fib6_info *rt = mlxsw_sp_fib6_entry_rt(fib6_entry);
|
struct fib6_info *rt = mlxsw_sp_fib6_entry_rt(fib6_entry);
|
||||||
@ -5179,18 +5172,13 @@ mlxsw_sp_fib6_node_entry_find(const struct mlxsw_sp_fib_node *fib_node,
|
|||||||
continue;
|
continue;
|
||||||
if (rt->fib6_table->tb6_id != nrt->fib6_table->tb6_id)
|
if (rt->fib6_table->tb6_id != nrt->fib6_table->tb6_id)
|
||||||
break;
|
break;
|
||||||
if (replace && rt->fib6_metric == nrt->fib6_metric) {
|
if (replace && rt->fib6_metric == nrt->fib6_metric)
|
||||||
if (mlxsw_sp_fib6_rt_can_mp(rt) ==
|
return fib6_entry;
|
||||||
mlxsw_sp_fib6_rt_can_mp(nrt))
|
|
||||||
return fib6_entry;
|
|
||||||
if (mlxsw_sp_fib6_rt_can_mp(nrt))
|
|
||||||
fallback = fallback ?: fib6_entry;
|
|
||||||
}
|
|
||||||
if (rt->fib6_metric > nrt->fib6_metric)
|
if (rt->fib6_metric > nrt->fib6_metric)
|
||||||
return fallback ?: fib6_entry;
|
return fib6_entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
return fallback;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -5316,7 +5304,8 @@ static void mlxsw_sp_fib6_entry_replace(struct mlxsw_sp *mlxsw_sp,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int mlxsw_sp_router_fib6_add(struct mlxsw_sp *mlxsw_sp,
|
static int mlxsw_sp_router_fib6_add(struct mlxsw_sp *mlxsw_sp,
|
||||||
struct fib6_info *rt, bool replace)
|
struct fib6_info *rt, bool replace,
|
||||||
|
bool append)
|
||||||
{
|
{
|
||||||
struct mlxsw_sp_fib6_entry *fib6_entry;
|
struct mlxsw_sp_fib6_entry *fib6_entry;
|
||||||
struct mlxsw_sp_fib_node *fib_node;
|
struct mlxsw_sp_fib_node *fib_node;
|
||||||
@ -5342,7 +5331,7 @@ static int mlxsw_sp_router_fib6_add(struct mlxsw_sp *mlxsw_sp,
|
|||||||
/* Before creating a new entry, try to append route to an existing
|
/* Before creating a new entry, try to append route to an existing
|
||||||
* multipath entry.
|
* multipath entry.
|
||||||
*/
|
*/
|
||||||
fib6_entry = mlxsw_sp_fib6_node_mp_entry_find(fib_node, rt, replace);
|
fib6_entry = mlxsw_sp_fib6_node_mp_entry_find(fib_node, rt, append);
|
||||||
if (fib6_entry) {
|
if (fib6_entry) {
|
||||||
err = mlxsw_sp_fib6_entry_nexthop_add(mlxsw_sp, fib6_entry, rt);
|
err = mlxsw_sp_fib6_entry_nexthop_add(mlxsw_sp, fib6_entry, rt);
|
||||||
if (err)
|
if (err)
|
||||||
@ -5350,6 +5339,14 @@ static int mlxsw_sp_router_fib6_add(struct mlxsw_sp *mlxsw_sp,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We received an append event, yet did not find any route to
|
||||||
|
* append to.
|
||||||
|
*/
|
||||||
|
if (WARN_ON(append)) {
|
||||||
|
err = -EINVAL;
|
||||||
|
goto err_fib6_entry_append;
|
||||||
|
}
|
||||||
|
|
||||||
fib6_entry = mlxsw_sp_fib6_entry_create(mlxsw_sp, fib_node, rt);
|
fib6_entry = mlxsw_sp_fib6_entry_create(mlxsw_sp, fib_node, rt);
|
||||||
if (IS_ERR(fib6_entry)) {
|
if (IS_ERR(fib6_entry)) {
|
||||||
err = PTR_ERR(fib6_entry);
|
err = PTR_ERR(fib6_entry);
|
||||||
@ -5367,6 +5364,7 @@ static int mlxsw_sp_router_fib6_add(struct mlxsw_sp *mlxsw_sp,
|
|||||||
err_fib6_node_entry_link:
|
err_fib6_node_entry_link:
|
||||||
mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_entry);
|
mlxsw_sp_fib6_entry_destroy(mlxsw_sp, fib6_entry);
|
||||||
err_fib6_entry_create:
|
err_fib6_entry_create:
|
||||||
|
err_fib6_entry_append:
|
||||||
err_fib6_entry_nexthop_add:
|
err_fib6_entry_nexthop_add:
|
||||||
mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
|
mlxsw_sp_fib_node_put(mlxsw_sp, fib_node);
|
||||||
return err;
|
return err;
|
||||||
@ -5717,7 +5715,7 @@ static void mlxsw_sp_router_fib6_event_work(struct work_struct *work)
|
|||||||
struct mlxsw_sp_fib_event_work *fib_work =
|
struct mlxsw_sp_fib_event_work *fib_work =
|
||||||
container_of(work, struct mlxsw_sp_fib_event_work, work);
|
container_of(work, struct mlxsw_sp_fib_event_work, work);
|
||||||
struct mlxsw_sp *mlxsw_sp = fib_work->mlxsw_sp;
|
struct mlxsw_sp *mlxsw_sp = fib_work->mlxsw_sp;
|
||||||
bool replace;
|
bool replace, append;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
rtnl_lock();
|
rtnl_lock();
|
||||||
@ -5728,8 +5726,10 @@ static void mlxsw_sp_router_fib6_event_work(struct work_struct *work)
|
|||||||
case FIB_EVENT_ENTRY_APPEND: /* fall through */
|
case FIB_EVENT_ENTRY_APPEND: /* fall through */
|
||||||
case FIB_EVENT_ENTRY_ADD:
|
case FIB_EVENT_ENTRY_ADD:
|
||||||
replace = fib_work->event == FIB_EVENT_ENTRY_REPLACE;
|
replace = fib_work->event == FIB_EVENT_ENTRY_REPLACE;
|
||||||
|
append = fib_work->event == FIB_EVENT_ENTRY_APPEND;
|
||||||
err = mlxsw_sp_router_fib6_add(mlxsw_sp,
|
err = mlxsw_sp_router_fib6_add(mlxsw_sp,
|
||||||
fib_work->fen6_info.rt, replace);
|
fib_work->fen6_info.rt, replace,
|
||||||
|
append);
|
||||||
if (err)
|
if (err)
|
||||||
mlxsw_sp_router_fib_abort(mlxsw_sp);
|
mlxsw_sp_router_fib_abort(mlxsw_sp);
|
||||||
mlxsw_sp_rt6_release(fib_work->fen6_info.rt);
|
mlxsw_sp_rt6_release(fib_work->fen6_info.rt);
|
||||||
|
@ -1018,8 +1018,10 @@ mlxsw_sp_port_vlan_bridge_join(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan,
|
|||||||
int err;
|
int err;
|
||||||
|
|
||||||
/* No need to continue if only VLAN flags were changed */
|
/* No need to continue if only VLAN flags were changed */
|
||||||
if (mlxsw_sp_port_vlan->bridge_port)
|
if (mlxsw_sp_port_vlan->bridge_port) {
|
||||||
|
mlxsw_sp_port_vlan_put(mlxsw_sp_port_vlan);
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
err = mlxsw_sp_port_vlan_fid_join(mlxsw_sp_port_vlan, bridge_port);
|
err = mlxsw_sp_port_vlan_fid_join(mlxsw_sp_port_vlan, bridge_port);
|
||||||
if (err)
|
if (err)
|
||||||
|
@ -934,6 +934,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt,
|
|||||||
{
|
{
|
||||||
struct fib6_info *leaf = rcu_dereference_protected(fn->leaf,
|
struct fib6_info *leaf = rcu_dereference_protected(fn->leaf,
|
||||||
lockdep_is_held(&rt->fib6_table->tb6_lock));
|
lockdep_is_held(&rt->fib6_table->tb6_lock));
|
||||||
|
enum fib_event_type event = FIB_EVENT_ENTRY_ADD;
|
||||||
struct fib6_info *iter = NULL, *match = NULL;
|
struct fib6_info *iter = NULL, *match = NULL;
|
||||||
struct fib6_info __rcu **ins;
|
struct fib6_info __rcu **ins;
|
||||||
int replace = (info->nlh &&
|
int replace = (info->nlh &&
|
||||||
@ -1013,6 +1014,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt,
|
|||||||
"Can not append to a REJECT route");
|
"Can not append to a REJECT route");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
event = FIB_EVENT_ENTRY_APPEND;
|
||||||
rt->fib6_nsiblings = match->fib6_nsiblings;
|
rt->fib6_nsiblings = match->fib6_nsiblings;
|
||||||
list_add_tail(&rt->fib6_siblings, &match->fib6_siblings);
|
list_add_tail(&rt->fib6_siblings, &match->fib6_siblings);
|
||||||
match->fib6_nsiblings++;
|
match->fib6_nsiblings++;
|
||||||
@ -1034,15 +1036,12 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt,
|
|||||||
* insert node
|
* insert node
|
||||||
*/
|
*/
|
||||||
if (!replace) {
|
if (!replace) {
|
||||||
enum fib_event_type event;
|
|
||||||
|
|
||||||
if (!add)
|
if (!add)
|
||||||
pr_warn("NLM_F_CREATE should be set when creating new route\n");
|
pr_warn("NLM_F_CREATE should be set when creating new route\n");
|
||||||
|
|
||||||
add:
|
add:
|
||||||
nlflags |= NLM_F_CREATE;
|
nlflags |= NLM_F_CREATE;
|
||||||
|
|
||||||
event = append ? FIB_EVENT_ENTRY_APPEND : FIB_EVENT_ENTRY_ADD;
|
|
||||||
err = call_fib6_entry_notifiers(info->nl_net, event, rt,
|
err = call_fib6_entry_notifiers(info->nl_net, event, rt,
|
||||||
extack);
|
extack);
|
||||||
if (err)
|
if (err)
|
||||||
|
Loading…
Reference in New Issue
Block a user