Skip to content

Commit

Permalink
Merge branch 'mlxsw-Add-tunnel-devlink-trap-support'
Browse files Browse the repository at this point in the history
Ido Schimmel says:

====================
mlxsw: Add tunnel devlink-trap support

This patch set from Amit adds support in mlxsw for tunnel traps and a
few additional layer 3 traps that can report drops and exceptions via
devlink-trap.

These traps allow the user to more quickly diagnose problems relating to
tunnel decapsulation errors, such as packet being too short to
decapsulate or a packet containing wrong GRE key in its GRE header.

Patch set overview:

Patches #1-#4 add three additional layer 3 traps. Two of which are
mlxsw-specific as they relate to hardware-specific errors. The patches
include documentation of each trap and selftests.

Patches #5-torvalds#8 are preparations. They ensure that the correct ECN bits
are set in the outer header during IPinIP encapsulation and that packets
with an invalid ECN combination in underlay and overlay are trapped to
the kernel and not decapsulated in hardware.

Patches torvalds#9-torvalds#15 add support for two tunnel related traps. Each trap is
documented and selftested using both VXLAN and IPinIP tunnels, if
applicable.
====================

Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
davem330 committed Jan 19, 2020
2 parents 95ae2d1 + b3073df commit 4ee9e6e
Show file tree
Hide file tree
Showing 14 changed files with 981 additions and 4 deletions.
19 changes: 19 additions & 0 deletions Documentation/networking/devlink/devlink-trap.rst
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,21 @@ be added to the following table:
* - ``ipv6_lpm_miss``
- ``exception``
- Traps unicast IPv6 packets that did not match any route
* - ``non_routable_packet``
- ``drop``
- Traps packets that the device decided to drop because they are not
supposed to be routed. For example, IGMP queries can be flooded by the
device in layer 2 and reach the router. Such packets should not be
routed and instead dropped
* - ``decap_error``
- ``exception``
- Traps NVE and IPinIP packets that the device decided to drop because of
failure during decapsulation (e.g., packet being too short, reserved
bits set in VXLAN header)
* - ``overlay_smac_is_mc``
- ``drop``
- Traps NVE packets that the device decided to drop because their overlay
source MAC is multicast

Driver-specific Packet Traps
============================
Expand All @@ -234,6 +249,7 @@ links to the description of driver-specific traps registered by various device
drivers:

* :doc:`netdevsim`
* :doc:`mlxsw`

Generic Packet Trap Groups
==========================
Expand All @@ -258,6 +274,9 @@ narrow. The description of these groups must be added to the following table:
* - ``buffer_drops``
- Contains packet traps for packets that were dropped by the device due to
an enqueue decision
* - ``tunnel_drops``
- Contains packet traps for packets that were dropped by the device during
tunnel encapsulation / decapsulation

Testing
=======
Expand Down
22 changes: 22 additions & 0 deletions Documentation/networking/devlink/mlxsw.rst
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,25 @@ The ``mlxsw`` driver reports the following versions
* - ``fw.version``
- running
- Three digit firmware version

Driver-specific Traps
=====================

.. list-table:: List of Driver-specific Traps Registered by ``mlxsw``
:widths: 5 5 90

* - Name
- Type
- Description
* - ``irif_disabled``
- ``drop``
- Traps packets that the device decided to drop because they need to be
routed from a disabled router interface (RIF). This can happen during
RIF dismantle, when the RIF is first disabled before being removed
completely
* - ``erif_disabled``
- ``drop``
- Traps packets that the device decided to drop because they need to be
routed through a disabled router interface (RIF). This can happen during
RIF dismantle, when the RIF is first disabled before being removed
completely
89 changes: 89 additions & 0 deletions drivers/net/ethernet/mellanox/mlxsw/reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -5513,6 +5513,7 @@ enum mlxsw_reg_htgt_discard_trap_group {
MLXSW_REG_HTGT_DISCARD_TRAP_GROUP_BASE = MLXSW_REG_HTGT_TRAP_GROUP_MAX,
MLXSW_REG_HTGT_TRAP_GROUP_SP_L2_DISCARDS,
MLXSW_REG_HTGT_TRAP_GROUP_SP_L3_DISCARDS,
MLXSW_REG_HTGT_TRAP_GROUP_SP_TUNNEL_DISCARDS,
};

