Skip to content

Commit 0063587

Browse files
pmachatadavem330
authored andcommitted
mlxsw: spectrum: Support decap-only IP-in-IP tunnels
Current code for offloading IP-in-IP tunneling assumes that there is no decap without encap. But that's never true for IPv6 overlays, and is not true for IPv4 ones either, if net.ipv4.conf.*.rp_filter is unset. To support decap-only tunnels, an IPIP entry is now created as soon as an offloadable tunneling device is created. When that netdevice is up'd, a decap route is looked up and possibly offloaded. Thus decap is not handled implicitly as part of mlxsw_sp_ipip_entry_get() call anymore, but needs to be done explicitly after the get, if desired. 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 6698c16 commit 0063587

File tree

3 files changed

+109
-10
lines changed

3 files changed

+109
-10
lines changed

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4497,13 +4497,17 @@ static bool mlxsw_sp_is_vrf_event(unsigned long event, void *ptr)
44974497
return netif_is_l3_master(info->upper_dev);
44984498
}
44994499

4500-
static int mlxsw_sp_netdevice_event(struct notifier_block *unused,
4500+
static int mlxsw_sp_netdevice_event(struct notifier_block *nb,
45014501
unsigned long event, void *ptr)
45024502
{
45034503
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
4504+
struct mlxsw_sp *mlxsw_sp;
45044505
int err = 0;
45054506

4506-
if (event == NETDEV_CHANGEADDR || event == NETDEV_CHANGEMTU)
4507+
mlxsw_sp = container_of(nb, struct mlxsw_sp, netdevice_nb);
4508+
if (mlxsw_sp_netdev_is_ipip(mlxsw_sp, dev))
4509+
err = mlxsw_sp_netdevice_ipip_event(mlxsw_sp, dev, event);
4510+
else if (event == NETDEV_CHANGEADDR || event == NETDEV_CHANGEMTU)
45074511
err = mlxsw_sp_netdevice_router_port_event(dev);
45084512
else if (mlxsw_sp_is_vrf_event(event, ptr))
45094513
err = mlxsw_sp_netdevice_vrf_event(dev, event, ptr);

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,12 @@ int mlxsw_sp_inet6addr_event(struct notifier_block *unused,
395395
unsigned long event, void *ptr);
396396
int mlxsw_sp_netdevice_vrf_event(struct net_device *l3_dev, unsigned long event,
397397
struct netdev_notifier_changeupper_info *info);
398+
bool mlxsw_sp_netdev_is_ipip(const struct mlxsw_sp *mlxsw_sp,
399+
const struct net_device *dev);
400+
int
401+
mlxsw_sp_netdevice_ipip_event(struct mlxsw_sp *mlxsw_sp,
402+
struct net_device *l3_dev,
403+
unsigned long event);
398404
void
399405
mlxsw_sp_port_vlan_router_leave(struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan);
400406
void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif);

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

Lines changed: 97 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1206,7 +1206,6 @@ mlxsw_sp_ipip_entry_get(struct mlxsw_sp *mlxsw_sp,
12061206
{
12071207
u32 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(ol_dev);
12081208
struct mlxsw_sp_router *router = mlxsw_sp->router;
1209-
struct mlxsw_sp_fib_entry *decap_fib_entry;
12101209
struct mlxsw_sp_ipip_entry *ipip_entry;
12111210
enum mlxsw_sp_l3proto ul_proto;
12121211
union mlxsw_sp_l3addr saddr;
@@ -1231,11 +1230,6 @@ mlxsw_sp_ipip_entry_get(struct mlxsw_sp *mlxsw_sp,
12311230
if (IS_ERR(ipip_entry))
12321231
return ipip_entry;
12331232

1234-
decap_fib_entry = mlxsw_sp_ipip_entry_find_decap(mlxsw_sp, ipip_entry);
1235-
if (decap_fib_entry)
1236-
mlxsw_sp_ipip_entry_promote_decap(mlxsw_sp, ipip_entry,
1237-
decap_fib_entry);
1238-
12391233
list_add_tail(&ipip_entry->ipip_list_node,
12401234
&mlxsw_sp->router->ipip_list);
12411235

@@ -1250,8 +1244,6 @@ mlxsw_sp_ipip_entry_put(struct mlxsw_sp *mlxsw_sp,
12501244
{
12511245
if (--ipip_entry->ref_count == 0) {
12521246
list_del(&ipip_entry->ipip_list_node);
1253-
if (ipip_entry->decap_fib_entry)
1254-
mlxsw_sp_ipip_entry_demote_decap(mlxsw_sp, ipip_entry);
12551247
mlxsw_sp_ipip_entry_destroy(ipip_entry);
12561248
}
12571249
}
@@ -1314,6 +1306,103 @@ static bool mlxsw_sp_netdev_ipip_type(const struct mlxsw_sp *mlxsw_sp,
13141306
return false;
13151307
}
13161308

1309+
bool mlxsw_sp_netdev_is_ipip(const struct mlxsw_sp *mlxsw_sp,
1310+
const struct net_device *dev)
1311+
{
1312+
return mlxsw_sp_netdev_ipip_type(mlxsw_sp, dev, NULL);
1313+
}
1314+
1315+
static struct mlxsw_sp_ipip_entry *
1316+
mlxsw_sp_ipip_entry_find_by_ol_dev(struct mlxsw_sp *mlxsw_sp,
1317+
const struct net_device *ol_dev)
1318+
{
1319+
struct mlxsw_sp_ipip_entry *ipip_entry;
1320+
1321+
list_for_each_entry(ipip_entry, &mlxsw_sp->router->ipip_list,
1322+
ipip_list_node)
1323+
if (ipip_entry->ol_dev == ol_dev)
1324+
return ipip_entry;
1325+
1326+
return NULL;
1327+
}
1328+
1329+
static int mlxsw_sp_netdevice_ipip_reg_event(struct mlxsw_sp *mlxsw_sp,
1330+
struct net_device *ol_dev)
1331+
{
1332+
struct mlxsw_sp_router *router = mlxsw_sp->router;
1333+
struct mlxsw_sp_ipip_entry *ipip_entry;
1334+
enum mlxsw_sp_ipip_type ipipt;
1335+
1336+
mlxsw_sp_netdev_ipip_type(mlxsw_sp, ol_dev, &ipipt);
1337+
if (router->ipip_ops_arr[ipipt]->can_offload(mlxsw_sp, ol_dev,
1338+
MLXSW_SP_L3_PROTO_IPV4) ||
1339+
router->ipip_ops_arr[ipipt]->can_offload(mlxsw_sp, ol_dev,
1340+
MLXSW_SP_L3_PROTO_IPV6)) {
1341+
ipip_entry = mlxsw_sp_ipip_entry_get(mlxsw_sp, ipipt, ol_dev);
1342+
if (IS_ERR(ipip_entry))
1343+
return PTR_ERR(ipip_entry);
1344+
}
1345+
1346+
return 0;
1347+
}
1348+
1349+
static void mlxsw_sp_netdevice_ipip_unreg_event(struct mlxsw_sp *mlxsw_sp,
1350+
struct net_device *ol_dev)
1351+
{
1352+
struct mlxsw_sp_ipip_entry *ipip_entry;
1353+
1354+
ipip_entry = mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp, ol_dev);
1355+
if (ipip_entry)
1356+
mlxsw_sp_ipip_entry_put(mlxsw_sp, ipip_entry);
1357+
}
1358+
1359+
static int mlxsw_sp_netdevice_ipip_up_event(struct mlxsw_sp *mlxsw_sp,
1360+
struct net_device *ol_dev)
1361+
{
1362+
struct mlxsw_sp_fib_entry *decap_fib_entry;
1363+
struct mlxsw_sp_ipip_entry *ipip_entry;
1364+
1365+
ipip_entry = mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp, ol_dev);
1366+
if (ipip_entry) {
1367+
decap_fib_entry = mlxsw_sp_ipip_entry_find_decap(mlxsw_sp,
1368+
ipip_entry);
1369+
if (decap_fib_entry)
1370+
mlxsw_sp_ipip_entry_promote_decap(mlxsw_sp, ipip_entry,
1371+
decap_fib_entry);
1372+
}
1373+
1374+
return 0;
1375+
}
1376+
1377+
static void mlxsw_sp_netdevice_ipip_down_event(struct mlxsw_sp *mlxsw_sp,
1378+
struct net_device *ol_dev)
1379+
{
1380+
struct mlxsw_sp_ipip_entry *ipip_entry;
1381+
1382+
ipip_entry = mlxsw_sp_ipip_entry_find_by_ol_dev(mlxsw_sp, ol_dev);
1383+
if (ipip_entry && ipip_entry->decap_fib_entry)
1384+
mlxsw_sp_ipip_entry_demote_decap(mlxsw_sp, ipip_entry);
1385+
}
1386+
1387+
int mlxsw_sp_netdevice_ipip_event(struct mlxsw_sp *mlxsw_sp,
1388+
struct net_device *ol_dev,
1389+
unsigned long event)
1390+
{
1391+
switch (event) {
1392+
case NETDEV_REGISTER:
1393+
return mlxsw_sp_netdevice_ipip_reg_event(mlxsw_sp, ol_dev);
1394+
case NETDEV_UNREGISTER:
1395+
mlxsw_sp_netdevice_ipip_unreg_event(mlxsw_sp, ol_dev);
1396+
return 0;
1397+
case NETDEV_UP:
1398+
return mlxsw_sp_netdevice_ipip_up_event(mlxsw_sp, ol_dev);
1399+
case NETDEV_DOWN:
1400+
mlxsw_sp_netdevice_ipip_down_event(mlxsw_sp, ol_dev);
1401+
return 0;
1402+
}
1403+
return 0;
1404+
}
1405+
13171406
struct mlxsw_sp_neigh_key {
13181407
struct neighbour *n;
13191408
};

0 commit comments

Comments
 (0)