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(struct ip_tunnel_parm parms) 28 { 29 return !!(parms.i_flags & TUNNEL_KEY); 30 } 31 32 static bool mlxsw_sp_ipip_parms4_has_okey(struct ip_tunnel_parm parms) 33 { 34 return !!(parms.o_flags & TUNNEL_KEY); 35 } 36 37 static u32 mlxsw_sp_ipip_parms4_ikey(struct ip_tunnel_parm parms) 38 { 39 return mlxsw_sp_ipip_parms4_has_ikey(parms) ? 40 be32_to_cpu(parms.i_key) : 0; 41 } 42 43 static u32 mlxsw_sp_ipip_parms4_okey(struct ip_tunnel_parm parms) 44 { 45 return mlxsw_sp_ipip_parms4_has_okey(parms) ? 46 be32_to_cpu(parms.o_key) : 0; 47 } 48 49 static union mlxsw_sp_l3addr 50 mlxsw_sp_ipip_parms4_saddr(struct ip_tunnel_parm parms) 51 { 52 return (union mlxsw_sp_l3addr) { .addr4 = parms.iph.saddr }; 53 } 54 55 static union mlxsw_sp_l3addr 56 mlxsw_sp_ipip_parms6_saddr(struct __ip6_tnl_parm parms) 57 { 58 return (union mlxsw_sp_l3addr) { .addr6 = parms.laddr }; 59 } 60 61 static union mlxsw_sp_l3addr 62 mlxsw_sp_ipip_parms4_daddr(struct ip_tunnel_parm parms) 63 { 64 return (union mlxsw_sp_l3addr) { .addr4 = parms.iph.daddr }; 65 } 66 67 static union mlxsw_sp_l3addr 68 mlxsw_sp_ipip_parms6_daddr(struct __ip6_tnl_parm parms) 69 { 70 return (union mlxsw_sp_l3addr) { .addr6 = parms.raddr }; 71 } 72 73 union mlxsw_sp_l3addr 74 mlxsw_sp_ipip_netdev_saddr(enum mlxsw_sp_l3proto proto, 75 const struct net_device *ol_dev) 76 { 77 struct ip_tunnel_parm parms4; 78 struct __ip6_tnl_parm parms6; 79 80 switch (proto) { 81 case MLXSW_SP_L3_PROTO_IPV4: 82 parms4 = mlxsw_sp_ipip_netdev_parms4(ol_dev); 83 return mlxsw_sp_ipip_parms4_saddr(parms4); 84 case MLXSW_SP_L3_PROTO_IPV6: 85 parms6 = mlxsw_sp_ipip_netdev_parms6(ol_dev); 86 return mlxsw_sp_ipip_parms6_saddr(parms6); 87 } 88 89 WARN_ON(1); 90 return (union mlxsw_sp_l3addr) {0}; 91 } 92 93 static __be32 mlxsw_sp_ipip_netdev_daddr4(const struct net_device *ol_dev) 94 { 95 96 struct ip_tunnel_parm parms4 = mlxsw_sp_ipip_netdev_parms4(ol_dev); 97 98 return mlxsw_sp_ipip_parms4_daddr(parms4).addr4; 99 } 100 101 static union mlxsw_sp_l3addr 102 mlxsw_sp_ipip_netdev_daddr(enum mlxsw_sp_l3proto proto, 103 const struct net_device *ol_dev) 104 { 105 struct ip_tunnel_parm parms4; 106 struct __ip6_tnl_parm parms6; 107 108 switch (proto) { 109 case MLXSW_SP_L3_PROTO_IPV4: 110 parms4 = mlxsw_sp_ipip_netdev_parms4(ol_dev); 111 return mlxsw_sp_ipip_parms4_daddr(parms4); 112 case MLXSW_SP_L3_PROTO_IPV6: 113 parms6 = mlxsw_sp_ipip_netdev_parms6(ol_dev); 114 return mlxsw_sp_ipip_parms6_daddr(parms6); 115 } 116 117 WARN_ON(1); 118 return (union mlxsw_sp_l3addr) {0}; 119 } 120 121 bool mlxsw_sp_l3addr_is_zero(union mlxsw_sp_l3addr addr) 122 { 123 union mlxsw_sp_l3addr naddr = {0}; 124 125 return !memcmp(&addr, &naddr, sizeof(naddr)); 126 } 127 128 static int 129 mlxsw_sp_ipip_nexthop_update_gre4(struct mlxsw_sp *mlxsw_sp, u32 adj_index, 130 struct mlxsw_sp_ipip_entry *ipip_entry) 131 { 132 u16 rif_index = mlxsw_sp_ipip_lb_rif_index(ipip_entry->ol_lb); 133 __be32 daddr4 = mlxsw_sp_ipip_netdev_daddr4(ipip_entry->ol_dev); 134 char ratr_pl[MLXSW_REG_RATR_LEN]; 135 136 mlxsw_reg_ratr_pack(ratr_pl, MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY, 137 true, MLXSW_REG_RATR_TYPE_IPIP, 138 adj_index, rif_index); 139 mlxsw_reg_ratr_ipip4_entry_pack(ratr_pl, be32_to_cpu(daddr4)); 140 141 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ratr), ratr_pl); 142 } 143 144 static int 145 mlxsw_sp_ipip_fib_entry_op_gre4_rtdp(struct mlxsw_sp *mlxsw_sp, 146 u32 tunnel_index, 147 struct mlxsw_sp_ipip_entry *ipip_entry) 148 { 149 u16 rif_index = mlxsw_sp_ipip_lb_rif_index(ipip_entry->ol_lb); 150 u16 ul_rif_id = mlxsw_sp_ipip_lb_ul_rif_id(ipip_entry->ol_lb); 151 char rtdp_pl[MLXSW_REG_RTDP_LEN]; 152 struct ip_tunnel_parm parms; 153 unsigned int type_check; 154 bool has_ikey; 155 u32 daddr4; 156 u32 ikey; 157 158 parms = mlxsw_sp_ipip_netdev_parms4(ipip_entry->ol_dev); 159 has_ikey = mlxsw_sp_ipip_parms4_has_ikey(parms); 160 ikey = mlxsw_sp_ipip_parms4_ikey(parms); 161 162 mlxsw_reg_rtdp_pack(rtdp_pl, MLXSW_REG_RTDP_TYPE_IPIP, tunnel_index); 163 mlxsw_reg_rtdp_egress_router_interface_set(rtdp_pl, ul_rif_id); 164 165 type_check = has_ikey ? 166 MLXSW_REG_RTDP_IPIP_TYPE_CHECK_ALLOW_GRE_KEY : 167 MLXSW_REG_RTDP_IPIP_TYPE_CHECK_ALLOW_GRE; 168 169 /* Linux demuxes tunnels based on packet SIP (which must match tunnel 170 * remote IP). Thus configure decap so that it filters out packets that 171 * are not IPv4 or have the wrong SIP. IPIP_DECAP_ERROR trap is 172 * generated for packets that fail this criterion. Linux then handles 173 * such packets in slow path and generates ICMP destination unreachable. 174 */ 175 daddr4 = be32_to_cpu(mlxsw_sp_ipip_netdev_daddr4(ipip_entry->ol_dev)); 176 mlxsw_reg_rtdp_ipip4_pack(rtdp_pl, rif_index, 177 MLXSW_REG_RTDP_IPIP_SIP_CHECK_FILTER_IPV4, 178 type_check, has_ikey, daddr4, ikey); 179 180 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rtdp), rtdp_pl); 181 } 182 183 static int 184 mlxsw_sp_ipip_fib_entry_op_gre4_ralue(struct mlxsw_sp *mlxsw_sp, 185 u32 dip, u8 prefix_len, u16 ul_vr_id, 186 enum mlxsw_reg_ralue_op op, 187 u32 tunnel_index) 188 { 189 char ralue_pl[MLXSW_REG_RALUE_LEN]; 190 191 mlxsw_reg_ralue_pack4(ralue_pl, MLXSW_REG_RALXX_PROTOCOL_IPV4, op, 192 ul_vr_id, prefix_len, dip); 193 mlxsw_reg_ralue_act_ip2me_tun_pack(ralue_pl, tunnel_index); 194 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ralue), ralue_pl); 195 } 196 197 static int mlxsw_sp_ipip_fib_entry_op_gre4(struct mlxsw_sp *mlxsw_sp, 198 struct mlxsw_sp_ipip_entry *ipip_entry, 199 enum mlxsw_reg_ralue_op op, 200 u32 tunnel_index) 201 { 202 u16 ul_vr_id = mlxsw_sp_ipip_lb_ul_vr_id(ipip_entry->ol_lb); 203 __be32 dip; 204 int err; 205 206 err = mlxsw_sp_ipip_fib_entry_op_gre4_rtdp(mlxsw_sp, tunnel_index, 207 ipip_entry); 208 if (err) 209 return err; 210 211 dip = mlxsw_sp_ipip_netdev_saddr(MLXSW_SP_L3_PROTO_IPV4, 212 ipip_entry->ol_dev).addr4; 213 return mlxsw_sp_ipip_fib_entry_op_gre4_ralue(mlxsw_sp, be32_to_cpu(dip), 214 32, ul_vr_id, op, 215 tunnel_index); 216 } 217 218 static bool mlxsw_sp_ipip_tunnel_complete(enum mlxsw_sp_l3proto proto, 219 const struct net_device *ol_dev) 220 { 221 union mlxsw_sp_l3addr saddr = mlxsw_sp_ipip_netdev_saddr(proto, ol_dev); 222 union mlxsw_sp_l3addr daddr = mlxsw_sp_ipip_netdev_daddr(proto, ol_dev); 223 224 /* Tunnels with unset local or remote address are valid in Linux and 225 * used for lightweight tunnels (LWT) and Non-Broadcast Multi-Access 226 * (NBMA) tunnels. In principle these can be offloaded, but the driver 227 * currently doesn't support this. So punt. 228 */ 229 return !mlxsw_sp_l3addr_is_zero(saddr) && 230 !mlxsw_sp_l3addr_is_zero(daddr); 231 } 232 233 static bool mlxsw_sp_ipip_can_offload_gre4(const struct mlxsw_sp *mlxsw_sp, 234 const struct net_device *ol_dev, 235 enum mlxsw_sp_l3proto ol_proto) 236 { 237 struct ip_tunnel *tunnel = netdev_priv(ol_dev); 238 __be16 okflags = TUNNEL_KEY; /* We can't offload any other features. */ 239 bool inherit_ttl = tunnel->parms.iph.ttl == 0; 240 bool inherit_tos = tunnel->parms.iph.tos & 0x1; 241 242 return (tunnel->parms.i_flags & ~okflags) == 0 && 243 (tunnel->parms.o_flags & ~okflags) == 0 && 244 inherit_ttl && inherit_tos && 245 mlxsw_sp_ipip_tunnel_complete(MLXSW_SP_L3_PROTO_IPV4, ol_dev); 246 } 247 248 static struct mlxsw_sp_rif_ipip_lb_config 249 mlxsw_sp_ipip_ol_loopback_config_gre4(struct mlxsw_sp *mlxsw_sp, 250 const struct net_device *ol_dev) 251 { 252 struct ip_tunnel_parm parms = mlxsw_sp_ipip_netdev_parms4(ol_dev); 253 enum mlxsw_reg_ritr_loopback_ipip_type lb_ipipt; 254 255 lb_ipipt = mlxsw_sp_ipip_parms4_has_okey(parms) ? 256 MLXSW_REG_RITR_LOOPBACK_IPIP_TYPE_IP_IN_GRE_KEY_IN_IP : 257 MLXSW_REG_RITR_LOOPBACK_IPIP_TYPE_IP_IN_GRE_IN_IP; 258 return (struct mlxsw_sp_rif_ipip_lb_config){ 259 .lb_ipipt = lb_ipipt, 260 .okey = mlxsw_sp_ipip_parms4_okey(parms), 261 .ul_protocol = MLXSW_SP_L3_PROTO_IPV4, 262 .saddr = mlxsw_sp_ipip_netdev_saddr(MLXSW_SP_L3_PROTO_IPV4, 263 ol_dev), 264 }; 265 } 266 267 static int 268 mlxsw_sp_ipip_ol_netdev_change_gre4(struct mlxsw_sp *mlxsw_sp, 269 struct mlxsw_sp_ipip_entry *ipip_entry, 270 struct netlink_ext_ack *extack) 271 { 272 union mlxsw_sp_l3addr old_saddr, new_saddr; 273 union mlxsw_sp_l3addr old_daddr, new_daddr; 274 struct ip_tunnel_parm new_parms; 275 bool update_tunnel = false; 276 bool update_decap = false; 277 bool update_nhs = false; 278 int err = 0; 279 280 new_parms = mlxsw_sp_ipip_netdev_parms4(ipip_entry->ol_dev); 281 282 new_saddr = mlxsw_sp_ipip_parms4_saddr(new_parms); 283 old_saddr = mlxsw_sp_ipip_parms4_saddr(ipip_entry->parms4); 284 new_daddr = mlxsw_sp_ipip_parms4_daddr(new_parms); 285 old_daddr = mlxsw_sp_ipip_parms4_daddr(ipip_entry->parms4); 286 287 if (!mlxsw_sp_l3addr_eq(&new_saddr, &old_saddr)) { 288 u16 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(ipip_entry->ol_dev); 289 290 /* Since the local address has changed, if there is another 291 * tunnel with a matching saddr, both need to be demoted. 292 */ 293 if (mlxsw_sp_ipip_demote_tunnel_by_saddr(mlxsw_sp, 294 MLXSW_SP_L3_PROTO_IPV4, 295 new_saddr, ul_tb_id, 296 ipip_entry)) { 297 mlxsw_sp_ipip_entry_demote_tunnel(mlxsw_sp, ipip_entry); 298 return 0; 299 } 300 301 update_tunnel = true; 302 } else if ((mlxsw_sp_ipip_parms4_okey(ipip_entry->parms4) != 303 mlxsw_sp_ipip_parms4_okey(new_parms)) || 304 ipip_entry->parms4.link != new_parms.link) { 305 update_tunnel = true; 306 } else if (!mlxsw_sp_l3addr_eq(&new_daddr, &old_daddr)) { 307 update_nhs = true; 308 } else if (mlxsw_sp_ipip_parms4_ikey(ipip_entry->parms4) != 309 mlxsw_sp_ipip_parms4_ikey(new_parms)) { 310 update_decap = true; 311 } 312 313 if (update_tunnel) 314 err = __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp, ipip_entry, 315 true, true, true, 316 extack); 317 else if (update_nhs) 318 err = __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp, ipip_entry, 319 false, false, true, 320 extack); 321 else if (update_decap) 322 err = __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp, ipip_entry, 323 false, false, false, 324 extack); 325 326 ipip_entry->parms4 = new_parms; 327 return err; 328 } 329 330 static const struct mlxsw_sp_ipip_ops mlxsw_sp_ipip_gre4_ops = { 331 .dev_type = ARPHRD_IPGRE, 332 .ul_proto = MLXSW_SP_L3_PROTO_IPV4, 333 .nexthop_update = mlxsw_sp_ipip_nexthop_update_gre4, 334 .fib_entry_op = mlxsw_sp_ipip_fib_entry_op_gre4, 335 .can_offload = mlxsw_sp_ipip_can_offload_gre4, 336 .ol_loopback_config = mlxsw_sp_ipip_ol_loopback_config_gre4, 337 .ol_netdev_change = mlxsw_sp_ipip_ol_netdev_change_gre4, 338 }; 339 340 const struct mlxsw_sp_ipip_ops *mlxsw_sp_ipip_ops_arr[] = { 341 [MLXSW_SP_IPIP_TYPE_GRE4] = &mlxsw_sp_ipip_gre4_ops, 342 }; 343 344 static int mlxsw_sp_ipip_ecn_encap_init_one(struct mlxsw_sp *mlxsw_sp, 345 u8 inner_ecn, u8 outer_ecn) 346 { 347 char tieem_pl[MLXSW_REG_TIEEM_LEN]; 348 349 mlxsw_reg_tieem_pack(tieem_pl, inner_ecn, outer_ecn); 350 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(tieem), tieem_pl); 351 } 352 353 int mlxsw_sp_ipip_ecn_encap_init(struct mlxsw_sp *mlxsw_sp) 354 { 355 int i; 356 357 /* Iterate over inner ECN values */ 358 for (i = INET_ECN_NOT_ECT; i <= INET_ECN_CE; i++) { 359 u8 outer_ecn = INET_ECN_encapsulate(0, i); 360 int err; 361 362 err = mlxsw_sp_ipip_ecn_encap_init_one(mlxsw_sp, i, outer_ecn); 363 if (err) 364 return err; 365 } 366 367 return 0; 368 } 369 370 static int mlxsw_sp_ipip_ecn_decap_init_one(struct mlxsw_sp *mlxsw_sp, 371 u8 inner_ecn, u8 outer_ecn) 372 { 373 char tidem_pl[MLXSW_REG_TIDEM_LEN]; 374 bool trap_en, set_ce = false; 375 u8 new_inner_ecn; 376 377 trap_en = __INET_ECN_decapsulate(outer_ecn, inner_ecn, &set_ce); 378 new_inner_ecn = set_ce ? INET_ECN_CE : inner_ecn; 379 380 mlxsw_reg_tidem_pack(tidem_pl, outer_ecn, inner_ecn, new_inner_ecn, 381 trap_en, trap_en ? MLXSW_TRAP_ID_DECAP_ECN0 : 0); 382 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(tidem), tidem_pl); 383 } 384 385 int mlxsw_sp_ipip_ecn_decap_init(struct mlxsw_sp *mlxsw_sp) 386 { 387 int i, j, err; 388 389 /* Iterate over inner ECN values */ 390 for (i = INET_ECN_NOT_ECT; i <= INET_ECN_CE; i++) { 391 /* Iterate over outer ECN values */ 392 for (j = INET_ECN_NOT_ECT; j <= INET_ECN_CE; j++) { 393 err = mlxsw_sp_ipip_ecn_decap_init_one(mlxsw_sp, i, j); 394 if (err) 395 return err; 396 } 397 } 398 399 return 0; 400 } 401