/* reg_htgt_trap_group
Expand Down Expand Up @@ -10140,6 +10141,92 @@ static inline void mlxsw_reg_tigcr_pack(char *payload, bool ttlc, u8 ttl_uc)
mlxsw_reg_tigcr_ttl_uc_set(payload, ttl_uc);
}

/* TIEEM - Tunneling IPinIP Encapsulation ECN Mapping Register
* -----------------------------------------------------------
* The TIEEM register maps ECN of the IP header at the ingress to the
* encapsulation to the ECN of the underlay network.
*/
#define MLXSW_REG_TIEEM_ID 0xA812
#define MLXSW_REG_TIEEM_LEN 0x0C

MLXSW_REG_DEFINE(tieem, MLXSW_REG_TIEEM_ID, MLXSW_REG_TIEEM_LEN);

/* reg_tieem_overlay_ecn
* ECN of the IP header in the overlay network.
* Access: Index
*/
MLXSW_ITEM32(reg, tieem, overlay_ecn, 0x04, 24, 2);

/* reg_tineem_underlay_ecn
* ECN of the IP header in the underlay network.
* Access: RW
*/
MLXSW_ITEM32(reg, tieem, underlay_ecn, 0x04, 16, 2);

static inline void mlxsw_reg_tieem_pack(char *payload, u8 overlay_ecn,
u8 underlay_ecn)
{
MLXSW_REG_ZERO(tieem, payload);
mlxsw_reg_tieem_overlay_ecn_set(payload, overlay_ecn);
mlxsw_reg_tieem_underlay_ecn_set(payload, underlay_ecn);
}

/* TIDEM - Tunneling IPinIP Decapsulation ECN Mapping Register
* -----------------------------------------------------------
* The TIDEM register configures the actions that are done in the
* decapsulation.
*/
#define MLXSW_REG_TIDEM_ID 0xA813
#define MLXSW_REG_TIDEM_LEN 0x0C

MLXSW_REG_DEFINE(tidem, MLXSW_REG_TIDEM_ID, MLXSW_REG_TIDEM_LEN);

/* reg_tidem_underlay_ecn
* ECN field of the IP header in the underlay network.
* Access: Index
*/
MLXSW_ITEM32(reg, tidem, underlay_ecn, 0x04, 24, 2);

/* reg_tidem_overlay_ecn
* ECN field of the IP header in the overlay network.
* Access: Index
*/
MLXSW_ITEM32(reg, tidem, overlay_ecn, 0x04, 16, 2);

/* reg_tidem_eip_ecn
* Egress IP ECN. ECN field of the IP header of the packet which goes out
* from the decapsulation.
* Access: RW
*/
MLXSW_ITEM32(reg, tidem, eip_ecn, 0x04, 8, 2);

/* reg_tidem_trap_en
* Trap enable:
* 0 - No trap due to decap ECN
* 1 - Trap enable with trap_id
* Access: RW
*/
MLXSW_ITEM32(reg, tidem, trap_en, 0x08, 28, 4);

/* reg_tidem_trap_id
* Trap ID. Either DECAP_ECN0 or DECAP_ECN1.
* Reserved when trap_en is '0'.
* Access: RW
*/
MLXSW_ITEM32(reg, tidem, trap_id, 0x08, 0, 9);

static inline void mlxsw_reg_tidem_pack(char *payload, u8 underlay_ecn,
u8 overlay_ecn, u8 eip_ecn,
bool trap_en, u16 trap_id)
{
MLXSW_REG_ZERO(tidem, payload);
mlxsw_reg_tidem_underlay_ecn_set(payload, underlay_ecn);
mlxsw_reg_tidem_overlay_ecn_set(payload, overlay_ecn);
mlxsw_reg_tidem_eip_ecn_set(payload, eip_ecn);
mlxsw_reg_tidem_trap_en_set(payload, trap_en);
mlxsw_reg_tidem_trap_id_set(payload, trap_id);
}

/* SBPR - Shared Buffer Pools Register
* -----------------------------------
* The SBPR configures and retrieves the shared buffer pools and configuration.
Expand Down Expand Up @@ -10684,6 +10771,8 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = {
MLXSW_REG(tndem),
MLXSW_REG(tnpc),
MLXSW_REG(tigcr),
MLXSW_REG(tieem),
MLXSW_REG(tidem),
MLXSW_REG(sbpr),
MLXSW_REG(sbcm),
MLXSW_REG(sbpm),
Expand Down
2 changes: 0 additions & 2 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum.c
Original file line number Diff line number Diff line change
Expand Up @@ -4538,8 +4538,6 @@ static const struct mlxsw_listener mlxsw_sp_listener[] = {
false),
MLXSW_SP_RXL_MARK(ROUTER_ALERT_IPV4, TRAP_TO_CPU, ROUTER_EXP, false),
MLXSW_SP_RXL_MARK(ROUTER_ALERT_IPV6, TRAP_TO_CPU, ROUTER_EXP, false),
MLXSW_SP_RXL_MARK(IPIP_DECAP_ERROR, TRAP_TO_CPU, ROUTER_EXP, false),
MLXSW_SP_RXL_MARK(DECAP_ECN0, TRAP_TO_CPU, ROUTER_EXP, false),
MLXSW_SP_RXL_MARK(IPV4_VRRP, TRAP_TO_CPU, VRRP, false),
MLXSW_SP_RXL_MARK(IPV6_VRRP, TRAP_TO_CPU, VRRP, false),
MLXSW_SP_RXL_NO_MARK(DISCARD_ING_ROUTER_SIP_CLASS_E, FORWARD,
Expand Down
60 changes: 60 additions & 0 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@

#include <net/ip_tunnels.h>
#include <net/ip6_tunnel.h>
#include <net/inet_ecn.h>

#include "spectrum_ipip.h"
#include "reg.h"

struct ip_tunnel_parm
mlxsw_sp_ipip_netdev_parms4(const struct net_device *ol_dev)
Expand Down Expand Up @@ -338,3 +340,61 @@ static const struct mlxsw_sp_ipip_ops mlxsw_sp_ipip_gre4_ops = {
const struct mlxsw_sp_ipip_ops *mlxsw_sp_ipip_ops_arr[] = {
[MLXSW_SP_IPIP_TYPE_GRE4] = &mlxsw_sp_ipip_gre4_ops,
};

static int mlxsw_sp_ipip_ecn_encap_init_one(struct mlxsw_sp *mlxsw_sp,
u8 inner_ecn, u8 outer_ecn)
{
char tieem_pl[MLXSW_REG_TIEEM_LEN];

mlxsw_reg_tieem_pack(tieem_pl, inner_ecn, outer_ecn);
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(tieem), tieem_pl);
}

int mlxsw_sp_ipip_ecn_encap_init(struct mlxsw_sp *mlxsw_sp)
{
int i;

/* Iterate over inner ECN values */
for (i = INET_ECN_NOT_ECT; i <= INET_ECN_CE; i++) {
u8 outer_ecn = INET_ECN_encapsulate(0, i);
int err;

err = mlxsw_sp_ipip_ecn_encap_init_one(mlxsw_sp, i, outer_ecn);
if (err)
return err;
}

return 0;
}

static int mlxsw_sp_ipip_ecn_decap_init_one(struct mlxsw_sp *mlxsw_sp,
u8 inner_ecn, u8 outer_ecn)
{
char tidem_pl[MLXSW_REG_TIDEM_LEN];
bool trap_en, set_ce = false;
u8 new_inner_ecn;

trap_en = __INET_ECN_decapsulate(outer_ecn, inner_ecn, &set_ce);
new_inner_ecn = set_ce ? INET_ECN_CE : inner_ecn;

mlxsw_reg_tidem_pack(tidem_pl, outer_ecn, inner_ecn, new_inner_ecn,
trap_en, trap_en ? MLXSW_TRAP_ID_DECAP_ECN0 : 0);
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(tidem), tidem_pl);
}

int mlxsw_sp_ipip_ecn_decap_init(struct mlxsw_sp *mlxsw_sp)
{
int i, j, err;

/* Iterate over inner ECN values */
for (i = INET_ECN_NOT_ECT; i <= INET_ECN_CE; i++) {
/* Iterate over outer ECN values */
for (j = INET_ECN_NOT_ECT; j <= INET_ECN_CE; j++) {
err = mlxsw_sp_ipip_ecn_decap_init_one(mlxsw_sp, i, j);
if (err)
return err;
}
}

return 0;
}
10 changes: 10 additions & 0 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
Original file line number Diff line number Diff line change
Expand Up @@ -7791,8 +7791,18 @@ mlxsw_sp_ipip_config_tigcr(struct mlxsw_sp *mlxsw_sp)

static int mlxsw_sp_ipips_init(struct mlxsw_sp *mlxsw_sp)
{
int err;

mlxsw_sp->router->ipip_ops_arr = mlxsw_sp_ipip_ops_arr;
INIT_LIST_HEAD(&mlxsw_sp->router->ipip_list);

err = mlxsw_sp_ipip_ecn_encap_init(mlxsw_sp);
if (err)
return err;
err = mlxsw_sp_ipip_ecn_decap_init(mlxsw_sp);
if (err)
return err;

return mlxsw_sp_ipip_config_tigcr(mlxsw_sp);
}

Expand Down
3 changes: 3 additions & 0 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum_router.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,7 @@ static inline bool mlxsw_sp_l3addr_eq(const union mlxsw_sp_l3addr *addr1,
return !memcmp(addr1, addr2, sizeof(*addr1));
}

int mlxsw_sp_ipip_ecn_encap_init(struct mlxsw_sp *mlxsw_sp);
int mlxsw_sp_ipip_ecn_decap_init(struct mlxsw_sp *mlxsw_sp);

#endif /* _MLXSW_ROUTER_H_*/
52 changes: 50 additions & 2 deletions drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,20 @@
#include "reg.h"
#include "spectrum.h"

/* All driver-specific traps must be documented in
* Documentation/networking/devlink/mlxsw.rst
*/
enum {
DEVLINK_MLXSW_TRAP_ID_BASE = DEVLINK_TRAP_GENERIC_ID_MAX,
DEVLINK_MLXSW_TRAP_ID_IRIF_DISABLED,
DEVLINK_MLXSW_TRAP_ID_ERIF_DISABLED,
};

#define DEVLINK_MLXSW_TRAP_NAME_IRIF_DISABLED \
"irif_disabled"
#define DEVLINK_MLXSW_TRAP_NAME_ERIF_DISABLED \
"erif_disabled"

#define MLXSW_SP_TRAP_METADATA DEVLINK_TRAP_METADATA_TYPE_F_IN_PORT

