|
7 | 7 | #include <net/vxlan.h>
|
8 | 8 |
|
9 | 9 | #include "reg.h"
|
| 10 | +#include "spectrum.h" |
10 | 11 | #include "spectrum_nve.h"
|
11 | 12 |
|
12 | 13 | /* Eth (18B) | IPv6 (40B) | UDP (8B) | VxLAN (8B) | Eth (14B) | IPv6 (40B)
|
|
20 | 21 | #define MLXSW_SP_NVE_VXLAN_SUPPORTED_FLAGS (VXLAN_F_UDP_ZERO_CSUM_TX | \
|
21 | 22 | VXLAN_F_LEARN)
|
22 | 23 |
|
23 |
| -static bool mlxsw_sp1_nve_vxlan_can_offload(const struct mlxsw_sp_nve *nve, |
24 |
| - const struct net_device *dev, |
25 |
| - struct netlink_ext_ack *extack) |
| 24 | +static bool mlxsw_sp_nve_vxlan_can_offload(const struct mlxsw_sp_nve *nve, |
| 25 | + const struct net_device *dev, |
| 26 | + struct netlink_ext_ack *extack) |
26 | 27 | {
|
27 | 28 | struct vxlan_dev *vxlan = netdev_priv(dev);
|
28 | 29 | struct vxlan_config *cfg = &vxlan->cfg;
|
@@ -112,32 +113,40 @@ static int mlxsw_sp_nve_parsing_set(struct mlxsw_sp *mlxsw_sp,
|
112 | 113 | return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mprs), mprs_pl);
|
113 | 114 | }
|
114 | 115 |
|
| 116 | +static void |
| 117 | +mlxsw_sp_nve_vxlan_config_prepare(char *tngcr_pl, |
| 118 | + const struct mlxsw_sp_nve_config *config) |
| 119 | +{ |
| 120 | + u8 udp_sport; |
| 121 | + |
| 122 | + mlxsw_reg_tngcr_pack(tngcr_pl, MLXSW_REG_TNGCR_TYPE_VXLAN, true, |
| 123 | + config->ttl); |
| 124 | + /* VxLAN driver's default UDP source port range is 32768 (0x8000) |
| 125 | + * to 60999 (0xee47). Set the upper 8 bits of the UDP source port |
| 126 | + * to a random number between 0x80 and 0xee |
| 127 | + */ |
| 128 | + get_random_bytes(&udp_sport, sizeof(udp_sport)); |
| 129 | + udp_sport = (udp_sport % (0xee - 0x80 + 1)) + 0x80; |
| 130 | + mlxsw_reg_tngcr_nve_udp_sport_prefix_set(tngcr_pl, udp_sport); |
| 131 | + mlxsw_reg_tngcr_usipv4_set(tngcr_pl, be32_to_cpu(config->ul_sip.addr4)); |
| 132 | +} |
| 133 | + |
115 | 134 | static int
|
116 | 135 | mlxsw_sp1_nve_vxlan_config_set(struct mlxsw_sp *mlxsw_sp,
|
117 | 136 | const struct mlxsw_sp_nve_config *config)
|
118 | 137 | {
|
119 | 138 | char tngcr_pl[MLXSW_REG_TNGCR_LEN];
|
120 | 139 | u16 ul_vr_id;
|
121 |
| - u8 udp_sport; |
122 | 140 | int err;
|
123 | 141 |
|
124 | 142 | err = mlxsw_sp_router_tb_id_vr_id(mlxsw_sp, config->ul_tb_id,
|
125 | 143 | &ul_vr_id);
|
126 | 144 | if (err)
|
127 | 145 | return err;
|
128 | 146 |
|
129 |
| - mlxsw_reg_tngcr_pack(tngcr_pl, MLXSW_REG_TNGCR_TYPE_VXLAN, true, |
130 |
| - config->ttl); |
131 |
| - /* VxLAN driver's default UDP source port range is 32768 (0x8000) |
132 |
| - * to 60999 (0xee47). Set the upper 8 bits of the UDP source port |
133 |
| - * to a random number between 0x80 and 0xee |
134 |
| - */ |
135 |
| - get_random_bytes(&udp_sport, sizeof(udp_sport)); |
136 |
| - udp_sport = (udp_sport % (0xee - 0x80 + 1)) + 0x80; |
137 |
| - mlxsw_reg_tngcr_nve_udp_sport_prefix_set(tngcr_pl, udp_sport); |
| 147 | + mlxsw_sp_nve_vxlan_config_prepare(tngcr_pl, config); |
138 | 148 | mlxsw_reg_tngcr_learn_enable_set(tngcr_pl, config->learning_en);
|
139 | 149 | mlxsw_reg_tngcr_underlay_virtual_router_set(tngcr_pl, ul_vr_id);
|
140 |
| - mlxsw_reg_tngcr_usipv4_set(tngcr_pl, be32_to_cpu(config->ul_sip.addr4)); |
141 | 150 |
|
142 | 151 | return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(tngcr), tngcr_pl);
|
143 | 152 | }
|
@@ -231,34 +240,134 @@ mlxsw_sp_nve_vxlan_clear_offload(const struct net_device *nve_dev, __be32 vni)
|
231 | 240 |
|
232 | 241 | const struct mlxsw_sp_nve_ops mlxsw_sp1_nve_vxlan_ops = {
|
233 | 242 | .type = MLXSW_SP_NVE_TYPE_VXLAN,
|
234 |
| - .can_offload = mlxsw_sp1_nve_vxlan_can_offload, |
| 243 | + .can_offload = mlxsw_sp_nve_vxlan_can_offload, |
235 | 244 | .nve_config = mlxsw_sp_nve_vxlan_config,
|
236 | 245 | .init = mlxsw_sp1_nve_vxlan_init,
|
237 | 246 | .fini = mlxsw_sp1_nve_vxlan_fini,
|
238 | 247 | .fdb_replay = mlxsw_sp_nve_vxlan_fdb_replay,
|
239 | 248 | .fdb_clear_offload = mlxsw_sp_nve_vxlan_clear_offload,
|
240 | 249 | };
|
241 | 250 |
|
242 |
| -static bool mlxsw_sp2_nve_vxlan_can_offload(const struct mlxsw_sp_nve *nve, |
243 |
| - const struct net_device *dev, |
244 |
| - struct netlink_ext_ack *extack) |
| 251 | +static bool mlxsw_sp2_nve_vxlan_learning_set(struct mlxsw_sp *mlxsw_sp, |
| 252 | + bool learning_en) |
245 | 253 | {
|
246 |
| - return false; |
| 254 | + char tnpc_pl[MLXSW_REG_TNPC_LEN]; |
| 255 | + |
| 256 | + mlxsw_reg_tnpc_pack(tnpc_pl, MLXSW_REG_TNPC_TUNNEL_PORT_NVE, |
| 257 | + learning_en); |
| 258 | + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(tnpc), tnpc_pl); |
| 259 | +} |
| 260 | + |
| 261 | +static int |
| 262 | +mlxsw_sp2_nve_vxlan_config_set(struct mlxsw_sp *mlxsw_sp, |
| 263 | + const struct mlxsw_sp_nve_config *config) |
| 264 | +{ |
| 265 | + char tngcr_pl[MLXSW_REG_TNGCR_LEN]; |
| 266 | + u16 ul_rif_index; |
| 267 | + int err; |
| 268 | + |
| 269 | + err = mlxsw_sp_router_ul_rif_get(mlxsw_sp, config->ul_tb_id, |
| 270 | + &ul_rif_index); |
| 271 | + if (err) |
| 272 | + return err; |
| 273 | + mlxsw_sp->nve->ul_rif_index = ul_rif_index; |
| 274 | + |
| 275 | + err = mlxsw_sp2_nve_vxlan_learning_set(mlxsw_sp, config->learning_en); |
| 276 | + if (err) |
| 277 | + goto err_vxlan_learning_set; |
| 278 | + |
| 279 | + mlxsw_sp_nve_vxlan_config_prepare(tngcr_pl, config); |
| 280 | + mlxsw_reg_tngcr_underlay_rif_set(tngcr_pl, ul_rif_index); |
| 281 | + |
| 282 | + err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(tngcr), tngcr_pl); |
| 283 | + if (err) |
| 284 | + goto err_tngcr_write; |
| 285 | + |
| 286 | + return 0; |
| 287 | + |
| 288 | +err_tngcr_write: |
| 289 | + mlxsw_sp2_nve_vxlan_learning_set(mlxsw_sp, false); |
| 290 | +err_vxlan_learning_set: |
| 291 | + mlxsw_sp_router_ul_rif_put(mlxsw_sp, ul_rif_index); |
| 292 | + return err; |
| 293 | +} |
| 294 | + |
| 295 | +static void mlxsw_sp2_nve_vxlan_config_clear(struct mlxsw_sp *mlxsw_sp) |
| 296 | +{ |
| 297 | + char tngcr_pl[MLXSW_REG_TNGCR_LEN]; |
| 298 | + |
| 299 | + mlxsw_reg_tngcr_pack(tngcr_pl, MLXSW_REG_TNGCR_TYPE_VXLAN, false, 0); |
| 300 | + mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(tngcr), tngcr_pl); |
| 301 | + mlxsw_sp2_nve_vxlan_learning_set(mlxsw_sp, false); |
| 302 | + mlxsw_sp_router_ul_rif_put(mlxsw_sp, mlxsw_sp->nve->ul_rif_index); |
| 303 | +} |
| 304 | + |
| 305 | +static int mlxsw_sp2_nve_vxlan_rtdp_set(struct mlxsw_sp *mlxsw_sp, |
| 306 | + unsigned int tunnel_index, |
| 307 | + u16 ul_rif_index) |
| 308 | +{ |
| 309 | + char rtdp_pl[MLXSW_REG_RTDP_LEN]; |
| 310 | + |
| 311 | + mlxsw_reg_rtdp_pack(rtdp_pl, MLXSW_REG_RTDP_TYPE_NVE, tunnel_index); |
| 312 | + mlxsw_reg_rtdp_egress_router_interface_set(rtdp_pl, ul_rif_index); |
| 313 | + |
| 314 | + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(rtdp), rtdp_pl); |
247 | 315 | }
|
248 | 316 |
|
249 | 317 | static int mlxsw_sp2_nve_vxlan_init(struct mlxsw_sp_nve *nve,
|
250 | 318 | const struct mlxsw_sp_nve_config *config)
|
251 | 319 | {
|
252 |
| - return -EOPNOTSUPP; |
| 320 | + struct mlxsw_sp *mlxsw_sp = nve->mlxsw_sp; |
| 321 | + int err; |
| 322 | + |
| 323 | + err = mlxsw_sp_nve_parsing_set(mlxsw_sp, |
| 324 | + MLXSW_SP_NVE_VXLAN_PARSING_DEPTH, |
| 325 | + config->udp_dport); |
| 326 | + if (err) |
| 327 | + return err; |
| 328 | + |
| 329 | + err = mlxsw_sp2_nve_vxlan_config_set(mlxsw_sp, config); |
| 330 | + if (err) |
| 331 | + goto err_config_set; |
| 332 | + |
| 333 | + err = mlxsw_sp2_nve_vxlan_rtdp_set(mlxsw_sp, nve->tunnel_index, |
| 334 | + nve->ul_rif_index); |
| 335 | + if (err) |
| 336 | + goto err_rtdp_set; |
| 337 | + |
| 338 | + err = mlxsw_sp_router_nve_promote_decap(mlxsw_sp, config->ul_tb_id, |
| 339 | + config->ul_proto, |
| 340 | + &config->ul_sip, |
| 341 | + nve->tunnel_index); |
| 342 | + if (err) |
| 343 | + goto err_promote_decap; |
| 344 | + |
| 345 | + return 0; |
| 346 | + |
| 347 | +err_promote_decap: |
| 348 | +err_rtdp_set: |
| 349 | + mlxsw_sp2_nve_vxlan_config_clear(mlxsw_sp); |
| 350 | +err_config_set: |
| 351 | + mlxsw_sp_nve_parsing_set(mlxsw_sp, MLXSW_SP_NVE_DEFAULT_PARSING_DEPTH, |
| 352 | + config->udp_dport); |
| 353 | + return err; |
253 | 354 | }
|
254 | 355 |
|
255 | 356 | static void mlxsw_sp2_nve_vxlan_fini(struct mlxsw_sp_nve *nve)
|
256 | 357 | {
|
| 358 | + struct mlxsw_sp_nve_config *config = &nve->config; |
| 359 | + struct mlxsw_sp *mlxsw_sp = nve->mlxsw_sp; |
| 360 | + |
| 361 | + mlxsw_sp_router_nve_demote_decap(mlxsw_sp, config->ul_tb_id, |
| 362 | + config->ul_proto, &config->ul_sip); |
| 363 | + mlxsw_sp2_nve_vxlan_config_clear(mlxsw_sp); |
| 364 | + mlxsw_sp_nve_parsing_set(mlxsw_sp, MLXSW_SP_NVE_DEFAULT_PARSING_DEPTH, |
| 365 | + config->udp_dport); |
257 | 366 | }
|
258 | 367 |
|
259 | 368 | const struct mlxsw_sp_nve_ops mlxsw_sp2_nve_vxlan_ops = {
|
260 | 369 | .type = MLXSW_SP_NVE_TYPE_VXLAN,
|
261 |
| - .can_offload = mlxsw_sp2_nve_vxlan_can_offload, |
| 370 | + .can_offload = mlxsw_sp_nve_vxlan_can_offload, |
262 | 371 | .nve_config = mlxsw_sp_nve_vxlan_config,
|
263 | 372 | .init = mlxsw_sp2_nve_vxlan_init,
|
264 | 373 | .fini = mlxsw_sp2_nve_vxlan_fini,
|
|
0 commit comments