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(struct ip_tunnel_parm parms) 28{ 29 return !!(parms.i_flags & TUNNEL_KEY); 30} 31 32static bool mlxsw_sp_ipip_parms4_has_okey(struct ip_tunnel_parm parms) 33{ 34 return !!(parms.o_flags & TUNNEL_KEY); 35} 36 37static u32 mlxsw_sp_ipip_parms4_ikey(struct ip_tunnel_parm parms) 38{ 39 return mlxsw_sp_ipip_parms4_has_ikey(parms) ? 40 be32_to_cpu(parms.i_key) : 0; 41} 42 43static u32 mlxsw_sp_ipip_parms4_okey(struct ip_tunnel_parm parms) 44{ 45 return mlxsw_sp_ipip_parms4_has_okey(parms) ? 46 be32_to_cpu(parms.o_key) : 0; 47} 48 49static union mlxsw_sp_l3addr 50mlxsw_sp_ipip_parms4_saddr(struct ip_tunnel_parm parms) 51{ 52 return (union mlxsw_sp_l3addr) { .addr4 = parms.iph.saddr }; 53} 54 55static union mlxsw_sp_l3addr 56mlxsw_sp_ipip_parms6_saddr(struct __ip6_tnl_parm parms) 57{ 58 return (union mlxsw_sp_l3addr) { .addr6 = parms.laddr }; 59} 60 61static union mlxsw_sp_l3addr 62mlxsw_sp_ipip_parms4_daddr(struct ip_tunnel_parm parms) 63{ 64 return (union mlxsw_sp_l3addr) { .addr4 = parms.iph.daddr }; 65} 66 67static union mlxsw_sp_l3addr 68mlxsw_sp_ipip_parms6_daddr(struct __ip6_tnl_parm parms) 69{ 70 return (union mlxsw_sp_l3addr) { .addr6 = parms.raddr }; 71} 72 73union mlxsw_sp_l3addr 74mlxsw_sp_ipip_netdev_saddr(enum mlxsw_sp_l3proto proto, 75 const struct net_device *ol_dev) 76{ 77 struct ip_tunnel_parm parms4; 78 struct __ip6_tnl_parm parms6; 79 80 switch (proto) { 81 case MLXSW_SP_L3_PROTO_IPV4: 82 parms4 = mlxsw_sp_ipip_netdev_parms4(ol_dev); 83 return mlxsw_sp_ipip_parms4_saddr(parms4); 84 case MLXSW_SP_L3_PROTO_IPV6: 85 parms6 = mlxsw_sp_ipip_netdev_parms6(ol_dev); 86 return mlxsw_sp_ipip_parms6_saddr(parms6); 87 } 88 89 WARN_ON(1); 90 return (union mlxsw_sp_l3addr) {0}; 91} 92 93static __be32 mlxsw_sp_ipip_netdev_daddr4(const struct net_device *ol_dev) 94{ 95 96 struct ip_tunnel_parm parms4 = mlxsw_sp_ipip_netdev_parms4(ol_dev); 97 98 return mlxsw_sp_ipip_parms4_daddr(parms4).addr4; 99} 100 101static union mlxsw_sp_l3addr 102mlxsw_sp_ipip_netdev_daddr(enum mlxsw_sp_l3proto proto, 103 const struct net_device *ol_dev) 104{ 105 struct ip_tunnel_parm parms4; 106 struct __ip6_tnl_parm parms6; 107 108 switch (proto) { 109 case MLXSW_SP_L3_PROTO_IPV4: 110 parms4 = mlxsw_sp_ipip_netdev_parms4(ol_dev); 111 return mlxsw_sp_ipip_parms4_daddr(parms4); 112 case MLXSW_SP_L3_PROTO_IPV6: 113 parms6 = mlxsw_sp_ipip_netdev_parms6(ol_dev); 114 return mlxsw_sp_ipip_parms6_daddr(parms6); 115 } 116 117 WARN_ON(1); 118 return (union mlxsw_sp_l3addr) {0}; 119} 120 121bool mlxsw_sp_l3addr_is_zero(union mlxsw_sp_l3addr addr) 122{ 123 union mlxsw_sp_l3addr naddr = {0}; 124 125 return !memcmp(&addr, &naddr, sizeof(naddr)); 126} 127 128static int 129mlxsw_sp_ipip_nexthop_update_gre4(struct mlxsw_sp *mlxsw_sp, u32 adj_index, 130 struct mlxsw_sp_ipip_entry *ipip_entry) 131{ 132 u16 rif_index = mlxsw_sp_ipip_lb_rif_index(ipip_entry->ol_lb); 133 __be32 daddr4 = mlxsw_sp_ipip_netdev_daddr4(ipip_entry->ol_dev); 134 char ratr_pl[MLXSW_REG_RATR_LEN]; 135 136 mlxsw_reg_ratr_pack(ratr_pl, MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY, 137 true, MLXSW_REG_RATR_TYPE_IPIP, 138 adj_index, rif_index); 139 mlxsw_reg_ratr_ipip4_entry_pack(ratr_pl, be32_to_cpu(daddr4)); 140 141 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ratr), ratr_pl); 142} 143 144static int 145mlxsw_sp_ipip_fib_entry_op_gre4_rtdp(struct mlxsw_sp *mlxsw_sp, 146 u32 tunnel_index, 147 struct mlxsw_sp_ipip_entry *ipip_entry) 148{ 149 u16 rif_index = mlxsw_sp_ipip_lb_rif_index(ipip_entry->ol_lb); 150 u16 ul_rif_id = mlxsw_sp_ipip_lb_ul_rif_id(ipip_entry->ol_lb); 151 char rtdp_pl[MLXSW_REG_RTDP_LEN]; 152 struct ip_tunnel_parm parms; 153 unsigned int type_check; 154 bool has_ikey; 155 u32 daddr4; 156 u32 ikey; 157 158 parms = mlxsw_sp_ipip_netdev_parms4(ipip_entry->ol_dev); 159 has_ikey = mlxsw_sp_ipip_parms4_has_ikey(parms); 160 ikey = mlxsw_sp_ipip_parms4_ikey(parms); 161 162 mlxsw_reg_rtdp_pack(rtdp_pl, MLXSW_REG_RTDP_TYPE_IPIP, tunnel_index); 163 mlxsw_reg_rtdp_egress_router_interface_set(rtdp_pl, ul_rif_id); 164 165 type_check = has_ikey ? 166 MLXSW_REG_RTDP_IPIP_TYPE_CHECK_ALLOW_GRE_KEY : 167 MLXSW_REG_RTDP_IPIP_TYPE_CHECK_ALLOW_GRE; 168 169 /* Linux demuxes tunnels based on packet SIP (which must match tunnel 170 * remote IP). Thus configure decap so that it filters out packets that 171 * are not IPv4 or have the wrong SIP. IPIP_DECAP_ERROR trap is 172 * generated for packets that fail this criterion. Linux then handles 173 * such packets in slow path and generates ICMP destination unreachable. 174 */ 175 daddr4 = be32_to_cpu(mlxsw_sp_ipip_netdev_daddr4(ipip_entry->ol_dev)); 176 mlxsw_reg_rtdp_ipip4_pack(rtdp_pl, rif_index, 177 MLXSW_REG_RTDP_IPIP_SIP_CHECK_FILTER_IPV4, 178 type_check, has_ikey, daddr4, ikey); 179 180 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rtdp), rtdp_pl); 181} 182 183static int 184mlxsw_sp_ipip_fib_entry_op_gre4_ralue(struct mlxsw_sp *mlxsw_sp, 185 u32 dip, u8 prefix_len, u16 ul_vr_id, 186 enum mlxsw_reg_ralue_op op, 187 u32 tunnel_index) 188{ 189 char ralue_pl[MLXSW_REG_RALUE_LEN]; 190 191 mlxsw_reg_ralue_pack4(ralue_pl, MLXSW_REG_RALXX_PROTOCOL_IPV4, op, 192 ul_vr_id, prefix_len, dip); 193 mlxsw_reg_ralue_act_ip2me_tun_pack(ralue_pl, tunnel_index); 194 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl); 195} 196 197static int mlxsw_sp_ipip_fib_entry_op_gre4(struct mlxsw_sp *mlxsw_sp, 198 struct mlxsw_sp_ipip_entry *ipip_entry, 199 enum mlxsw_reg_ralue_op op, 200 u32 tunnel_index) 201{ 202 u16 ul_vr_id = mlxsw_sp_ipip_lb_ul_vr_id(ipip_entry->ol_lb); 203 __be32 dip; 204 int err; 205 206 err = mlxsw_sp_ipip_fib_entry_op_gre4_rtdp(mlxsw_sp, tunnel_index, 207 ipip_entry); 208 if (err) 209 return err; 210 211 dip = mlxsw_sp_ipip_netdev_saddr(MLXSW_SP_L3_PROTO_IPV4, 212 ipip_entry->ol_dev).addr4; 213 return mlxsw_sp_ipip_fib_entry_op_gre4_ralue(mlxsw_sp, be32_to_cpu(dip), 214 32, ul_vr_id, op, 215 tunnel_index); 216} 217 218static bool mlxsw_sp_ipip_tunnel_complete(enum mlxsw_sp_l3proto proto, 219 const struct net_device *ol_dev) 220{ 221 union mlxsw_sp_l3addr saddr = mlxsw_sp_ipip_netdev_saddr(proto, ol_dev); 222 union mlxsw_sp_l3addr daddr = mlxsw_sp_ipip_netdev_daddr(proto, ol_dev); 223 224 /* Tunnels with unset local or remote address are valid in Linux and 225 * used for lightweight tunnels (LWT) and Non-Broadcast Multi-Access 226 * (NBMA) tunnels. In principle these can be offloaded, but the driver 227 * currently doesn't support this. So punt. 228 */ 229 return !mlxsw_sp_l3addr_is_zero(saddr) && 230 !mlxsw_sp_l3addr_is_zero(daddr); 231} 232 233static bool mlxsw_sp_ipip_can_offload_gre4(const struct mlxsw_sp *mlxsw_sp, 234 const struct net_device *ol_dev, 235 enum mlxsw_sp_l3proto ol_proto) 236{ 237 struct ip_tunnel *tunnel = netdev_priv(ol_dev); 238 __be16 okflags = TUNNEL_KEY; /* We can't offload any other features. */ 239 bool inherit_ttl = tunnel->parms.iph.ttl == 0; 240 bool inherit_tos = tunnel->parms.iph.tos & 0x1; 241 242 return (tunnel->parms.i_flags & ~okflags) == 0 && 243 (tunnel->parms.o_flags & ~okflags) == 0 && 244 inherit_ttl && inherit_tos && 245 mlxsw_sp_ipip_tunnel_complete(MLXSW_SP_L3_PROTO_IPV4, ol_dev); 246} 247 248static struct mlxsw_sp_rif_ipip_lb_config 249mlxsw_sp_ipip_ol_loopback_config_gre4(struct mlxsw_sp *mlxsw_sp, 250 const struct net_device *ol_dev) 251{ 252 struct ip_tunnel_parm parms = mlxsw_sp_ipip_netdev_parms4(ol_dev); 253 enum mlxsw_reg_ritr_loopback_ipip_type lb_ipipt; 254 255 lb_ipipt = mlxsw_sp_ipip_parms4_has_okey(parms) ? 256 MLXSW_REG_RITR_LOOPBACK_IPIP_TYPE_IP_IN_GRE_KEY_IN_IP : 257 MLXSW_REG_RITR_LOOPBACK_IPIP_TYPE_IP_IN_GRE_IN_IP; 258 return (struct mlxsw_sp_rif_ipip_lb_config){ 259 .lb_ipipt = lb_ipipt, 260 .okey = mlxsw_sp_ipip_parms4_okey(parms), 261 .ul_protocol = MLXSW_SP_L3_PROTO_IPV4, 262 .saddr = mlxsw_sp_ipip_netdev_saddr(MLXSW_SP_L3_PROTO_IPV4, 263 ol_dev), 264 }; 265} 266 267static int 268mlxsw_sp_ipip_ol_netdev_change_gre4(struct mlxsw_sp *mlxsw_sp, 269 struct mlxsw_sp_ipip_entry *ipip_entry, 270 struct netlink_ext_ack *extack) 271{ 272 union mlxsw_sp_l3addr old_saddr, new_saddr; 273 union mlxsw_sp_l3addr old_daddr, new_daddr; 274 struct ip_tunnel_parm new_parms; 275 bool update_tunnel = false; 276 bool update_decap = false; 277 bool update_nhs = false; 278 int err = 0; 279 280 new_parms = mlxsw_sp_ipip_netdev_parms4(ipip_entry->ol_dev); 281 282 new_saddr = mlxsw_sp_ipip_parms4_saddr(new_parms); 283 old_saddr = mlxsw_sp_ipip_parms4_saddr(ipip_entry->parms4); 284 new_daddr = mlxsw_sp_ipip_parms4_daddr(new_parms); 285 old_daddr = mlxsw_sp_ipip_parms4_daddr(ipip_entry->parms4); 286 287 if (!mlxsw_sp_l3addr_eq(&new_saddr, &old_saddr)) { 288 u16 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(ipip_entry->ol_dev); 289 290 /* Since the local address has changed, if there is another 291 * tunnel with a matching saddr, both need to be demoted. 292 */ 293 if (mlxsw_sp_ipip_demote_tunnel_by_saddr(mlxsw_sp, 294 MLXSW_SP_L3_PROTO_IPV4, 295 new_saddr, ul_tb_id, 296 ipip_entry)) { 297 mlxsw_sp_ipip_entry_demote_tunnel(mlxsw_sp, ipip_entry); 298 return 0; 299 } 300 301 update_tunnel = true; 302 } else if ((mlxsw_sp_ipip_parms4_okey(ipip_entry->parms4) != 303 mlxsw_sp_ipip_parms4_okey(new_parms)) || 304 ipip_entry->parms4.link != new_parms.link) { 305 update_tunnel = true; 306 } else if (!mlxsw_sp_l3addr_eq(&new_daddr, &old_daddr)) { 307 update_nhs = true; 308 } else if (mlxsw_sp_ipip_parms4_ikey(ipip_entry->parms4) != 309 mlxsw_sp_ipip_parms4_ikey(new_parms)) { 310 update_decap = true; 311 } 312 313 if (update_tunnel) 314 err = __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp, ipip_entry, 315 true, true, true, 316 extack); 317 else if (update_nhs) 318 err = __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp, ipip_entry, 319 false, false, true, 320 extack); 321 else if (update_decap) 322 err = __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp, ipip_entry, 323 false, false, false, 324 extack); 325 326 ipip_entry->parms4 = new_parms; 327 return err; 328} 329 330static const struct mlxsw_sp_ipip_ops mlxsw_sp_ipip_gre4_ops = { 331 .dev_type = ARPHRD_IPGRE, 332 .ul_proto = MLXSW_SP_L3_PROTO_IPV4, 333 .nexthop_update = mlxsw_sp_ipip_nexthop_update_gre4, 334 .fib_entry_op = mlxsw_sp_ipip_fib_entry_op_gre4, 335 .can_offload = mlxsw_sp_ipip_can_offload_gre4, 336 .ol_loopback_config = mlxsw_sp_ipip_ol_loopback_config_gre4, 337 .ol_netdev_change = mlxsw_sp_ipip_ol_netdev_change_gre4, 338}; 339 340const struct mlxsw_sp_ipip_ops *mlxsw_sp_ipip_ops_arr[] = { 341 [MLXSW_SP_IPIP_TYPE_GRE4] = &mlxsw_sp_ipip_gre4_ops, 342}; 343 344static int mlxsw_sp_ipip_ecn_encap_init_one(struct mlxsw_sp *mlxsw_sp, 345 u8 inner_ecn, u8 outer_ecn) 346{ 347 char tieem_pl[MLXSW_REG_TIEEM_LEN]; 348 349 mlxsw_reg_tieem_pack(tieem_pl, inner_ecn, outer_ecn); 350 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(tieem), tieem_pl); 351} 352 353int mlxsw_sp_ipip_ecn_encap_init(struct mlxsw_sp *mlxsw_sp) 354{ 355 int i; 356 357 /* Iterate over inner ECN values */ 358 for (i = INET_ECN_NOT_ECT; i <= INET_ECN_CE; i++) { 359 u8 outer_ecn = INET_ECN_encapsulate(0, i); 360 int err; 361 362 err = mlxsw_sp_ipip_ecn_encap_init_one(mlxsw_sp, i, outer_ecn); 363 if (err) 364 return err; 365 } 366 367 return 0; 368} 369 370static int mlxsw_sp_ipip_ecn_decap_init_one(struct mlxsw_sp *mlxsw_sp, 371 u8 inner_ecn, u8 outer_ecn) 372{ 373 char tidem_pl[MLXSW_REG_TIDEM_LEN]; 374 u8 new_inner_ecn; 375 bool trap_en; 376 377 new_inner_ecn = mlxsw_sp_tunnel_ecn_decap(outer_ecn, inner_ecn, 378 &trap_en); 379 mlxsw_reg_tidem_pack(tidem_pl, outer_ecn, inner_ecn, new_inner_ecn, 380 trap_en, trap_en ? MLXSW_TRAP_ID_DECAP_ECN0 : 0); 381 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(tidem), tidem_pl); 382} 383 384int mlxsw_sp_ipip_ecn_decap_init(struct mlxsw_sp *mlxsw_sp) 385{ 386 int i, j, err; 387 388 /* Iterate over inner ECN values */ 389 for (i = INET_ECN_NOT_ECT; i <= INET_ECN_CE; i++) { 390 /* Iterate over outer ECN values */ 391 for (j = INET_ECN_NOT_ECT; j <= INET_ECN_CE; j++) { 392 err = mlxsw_sp_ipip_ecn_decap_init_one(mlxsw_sp, i, j); 393 if (err) 394 return err; 395 } 396 } 397 398 return 0; 399} 400