static void mlxsw_sp_rx_drop_listener(struct sk_buff *skb, u8 local_port,
Expand All @@ -21,6 +35,12 @@ static void mlxsw_sp_rx_exception_listener(struct sk_buff *skb, u8 local_port,
DEVLINK_TRAP_GROUP_GENERIC(_group_id), \
MLXSW_SP_TRAP_METADATA)

#define MLXSW_SP_TRAP_DRIVER_DROP(_id, _group_id) \
DEVLINK_TRAP_DRIVER(DROP, DROP, DEVLINK_MLXSW_TRAP_ID_##_id, \
DEVLINK_MLXSW_TRAP_NAME_##_id, \
DEVLINK_TRAP_GROUP_GENERIC(_group_id), \
MLXSW_SP_TRAP_METADATA)

#define MLXSW_SP_TRAP_EXCEPTION(_id, _group_id) \
DEVLINK_TRAP_GENERIC(EXCEPTION, TRAP, _id, \
DEVLINK_TRAP_GROUP_GENERIC(_group_id), \
Expand Down Expand Up @@ -58,6 +78,11 @@ static struct devlink_trap mlxsw_sp_traps_arr[] = {
MLXSW_SP_TRAP_EXCEPTION(UNRESOLVED_NEIGH, L3_DROPS),
MLXSW_SP_TRAP_EXCEPTION(IPV4_LPM_UNICAST_MISS, L3_DROPS),
MLXSW_SP_TRAP_EXCEPTION(IPV6_LPM_UNICAST_MISS, L3_DROPS),
MLXSW_SP_TRAP_DRIVER_DROP(IRIF_DISABLED, L3_DROPS),
MLXSW_SP_TRAP_DRIVER_DROP(ERIF_DISABLED, L3_DROPS),
MLXSW_SP_TRAP_DROP(NON_ROUTABLE, L3_DROPS),
MLXSW_SP_TRAP_EXCEPTION(DECAP_ERROR, TUNNEL_DROPS),
MLXSW_SP_TRAP_DROP(OVERLAY_SMAC_MC, TUNNEL_DROPS),
};

static struct mlxsw_listener mlxsw_sp_listeners_arr[] = {
Expand Down Expand Up @@ -90,6 +115,15 @@ static struct mlxsw_listener mlxsw_sp_listeners_arr[] = {
TRAP_EXCEPTION_TO_CPU),
MLXSW_SP_RXL_EXCEPTION(DISCARD_ROUTER_LPM6, ROUTER_EXP,
TRAP_EXCEPTION_TO_CPU),
MLXSW_SP_RXL_DISCARD(ROUTER_IRIF_EN, L3_DISCARDS),
MLXSW_SP_RXL_DISCARD(ROUTER_ERIF_EN, L3_DISCARDS),
MLXSW_SP_RXL_DISCARD(NON_ROUTABLE, L3_DISCARDS),
MLXSW_SP_RXL_EXCEPTION(DECAP_ECN0, ROUTER_EXP, TRAP_EXCEPTION_TO_CPU),
MLXSW_SP_RXL_EXCEPTION(IPIP_DECAP_ERROR, ROUTER_EXP,
TRAP_EXCEPTION_TO_CPU),
MLXSW_SP_RXL_EXCEPTION(DISCARD_DEC_PKT, TUNNEL_DISCARDS,
TRAP_EXCEPTION_TO_CPU),
MLXSW_SP_RXL_DISCARD(OVERLAY_SMAC_MC, TUNNEL_DISCARDS),
};

/* Mapping between hardware trap and devlink trap. Multiple hardware traps can
Expand Down Expand Up @@ -123,6 +157,13 @@ static u16 mlxsw_sp_listener_devlink_map[] = {
DEVLINK_TRAP_GENERIC_ID_UNRESOLVED_NEIGH,
DEVLINK_TRAP_GENERIC_ID_IPV4_LPM_UNICAST_MISS,
DEVLINK_TRAP_GENERIC_ID_IPV6_LPM_UNICAST_MISS,
DEVLINK_MLXSW_TRAP_ID_IRIF_DISABLED,
DEVLINK_MLXSW_TRAP_ID_ERIF_DISABLED,
DEVLINK_TRAP_GENERIC_ID_NON_ROUTABLE,
DEVLINK_TRAP_GENERIC_ID_DECAP_ERROR,
DEVLINK_TRAP_GENERIC_ID_DECAP_ERROR,
DEVLINK_TRAP_GENERIC_ID_DECAP_ERROR,
DEVLINK_TRAP_GENERIC_ID_OVERLAY_SMAC_MC,
};

static int mlxsw_sp_rx_listener(struct mlxsw_sp *mlxsw_sp, struct sk_buff *skb,
Expand Down Expand Up @@ -304,8 +345,9 @@ mlxsw_sp_trap_group_policer_init(struct mlxsw_sp *mlxsw_sp,
u32 rate;

switch (group->id) {
case DEVLINK_TRAP_GROUP_GENERIC_ID_L3_DROPS:/* fall through */
case DEVLINK_TRAP_GROUP_GENERIC_ID_L2_DROPS:
case DEVLINK_TRAP_GROUP_GENERIC_ID_L2_DROPS: /* fall through */
case DEVLINK_TRAP_GROUP_GENERIC_ID_L3_DROPS: /* fall through */
case DEVLINK_TRAP_GROUP_GENERIC_ID_TUNNEL_DROPS:
policer_id = MLXSW_SP_DISCARD_POLICER_ID;
ir_units = MLXSW_REG_QPCR_IR_UNITS_M;
is_bytes = false;
Expand Down Expand Up @@ -342,6 +384,12 @@ __mlxsw_sp_trap_group_init(struct mlxsw_sp *mlxsw_sp,
priority = 0;
tc = 1;
break;
case DEVLINK_TRAP_GROUP_GENERIC_ID_TUNNEL_DROPS:
group_id = MLXSW_REG_HTGT_TRAP_GROUP_SP_TUNNEL_DISCARDS;
policer_id = MLXSW_SP_DISCARD_POLICER_ID;
priority = 0;
tc = 1;
break;
default:
return -EINVAL;
}
Expand Down
Loading

0 comments on commit 4ee9e6e

Please sign in to comment.