Commit 56e66053 authored by David S. Miller's avatar David S. Miller

Merge branch 'mlxsw-next'

Ido Schimmel says:

====================
mlxsw: Add support for IP-in-IP with IPv6 underlay

Currently, mlxsw only supports IP-in-IP with IPv4 underlay. Traffic
routed through 'gre' netdevs is encapsulated with IPv4 and GRE headers.
Similarly, incoming IPv4 GRE packets are decapsulated and routed in the
overlay VRF (which can be the same as the underlay VRF).

This patchset adds support for IPv6 underlay using the 'ip6gre' netdev.
Due to architectural differences between Spectrum-1 and later ASICs,
this functionality is only supported on Spectrum-2 onwards (the software
data path is used for Spectrum-1).

Patchset overview:

Patches #1-#5 are preparations.

Patches #6-#9 add and extend required device registers.

Patches #10-#14 gradually add IPv6 underlay support.

A follow-up patchset will add net/forwarding/ selftests.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 2fcd14d0 ba1c7132
...@@ -6734,6 +6734,23 @@ mlxsw_reg_ritr_loopback_ipip4_pack(char *payload, ...@@ -6734,6 +6734,23 @@ mlxsw_reg_ritr_loopback_ipip4_pack(char *payload,
mlxsw_reg_ritr_loopback_ipip_usip4_set(payload, usip); mlxsw_reg_ritr_loopback_ipip_usip4_set(payload, usip);
} }
static inline void
mlxsw_reg_ritr_loopback_ipip6_pack(char *payload,
enum mlxsw_reg_ritr_loopback_ipip_type ipip_type,
enum mlxsw_reg_ritr_loopback_ipip_options options,
u16 uvr_id, u16 underlay_rif,
const struct in6_addr *usip, u32 gre_key)
{
enum mlxsw_reg_ritr_loopback_protocol protocol =
MLXSW_REG_RITR_LOOPBACK_PROTOCOL_IPIP_IPV6;
mlxsw_reg_ritr_loopback_protocol_set(payload, protocol);
mlxsw_reg_ritr_loopback_ipip_common_pack(payload, ipip_type, options,
uvr_id, underlay_rif, gre_key);
mlxsw_reg_ritr_loopback_ipip_usip6_memcpy_to(payload,
(const char *)usip);
}
/* RTAR - Router TCAM Allocation Register /* RTAR - Router TCAM Allocation Register
* -------------------------------------- * --------------------------------------
* This register is used for allocation of regions in the TCAM table. * This register is used for allocation of regions in the TCAM table.
...@@ -7002,6 +7019,12 @@ static inline void mlxsw_reg_ratr_ipip4_entry_pack(char *payload, u32 ipv4_udip) ...@@ -7002,6 +7019,12 @@ static inline void mlxsw_reg_ratr_ipip4_entry_pack(char *payload, u32 ipv4_udip)
mlxsw_reg_ratr_ipip_ipv4_udip_set(payload, ipv4_udip); mlxsw_reg_ratr_ipip_ipv4_udip_set(payload, ipv4_udip);
} }
static inline void mlxsw_reg_ratr_ipip6_entry_pack(char *payload, u32 ipv6_ptr)
{
mlxsw_reg_ratr_ipip_type_set(payload, MLXSW_REG_RATR_IPIP_TYPE_IPV6);
mlxsw_reg_ratr_ipip_ipv6_ptr_set(payload, ipv6_ptr);
}
static inline void mlxsw_reg_ratr_counter_pack(char *payload, u64 counter_index, static inline void mlxsw_reg_ratr_counter_pack(char *payload, u64 counter_index,
bool counter_enable) bool counter_enable)
{ {
...@@ -8187,19 +8210,71 @@ static inline void mlxsw_reg_rtdp_pack(char *payload, ...@@ -8187,19 +8210,71 @@ static inline void mlxsw_reg_rtdp_pack(char *payload,
} }
static inline void static inline void
mlxsw_reg_rtdp_ipip4_pack(char *payload, u16 irif, mlxsw_reg_rtdp_ipip_pack(char *payload, u16 irif,
enum mlxsw_reg_rtdp_ipip_sip_check sip_check, enum mlxsw_reg_rtdp_ipip_sip_check sip_check,
unsigned int type_check, bool gre_key_check, unsigned int type_check, bool gre_key_check,
u32 ipv4_usip, u32 expected_gre_key) u32 expected_gre_key)
{ {
mlxsw_reg_rtdp_ipip_irif_set(payload, irif); mlxsw_reg_rtdp_ipip_irif_set(payload, irif);
mlxsw_reg_rtdp_ipip_sip_check_set(payload, sip_check); mlxsw_reg_rtdp_ipip_sip_check_set(payload, sip_check);
mlxsw_reg_rtdp_ipip_type_check_set(payload, type_check); mlxsw_reg_rtdp_ipip_type_check_set(payload, type_check);
mlxsw_reg_rtdp_ipip_gre_key_check_set(payload, gre_key_check); mlxsw_reg_rtdp_ipip_gre_key_check_set(payload, gre_key_check);
mlxsw_reg_rtdp_ipip_ipv4_usip_set(payload, ipv4_usip);
mlxsw_reg_rtdp_ipip_expected_gre_key_set(payload, expected_gre_key); mlxsw_reg_rtdp_ipip_expected_gre_key_set(payload, expected_gre_key);
} }
static inline void
mlxsw_reg_rtdp_ipip4_pack(char *payload, u16 irif,
enum mlxsw_reg_rtdp_ipip_sip_check sip_check,
unsigned int type_check, bool gre_key_check,
u32 ipv4_usip, u32 expected_gre_key)
{
mlxsw_reg_rtdp_ipip_pack(payload, irif, sip_check, type_check,
gre_key_check, expected_gre_key);
mlxsw_reg_rtdp_ipip_ipv4_usip_set(payload, ipv4_usip);
}
static inline void
mlxsw_reg_rtdp_ipip6_pack(char *payload, u16 irif,
enum mlxsw_reg_rtdp_ipip_sip_check sip_check,
unsigned int type_check, bool gre_key_check,
u32 ipv6_usip_ptr, u32 expected_gre_key)
{
mlxsw_reg_rtdp_ipip_pack(payload, irif, sip_check, type_check,
gre_key_check, expected_gre_key);
mlxsw_reg_rtdp_ipip_ipv6_usip_ptr_set(payload, ipv6_usip_ptr);
}
/* RIPS - Router IP version Six Register
* -------------------------------------
* The RIPS register is used to store IPv6 addresses for use by the NVE and
* IPinIP
*/
#define MLXSW_REG_RIPS_ID 0x8021
#define MLXSW_REG_RIPS_LEN 0x14
MLXSW_REG_DEFINE(rips, MLXSW_REG_RIPS_ID, MLXSW_REG_RIPS_LEN);
/* reg_rips_index
* Index to IPv6 address.
* For Spectrum, the index is to the KVD linear.
* Access: Index
*/
MLXSW_ITEM32(reg, rips, index, 0x00, 0, 24);
/* reg_rips_ipv6
* IPv6 address
* Access: RW
*/
MLXSW_ITEM_BUF(reg, rips, ipv6, 0x04, 16);
static inline void mlxsw_reg_rips_pack(char *payload, u32 index,
const struct in6_addr *ipv6)
{
MLXSW_REG_ZERO(rips, payload);
mlxsw_reg_rips_index_set(payload, index);
mlxsw_reg_rips_ipv6_memcpy_to(payload, (const char *)ipv6);
}
/* RATRAD - Router Adjacency Table Activity Dump Register /* RATRAD - Router Adjacency Table Activity Dump Register
* ------------------------------------------------------ * ------------------------------------------------------
* The RATRAD register is used to dump and optionally clear activity bits of * The RATRAD register is used to dump and optionally clear activity bits of
...@@ -12281,6 +12356,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = { ...@@ -12281,6 +12356,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = {
MLXSW_REG(rtar), MLXSW_REG(rtar),
MLXSW_REG(ratr), MLXSW_REG(ratr),
MLXSW_REG(rtdp), MLXSW_REG(rtdp),
MLXSW_REG(rips),
MLXSW_REG(ratrad), MLXSW_REG(ratrad),
MLXSW_REG(rdpm), MLXSW_REG(rdpm),
MLXSW_REG(ricnt), MLXSW_REG(ricnt),
......
...@@ -747,6 +747,7 @@ enum mlxsw_sp_kvdl_entry_type { ...@@ -747,6 +747,7 @@ enum mlxsw_sp_kvdl_entry_type {
MLXSW_SP_KVDL_ENTRY_TYPE_ACTSET, MLXSW_SP_KVDL_ENTRY_TYPE_ACTSET,
MLXSW_SP_KVDL_ENTRY_TYPE_PBS, MLXSW_SP_KVDL_ENTRY_TYPE_PBS,
MLXSW_SP_KVDL_ENTRY_TYPE_MCRIGR, MLXSW_SP_KVDL_ENTRY_TYPE_MCRIGR,
MLXSW_SP_KVDL_ENTRY_TYPE_IPV6_ADDRESS,
MLXSW_SP_KVDL_ENTRY_TYPE_TNUMT, MLXSW_SP_KVDL_ENTRY_TYPE_TNUMT,
}; };
...@@ -758,6 +759,7 @@ mlxsw_sp_kvdl_entry_size(enum mlxsw_sp_kvdl_entry_type type) ...@@ -758,6 +759,7 @@ mlxsw_sp_kvdl_entry_size(enum mlxsw_sp_kvdl_entry_type type)
case MLXSW_SP_KVDL_ENTRY_TYPE_ACTSET: case MLXSW_SP_KVDL_ENTRY_TYPE_ACTSET:
case MLXSW_SP_KVDL_ENTRY_TYPE_PBS: case MLXSW_SP_KVDL_ENTRY_TYPE_PBS:
case MLXSW_SP_KVDL_ENTRY_TYPE_MCRIGR: case MLXSW_SP_KVDL_ENTRY_TYPE_MCRIGR:
case MLXSW_SP_KVDL_ENTRY_TYPE_IPV6_ADDRESS:
case MLXSW_SP_KVDL_ENTRY_TYPE_TNUMT: case MLXSW_SP_KVDL_ENTRY_TYPE_TNUMT:
default: default:
return 1; return 1;
......
...@@ -35,6 +35,7 @@ static const struct mlxsw_sp2_kvdl_part_info mlxsw_sp2_kvdl_parts_info[] = { ...@@ -35,6 +35,7 @@ static const struct mlxsw_sp2_kvdl_part_info mlxsw_sp2_kvdl_parts_info[] = {
MAX_KVD_ACTION_SETS), MAX_KVD_ACTION_SETS),
MLXSW_SP2_KVDL_PART_INFO(PBS, 0x24, KVD_SIZE, KVD_SIZE), MLXSW_SP2_KVDL_PART_INFO(PBS, 0x24, KVD_SIZE, KVD_SIZE),
MLXSW_SP2_KVDL_PART_INFO(MCRIGR, 0x26, KVD_SIZE, KVD_SIZE), MLXSW_SP2_KVDL_PART_INFO(MCRIGR, 0x26, KVD_SIZE, KVD_SIZE),
MLXSW_SP2_KVDL_PART_INFO(IPV6_ADDRESS, 0x28, KVD_SIZE, KVD_SIZE),
MLXSW_SP2_KVDL_PART_INFO(TNUMT, 0x29, KVD_SIZE, KVD_SIZE), MLXSW_SP2_KVDL_PART_INFO(TNUMT, 0x29, KVD_SIZE, KVD_SIZE),
}; };
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "spectrum_router.h" #include "spectrum_router.h"
#include <net/ip_fib.h> #include <net/ip_fib.h>
#include <linux/if_tunnel.h> #include <linux/if_tunnel.h>
#include <net/ip6_tunnel.h>
struct ip_tunnel_parm struct ip_tunnel_parm
mlxsw_sp_ipip_netdev_parms4(const struct net_device *ol_dev); mlxsw_sp_ipip_netdev_parms4(const struct net_device *ol_dev);
...@@ -21,23 +22,36 @@ bool mlxsw_sp_l3addr_is_zero(union mlxsw_sp_l3addr addr); ...@@ -21,23 +22,36 @@ bool mlxsw_sp_l3addr_is_zero(union mlxsw_sp_l3addr addr);
enum mlxsw_sp_ipip_type { enum mlxsw_sp_ipip_type {
MLXSW_SP_IPIP_TYPE_GRE4, MLXSW_SP_IPIP_TYPE_GRE4,
MLXSW_SP_IPIP_TYPE_GRE6,
MLXSW_SP_IPIP_TYPE_MAX, MLXSW_SP_IPIP_TYPE_MAX,
}; };
struct mlxsw_sp_ipip_parms {
enum mlxsw_sp_l3proto proto;
union mlxsw_sp_l3addr saddr;
union mlxsw_sp_l3addr daddr;
int link;
u32 ikey;
u32 okey;
};
struct mlxsw_sp_ipip_entry { struct mlxsw_sp_ipip_entry {
enum mlxsw_sp_ipip_type ipipt; enum mlxsw_sp_ipip_type ipipt;
struct net_device *ol_dev; /* Overlay. */ struct net_device *ol_dev; /* Overlay. */
struct mlxsw_sp_rif_ipip_lb *ol_lb; struct mlxsw_sp_rif_ipip_lb *ol_lb;
struct mlxsw_sp_fib_entry *decap_fib_entry; struct mlxsw_sp_fib_entry *decap_fib_entry;
struct list_head ipip_list_node; struct list_head ipip_list_node;
union { struct mlxsw_sp_ipip_parms parms;
struct ip_tunnel_parm parms4; u32 dip_kvdl_index;
};
}; };
struct mlxsw_sp_ipip_ops { struct mlxsw_sp_ipip_ops {
int dev_type; int dev_type;
enum mlxsw_sp_l3proto ul_proto; /* Underlay. */ enum mlxsw_sp_l3proto ul_proto; /* Underlay. */
bool inc_parsing_depth;
struct mlxsw_sp_ipip_parms
(*parms_init)(const struct net_device *ol_dev);
int (*nexthop_update)(struct mlxsw_sp *mlxsw_sp, u32 adj_index, int (*nexthop_update)(struct mlxsw_sp *mlxsw_sp, u32 adj_index,
struct mlxsw_sp_ipip_entry *ipip_entry, struct mlxsw_sp_ipip_entry *ipip_entry,
...@@ -58,8 +72,13 @@ struct mlxsw_sp_ipip_ops { ...@@ -58,8 +72,13 @@ struct mlxsw_sp_ipip_ops {
int (*ol_netdev_change)(struct mlxsw_sp *mlxsw_sp, int (*ol_netdev_change)(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_ipip_entry *ipip_entry, struct mlxsw_sp_ipip_entry *ipip_entry,
struct netlink_ext_ack *extack); struct netlink_ext_ack *extack);
int (*rem_ip_addr_set)(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_ipip_entry *ipip_entry);
void (*rem_ip_addr_unset)(struct mlxsw_sp *mlxsw_sp,
const struct mlxsw_sp_ipip_entry *ipip_entry);
}; };
extern const struct mlxsw_sp_ipip_ops *mlxsw_sp_ipip_ops_arr[]; extern const struct mlxsw_sp_ipip_ops *mlxsw_sp1_ipip_ops_arr[];
extern const struct mlxsw_sp_ipip_ops *mlxsw_sp2_ipip_ops_arr[];
#endif /* _MLXSW_IPIP_H_*/ #endif /* _MLXSW_IPIP_H_*/
...@@ -226,6 +226,8 @@ static inline bool mlxsw_sp_l3addr_eq(const union mlxsw_sp_l3addr *addr1, ...@@ -226,6 +226,8 @@ static inline bool mlxsw_sp_l3addr_eq(const union mlxsw_sp_l3addr *addr1,
int mlxsw_sp_ipip_ecn_encap_init(struct mlxsw_sp *mlxsw_sp); int mlxsw_sp_ipip_ecn_encap_init(struct mlxsw_sp *mlxsw_sp);
int mlxsw_sp_ipip_ecn_decap_init(struct mlxsw_sp *mlxsw_sp); int mlxsw_sp_ipip_ecn_decap_init(struct mlxsw_sp *mlxsw_sp);
struct net_device *
mlxsw_sp_ipip_netdev_ul_dev_get(const struct net_device *ol_dev);
extern const struct mlxsw_sp_router_ll_ops mlxsw_sp_router_ll_xm_ops; extern const struct mlxsw_sp_router_ll_ops mlxsw_sp_router_ll_xm_ops;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment