aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPetr Machata <petrm@mellanox.com>2017-11-03 05:03:44 -0400
committerDavid S. Miller <davem@davemloft.net>2017-11-03 20:15:18 -0400
commit44b0fff1d8a461a5cd66cfc3a15ff05959d77df5 (patch)
tree5e45dadf8c97c9b0ad72070194741c848e96645e
parent89c2b7dabaafee2220e516d314c9b7757fc8176e (diff)
mlxsw: spectrum_router: Handle down of tunnel underlay
When the bound device of a tunnel device is down, encapsulated packets are not egressed anymore, but tunnel decap still works. Extend mlxsw_sp_nexthop_rif_update() to take IFF_UP into consideration when deciding whether a given next hop should be offloaded. Because the new logic was added to mlxsw_sp_nexthop_rif_update(), this fixes the case where a newly-added tunnel has a down bound device, which would previously be fully offloaded. Now the down state of the bound device is noted and next hops forwarding to such tunnel are not offloaded. In addition to that, notice NETDEV_UP and NETDEV_DOWN of a bound device to force refresh of tunnel encap route offloads. Signed-off-by: Petr Machata <petrm@mellanox.com> Reviewed-by: Ido Schimmel <idosch@mellanox.com> Signed-off-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c57
1 files changed, 55 insertions, 2 deletions
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index c1928561c412..e9187841d82a 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -1467,6 +1467,28 @@ mlxsw_sp_netdevice_ipip_ul_vrf_event(struct mlxsw_sp *mlxsw_sp,
1467} 1467}
1468 1468
1469static int 1469static int
1470mlxsw_sp_netdevice_ipip_ul_up_event(struct mlxsw_sp *mlxsw_sp,
1471 struct mlxsw_sp_ipip_entry *ipip_entry,
1472 struct net_device *ul_dev)
1473{
1474 return __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp, ipip_entry,
1475 false, false, true, NULL);
1476}
1477
1478static int
1479mlxsw_sp_netdevice_ipip_ul_down_event(struct mlxsw_sp *mlxsw_sp,
1480 struct mlxsw_sp_ipip_entry *ipip_entry,
1481 struct net_device *ul_dev)
1482{
1483 /* A down underlay device causes encapsulated packets to not be
1484 * forwarded, but decap still works. So refresh next hops without
1485 * touching anything else.
1486 */
1487 return __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp, ipip_entry,
1488 false, false, true, NULL);
1489}
1490
1491static int
1470mlxsw_sp_netdevice_ipip_ol_change_event(struct mlxsw_sp *mlxsw_sp, 1492mlxsw_sp_netdevice_ipip_ol_change_event(struct mlxsw_sp *mlxsw_sp,
1471 struct net_device *ol_dev, 1493 struct net_device *ol_dev,
1472 struct netlink_ext_ack *extack) 1494 struct netlink_ext_ack *extack)
@@ -1604,6 +1626,14 @@ __mlxsw_sp_netdevice_ipip_ul_event(struct mlxsw_sp *mlxsw_sp,
1604 ul_dev, 1626 ul_dev,
1605 extack); 1627 extack);
1606 break; 1628 break;
1629
1630 case NETDEV_UP:
1631 return mlxsw_sp_netdevice_ipip_ul_up_event(mlxsw_sp, ipip_entry,
1632 ul_dev);
1633 case NETDEV_DOWN:
1634 return mlxsw_sp_netdevice_ipip_ul_down_event(mlxsw_sp,
1635 ipip_entry,
1636 ul_dev);
1607 } 1637 }
1608 return 0; 1638 return 0;
1609} 1639}
@@ -3297,10 +3327,19 @@ static void mlxsw_sp_nexthop_neigh_fini(struct mlxsw_sp *mlxsw_sp,
3297 neigh_release(n); 3327 neigh_release(n);
3298} 3328}
3299 3329
3330static bool mlxsw_sp_ipip_netdev_ul_up(struct net_device *ol_dev)
3331{
3332 struct net_device *ul_dev = __mlxsw_sp_ipip_netdev_ul_dev_get(ol_dev);
3333
3334 return ul_dev ? (ul_dev->flags & IFF_UP) : true;
3335}
3336
3300static int mlxsw_sp_nexthop_ipip_init(struct mlxsw_sp *mlxsw_sp, 3337static int mlxsw_sp_nexthop_ipip_init(struct mlxsw_sp *mlxsw_sp,
3301 struct mlxsw_sp_nexthop *nh, 3338 struct mlxsw_sp_nexthop *nh,
3302 struct net_device *ol_dev) 3339 struct net_device *ol_dev)
3303{ 3340{
3341 bool removing;
3342
3304 if (!nh->nh_grp->gateway || nh->ipip_entry) 3343 if (!nh->nh_grp->gateway || nh->ipip_entry)
3305 return 0; 3344 return 0;
3306 3345
@@ -3308,7 +3347,8 @@ static int mlxsw_sp_nexthop_ipip_init(struct mlxsw_sp *mlxsw_sp,
3308 if (!nh->ipip_entry) 3347 if (!nh->ipip_entry)
3309 return -ENOENT; 3348 return -ENOENT;
3310 3349
3311 __mlxsw_sp_nexthop_neigh_update(nh, false); 3350 removing = !mlxsw_sp_ipip_netdev_ul_up(ol_dev);
3351 __mlxsw_sp_nexthop_neigh_update(nh, removing);
3312 return 0; 3352 return 0;
3313} 3353}
3314 3354
@@ -3476,9 +3516,22 @@ static void mlxsw_sp_nexthop_rif_update(struct mlxsw_sp *mlxsw_sp,
3476 struct mlxsw_sp_rif *rif) 3516 struct mlxsw_sp_rif *rif)
3477{ 3517{
3478 struct mlxsw_sp_nexthop *nh; 3518 struct mlxsw_sp_nexthop *nh;
3519 bool removing;
3479 3520
3480 list_for_each_entry(nh, &rif->nexthop_list, rif_list_node) { 3521 list_for_each_entry(nh, &rif->nexthop_list, rif_list_node) {
3481 __mlxsw_sp_nexthop_neigh_update(nh, false); 3522 switch (nh->type) {
3523 case MLXSW_SP_NEXTHOP_TYPE_ETH:
3524 removing = false;
3525 break;
3526 case MLXSW_SP_NEXTHOP_TYPE_IPIP:
3527 removing = !mlxsw_sp_ipip_netdev_ul_up(rif->dev);
3528 break;
3529 default:
3530 WARN_ON(1);
3531 continue;
3532 }
3533
3534 __mlxsw_sp_nexthop_neigh_update(nh, removing);
3482 mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nh_grp); 3535 mlxsw_sp_nexthop_group_refresh(mlxsw_sp, nh->nh_grp);
3483 } 3536 }
3484} 3537}