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 bool force, char *ratr_pl) 132 { 133 u16 rif_index = mlxsw_sp_ipip_lb_rif_index(ipip_entry->ol_lb); 134 __be32 daddr4 = mlxsw_sp_ipip_netdev_daddr4(ipip_entry->ol_dev); 135 enum mlxsw_reg_ratr_op op; 136 137 op = force ? MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY : 138 MLXSW_REG_RATR_OP_WRITE_WRITE_ENTRY_ON_ACTIVITY; 139 mlxsw_reg_ratr_pack(ratr_pl, op, true, MLXSW_REG_RATR_TYPE_IPIP, 140 adj_index, rif_index); 141 mlxsw_reg_ratr_ipip4_entry_pack(ratr_pl, be32_to_cpu(daddr4)); 142 143 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ratr), ratr_pl); 144 } 145 146 static int 147 mlxsw_sp_ipip_decap_config_gre4(struct mlxsw_sp *mlxsw_sp, 148 struct mlxsw_sp_ipip_entry *ipip_entry, 149 u32 tunnel_index) 150 { 151 u16 rif_index = mlxsw_sp_ipip_lb_rif_index(ipip_entry->ol_lb); 152 u16 ul_rif_id = mlxsw_sp_ipip_lb_ul_rif_id(ipip_entry->ol_lb); 153 char rtdp_pl[MLXSW_REG_RTDP_LEN]; 154 struct ip_tunnel_parm parms; 155 unsigned int type_check; 156 bool has_ikey; 157 u32 daddr4; 158 u32 ikey; 159 160 parms = mlxsw_sp_ipip_netdev_parms4(ipip_entry->ol_dev); 161 has_ikey = mlxsw_sp_ipip_parms4_has_ikey(parms); 162 ikey = mlxsw_sp_ipip_parms4_ikey(parms); 163 164 mlxsw_reg_rtdp_pack(rtdp_pl, MLXSW_REG_RTDP_TYPE_IPIP, tunnel_index); 165 mlxsw_reg_rtdp_egress_router_interface_set(rtdp_pl, ul_rif_id); 166 167 type_check = has_ikey ? 168 MLXSW_REG_RTDP_IPIP_TYPE_CHECK_ALLOW_GRE_KEY : 169 MLXSW_REG_RTDP_IPIP_TYPE_CHECK_ALLOW_GRE; 170 171 /* Linux demuxes tunnels based on packet SIP (which must match tunnel 172 * remote IP). Thus configure decap so that it filters out packets that 173 * are not IPv4 or have the wrong SIP. IPIP_DECAP_ERROR trap is 174 * generated for packets that fail this criterion. Linux then handles 175 * such packets in slow path and generates ICMP destination unreachable. 176 */ 177 daddr4 = be32_to_cpu(mlxsw_sp_ipip_netdev_daddr4(ipip_entry->ol_dev)); 178 mlxsw_reg_rtdp_ipip4_pack(rtdp_pl, rif_index, 179 MLXSW_REG_RTDP_IPIP_SIP_CHECK_FILTER_IPV4, 180 type_check, has_ikey, daddr4, ikey); 181 182 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rtdp), rtdp_pl); 183 } 184 185 static bool mlxsw_sp_ipip_tunnel_complete(enum mlxsw_sp_l3proto proto, 186 const struct net_device *ol_dev) 187 { 188 union mlxsw_sp_l3addr saddr = mlxsw_sp_ipip_netdev_saddr(proto, ol_dev); 189 union mlxsw_sp_l3addr daddr = mlxsw_sp_ipip_netdev_daddr(proto, ol_dev); 190 191 /* Tunnels with unset local or remote address are valid in Linux and 192 * used for lightweight tunnels (LWT) and Non-Broadcast Multi-Access 193 * (NBMA) tunnels. In principle these can be offloaded, but the driver 194 * currently doesn't support this. So punt. 195 */ 196 return !mlxsw_sp_l3addr_is_zero(saddr) && 197 !mlxsw_sp_l3addr_is_zero(daddr); 198 } 199 200 static bool mlxsw_sp_ipip_can_offload_gre4(const struct mlxsw_sp *mlxsw_sp, 201 const struct net_device *ol_dev) 202 { 203 struct ip_tunnel *tunnel = netdev_priv(ol_dev); 204 __be16 okflags = TUNNEL_KEY; /* We can't offload any other features. */ 205 bool inherit_ttl = tunnel->parms.iph.ttl == 0; 206 bool inherit_tos = tunnel->parms.iph.tos & 0x1; 207 208 return (tunnel->parms.i_flags & ~okflags) == 0 && 209 (tunnel->parms.o_flags & ~okflags) == 0 && 210 inherit_ttl && inherit_tos && 211 mlxsw_sp_ipip_tunnel_complete(MLXSW_SP_L3_PROTO_IPV4, ol_dev); 212 } 213 214 static struct mlxsw_sp_rif_ipip_lb_config 215 mlxsw_sp_ipip_ol_loopback_config_gre4(struct mlxsw_sp *mlxsw_sp, 216 const struct net_device *ol_dev) 217 { 218 struct ip_tunnel_parm parms = mlxsw_sp_ipip_netdev_parms4(ol_dev); 219 enum mlxsw_reg_ritr_loopback_ipip_type lb_ipipt; 220 221 lb_ipipt = mlxsw_sp_ipip_parms4_has_okey(parms) ? 222 MLXSW_REG_RITR_LOOPBACK_IPIP_TYPE_IP_IN_GRE_KEY_IN_IP : 223 MLXSW_REG_RITR_LOOPBACK_IPIP_TYPE_IP_IN_GRE_IN_IP; 224 return (struct mlxsw_sp_rif_ipip_lb_config){ 225 .lb_ipipt = lb_ipipt, 226 .okey = mlxsw_sp_ipip_parms4_okey(parms), 227 .ul_protocol = MLXSW_SP_L3_PROTO_IPV4, 228 .saddr = mlxsw_sp_ipip_netdev_saddr(MLXSW_SP_L3_PROTO_IPV4, 229 ol_dev), 230 }; 231 } 232 233 static int 234 mlxsw_sp_ipip_ol_netdev_change_gre4(struct mlxsw_sp *mlxsw_sp, 235 struct mlxsw_sp_ipip_entry *ipip_entry, 236 struct netlink_ext_ack *extack) 237 { 238 union mlxsw_sp_l3addr old_saddr, new_saddr; 239 union mlxsw_sp_l3addr old_daddr, new_daddr; 240 struct ip_tunnel_parm new_parms; 241 bool update_tunnel = false; 242 bool update_decap = false; 243 bool update_nhs = false; 244 int err = 0; 245 246 new_parms = mlxsw_sp_ipip_netdev_parms4(ipip_entry->ol_dev); 247 248 new_saddr = mlxsw_sp_ipip_parms4_saddr(new_parms); 249 old_saddr = mlxsw_sp_ipip_parms4_saddr(ipip_entry->parms4); 250 new_daddr = mlxsw_sp_ipip_parms4_daddr(new_parms); 251 old_daddr = mlxsw_sp_ipip_parms4_daddr(ipip_entry->parms4); 252 253 if (!mlxsw_sp_l3addr_eq(&new_saddr, &old_saddr)) { 254 u16 ul_tb_id = mlxsw_sp_ipip_dev_ul_tb_id(ipip_entry->ol_dev); 255 256 /* Since the local address has changed, if there is another 257 * tunnel with a matching saddr, both need to be demoted. 258 */ 259 if (mlxsw_sp_ipip_demote_tunnel_by_saddr(mlxsw_sp, 260 MLXSW_SP_L3_PROTO_IPV4, 261 new_saddr, ul_tb_id, 262 ipip_entry)) { 263 mlxsw_sp_ipip_entry_demote_tunnel(mlxsw_sp, ipip_entry); 264 return 0; 265 } 266 267 update_tunnel = true; 268 } else if ((mlxsw_sp_ipip_parms4_okey(ipip_entry->parms4) != 269 mlxsw_sp_ipip_parms4_okey(new_parms)) || 270 ipip_entry->parms4.link != new_parms.link) { 271 update_tunnel = true; 272 } else if (!mlxsw_sp_l3addr_eq(&new_daddr, &old_daddr)) { 273 update_nhs = true; 274 } else if (mlxsw_sp_ipip_parms4_ikey(ipip_entry->parms4) != 275 mlxsw_sp_ipip_parms4_ikey(new_parms)) { 276 update_decap = true; 277 } 278 279 if (update_tunnel) 280 err = __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp, ipip_entry, 281 true, true, true, 282 extack); 283 else if (update_nhs) 284 err = __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp, ipip_entry, 285 false, false, true, 286 extack); 287 else if (update_decap) 288 err = __mlxsw_sp_ipip_entry_update_tunnel(mlxsw_sp, ipip_entry, 289 false, false, false, 290 extack); 291 292 ipip_entry->parms4 = new_parms; 293 return err; 294 } 295 296 static const struct mlxsw_sp_ipip_ops mlxsw_sp_ipip_gre4_ops = { 297 .dev_type = ARPHRD_IPGRE, 298 .ul_proto = MLXSW_SP_L3_PROTO_IPV4, 299 .nexthop_update = mlxsw_sp_ipip_nexthop_update_gre4, 300 .decap_config = mlxsw_sp_ipip_decap_config_gre4, 301 .can_offload = mlxsw_sp_ipip_can_offload_gre4, 302 .ol_loopback_config = mlxsw_sp_ipip_ol_loopback_config_gre4, 303 .ol_netdev_change = mlxsw_sp_ipip_ol_netdev_change_gre4, 304 }; 305 306 const struct mlxsw_sp_ipip_ops *mlxsw_sp_ipip_ops_arr[] = { 307 [MLXSW_SP_IPIP_TYPE_GRE4] = &mlxsw_sp_ipip_gre4_ops, 308 }; 309 310 static int mlxsw_sp_ipip_ecn_encap_init_one(struct mlxsw_sp *mlxsw_sp, 311 u8 inner_ecn, u8 outer_ecn) 312 { 313 char tieem_pl[MLXSW_REG_TIEEM_LEN]; 314 315 mlxsw_reg_tieem_pack(tieem_pl, inner_ecn, outer_ecn); 316 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(tieem), tieem_pl); 317 } 318 319 int mlxsw_sp_ipip_ecn_encap_init(struct mlxsw_sp *mlxsw_sp) 320 { 321 int i; 322 323 /* Iterate over inner ECN values */ 324 for (i = INET_ECN_NOT_ECT; i <= INET_ECN_CE; i++) { 325 u8 outer_ecn = INET_ECN_encapsulate(0, i); 326 int err; 327 328 err = mlxsw_sp_ipip_ecn_encap_init_one(mlxsw_sp, i, outer_ecn); 329 if (err) 330 return err; 331 } 332 333 return 0; 334 } 335 336 static int mlxsw_sp_ipip_ecn_decap_init_one(struct mlxsw_sp *mlxsw_sp, 337 u8 inner_ecn, u8 outer_ecn) 338 { 339 char tidem_pl[MLXSW_REG_TIDEM_LEN]; 340 u8 new_inner_ecn; 341 bool trap_en; 342 343 new_inner_ecn = mlxsw_sp_tunnel_ecn_decap(outer_ecn, inner_ecn, 344 &trap_en); 345 mlxsw_reg_tidem_pack(tidem_pl, outer_ecn, inner_ecn, new_inner_ecn, 346 trap_en, trap_en ? MLXSW_TRAP_ID_DECAP_ECN0 : 0); 347 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(tidem), tidem_pl); 348 } 349 350 int mlxsw_sp_ipip_ecn_decap_init(struct mlxsw_sp *mlxsw_sp) 351 { 352 int i, j, err; 353 354 /* Iterate over inner ECN values */ 355 for (i = INET_ECN_NOT_ECT; i <= INET_ECN_CE; i++) { 356 /* Iterate over outer ECN values */ 357 for (j = INET_ECN_NOT_ECT; j <= INET_ECN_CE; j++) { 358 err = mlxsw_sp_ipip_ecn_decap_init_one(mlxsw_sp, i, j); 359 if (err) 360 return err; 361 } 362 } 363 364 return 0; 365 } 366