Skip to content

Commit 6ddb742

Browse files
pmachatadavem330
authored andcommitted
mlxsw: spectrum_router: Introduce loopback RIFs
When offloading L3 tunnels, an adjacency entry is created that loops the packet back into the underlay router. Loopback interfaces then hold the corresponding information and are created for IP-in-IP netdevices. Signed-off-by: Petr Machata <[email protected]> Reviewed-by: Ido Schimmel <[email protected]> Signed-off-by: Jiri Pirko <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 010cadf commit 6ddb742

File tree

3 files changed

+164
-2
lines changed

3 files changed

+164
-2
lines changed

drivers/net/ethernet/mellanox/mlxsw/spectrum.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ enum mlxsw_sp_rif_type {
7777
MLXSW_SP_RIF_TYPE_SUBPORT,
7878
MLXSW_SP_RIF_TYPE_VLAN,
7979
MLXSW_SP_RIF_TYPE_FID,
80+
MLXSW_SP_RIF_TYPE_IPIP_LB, /* IP-in-IP loopback. */
8081
MLXSW_SP_RIF_TYPE_MAX,
8182
};
8283

drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c

Lines changed: 150 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
/*
22
* drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
3-
* Copyright (c) 2016 Mellanox Technologies. All rights reserved.
3+
* Copyright (c) 2016-2017 Mellanox Technologies. All rights reserved.
44
* Copyright (c) 2016 Jiri Pirko <[email protected]>
55
* Copyright (c) 2016 Ido Schimmel <[email protected]>
66
* Copyright (c) 2016 Yotam Gigi <[email protected]>
7+
* Copyright (c) 2017 Petr Machata <[email protected]>
78
*
89
* Redistribution and use in source and binary forms, with or without
910
* modification, are permitted provided that the following conditions are met:
@@ -51,6 +52,7 @@
5152
#include <net/ip_fib.h>
5253
#include <net/ip6_fib.h>
5354
#include <net/fib_rules.h>
55+
#include <net/ip_tunnels.h>
5456
#include <net/l3mdev.h>
5557
#include <net/addrconf.h>
5658
#include <net/ndisc.h>
@@ -131,6 +133,17 @@ struct mlxsw_sp_rif_subport {
131133
bool lag;
132134
};
133135

136+
struct mlxsw_sp_rif_ipip_lb {
137+
struct mlxsw_sp_rif common;
138+
struct mlxsw_sp_rif_ipip_lb_config lb_config;
139+
u16 ul_vr_id; /* Reserved for Spectrum-2. */
140+
};
141+
142+
struct mlxsw_sp_rif_params_ipip_lb {
143+
struct mlxsw_sp_rif_params common;
144+
struct mlxsw_sp_rif_ipip_lb_config lb_config;
145+
};
146+
134147
struct mlxsw_sp_rif_ops {
135148
enum mlxsw_sp_rif_type type;
136149
size_t rif_size;
@@ -883,6 +896,25 @@ static void mlxsw_sp_vrs_fini(struct mlxsw_sp *mlxsw_sp)
883896
kfree(mlxsw_sp->router->vrs);
884897
}
885898

899+
static struct net_device *
900+
__mlxsw_sp_ipip_netdev_ul_dev_get(const struct net_device *ol_dev)
901+
{
902+
struct ip_tunnel *tun = netdev_priv(ol_dev);
903+
struct net *net = dev_net(ol_dev);
904+
905+
return __dev_get_by_index(net, tun->parms.link);
906+
}
907+
908+
static u32 mlxsw_sp_ipip_dev_ul_tb_id(const struct net_device *ol_dev)
909+
{
910+
struct net_device *d = __mlxsw_sp_ipip_netdev_ul_dev_get(ol_dev);
911+
912+
if (d)
913+
return l3mdev_fib_table(d) ? : RT_TABLE_MAIN;
914+
else
915+
return l3mdev_fib_table(ol_dev) ? : RT_TABLE_MAIN;
916+
}
917+
886918
struct mlxsw_sp_neigh_key {
887919
struct neighbour *n;
888920
};
@@ -2236,6 +2268,25 @@ static void mlxsw_sp_nexthop_neigh_fini(struct mlxsw_sp *mlxsw_sp,
22362268
neigh_release(n);
22372269
}
22382270

