cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

spectrum_ipip.c (20421B)


      1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
      2/* Copyright (c) 2017-2018 Mellanox Technologies. All rights reserved */
      3
      4#include <net/ip_tunnels.h>
      5#include <net/ip6_tunnel.h>
      6#include <net/inet_ecn.h>
      7
      8#include "spectrum_ipip.h"
      9#include "reg.h"
     10
     11struct ip_tunnel_parm
     12mlxsw_sp_ipip_netdev_parms4(const struct net_device *ol_dev)
     13{
     14	struct ip_tunnel *tun = netdev_priv(ol_dev);
     15
     16	return tun->parms;
     17}
     18
     19struct __ip6_tnl_parm
     20mlxsw_sp_ipip_netdev_parms6(const struct net_device *ol_dev)
     21{
     22	struct ip6_tnl *tun = netdev_priv(ol_dev);
     23
     24	return tun->parms;
     25}
     26
     27static bool mlxsw_sp_ipip_parms4_has_ikey(const struct ip_tunnel_parm *parms)
     28{
     29	return !!(parms->i_flags & TUNNEL_KEY);
     30}
     31
     32static bool mlxsw_sp_ipip_parms6_has_ikey(const struct __ip6_tnl_parm *parms)
     33{
     34	return !!(parms->i_flags & TUNNEL_KEY);
     35}
     36
     37static bool mlxsw_sp_ipip_parms4_has_okey(const struct ip_tunnel_parm *parms)
     38{
     39	return !!(parms->o_flags & TUNNEL_KEY);
     40}
     41
     42static bool mlxsw_sp_ipip_parms6_has_okey(const struct __ip6_tnl_parm *parms)
     43{
     44	return !!(parms->o_flags & TUNNEL_KEY);
     45}
     46
     47static u32 mlxsw_sp_ipip_parms4_ikey(const struct ip_tunnel_parm *parms)
     48{
     49	return mlxsw_sp_ipip_parms4_has_ikey(parms) ?
     50		be32_to_cpu(parms->i_key) : 0;
     51}
     52
     53static u32 mlxsw_sp_ipip_parms6_ikey(const struct __ip6_tnl_parm *parms)
     54{
     55	return mlxsw_sp_ipip_parms6_has_ikey(parms) ?
     56		be32_to_cpu(parms->i_key) : 0;
     57}
     58
     59static u32 mlxsw_sp_ipip_parms4_okey(const struct ip_tunnel_parm *parms)
     60{
     61	return mlxsw_sp_ipip_parms4_has_okey(parms) ?
     62		be32_to_cpu(parms->o_key) : 0;
     63}
     64
     65static u32 mlxsw_sp_ipip_parms6_okey(const struct __ip6_tnl_parm *parms)
     66{
     67	return mlxsw_sp_ipip_parms6_has_okey(parms) ?
     68		be32_to_cpu(parms->o_key) : 0;
     69}
     70
     71static union mlxsw_sp_l3addr
     72mlxsw_sp_ipip_parms4_saddr(const struct ip_tunnel_parm *parms)
     73{
     74	return (union mlxsw_sp_l3addr) { .addr4 = parms->iph.saddr };
     75}
     76
     77static union mlxsw_sp_l3addr
     78mlxsw_sp_ipip_parms6_saddr(const struct __ip6_tnl_parm *parms)
     79{
     80	return (union mlxsw_sp_l3addr) { .addr6 = parms->laddr };
     81}
     82
     83static union mlxsw_sp_l3addr
     84mlxsw_sp_ipip_parms4_daddr(const struct ip_tunnel_parm *parms)
     85{
     86	return (union mlxsw_sp_l3addr) { .addr4 = parms->iph.daddr };
     87}
     88
     89static union mlxsw_sp_l3addr
     90mlxsw_sp_ipip_parms6_daddr(const struct __ip6_tnl_parm *parms)
     91{
     92	return (union mlxsw_sp_l3addr) { .addr6 = parms->raddr };
     93}
     94
     95union mlxsw_sp_l3addr
     96mlxsw_sp_ipip_netdev_saddr(enum mlxsw_sp_l3proto proto,
     97			   const struct net_device *ol_dev)
     98{
     99	struct ip_tunnel_parm parms4;
    100	struct __ip6_tnl_parm parms6;
    101
    102	switch (proto) {
    103	case MLXSW_SP_L3_PROTO_IPV4:
    104		parms4 = mlxsw_sp_ipip_netdev_parms4(ol_dev);
    105		return mlxsw_sp_ipip_parms4_saddr(&parms4);
    106	case MLXSW_SP_L3_PROTO_IPV6:
    107		parms6 = mlxsw_sp_ipip_netdev_parms6(ol_dev);
    108		return mlxsw_sp_ipip_parms6_saddr(&parms6);
    109	}
    110
    111	WARN_ON(1);
    112	return (union mlxsw_sp_l3addr) {0};
    113}
    114
    115static __be32 mlxsw_sp_ipip_netdev_daddr4(const struct net_device *ol_dev)
    116{
    117
    118	struct ip_tunnel_parm parms4 = mlxsw_sp_ipip_netdev_parms4(ol_dev);
    119
    120	return mlxsw_sp_ipip_parms4_daddr(&parms4).addr4;
    121}
    122
    123static union mlxsw_sp_l3addr
    124mlxsw_sp_ipip_netdev_daddr(enum mlxsw_sp_l3proto proto,
    125			   const struct net_device *ol_dev)
    126{
    127	struct ip_tunnel_parm parms4;
    128	struct __ip6_tnl_parm parms6;
    129
    130	switch (proto) {
    131	case MLXSW_SP_L3_PROTO_IPV4:
    132		parms4 = mlxsw_sp_ipip_netdev_parms4(ol_dev);
    133		return mlxsw_sp_ipip_parms4_daddr(&parms4);
    134	case MLXSW_SP_L3_PROTO_IPV6:
    135		parms6 = mlxsw_sp_ipip_netdev_parms6(ol_dev);
    136		return mlxsw_sp_ipip_parms6_daddr(&parms6);
    137	}
    138
    139	WARN_ON(1);
    140	return (union mlxsw_sp_l3addr) {0};
    141}
    142
    143bool mlxsw_sp_l3addr_is_zero(union mlxsw_sp_l3addr addr)
    144{
    145	union mlxsw_sp_l3addr naddr = {0};
    146
    147	return !memcmp(&addr, &naddr, sizeof(naddr));
    148}
    149
    150static struct mlxsw_sp_ipip_parms
    151mlxsw_sp_ipip_netdev_parms_init_gre4(const struct net_device *ol_dev)
    152{
    153	struct ip_tunnel_parm parms = mlxsw_sp_ipip_netdev_parms4(ol_dev);
    154
    155	return (struct mlxsw_sp_ipip_parms) {
    156		.proto = MLXSW_SP_L3_PROTO_IPV4,
    157		.saddr = mlxsw_sp_ipip_parms4_saddr(&parms),
    158		.daddr = mlxsw_sp_ipip_parms4_daddr(&parms),
    159		.link = parms.link,
    160		.ikey = mlxsw_sp_ipip_parms4_ikey(&parms),
    161		.okey = mlxsw_sp_ipip_parms4_okey(&parms),
    162	};
    163}
    164
    165static int
    166mlxsw_sp_ipip_nexthop_update_gre4(struct mlxsw_sp *mlxsw_sp, u32 adj_index,
    167				  struct mlxsw_sp_ipip_entry *ipip_entry,
    168				  bool force, char *ratr_pl)
    169{
    170	u16 rif_index = mlxsw_sp_ipip_lb_rif_index(ipip_entry->ol_lb);
    171	__be32 daddr4 = mlxsw_sp_ipip_netdev_daddr4(ipip_entry->ol_dev);
    172	enum mlxsw_reg_ratr_op op;
    173
    174	op = force ? MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY :
    175		     MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY_ON_ACTIVITY;
    176	mlxsw_reg_ratr_pack(ratr_pl, op, true, MLXSW_REG_RATR_TYPE_IPIP,
    177			    adj_index, rif_index);
    178	mlxsw_reg_ratr_ipip4_entry_pack(ratr_pl, be32_to_cpu(daddr4));
    179
    180	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ratr), ratr_pl);
    181}
    182
    183static int
    184mlxsw_sp_ipip_decap_config_gre4(struct mlxsw_sp *mlxsw_sp,
    185				struct mlxsw_sp_ipip_entry *ipip_entry,
    186				u32 tunnel_index)
    187{
    188	u16 rif_index = mlxsw_sp_ipip_lb_rif_index(ipip_entry->ol_lb);
    189	u16 ul_rif_id = mlxsw_sp_ipip_lb_ul_rif_id(ipip_entry->ol_lb);
    190	char rtdp_pl[MLXSW_REG_RTDP_LEN];
    191	struct ip_tunnel_parm parms;
    192	unsigned int type_check;
    193	bool has_ikey;
    194	u32 daddr4;
    195	u32 ikey;
    196
    197	parms = mlxsw_sp_ipip_netdev_parms4(ipip_entry->ol_dev);
    198	has_ikey = mlxsw_sp_ipip_parms4_has_ikey(&parms);
    199	ikey = mlxsw_sp_ipip_parms4_ikey(&parms);
    200
    201	mlxsw_reg_rtdp_pack(rtdp_pl, MLXSW_REG_RTDP_TYPE_IPIP, tunnel_index);
    202	mlxsw_reg_rtdp_egress_router_interface_set(rtdp_pl, ul_rif_id);
    203
    204	type_check = has_ikey ?
    205		MLXSW_REG_RTDP_IPIP_TYPE_CHECK_ALLOW_GRE_KEY :
    206		MLXSW_REG_RTDP_IPIP_TYPE_CHECK_ALLOW_GRE;
    207
    208	/* Linux demuxes tunnels based on packet SIP (which must match tunnel
    209	 * remote IP). Thus configure decap so that it filters out packets that
    210	 * are not IPv4 or have the wrong SIP. IPIP_DECAP_ERROR trap is
    211	 * generated for packets that fail this criterion. Linux then handles
    212	 * such packets in slow path and generates ICMP destination unreachable.
    213	 */
    214	daddr4 = be32_to_cpu(mlxsw_sp_ipip_netdev_daddr4(ipip_entry->ol_dev));
    215	mlxsw_reg_rtdp_ipip4_pack(rtdp_pl, rif_index,
    216				  MLXSW_REG_RTDP_IPIP_SIP_CHECK_FILTER_IPV4,
    217				  type_check, has_ikey, daddr4, ikey);
    218
    219	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rtdp), rtdp_pl);
    220}
    221
    222static bool mlxsw_sp_ipip_tunnel_complete(enum mlxsw_sp_l3proto proto,
    223					  const struct net_device *ol_dev)
    224{
    225	union mlxsw_sp_l3addr saddr = mlxsw_sp_ipip_netdev_saddr(proto, ol_dev);
    226	union mlxsw_sp_l3addr daddr = mlxsw_sp_ipip_netdev_daddr(proto, ol_dev);
    227
    228	/* Tunnels with unset local or remote address are valid in Linux and
    229	 * used for lightweight tunnels (LWT) and Non-Broadcast Multi-Access
    230	 * (NBMA) tunnels. In principle these can be offloaded, but the driver
    231	 * currently doesn't support this. So punt.
    232	 */
    233	return !mlxsw_sp_l3addr_is_zero(saddr) &&
    234	       !mlxsw_sp_l3addr_is_zero(daddr);
    235}
    236
    237static bool mlxsw_sp_ipip_can_offload_gre4(const struct mlxsw_sp *mlxsw_sp,
    238					   const struct net_device *ol_dev)
    239{
    240	struct ip_tunnel *tunnel = netdev_priv(ol_dev);
    241	__be16 okflags = TUNNEL_KEY; /* We can't offload any other features. */
    242	bool inherit_ttl = tunnel->parms.iph.ttl == 0;
    243	bool inherit_tos = tunnel->parms.iph.tos & 0x1;
    244
    245	return (tunnel->parms.i_flags & ~okflags) == 0 &&
    246	       (tunnel->parms.o_flags & ~okflags) == 0 &&
    247	       inherit_ttl && inherit_tos &&
    248	       mlxsw_sp_ipip_tunnel_complete(MLXSW_SP_L3_PROTO_IPV4, ol_dev);
    249}
    250
    251static struct mlxsw_sp_rif_ipip_lb_config
    252mlxsw_sp_ipip_ol_loopback_config_gre4(struct mlxsw_sp *mlxsw_sp,
    253				      const struct net_device *ol_dev)
    254{
    255	struct ip_tunnel_parm parms = mlxsw_sp_ipip_netdev_parms4(ol_dev);
    256	enum mlxsw_reg_ritr_loopback_ipip_type lb_ipipt;
    257
    258	lb_ipipt = mlxsw_sp_ipip_parms4_has_okey(&parms) ?
    259		MLXSW_REG_RITR_LOOPBACK_IPIP_TYPE_IP_IN_GRE_KEY_IN_IP :
    260		MLXSW_REG_RITR_LOOPBACK_IPIP_TYPE_IP_IN_GRE_IN_IP;
    261	return (struct mlxsw_sp_rif_ipip_lb_config){
    262		.lb_ipipt = lb_ipipt,
    263		.okey = mlxsw_sp_ipip_parms4_okey(&parms),
    264		.ul_protocol = MLXSW_SP_L3_PROTO_IPV4,
    265		.saddr = mlxsw_sp_ipip_netdev_saddr(MLXSW_SP_L3_PROTO_IPV4,
    266						    ol_dev),
    267	};
    268}
    269
    270static int
    271mlxsw_sp_ipip_ol_netdev_change_gre(struct mlxsw_sp *mlxsw_sp,
    272				   struct mlxsw_sp_ipip_entry *ipip_entry,
    273				   const struct mlxsw_sp_ipip_parms *new_parms,
    274				   struct netlink_ext_ack *extack)
    275{
    276	const struct mlxsw_sp_ipip_parms *old_parms = &ipip_entry->parms;
    277	bool update_tunnel = false;
    278	bool update_decap = false;
    279	bool update_nhs = false;
    280	int err = 0;
    281
    282	if (!mlxsw_sp_l3addr_eq(&new_parms->saddr, &old_parms->saddr)) {
    283		u16 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(ipip_entry->ol_dev);
    284
    285		/* Since the local address has changed, if there is another
    286		 * tunnel with a matching saddr, both need to be demoted.
    287		 */
    288		if (mlxsw_sp_ipip_demote_tunnel_by_saddr(mlxsw_sp,
    289							 new_parms->proto,
    290							 new_parms->saddr,
    291							 ul_tb_id,
    292							 ipip_entry)) {
    293			mlxsw_sp_ipip_entry_demote_tunnel(mlxsw_sp, ipip_entry);
    294			return 0;
    295		}
    296
    297		update_tunnel = true;
    298	} else if (old_parms->okey != new_parms->okey ||
    299		   old_parms->link != new_parms->link) {
    300		update_tunnel = true;
    301	} else if (!mlxsw_sp_l3addr_eq(&new_parms->daddr, &old_parms->daddr)) {
    302		update_nhs = true;
    303	} else if (old_parms->ikey != new_parms->ikey) {
    304		update_decap = true;
    305	}
    306
    307	if (update_tunnel)
    308		err = __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp, ipip_entry,
    309							  true, true, true,
    310							  extack);
    311	else if (update_nhs)
    312		err = __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp, ipip_entry,
    313							  false, false, true,
    314							  extack);
    315	else if (update_decap)
    316		err = __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp, ipip_entry,
    317							  false, false, false,
    318							  extack);
    319	if (err)
    320		return err;
    321
    322	ipip_entry->parms = *new_parms;
    323	return 0;
    324}
    325
    326static int
    327mlxsw_sp_ipip_ol_netdev_change_gre4(struct mlxsw_sp *mlxsw_sp,
    328				    struct mlxsw_sp_ipip_entry *ipip_entry,
    329				    struct netlink_ext_ack *extack)
    330{
    331	struct mlxsw_sp_ipip_parms new_parms;
    332
    333	new_parms = mlxsw_sp_ipip_netdev_parms_init_gre4(ipip_entry->ol_dev);
    334	return mlxsw_sp_ipip_ol_netdev_change_gre(mlxsw_sp, ipip_entry,
    335						  &new_parms, extack);
    336}
    337
    338static int
    339mlxsw_sp_ipip_rem_addr_set_gre4(struct mlxsw_sp *mlxsw_sp,
    340				struct mlxsw_sp_ipip_entry *ipip_entry)
    341{
    342	return 0;
    343}
    344
    345static void
    346mlxsw_sp_ipip_rem_addr_unset_gre4(struct mlxsw_sp *mlxsw_sp,
    347				  const struct mlxsw_sp_ipip_entry *ipip_entry)
    348{
    349}
    350
    351static const struct mlxsw_sp_ipip_ops mlxsw_sp_ipip_gre4_ops = {
    352	.dev_type = ARPHRD_IPGRE,
    353	.ul_proto = MLXSW_SP_L3_PROTO_IPV4,
    354	.inc_parsing_depth = false,
    355	.parms_init = mlxsw_sp_ipip_netdev_parms_init_gre4,
    356	.nexthop_update = mlxsw_sp_ipip_nexthop_update_gre4,
    357	.decap_config = mlxsw_sp_ipip_decap_config_gre4,
    358	.can_offload = mlxsw_sp_ipip_can_offload_gre4,
    359	.ol_loopback_config = mlxsw_sp_ipip_ol_loopback_config_gre4,
    360	.ol_netdev_change = mlxsw_sp_ipip_ol_netdev_change_gre4,
    361	.rem_ip_addr_set = mlxsw_sp_ipip_rem_addr_set_gre4,
    362	.rem_ip_addr_unset = mlxsw_sp_ipip_rem_addr_unset_gre4,
    363};
    364
    365static struct mlxsw_sp_ipip_parms
    366mlxsw_sp1_ipip_netdev_parms_init_gre6(const struct net_device *ol_dev)
    367{
    368	struct mlxsw_sp_ipip_parms parms = {0};
    369
    370	WARN_ON_ONCE(1);
    371	return parms;
    372}
    373
    374static int
    375mlxsw_sp1_ipip_nexthop_update_gre6(struct mlxsw_sp *mlxsw_sp, u32 adj_index,
    376				   struct mlxsw_sp_ipip_entry *ipip_entry,
    377				   bool force, char *ratr_pl)
    378{
    379	WARN_ON_ONCE(1);
    380	return -EINVAL;
    381}
    382
    383static int
    384mlxsw_sp1_ipip_decap_config_gre6(struct mlxsw_sp *mlxsw_sp,
    385				 struct mlxsw_sp_ipip_entry *ipip_entry,
    386				 u32 tunnel_index)
    387{
    388	WARN_ON_ONCE(1);
    389	return -EINVAL;
    390}
    391
    392static bool mlxsw_sp1_ipip_can_offload_gre6(const struct mlxsw_sp *mlxsw_sp,
    393					    const struct net_device *ol_dev)
    394{
    395	return false;
    396}
    397
    398static struct mlxsw_sp_rif_ipip_lb_config
    399mlxsw_sp1_ipip_ol_loopback_config_gre6(struct mlxsw_sp *mlxsw_sp,
    400				       const struct net_device *ol_dev)
    401{
    402	struct mlxsw_sp_rif_ipip_lb_config config = {0};
    403
    404	WARN_ON_ONCE(1);
    405	return config;
    406}
    407
    408static int
    409mlxsw_sp1_ipip_ol_netdev_change_gre6(struct mlxsw_sp *mlxsw_sp,
    410				     struct mlxsw_sp_ipip_entry *ipip_entry,
    411				     struct netlink_ext_ack *extack)
    412{
    413	WARN_ON_ONCE(1);
    414	return -EINVAL;
    415}
    416
    417static int
    418mlxsw_sp1_ipip_rem_addr_set_gre6(struct mlxsw_sp *mlxsw_sp,
    419				 struct mlxsw_sp_ipip_entry *ipip_entry)
    420{
    421	WARN_ON_ONCE(1);
    422	return -EINVAL;
    423}
    424
    425static void
    426mlxsw_sp1_ipip_rem_addr_unset_gre6(struct mlxsw_sp *mlxsw_sp,
    427				   const struct mlxsw_sp_ipip_entry *ipip_entry)
    428{
    429	WARN_ON_ONCE(1);
    430}
    431
    432static const struct mlxsw_sp_ipip_ops mlxsw_sp1_ipip_gre6_ops = {
    433	.dev_type = ARPHRD_IP6GRE,
    434	.ul_proto = MLXSW_SP_L3_PROTO_IPV6,
    435	.inc_parsing_depth = true,
    436	.parms_init = mlxsw_sp1_ipip_netdev_parms_init_gre6,
    437	.nexthop_update = mlxsw_sp1_ipip_nexthop_update_gre6,
    438	.decap_config = mlxsw_sp1_ipip_decap_config_gre6,
    439	.can_offload = mlxsw_sp1_ipip_can_offload_gre6,
    440	.ol_loopback_config = mlxsw_sp1_ipip_ol_loopback_config_gre6,
    441	.ol_netdev_change = mlxsw_sp1_ipip_ol_netdev_change_gre6,
    442	.rem_ip_addr_set = mlxsw_sp1_ipip_rem_addr_set_gre6,
    443	.rem_ip_addr_unset = mlxsw_sp1_ipip_rem_addr_unset_gre6,
    444};
    445
    446const struct mlxsw_sp_ipip_ops *mlxsw_sp1_ipip_ops_arr[] = {
    447	[MLXSW_SP_IPIP_TYPE_GRE4] = &mlxsw_sp_ipip_gre4_ops,
    448	[MLXSW_SP_IPIP_TYPE_GRE6] = &mlxsw_sp1_ipip_gre6_ops,
    449};
    450
    451static struct mlxsw_sp_ipip_parms
    452mlxsw_sp2_ipip_netdev_parms_init_gre6(const struct net_device *ol_dev)
    453{
    454	struct __ip6_tnl_parm parms = mlxsw_sp_ipip_netdev_parms6(ol_dev);
    455
    456	return (struct mlxsw_sp_ipip_parms) {
    457		.proto = MLXSW_SP_L3_PROTO_IPV6,
    458		.saddr = mlxsw_sp_ipip_parms6_saddr(&parms),
    459		.daddr = mlxsw_sp_ipip_parms6_daddr(&parms),
    460		.link = parms.link,
    461		.ikey = mlxsw_sp_ipip_parms6_ikey(&parms),
    462		.okey = mlxsw_sp_ipip_parms6_okey(&parms),
    463	};
    464}
    465
    466static int
    467mlxsw_sp2_ipip_nexthop_update_gre6(struct mlxsw_sp *mlxsw_sp, u32 adj_index,
    468				   struct mlxsw_sp_ipip_entry *ipip_entry,
    469				   bool force, char *ratr_pl)
    470{
    471	u16 rif_index = mlxsw_sp_ipip_lb_rif_index(ipip_entry->ol_lb);
    472	enum mlxsw_reg_ratr_op op;
    473
    474	op = force ? MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY :
    475		     MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY_ON_ACTIVITY;
    476	mlxsw_reg_ratr_pack(ratr_pl, op, true, MLXSW_REG_RATR_TYPE_IPIP,
    477			    adj_index, rif_index);
    478	mlxsw_reg_ratr_ipip6_entry_pack(ratr_pl,
    479					ipip_entry->dip_kvdl_index);
    480
    481	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ratr), ratr_pl);
    482}
    483
    484static int
    485mlxsw_sp2_ipip_decap_config_gre6(struct mlxsw_sp *mlxsw_sp,
    486				 struct mlxsw_sp_ipip_entry *ipip_entry,
    487				 u32 tunnel_index)
    488{
    489	u16 rif_index = mlxsw_sp_ipip_lb_rif_index(ipip_entry->ol_lb);
    490	u16 ul_rif_id = mlxsw_sp_ipip_lb_ul_rif_id(ipip_entry->ol_lb);
    491	char rtdp_pl[MLXSW_REG_RTDP_LEN];
    492	struct __ip6_tnl_parm parms;
    493	unsigned int type_check;
    494	bool has_ikey;
    495	u32 ikey;
    496
    497	parms = mlxsw_sp_ipip_netdev_parms6(ipip_entry->ol_dev);
    498	has_ikey = mlxsw_sp_ipip_parms6_has_ikey(&parms);
    499	ikey = mlxsw_sp_ipip_parms6_ikey(&parms);
    500
    501	mlxsw_reg_rtdp_pack(rtdp_pl, MLXSW_REG_RTDP_TYPE_IPIP, tunnel_index);
    502	mlxsw_reg_rtdp_egress_router_interface_set(rtdp_pl, ul_rif_id);
    503
    504	type_check = has_ikey ?
    505		MLXSW_REG_RTDP_IPIP_TYPE_CHECK_ALLOW_GRE_KEY :
    506		MLXSW_REG_RTDP_IPIP_TYPE_CHECK_ALLOW_GRE;
    507
    508	/* Linux demuxes tunnels based on packet SIP (which must match tunnel
    509	 * remote IP). Thus configure decap so that it filters out packets that
    510	 * are not IPv6 or have the wrong SIP. IPIP_DECAP_ERROR trap is
    511	 * generated for packets that fail this criterion. Linux then handles
    512	 * such packets in slow path and generates ICMP destination unreachable.
    513	 */
    514	mlxsw_reg_rtdp_ipip6_pack(rtdp_pl, rif_index,
    515				  MLXSW_REG_RTDP_IPIP_SIP_CHECK_FILTER_IPV6,
    516				  type_check, has_ikey,
    517				  ipip_entry->dip_kvdl_index, ikey);
    518
    519	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rtdp), rtdp_pl);
    520}
    521
    522static bool mlxsw_sp2_ipip_can_offload_gre6(const struct mlxsw_sp *mlxsw_sp,
    523					    const struct net_device *ol_dev)
    524{
    525	struct __ip6_tnl_parm tparm = mlxsw_sp_ipip_netdev_parms6(ol_dev);
    526	bool inherit_tos = tparm.flags & IP6_TNL_F_USE_ORIG_TCLASS;
    527	bool inherit_ttl = tparm.hop_limit == 0;
    528	__be16 okflags = TUNNEL_KEY; /* We can't offload any other features. */
    529
    530	return (tparm.i_flags & ~okflags) == 0 &&
    531	       (tparm.o_flags & ~okflags) == 0 &&
    532	       inherit_ttl && inherit_tos &&
    533	       mlxsw_sp_ipip_tunnel_complete(MLXSW_SP_L3_PROTO_IPV6, ol_dev);
    534}
    535
    536static struct mlxsw_sp_rif_ipip_lb_config
    537mlxsw_sp2_ipip_ol_loopback_config_gre6(struct mlxsw_sp *mlxsw_sp,
    538				       const struct net_device *ol_dev)
    539{
    540	struct __ip6_tnl_parm parms = mlxsw_sp_ipip_netdev_parms6(ol_dev);
    541	enum mlxsw_reg_ritr_loopback_ipip_type lb_ipipt;
    542
    543	lb_ipipt = mlxsw_sp_ipip_parms6_has_okey(&parms) ?
    544		MLXSW_REG_RITR_LOOPBACK_IPIP_TYPE_IP_IN_GRE_KEY_IN_IP :
    545		MLXSW_REG_RITR_LOOPBACK_IPIP_TYPE_IP_IN_GRE_IN_IP;
    546	return (struct mlxsw_sp_rif_ipip_lb_config){
    547		.lb_ipipt = lb_ipipt,
    548		.okey = mlxsw_sp_ipip_parms6_okey(&parms),
    549		.ul_protocol = MLXSW_SP_L3_PROTO_IPV6,
    550		.saddr = mlxsw_sp_ipip_netdev_saddr(MLXSW_SP_L3_PROTO_IPV6,
    551						    ol_dev),
    552	};
    553}
    554
    555static int
    556mlxsw_sp2_ipip_ol_netdev_change_gre6(struct mlxsw_sp *mlxsw_sp,
    557				     struct mlxsw_sp_ipip_entry *ipip_entry,
    558				     struct netlink_ext_ack *extack)
    559{
    560	struct mlxsw_sp_ipip_parms new_parms;
    561
    562	new_parms = mlxsw_sp2_ipip_netdev_parms_init_gre6(ipip_entry->ol_dev);
    563	return mlxsw_sp_ipip_ol_netdev_change_gre(mlxsw_sp, ipip_entry,
    564						  &new_parms, extack);
    565}
    566
    567static int
    568mlxsw_sp2_ipip_rem_addr_set_gre6(struct mlxsw_sp *mlxsw_sp,
    569				 struct mlxsw_sp_ipip_entry *ipip_entry)
    570{
    571	return mlxsw_sp_ipv6_addr_kvdl_index_get(mlxsw_sp,
    572						 &ipip_entry->parms.daddr.addr6,
    573						 &ipip_entry->dip_kvdl_index);
    574}
    575
    576static void
    577mlxsw_sp2_ipip_rem_addr_unset_gre6(struct mlxsw_sp *mlxsw_sp,
    578				   const struct mlxsw_sp_ipip_entry *ipip_entry)
    579{
    580	mlxsw_sp_ipv6_addr_put(mlxsw_sp, &ipip_entry->parms.daddr.addr6);
    581}
    582
    583static const struct mlxsw_sp_ipip_ops mlxsw_sp2_ipip_gre6_ops = {
    584	.dev_type = ARPHRD_IP6GRE,
    585	.ul_proto = MLXSW_SP_L3_PROTO_IPV6,
    586	.inc_parsing_depth = true,
    587	.parms_init = mlxsw_sp2_ipip_netdev_parms_init_gre6,
    588	.nexthop_update = mlxsw_sp2_ipip_nexthop_update_gre6,
    589	.decap_config = mlxsw_sp2_ipip_decap_config_gre6,
    590	.can_offload = mlxsw_sp2_ipip_can_offload_gre6,
    591	.ol_loopback_config = mlxsw_sp2_ipip_ol_loopback_config_gre6,
    592	.ol_netdev_change = mlxsw_sp2_ipip_ol_netdev_change_gre6,
    593	.rem_ip_addr_set = mlxsw_sp2_ipip_rem_addr_set_gre6,
    594	.rem_ip_addr_unset = mlxsw_sp2_ipip_rem_addr_unset_gre6,
    595};
    596
    597const struct mlxsw_sp_ipip_ops *mlxsw_sp2_ipip_ops_arr[] = {
    598	[MLXSW_SP_IPIP_TYPE_GRE4] = &mlxsw_sp_ipip_gre4_ops,
    599	[MLXSW_SP_IPIP_TYPE_GRE6] = &mlxsw_sp2_ipip_gre6_ops,
    600};
    601
    602static int mlxsw_sp_ipip_ecn_encap_init_one(struct mlxsw_sp *mlxsw_sp,
    603					    u8 inner_ecn, u8 outer_ecn)
    604{
    605	char tieem_pl[MLXSW_REG_TIEEM_LEN];
    606
    607	mlxsw_reg_tieem_pack(tieem_pl, inner_ecn, outer_ecn);
    608	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(tieem), tieem_pl);
    609}
    610
    611int mlxsw_sp_ipip_ecn_encap_init(struct mlxsw_sp *mlxsw_sp)
    612{
    613	int i;
    614
    615	/* Iterate over inner ECN values */
    616	for (i = INET_ECN_NOT_ECT; i <= INET_ECN_CE; i++) {
    617		u8 outer_ecn = INET_ECN_encapsulate(0, i);
    618		int err;
    619
    620		err = mlxsw_sp_ipip_ecn_encap_init_one(mlxsw_sp, i, outer_ecn);
    621		if (err)
    622			return err;
    623	}
    624
    625	return 0;
    626}
    627
    628static int mlxsw_sp_ipip_ecn_decap_init_one(struct mlxsw_sp *mlxsw_sp,
    629					    u8 inner_ecn, u8 outer_ecn)
    630{
    631	char tidem_pl[MLXSW_REG_TIDEM_LEN];
    632	u8 new_inner_ecn;
    633	bool trap_en;
    634
    635	new_inner_ecn = mlxsw_sp_tunnel_ecn_decap(outer_ecn, inner_ecn,
    636						  &trap_en);
    637	mlxsw_reg_tidem_pack(tidem_pl, outer_ecn, inner_ecn, new_inner_ecn,
    638			     trap_en, trap_en ? MLXSW_TRAP_ID_DECAP_ECN0 : 0);
    639	return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(tidem), tidem_pl);
    640}
    641
    642int mlxsw_sp_ipip_ecn_decap_init(struct mlxsw_sp *mlxsw_sp)
    643{
    644	int i, j, err;
    645
    646	/* Iterate over inner ECN values */
    647	for (i = INET_ECN_NOT_ECT; i <= INET_ECN_CE; i++) {
    648		/* Iterate over outer ECN values */
    649		for (j = INET_ECN_NOT_ECT; j <= INET_ECN_CE; j++) {
    650			err = mlxsw_sp_ipip_ecn_decap_init_one(mlxsw_sp, i, j);
    651			if (err)
    652				return err;
    653		}
    654	}
    655
    656	return 0;
    657}
    658
    659struct net_device *
    660mlxsw_sp_ipip_netdev_ul_dev_get(const struct net_device *ol_dev)
    661{
    662	struct net *net = dev_net(ol_dev);
    663	struct ip_tunnel *tun4;
    664	struct ip6_tnl *tun6;
    665
    666	switch (ol_dev->type) {
    667	case ARPHRD_IPGRE:
    668		tun4 = netdev_priv(ol_dev);
    669		return dev_get_by_index_rcu(net, tun4->parms.link);
    670	case ARPHRD_IP6GRE:
    671		tun6 = netdev_priv(ol_dev);
    672		return dev_get_by_index_rcu(net, tun6->parms.link);
    673	default:
    674		return NULL;
    675	}
    676}