FILE
spectrum_ipip.c
File preview with syntax highlighting.
linux-6.19.14/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.c
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_kern 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 28mlxsw_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 33static 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 38static bool 39mlxsw_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 44static 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 49static 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 55static 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 61static 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 67static 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 73static union mlxsw_sp_l3addr 74mlxsw_sp_ipip_parms4_saddr(const struct ip_tunnel_parm_kern *parms) 75{ 76 return (union mlxsw_sp_l3addr) { .addr4 = parms->iph.saddr }; 77} 78 79static union mlxsw_sp_l3addr 80mlxsw_sp_ipip_parms6_saddr(const struct __ip6_tnl_parm *parms) 81{ 82 return (union mlxsw_sp_l3addr) { .addr6 = parms->laddr }; 83} 84 85static union mlxsw_sp_l3addr 86mlxsw_sp_ipip_parms4_daddr(const struct ip_tunnel_parm_kern *parms) 87{ 88 return (union mlxsw_sp_l3addr) { .addr4 = parms->iph.daddr }; 89} 90 91static union mlxsw_sp_l3addr 92mlxsw_sp_ipip_parms6_daddr(const struct __ip6_tnl_parm *parms) 93{ 94 return (union mlxsw_sp_l3addr) { .addr6 = parms->raddr }; 95} 96 97union mlxsw_sp_l3addr 98mlxsw_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 117static __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 127static union mlxsw_sp_l3addr 128mlxsw_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 147bool 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 154static struct mlxsw_sp_ipip_parms 155mlxsw_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 169static int 170mlxsw_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 187static int 188mlxsw_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 226static 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 241static 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 258static struct mlxsw_sp_rif_ipip_lb_config 259mlxsw_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 277static int 278mlxsw_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 333static int 334mlxsw_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 345static int 346mlxsw_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 352static void 353mlxsw_sp_ipip_rem_addr_unset_gre4(struct mlxsw_sp *mlxsw_sp, 354 const struct mlxsw_sp_ipip_entry *ipip_entry) 355{ 356} 357 358static 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 372static struct mlxsw_sp_ipip_parms 373mlxsw_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 387static int 388mlxsw_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 405static int 406mlxsw_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 443static 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 460static struct mlxsw_sp_rif_ipip_lb_config 461mlxsw_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 479static int 480mlxsw_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 507err_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 513static int 514mlxsw_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 522static void 523mlxsw_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 529static 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 544const 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 549static 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 563const 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 568static 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 577int 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 594static 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 608int 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 625struct net_device * 626mlxsw_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}
~/
Read-only file preview.