mlxsw: spectrum_router: Store NVE decapsulation configuration in router
authorIdo Schimmel <idosch@mellanox.com>
Fri, 21 Feb 2020 17:54:08 +0000 (19:54 +0200)
committerDavid S. Miller <davem@davemloft.net>
Sun, 23 Feb 2020 05:24:51 +0000 (21:24 -0800)
When a host route is added, the driver checks if the route needs to be
promoted to perform NVE decapsulation based on the current NVE
configuration. If so, the index of the decapsulation entry is retrieved
and associated with the route.

Currently, this information is stored in the NVE module which the router
module consults. Since the information is protected under RTNL and since
route insertion happens with RTNL held, there is no problem to retrieve
the information from the NVE module.

However, this is going to change and route insertion will no longer
happen under RTNL. Instead, a dedicated lock will be introduced for the
router module.

Therefore, store this information in the router module and change the
router module to consult this copy.

The validity of the information is set / cleared whenever an NVE tunnel
is initialized / de-initialized. When this happens the NVE module calls
into the router module to promote / demote the relevant host route.

Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Acked-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlxsw/spectrum.h
drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h

index bed86f4825a88fef11cdf5720a4b3faf989e7646..66cfe27e1f9b7026c5c5a977be6b8f530b59c9a5 100644 (file)
@@ -966,9 +966,6 @@ void mlxsw_sp_nve_flood_ip_del(struct mlxsw_sp *mlxsw_sp,
                               struct mlxsw_sp_fid *fid,
                               enum mlxsw_sp_l3proto proto,
                               union mlxsw_sp_l3addr *addr);
-u32 mlxsw_sp_nve_decap_tunnel_index_get(const struct mlxsw_sp *mlxsw_sp);
-bool mlxsw_sp_nve_ipv4_route_is_decap(const struct mlxsw_sp *mlxsw_sp,
-                                     u32 tb_id, __be32 addr);
 int mlxsw_sp_nve_fid_enable(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_fid *fid,
                            struct mlxsw_sp_nve_params *params,
                            struct netlink_ext_ack *extack);
index eced553fd4effa9bc27ccc294aa2a0f412d339a3..54d3e7dcd303b078444da10dd2fae0ce4e3bc143 100644 (file)
@@ -713,27 +713,6 @@ static void mlxsw_sp_nve_flood_ip_flush(struct mlxsw_sp *mlxsw_sp,
        mlxsw_sp_nve_mc_list_put(mlxsw_sp, mc_list);
 }
 
