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 struct mlxsw_sp_ipip_parms new_parms; 485 486 new_parms = mlxsw_sp_ipip_netdev_parms_init_gre6(ipip_entry->ol_dev); 487 return mlxsw_sp_ipip_ol_netdev_change_gre(mlxsw_sp, ipip_entry, 488 &new_parms, extack); 489 } 490 491 static int 492 mlxsw_sp_ipip_rem_addr_set_gre6(struct mlxsw_sp *mlxsw_sp, 493 struct mlxsw_sp_ipip_entry *ipip_entry) 494 { 495 return mlxsw_sp_ipv6_addr_kvdl_index_get(mlxsw_sp, 496 &ipip_entry->parms.daddr.addr6, 497 &ipip_entry->dip_kvdl_index); 498 } 499 500 static void 501 mlxsw_sp_ipip_rem_addr_unset_gre6(struct mlxsw_sp *mlxsw_sp, 502 const struct mlxsw_sp_ipip_entry *ipip_entry) 503 { 504 mlxsw_sp_ipv6_addr_put(mlxsw_sp, &ipip_entry->parms.daddr.addr6); 505 } 506 507 static const struct mlxsw_sp_ipip_ops mlxsw_sp1_ipip_gre6_ops = { 508 .dev_type = ARPHRD_IP6GRE, 509 .ul_proto = MLXSW_SP_L3_PROTO_IPV6, 510 .inc_parsing_depth = true, 511 .double_rif_entry = true, 512 .parms_init = mlxsw_sp_ipip_netdev_parms_init_gre6, 513 .nexthop_update = mlxsw_sp_ipip_nexthop_update_gre6, 514 .decap_config = mlxsw_sp_ipip_decap_config_gre6, 515 .can_offload = mlxsw_sp_ipip_can_offload_gre6, 516 .ol_loopback_config = mlxsw_sp_ipip_ol_loopback_config_gre6, 517 .ol_netdev_change = mlxsw_sp_ipip_ol_netdev_change_gre6, 518 .rem_ip_addr_set = mlxsw_sp_ipip_rem_addr_set_gre6, 519 .rem_ip_addr_unset = mlxsw_sp_ipip_rem_addr_unset_gre6, 520 }; 521 522 const struct mlxsw_sp_ipip_ops *mlxsw_sp1_ipip_ops_arr[] = { 523 [MLXSW_SP_IPIP_TYPE_GRE4] = &mlxsw_sp_ipip_gre4_ops, 524 [MLXSW_SP_IPIP_TYPE_GRE6] = &mlxsw_sp1_ipip_gre6_ops, 525 }; 526 527 static const struct mlxsw_sp_ipip_ops mlxsw_sp2_ipip_gre6_ops = { 528 .dev_type = ARPHRD_IP6GRE, 529 .ul_proto = MLXSW_SP_L3_PROTO_IPV6, 530 .inc_parsing_depth = true, 531 .parms_init = mlxsw_sp_ipip_netdev_parms_init_gre6, 532 .nexthop_update = mlxsw_sp_ipip_nexthop_update_gre6, 533 .decap_config = mlxsw_sp_ipip_decap_config_gre6, 534 .can_offload = mlxsw_sp_ipip_can_offload_gre6, 535 .ol_loopback_config = mlxsw_sp_ipip_ol_loopback_config_gre6, 536 .ol_netdev_change = mlxsw_sp_ipip_ol_netdev_change_gre6, 537 .rem_ip_addr_set = mlxsw_sp_ipip_rem_addr_set_gre6, 538 .rem_ip_addr_unset = mlxsw_sp_ipip_rem_addr_unset_gre6, 539 }; 540 541 const struct mlxsw_sp_ipip_ops *mlxsw_sp2_ipip_ops_arr[] = { 542 [MLXSW_SP_IPIP_TYPE_GRE4] = &mlxsw_sp_ipip_gre4_ops, 543 [MLXSW_SP_IPIP_TYPE_GRE6] = &mlxsw_sp2_ipip_gre6_ops, 544 }; 545 546 static int mlxsw_sp_ipip_ecn_encap_init_one(struct mlxsw_sp *mlxsw_sp, 547 u8 inner_ecn, u8 outer_ecn) 548 { 549 char tieem_pl[MLXSW_REG_TIEEM_LEN]; 550 551 mlxsw_reg_tieem_pack(tieem_pl, inner_ecn, outer_ecn); 552 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(tieem), tieem_pl); 553 } 554 555 int mlxsw_sp_ipip_ecn_encap_init(struct mlxsw_sp *mlxsw_sp) 556 { 557 int i; 558 559 /* Iterate over inner ECN values */ 560 for (i = INET_ECN_NOT_ECT; i <= INET_ECN_CE; i++) { 561 u8 outer_ecn = INET_ECN_encapsulate(0, i); 562 int err; 563 564 err = mlxsw_sp_ipip_ecn_encap_init_one(mlxsw_sp, i, outer_ecn); 565 if (err) 566 return err; 567 } 568 569 return 0; 570 } 571 572 static int mlxsw_sp_ipip_ecn_decap_init_one(struct mlxsw_sp *mlxsw_sp, 573 u8 inner_ecn, u8 outer_ecn) 574 { 575 char tidem_pl[MLXSW_REG_TIDEM_LEN]; 576 u8 new_inner_ecn; 577 bool trap_en; 578 579 new_inner_ecn = mlxsw_sp_tunnel_ecn_decap(outer_ecn, inner_ecn, 580 &trap_en); 581 mlxsw_reg_tidem_pack(tidem_pl, outer_ecn, inner_ecn, new_inner_ecn, 582 trap_en, trap_en ? MLXSW_TRAP_ID_DECAP_ECN0 : 0); 583 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(tidem), tidem_pl); 584 } 585 586 int mlxsw_sp_ipip_ecn_decap_init(struct mlxsw_sp *mlxsw_sp) 587 { 588 int i, j, err; 589 590 /* Iterate over inner ECN values */ 591 for (i = INET_ECN_NOT_ECT; i <= INET_ECN_CE; i++) { 592 /* Iterate over outer ECN values */ 593 for (j = INET_ECN_NOT_ECT; j <= INET_ECN_CE; j++) { 594 err = mlxsw_sp_ipip_ecn_decap_init_one(mlxsw_sp, i, j); 595 if (err) 596 return err; 597 } 598 } 599 600 return 0; 601 } 602 603 struct net_device * 604 mlxsw_sp_ipip_netdev_ul_dev_get(const struct net_device *ol_dev) 605 { 606 struct net *net = dev_net(ol_dev); 607 struct ip_tunnel *tun4; 608 struct ip6_tnl *tun6; 609 610 switch (ol_dev->type) { 611 case ARPHRD_IPGRE: 612 tun4 = netdev_priv(ol_dev); 613 return dev_get_by_index_rcu(net, tun4->parms.link); 614 case ARPHRD_IP6GRE: 615 tun6 = netdev_priv(ol_dev); 616 return dev_get_by_index_rcu(net, tun6->parms.link); 617 default: 618 return NULL; 619 } 620 } 621