aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPetr Machata <petrm@mellanox.com>2018-02-27 08:53:49 -0500
committerDavid S. Miller <davem@davemloft.net>2018-02-27 14:46:28 -0500
commit8f08a528de5eaded034c5480588722e7dc167540 (patch)
tree69f007862fe11de8dadd24a81e0023e05450b979
parent27cf76fe60ec6fbe2ba8844261b90a6aecbc42f0 (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/Kconfig2
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c101
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
295static struct net_device *
296mlxsw_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
323out:
324 dst_release(dst);
325 return dev;
326}
327
328static int
329mlxsw_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
355static int
356mlxsw_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
378static void
379mlxsw_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
385static const
386struct 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
293static const 393static const
294struct mlxsw_sp_span_entry_ops *const mlxsw_sp_span_entry_types[] = { 394struct 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
299static int 400static int