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 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 mlxsw_sp_ipip_parms4_has_ikey(const struct ip_tunnel_parm *parms) 28 { 29 return !!(parms->i_flags & TUNNEL_KEY); 30 } 31 32 static bool mlxsw_sp_ipip_parms6_has_ikey(const struct __ip6_tnl_parm *parms) 33 { 34 return !!(parms->i_flags & TUNNEL_KEY); 35 } 36 37 static bool mlxsw_sp_ipip_parms4_has_okey(const struct ip_tunnel_parm *parms) 38 { 39 return !!(parms->o_flags & TUNNEL_KEY); 40 } 41 42 static bool mlxsw_sp_ipip_parms6_has_okey(const struct __ip6_tnl_parm *parms) 43 { 44 return !!(parms->o_flags & TUNNEL_KEY); 45 } 46 47 static 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 53 static 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 59 static 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 65 static 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 71 static union mlxsw_sp_l3addr 72 mlxsw_sp_ipip_parms4_saddr(const struct ip_tunnel_parm *parms) 73 { 74 return (union mlxsw_sp_l3addr) { .addr4 = parms->iph.saddr }; 75 } 76 77 static union mlxsw_sp_l3addr 78 mlxsw_sp_ipip_parms6_saddr(const struct __ip6_tnl_parm *parms) 79 { 80 return (union mlxsw_sp_l3addr) { .addr6 = parms->laddr }; 81 } 82 83 static union mlxsw_sp_l3addr 84 mlxsw_sp_ipip_parms4_daddr(const struct ip_tunnel_parm *parms) 85 { 86 return (union mlxsw_sp_l3addr) { .addr4 = parms->iph.daddr }; 87 } 88 89 static union mlxsw_sp_l3addr 90 mlxsw_sp_ipip_parms6_daddr(const struct __ip6_tnl_parm *parms) 91 { 92 return (union mlxsw_sp_l3addr) { .addr6 = parms->raddr }; 93 } 94 95 union mlxsw_sp_l3addr 96 mlxsw_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 115 static __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 123 static union mlxsw_sp_l3addr 124 mlxsw_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 143 bool 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 150 static struct mlxsw_sp_ipip_parms 151 mlxsw_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 165 static int 166 mlxsw_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 183 static int 184 mlxsw_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 222 static 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 237 static 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 251 static struct mlxsw_sp_rif_ipip_lb_config 252 mlxsw_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 270 static int 271 mlxsw_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 326 static int 327 mlxsw_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 338 static int 339 mlxsw_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 345 static void 346 mlxsw_sp_ipip_rem_addr_unset_gre4(struct mlxsw_sp *mlxsw_sp, 347 const struct mlxsw_sp_ipip_entry *ipip_entry) 348 { 349 } 350 351 static 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 365 static struct mlxsw_sp_ipip_parms 366 mlxsw_sp_ipip_netdev_parms_init_gre6(const struct net_device *ol_dev) 367 { 368 struct __ip6_tnl_parm parms = mlxsw_sp_ipip_netdev_parms6(ol_dev); 369 370 return (struct mlxsw_sp_ipip_parms) { 371 .proto = MLXSW_SP_L3_PROTO_IPV6, 372 .saddr = mlxsw_sp_ipip_parms6_saddr(&parms), 373 .daddr = mlxsw_sp_ipip_parms6_daddr(&parms), 374 .link = parms.link, 375 .ikey = mlxsw_sp_ipip_parms6_ikey(&parms), 376 .okey = mlxsw_sp_ipip_parms6_okey(&parms), 377 }; 378 } 379 380 static int 381 mlxsw_sp_ipip_nexthop_update_gre6(struct mlxsw_sp *mlxsw_sp, u32 adj_index, 382 struct mlxsw_sp_ipip_entry *ipip_entry, 383 bool force, char *ratr_pl) 384 { 385 u16 rif_index = mlxsw_sp_ipip_lb_rif_index(ipip_entry->ol_lb); 386 enum mlxsw_reg_ratr_op op; 387 388 op = force ? MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY : 389 MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY_ON_ACTIVITY; 390 mlxsw_reg_ratr_pack(ratr_pl, op, true, MLXSW_REG_RATR_TYPE_IPIP, 391 adj_index, rif_index); 392 mlxsw_reg_ratr_ipip6_entry_pack(ratr_pl, 393 ipip_entry->dip_kvdl_index); 394 395 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ratr), ratr_pl); 396 } 397 398 static int 399 mlxsw_sp_ipip_decap_config_gre6(struct mlxsw_sp *mlxsw_sp, 400 struct mlxsw_sp_ipip_entry *ipip_entry, 401 u32 tunnel_index) 402 { 403 u16 rif_index = mlxsw_sp_ipip_lb_rif_index(ipip_entry->ol_lb); 404 u16 ul_rif_id = mlxsw_sp_ipip_lb_ul_rif_id(ipip_entry->ol_lb); 405 char rtdp_pl[MLXSW_REG_RTDP_LEN]; 406 struct __ip6_tnl_parm parms; 407 unsigned int type_check; 408 bool has_ikey; 409 u32 ikey; 410 411 parms = mlxsw_sp_ipip_netdev_parms6(ipip_entry->ol_dev); 412 has_ikey = mlxsw_sp_ipip_parms6_has_ikey(&parms); 413 ikey = mlxsw_sp_ipip_parms6_ikey(&parms); 414 415 mlxsw_reg_rtdp_pack(rtdp_pl, MLXSW_REG_RTDP_TYPE_IPIP, tunnel_index); 416 mlxsw_reg_rtdp_egress_router_interface_set(rtdp_pl, ul_rif_id); 417 418 type_check = has_ikey ? 419 MLXSW_REG_RTDP_IPIP_TYPE_CHECK_ALLOW_GRE_KEY : 420 MLXSW_REG_RTDP_IPIP_TYPE_CHECK_ALLOW_GRE; 421 422 /* Linux demuxes tunnels based on packet SIP (which must match tunnel 423 * remote IP). Thus configure decap so that it filters out packets that 424 * are not IPv6 or have the wrong SIP. IPIP_DECAP_ERROR trap is 425 * generated for packets that fail this criterion. Linux then handles 426 * such packets in slow path and generates ICMP destination unreachable. 427 */ 428 mlxsw_reg_rtdp_ipip6_pack(rtdp_pl, rif_index, 429 MLXSW_REG_RTDP_IPIP_SIP_CHECK_FILTER_IPV6, 430 type_check, has_ikey, 431 ipip_entry->dip_kvdl_index, ikey); 432 433 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rtdp), rtdp_pl); 434 } 435 436 static bool mlxsw_sp_ipip_can_offload_gre6(const struct mlxsw_sp *mlxsw_sp, 437 const struct net_device *ol_dev) 438 { 439 struct __ip6_tnl_parm tparm = mlxsw_sp_ipip_netdev_parms6(ol_dev); 440 bool inherit_tos = tparm.flags & IP6_TNL_F_USE_ORIG_TCLASS; 441 bool inherit_ttl = tparm.hop_limit == 0; 442 __be16 okflags = TUNNEL_KEY; /* We can't offload any other features. */ 443 444 return (tparm.i_flags & ~okflags) == 0 && 445 (tparm.o_flags & ~okflags) == 0 && 446 inherit_ttl && inherit_tos && 447 mlxsw_sp_ipip_tunnel_complete(MLXSW_SP_L3_PROTO_IPV6, ol_dev); 448 } 449 450 static struct mlxsw_sp_rif_ipip_lb_config 451 mlxsw_sp_ipip_ol_loopback_config_gre6(struct mlxsw_sp *mlxsw_sp, 452 const struct net_device *ol_dev) 453 { 454 struct __ip6_tnl_parm parms = mlxsw_sp_ipip_netdev_parms6(ol_dev); 455 enum mlxsw_reg_ritr_loopback_ipip_type lb_ipipt; 456 457 lb_ipipt = mlxsw_sp_ipip_parms6_has_okey(&parms) ? 458 MLXSW_REG_RITR_LOOPBACK_IPIP_TYPE_IP_IN_GRE_KEY_IN_IP : 459 MLXSW_REG_RITR_LOOPBACK_IPIP_TYPE_IP_IN_GRE_IN_IP; 460 return (struct mlxsw_sp_rif_ipip_lb_config){ 461 .lb_ipipt = lb_ipipt, 462 .okey = mlxsw_sp_ipip_parms6_okey(&parms), 463 .ul_protocol = MLXSW_SP_L3_PROTO_IPV6, 464 .saddr = mlxsw_sp_ipip_netdev_saddr(MLXSW_SP_L3_PROTO_IPV6, 465 ol_dev), 466 }; 467 } 468 469 static int 470 mlxsw_sp_ipip_ol_netdev_change_gre6(struct mlxsw_sp *mlxsw_sp, 471 struct mlxsw_sp_ipip_entry *ipip_entry, 472 struct netlink_ext_ack *extack) 473 { 474 struct mlxsw_sp_ipip_parms new_parms; 475 476 new_parms = mlxsw_sp_ipip_netdev_parms_init_gre6(ipip_entry->ol_dev); 477 return mlxsw_sp_ipip_ol_netdev_change_gre(mlxsw_sp, ipip_entry, 478 &new_parms, extack); 479 } 480 481 static int 482 mlxsw_sp_ipip_rem_addr_set_gre6(struct mlxsw_sp *mlxsw_sp, 483 struct mlxsw_sp_ipip_entry *ipip_entry) 484 { 485 return mlxsw_sp_ipv6_addr_kvdl_index_get(mlxsw_sp, 486 &ipip_entry->parms.daddr.addr6, 487 &ipip_entry->dip_kvdl_index); 488 } 489 490 static void 491 mlxsw_sp_ipip_rem_addr_unset_gre6(struct mlxsw_sp *mlxsw_sp, 492 const struct mlxsw_sp_ipip_entry *ipip_entry) 493 { 494 mlxsw_sp_ipv6_addr_put(mlxsw_sp, &ipip_entry->parms.daddr.addr6); 495 } 496 497 static const struct mlxsw_sp_ipip_ops mlxsw_sp1_ipip_gre6_ops = { 498 .dev_type = ARPHRD_IP6GRE, 499 .ul_proto = MLXSW_SP_L3_PROTO_IPV6, 500 .inc_parsing_depth = true, 501 .double_rif_entry = true, 502 .parms_init = mlxsw_sp_ipip_netdev_parms_init_gre6, 503 .nexthop_update = mlxsw_sp_ipip_nexthop_update_gre6, 504 .decap_config = mlxsw_sp_ipip_decap_config_gre6, 505 .can_offload = mlxsw_sp_ipip_can_offload_gre6, 506 .ol_loopback_config = mlxsw_sp_ipip_ol_loopback_config_gre6, 507 .ol_netdev_change = mlxsw_sp_ipip_ol_netdev_change_gre6, 508 .rem_ip_addr_set = mlxsw_sp_ipip_rem_addr_set_gre6, 509 .rem_ip_addr_unset = mlxsw_sp_ipip_rem_addr_unset_gre6, 510 }; 511 512 const struct mlxsw_sp_ipip_ops *mlxsw_sp1_ipip_ops_arr[] = { 513 [MLXSW_SP_IPIP_TYPE_GRE4] = &mlxsw_sp_ipip_gre4_ops, 514 [MLXSW_SP_IPIP_TYPE_GRE6] = &mlxsw_sp1_ipip_gre6_ops, 515 }; 516 517 static const struct mlxsw_sp_ipip_ops mlxsw_sp2_ipip_gre6_ops = { 518 .dev_type = ARPHRD_IP6GRE, 519 .ul_proto = MLXSW_SP_L3_PROTO_IPV6, 520 .inc_parsing_depth = true, 521 .parms_init = mlxsw_sp_ipip_netdev_parms_init_gre6, 522 .nexthop_update = mlxsw_sp_ipip_nexthop_update_gre6, 523 .decap_config = mlxsw_sp_ipip_decap_config_gre6, 524 .can_offload = mlxsw_sp_ipip_can_offload_gre6, 525 .ol_loopback_config = mlxsw_sp_ipip_ol_loopback_config_gre6, 526 .ol_netdev_change = mlxsw_sp_ipip_ol_netdev_change_gre6, 527 .rem_ip_addr_set = mlxsw_sp_ipip_rem_addr_set_gre6, 528 .rem_ip_addr_unset = mlxsw_sp_ipip_rem_addr_unset_gre6, 529 }; 530 531 const struct mlxsw_sp_ipip_ops *mlxsw_sp2_ipip_ops_arr[] = { 532 [MLXSW_SP_IPIP_TYPE_GRE4] = &mlxsw_sp_ipip_gre4_ops, 533 [MLXSW_SP_IPIP_TYPE_GRE6] = &mlxsw_sp2_ipip_gre6_ops, 534 }; 535 536 static int mlxsw_sp_ipip_ecn_encap_init_one(struct mlxsw_sp *mlxsw_sp, 537 u8 inner_ecn, u8 outer_ecn) 538 { 539 char tieem_pl[MLXSW_REG_TIEEM_LEN]; 540 541 mlxsw_reg_tieem_pack(tieem_pl, inner_ecn, outer_ecn); 542 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(tieem), tieem_pl); 543 } 544 545 int mlxsw_sp_ipip_ecn_encap_init(struct mlxsw_sp *mlxsw_sp) 546 { 547 int i; 548 549 /* Iterate over inner ECN values */ 550 for (i = INET_ECN_NOT_ECT; i <= INET_ECN_CE; i++) { 551 u8 outer_ecn = INET_ECN_encapsulate(0, i); 552 int err; 553 554 err = mlxsw_sp_ipip_ecn_encap_init_one(mlxsw_sp, i, outer_ecn); 555 if (err) 556 return err; 557 } 558 559 return 0; 560 } 561 562 static int mlxsw_sp_ipip_ecn_decap_init_one(struct mlxsw_sp *mlxsw_sp, 563 u8 inner_ecn, u8 outer_ecn) 564 { 565 char tidem_pl[MLXSW_REG_TIDEM_LEN]; 566 u8 new_inner_ecn; 567 bool trap_en; 568 569 new_inner_ecn = mlxsw_sp_tunnel_ecn_decap(outer_ecn, inner_ecn, 570 &trap_en); 571 mlxsw_reg_tidem_pack(tidem_pl, outer_ecn, inner_ecn, new_inner_ecn, 572 trap_en, trap_en ? MLXSW_TRAP_ID_DECAP_ECN0 : 0); 573 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(tidem), tidem_pl); 574 } 575 576 int mlxsw_sp_ipip_ecn_decap_init(struct mlxsw_sp *mlxsw_sp) 577 { 578 int i, j, err; 579 580 /* Iterate over inner ECN values */ 581 for (i = INET_ECN_NOT_ECT; i <= INET_ECN_CE; i++) { 582 /* Iterate over outer ECN values */ 583 for (j = INET_ECN_NOT_ECT; j <= INET_ECN_CE; j++) { 584 err = mlxsw_sp_ipip_ecn_decap_init_one(mlxsw_sp, i, j); 585 if (err) 586 return err; 587 } 588 } 589 590 return 0; 591 } 592 593 struct net_device * 594 mlxsw_sp_ipip_netdev_ul_dev_get(const struct net_device *ol_dev) 595 { 596 struct net *net = dev_net(ol_dev); 597 struct ip_tunnel *tun4; 598 struct ip6_tnl *tun6; 599 600 switch (ol_dev->type) { 601 case ARPHRD_IPGRE: 602 tun4 = netdev_priv(ol_dev); 603 return dev_get_by_index_rcu(net, tun4->parms.link); 604 case ARPHRD_IP6GRE: 605 tun6 = netdev_priv(ol_dev); 606 return dev_get_by_index_rcu(net, tun6->parms.link); 607 default: 608 return NULL; 609 } 610 } 611