-u32 mlxsw_sp_nve_decap_tunnel_index_get(const struct mlxsw_sp *mlxsw_sp)
-{
-       WARN_ON(mlxsw_sp->nve->num_nve_tunnels == 0);
-
-       return mlxsw_sp->nve->tunnel_index;
-}
-
-bool mlxsw_sp_nve_ipv4_route_is_decap(const struct mlxsw_sp *mlxsw_sp,
-                                     u32 tb_id, __be32 addr)
-{
-       struct mlxsw_sp_nve *nve = mlxsw_sp->nve;
-       struct mlxsw_sp_nve_config *config = &nve->config;
-
-       if (nve->num_nve_tunnels &&
-           config->ul_proto == MLXSW_SP_L3_PROTO_IPV4 &&
-           config->ul_sip.addr4 == addr && config->ul_tb_id == tb_id)
-               return true;
-
-       return false;
-}
-
 static int mlxsw_sp_nve_tunnel_init(struct mlxsw_sp *mlxsw_sp,
                                    struct mlxsw_sp_nve_config *config)
 {
index 991095f66fc204d3f3a9315d731e58a96e5d7c5a..fe8c1f3866517f89cd241fa7df9401d5132d00bb 100644 (file)
@@ -1833,9 +1833,19 @@ int mlxsw_sp_router_nve_promote_decap(struct mlxsw_sp *mlxsw_sp, u32 ul_tb_id,
                                      u32 tunnel_index)
 {
        enum mlxsw_sp_fib_entry_type type = MLXSW_SP_FIB_ENTRY_TYPE_TRAP;
+       struct mlxsw_sp_router *router = mlxsw_sp->router;
        struct mlxsw_sp_fib_entry *fib_entry;
        int err;
 
+       if (WARN_ON_ONCE(router->nve_decap_config.valid))
+               return -EINVAL;
+
+       router->nve_decap_config.ul_tb_id = ul_tb_id;
+       router->nve_decap_config.tunnel_index = tunnel_index;
+       router->nve_decap_config.ul_proto = ul_proto;
+       router->nve_decap_config.ul_sip = *ul_sip;
+       router->nve_decap_config.valid = true;
+
        /* It is valid to create a tunnel with a local IP and only later
         * assign this IP address to a local interface
         */
@@ -1865,8 +1875,14 @@ void mlxsw_sp_router_nve_demote_decap(struct mlxsw_sp *mlxsw_sp, u32 ul_tb_id,
                                      const union mlxsw_sp_l3addr *ul_sip)
 {
        enum mlxsw_sp_fib_entry_type type = MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP;
+       struct mlxsw_sp_router *router = mlxsw_sp->router;
        struct mlxsw_sp_fib_entry *fib_entry;
 
+       if (WARN_ON_ONCE(!router->nve_decap_config.valid))
+               return;
+
+       router->nve_decap_config.valid = false;
+
        fib_entry = mlxsw_sp_router_ip2me_fib_entry_find(mlxsw_sp, ul_tb_id,
                                                         ul_proto, ul_sip,
                                                         type);
@@ -1877,6 +1893,20 @@ void mlxsw_sp_router_nve_demote_decap(struct mlxsw_sp *mlxsw_sp, u32 ul_tb_id,
        mlxsw_sp_fib_entry_update(mlxsw_sp, fib_entry);
 }
 
+static bool mlxsw_sp_router_nve_is_decap(struct mlxsw_sp *mlxsw_sp,
+                                        u32 ul_tb_id,
+                                        enum mlxsw_sp_l3proto ul_proto,
+                                        const union mlxsw_sp_l3addr *ul_sip)
+{
+       struct mlxsw_sp_router *router = mlxsw_sp->router;
+
+       return router->nve_decap_config.valid &&
+              router->nve_decap_config.ul_tb_id == ul_tb_id &&
+              router->nve_decap_config.ul_proto == ul_proto &&
+              !memcmp(&router->nve_decap_config.ul_sip, ul_sip,
+                      sizeof(*ul_sip));
+}
+
 struct mlxsw_sp_neigh_key {
        struct neighbour *n;
 };
@@ -4466,6 +4496,7 @@ mlxsw_sp_fib4_entry_type_set(struct mlxsw_sp *mlxsw_sp,
 {
        struct net_device *dev = fib_info_nh(fen_info->fi, 0)->fib_nh_dev;
        union mlxsw_sp_l3addr dip = { .addr4 = htonl(fen_info->dst) };
+       struct mlxsw_sp_router *router = mlxsw_sp->router;
        u32 tb_id = mlxsw_sp_fix_tb_id(fen_info->tb_id);
        struct mlxsw_sp_ipip_entry *ipip_entry;
        struct fib_info *fi = fen_info->fi;
@@ -4480,12 +4511,13 @@ mlxsw_sp_fib4_entry_type_set(struct mlxsw_sp *mlxsw_sp,
                                                             fib_entry,
                                                             ipip_entry);
                }
-               if (mlxsw_sp_nve_ipv4_route_is_decap(mlxsw_sp, tb_id,
-                                                    dip.addr4)) {
-                       u32 t_index;
+               if (mlxsw_sp_router_nve_is_decap(mlxsw_sp, tb_id,
+                                                MLXSW_SP_L3_PROTO_IPV4,
+                                                &dip)) {
+                       u32 tunnel_index;
 
-                       t_index = mlxsw_sp_nve_decap_tunnel_index_get(mlxsw_sp);
-                       fib_entry->decap.tunnel_index = t_index;
+                       tunnel_index = router->nve_decap_config.tunnel_index;
+                       fib_entry->decap.tunnel_index = tunnel_index;
                        fib_entry->type = MLXSW_SP_FIB_ENTRY_TYPE_NVE_DECAP;
                        return 0;
                }
index b2554727d8ee5cf7f1a2cc14676a62ae34bcfe3d..3c99db1f434b22674709323c50dab66207d89c7e 100644 (file)
@@ -7,6 +7,14 @@
 #include "spectrum.h"
 #include "reg.h"
 
+struct mlxsw_sp_router_nve_decap {
+       u32 ul_tb_id;
+       u32 tunnel_index;
+       enum mlxsw_sp_l3proto ul_proto;
+       union mlxsw_sp_l3addr ul_sip;
+       u8 valid:1;
+};
+
 struct mlxsw_sp_router {
        struct mlxsw_sp *mlxsw_sp;
        struct mlxsw_sp_rif **rifs;
@@ -38,6 +46,7 @@ struct mlxsw_sp_router {
        const struct mlxsw_sp_ipip_ops **ipip_ops_arr;
        u32 adj_discard_index;
        bool adj_discard_index_valid;
+       struct mlxsw_sp_router_nve_decap nve_decap_config;
 };
 
 struct mlxsw_sp_rif_ipip_lb;