2271+
static bool mlxsw_sp_netdev_ipip_type(const struct mlxsw_sp *mlxsw_sp,
2272+
const struct net_device *dev,
2273+
enum mlxsw_sp_ipip_type *p_type)
2274+
{
2275+
struct mlxsw_sp_router *router = mlxsw_sp->router;
2276+
const struct mlxsw_sp_ipip_ops *ipip_ops;
2277+
enum mlxsw_sp_ipip_type ipipt;
2278+
2279+
for (ipipt = 0; ipipt < MLXSW_SP_IPIP_TYPE_MAX; ++ipipt) {
2280+
ipip_ops = router->ipip_ops_arr[ipipt];
2281+
if (dev->type == ipip_ops->dev_type) {
2282+
if (p_type)
2283+
*p_type = ipipt;
2284+
return true;
2285+
}
2286+
}
2287+
return false;
2288+
}
2289+
22392290
static int mlxsw_sp_nexthop4_init(struct mlxsw_sp *mlxsw_sp,
22402291
struct mlxsw_sp_nexthop_group *nh_grp,
22412292
struct mlxsw_sp_nexthop *nh,
@@ -4374,7 +4425,10 @@ mlxsw_sp_dev_rif_type(const struct mlxsw_sp *mlxsw_sp,
43744425
{
43754426
enum mlxsw_sp_fid_type type;
43764427

4377-
/* RIF type is derived from the type of the underlying FID */
4428+
if (mlxsw_sp_netdev_ipip_type(mlxsw_sp, dev, NULL))
4429+
return MLXSW_SP_RIF_TYPE_IPIP_LB;
4430+
4431+
/* Otherwise RIF type is derived from the type of the underlying FID. */
43784432
if (is_vlan_dev(dev) && netif_is_bridge_master(vlan_dev_real_dev(dev)))
43794433
type = MLXSW_SP_FID_TYPE_8021Q;
43804434
else if (netif_is_bridge_master(dev) && br_vlan_enabled(dev))
@@ -5164,10 +5218,104 @@ static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_fid_ops = {
51645218
.fid_get = mlxsw_sp_rif_fid_fid_get,
51655219
};
51665220

5221+
static struct mlxsw_sp_rif_ipip_lb *
5222+
mlxsw_sp_rif_ipip_lb_rif(struct mlxsw_sp_rif *rif)
5223+
{
5224+
return container_of(rif, struct mlxsw_sp_rif_ipip_lb, common);
5225+
}
5226+
5227+
static void
5228+
mlxsw_sp_rif_ipip_lb_setup(struct mlxsw_sp_rif *rif,
5229+
const struct mlxsw_sp_rif_params *params)
5230+
{
5231+
struct mlxsw_sp_rif_params_ipip_lb *params_lb;
5232+
struct mlxsw_sp_rif_ipip_lb *rif_lb;
5233+
5234+
params_lb = container_of(params, struct mlxsw_sp_rif_params_ipip_lb,
5235+
common);
5236+
rif_lb = mlxsw_sp_rif_ipip_lb_rif(rif);
5237+
rif_lb->lb_config = params_lb->lb_config;
5238+
}
5239+
5240+
static int
5241+
mlxsw_sp_rif_ipip_lb_op(struct mlxsw_sp_rif_ipip_lb *lb_rif,
5242+
struct mlxsw_sp_vr *ul_vr, bool enable)
5243+
{
5244+
struct mlxsw_sp_rif_ipip_lb_config lb_cf = lb_rif->lb_config;
5245+
struct mlxsw_sp_rif *rif = &lb_rif->common;
5246+
struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
5247+
char ritr_pl[MLXSW_REG_RITR_LEN];
5248+
u32 saddr4;
5249+
5250+
switch (lb_cf.ul_protocol) {
5251+
case MLXSW_SP_L3_PROTO_IPV4:
5252+
saddr4 = be32_to_cpu(lb_cf.saddr.addr4);
5253+
mlxsw_reg_ritr_pack(ritr_pl, enable, MLXSW_REG_RITR_LOOPBACK_IF,
5254+
rif->rif_index, rif->vr_id, rif->dev->mtu);
5255+
mlxsw_reg_ritr_loopback_ipip4_pack(ritr_pl, lb_cf.lb_ipipt,
5256+
MLXSW_REG_RITR_LOOPBACK_IPIP_OPTIONS_GRE_KEY_PRESET,
5257+
ul_vr->id, saddr4, lb_cf.okey);
5258+
break;
5259+
5260+
case MLXSW_SP_L3_PROTO_IPV6:
5261+
return -EAFNOSUPPORT;
5262+
}
5263+
5264+
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ritr), ritr_pl);
5265+
}
5266+
5267+
static int
5268+
mlxsw_sp_rif_ipip_lb_configure(struct mlxsw_sp_rif *rif)
5269+
{
5270+
struct mlxsw_sp_rif_ipip_lb *lb_rif = mlxsw_sp_rif_ipip_lb_rif(rif);
5271+
u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(rif->dev);
5272+
struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
5273+
struct mlxsw_sp_vr *ul_vr;
5274+
int err;
5275+
5276+
ul_vr = mlxsw_sp_vr_get(mlxsw_sp, ul_tb_id);
5277+
if (IS_ERR(ul_vr))
5278+
return PTR_ERR(ul_vr);
5279+
5280+
err = mlxsw_sp_rif_ipip_lb_op(lb_rif, ul_vr, true);
5281+
if (err)
5282+
goto err_loopback_op;
5283+
5284+
lb_rif->ul_vr_id = ul_vr->id;
5285+
++ul_vr->rif_count;
5286+
return 0;
5287+
5288+
err_loopback_op:
5289+
mlxsw_sp_vr_put(ul_vr);
5290+
return err;
5291+
}
5292+
5293+
static void mlxsw_sp_rif_ipip_lb_deconfigure(struct mlxsw_sp_rif *rif)
5294+
{
5295+
struct mlxsw_sp_rif_ipip_lb *lb_rif = mlxsw_sp_rif_ipip_lb_rif(rif);
5296+
struct mlxsw_sp *mlxsw_sp = rif->mlxsw_sp;
5297+
struct mlxsw_sp_vr *ul_vr;
5298+
5299+
ul_vr = &mlxsw_sp->router->vrs[lb_rif->ul_vr_id];
5300+
mlxsw_sp_rif_ipip_lb_op(lb_rif, ul_vr, false);
5301+
5302+
--ul_vr->rif_count;
5303+
mlxsw_sp_vr_put(ul_vr);
5304+
}
5305+
5306+
static const struct mlxsw_sp_rif_ops mlxsw_sp_rif_ipip_lb_ops = {
5307+
.type = MLXSW_SP_RIF_TYPE_IPIP_LB,
5308+
.rif_size = sizeof(struct mlxsw_sp_rif_ipip_lb),
5309+
.setup = mlxsw_sp_rif_ipip_lb_setup,
5310+
.configure = mlxsw_sp_rif_ipip_lb_configure,
5311+
.deconfigure = mlxsw_sp_rif_ipip_lb_deconfigure,
5312+
};
5313+
51675314
static const struct mlxsw_sp_rif_ops *mlxsw_sp_rif_ops_arr[] = {
51685315
[MLXSW_SP_RIF_TYPE_SUBPORT] = &mlxsw_sp_rif_subport_ops,
51695316
[MLXSW_SP_RIF_TYPE_VLAN] = &mlxsw_sp_rif_vlan_ops,
51705317
[MLXSW_SP_RIF_TYPE_FID] = &mlxsw_sp_rif_fid_ops,
5318+
[MLXSW_SP_RIF_TYPE_IPIP_LB] = &mlxsw_sp_rif_ipip_lb_ops,
51715319
};
51725320

51735321
static int mlxsw_sp_rifs_init(struct mlxsw_sp *mlxsw_sp)

drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,25 @@
3636
#define _MLXSW_ROUTER_H_
3737

3838
#include "spectrum.h"
39+
#include "reg.h"
3940

4041
enum mlxsw_sp_l3proto {
4142
MLXSW_SP_L3_PROTO_IPV4,
4243
MLXSW_SP_L3_PROTO_IPV6,
4344
};
4445

46+
union mlxsw_sp_l3addr {
47+
__be32 addr4;
48+
struct in6_addr addr6;
49+
};
50+
51+
struct mlxsw_sp_rif_ipip_lb_config {
52+
enum mlxsw_reg_ritr_loopback_ipip_type lb_ipipt;
53+
u32 okey;
54+
enum mlxsw_sp_l3proto ul_protocol; /* Underlay. */
55+
union mlxsw_sp_l3addr saddr;
56+
};
57+
4558
enum mlxsw_sp_rif_counter_dir {
4659
MLXSW_SP_RIF_COUNTER_INGRESS,
4760
MLXSW_SP_RIF_COUNTER_EGRESS,

0 commit comments

Comments
 (0)