diff options
author | Petr Machata <petrm@mellanox.com> | 2018-02-27 08:53:49 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-02-27 14:46:28 -0500 |
commit | 8f08a528de5eaded034c5480588722e7dc167540 (patch) | |
tree | 69f007862fe11de8dadd24a81e0023e05450b979 | |
parent | 27cf76fe60ec6fbe2ba8844261b90a6aecbc42f0 (diff) |
mlxsw: spectrum_span: Support mirror to ip6gretap
Similarly to mirror-to-gretap, this enables mirroring to IPv6 gretap
netdevice.
Signed-off-by: Petr Machata <petrm@mellanox.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/Kconfig | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c | 101 |
2 files changed, 103 insertions, 0 deletions
diff --git a/drivers/net/ethernet/mellanox/mlxsw/Kconfig b/drivers/net/ethernet/mellanox/mlxsw/Kconfig index 830c3e28505e..93d97b4676eb 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/Kconfig +++ b/drivers/net/ethernet/mellanox/mlxsw/Kconfig | |||
@@ -80,6 +80,8 @@ config MLXSW_SPECTRUM | |||
80 | select MLXFW | 80 | select MLXFW |
81 | depends on NET_IPGRE | 81 | depends on NET_IPGRE |
82 | depends on !(MLXSW_CORE=y && NET_IPGRE=m) | 82 | depends on !(MLXSW_CORE=y && NET_IPGRE=m) |
83 | depends on IPV6_GRE | ||
84 | depends on !(MLXSW_CORE=y && IPV6_GRE=m) | ||
83 | default m | 85 | default m |
84 | ---help--- | 86 | ---help--- |
85 | This driver supports Mellanox Technologies Spectrum Ethernet | 87 | This driver supports Mellanox Technologies Spectrum Ethernet |
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c index d5fda4f13c31..f537e1de11d9 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c | |||
@@ -35,6 +35,8 @@ | |||
35 | #include <linux/list.h> | 35 | #include <linux/list.h> |
36 | #include <net/arp.h> | 36 | #include <net/arp.h> |
37 | #include <net/gre.h> | 37 | #include <net/gre.h> |
38 | #include <net/ndisc.h> | ||
39 | #include <net/ip6_tunnel.h> | ||
38 | 40 | ||
39 | #include "spectrum.h" | 41 | #include "spectrum.h" |
40 | #include "spectrum_span.h" | 42 | #include "spectrum_span.h" |
@@ -290,10 +292,109 @@ static const struct mlxsw_sp_span_entry_ops mlxsw_sp_span_entry_ops_gretap4 = { | |||
290 | .deconfigure = mlxsw_sp_span_entry_gretap4_deconfigure, | 292 | .deconfigure = mlxsw_sp_span_entry_gretap4_deconfigure, |
291 | }; | 293 | }; |
292 | 294 | ||
295 | static struct net_device * | ||
296 | mlxsw_sp_span_gretap6_route(const struct net_device *to_dev, | ||
297 | struct in6_addr *saddrp, | ||
298 | struct in6_addr *daddrp) | ||
299 | { | ||
300 | struct ip6_tnl *t = netdev_priv(to_dev); | ||
301 | struct flowi6 fl6 = t->fl.u.ip6; | ||
302 | struct net_device *dev = NULL; | ||
303 | struct dst_entry *dst; | ||
304 | struct rt6_info *rt6; | ||
305 | |||
306 | /* We assume "dev" stays valid after dst is released. */ | ||
307 | ASSERT_RTNL(); | ||
308 | |||
309 | fl6.flowi6_mark = t->parms.fwmark; | ||
310 | if (!ip6_tnl_xmit_ctl(t, &fl6.saddr, &fl6.daddr)) | ||
311 | return NULL; | ||
312 | |||
313 | dst = ip6_route_output(t->net, NULL, &fl6); | ||
314 | if (!dst || dst->error) | ||
315 | goto out; | ||
316 | |||
317 | rt6 = container_of(dst, struct rt6_info, dst); | ||
318 | |||
319 | dev = dst->dev; | ||
320 | *saddrp = fl6.saddr; | ||
321 | *daddrp = rt6->rt6i_gateway; | ||
322 | |||
323 | out: | ||
324 | dst_release(dst); | ||
325 | return dev; | ||
326 | } | ||
327 | |||
328 | static int | ||
329 | mlxsw_sp_span_entry_gretap6_parms(const struct net_device *to_dev, | ||
330 | struct mlxsw_sp_span_parms *sparmsp) | ||
331 | { | ||
332 | struct __ip6_tnl_parm tparm = mlxsw_sp_ipip_netdev_parms6(to_dev); | ||
333 | bool inherit_tos = tparm.flags & IP6_TNL_F_USE_ORIG_TCLASS; | ||
334 | union mlxsw_sp_l3addr saddr = { .addr6 = tparm.laddr }; | ||
335 | union mlxsw_sp_l3addr daddr = { .addr6 = tparm.raddr }; | ||
336 | bool inherit_ttl = !tparm.hop_limit; | ||
337 | union mlxsw_sp_l3addr gw = daddr; | ||
338 | struct net_device *l3edev; | ||
339 | |||
340 | if (!(to_dev->flags & IFF_UP) || | ||
341 | /* Reject tunnels with GRE keys, checksums, etc. */ | ||
342 | tparm.i_flags || tparm.o_flags || | ||
343 | /* Require a fixed TTL and a TOS copied from the mirrored packet. */ | ||
344 | inherit_ttl || !inherit_tos || | ||
345 | /* A destination address may not be "any". */ | ||
346 | mlxsw_sp_l3addr_is_zero(daddr)) | ||
347 | return mlxsw_sp_span_entry_unoffloadable(sparmsp); | ||
348 | |||
349 | l3edev = mlxsw_sp_span_gretap6_route(to_dev, &saddr.addr6, &gw.addr6); | ||
350 | return mlxsw_sp_span_entry_tunnel_parms_common(l3edev, saddr, daddr, gw, | ||
351 | tparm.hop_limit, | ||
352 | &nd_tbl, sparmsp); | ||
353 | } | ||
354 | |||
355 | static int | ||
356 | mlxsw_sp_span_entry_gretap6_configure(struct mlxsw_sp_span_entry *span_entry, | ||
357 | struct mlxsw_sp_span_parms sparms) | ||
358 | { | ||
359 | struct mlxsw_sp_port *dest_port = sparms.dest_port; | ||
360 | struct mlxsw_sp *mlxsw_sp = dest_port->mlxsw_sp; | ||
361 | u8 local_port = dest_port->local_port; | ||
362 | char mpat_pl[MLXSW_REG_MPAT_LEN]; | ||
363 | int pa_id = span_entry->id; | ||
364 | |||
365 | /* Create a new port analayzer entry for local_port. */ | ||
366 | mlxsw_reg_mpat_pack(mpat_pl, pa_id, local_port, true, | ||
367 | MLXSW_REG_MPAT_SPAN_TYPE_REMOTE_ETH_L3); | ||
368 | mlxsw_reg_mpat_eth_rspan_l2_pack(mpat_pl, | ||
369 | MLXSW_REG_MPAT_ETH_RSPAN_VERSION_NO_HEADER, | ||
370 | sparms.dmac, false); | ||
371 | mlxsw_reg_mpat_eth_rspan_l3_ipv6_pack(mpat_pl, sparms.ttl, sparms.smac, | ||
372 | sparms.saddr.addr6, | ||
373 | sparms.daddr.addr6); | ||
374 | |||
375 | return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpat), mpat_pl); | ||
376 | } | ||
377 | |||
378 | static void | ||
379 | mlxsw_sp_span_entry_gretap6_deconfigure(struct mlxsw_sp_span_entry *span_entry) | ||
380 | { | ||
381 | mlxsw_sp_span_entry_deconfigure_common(span_entry, | ||
382 | MLXSW_REG_MPAT_SPAN_TYPE_REMOTE_ETH_L3); | ||
383 | } | ||
384 | |||
385 | static const | ||
386 | struct mlxsw_sp_span_entry_ops mlxsw_sp_span_entry_ops_gretap6 = { | ||
387 | .can_handle = is_ip6gretap_dev, | ||
388 | .parms = mlxsw_sp_span_entry_gretap6_parms, | ||
389 | .configure = mlxsw_sp_span_entry_gretap6_configure, | ||
390 | .deconfigure = mlxsw_sp_span_entry_gretap6_deconfigure, | ||
391 | }; | ||
392 | |||
293 | static const | 393 | static const |
294 | struct mlxsw_sp_span_entry_ops *const mlxsw_sp_span_entry_types[] = { | 394 | struct mlxsw_sp_span_entry_ops *const mlxsw_sp_span_entry_types[] = { |
295 | &mlxsw_sp_span_entry_ops_phys, | 395 | &mlxsw_sp_span_entry_ops_phys, |
296 | &mlxsw_sp_span_entry_ops_gretap4, | 396 | &mlxsw_sp_span_entry_ops_gretap4, |
397 | &mlxsw_sp_span_entry_ops_gretap6, | ||
297 | }; | 398 | }; |
298 | 399 | ||
299 | static int | 400 | static int |