mlxsw: spectrum_router: Add support for blackhole nexthops
authorIdo Schimmel <idosch@nvidia.com>
Mon, 23 Nov 2020 07:12:25 +0000 (09:12 +0200)
committerJakub Kicinski <kuba@kernel.org>
Tue, 24 Nov 2020 20:14:56 +0000 (12:14 -0800)
Add support for blackhole nexthops by programming them to the adjacency
table with a discard action.

Signed-off-by: Ido Schimmel <idosch@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h

index daf0299..ed81d4f 100644 (file)
@@ -913,7 +913,8 @@ static u64 mlxsw_sp_dpipe_table_adj_size(struct mlxsw_sp *mlxsw_sp)
 
        mlxsw_sp_nexthop_for_each(nh, mlxsw_sp->router)
                if (mlxsw_sp_nexthop_offload(nh) &&
-                   !mlxsw_sp_nexthop_group_has_ipip(nh))
+                   !mlxsw_sp_nexthop_group_has_ipip(nh) &&
+                   !mlxsw_sp_nexthop_is_discard(nh))
                        size++;
        return size;
 }
@@ -1105,7 +1106,8 @@ start_again:
        nh_count = 0;
        mlxsw_sp_nexthop_for_each(nh, mlxsw_sp->router) {
                if (!mlxsw_sp_nexthop_offload(nh) ||
-                   mlxsw_sp_nexthop_group_has_ipip(nh))
+                   mlxsw_sp_nexthop_group_has_ipip(nh) ||
+                   mlxsw_sp_nexthop_is_discard(nh))
                        continue;
 
                if (nh_count < nh_skip)
