* [patch net-next 00/15] mlxsw: Offloading encapsulated SPAN
@ 2018-02-27 13:53 Jiri Pirko
2018-02-27 13:53 ` [patch net-next 01/15] mlxsw: spectrum_ipip: Extract mlxsw_sp_l3addr_is_zero Jiri Pirko
` (15 more replies)
0 siblings, 16 replies; 20+ messages in thread
From: Jiri Pirko @ 2018-02-27 13:53 UTC (permalink / raw)
To: netdev; +Cc: davem, petrm, idosch, mlxsw, xeb, dsa
From: Jiri Pirko <jiri@mellanox.com>
Petr says:
This patch series introduces support for mirroring with GRE
encapsulation. It offloads tc action mirred mirror from a mlxsw port to
either a gretap or an ip6gretap netdevice.
Spectrum hardware needs to know all the details of the requested
encapsulation: source and destination MAC and IP addresses, details of
VLAN tagging, etc. The only variables are the encapsulated packet
itself, and TOS field, which may be inherited. To that end, mlxsw driver
resolves the route that encapsulated packets would take, queries the
corresponding neighbor, and with that configuration in hand, configures
the mirroring in the hardware.
The driver also hooks into event handlers for netdevice changes, FIB and
neighbor events, and reconsiders the configuration on each such change.
When the new configuration differs from the currently-offloaded one, the
existing offload is removed and replaced with a new one.
It is possible to mirror to {ip6,}gretap from a matchall rule as well as
from a flower match.
** Note that with this patch set, mlxsw build depends on NET_IPGRE and
IPV6_GRE.
Current limitations:
- There has to be a route that directs packets to an mlxsw port. We
intend to extend the logic to support other netdevice types in the
future, but the eventual egress netdevice will have to be an mlxsw
port in any case.
- Offload reconfiguration due to changes in netdevice configuration
creates a window of time where packets are not mirrored. Under some
circumstances this can be prevented by configuring an unused port
analyzer and migrating mirrors over to that. However that's currently
not implemented.
- Remote address of a tunnel device needs to be set, there may not be a
GRE key, checksumming or sequence numbers, and TTL needs to be fixed
(non-inherit). These are hard requirements imposed by the underlying
hardware.
- TOS of a tunnel device needs to be "inherit". The hardware supports a
fixed TOS, but that's currently not implemented.
The series start with two patches, #1 and #2, that publish one function
and add support for querying IPv6 tunnel parameters.
In patches #3 and #4, we introduce helpers to GRE and tunneling code
that we will use later in the patchset from the SPAN code.
Patches #5 and #6 introduce support for encapsulated SPAN in reg.h.
The following seven patches, #7-#13, then prepare the SPAN codebase for
introduction of mirroring to netdevices that don't correspond to front
panel ports.
Then #14 and #15 pull all this together to implement mirroring to
{ip6,}gretap netdevices.
Petr Machata (15):
mlxsw: spectrum_ipip: Extract mlxsw_sp_l3addr_is_zero
mlxsw: spectrum_ipip: Support decoding IPv6 tunnel addresses
net: GRE: Add is_gretap_dev, is_ip6gretap_dev
ip_tunnel: Rename & publish init_tunnel_flow
mlxsw: reg: Add SPAN encapsulation to MPAT register
mlxsw: reg: Extend mlxsw_reg_mpat_pack()
mlxsw: span: Remove span_entry by span_id
mlxsw: spectrum_span: Initialize span_entry.id eagerly
mlxsw: spectrum_span: Extract mlxsw_sp_span_entry_{de,}configure()
mlxsw: spectrum: Keep mirror netdev in mlxsw_sp_span_entry
mlxsw: spectrum_span: Generalize SPAN support
mlxsw: Handle config changes pertinent to SPAN
mlxsw: Move a mirroring check to mlxsw_sp_span_entry_create
mlxsw: spectrum_span: Support mirror to gretap
mlxsw: spectrum_span: Support mirror to ip6gretap
drivers/net/ethernet/mellanox/mlxsw/Kconfig | 4 +
.../mellanox/mlxsw/core_acl_flex_actions.c | 19 +-
.../mellanox/mlxsw/core_acl_flex_actions.h | 9 +-
drivers/net/ethernet/mellanox/mlxsw/reg.h | 145 +++++-
drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 50 +-
drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 2 +-
drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c | 9 +-
.../mellanox/mlxsw/spectrum_acl_flex_actions.c | 33 +-
.../net/ethernet/mellanox/mlxsw/spectrum_ipip.c | 45 +-
.../net/ethernet/mellanox/mlxsw/spectrum_ipip.h | 8 +-
.../net/ethernet/mellanox/mlxsw/spectrum_router.c | 7 +
.../net/ethernet/mellanox/mlxsw/spectrum_span.c | 522 +++++++++++++++++++--
.../net/ethernet/mellanox/mlxsw/spectrum_span.h | 41 +-
include/net/gre.h | 3 +
include/net/ip_tunnels.h | 16 +
net/ipv4/ip_gre.c | 6 +
net/ipv4/ip_tunnel.c | 40 +-
net/ipv6/ip6_gre.c | 6 +
18 files changed, 808 insertions(+), 157 deletions(-)
--
2.14.3
^ permalink raw reply [flat|nested] 20+ messages in thread
* [patch net-next 01/15] mlxsw: spectrum_ipip: Extract mlxsw_sp_l3addr_is_zero
2018-02-27 13:53 [patch net-next 00/15] mlxsw: Offloading encapsulated SPAN Jiri Pirko
@ 2018-02-27 13:53 ` Jiri Pirko
2018-02-27 13:53 ` [patch net-next 02/15] mlxsw: spectrum_ipip: Support decoding IPv6 tunnel addresses Jiri Pirko
` (14 subsequent siblings)
15 siblings, 0 replies; 20+ messages in thread
From: Jiri Pirko @ 2018-02-27 13:53 UTC (permalink / raw)
To: netdev; +Cc: davem, petrm, idosch, mlxsw, xeb, dsa
From: Petr Machata <petrm@mellanox.com>
Extract the logic for determining whether a given IPv4/IPv6 address is
all-zeroes from mlxsw_sp_ipip_tunnel_complete to a separate function.
Make that function public within the module.
Signed-off-by: Petr Machata <petrm@mellanox.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.c | 16 +++++++++++-----
drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.h | 6 ++++--
2 files changed, 15 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.c
index a1c4b1e63f8d..0378cccc8182 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.c
@@ -1,7 +1,7 @@
/*
* drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.c
- * Copyright (c) 2017 Mellanox Technologies. All rights reserved.
- * Copyright (c) 2017 Petr Machata <petrm@mellanox.com>
+ * Copyright (c) 2017-2018 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2017-2018 Petr Machata <petrm@mellanox.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -122,6 +122,13 @@ mlxsw_sp_ipip_netdev_daddr(enum mlxsw_sp_l3proto proto,
return (union mlxsw_sp_l3addr) {0};
}
+bool mlxsw_sp_l3addr_is_zero(union mlxsw_sp_l3addr addr)
+{
+ union mlxsw_sp_l3addr naddr = {0};
+
+ return !memcmp(&addr, &naddr, sizeof(naddr));
+}
+
static int
mlxsw_sp_ipip_nexthop_update_gre4(struct mlxsw_sp *mlxsw_sp, u32 adj_index,
struct mlxsw_sp_ipip_entry *ipip_entry)
@@ -215,15 +222,14 @@ static bool mlxsw_sp_ipip_tunnel_complete(enum mlxsw_sp_l3proto proto,
{
union mlxsw_sp_l3addr saddr = mlxsw_sp_ipip_netdev_saddr(proto, ol_dev);
union mlxsw_sp_l3addr daddr = mlxsw_sp_ipip_netdev_daddr(proto, ol_dev);
- union mlxsw_sp_l3addr naddr = {0};
/* Tunnels with unset local or remote address are valid in Linux and
* used for lightweight tunnels (LWT) and Non-Broadcast Multi-Access
* (NBMA) tunnels. In principle these can be offloaded, but the driver
* currently doesn't support this. So punt.
*/
- return memcmp(&saddr, &naddr, sizeof(naddr)) &&
- memcmp(&daddr, &naddr, sizeof(naddr));
+ return !mlxsw_sp_l3addr_is_zero(saddr) &&
+ !mlxsw_sp_l3addr_is_zero(daddr);
}
static bool mlxsw_sp_ipip_can_offload_gre4(const struct mlxsw_sp *mlxsw_sp,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.h
index a4ff5737eccc..888f19000209 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.h
@@ -1,7 +1,7 @@
/*
* drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.h
- * Copyright (c) 2017 Mellanox Technologies. All rights reserved.
- * Copyright (c) 2017 Petr Machata <petrm@mellanox.com>
+ * Copyright (c) 2017-2018 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2017-2018 Petr Machata <petrm@mellanox.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -46,6 +46,8 @@ union mlxsw_sp_l3addr
mlxsw_sp_ipip_netdev_saddr(enum mlxsw_sp_l3proto proto,
const struct net_device *ol_dev);
+bool mlxsw_sp_l3addr_is_zero(union mlxsw_sp_l3addr addr);
+
enum mlxsw_sp_ipip_type {
MLXSW_SP_IPIP_TYPE_GRE4,
MLXSW_SP_IPIP_TYPE_MAX,
--
2.14.3
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [patch net-next 02/15] mlxsw: spectrum_ipip: Support decoding IPv6 tunnel addresses
2018-02-27 13:53 [patch net-next 00/15] mlxsw: Offloading encapsulated SPAN Jiri Pirko
2018-02-27 13:53 ` [patch net-next 01/15] mlxsw: spectrum_ipip: Extract mlxsw_sp_l3addr_is_zero Jiri Pirko
@ 2018-02-27 13:53 ` Jiri Pirko
2018-02-27 13:53 ` [patch net-next 03/15] net: GRE: Add is_gretap_dev, is_ip6gretap_dev Jiri Pirko
` (13 subsequent siblings)
15 siblings, 0 replies; 20+ messages in thread
From: Jiri Pirko @ 2018-02-27 13:53 UTC (permalink / raw)
To: netdev; +Cc: davem, petrm, idosch, mlxsw, xeb, dsa
From: Petr Machata <petrm@mellanox.com>
To support mirroring to ip6gretap, the SPAN module needs to be able to
decode IPv6 addresses specified at that tunnel.
Extend mlxsw_sp_ipip_netdev_saddr() and mlxsw_sp_ipip_netdev_daddr() to
support IPv6 addresses. To that end, add and publish a support function
mlxsw_sp_ipip_netdev_parms6().
Signed-off-by: Petr Machata <petrm@mellanox.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
.../net/ethernet/mellanox/mlxsw/spectrum_ipip.c | 29 ++++++++++++++++++++--
.../net/ethernet/mellanox/mlxsw/spectrum_ipip.h | 2 ++
2 files changed, 29 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.c
index 0378cccc8182..98d896c14b87 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.c
@@ -33,6 +33,7 @@
*/
#include <net/ip_tunnels.h>
+#include <net/ip6_tunnel.h>
#include "spectrum_ipip.h"
@@ -44,6 +45,14 @@ mlxsw_sp_ipip_netdev_parms4(const struct net_device *ol_dev)
return tun->parms;
}
+struct __ip6_tnl_parm
+mlxsw_sp_ipip_netdev_parms6(const struct net_device *ol_dev)
+{
+ struct ip6_tnl *tun = netdev_priv(ol_dev);
+
+ return tun->parms;
+}
+
static bool mlxsw_sp_ipip_parms4_has_ikey(struct ip_tunnel_parm parms)
{
return !!(parms.i_flags & TUNNEL_KEY);
@@ -72,24 +81,38 @@ mlxsw_sp_ipip_parms4_saddr(struct ip_tunnel_parm parms)
return (union mlxsw_sp_l3addr) { .addr4 = parms.iph.saddr };
}
+static union mlxsw_sp_l3addr
+mlxsw_sp_ipip_parms6_saddr(struct __ip6_tnl_parm parms)
+{
+ return (union mlxsw_sp_l3addr) { .addr6 = parms.laddr };
+}
+
static union mlxsw_sp_l3addr
mlxsw_sp_ipip_parms4_daddr(struct ip_tunnel_parm parms)
{
return (union mlxsw_sp_l3addr) { .addr4 = parms.iph.daddr };
}
+static union mlxsw_sp_l3addr
+mlxsw_sp_ipip_parms6_daddr(struct __ip6_tnl_parm parms)
+{
+ return (union mlxsw_sp_l3addr) { .addr6 = parms.raddr };
+}
+
union mlxsw_sp_l3addr
mlxsw_sp_ipip_netdev_saddr(enum mlxsw_sp_l3proto proto,
const struct net_device *ol_dev)
{
struct ip_tunnel_parm parms4;
+ struct __ip6_tnl_parm parms6;
switch (proto) {
case MLXSW_SP_L3_PROTO_IPV4:
parms4 = mlxsw_sp_ipip_netdev_parms4(ol_dev);
return mlxsw_sp_ipip_parms4_saddr(parms4);
case MLXSW_SP_L3_PROTO_IPV6:
- break;
+ parms6 = mlxsw_sp_ipip_netdev_parms6(ol_dev);
+ return mlxsw_sp_ipip_parms6_saddr(parms6);
}
WARN_ON(1);
@@ -109,13 +132,15 @@ mlxsw_sp_ipip_netdev_daddr(enum mlxsw_sp_l3proto proto,
const struct net_device *ol_dev)
{
struct ip_tunnel_parm parms4;
+ struct __ip6_tnl_parm parms6;
switch (proto) {
case MLXSW_SP_L3_PROTO_IPV4:
parms4 = mlxsw_sp_ipip_netdev_parms4(ol_dev);
return mlxsw_sp_ipip_parms4_daddr(parms4);
case MLXSW_SP_L3_PROTO_IPV6:
- break;
+ parms6 = mlxsw_sp_ipip_netdev_parms6(ol_dev);
+ return mlxsw_sp_ipip_parms6_daddr(parms6);
}
WARN_ON(1);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.h
index 888f19000209..6909d867bb59 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.h
@@ -41,6 +41,8 @@
struct ip_tunnel_parm
mlxsw_sp_ipip_netdev_parms4(const struct net_device *ol_dev);
+struct __ip6_tnl_parm
+mlxsw_sp_ipip_netdev_parms6(const struct net_device *ol_dev);
union mlxsw_sp_l3addr
mlxsw_sp_ipip_netdev_saddr(enum mlxsw_sp_l3proto proto,
--
2.14.3
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [patch net-next 03/15] net: GRE: Add is_gretap_dev, is_ip6gretap_dev
2018-02-27 13:53 [patch net-next 00/15] mlxsw: Offloading encapsulated SPAN Jiri Pirko
2018-02-27 13:53 ` [patch net-next 01/15] mlxsw: spectrum_ipip: Extract mlxsw_sp_l3addr_is_zero Jiri Pirko
2018-02-27 13:53 ` [patch net-next 02/15] mlxsw: spectrum_ipip: Support decoding IPv6 tunnel addresses Jiri Pirko
@ 2018-02-27 13:53 ` Jiri Pirko
2018-02-27 13:53 ` [patch net-next 04/15] ip_tunnel: Rename & publish init_tunnel_flow Jiri Pirko
` (12 subsequent siblings)
15 siblings, 0 replies; 20+ messages in thread
From: Jiri Pirko @ 2018-02-27 13:53 UTC (permalink / raw)
To: netdev; +Cc: davem, petrm, idosch, mlxsw, xeb, dsa
From: Petr Machata <petrm@mellanox.com>
Determining whether a device is a GRE device is easily done by
inspecting struct net_device.type. However, for the tap variants, the
type is just ARPHRD_ETHER.
Therefore introduce two predicate functions that use netdev_ops to tell
the tap devices.
Signed-off-by: Petr Machata <petrm@mellanox.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
include/net/gre.h | 3 +++
net/ipv4/ip_gre.c | 6 ++++++
net/ipv6/ip6_gre.c | 6 ++++++
3 files changed, 15 insertions(+)
diff --git a/include/net/gre.h b/include/net/gre.h
index f90585decbce..797142eee9cd 100644
--- a/include/net/gre.h
+++ b/include/net/gre.h
@@ -37,6 +37,9 @@ struct net_device *gretap_fb_dev_create(struct net *net, const char *name,
int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi,
bool *csum_err, __be16 proto, int nhs);
+bool is_gretap_dev(const struct net_device *dev);
+bool is_ip6gretap_dev(const struct net_device *dev);
+
static inline int gre_calc_hlen(__be16 o_flags)
{
int addend = 4;
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 45d97e9b2759..8050be9f6b51 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -1322,6 +1322,12 @@ static void ipgre_tap_setup(struct net_device *dev)
ip_tunnel_setup(dev, gre_tap_net_id);
}
+bool is_gretap_dev(const struct net_device *dev)
+{
+ return dev->netdev_ops == &gre_tap_netdev_ops;
+}
+EXPORT_SYMBOL_GPL(is_gretap_dev);
+
static int ipgre_newlink(struct net *src_net, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index 3c353125546d..0bdd74d4e9c9 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -1784,6 +1784,12 @@ static void ip6gre_tap_setup(struct net_device *dev)
netif_keep_dst(dev);
}
+bool is_ip6gretap_dev(const struct net_device *dev)
+{
+ return dev->netdev_ops == &ip6gre_tap_netdev_ops;
+}
+EXPORT_SYMBOL_GPL(is_ip6gretap_dev);
+
static bool ip6gre_netlink_encap_parms(struct nlattr *data[],
struct ip_tunnel_encap *ipencap)
{
--
2.14.3
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [patch net-next 04/15] ip_tunnel: Rename & publish init_tunnel_flow
2018-02-27 13:53 [patch net-next 00/15] mlxsw: Offloading encapsulated SPAN Jiri Pirko
` (2 preceding siblings ...)
2018-02-27 13:53 ` [patch net-next 03/15] net: GRE: Add is_gretap_dev, is_ip6gretap_dev Jiri Pirko
@ 2018-02-27 13:53 ` Jiri Pirko
2018-02-27 13:53 ` [patch net-next 05/15] mlxsw: reg: Add SPAN encapsulation to MPAT register Jiri Pirko
` (11 subsequent siblings)
15 siblings, 0 replies; 20+ messages in thread
From: Jiri Pirko @ 2018-02-27 13:53 UTC (permalink / raw)
To: netdev; +Cc: davem, petrm, idosch, mlxsw, xeb, dsa
From: Petr Machata <petrm@mellanox.com>
Initializing struct flowi4 is useful for drivers that need to emulate
routing decisions made by a tunnel interface. Publish the
function (appropriately renamed) so that the drivers in question don't
need to cut'n'paste it around.
Signed-off-by: Petr Machata <petrm@mellanox.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
include/net/ip_tunnels.h | 16 ++++++++++++++++
net/ipv4/ip_tunnel.c | 40 ++++++++++++----------------------------
2 files changed, 28 insertions(+), 28 deletions(-)
diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
index 1f16773cfd76..cbe5addb9293 100644
--- a/include/net/ip_tunnels.h
+++ b/include/net/ip_tunnels.h
@@ -254,6 +254,22 @@ static inline __be32 tunnel_id_to_key32(__be64 tun_id)
#ifdef CONFIG_INET
+static inline void ip_tunnel_init_flow(struct flowi4 *fl4,
+ int proto,
+ __be32 daddr, __be32 saddr,
+ __be32 key, __u8 tos, int oif,
+ __u32 mark)
+{
+ memset(fl4, 0, sizeof(*fl4));
+ fl4->flowi4_oif = oif;
+ fl4->daddr = daddr;
+ fl4->saddr = saddr;
+ fl4->flowi4_tos = tos;
+ fl4->flowi4_proto = proto;
+ fl4->fl4_gre_key = key;
+ fl4->flowi4_mark = mark;
+}
+
int ip_tunnel_init(struct net_device *dev);
void ip_tunnel_uninit(struct net_device *dev);
void ip_tunnel_dellink(struct net_device *dev, struct list_head *head);
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
index d786a8441bce..b2117d89bc83 100644
--- a/net/ipv4/ip_tunnel.c
+++ b/net/ipv4/ip_tunnel.c
@@ -290,22 +290,6 @@ static struct net_device *__ip_tunnel_create(struct net *net,
return ERR_PTR(err);
}
-static inline void init_tunnel_flow(struct flowi4 *fl4,
- int proto,
- __be32 daddr, __be32 saddr,
- __be32 key, __u8 tos, int oif,
- __u32 mark)
-{
- memset(fl4, 0, sizeof(*fl4));
- fl4->flowi4_oif = oif;
- fl4->daddr = daddr;
- fl4->saddr = saddr;
- fl4->flowi4_tos = tos;
- fl4->flowi4_proto = proto;
- fl4->fl4_gre_key = key;
- fl4->flowi4_mark = mark;
-}
-
static int ip_tunnel_bind_dev(struct net_device *dev)
{
struct net_device *tdev = NULL;
@@ -322,10 +306,10 @@ static int ip_tunnel_bind_dev(struct net_device *dev)
struct flowi4 fl4;
struct rtable *rt;
- init_tunnel_flow(&fl4, iph->protocol, iph->daddr,
- iph->saddr, tunnel->parms.o_key,
- RT_TOS(iph->tos), tunnel->parms.link,
- tunnel->fwmark);
+ ip_tunnel_init_flow(&fl4, iph->protocol, iph->daddr,
+ iph->saddr, tunnel->parms.o_key,
+ RT_TOS(iph->tos), tunnel->parms.link,
+ tunnel->fwmark);
rt = ip_route_output_key(tunnel->net, &fl4);
if (!IS_ERR(rt)) {
@@ -581,8 +565,8 @@ void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, u8 proto)
else if (skb->protocol == htons(ETH_P_IPV6))
tos = ipv6_get_dsfield((const struct ipv6hdr *)inner_iph);
}
- init_tunnel_flow(&fl4, proto, key->u.ipv4.dst, key->u.ipv4.src, 0,
- RT_TOS(tos), tunnel->parms.link, tunnel->fwmark);
+ ip_tunnel_init_flow(&fl4, proto, key->u.ipv4.dst, key->u.ipv4.src, 0,
+ RT_TOS(tos), tunnel->parms.link, tunnel->fwmark);
if (tunnel->encap.type != TUNNEL_ENCAP_NONE)
goto tx_error;
rt = ip_route_output_key(tunnel->net, &fl4);
@@ -711,14 +695,14 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
}
if (tunnel->fwmark) {
- init_tunnel_flow(&fl4, protocol, dst, tnl_params->saddr,
- tunnel->parms.o_key, RT_TOS(tos), tunnel->parms.link,
- tunnel->fwmark);
+ ip_tunnel_init_flow(&fl4, protocol, dst, tnl_params->saddr,
+ tunnel->parms.o_key, RT_TOS(tos),
+ tunnel->parms.link, tunnel->fwmark);
}
else {
- init_tunnel_flow(&fl4, protocol, dst, tnl_params->saddr,
- tunnel->parms.o_key, RT_TOS(tos), tunnel->parms.link,
- skb->mark);
+ ip_tunnel_init_flow(&fl4, protocol, dst, tnl_params->saddr,
+ tunnel->parms.o_key, RT_TOS(tos),
+ tunnel->parms.link, skb->mark);
}
if (ip_tunnel_encap(skb, tunnel, &protocol, &fl4) < 0)
--
2.14.3
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [patch net-next 05/15] mlxsw: reg: Add SPAN encapsulation to MPAT register
2018-02-27 13:53 [patch net-next 00/15] mlxsw: Offloading encapsulated SPAN Jiri Pirko
` (3 preceding siblings ...)
2018-02-27 13:53 ` [patch net-next 04/15] ip_tunnel: Rename & publish init_tunnel_flow Jiri Pirko
@ 2018-02-27 13:53 ` Jiri Pirko
2018-02-27 13:53 ` [patch net-next 06/15] mlxsw: reg: Extend mlxsw_reg_mpat_pack() Jiri Pirko
` (10 subsequent siblings)
15 siblings, 0 replies; 20+ messages in thread
From: Jiri Pirko @ 2018-02-27 13:53 UTC (permalink / raw)
To: netdev; +Cc: davem, petrm, idosch, mlxsw, xeb, dsa
From: Petr Machata <petrm@mellanox.com>
MPAT Register is used to query and configure the Switch Port Analyzer
Table. To configure Port Analyzer to encapsulate mirrored packets,
additional fields need to be specified for the MPAT register.
Signed-off-by: Petr Machata <petrm@mellanox.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
drivers/net/ethernet/mellanox/mlxsw/reg.h | 141 +++++++++++++++++++++++++++++-
1 file changed, 139 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h
index 0e08be41c8e0..2aaccbac3ed1 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h
@@ -1,11 +1,11 @@
/*
* drivers/net/ethernet/mellanox/mlxsw/reg.h
- * Copyright (c) 2015-2017 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2015-2018 Mellanox Technologies. All rights reserved.
* Copyright (c) 2015-2016 Ido Schimmel <idosch@mellanox.com>
* Copyright (c) 2015 Elad Raz <eladr@mellanox.com>
* Copyright (c) 2015-2017 Jiri Pirko <jiri@mellanox.com>
* Copyright (c) 2016 Yotam Gigi <yotamg@mellanox.com>
- * Copyright (c) 2017 Petr Machata <petrm@mellanox.com>
+ * Copyright (c) 2017-2018 Petr Machata <petrm@mellanox.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -6772,6 +6772,101 @@ MLXSW_ITEM32(reg, mpat, qos, 0x04, 26, 1);
*/
MLXSW_ITEM32(reg, mpat, be, 0x04, 25, 1);
+enum mlxsw_reg_mpat_span_type {
+ /* Local SPAN Ethernet.
+ * The original packet is not encapsulated.
+ */
+ MLXSW_REG_MPAT_SPAN_TYPE_LOCAL_ETH = 0x0,
+
+ /* Encapsulated Remote SPAN Ethernet L3 GRE.
+ * The packet is encapsulated with GRE header.
+ */
+ MLXSW_REG_MPAT_SPAN_TYPE_REMOTE_ETH_L3 = 0x3,
+};
+
+/* reg_mpat_span_type
+ * SPAN type.
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, mpat, span_type, 0x04, 0, 4);
+
+/* Remote SPAN - Ethernet VLAN
+ * - - - - - - - - - - - - - -
+ */
+
+/* reg_mpat_eth_rspan_vid
+ * Encapsulation header VLAN ID.
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, mpat, eth_rspan_vid, 0x18, 0, 12);
+
+/* Encapsulated Remote SPAN - Ethernet L2
+ * - - - - - - - - - - - - - - - - - - -
+ */
+
+enum mlxsw_reg_mpat_eth_rspan_version {
+ MLXSW_REG_MPAT_ETH_RSPAN_VERSION_NO_HEADER = 15,
+};
+
+/* reg_mpat_eth_rspan_version
+ * RSPAN mirror header version.
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, mpat, eth_rspan_version, 0x10, 18, 4);
+
+/* reg_mpat_eth_rspan_mac
+ * Destination MAC address.
+ * Access: RW
+ */
+MLXSW_ITEM_BUF(reg, mpat, eth_rspan_mac, 0x12, 6);
+
+/* reg_mpat_eth_rspan_tp
+ * Tag Packet. Indicates whether the mirroring header should be VLAN tagged.
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, mpat, eth_rspan_tp, 0x18, 16, 1);
+
+/* Encapsulated Remote SPAN - Ethernet L3
+ * - - - - - - - - - - - - - - - - - - -
+ */
+
+enum mlxsw_reg_mpat_eth_rspan_protocol {
+ MLXSW_REG_MPAT_ETH_RSPAN_PROTOCOL_IPV4,
+ MLXSW_REG_MPAT_ETH_RSPAN_PROTOCOL_IPV6,
+};
+
+/* reg_mpat_eth_rspan_protocol
+ * SPAN encapsulation protocol.
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, mpat, eth_rspan_protocol, 0x18, 24, 4);
+
+/* reg_mpat_eth_rspan_ttl
+ * Encapsulation header Time-to-Live/HopLimit.
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, mpat, eth_rspan_ttl, 0x1C, 4, 8);
+
+/* reg_mpat_eth_rspan_smac
+ * Source MAC address
+ * Access: RW
+ */
+MLXSW_ITEM_BUF(reg, mpat, eth_rspan_smac, 0x22, 6);
+
+/* reg_mpat_eth_rspan_dip*
+ * Destination IP address. The IP version is configured by protocol.
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, mpat, eth_rspan_dip4, 0x4C, 0, 32);
+MLXSW_ITEM_BUF(reg, mpat, eth_rspan_dip6, 0x40, 16);
+
+/* reg_mpat_eth_rspan_sip*
+ * Source IP address. The IP version is configured by protocol.
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, mpat, eth_rspan_sip4, 0x5C, 0, 32);
+MLXSW_ITEM_BUF(reg, mpat, eth_rspan_sip6, 0x50, 16);
+
static inline void mlxsw_reg_mpat_pack(char *payload, u8 pa_id,
u16 system_port, bool e)
{
@@ -6783,6 +6878,48 @@ static inline void mlxsw_reg_mpat_pack(char *payload, u8 pa_id,
mlxsw_reg_mpat_be_set(payload, 1);
}
+static inline void mlxsw_reg_mpat_eth_rspan_pack(char *payload, u16 vid)
+{
+ mlxsw_reg_mpat_eth_rspan_vid_set(payload, vid);
+}
+
+static inline void
+mlxsw_reg_mpat_eth_rspan_l2_pack(char *payload,
+ enum mlxsw_reg_mpat_eth_rspan_version version,
+ const char *mac,
+ bool tp)
+{
+ mlxsw_reg_mpat_eth_rspan_version_set(payload, version);
+ mlxsw_reg_mpat_eth_rspan_mac_memcpy_to(payload, mac);
+ mlxsw_reg_mpat_eth_rspan_tp_set(payload, tp);
+}
+
+static inline void
+mlxsw_reg_mpat_eth_rspan_l3_ipv4_pack(char *payload, u8 ttl,
+ const char *smac,
+ u32 sip, u32 dip)
+{
+ mlxsw_reg_mpat_eth_rspan_ttl_set(payload, ttl);
+ mlxsw_reg_mpat_eth_rspan_smac_memcpy_to(payload, smac);
+ mlxsw_reg_mpat_eth_rspan_protocol_set(payload,
+ MLXSW_REG_MPAT_ETH_RSPAN_PROTOCOL_IPV4);
+ mlxsw_reg_mpat_eth_rspan_sip4_set(payload, sip);
+ mlxsw_reg_mpat_eth_rspan_dip4_set(payload, dip);
+}
+
+static inline void
+mlxsw_reg_mpat_eth_rspan_l3_ipv6_pack(char *payload, u8 ttl,
+ const char *smac,
+ struct in6_addr sip, struct in6_addr dip)
+{
+ mlxsw_reg_mpat_eth_rspan_ttl_set(payload, ttl);
+ mlxsw_reg_mpat_eth_rspan_smac_memcpy_to(payload, smac);
+ mlxsw_reg_mpat_eth_rspan_protocol_set(payload,
+ MLXSW_REG_MPAT_ETH_RSPAN_PROTOCOL_IPV6);
+ mlxsw_reg_mpat_eth_rspan_sip6_memcpy_to(payload, (void *)&sip);
+ mlxsw_reg_mpat_eth_rspan_dip6_memcpy_to(payload, (void *)&dip);
+}
+
/* MPAR - Monitoring Port Analyzer Register
* ----------------------------------------
* MPAR register is used to query and configure the port analyzer port mirroring
--
2.14.3
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [patch net-next 06/15] mlxsw: reg: Extend mlxsw_reg_mpat_pack()
2018-02-27 13:53 [patch net-next 00/15] mlxsw: Offloading encapsulated SPAN Jiri Pirko
` (4 preceding siblings ...)
2018-02-27 13:53 ` [patch net-next 05/15] mlxsw: reg: Add SPAN encapsulation to MPAT register Jiri Pirko
@ 2018-02-27 13:53 ` Jiri Pirko
2018-02-27 13:53 ` [patch net-next 07/15] mlxsw: span: Remove span_entry by span_id Jiri Pirko
` (9 subsequent siblings)
15 siblings, 0 replies; 20+ messages in thread
From: Jiri Pirko @ 2018-02-27 13:53 UTC (permalink / raw)
To: netdev; +Cc: davem, petrm, idosch, mlxsw, xeb, dsa
From: Petr Machata <petrm@mellanox.com>
To support encapsulated SPAN, extend mlxsw_reg_mpat_pack() with a field
to set the SPAN type.
Signed-off-by: Petr Machata <petrm@mellanox.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
drivers/net/ethernet/mellanox/mlxsw/reg.h | 4 +++-
drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c | 6 ++++--
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h
index 2aaccbac3ed1..cb5f77f09f8e 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h
@@ -6868,7 +6868,8 @@ MLXSW_ITEM32(reg, mpat, eth_rspan_sip4, 0x5C, 0, 32);
MLXSW_ITEM_BUF(reg, mpat, eth_rspan_sip6, 0x50, 16);
static inline void mlxsw_reg_mpat_pack(char *payload, u8 pa_id,
- u16 system_port, bool e)
+ u16 system_port, bool e,
+ enum mlxsw_reg_mpat_span_type span_type)
{
MLXSW_REG_ZERO(mpat, payload);
mlxsw_reg_mpat_pa_id_set(payload, pa_id);
@@ -6876,6 +6877,7 @@ static inline void mlxsw_reg_mpat_pack(char *payload, u8 pa_id,
mlxsw_reg_mpat_e_set(payload, e);
mlxsw_reg_mpat_qos_set(payload, 1);
mlxsw_reg_mpat_be_set(payload, 1);
+ mlxsw_reg_mpat_span_type_set(payload, span_type);
}
static inline void mlxsw_reg_mpat_eth_rspan_pack(char *payload, u16 vid)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
index c3bec37d71ed..1433d4890b88 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
@@ -93,7 +93,8 @@ mlxsw_sp_span_entry_create(struct mlxsw_sp_port *port)
return NULL;
/* create a new port analayzer entry for local_port */
- mlxsw_reg_mpat_pack(mpat_pl, index, local_port, true);
+ mlxsw_reg_mpat_pack(mpat_pl, index, local_port, true,
+ MLXSW_REG_MPAT_SPAN_TYPE_LOCAL_ETH);
err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpat), mpat_pl);
if (err)
return NULL;
@@ -111,7 +112,8 @@ static void mlxsw_sp_span_entry_destroy(struct mlxsw_sp *mlxsw_sp,
char mpat_pl[MLXSW_REG_MPAT_LEN];
int pa_id = span_entry->id;
- mlxsw_reg_mpat_pack(mpat_pl, pa_id, local_port, false);
+ mlxsw_reg_mpat_pack(mpat_pl, pa_id, local_port, false,
+ MLXSW_REG_MPAT_SPAN_TYPE_LOCAL_ETH);
mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpat), mpat_pl);
}
--
2.14.3
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [patch net-next 07/15] mlxsw: span: Remove span_entry by span_id
2018-02-27 13:53 [patch net-next 00/15] mlxsw: Offloading encapsulated SPAN Jiri Pirko
` (5 preceding siblings ...)
2018-02-27 13:53 ` [patch net-next 06/15] mlxsw: reg: Extend mlxsw_reg_mpat_pack() Jiri Pirko
@ 2018-02-27 13:53 ` Jiri Pirko
2018-02-27 13:53 ` [patch net-next 08/15] mlxsw: spectrum_span: Initialize span_entry.id eagerly Jiri Pirko
` (8 subsequent siblings)
15 siblings, 0 replies; 20+ messages in thread
From: Jiri Pirko @ 2018-02-27 13:53 UTC (permalink / raw)
To: netdev; +Cc: davem, petrm, idosch, mlxsw, xeb, dsa
From: Petr Machata <petrm@mellanox.com>
Instead of removing span_entry by the port number, allow removing by
SPAN id. That simplifies some code right here, and for mirroring to soft
netdevices, avoids problems with netdevice pointer invalidation and
reuse.
Rename mlxsw_sp_span_entry_find() to mlxsw_sp_span_entry_find_by_port()
and keep it--follow-up patches will make use of it.
Signed-off-by: Petr Machata <petrm@mellanox.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
.../mellanox/mlxsw/core_acl_flex_actions.c | 6 ++---
.../mellanox/mlxsw/core_acl_flex_actions.h | 2 +-
drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 5 ++--
drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 2 +-
.../mellanox/mlxsw/spectrum_acl_flex_actions.c | 27 ++++----------------
.../net/ethernet/mellanox/mlxsw/spectrum_span.c | 29 ++++++++++++++++------
.../net/ethernet/mellanox/mlxsw/spectrum_span.h | 7 +++---
7 files changed, 37 insertions(+), 41 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c
index b698fb481b2e..d1c2d85f396d 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c
@@ -1,6 +1,6 @@
/*
* drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c
- * Copyright (c) 2017 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2017, 2018 Mellanox Technologies. All rights reserved.
* Copyright (c) 2017 Jiri Pirko <jiri@mellanox.com>
*
* Redistribution and use in source and binary forms, with or without
@@ -838,7 +838,6 @@ struct mlxsw_afa_mirror {
struct mlxsw_afa_resource resource;
int span_id;
u8 local_in_port;
- u8 local_out_port;
bool ingress;
};
@@ -848,7 +847,7 @@ mlxsw_afa_mirror_destroy(struct mlxsw_afa_block *block,
{
block->afa->ops->mirror_del(block->afa->ops_priv,
mirror->local_in_port,
- mirror->local_out_port,
+ mirror->span_id,
mirror->ingress);
kfree(mirror);
}
@@ -882,7 +881,6 @@ mlxsw_afa_mirror_create(struct mlxsw_afa_block *block,
goto err_mirror_add;
mirror->ingress = ingress;
- mirror->local_out_port = local_out_port;
mirror->local_in_port = local_in_port;
mirror->resource.destructor = mlxsw_afa_mirror_destructor;
mlxsw_afa_resource_add(block, &mirror->resource);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.h b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.h
index 43132293475c..4e991ca6dce5 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.h
@@ -50,7 +50,7 @@ struct mlxsw_afa_ops {
void (*counter_index_put)(void *priv, unsigned int counter_index);
int (*mirror_add)(void *priv, u8 locol_in_port, u8 local_out_port,
bool ingress, int *p_span_id);
- void (*mirror_del)(void *priv, u8 locol_in_port, u8 local_out_port,
+ void (*mirror_del)(void *priv, u8 local_in_port, int span_id,
bool ingress);
};
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index bfde93910f82..10bb4891ec31 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -1273,11 +1273,10 @@ mlxsw_sp_port_add_cls_matchall_mirror(struct mlxsw_sp_port *mlxsw_sp_port,
}
to_port = netdev_priv(to_dev);
- mirror->to_local_port = to_port->local_port;
mirror->ingress = ingress;
span_type = ingress ? MLXSW_SP_SPAN_INGRESS : MLXSW_SP_SPAN_EGRESS;
return mlxsw_sp_span_mirror_add(mlxsw_sp_port, to_port, span_type,
- true);
+ true, &mirror->span_id);
}
static void
@@ -1288,7 +1287,7 @@ mlxsw_sp_port_del_cls_matchall_mirror(struct mlxsw_sp_port *mlxsw_sp_port,
span_type = mirror->ingress ?
MLXSW_SP_SPAN_INGRESS : MLXSW_SP_SPAN_EGRESS;
- mlxsw_sp_span_mirror_del(mlxsw_sp_port, mirror->to_local_port,
+ mlxsw_sp_span_mirror_del(mlxsw_sp_port, mirror->span_id,
span_type, true);
}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
index 675e03a892ed..2673310f92da 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h
@@ -124,7 +124,7 @@ enum mlxsw_sp_port_mall_action_type {
};
struct mlxsw_sp_port_mall_mirror_tc_entry {
- u8 to_local_port;
+ int span_id;
bool ingress;
};
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_actions.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_actions.c
index f7e61cecc42b..b450d3e4a905 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_actions.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_actions.c
@@ -1,6 +1,6 @@
/*
* drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_actions.c
- * Copyright (c) 2017 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2017, 2018 Mellanox Technologies. All rights reserved.
* Copyright (c) 2017 Jiri Pirko <jiri@mellanox.com>
* Copyright (c) 2017 Yotam Gigi <yotamg@mellanox.com>
*
@@ -130,36 +130,19 @@ mlxsw_sp_act_mirror_add(void *priv, u8 local_in_port, u8 local_out_port,
bool ingress, int *p_span_id)
{
struct mlxsw_sp_port *in_port, *out_port;
- struct mlxsw_sp_span_entry *span_entry;
struct mlxsw_sp *mlxsw_sp = priv;
enum mlxsw_sp_span_type type;
- int err;
type = ingress ? MLXSW_SP_SPAN_INGRESS : MLXSW_SP_SPAN_EGRESS;
out_port = mlxsw_sp->ports[local_out_port];
in_port = mlxsw_sp->ports[local_in_port];
- err = mlxsw_sp_span_mirror_add(in_port, out_port, type, false);
- if (err)
- return err;
-
- span_entry = mlxsw_sp_span_entry_find(mlxsw_sp, local_out_port);
- if (!span_entry) {
- err = -ENOENT;
- goto err_span_entry_find;
- }
-
- *p_span_id = span_entry->id;
- return 0;
-
-err_span_entry_find:
- mlxsw_sp_span_mirror_del(in_port, local_out_port, type, false);
- return err;
+ return mlxsw_sp_span_mirror_add(in_port, out_port, type,
+ false, p_span_id);
}
static void
-mlxsw_sp_act_mirror_del(void *priv, u8 local_in_port, u8 local_out_port,
- bool ingress)
+mlxsw_sp_act_mirror_del(void *priv, u8 local_in_port, int span_id, bool ingress)
{
struct mlxsw_sp *mlxsw_sp = priv;
struct mlxsw_sp_port *in_port;
@@ -168,7 +151,7 @@ mlxsw_sp_act_mirror_del(void *priv, u8 local_in_port, u8 local_out_port,
type = ingress ? MLXSW_SP_SPAN_INGRESS : MLXSW_SP_SPAN_EGRESS;
in_port = mlxsw_sp->ports[local_in_port];
- mlxsw_sp_span_mirror_del(in_port, local_out_port, type, false);
+ mlxsw_sp_span_mirror_del(in_port, span_id, type, false);
}
static const struct mlxsw_afa_ops mlxsw_sp_act_afa_ops = {
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
index 1433d4890b88..9e596b064582 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
@@ -118,7 +118,7 @@ static void mlxsw_sp_span_entry_destroy(struct mlxsw_sp *mlxsw_sp,
}
struct mlxsw_sp_span_entry *
-mlxsw_sp_span_entry_find(struct mlxsw_sp *mlxsw_sp, u8 local_port)
+mlxsw_sp_span_entry_find_by_port(struct mlxsw_sp *mlxsw_sp, u8 local_port)
{
int i;
@@ -131,13 +131,27 @@ mlxsw_sp_span_entry_find(struct mlxsw_sp *mlxsw_sp, u8 local_port)
return NULL;
}
+static struct mlxsw_sp_span_entry *
+mlxsw_sp_span_entry_find_by_id(struct mlxsw_sp *mlxsw_sp, int span_id)
+{
+ int i;
+
+ for (i = 0; i < mlxsw_sp->span.entries_count; i++) {
+ struct mlxsw_sp_span_entry *curr = &mlxsw_sp->span.entries[i];
+
+ if (curr->ref_count && curr->id == span_id)
+ return curr;
+ }
+ return NULL;
+}
+
static struct mlxsw_sp_span_entry *
mlxsw_sp_span_entry_get(struct mlxsw_sp_port *port)
{
struct mlxsw_sp_span_entry *span_entry;
- span_entry = mlxsw_sp_span_entry_find(port->mlxsw_sp,
- port->local_port);
+ span_entry = mlxsw_sp_span_entry_find_by_port(port->mlxsw_sp,
+ port->local_port);
if (span_entry) {
/* Already exists, just take a reference */
span_entry->ref_count++;
@@ -316,7 +330,8 @@ mlxsw_sp_span_inspected_port_del(struct mlxsw_sp_port *port,
int mlxsw_sp_span_mirror_add(struct mlxsw_sp_port *from,
struct mlxsw_sp_port *to,
- enum mlxsw_sp_span_type type, bool bind)
+ enum mlxsw_sp_span_type type, bool bind,
+ int *p_span_id)
{
struct mlxsw_sp *mlxsw_sp = from->mlxsw_sp;
struct mlxsw_sp_span_entry *span_entry;
@@ -333,6 +348,7 @@ int mlxsw_sp_span_mirror_add(struct mlxsw_sp_port *from,
if (err)
goto err_port_bind;
+ *p_span_id = span_entry->id;
return 0;
err_port_bind:
@@ -340,13 +356,12 @@ int mlxsw_sp_span_mirror_add(struct mlxsw_sp_port *from,
return err;
}
-void mlxsw_sp_span_mirror_del(struct mlxsw_sp_port *from, u8 destination_port,
+void mlxsw_sp_span_mirror_del(struct mlxsw_sp_port *from, int span_id,
enum mlxsw_sp_span_type type, bool bind)
{
struct mlxsw_sp_span_entry *span_entry;
- span_entry = mlxsw_sp_span_entry_find(from->mlxsw_sp,
- destination_port);
+ span_entry = mlxsw_sp_span_entry_find_by_id(from->mlxsw_sp, span_id);
if (!span_entry) {
netdev_err(from->dev, "no span entry found\n");
return;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.h
index 069050e385ff..02dedf2fcd3f 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.h
@@ -62,11 +62,12 @@ void mlxsw_sp_span_fini(struct mlxsw_sp *mlxsw_sp);
int mlxsw_sp_span_mirror_add(struct mlxsw_sp_port *from,
struct mlxsw_sp_port *to,
- enum mlxsw_sp_span_type type, bool bind);
-void mlxsw_sp_span_mirror_del(struct mlxsw_sp_port *from, u8 destination_port,
+ enum mlxsw_sp_span_type type,
+ bool bind, int *p_span_id);
+void mlxsw_sp_span_mirror_del(struct mlxsw_sp_port *from, int span_id,
enum mlxsw_sp_span_type type, bool bind);
struct mlxsw_sp_span_entry *
-mlxsw_sp_span_entry_find(struct mlxsw_sp *mlxsw_sp, u8 local_port);
+mlxsw_sp_span_entry_find_by_port(struct mlxsw_sp *mlxsw_sp, u8 local_port);
int mlxsw_sp_span_port_mtu_update(struct mlxsw_sp_port *port, u16 mtu);
--
2.14.3
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [patch net-next 08/15] mlxsw: spectrum_span: Initialize span_entry.id eagerly
2018-02-27 13:53 [patch net-next 00/15] mlxsw: Offloading encapsulated SPAN Jiri Pirko
` (6 preceding siblings ...)
2018-02-27 13:53 ` [patch net-next 07/15] mlxsw: span: Remove span_entry by span_id Jiri Pirko
@ 2018-02-27 13:53 ` Jiri Pirko
2018-02-27 13:53 ` [patch net-next 09/15] mlxsw: spectrum_span: Extract mlxsw_sp_span_entry_{de,}configure() Jiri Pirko
` (7 subsequent siblings)
15 siblings, 0 replies; 20+ messages in thread
From: Jiri Pirko @ 2018-02-27 13:53 UTC (permalink / raw)
To: netdev; +Cc: davem, petrm, idosch, mlxsw, xeb, dsa
From: Petr Machata <petrm@mellanox.com>
It is known statically ahead of time which SPAN entry will have which
ID. Just initialize it eagerly in mlxsw_sp_span_init(), don't wait until
the entry is actually created. This simplifies some code in
mlxsw_sp_span_entry_create()
Signed-off-by: Petr Machata <petrm@mellanox.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c | 18 +++++++++---------
1 file changed, 9 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
index 9e596b064582..5c87e6dfc5a1 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
@@ -51,8 +51,12 @@ int mlxsw_sp_span_init(struct mlxsw_sp *mlxsw_sp)
if (!mlxsw_sp->span.entries)
return -ENOMEM;
- for (i = 0; i < mlxsw_sp->span.entries_count; i++)
- INIT_LIST_HEAD(&mlxsw_sp->span.entries[i].bound_ports_list);
+ for (i = 0; i < mlxsw_sp->span.entries_count; i++) {
+ struct mlxsw_sp_span_entry *curr = &mlxsw_sp->span.entries[i];
+
+ INIT_LIST_HEAD(&curr->bound_ports_list);
+ curr->id = i;
+ }
return 0;
}
@@ -72,34 +76,30 @@ void mlxsw_sp_span_fini(struct mlxsw_sp *mlxsw_sp)
static struct mlxsw_sp_span_entry *
mlxsw_sp_span_entry_create(struct mlxsw_sp_port *port)
{
+ struct mlxsw_sp_span_entry *span_entry = NULL;
struct mlxsw_sp *mlxsw_sp = port->mlxsw_sp;
- struct mlxsw_sp_span_entry *span_entry;
char mpat_pl[MLXSW_REG_MPAT_LEN];
u8 local_port = port->local_port;
- int index;
int i;
int err;
/* find a free entry to use */
- index = -1;
for (i = 0; i < mlxsw_sp->span.entries_count; i++) {
if (!mlxsw_sp->span.entries[i].ref_count) {
- index = i;
span_entry = &mlxsw_sp->span.entries[i];
break;
}
}
- if (index < 0)
+ if (!span_entry)
return NULL;
/* create a new port analayzer entry for local_port */
- mlxsw_reg_mpat_pack(mpat_pl, index, local_port, true,
+ mlxsw_reg_mpat_pack(mpat_pl, span_entry->id, local_port, true,
MLXSW_REG_MPAT_SPAN_TYPE_LOCAL_ETH);
err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpat), mpat_pl);
if (err)
return NULL;
- span_entry->id = index;
span_entry->ref_count = 1;
span_entry->local_port = local_port;
return span_entry;
--
2.14.3
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [patch net-next 09/15] mlxsw: spectrum_span: Extract mlxsw_sp_span_entry_{de,}configure()
2018-02-27 13:53 [patch net-next 00/15] mlxsw: Offloading encapsulated SPAN Jiri Pirko
` (7 preceding siblings ...)
2018-02-27 13:53 ` [patch net-next 08/15] mlxsw: spectrum_span: Initialize span_entry.id eagerly Jiri Pirko
@ 2018-02-27 13:53 ` Jiri Pirko
2018-02-27 13:53 ` [patch net-next 10/15] mlxsw: spectrum: Keep mirror netdev in mlxsw_sp_span_entry Jiri Pirko
` (6 subsequent siblings)
15 siblings, 0 replies; 20+ messages in thread
From: Jiri Pirko @ 2018-02-27 13:53 UTC (permalink / raw)
To: netdev; +Cc: davem, petrm, idosch, mlxsw, xeb, dsa
From: Petr Machata <petrm@mellanox.com>
Configuring the hardware for encapsulated SPAN involves more code than
the simple mirroring case. Extract the related code to a separate
function to separate it from the rest of SPAN entry creation. Extract
deconfigure as well for symmetry, even though disablement is the same
regardless of SPAN type.
Signed-off-by: Petr Machata <petrm@mellanox.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
.../net/ethernet/mellanox/mlxsw/spectrum_span.c | 43 +++++++++++++++-------
1 file changed, 29 insertions(+), 14 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
index 5c87e6dfc5a1..442771908600 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
@@ -73,15 +73,40 @@ void mlxsw_sp_span_fini(struct mlxsw_sp *mlxsw_sp)
kfree(mlxsw_sp->span.entries);
}
+static int
+mlxsw_sp_span_entry_configure(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_span_entry *span_entry,
+ u8 local_port)
+{
+ char mpat_pl[MLXSW_REG_MPAT_LEN];
+ int pa_id = span_entry->id;
+
+ /* Create a new port analayzer entry for local_port. */
+ mlxsw_reg_mpat_pack(mpat_pl, pa_id, local_port, true,
+ MLXSW_REG_MPAT_SPAN_TYPE_LOCAL_ETH);
+ return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpat), mpat_pl);
+}
+
+static void
+mlxsw_sp_span_entry_deconfigure(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_span_entry *span_entry)
+{
+ u8 local_port = span_entry->local_port;
+ char mpat_pl[MLXSW_REG_MPAT_LEN];
+ int pa_id = span_entry->id;
+
+ mlxsw_reg_mpat_pack(mpat_pl, pa_id, local_port, false,
+ MLXSW_REG_MPAT_SPAN_TYPE_LOCAL_ETH);
+ mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpat), mpat_pl);
+}
+
static struct mlxsw_sp_span_entry *
mlxsw_sp_span_entry_create(struct mlxsw_sp_port *port)
{
struct mlxsw_sp_span_entry *span_entry = NULL;
struct mlxsw_sp *mlxsw_sp = port->mlxsw_sp;
- char mpat_pl[MLXSW_REG_MPAT_LEN];
u8 local_port = port->local_port;
int i;
- int err;
/* find a free entry to use */
for (i = 0; i < mlxsw_sp->span.entries_count; i++) {
@@ -93,11 +118,7 @@ mlxsw_sp_span_entry_create(struct mlxsw_sp_port *port)
if (!span_entry)
return NULL;
- /* create a new port analayzer entry for local_port */
- mlxsw_reg_mpat_pack(mpat_pl, span_entry->id, local_port, true,
- MLXSW_REG_MPAT_SPAN_TYPE_LOCAL_ETH);
- err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpat), mpat_pl);
- if (err)
+ if (mlxsw_sp_span_entry_configure(mlxsw_sp, span_entry, local_port))
return NULL;
span_entry->ref_count = 1;
@@ -108,13 +129,7 @@ mlxsw_sp_span_entry_create(struct mlxsw_sp_port *port)
static void mlxsw_sp_span_entry_destroy(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_span_entry *span_entry)
{
- u8 local_port = span_entry->local_port;
- char mpat_pl[MLXSW_REG_MPAT_LEN];
- int pa_id = span_entry->id;
-
- mlxsw_reg_mpat_pack(mpat_pl, pa_id, local_port, false,
- MLXSW_REG_MPAT_SPAN_TYPE_LOCAL_ETH);
- mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpat), mpat_pl);
+ mlxsw_sp_span_entry_deconfigure(mlxsw_sp, span_entry);
}
struct mlxsw_sp_span_entry *
--
2.14.3
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [patch net-next 10/15] mlxsw: spectrum: Keep mirror netdev in mlxsw_sp_span_entry
2018-02-27 13:53 [patch net-next 00/15] mlxsw: Offloading encapsulated SPAN Jiri Pirko
` (8 preceding siblings ...)
2018-02-27 13:53 ` [patch net-next 09/15] mlxsw: spectrum_span: Extract mlxsw_sp_span_entry_{de,}configure() Jiri Pirko
@ 2018-02-27 13:53 ` Jiri Pirko
2018-02-27 13:53 ` [patch net-next 11/15] mlxsw: spectrum_span: Generalize SPAN support Jiri Pirko
` (5 subsequent siblings)
15 siblings, 0 replies; 20+ messages in thread
From: Jiri Pirko @ 2018-02-27 13:53 UTC (permalink / raw)
To: netdev; +Cc: davem, petrm, idosch, mlxsw, xeb, dsa
From: Petr Machata <petrm@mellanox.com>
Currently the only mirror action supported by mlxsw is mirror to another
mlxsw physical port. Correspondingly, span_entry, which tracks each
mlxsw mirror in the system, currently holds a u8 number of the
destination port.
To extend this system to mirror to gretap and ip6gretap netdevices, have
struct mlxsw_sp_span_entry actually hold the destination netdevice
itself.
This change then trickles down in obvious manner to SPAN module API and
mirror-related interfaces in struct mlxsw_afa_ops.
To prevent use of invalid pointer, NETDEV_UNREGISTER needs to be hooked
and the corresponding SPAN entry invalidated.
Signed-off-by: Petr Machata <petrm@mellanox.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
.../mellanox/mlxsw/core_acl_flex_actions.c | 13 ++++----
.../mellanox/mlxsw/core_acl_flex_actions.h | 7 ++--
drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 11 ++++--
drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c | 2 +-
.../mellanox/mlxsw/spectrum_acl_flex_actions.c | 8 ++---
.../net/ethernet/mellanox/mlxsw/spectrum_span.c | 39 ++++++++++++++--------
.../net/ethernet/mellanox/mlxsw/spectrum_span.h | 10 ++++--
7 files changed, 56 insertions(+), 34 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c
index d1c2d85f396d..ba338428ffd1 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.c
@@ -863,9 +863,8 @@ mlxsw_afa_mirror_destructor(struct mlxsw_afa_block *block,
}
static struct mlxsw_afa_mirror *
-mlxsw_afa_mirror_create(struct mlxsw_afa_block *block,
- u8 local_in_port, u8 local_out_port,
- bool ingress)
+mlxsw_afa_mirror_create(struct mlxsw_afa_block *block, u8 local_in_port,
+ const struct net_device *out_dev, bool ingress)
{
struct mlxsw_afa_mirror *mirror;
int err;
@@ -875,7 +874,7 @@ mlxsw_afa_mirror_create(struct mlxsw_afa_block *block,
return ERR_PTR(-ENOMEM);
err = block->afa->ops->mirror_add(block->afa->ops_priv,
- local_in_port, local_out_port,
+ local_in_port, out_dev,
ingress, &mirror->span_id);
if (err)
goto err_mirror_add;
@@ -907,13 +906,13 @@ mlxsw_afa_block_append_allocated_mirror(struct mlxsw_afa_block *block,
}
int
-mlxsw_afa_block_append_mirror(struct mlxsw_afa_block *block,
- u8 local_in_port, u8 local_out_port, bool ingress)
+mlxsw_afa_block_append_mirror(struct mlxsw_afa_block *block, u8 local_in_port,
+ const struct net_device *out_dev, bool ingress)
{
struct mlxsw_afa_mirror *mirror;
int err;
- mirror = mlxsw_afa_mirror_create(block, local_in_port, local_out_port,
+ mirror = mlxsw_afa_mirror_create(block, local_in_port, out_dev,
ingress);
if (IS_ERR(mirror))
return PTR_ERR(mirror);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.h b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.h
index 4e991ca6dce5..6dd601703c99 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/core_acl_flex_actions.h
@@ -36,6 +36,7 @@
#define _MLXSW_CORE_ACL_FLEX_ACTIONS_H
#include <linux/types.h>
+#include <linux/netdevice.h>
struct mlxsw_afa;
struct mlxsw_afa_block;
@@ -48,7 +49,8 @@ struct mlxsw_afa_ops {
void (*kvdl_fwd_entry_del)(void *priv, u32 kvdl_index);
int (*counter_index_get)(void *priv, unsigned int *p_counter_index);
void (*counter_index_put)(void *priv, unsigned int counter_index);
- int (*mirror_add)(void *priv, u8 locol_in_port, u8 local_out_port,
+ int (*mirror_add)(void *priv, u8 local_in_port,
+ const struct net_device *out_dev,
bool ingress, int *p_span_id);
void (*mirror_del)(void *priv, u8 local_in_port, int span_id,
bool ingress);
@@ -70,7 +72,8 @@ int mlxsw_afa_block_append_trap(struct mlxsw_afa_block *block, u16 trap_id);
int mlxsw_afa_block_append_trap_and_forward(struct mlxsw_afa_block *block,
u16 trap_id);
int mlxsw_afa_block_append_mirror(struct mlxsw_afa_block *block,
- u8 local_in_port, u8 local_out_port,
+ u8 local_in_port,
+ const struct net_device *out_dev,
bool ingress);
int mlxsw_afa_block_append_fwd(struct mlxsw_afa_block *block,
u8 local_port, bool in_port);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 10bb4891ec31..86991db3478c 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -1258,7 +1258,6 @@ mlxsw_sp_port_add_cls_matchall_mirror(struct mlxsw_sp_port *mlxsw_sp_port,
bool ingress)
{
enum mlxsw_sp_span_type span_type;
- struct mlxsw_sp_port *to_port;
struct net_device *to_dev;
to_dev = tcf_mirred_dev(a);
@@ -1271,11 +1270,10 @@ mlxsw_sp_port_add_cls_matchall_mirror(struct mlxsw_sp_port *mlxsw_sp_port,
netdev_err(mlxsw_sp_port->dev, "Cannot mirror to a non-spectrum port");
return -EOPNOTSUPP;
}
- to_port = netdev_priv(to_dev);
mirror->ingress = ingress;
span_type = ingress ? MLXSW_SP_SPAN_INGRESS : MLXSW_SP_SPAN_EGRESS;
- return mlxsw_sp_span_mirror_add(mlxsw_sp_port, to_port, span_type,
+ return mlxsw_sp_span_mirror_add(mlxsw_sp_port, to_dev, span_type,
true, &mirror->span_id);
}
@@ -4638,10 +4636,17 @@ static int mlxsw_sp_netdevice_event(struct notifier_block *nb,
unsigned long event, void *ptr)
{
struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+ struct mlxsw_sp_span_entry *span_entry;
struct mlxsw_sp *mlxsw_sp;
int err = 0;
mlxsw_sp = container_of(nb, struct mlxsw_sp, netdevice_nb);
+ if (event == NETDEV_UNREGISTER) {
+ span_entry = mlxsw_sp_span_entry_find_by_port(mlxsw_sp, dev);
+ if (span_entry)
+ mlxsw_sp_span_entry_invalidate(mlxsw_sp, span_entry);
+ }
+
if (mlxsw_sp_netdev_is_ipip_ol(mlxsw_sp, dev))
err = mlxsw_sp_netdevice_ipip_ol_event(mlxsw_sp, dev,
event, ptr);
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
index 0897a5435cc2..50f5eacdfa24 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
@@ -590,7 +590,7 @@ int mlxsw_sp_acl_rulei_act_mirror(struct mlxsw_sp *mlxsw_sp,
return mlxsw_afa_block_append_mirror(rulei->act_block,
in_port->local_port,
- out_port->local_port,
+ out_dev,
binding->ingress);
}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_actions.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_actions.c
index b450d3e4a905..510ce48d87f7 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_actions.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_actions.c
@@ -126,18 +126,18 @@ mlxsw_sp_act_counter_index_put(void *priv, unsigned int counter_index)
}
static int
-mlxsw_sp_act_mirror_add(void *priv, u8 local_in_port, u8 local_out_port,
+mlxsw_sp_act_mirror_add(void *priv, u8 local_in_port,
+ const struct net_device *out_dev,
bool ingress, int *p_span_id)
{
- struct mlxsw_sp_port *in_port, *out_port;
+ struct mlxsw_sp_port *in_port;
struct mlxsw_sp *mlxsw_sp = priv;
enum mlxsw_sp_span_type type;
type = ingress ? MLXSW_SP_SPAN_INGRESS : MLXSW_SP_SPAN_EGRESS;
- out_port = mlxsw_sp->ports[local_out_port];
in_port = mlxsw_sp->ports[local_in_port];
- return mlxsw_sp_span_mirror_add(in_port, out_port, type,
+ return mlxsw_sp_span_mirror_add(in_port, out_dev, type,
false, p_span_id);
}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
index 442771908600..9819cdcf9e5c 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
@@ -91,7 +91,8 @@ static void
mlxsw_sp_span_entry_deconfigure(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_span_entry *span_entry)
{
- u8 local_port = span_entry->local_port;
+ struct mlxsw_sp_port *to_port = netdev_priv(span_entry->to_dev);
+ u8 local_port = to_port->local_port;
char mpat_pl[MLXSW_REG_MPAT_LEN];
int pa_id = span_entry->id;
@@ -101,11 +102,12 @@ mlxsw_sp_span_entry_deconfigure(struct mlxsw_sp *mlxsw_sp,
}
static struct mlxsw_sp_span_entry *
-mlxsw_sp_span_entry_create(struct mlxsw_sp_port *port)
+mlxsw_sp_span_entry_create(struct mlxsw_sp *mlxsw_sp,
+ const struct net_device *to_dev)
{
+ struct mlxsw_sp_port *to_port = netdev_priv(to_dev);
struct mlxsw_sp_span_entry *span_entry = NULL;
- struct mlxsw_sp *mlxsw_sp = port->mlxsw_sp;
- u8 local_port = port->local_port;
+ u8 local_port = to_port->local_port;
int i;
/* find a free entry to use */
@@ -122,30 +124,39 @@ mlxsw_sp_span_entry_create(struct mlxsw_sp_port *port)
return NULL;
span_entry->ref_count = 1;
- span_entry->local_port = local_port;
+ span_entry->to_dev = to_dev;
return span_entry;
}
static void mlxsw_sp_span_entry_destroy(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_span_entry *span_entry)
{
- mlxsw_sp_span_entry_deconfigure(mlxsw_sp, span_entry);
+ if (span_entry->to_dev)
+ mlxsw_sp_span_entry_deconfigure(mlxsw_sp, span_entry);
}
struct mlxsw_sp_span_entry *
-mlxsw_sp_span_entry_find_by_port(struct mlxsw_sp *mlxsw_sp, u8 local_port)
+mlxsw_sp_span_entry_find_by_port(struct mlxsw_sp *mlxsw_sp,
+ const struct net_device *to_dev)
{
int i;
for (i = 0; i < mlxsw_sp->span.entries_count; i++) {
struct mlxsw_sp_span_entry *curr = &mlxsw_sp->span.entries[i];
- if (curr->ref_count && curr->local_port == local_port)
+ if (curr->ref_count && curr->to_dev == to_dev)
return curr;
}
return NULL;
}
+void mlxsw_sp_span_entry_invalidate(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_span_entry *span_entry)
+{
+ mlxsw_sp_span_entry_deconfigure(mlxsw_sp, span_entry);
+ span_entry->to_dev = NULL;
+}
+
static struct mlxsw_sp_span_entry *
mlxsw_sp_span_entry_find_by_id(struct mlxsw_sp *mlxsw_sp, int span_id)
{
@@ -161,19 +172,19 @@ mlxsw_sp_span_entry_find_by_id(struct mlxsw_sp *mlxsw_sp, int span_id)
}
static struct mlxsw_sp_span_entry *
-mlxsw_sp_span_entry_get(struct mlxsw_sp_port *port)
+mlxsw_sp_span_entry_get(struct mlxsw_sp *mlxsw_sp,
+ const struct net_device *to_dev)
{
struct mlxsw_sp_span_entry *span_entry;
- span_entry = mlxsw_sp_span_entry_find_by_port(port->mlxsw_sp,
- port->local_port);
+ span_entry = mlxsw_sp_span_entry_find_by_port(mlxsw_sp, to_dev);
if (span_entry) {
/* Already exists, just take a reference */
span_entry->ref_count++;
return span_entry;
}
- return mlxsw_sp_span_entry_create(port);
+ return mlxsw_sp_span_entry_create(mlxsw_sp, to_dev);
}
static int mlxsw_sp_span_entry_put(struct mlxsw_sp *mlxsw_sp,
@@ -344,7 +355,7 @@ mlxsw_sp_span_inspected_port_del(struct mlxsw_sp_port *port,
}
int mlxsw_sp_span_mirror_add(struct mlxsw_sp_port *from,
- struct mlxsw_sp_port *to,
+ const struct net_device *to_dev,
enum mlxsw_sp_span_type type, bool bind,
int *p_span_id)
{
@@ -352,7 +363,7 @@ int mlxsw_sp_span_mirror_add(struct mlxsw_sp_port *from,
struct mlxsw_sp_span_entry *span_entry;
int err;
- span_entry = mlxsw_sp_span_entry_get(to);
+ span_entry = mlxsw_sp_span_entry_get(mlxsw_sp, to_dev);
if (!span_entry)
return -ENOENT;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.h
index 02dedf2fcd3f..44b307c59d0e 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.h
@@ -51,7 +51,7 @@ struct mlxsw_sp_span_inspected_port {
};
struct mlxsw_sp_span_entry {
- u8 local_port;
+ const struct net_device *to_dev;
struct list_head bound_ports_list;
int ref_count;
int id;
@@ -61,13 +61,17 @@ int mlxsw_sp_span_init(struct mlxsw_sp *mlxsw_sp);
void mlxsw_sp_span_fini(struct mlxsw_sp *mlxsw_sp);
int mlxsw_sp_span_mirror_add(struct mlxsw_sp_port *from,
- struct mlxsw_sp_port *to,
+ const struct net_device *to_dev,
enum mlxsw_sp_span_type type,
bool bind, int *p_span_id);
void mlxsw_sp_span_mirror_del(struct mlxsw_sp_port *from, int span_id,
enum mlxsw_sp_span_type type, bool bind);
struct mlxsw_sp_span_entry *
-mlxsw_sp_span_entry_find_by_port(struct mlxsw_sp *mlxsw_sp, u8 local_port);
+mlxsw_sp_span_entry_find_by_port(struct mlxsw_sp *mlxsw_sp,
+ const struct net_device *to_dev);
+
+void mlxsw_sp_span_entry_invalidate(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_span_entry *span_entry);
int mlxsw_sp_span_port_mtu_update(struct mlxsw_sp_port *port, u16 mtu);
--
2.14.3
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [patch net-next 11/15] mlxsw: spectrum_span: Generalize SPAN support
2018-02-27 13:53 [patch net-next 00/15] mlxsw: Offloading encapsulated SPAN Jiri Pirko
` (9 preceding siblings ...)
2018-02-27 13:53 ` [patch net-next 10/15] mlxsw: spectrum: Keep mirror netdev in mlxsw_sp_span_entry Jiri Pirko
@ 2018-02-27 13:53 ` Jiri Pirko
2018-02-27 13:53 ` [patch net-next 12/15] mlxsw: Handle config changes pertinent to SPAN Jiri Pirko
` (4 subsequent siblings)
15 siblings, 0 replies; 20+ messages in thread
From: Jiri Pirko @ 2018-02-27 13:53 UTC (permalink / raw)
To: netdev; +Cc: davem, petrm, idosch, mlxsw, xeb, dsa
From: Petr Machata <petrm@mellanox.com>
To support mirroring to different device types, the functions that
partake in configuring the port analyzer need to be extended to admit
non-trivial SPAN types.
Create a structure where all details of SPAN configuration are kept,
struct mlxsw_sp_span_parms. Also create struct mlxsw_sp_span_entry_ops
to keep per-SPAN-type operations.
Instantiate the latter once for MLXSW_REG_MPAT_SPAN_TYPE_LOCAL_ETH, and
once for a suite of NOP callbacks used for invalidated SPAN entry. Put
the formet as a sole member of a new array mlxsw_sp_span_entry_types,
where all known SPAN types are kept. Introduce a new function,
mlxsw_sp_span_entry_ops(), to look up the right ops suite given a
netdevice.
Change mlxsw_sp_span_mirror_add() to use both parms and ops structures.
Change mlxsw_sp_span_entry_get() and mlxsw_sp_span_entry_create() to
take these as arguments. Modify mlxsw_sp_span_entry_configure() and
mlxsw_sp_span_entry_deconfigure() to dispatch to ops.
Signed-off-by: Petr Machata <petrm@mellanox.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 5 -
drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c | 3 -
.../net/ethernet/mellanox/mlxsw/spectrum_span.c | 155 +++++++++++++++++----
.../net/ethernet/mellanox/mlxsw/spectrum_span.h | 17 +++
4 files changed, 147 insertions(+), 33 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 86991db3478c..b070cad8dba7 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -1266,11 +1266,6 @@ mlxsw_sp_port_add_cls_matchall_mirror(struct mlxsw_sp_port *mlxsw_sp_port,
return -EINVAL;
}
- if (!mlxsw_sp_port_dev_check(to_dev)) {
- netdev_err(mlxsw_sp_port->dev, "Cannot mirror to a non-spectrum port");
- return -EOPNOTSUPP;
- }
-
mirror->ingress = ingress;
span_type = ingress ? MLXSW_SP_SPAN_INGRESS : MLXSW_SP_SPAN_EGRESS;
return mlxsw_sp_span_mirror_add(mlxsw_sp_port, to_dev, span_type,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
index 50f5eacdfa24..9d7197b9abb1 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
@@ -581,9 +581,6 @@ int mlxsw_sp_acl_rulei_act_mirror(struct mlxsw_sp *mlxsw_sp,
binding = list_first_entry(&block->binding_list,
struct mlxsw_sp_acl_block_binding, list);
in_port = binding->mlxsw_sp_port;
- if (!mlxsw_sp_port_dev_check(out_dev))
- return -EINVAL;
-
out_port = netdev_priv(out_dev);
if (out_port->mlxsw_sp != mlxsw_sp)
return -EINVAL;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
index 9819cdcf9e5c..c0e0e9af2da7 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
@@ -74,40 +74,120 @@ void mlxsw_sp_span_fini(struct mlxsw_sp *mlxsw_sp)
}
static int
-mlxsw_sp_span_entry_configure(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_span_entry *span_entry,
- u8 local_port)
+mlxsw_sp_span_entry_phys_parms(const struct net_device *to_dev,
+ struct mlxsw_sp_span_parms *sparmsp)
+{
+ sparmsp->dest_port = netdev_priv(to_dev);
+ return 0;
+}
+
+static int
+mlxsw_sp_span_entry_phys_configure(struct mlxsw_sp_span_entry *span_entry,
+ struct mlxsw_sp_span_parms sparms)
{
+ struct mlxsw_sp_port *dest_port = sparms.dest_port;
+ struct mlxsw_sp *mlxsw_sp = dest_port->mlxsw_sp;
+ u8 local_port = dest_port->local_port;
char mpat_pl[MLXSW_REG_MPAT_LEN];
int pa_id = span_entry->id;
/* Create a new port analayzer entry for local_port. */
mlxsw_reg_mpat_pack(mpat_pl, pa_id, local_port, true,
MLXSW_REG_MPAT_SPAN_TYPE_LOCAL_ETH);
+
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpat), mpat_pl);
}
static void
-mlxsw_sp_span_entry_deconfigure(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_span_entry *span_entry)
+mlxsw_sp_span_entry_deconfigure_common(struct mlxsw_sp_span_entry *span_entry,
+ enum mlxsw_reg_mpat_span_type span_type)
{
- struct mlxsw_sp_port *to_port = netdev_priv(span_entry->to_dev);
- u8 local_port = to_port->local_port;
+ struct mlxsw_sp_port *dest_port = span_entry->parms.dest_port;
+ struct mlxsw_sp *mlxsw_sp = dest_port->mlxsw_sp;
+ u8 local_port = dest_port->local_port;
char mpat_pl[MLXSW_REG_MPAT_LEN];
int pa_id = span_entry->id;
- mlxsw_reg_mpat_pack(mpat_pl, pa_id, local_port, false,
- MLXSW_REG_MPAT_SPAN_TYPE_LOCAL_ETH);
+ mlxsw_reg_mpat_pack(mpat_pl, pa_id, local_port, false, span_type);
mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpat), mpat_pl);
}
+static void
+mlxsw_sp_span_entry_phys_deconfigure(struct mlxsw_sp_span_entry *span_entry)
+{
+ mlxsw_sp_span_entry_deconfigure_common(span_entry,
+ MLXSW_REG_MPAT_SPAN_TYPE_LOCAL_ETH);
+}
+
+static const
+struct mlxsw_sp_span_entry_ops mlxsw_sp_span_entry_ops_phys = {
+ .can_handle = mlxsw_sp_port_dev_check,
+ .parms = mlxsw_sp_span_entry_phys_parms,
+ .configure = mlxsw_sp_span_entry_phys_configure,
+ .deconfigure = mlxsw_sp_span_entry_phys_deconfigure,
+};
+
+static const
+struct mlxsw_sp_span_entry_ops *const mlxsw_sp_span_entry_types[] = {
+ &mlxsw_sp_span_entry_ops_phys,
+};
+
+static int
+mlxsw_sp_span_entry_nop_parms(const struct net_device *to_dev,
+ struct mlxsw_sp_span_parms *sparmsp)
+{
+ sparmsp->dest_port = NULL;
+ return 0;
+}
+
+static int
+mlxsw_sp_span_entry_nop_configure(struct mlxsw_sp_span_entry *span_entry,
+ struct mlxsw_sp_span_parms sparms)
+{
+ return 0;
+}
+
+static void
+mlxsw_sp_span_entry_nop_deconfigure(struct mlxsw_sp_span_entry *span_entry)
+{
+}
+
+static const struct mlxsw_sp_span_entry_ops mlxsw_sp_span_entry_ops_nop = {
+ .parms = mlxsw_sp_span_entry_nop_parms,
+ .configure = mlxsw_sp_span_entry_nop_configure,
+ .deconfigure = mlxsw_sp_span_entry_nop_deconfigure,
+};
+
+static void
+mlxsw_sp_span_entry_configure(struct mlxsw_sp *mlxsw_sp,
+ struct mlxsw_sp_span_entry *span_entry,
+ struct mlxsw_sp_span_parms sparms)
+{
+ if (sparms.dest_port) {
+ if (span_entry->ops->configure(span_entry, sparms)) {
+ netdev_err(span_entry->to_dev, "Failed to offload mirror to %s",
+ sparms.dest_port->dev->name);
+ sparms.dest_port = NULL;
+ }
+ }
+
+ span_entry->parms = sparms;
+}
+
+static void
+mlxsw_sp_span_entry_deconfigure(struct mlxsw_sp_span_entry *span_entry)
+{
+ if (span_entry->parms.dest_port)
+ span_entry->ops->deconfigure(span_entry);
+}
+
static struct mlxsw_sp_span_entry *
mlxsw_sp_span_entry_create(struct mlxsw_sp *mlxsw_sp,
- const struct net_device *to_dev)
+ const struct net_device *to_dev,
+ const struct mlxsw_sp_span_entry_ops *ops,
+ struct mlxsw_sp_span_parms sparms)
{
- struct mlxsw_sp_port *to_port = netdev_priv(to_dev);
struct mlxsw_sp_span_entry *span_entry = NULL;
- u8 local_port = to_port->local_port;
int i;
/* find a free entry to use */
@@ -120,19 +200,17 @@ mlxsw_sp_span_entry_create(struct mlxsw_sp *mlxsw_sp,
if (!span_entry)
return NULL;
- if (mlxsw_sp_span_entry_configure(mlxsw_sp, span_entry, local_port))
- return NULL;
-
+ span_entry->ops = ops;
span_entry->ref_count = 1;
span_entry->to_dev = to_dev;
+ mlxsw_sp_span_entry_configure(mlxsw_sp, span_entry, sparms);
+
return span_entry;
}
-static void mlxsw_sp_span_entry_destroy(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_span_entry *span_entry)
+static void mlxsw_sp_span_entry_destroy(struct mlxsw_sp_span_entry *span_entry)
{
- if (span_entry->to_dev)
- mlxsw_sp_span_entry_deconfigure(mlxsw_sp, span_entry);
+ mlxsw_sp_span_entry_deconfigure(span_entry);
}
struct mlxsw_sp_span_entry *
@@ -153,8 +231,8 @@ mlxsw_sp_span_entry_find_by_port(struct mlxsw_sp *mlxsw_sp,
void mlxsw_sp_span_entry_invalidate(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_span_entry *span_entry)
{
- mlxsw_sp_span_entry_deconfigure(mlxsw_sp, span_entry);
- span_entry->to_dev = NULL;
+ mlxsw_sp_span_entry_deconfigure(span_entry);
+ span_entry->ops = &mlxsw_sp_span_entry_ops_nop;
}
static struct mlxsw_sp_span_entry *
@@ -173,7 +251,9 @@ mlxsw_sp_span_entry_find_by_id(struct mlxsw_sp *mlxsw_sp, int span_id)
static struct mlxsw_sp_span_entry *
mlxsw_sp_span_entry_get(struct mlxsw_sp *mlxsw_sp,
- const struct net_device *to_dev)
+ const struct net_device *to_dev,
+ const struct mlxsw_sp_span_entry_ops *ops,
+ struct mlxsw_sp_span_parms sparms)
{
struct mlxsw_sp_span_entry *span_entry;
@@ -184,7 +264,7 @@ mlxsw_sp_span_entry_get(struct mlxsw_sp *mlxsw_sp,
return span_entry;
}
- return mlxsw_sp_span_entry_create(mlxsw_sp, to_dev);
+ return mlxsw_sp_span_entry_create(mlxsw_sp, to_dev, ops, sparms);
}
static int mlxsw_sp_span_entry_put(struct mlxsw_sp *mlxsw_sp,
@@ -192,7 +272,7 @@ static int mlxsw_sp_span_entry_put(struct mlxsw_sp *mlxsw_sp,
{
WARN_ON(!span_entry->ref_count);
if (--span_entry->ref_count == 0)
- mlxsw_sp_span_entry_destroy(mlxsw_sp, span_entry);
+ mlxsw_sp_span_entry_destroy(span_entry);
return 0;
}
@@ -354,16 +434,41 @@ mlxsw_sp_span_inspected_port_del(struct mlxsw_sp_port *port,
kfree(inspected_port);
}
+static const struct mlxsw_sp_span_entry_ops *
+mlxsw_sp_span_entry_ops(struct mlxsw_sp *mlxsw_sp,
+ const struct net_device *to_dev)
+{
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(mlxsw_sp_span_entry_types); ++i)
+ if (mlxsw_sp_span_entry_types[i]->can_handle(to_dev))
+ return mlxsw_sp_span_entry_types[i];
+
+ return NULL;
+}
+
int mlxsw_sp_span_mirror_add(struct mlxsw_sp_port *from,
const struct net_device *to_dev,
enum mlxsw_sp_span_type type, bool bind,
int *p_span_id)
{
struct mlxsw_sp *mlxsw_sp = from->mlxsw_sp;
+ const struct mlxsw_sp_span_entry_ops *ops;
+ struct mlxsw_sp_span_parms sparms = {0};
struct mlxsw_sp_span_entry *span_entry;
int err;
- span_entry = mlxsw_sp_span_entry_get(mlxsw_sp, to_dev);
+ ops = mlxsw_sp_span_entry_ops(mlxsw_sp, to_dev);
+ if (!ops) {
+ netdev_err(to_dev, "Cannot mirror to %s", to_dev->name);
+ return -EOPNOTSUPP;
+ }
+
+ err = ops->parms(to_dev, &sparms);
+ if (err)
+ return err;
+
+ span_entry = mlxsw_sp_span_entry_get(mlxsw_sp, to_dev, ops, sparms);
if (!span_entry)
return -ENOENT;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.h
index 44b307c59d0e..9390b05a7919 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.h
@@ -50,13 +50,30 @@ struct mlxsw_sp_span_inspected_port {
u8 local_port;
};
+struct mlxsw_sp_span_parms {
+ struct mlxsw_sp_port *dest_port; /* NULL for unoffloaded SPAN. */
+};
+
+struct mlxsw_sp_span_entry_ops;
+
struct mlxsw_sp_span_entry {
const struct net_device *to_dev;
+ const struct mlxsw_sp_span_entry_ops *ops;
+ struct mlxsw_sp_span_parms parms;
struct list_head bound_ports_list;
int ref_count;
int id;
};
+struct mlxsw_sp_span_entry_ops {
+ bool (*can_handle)(const struct net_device *to_dev);
+ int (*parms)(const struct net_device *to_dev,
+ struct mlxsw_sp_span_parms *sparmsp);
+ int (*configure)(struct mlxsw_sp_span_entry *span_entry,
+ struct mlxsw_sp_span_parms sparms);
+ void (*deconfigure)(struct mlxsw_sp_span_entry *span_entry);
+};
+
int mlxsw_sp_span_init(struct mlxsw_sp *mlxsw_sp);
void mlxsw_sp_span_fini(struct mlxsw_sp *mlxsw_sp);
--
2.14.3
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [patch net-next 12/15] mlxsw: Handle config changes pertinent to SPAN
2018-02-27 13:53 [patch net-next 00/15] mlxsw: Offloading encapsulated SPAN Jiri Pirko
` (10 preceding siblings ...)
2018-02-27 13:53 ` [patch net-next 11/15] mlxsw: spectrum_span: Generalize SPAN support Jiri Pirko
@ 2018-02-27 13:53 ` Jiri Pirko
2018-02-27 13:53 ` [patch net-next 13/15] mlxsw: Move a mirroring check to mlxsw_sp_span_entry_create Jiri Pirko
` (3 subsequent siblings)
15 siblings, 0 replies; 20+ messages in thread
From: Jiri Pirko @ 2018-02-27 13:53 UTC (permalink / raw)
To: netdev; +Cc: davem, petrm, idosch, mlxsw, xeb, dsa
From: Petr Machata <petrm@mellanox.com>
For some netdevices, for which mlxsw offloads mirroring, may have a
complex relationship between the declared intent and low-level
device configuration.
Trying to accurately track which changes might influence offloading
decisions is finicky and error-prone. Instead, this patch introduces a
function mlxsw_sp_span_entry_respin, which re-queries the configuration
anew and, if different, removes the existing offloads and installs new
ones.
Call this function strategically at event handlers that might influence
the mirroring configuration.
Signed-off-by: Petr Machata <petrm@mellanox.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 29 +++++++++++++---------
.../net/ethernet/mellanox/mlxsw/spectrum_router.c | 7 ++++++
.../net/ethernet/mellanox/mlxsw/spectrum_span.c | 24 ++++++++++++++++++
.../net/ethernet/mellanox/mlxsw/spectrum_span.h | 1 +
4 files changed, 49 insertions(+), 12 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index b070cad8dba7..8d2d140d7910 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -1,6 +1,6 @@
/*
* drivers/net/ethernet/mellanox/mlxsw/spectrum.c
- * Copyright (c) 2015-2017 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2015-2018 Mellanox Technologies. All rights reserved.
* Copyright (c) 2015-2017 Jiri Pirko <jiri@mellanox.com>
* Copyright (c) 2015 Ido Schimmel <idosch@mellanox.com>
* Copyright (c) 2015 Elad Raz <eladr@mellanox.com>
@@ -3667,14 +3667,24 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
goto err_afa_init;
}
+ err = mlxsw_sp_span_init(mlxsw_sp);
+ if (err) {
+ dev_err(mlxsw_sp->bus_info->dev, "Failed to init span system\n");
+ goto err_span_init;
+ }
+
+ /* Initialize router after SPAN is initialized, so that the FIB and
+ * neighbor event handlers can issue SPAN respin.
+ */
err = mlxsw_sp_router_init(mlxsw_sp);
if (err) {
dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize router\n");
goto err_router_init;
}
- /* Initialize netdevice notifier after router is initialized, so that
- * the event handler can use router structures.
+ /* Initialize netdevice notifier after router and SPAN is initialized,
+ * so that the event handler can use router structures and call SPAN
+ * respin.
*/
mlxsw_sp->netdevice_nb.notifier_call = mlxsw_sp_netdevice_event;
err = register_netdevice_notifier(&mlxsw_sp->netdevice_nb);
@@ -3683,12 +3693,6 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
goto err_netdev_notifier;
}
- err = mlxsw_sp_span_init(mlxsw_sp);
- if (err) {
- dev_err(mlxsw_sp->bus_info->dev, "Failed to init span system\n");
- goto err_span_init;
- }
-
err = mlxsw_sp_acl_init(mlxsw_sp);
if (err) {
dev_err(mlxsw_sp->bus_info->dev, "Failed to initialize ACL\n");
@@ -3714,12 +3718,12 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core,
err_dpipe_init:
mlxsw_sp_acl_fini(mlxsw_sp);
err_acl_init:
- mlxsw_sp_span_fini(mlxsw_sp);
-err_span_init:
unregister_netdevice_notifier(&mlxsw_sp->netdevice_nb);
err_netdev_notifier:
mlxsw_sp_router_fini(mlxsw_sp);
err_router_init:
+ mlxsw_sp_span_fini(mlxsw_sp);
+err_span_init:
mlxsw_sp_afa_fini(mlxsw_sp);
err_afa_init:
mlxsw_sp_counter_pool_fini(mlxsw_sp);
@@ -3745,9 +3749,9 @@ static void mlxsw_sp_fini(struct mlxsw_core *mlxsw_core)
mlxsw_sp_ports_remove(mlxsw_sp);
mlxsw_sp_dpipe_fini(mlxsw_sp);
mlxsw_sp_acl_fini(mlxsw_sp);
- mlxsw_sp_span_fini(mlxsw_sp);
unregister_netdevice_notifier(&mlxsw_sp->netdevice_nb);
mlxsw_sp_router_fini(mlxsw_sp);
+ mlxsw_sp_span_fini(mlxsw_sp);
mlxsw_sp_afa_fini(mlxsw_sp);
mlxsw_sp_counter_pool_fini(mlxsw_sp);
mlxsw_sp_switchdev_fini(mlxsw_sp);
@@ -4641,6 +4645,7 @@ static int mlxsw_sp_netdevice_event(struct notifier_block *nb,
if (span_entry)
mlxsw_sp_span_entry_invalidate(mlxsw_sp, span_entry);
}
+ mlxsw_sp_span_respin(mlxsw_sp);
if (mlxsw_sp_netdev_is_ipip_ol(mlxsw_sp, dev))
err = mlxsw_sp_netdevice_ipip_ol_event(mlxsw_sp, dev,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index 05146970c19c..69f16c605b9d 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -70,6 +70,7 @@
#include "spectrum_mr.h"
#include "spectrum_mr_tcam.h"
#include "spectrum_router.h"
+#include "spectrum_span.h"
struct mlxsw_sp_fib;
struct mlxsw_sp_vr;
@@ -2330,6 +2331,8 @@ static void mlxsw_sp_router_neigh_event_work(struct work_struct *work)
read_unlock_bh(&n->lock);
rtnl_lock();
+ mlxsw_sp_span_respin(mlxsw_sp);
+
entry_connected = nud_state & NUD_VALID && !dead;
neigh_entry = mlxsw_sp_neigh_entry_lookup(mlxsw_sp, n);
if (!entry_connected && !neigh_entry)
@@ -5589,6 +5592,8 @@ static void mlxsw_sp_router_fib4_event_work(struct work_struct *work)
/* Protect internal structures from changes */
rtnl_lock();
+ mlxsw_sp_span_respin(mlxsw_sp);
+
switch (fib_work->event) {
case FIB_EVENT_ENTRY_REPLACE: /* fall through */
case FIB_EVENT_ENTRY_APPEND: /* fall through */
@@ -5631,6 +5636,8 @@ static void mlxsw_sp_router_fib6_event_work(struct work_struct *work)
int err;
rtnl_lock();
+ mlxsw_sp_span_respin(mlxsw_sp);
+
switch (fib_work->event) {
case FIB_EVENT_ENTRY_REPLACE: /* fall through */
case FIB_EVENT_ENTRY_ADD:
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
index c0e0e9af2da7..71102f156a97 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
@@ -502,3 +502,27 @@ void mlxsw_sp_span_mirror_del(struct mlxsw_sp_port *from, int span_id,
span_entry->id);
mlxsw_sp_span_inspected_port_del(from, span_entry, type, bind);
}
+
+void mlxsw_sp_span_respin(struct mlxsw_sp *mlxsw_sp)
+{
+ int i;
+ int err;
+
+ ASSERT_RTNL();
+ for (i = 0; i < mlxsw_sp->span.entries_count; i++) {
+ struct mlxsw_sp_span_entry *curr = &mlxsw_sp->span.entries[i];
+ struct mlxsw_sp_span_parms sparms = {0};
+
+ if (!curr->ref_count)
+ continue;
+
+ err = curr->ops->parms(curr->to_dev, &sparms);
+ if (err)
+ continue;
+
+ if (memcmp(&sparms, &curr->parms, sizeof(sparms))) {
+ mlxsw_sp_span_entry_deconfigure(curr);
+ mlxsw_sp_span_entry_configure(mlxsw_sp, curr, sparms);
+ }
+ }
+}
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.h
index 9390b05a7919..b6dcd7d7277c 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.h
@@ -76,6 +76,7 @@ struct mlxsw_sp_span_entry_ops {
int mlxsw_sp_span_init(struct mlxsw_sp *mlxsw_sp);
void mlxsw_sp_span_fini(struct mlxsw_sp *mlxsw_sp);
+void mlxsw_sp_span_respin(struct mlxsw_sp *mlxsw_sp);
int mlxsw_sp_span_mirror_add(struct mlxsw_sp_port *from,
const struct net_device *to_dev,
--
2.14.3
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [patch net-next 13/15] mlxsw: Move a mirroring check to mlxsw_sp_span_entry_create
2018-02-27 13:53 [patch net-next 00/15] mlxsw: Offloading encapsulated SPAN Jiri Pirko
` (11 preceding siblings ...)
2018-02-27 13:53 ` [patch net-next 12/15] mlxsw: Handle config changes pertinent to SPAN Jiri Pirko
@ 2018-02-27 13:53 ` Jiri Pirko
2018-02-27 13:53 ` [patch net-next 14/15] mlxsw: spectrum_span: Support mirror to gretap Jiri Pirko
` (2 subsequent siblings)
15 siblings, 0 replies; 20+ messages in thread
From: Jiri Pirko @ 2018-02-27 13:53 UTC (permalink / raw)
To: netdev; +Cc: davem, petrm, idosch, mlxsw, xeb, dsa
From: Petr Machata <petrm@mellanox.com>
The check for whether a mirror port (which is a mlxsw front panel port)
belongs to the same mlxsw instance as the mirrored port, is currently
only done in spectrum_acl, even though it's applicable for the matchall
case as well. Thus move it to mlxsw_sp_span_entry_create().
Signed-off-by: Petr Machata <petrm@mellanox.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c | 4 ----
drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c | 6 +++++-
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
index 9d7197b9abb1..21ed27ae51e3 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl.c
@@ -572,7 +572,6 @@ int mlxsw_sp_acl_rulei_act_mirror(struct mlxsw_sp *mlxsw_sp,
struct net_device *out_dev)
{
struct mlxsw_sp_acl_block_binding *binding;
- struct mlxsw_sp_port *out_port;
struct mlxsw_sp_port *in_port;
if (!list_is_singular(&block->binding_list))
@@ -581,9 +580,6 @@ int mlxsw_sp_acl_rulei_act_mirror(struct mlxsw_sp *mlxsw_sp,
binding = list_first_entry(&block->binding_list,
struct mlxsw_sp_acl_block_binding, list);
in_port = binding->mlxsw_sp_port;
- out_port = netdev_priv(out_dev);
- if (out_port->mlxsw_sp != mlxsw_sp)
- return -EINVAL;
return mlxsw_afa_block_append_mirror(rulei->act_block,
in_port->local_port,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
index 71102f156a97..57df57c7a405 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
@@ -164,7 +164,11 @@ mlxsw_sp_span_entry_configure(struct mlxsw_sp *mlxsw_sp,
struct mlxsw_sp_span_parms sparms)
{
if (sparms.dest_port) {
- if (span_entry->ops->configure(span_entry, sparms)) {
+ if (sparms.dest_port->mlxsw_sp != mlxsw_sp) {
+ netdev_err(span_entry->to_dev, "Cannot mirror to %s, which belongs to a different mlxsw instance",
+ sparms.dest_port->dev->name);
+ sparms.dest_port = NULL;
+ } else if (span_entry->ops->configure(span_entry, sparms)) {
netdev_err(span_entry->to_dev, "Failed to offload mirror to %s",
sparms.dest_port->dev->name);
sparms.dest_port = NULL;
--
2.14.3
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [patch net-next 14/15] mlxsw: spectrum_span: Support mirror to gretap
2018-02-27 13:53 [patch net-next 00/15] mlxsw: Offloading encapsulated SPAN Jiri Pirko
` (12 preceding siblings ...)
2018-02-27 13:53 ` [patch net-next 13/15] mlxsw: Move a mirroring check to mlxsw_sp_span_entry_create Jiri Pirko
@ 2018-02-27 13:53 ` Jiri Pirko
2018-02-27 13:53 ` [patch net-next 15/15] mlxsw: spectrum_span: Support mirror to ip6gretap Jiri Pirko
2018-02-27 19:52 ` [patch net-next 00/15] mlxsw: Offloading encapsulated SPAN David Miller
15 siblings, 0 replies; 20+ messages in thread
From: Jiri Pirko @ 2018-02-27 13:53 UTC (permalink / raw)
To: netdev; +Cc: davem, petrm, idosch, mlxsw, xeb, dsa
From: Petr Machata <petrm@mellanox.com>
When a user requests mirror from a mlxsw physical port (possibly based
on an ACL match) to a gretap netdevice, the driver needs to resolve the
request to a particular physical port that the mirrored packets will
egress through, and a suite of configuration keys (importantly, IP and
MAC addresses). That means calling into routing and neighbor kernel code
to simulate the decisions made by the system for packets passing through
a gretap netdevice.
Add a new instance of mlxsw_sp_span_entry_ops to support this.
Signed-off-by: Petr Machata <petrm@mellanox.com>
Reviewed-by: Ido Schimmel <idosch@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
---
drivers/net/ethernet/mellanox/mlxsw/Kconfig | 2 +
.../net/ethernet/mellanox/mlxsw/spectrum_span.c | 167 ++++++++++++++++++++-
.../net/ethernet/mellanox/mlxsw/spectrum_span.h | 8 +
3 files changed, 175 insertions(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/Kconfig b/drivers/net/ethernet/mellanox/mlxsw/Kconfig
index d56eea310509..830c3e28505e 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/Kconfig
+++ b/drivers/net/ethernet/mellanox/mlxsw/Kconfig
@@ -78,6 +78,8 @@ config MLXSW_SPECTRUM
depends on IPV6 || IPV6=n
select PARMAN
select MLXFW
+ depends on NET_IPGRE
+ depends on !(MLXSW_CORE=y && NET_IPGRE=m)
default m
---help---
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 57df57c7a405..d5fda4f13c31 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
@@ -1,6 +1,7 @@
/*
* drivers/net/ethernet/mellanox/mlxsw/mlxsw_span.c
* Copyright (c) 2018 Mellanox Technologies. All rights reserved.
+ * Copyright (c) 2018 Petr Machata <petrm@mellanox.com>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@@ -32,9 +33,12 @@
*/
#include <linux/list.h>
+#include <net/arp.h>
+#include <net/gre.h>
#include "spectrum.h"
#include "spectrum_span.h"
+#include "spectrum_ipip.h"
int mlxsw_sp_span_init(struct mlxsw_sp *mlxsw_sp)
{
@@ -127,17 +131,176 @@ struct mlxsw_sp_span_entry_ops mlxsw_sp_span_entry_ops_phys = {
.deconfigure = mlxsw_sp_span_entry_phys_deconfigure,
};
+static struct net_device *
+mlxsw_sp_span_gretap4_route(const struct net_device *to_dev,
+ __be32 *saddrp, __be32 *daddrp)
+{
+ struct ip_tunnel *tun = netdev_priv(to_dev);
+ struct net_device *dev = NULL;
+ struct ip_tunnel_parm parms;
+ struct rtable *rt = NULL;
+ struct flowi4 fl4;
+
+ /* We assume "dev" stays valid after rt is put. */
+ ASSERT_RTNL();
+
+ parms = mlxsw_sp_ipip_netdev_parms4(to_dev);
+ ip_tunnel_init_flow(&fl4, parms.iph.protocol, *daddrp, *saddrp,
+ 0, 0, parms.link, tun->fwmark);
+
+ rt = ip_route_output_key(tun->net, &fl4);
+ if (IS_ERR(rt))
+ return NULL;
+
+ if (rt->rt_type != RTN_UNICAST)
+ goto out;
+
+ dev = rt->dst.dev;
+ *saddrp = fl4.saddr;
+ *daddrp = rt->rt_gateway;
+
+out:
+ ip_rt_put(rt);
+ return dev;
+}
+
+static int mlxsw_sp_span_dmac(struct neigh_table *tbl,
+ const void *pkey,
+ struct net_device *l3edev,
+ unsigned char dmac[ETH_ALEN])
+{
+ struct neighbour *neigh = neigh_lookup(tbl, pkey, l3edev);
+ int err = 0;
+
+ if (!neigh) {
+ neigh = neigh_create(tbl, pkey, l3edev);
+ if (IS_ERR(neigh))
+ return PTR_ERR(neigh);
+ }
+
+ neigh_event_send(neigh, NULL);
+
+ read_lock_bh(&neigh->lock);
+ if ((neigh->nud_state & NUD_VALID) && !neigh->dead)
+ memcpy(dmac, neigh->ha, ETH_ALEN);
+ else
+ err = -ENOENT;
+ read_unlock_bh(&neigh->lock);
+
+ neigh_release(neigh);
+ return err;
+}
+
+static int
+mlxsw_sp_span_entry_unoffloadable(struct mlxsw_sp_span_parms *sparmsp)
+{
+ sparmsp->dest_port = NULL;
+ return 0;
+}
+
+static int
+mlxsw_sp_span_entry_tunnel_parms_common(struct net_device *l3edev,
+ union mlxsw_sp_l3addr saddr,
+ union mlxsw_sp_l3addr daddr,
+ union mlxsw_sp_l3addr gw,
+ __u8 ttl,
+ struct neigh_table *tbl,
+ struct mlxsw_sp_span_parms *sparmsp)
+{
+ unsigned char dmac[ETH_ALEN];
+
+ if (mlxsw_sp_l3addr_is_zero(gw))
+ gw = daddr;
+
+ if (!l3edev || !mlxsw_sp_port_dev_check(l3edev) ||
+ mlxsw_sp_span_dmac(tbl, &gw, l3edev, dmac))
+ return mlxsw_sp_span_entry_unoffloadable(sparmsp);
+
+ sparmsp->dest_port = netdev_priv(l3edev);
+ sparmsp->ttl = ttl;
+ memcpy(sparmsp->dmac, dmac, ETH_ALEN);
+ memcpy(sparmsp->smac, l3edev->dev_addr, ETH_ALEN);
+ sparmsp->saddr = saddr;
+ sparmsp->daddr = daddr;
+ return 0;
+}
+
+static int
+mlxsw_sp_span_entry_gretap4_parms(const struct net_device *to_dev,
+ struct mlxsw_sp_span_parms *sparmsp)
+{
+ struct ip_tunnel_parm tparm = mlxsw_sp_ipip_netdev_parms4(to_dev);
+ union mlxsw_sp_l3addr saddr = { .addr4 = tparm.iph.saddr };
+ union mlxsw_sp_l3addr daddr = { .addr4 = tparm.iph.daddr };
+ bool inherit_tos = tparm.iph.tos & 0x1;
+ bool inherit_ttl = !tparm.iph.ttl;
+ union mlxsw_sp_l3addr gw = daddr;
+ struct net_device *l3edev;
+
+ if (!(to_dev->flags & IFF_UP) ||
+ /* Reject tunnels with GRE keys, checksums, etc. */
+ tparm.i_flags || tparm.o_flags ||
+ /* Require a fixed TTL and a TOS copied from the mirrored packet. */
+ inherit_ttl || !inherit_tos ||
+ /* A destination address may not be "any". */
+ mlxsw_sp_l3addr_is_zero(daddr))
+ return mlxsw_sp_span_entry_unoffloadable(sparmsp);
+
+ l3edev = mlxsw_sp_span_gretap4_route(to_dev, &saddr.addr4, &gw.addr4);
+ return mlxsw_sp_span_entry_tunnel_parms_common(l3edev, saddr, daddr, gw,
+ tparm.iph.ttl,
+ &arp_tbl, sparmsp);
+}
+
+static int
+mlxsw_sp_span_entry_gretap4_configure(struct mlxsw_sp_span_entry *span_entry,
+ struct mlxsw_sp_span_parms sparms)
+{
+ struct mlxsw_sp_port *dest_port = sparms.dest_port;
+ struct mlxsw_sp *mlxsw_sp = dest_port->mlxsw_sp;
+ u8 local_port = dest_port->local_port;
+ char mpat_pl[MLXSW_REG_MPAT_LEN];
+ int pa_id = span_entry->id;
+
+ /* Create a new port analayzer entry for local_port. */
+ mlxsw_reg_mpat_pack(mpat_pl, pa_id, local_port, true,
+ MLXSW_REG_MPAT_SPAN_TYPE_REMOTE_ETH_L3);
+ mlxsw_reg_mpat_eth_rspan_l2_pack(mpat_pl,
+ MLXSW_REG_MPAT_ETH_RSPAN_VERSION_NO_HEADER,
+ sparms.dmac, false);
+ mlxsw_reg_mpat_eth_rspan_l3_ipv4_pack(mpat_pl,
+ sparms.ttl, sparms.smac,
+ be32_to_cpu(sparms.saddr.addr4),
+ be32_to_cpu(sparms.daddr.addr4));
+
+ return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpat), mpat_pl);
+}
+
+static void
+mlxsw_sp_span_entry_gretap4_deconfigure(struct mlxsw_sp_span_entry *span_entry)
+{
+ mlxsw_sp_span_entry_deconfigure_common(span_entry,
+ MLXSW_REG_MPAT_SPAN_TYPE_REMOTE_ETH_L3);
+}
+
+static const struct mlxsw_sp_span_entry_ops mlxsw_sp_span_entry_ops_gretap4 = {
+ .can_handle = is_gretap_dev,
+ .parms = mlxsw_sp_span_entry_gretap4_parms,
+ .configure = mlxsw_sp_span_entry_gretap4_configure,
+ .deconfigure = mlxsw_sp_span_entry_gretap4_deconfigure,
+};
+
static const
struct mlxsw_sp_span_entry_ops *const mlxsw_sp_span_entry_types[] = {
&mlxsw_sp_span_entry_ops_phys,
+ &mlxsw_sp_span_entry_ops_gretap4,
};
static int
mlxsw_sp_span_entry_nop_parms(const struct net_device *to_dev,
struct mlxsw_sp_span_parms *sparmsp)
{
- sparmsp->dest_port = NULL;
- return 0;
+ return mlxsw_sp_span_entry_unoffloadable(sparmsp);
}
static int
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.h
index b6dcd7d7277c..948aceb512c5 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.h
@@ -35,6 +35,9 @@
#define _MLXSW_SPECTRUM_SPAN_H
#include <linux/types.h>
+#include <linux/if_ether.h>
+
+#include "spectrum_router.h"
struct mlxsw_sp;
struct mlxsw_sp_port;
@@ -52,6 +55,11 @@ struct mlxsw_sp_span_inspected_port {
struct mlxsw_sp_span_parms {
struct mlxsw_sp_port *dest_port; /* NULL for unoffloaded SPAN. */
+ unsigned int ttl;
+ unsigned char dmac[ETH_ALEN];
+ unsigned char smac[ETH_ALEN];
+ union mlxsw_sp_l3addr daddr;
+ union mlxsw_sp_l3addr saddr;
};
struct mlxsw_sp_span_entry_ops;
--
2.14.3
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [patch net-next 15/15] mlxsw: spectrum_span: Support mirror to ip6gretap
2018-02-27 13:53 [patch net-next 00/15] mlxsw: Offloading encapsulated SPAN Jiri Pirko
` (13 preceding siblings ...)
2018-02-27 13:53 ` [patch net-next 14/15] mlxsw: spectrum_span: Support mirror to gretap Jiri Pirko
@ 2018-02-27 13:53 ` Jiri Pirko
2018-02-27 20:17 ` David Ahern
2018-02-27 19:52 ` [patch net-next 00/15] mlxsw: Offloading encapsulated SPAN David Miller
15 siblings, 1 reply; 20+ messages in thread
From: Jiri Pirko @ 2018-02-27 13:53 UTC (permalink / raw)
To: netdev; +Cc: davem, petrm, idosch, mlxsw, xeb, dsa
From: Petr Machata <petrm@mellanox.com>
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>
---
drivers/net/ethernet/mellanox/mlxsw/Kconfig | 2 +
.../net/ethernet/mellanox/mlxsw/spectrum_span.c | 101 +++++++++++++++++++++
2 files changed, 103 insertions(+)
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
select MLXFW
depends on NET_IPGRE
depends on !(MLXSW_CORE=y && NET_IPGRE=m)
+ depends on IPV6_GRE
+ depends on !(MLXSW_CORE=y && IPV6_GRE=m)
default m
---help---
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 @@
#include <linux/list.h>
#include <net/arp.h>
#include <net/gre.h>
+#include <net/ndisc.h>
+#include <net/ip6_tunnel.h>
#include "spectrum.h"
#include "spectrum_span.h"
@@ -290,10 +292,109 @@ static const struct mlxsw_sp_span_entry_ops mlxsw_sp_span_entry_ops_gretap4 = {
.deconfigure = mlxsw_sp_span_entry_gretap4_deconfigure,
};
+static struct net_device *
+mlxsw_sp_span_gretap6_route(const struct net_device *to_dev,
+ struct in6_addr *saddrp,
+ struct in6_addr *daddrp)
+{
+ struct ip6_tnl *t = netdev_priv(to_dev);
+ struct flowi6 fl6 = t->fl.u.ip6;
+ struct net_device *dev = NULL;
+ struct dst_entry *dst;
+ struct rt6_info *rt6;
+
+ /* We assume "dev" stays valid after dst is released. */
+ ASSERT_RTNL();
+
+ fl6.flowi6_mark = t->parms.fwmark;
+ if (!ip6_tnl_xmit_ctl(t, &fl6.saddr, &fl6.daddr))
+ return NULL;
+
+ dst = ip6_route_output(t->net, NULL, &fl6);
+ if (!dst || dst->error)
+ goto out;
+
+ rt6 = container_of(dst, struct rt6_info, dst);
+
+ dev = dst->dev;
+ *saddrp = fl6.saddr;
+ *daddrp = rt6->rt6i_gateway;
+
+out:
+ dst_release(dst);
+ return dev;
+}
+
+static int
+mlxsw_sp_span_entry_gretap6_parms(const struct net_device *to_dev,
+ struct mlxsw_sp_span_parms *sparmsp)
+{
+ struct __ip6_tnl_parm tparm = mlxsw_sp_ipip_netdev_parms6(to_dev);
+ bool inherit_tos = tparm.flags & IP6_TNL_F_USE_ORIG_TCLASS;
+ union mlxsw_sp_l3addr saddr = { .addr6 = tparm.laddr };
+ union mlxsw_sp_l3addr daddr = { .addr6 = tparm.raddr };
+ bool inherit_ttl = !tparm.hop_limit;
+ union mlxsw_sp_l3addr gw = daddr;
+ struct net_device *l3edev;
+
+ if (!(to_dev->flags & IFF_UP) ||
+ /* Reject tunnels with GRE keys, checksums, etc. */
+ tparm.i_flags || tparm.o_flags ||
+ /* Require a fixed TTL and a TOS copied from the mirrored packet. */
+ inherit_ttl || !inherit_tos ||
+ /* A destination address may not be "any". */
+ mlxsw_sp_l3addr_is_zero(daddr))
+ return mlxsw_sp_span_entry_unoffloadable(sparmsp);
+
+ l3edev = mlxsw_sp_span_gretap6_route(to_dev, &saddr.addr6, &gw.addr6);
+ return mlxsw_sp_span_entry_tunnel_parms_common(l3edev, saddr, daddr, gw,
+ tparm.hop_limit,
+ &nd_tbl, sparmsp);
+}
+
+static int
+mlxsw_sp_span_entry_gretap6_configure(struct mlxsw_sp_span_entry *span_entry,
+ struct mlxsw_sp_span_parms sparms)
+{
+ struct mlxsw_sp_port *dest_port = sparms.dest_port;
+ struct mlxsw_sp *mlxsw_sp = dest_port->mlxsw_sp;
+ u8 local_port = dest_port->local_port;
+ char mpat_pl[MLXSW_REG_MPAT_LEN];
+ int pa_id = span_entry->id;
+
+ /* Create a new port analayzer entry for local_port. */
+ mlxsw_reg_mpat_pack(mpat_pl, pa_id, local_port, true,
+ MLXSW_REG_MPAT_SPAN_TYPE_REMOTE_ETH_L3);
+ mlxsw_reg_mpat_eth_rspan_l2_pack(mpat_pl,
+ MLXSW_REG_MPAT_ETH_RSPAN_VERSION_NO_HEADER,
+ sparms.dmac, false);
+ mlxsw_reg_mpat_eth_rspan_l3_ipv6_pack(mpat_pl, sparms.ttl, sparms.smac,
+ sparms.saddr.addr6,
+ sparms.daddr.addr6);
+
+ return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mpat), mpat_pl);
+}
+
+static void
+mlxsw_sp_span_entry_gretap6_deconfigure(struct mlxsw_sp_span_entry *span_entry)
+{
+ mlxsw_sp_span_entry_deconfigure_common(span_entry,
+ MLXSW_REG_MPAT_SPAN_TYPE_REMOTE_ETH_L3);
+}
+
+static const
+struct mlxsw_sp_span_entry_ops mlxsw_sp_span_entry_ops_gretap6 = {
+ .can_handle = is_ip6gretap_dev,
+ .parms = mlxsw_sp_span_entry_gretap6_parms,
+ .configure = mlxsw_sp_span_entry_gretap6_configure,
+ .deconfigure = mlxsw_sp_span_entry_gretap6_deconfigure,
+};
+
static const
struct mlxsw_sp_span_entry_ops *const mlxsw_sp_span_entry_types[] = {
&mlxsw_sp_span_entry_ops_phys,
&mlxsw_sp_span_entry_ops_gretap4,
+ &mlxsw_sp_span_entry_ops_gretap6,
};
static int
--
2.14.3
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [patch net-next 00/15] mlxsw: Offloading encapsulated SPAN
2018-02-27 13:53 [patch net-next 00/15] mlxsw: Offloading encapsulated SPAN Jiri Pirko
` (14 preceding siblings ...)
2018-02-27 13:53 ` [patch net-next 15/15] mlxsw: spectrum_span: Support mirror to ip6gretap Jiri Pirko
@ 2018-02-27 19:52 ` David Miller
15 siblings, 0 replies; 20+ messages in thread
From: David Miller @ 2018-02-27 19:52 UTC (permalink / raw)
To: jiri; +Cc: netdev, petrm, idosch, mlxsw, xeb, dsa
From: Jiri Pirko <jiri@resnulli.us>
Date: Tue, 27 Feb 2018 14:53:34 +0100
> From: Jiri Pirko <jiri@mellanox.com>
>
> Petr says:
>
> This patch series introduces support for mirroring with GRE
> encapsulation. It offloads tc action mirred mirror from a mlxsw port to
> either a gretap or an ip6gretap netdevice.
Ok, series applied.
People will have to be really careful when using those new device
type detection helpers.
It's adding another case where the feature has to be enabled and
the modularity has to be the same as the referencing module.
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [patch net-next 15/15] mlxsw: spectrum_span: Support mirror to ip6gretap
2018-02-27 13:53 ` [patch net-next 15/15] mlxsw: spectrum_span: Support mirror to ip6gretap Jiri Pirko
@ 2018-02-27 20:17 ` David Ahern
2018-02-27 21:08 ` Petr Machata
2018-02-28 14:35 ` Petr Machata
0 siblings, 2 replies; 20+ messages in thread
From: David Ahern @ 2018-02-27 20:17 UTC (permalink / raw)
To: Jiri Pirko, netdev, idosch; +Cc: davem, petrm, mlxsw, xeb
On 2/27/18 6:53 AM, Jiri Pirko wrote:
> 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
> select MLXFW
> depends on NET_IPGRE
> depends on !(MLXSW_CORE=y && NET_IPGRE=m)
> + depends on IPV6_GRE
> + depends on !(MLXSW_CORE=y && IPV6_GRE=m)
> default m
> ---help---
> This driver supports Mellanox Technologies Spectrum Ethernet
Since mlxsw now has a hard dependency on IPv6 the 'if
IS_ENABLED(CONFIG_IPV6)' checks can be removed from the spectrum code.
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [patch net-next 15/15] mlxsw: spectrum_span: Support mirror to ip6gretap
2018-02-27 20:17 ` David Ahern
@ 2018-02-27 21:08 ` Petr Machata
2018-02-28 14:35 ` Petr Machata
1 sibling, 0 replies; 20+ messages in thread
From: Petr Machata @ 2018-02-27 21:08 UTC (permalink / raw)
To: David Ahern; +Cc: Jiri Pirko, netdev, idosch, davem, mlxsw, xeb
David Ahern <dsa@cumulusnetworks.com> writes:
> On 2/27/18 6:53 AM, Jiri Pirko wrote:
>> 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
>> select MLXFW
>> depends on NET_IPGRE
>> depends on !(MLXSW_CORE=y && NET_IPGRE=m)
>> + depends on IPV6_GRE
>> + depends on !(MLXSW_CORE=y && IPV6_GRE=m)
>> default m
>> ---help---
>> This driver supports Mellanox Technologies Spectrum Ethernet
>
> Since mlxsw now has a hard dependency on IPv6 the 'if
> IS_ENABLED(CONFIG_IPV6)' checks can be removed from the spectrum code.
Sure, I'll send a follow-up patch for that.
Thanks,
Petr
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [patch net-next 15/15] mlxsw: spectrum_span: Support mirror to ip6gretap
2018-02-27 20:17 ` David Ahern
2018-02-27 21:08 ` Petr Machata
@ 2018-02-28 14:35 ` Petr Machata
1 sibling, 0 replies; 20+ messages in thread
From: Petr Machata @ 2018-02-28 14:35 UTC (permalink / raw)
To: David Ahern; +Cc: Jiri Pirko, netdev, idosch, davem, mlxsw, xeb
David Ahern <dsa@cumulusnetworks.com> writes:
> On 2/27/18 6:53 AM, Jiri Pirko wrote:
>> 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
>> select MLXFW
>> depends on NET_IPGRE
>> depends on !(MLXSW_CORE=y && NET_IPGRE=m)
>> + depends on IPV6_GRE
>> + depends on !(MLXSW_CORE=y && IPV6_GRE=m)
>> default m
>> ---help---
>> This driver supports Mellanox Technologies Spectrum Ethernet
>
> Since mlxsw now has a hard dependency on IPv6 the 'if
> IS_ENABLED(CONFIG_IPV6)' checks can be removed from the spectrum code.
I'll add a default implementation of is_gretap_dev and is_ip6gretap_dev
for cases where the corresponding code is not selected so that the
Spectrum driver doesn't depend on all these modules.
Thanks,
Petr
^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2018-02-28 14:36 UTC | newest]
Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-02-27 13:53 [patch net-next 00/15] mlxsw: Offloading encapsulated SPAN Jiri Pirko
2018-02-27 13:53 ` [patch net-next 01/15] mlxsw: spectrum_ipip: Extract mlxsw_sp_l3addr_is_zero Jiri Pirko
2018-02-27 13:53 ` [patch net-next 02/15] mlxsw: spectrum_ipip: Support decoding IPv6 tunnel addresses Jiri Pirko
2018-02-27 13:53 ` [patch net-next 03/15] net: GRE: Add is_gretap_dev, is_ip6gretap_dev Jiri Pirko
2018-02-27 13:53 ` [patch net-next 04/15] ip_tunnel: Rename & publish init_tunnel_flow Jiri Pirko
2018-02-27 13:53 ` [patch net-next 05/15] mlxsw: reg: Add SPAN encapsulation to MPAT register Jiri Pirko
2018-02-27 13:53 ` [patch net-next 06/15] mlxsw: reg: Extend mlxsw_reg_mpat_pack() Jiri Pirko
2018-02-27 13:53 ` [patch net-next 07/15] mlxsw: span: Remove span_entry by span_id Jiri Pirko
2018-02-27 13:53 ` [patch net-next 08/15] mlxsw: spectrum_span: Initialize span_entry.id eagerly Jiri Pirko
2018-02-27 13:53 ` [patch net-next 09/15] mlxsw: spectrum_span: Extract mlxsw_sp_span_entry_{de,}configure() Jiri Pirko
2018-02-27 13:53 ` [patch net-next 10/15] mlxsw: spectrum: Keep mirror netdev in mlxsw_sp_span_entry Jiri Pirko
2018-02-27 13:53 ` [patch net-next 11/15] mlxsw: spectrum_span: Generalize SPAN support Jiri Pirko
2018-02-27 13:53 ` [patch net-next 12/15] mlxsw: Handle config changes pertinent to SPAN Jiri Pirko
2018-02-27 13:53 ` [patch net-next 13/15] mlxsw: Move a mirroring check to mlxsw_sp_span_entry_create Jiri Pirko
2018-02-27 13:53 ` [patch net-next 14/15] mlxsw: spectrum_span: Support mirror to gretap Jiri Pirko
2018-02-27 13:53 ` [patch net-next 15/15] mlxsw: spectrum_span: Support mirror to ip6gretap Jiri Pirko
2018-02-27 20:17 ` David Ahern
2018-02-27 21:08 ` Petr Machata
2018-02-28 14:35 ` Petr Machata
2018-02-27 19:52 ` [patch net-next 00/15] mlxsw: Offloading encapsulated SPAN David Miller
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).