spectrum_nve_vxlan.c (13513B)
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2/* Copyright (c) 2018 Mellanox Technologies. All rights reserved */ 3 4#include <linux/netdevice.h> 5#include <linux/netlink.h> 6#include <linux/random.h> 7#include <net/vxlan.h> 8 9#include "reg.h" 10#include "spectrum.h" 11#include "spectrum_nve.h" 12 13#define MLXSW_SP_NVE_VXLAN_IPV4_SUPPORTED_FLAGS (VXLAN_F_UDP_ZERO_CSUM_TX | \ 14 VXLAN_F_LEARN) 15#define MLXSW_SP_NVE_VXLAN_IPV6_SUPPORTED_FLAGS (VXLAN_F_IPV6 | \ 16 VXLAN_F_UDP_ZERO_CSUM6_TX | \ 17 VXLAN_F_UDP_ZERO_CSUM6_RX) 18 19static bool mlxsw_sp_nve_vxlan_ipv4_flags_check(const struct vxlan_config *cfg, 20 struct netlink_ext_ack *extack) 21{ 22 if (!(cfg->flags & VXLAN_F_UDP_ZERO_CSUM_TX)) { 23 NL_SET_ERR_MSG_MOD(extack, "VxLAN: Zero UDP checksum must be allowed for TX"); 24 return false; 25 } 26 27 if (cfg->flags & ~MLXSW_SP_NVE_VXLAN_IPV4_SUPPORTED_FLAGS) { 28 NL_SET_ERR_MSG_MOD(extack, "VxLAN: Unsupported flag"); 29 return false; 30 } 31 32 return true; 33} 34 35static bool mlxsw_sp_nve_vxlan_ipv6_flags_check(const struct vxlan_config *cfg, 36 struct netlink_ext_ack *extack) 37{ 38 if (!(cfg->flags & VXLAN_F_UDP_ZERO_CSUM6_TX)) { 39 NL_SET_ERR_MSG_MOD(extack, "VxLAN: Zero UDP checksum must be allowed for TX"); 40 return false; 41 } 42 43 if (!(cfg->flags & VXLAN_F_UDP_ZERO_CSUM6_RX)) { 44 NL_SET_ERR_MSG_MOD(extack, "VxLAN: Zero UDP checksum must be allowed for RX"); 45 return false; 46 } 47 48 if (cfg->flags & ~MLXSW_SP_NVE_VXLAN_IPV6_SUPPORTED_FLAGS) { 49 NL_SET_ERR_MSG_MOD(extack, "VxLAN: Unsupported flag"); 50 return false; 51 } 52 53 return true; 54} 55 56static bool mlxsw_sp_nve_vxlan_can_offload(const struct mlxsw_sp_nve *nve, 57 const struct mlxsw_sp_nve_params *params, 58 struct netlink_ext_ack *extack) 59{ 60 struct vxlan_dev *vxlan = netdev_priv(params->dev); 61 struct vxlan_config *cfg = &vxlan->cfg; 62 63 if (vxlan_addr_multicast(&cfg->remote_ip)) { 64 NL_SET_ERR_MSG_MOD(extack, "VxLAN: Multicast destination IP is not supported"); 65 return false; 66 } 67 68 if (vxlan_addr_any(&cfg->saddr)) { 69 NL_SET_ERR_MSG_MOD(extack, "VxLAN: Source address must be specified"); 70 return false; 71 } 72 73 if (cfg->remote_ifindex) { 74 NL_SET_ERR_MSG_MOD(extack, "VxLAN: Local interface is not supported"); 75 return false; 76 } 77 78 if (cfg->port_min || cfg->port_max) { 79 NL_SET_ERR_MSG_MOD(extack, "VxLAN: Only default UDP source port range is supported"); 80 return false; 81 } 82 83 if (cfg->tos != 1) { 84 NL_SET_ERR_MSG_MOD(extack, "VxLAN: TOS must be configured to inherit"); 85 return false; 86 } 87 88 if (cfg->flags & VXLAN_F_TTL_INHERIT) { 89 NL_SET_ERR_MSG_MOD(extack, "VxLAN: TTL must not be configured to inherit"); 90 return false; 91 } 92 93 switch (cfg->saddr.sa.sa_family) { 94 case AF_INET: 95 if (!mlxsw_sp_nve_vxlan_ipv4_flags_check(cfg, extack)) 96 return false; 97 break; 98 case AF_INET6: 99 if (!mlxsw_sp_nve_vxlan_ipv6_flags_check(cfg, extack)) 100 return false; 101 break; 102 } 103 104 if (cfg->ttl == 0) { 105 NL_SET_ERR_MSG_MOD(extack, "VxLAN: TTL must not be configured to 0"); 106 return false; 107 } 108 109 if (cfg->label != 0) { 110 NL_SET_ERR_MSG_MOD(extack, "VxLAN: Flow label must be configured to 0"); 111 return false; 112 } 113 114 return true; 115} 116 117static bool mlxsw_sp1_nve_vxlan_can_offload(const struct mlxsw_sp_nve *nve, 118 const struct mlxsw_sp_nve_params *params, 119 struct netlink_ext_ack *extack) 120{ 121 if (params->ethertype == ETH_P_8021AD) { 122 NL_SET_ERR_MSG_MOD(extack, "VxLAN: 802.1ad bridge is not supported with VxLAN"); 123 return false; 124 } 125 126 return mlxsw_sp_nve_vxlan_can_offload(nve, params, extack); 127} 128 129static void 130mlxsw_sp_nve_vxlan_ul_proto_sip_config(const struct vxlan_config *cfg, 131 struct mlxsw_sp_nve_config *config) 132{ 133 switch (cfg->saddr.sa.sa_family) { 134 case AF_INET: 135 config->ul_proto = MLXSW_SP_L3_PROTO_IPV4; 136 config->ul_sip.addr4 = cfg->saddr.sin.sin_addr.s_addr; 137 break; 138 case AF_INET6: 139 config->ul_proto = MLXSW_SP_L3_PROTO_IPV6; 140 config->ul_sip.addr6 = cfg->saddr.sin6.sin6_addr; 141 break; 142 } 143} 144 145static void mlxsw_sp_nve_vxlan_config(const struct mlxsw_sp_nve *nve, 146 const struct mlxsw_sp_nve_params *params, 147 struct mlxsw_sp_nve_config *config) 148{ 149 struct vxlan_dev *vxlan = netdev_priv(params->dev); 150 struct vxlan_config *cfg = &vxlan->cfg; 151 152 config->type = MLXSW_SP_NVE_TYPE_VXLAN; 153 config->ttl = cfg->ttl; 154 config->flowlabel = cfg->label; 155 config->learning_en = cfg->flags & VXLAN_F_LEARN ? 1 : 0; 156 config->ul_tb_id = RT_TABLE_MAIN; 157 mlxsw_sp_nve_vxlan_ul_proto_sip_config(cfg, config); 158 config->udp_dport = cfg->dst_port; 159} 160 161static void 162mlxsw_sp_nve_vxlan_config_prepare(char *tngcr_pl, 163 const struct mlxsw_sp_nve_config *config) 164{ 165 struct in6_addr addr6; 166 u8 udp_sport; 167 168 mlxsw_reg_tngcr_pack(tngcr_pl, MLXSW_REG_TNGCR_TYPE_VXLAN, true, 169 config->ttl); 170 /* VxLAN driver's default UDP source port range is 32768 (0x8000) 171 * to 60999 (0xee47). Set the upper 8 bits of the UDP source port 172 * to a random number between 0x80 and 0xee 173 */ 174 get_random_bytes(&udp_sport, sizeof(udp_sport)); 175 udp_sport = (udp_sport % (0xee - 0x80 + 1)) + 0x80; 176 mlxsw_reg_tngcr_nve_udp_sport_prefix_set(tngcr_pl, udp_sport); 177 178 switch (config->ul_proto) { 179 case MLXSW_SP_L3_PROTO_IPV4: 180 mlxsw_reg_tngcr_usipv4_set(tngcr_pl, 181 be32_to_cpu(config->ul_sip.addr4)); 182 break; 183 case MLXSW_SP_L3_PROTO_IPV6: 184 addr6 = config->ul_sip.addr6; 185 mlxsw_reg_tngcr_usipv6_memcpy_to(tngcr_pl, 186 (const char *)&addr6); 187 break; 188 } 189} 190 191static int 192mlxsw_sp1_nve_vxlan_config_set(struct mlxsw_sp *mlxsw_sp, 193 const struct mlxsw_sp_nve_config *config) 194{ 195 char tngcr_pl[MLXSW_REG_TNGCR_LEN]; 196 u16 ul_vr_id; 197 int err; 198 199 err = mlxsw_sp_router_tb_id_vr_id(mlxsw_sp, config->ul_tb_id, 200 &ul_vr_id); 201 if (err) 202 return err; 203 204 mlxsw_sp_nve_vxlan_config_prepare(tngcr_pl, config); 205 mlxsw_reg_tngcr_learn_enable_set(tngcr_pl, config->learning_en); 206 mlxsw_reg_tngcr_underlay_virtual_router_set(tngcr_pl, ul_vr_id); 207 208 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(tngcr), tngcr_pl); 209} 210 211static void mlxsw_sp1_nve_vxlan_config_clear(struct mlxsw_sp *mlxsw_sp) 212{ 213 char tngcr_pl[MLXSW_REG_TNGCR_LEN]; 214 215 mlxsw_reg_tngcr_pack(tngcr_pl, MLXSW_REG_TNGCR_TYPE_VXLAN, false, 0); 216 217 mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(tngcr), tngcr_pl); 218} 219 220static int mlxsw_sp1_nve_vxlan_rtdp_set(struct mlxsw_sp *mlxsw_sp, 221 unsigned int tunnel_index) 222{ 223 char rtdp_pl[MLXSW_REG_RTDP_LEN]; 224 225 mlxsw_reg_rtdp_pack(rtdp_pl, MLXSW_REG_RTDP_TYPE_NVE, tunnel_index); 226 227 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rtdp), rtdp_pl); 228} 229 230static int mlxsw_sp1_nve_vxlan_init(struct mlxsw_sp_nve *nve, 231 const struct mlxsw_sp_nve_config *config) 232{ 233 struct mlxsw_sp *mlxsw_sp = nve->mlxsw_sp; 234 int err; 235 236 err = mlxsw_sp_parsing_vxlan_udp_dport_set(mlxsw_sp, config->udp_dport); 237 if (err) 238 return err; 239 240 err = mlxsw_sp_parsing_depth_inc(mlxsw_sp); 241 if (err) 242 goto err_parsing_depth_inc; 243 244 err = mlxsw_sp1_nve_vxlan_config_set(mlxsw_sp, config); 245 if (err) 246 goto err_config_set; 247 248 err = mlxsw_sp1_nve_vxlan_rtdp_set(mlxsw_sp, nve->tunnel_index); 249 if (err) 250 goto err_rtdp_set; 251 252 err = mlxsw_sp_router_nve_promote_decap(mlxsw_sp, config->ul_tb_id, 253 config->ul_proto, 254 &config->ul_sip, 255 nve->tunnel_index); 256 if (err) 257 goto err_promote_decap; 258 259 return 0; 260 261err_promote_decap: 262err_rtdp_set: 263 mlxsw_sp1_nve_vxlan_config_clear(mlxsw_sp); 264err_config_set: 265 mlxsw_sp_parsing_depth_dec(mlxsw_sp); 266err_parsing_depth_inc: 267 mlxsw_sp_parsing_vxlan_udp_dport_set(mlxsw_sp, 0); 268 return err; 269} 270 271static void mlxsw_sp1_nve_vxlan_fini(struct mlxsw_sp_nve *nve) 272{ 273 struct mlxsw_sp_nve_config *config = &nve->config; 274 struct mlxsw_sp *mlxsw_sp = nve->mlxsw_sp; 275 276 mlxsw_sp_router_nve_demote_decap(mlxsw_sp, config->ul_tb_id, 277 config->ul_proto, &config->ul_sip); 278 mlxsw_sp1_nve_vxlan_config_clear(mlxsw_sp); 279 mlxsw_sp_parsing_depth_dec(mlxsw_sp); 280 mlxsw_sp_parsing_vxlan_udp_dport_set(mlxsw_sp, 0); 281} 282 283static int 284mlxsw_sp_nve_vxlan_fdb_replay(const struct net_device *nve_dev, __be32 vni, 285 struct netlink_ext_ack *extack) 286{ 287 if (WARN_ON(!netif_is_vxlan(nve_dev))) 288 return -EINVAL; 289 return vxlan_fdb_replay(nve_dev, vni, &mlxsw_sp_switchdev_notifier, 290 extack); 291} 292 293static void 294mlxsw_sp_nve_vxlan_clear_offload(const struct net_device *nve_dev, __be32 vni) 295{ 296 if (WARN_ON(!netif_is_vxlan(nve_dev))) 297 return; 298 vxlan_fdb_clear_offload(nve_dev, vni); 299} 300 301const struct mlxsw_sp_nve_ops mlxsw_sp1_nve_vxlan_ops = { 302 .type = MLXSW_SP_NVE_TYPE_VXLAN, 303 .can_offload = mlxsw_sp1_nve_vxlan_can_offload, 304 .nve_config = mlxsw_sp_nve_vxlan_config, 305 .init = mlxsw_sp1_nve_vxlan_init, 306 .fini = mlxsw_sp1_nve_vxlan_fini, 307 .fdb_replay = mlxsw_sp_nve_vxlan_fdb_replay, 308 .fdb_clear_offload = mlxsw_sp_nve_vxlan_clear_offload, 309}; 310 311static bool mlxsw_sp2_nve_vxlan_learning_set(struct mlxsw_sp *mlxsw_sp, 312 bool learning_en) 313{ 314 char tnpc_pl[MLXSW_REG_TNPC_LEN]; 315 316 mlxsw_reg_tnpc_pack(tnpc_pl, MLXSW_REG_TUNNEL_PORT_NVE, 317 learning_en); 318 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(tnpc), tnpc_pl); 319} 320 321static int 322mlxsw_sp2_nve_decap_ethertype_set(struct mlxsw_sp *mlxsw_sp) 323{ 324 char spvid_pl[MLXSW_REG_SPVID_LEN] = {}; 325 326 mlxsw_reg_spvid_tport_set(spvid_pl, true); 327 mlxsw_reg_spvid_local_port_set(spvid_pl, 328 MLXSW_REG_TUNNEL_PORT_NVE); 329 mlxsw_reg_spvid_egr_et_set_set(spvid_pl, true); 330 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spvid), spvid_pl); 331} 332 333static int 334mlxsw_sp2_nve_vxlan_config_set(struct mlxsw_sp *mlxsw_sp, 335 const struct mlxsw_sp_nve_config *config) 336{ 337 char tngcr_pl[MLXSW_REG_TNGCR_LEN]; 338 char spvtr_pl[MLXSW_REG_SPVTR_LEN]; 339 u16 ul_rif_index; 340 int err; 341 342 err = mlxsw_sp_router_ul_rif_get(mlxsw_sp, config->ul_tb_id, 343 &ul_rif_index); 344 if (err) 345 return err; 346 mlxsw_sp->nve->ul_rif_index = ul_rif_index; 347 348 err = mlxsw_sp2_nve_vxlan_learning_set(mlxsw_sp, config->learning_en); 349 if (err) 350 goto err_vxlan_learning_set; 351 352 mlxsw_sp_nve_vxlan_config_prepare(tngcr_pl, config); 353 mlxsw_reg_tngcr_underlay_rif_set(tngcr_pl, ul_rif_index); 354 355 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(tngcr), tngcr_pl); 356 if (err) 357 goto err_tngcr_write; 358 359 mlxsw_reg_spvtr_pack(spvtr_pl, true, MLXSW_REG_TUNNEL_PORT_NVE, 360 MLXSW_REG_SPVTR_IPVID_MODE_ALWAYS_PUSH_VLAN); 361 err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spvtr), spvtr_pl); 362 if (err) 363 goto err_spvtr_write; 364 365 err = mlxsw_sp2_nve_decap_ethertype_set(mlxsw_sp); 366 if (err) 367 goto err_decap_ethertype_set; 368 369 return 0; 370 371err_decap_ethertype_set: 372 mlxsw_reg_spvtr_pack(spvtr_pl, true, MLXSW_REG_TUNNEL_PORT_NVE, 373 MLXSW_REG_SPVTR_IPVID_MODE_IEEE_COMPLIANT_PVID); 374 mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spvtr), spvtr_pl); 375err_spvtr_write: 376 mlxsw_reg_tngcr_pack(tngcr_pl, MLXSW_REG_TNGCR_TYPE_VXLAN, false, 0); 377 mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(tngcr), tngcr_pl); 378err_tngcr_write: 379 mlxsw_sp2_nve_vxlan_learning_set(mlxsw_sp, false); 380err_vxlan_learning_set: 381 mlxsw_sp_router_ul_rif_put(mlxsw_sp, ul_rif_index); 382 return err; 383} 384 385static void mlxsw_sp2_nve_vxlan_config_clear(struct mlxsw_sp *mlxsw_sp) 386{ 387 char spvtr_pl[MLXSW_REG_SPVTR_LEN]; 388 char tngcr_pl[MLXSW_REG_TNGCR_LEN]; 389 390 mlxsw_reg_spvtr_pack(spvtr_pl, true, MLXSW_REG_TUNNEL_PORT_NVE, 391 MLXSW_REG_SPVTR_IPVID_MODE_IEEE_COMPLIANT_PVID); 392 mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(spvtr), spvtr_pl); 393 mlxsw_reg_tngcr_pack(tngcr_pl, MLXSW_REG_TNGCR_TYPE_VXLAN, false, 0); 394 mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(tngcr), tngcr_pl); 395 mlxsw_sp2_nve_vxlan_learning_set(mlxsw_sp, false); 396 mlxsw_sp_router_ul_rif_put(mlxsw_sp, mlxsw_sp->nve->ul_rif_index); 397} 398 399static int mlxsw_sp2_nve_vxlan_rtdp_set(struct mlxsw_sp *mlxsw_sp, 400 unsigned int tunnel_index, 401 u16 ul_rif_index) 402{ 403 char rtdp_pl[MLXSW_REG_RTDP_LEN]; 404 405 mlxsw_reg_rtdp_pack(rtdp_pl, MLXSW_REG_RTDP_TYPE_NVE, tunnel_index); 406 mlxsw_reg_rtdp_egress_router_interface_set(rtdp_pl, ul_rif_index); 407 408 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rtdp), rtdp_pl); 409} 410 411static int mlxsw_sp2_nve_vxlan_init(struct mlxsw_sp_nve *nve, 412 const struct mlxsw_sp_nve_config *config) 413{ 414 struct mlxsw_sp *mlxsw_sp = nve->mlxsw_sp; 415 int err; 416 417 err = mlxsw_sp_parsing_vxlan_udp_dport_set(mlxsw_sp, config->udp_dport); 418 if (err) 419 return err; 420 421 err = mlxsw_sp_parsing_depth_inc(mlxsw_sp); 422 if (err) 423 goto err_parsing_depth_inc; 424 425 err = mlxsw_sp2_nve_vxlan_config_set(mlxsw_sp, config); 426 if (err) 427 goto err_config_set; 428 429 err = mlxsw_sp2_nve_vxlan_rtdp_set(mlxsw_sp, nve->tunnel_index, 430 nve->ul_rif_index); 431 if (err) 432 goto err_rtdp_set; 433 434 err = mlxsw_sp_router_nve_promote_decap(mlxsw_sp, config->ul_tb_id, 435 config->ul_proto, 436 &config->ul_sip, 437 nve->tunnel_index); 438 if (err) 439 goto err_promote_decap; 440 441 return 0; 442 443err_promote_decap: 444err_rtdp_set: 445 mlxsw_sp2_nve_vxlan_config_clear(mlxsw_sp); 446err_config_set: 447 mlxsw_sp_parsing_depth_dec(mlxsw_sp); 448err_parsing_depth_inc: 449 mlxsw_sp_parsing_vxlan_udp_dport_set(mlxsw_sp, 0); 450 return err; 451} 452 453static void mlxsw_sp2_nve_vxlan_fini(struct mlxsw_sp_nve *nve) 454{ 455 struct mlxsw_sp_nve_config *config = &nve->config; 456 struct mlxsw_sp *mlxsw_sp = nve->mlxsw_sp; 457 458 mlxsw_sp_router_nve_demote_decap(mlxsw_sp, config->ul_tb_id, 459 config->ul_proto, &config->ul_sip); 460 mlxsw_sp2_nve_vxlan_config_clear(mlxsw_sp); 461 mlxsw_sp_parsing_depth_dec(mlxsw_sp); 462 mlxsw_sp_parsing_vxlan_udp_dport_set(mlxsw_sp, 0); 463} 464 465const struct mlxsw_sp_nve_ops mlxsw_sp2_nve_vxlan_ops = { 466 .type = MLXSW_SP_NVE_TYPE_VXLAN, 467 .can_offload = mlxsw_sp_nve_vxlan_can_offload, 468 .nve_config = mlxsw_sp_nve_vxlan_config, 469 .init = mlxsw_sp2_nve_vxlan_init, 470 .fini = mlxsw_sp2_nve_vxlan_fini, 471 .fdb_replay = mlxsw_sp_nve_vxlan_fdb_replay, 472 .fdb_clear_offload = mlxsw_sp_nve_vxlan_clear_offload, 473};