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