@@ -1186,7 +1188,8 @@ static int mlxsw_sp_dpipe_table_adj_counters_update(void *priv, bool enable)
 
        mlxsw_sp_nexthop_for_each(nh, mlxsw_sp->router) {
                if (!mlxsw_sp_nexthop_offload(nh) ||
-                   mlxsw_sp_nexthop_group_has_ipip(nh))
+                   mlxsw_sp_nexthop_group_has_ipip(nh) ||
+                   mlxsw_sp_nexthop_is_discard(nh))
                        continue;
 
                mlxsw_sp_nexthop_indexes(nh, &adj_index, &adj_size,
index ef0e4e4..d551e9b 100644 (file)
@@ -2858,9 +2858,10 @@ struct mlxsw_sp_nexthop {
           offloaded:1, /* set in case the neigh is actually put into
                         * KVD linear area of this group.
                         */
-          update:1; /* set indicates that MAC of this neigh should be
+          update:1, /* set indicates that MAC of this neigh should be
                      * updated in HW
                      */
+          discard:1; /* nexthop is programmed to discard packets */
        enum mlxsw_sp_nexthop_type type;
        union {
                struct mlxsw_sp_neigh_entry *neigh_entry;
@@ -3011,6 +3012,11 @@ bool mlxsw_sp_nexthop_group_has_ipip(struct mlxsw_sp_nexthop *nh)
        return false;
 }
 
+bool mlxsw_sp_nexthop_is_discard(const struct mlxsw_sp_nexthop *nh)
+{
+       return nh->discard;
+}
+
 struct mlxsw_sp_nexthop_group_cmp_arg {
        enum mlxsw_sp_nexthop_group_type type;
        union {
@@ -3285,7 +3291,11 @@ static int __mlxsw_sp_nexthop_update(struct mlxsw_sp *mlxsw_sp, u32 adj_index,
        mlxsw_reg_ratr_pack(ratr_pl, MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY,
                            true, MLXSW_REG_RATR_TYPE_ETHERNET,
                            adj_index, nh->rif->rif_index);
-       mlxsw_reg_ratr_eth_entry_pack(ratr_pl, neigh_entry->ha);
+       if (nh->discard)
+               mlxsw_reg_ratr_trap_action_set(ratr_pl,
+                                              MLXSW_REG_RATR_TRAP_ACTION_DISCARD_ERRORS);
+       else
+               mlxsw_reg_ratr_eth_entry_pack(ratr_pl, neigh_entry->ha);
        if (nh->counter_valid)
                mlxsw_reg_ratr_counter_pack(ratr_pl, nh->counter_index, true);
        else
@@ -4128,9 +4138,7 @@ mlxsw_sp_nexthop_obj_single_validate(struct mlxsw_sp *mlxsw_sp,
 {
        int err = -EINVAL;
 
-       if (nh->is_reject)
-               NL_SET_ERR_MSG_MOD(extack, "Blackhole nexthops are not supported");
-       else if (nh->is_fdb)
+       if (nh->is_fdb)
                NL_SET_ERR_MSG_MOD(extack, "FDB nexthops are not supported");
        else if (nh->has_encap)
                NL_SET_ERR_MSG_MOD(extack, "Encapsulating nexthops are not supported");
@@ -4165,7 +4173,7 @@ mlxsw_sp_nexthop_obj_group_validate(struct mlxsw_sp *mlxsw_sp,
                /* Device only nexthops with an IPIP device are programmed as
                 * encapsulating adjacency entries.
                 */
-               if (!nh->gw_family &&
+               if (!nh->gw_family && !nh->is_reject &&
                    !mlxsw_sp_netdev_ipip_type(mlxsw_sp, nh->dev, NULL)) {
                        NL_SET_ERR_MSG_MOD(extack, "Nexthop group entry does not have a gateway");
                        return -EINVAL;
@@ -4199,10 +4207,31 @@ static bool mlxsw_sp_nexthop_obj_is_gateway(struct mlxsw_sp *mlxsw_sp,
                return true;
 
        dev = info->nh->dev;
-       return info->nh->gw_family ||
+       return info->nh->gw_family || info->nh->is_reject ||
               mlxsw_sp_netdev_ipip_type(mlxsw_sp, dev, NULL);
 }
 
+static void mlxsw_sp_nexthop_obj_blackhole_init(struct mlxsw_sp *mlxsw_sp,
+                                               struct mlxsw_sp_nexthop *nh)
+{
+       u16 lb_rif_index = mlxsw_sp->router->lb_rif_index;
+
+       nh->discard = 1;
+       nh->should_offload = 1;
+       /* While nexthops that discard packets do not forward packets
+        * via an egress RIF, they still need to be programmed using a
+        * valid RIF, so use the loopback RIF created during init.
+        */
+       nh->rif = mlxsw_sp->router->rifs[lb_rif_index];
+}
+
+static void mlxsw_sp_nexthop_obj_blackhole_fini(struct mlxsw_sp *mlxsw_sp,
+                                               struct mlxsw_sp_nexthop *nh)
+{
+       nh->rif = NULL;
+       nh->should_offload = 0;
+}
+
 static int
 mlxsw_sp_nexthop_obj_init(struct mlxsw_sp *mlxsw_sp,
                          struct mlxsw_sp_nexthop_group *nh_grp,
@@ -4236,6 +4265,9 @@ mlxsw_sp_nexthop_obj_init(struct mlxsw_sp *mlxsw_sp,
        if (err)
                goto err_type_init;
 
+       if (nh_obj->is_reject)
+               mlxsw_sp_nexthop_obj_blackhole_init(mlxsw_sp, nh);
+
        return 0;
 
 err_type_init:
@@ -4247,6 +4279,8 @@ err_type_init:
 static void mlxsw_sp_nexthop_obj_fini(struct mlxsw_sp *mlxsw_sp,
                                      struct mlxsw_sp_nexthop *nh)
 {
+       if (nh->discard)
+               mlxsw_sp_nexthop_obj_blackhole_fini(mlxsw_sp, nh);
        mlxsw_sp_nexthop_type_fini(mlxsw_sp, nh);
        list_del(&nh->router_list_node);
        mlxsw_sp_nexthop_counter_free(mlxsw_sp, nh);
index f9a59d4..96d8bf7 100644 (file)
@@ -201,6 +201,7 @@ int mlxsw_sp_nexthop_indexes(struct mlxsw_sp_nexthop *nh, u32 *p_adj_index,
                             u32 *p_adj_size, u32 *p_adj_hash_index);
 struct mlxsw_sp_rif *mlxsw_sp_nexthop_rif(struct mlxsw_sp_nexthop *nh);
 bool mlxsw_sp_nexthop_group_has_ipip(struct mlxsw_sp_nexthop *nh);
+bool mlxsw_sp_nexthop_is_discard(const struct mlxsw_sp_nexthop *nh);
 #define mlxsw_sp_nexthop_for_each(nh, router)                          \
        for (nh = mlxsw_sp_nexthop_next(router, NULL); nh;              \
             nh = mlxsw_sp_nexthop_next(router, nh))