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}