Commit 1cc38fb1 authored by Petr Machata's avatar Petr Machata Committed by David S. Miller

mlxsw: spectrum_router: Use existing decap route

The local route that points at IPIP's underlay device (decap route) can
be present long before the GRE device. Thus when an encap route is
added, it's necessary to look inside the underlay FIB if the decap route
is already present. If so, the current trap offload needs to be
withdrawn and replaced with a decap offload.
Signed-off-by: default avatarPetr Machata <petrm@mellanox.com>
Reviewed-by: default avatarIdo Schimmel <idosch@mellanox.com>
Signed-off-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 4607f6d2
...@@ -1072,6 +1072,9 @@ static void mlxsw_sp_fib_entry_decap_fini(struct mlxsw_sp *mlxsw_sp, ...@@ -1072,6 +1072,9 @@ static void mlxsw_sp_fib_entry_decap_fini(struct mlxsw_sp *mlxsw_sp,
mlxsw_sp_kvdl_free(mlxsw_sp, fib_entry->decap.tunnel_index); mlxsw_sp_kvdl_free(mlxsw_sp, fib_entry->decap.tunnel_index);
} }
static struct mlxsw_sp_fib_node *
mlxsw_sp_fib_node_lookup(struct mlxsw_sp_fib *fib, const void *addr,
size_t addr_len, unsigned char prefix_len);
static int mlxsw_sp_fib_entry_update(struct mlxsw_sp *mlxsw_sp, static int mlxsw_sp_fib_entry_update(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_fib_entry *fib_entry); struct mlxsw_sp_fib_entry *fib_entry);
...@@ -1087,6 +1090,73 @@ mlxsw_sp_ipip_entry_demote_decap(struct mlxsw_sp *mlxsw_sp, ...@@ -1087,6 +1090,73 @@ mlxsw_sp_ipip_entry_demote_decap(struct mlxsw_sp *mlxsw_sp,
mlxsw_sp_fib_entry_update(mlxsw_sp, fib_entry); mlxsw_sp_fib_entry_update(mlxsw_sp, fib_entry);
} }
static void
mlxsw_sp_ipip_entry_promote_decap(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_ipip_entry *ipip_entry,
struct mlxsw_sp_fib_entry *decap_fib_entry)
{
if (mlxsw_sp_fib_entry_decap_init(mlxsw_sp, decap_fib_entry,
ipip_entry))
return;
decap_fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_IPIP_DECAP;
if (mlxsw_sp_fib_entry_update(mlxsw_sp, decap_fib_entry))
mlxsw_sp_ipip_entry_demote_decap(mlxsw_sp, ipip_entry);
}
/* Given an IPIP entry, find the corresponding decap route. */
static struct mlxsw_sp_fib_entry *
mlxsw_sp_ipip_entry_find_decap(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_ipip_entry *ipip_entry)
{
static struct mlxsw_sp_fib_node *fib_node;
const struct mlxsw_sp_ipip_ops *ipip_ops;
struct mlxsw_sp_fib_entry *fib_entry;
unsigned char saddr_prefix_len;
union mlxsw_sp_l3addr saddr;
struct mlxsw_sp_fib *ul_fib;
struct mlxsw_sp_vr *ul_vr;
const void *saddrp;
size_t saddr_len;
u32 ul_tb_id;
u32 saddr4;
ipip_ops = mlxsw_sp->router->ipip_ops_arr[ipip_entry->ipipt];
ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(ipip_entry->ol_dev);
ul_vr = mlxsw_sp_vr_find(mlxsw_sp, ul_tb_id);
if (!ul_vr)
return NULL;
ul_fib = mlxsw_sp_vr_fib(ul_vr, ipip_ops->ul_proto);
saddr = mlxsw_sp_ipip_netdev_saddr(ipip_ops->ul_proto,
ipip_entry->ol_dev);
switch (ipip_ops->ul_proto) {
case MLXSW_SP_L3_PROTO_IPV4:
saddr4 = be32_to_cpu(saddr.addr4);
saddrp = &saddr4;
saddr_len = 4;
saddr_prefix_len = 32;
break;
case MLXSW_SP_L3_PROTO_IPV6:
WARN_ON(1);
return NULL;
}
fib_node = mlxsw_sp_fib_node_lookup(ul_fib, saddrp, saddr_len,
saddr_prefix_len);
if (!fib_node || list_empty(&fib_node->entry_list))
return NULL;
fib_entry = list_first_entry(&fib_node->entry_list,
struct mlxsw_sp_fib_entry, list);
if (fib_entry->type != MLXSW_SP_FIB_ENTRY_TYPE_TRAP)
return NULL;
return fib_entry;
}
static struct mlxsw_sp_ipip_entry * static struct mlxsw_sp_ipip_entry *
mlxsw_sp_ipip_entry_get(struct mlxsw_sp *mlxsw_sp, mlxsw_sp_ipip_entry_get(struct mlxsw_sp *mlxsw_sp,
enum mlxsw_sp_ipip_type ipipt, enum mlxsw_sp_ipip_type ipipt,
...@@ -1094,6 +1164,7 @@ mlxsw_sp_ipip_entry_get(struct mlxsw_sp *mlxsw_sp, ...@@ -1094,6 +1164,7 @@ mlxsw_sp_ipip_entry_get(struct mlxsw_sp *mlxsw_sp,
{ {
u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(ol_dev); u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(ol_dev);
struct mlxsw_sp_router *router = mlxsw_sp->router; struct mlxsw_sp_router *router = mlxsw_sp->router;
struct mlxsw_sp_fib_entry *decap_fib_entry;
struct mlxsw_sp_ipip_entry *ipip_entry; struct mlxsw_sp_ipip_entry *ipip_entry;
enum mlxsw_sp_l3proto ul_proto; enum mlxsw_sp_l3proto ul_proto;
union mlxsw_sp_l3addr saddr; union mlxsw_sp_l3addr saddr;
...@@ -1118,6 +1189,11 @@ mlxsw_sp_ipip_entry_get(struct mlxsw_sp *mlxsw_sp, ...@@ -1118,6 +1189,11 @@ mlxsw_sp_ipip_entry_get(struct mlxsw_sp *mlxsw_sp,
if (IS_ERR(ipip_entry)) if (IS_ERR(ipip_entry))
return ipip_entry; return ipip_entry;
decap_fib_entry = mlxsw_sp_ipip_entry_find_decap(mlxsw_sp, ipip_entry);
if (decap_fib_entry)
mlxsw_sp_ipip_entry_promote_decap(mlxsw_sp, ipip_entry,
decap_fib_entry);
list_add_tail(&ipip_entry->ipip_list_node, list_add_tail(&ipip_entry->ipip_list_node,
&mlxsw_sp->router->ipip_list); &mlxsw_sp->router->ipip_list);
...@@ -3259,10 +3335,6 @@ static void mlxsw_sp_fib4_entry_destroy(struct mlxsw_sp *mlxsw_sp, ...@@ -3259,10 +3335,6 @@ static void mlxsw_sp_fib4_entry_destroy(struct mlxsw_sp *mlxsw_sp,
kfree(fib4_entry); kfree(fib4_entry);
} }
static struct mlxsw_sp_fib_node *
mlxsw_sp_fib_node_lookup(struct mlxsw_sp_fib *fib, const void *addr,
size_t addr_len, unsigned char prefix_len);
static struct mlxsw_sp_fib4_entry * static struct mlxsw_sp_fib4_entry *
mlxsw_sp_fib4_entry_lookup(struct mlxsw_sp *mlxsw_sp, mlxsw_sp_fib4_entry_lookup(struct mlxsw_sp *mlxsw_sp,
const struct fib_entry_notifier_info *fen_info) const struct fib_entry_notifier_info *fen_info)
......
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