Commit 3d12e50f authored by David S. Miller's avatar David S. Miller

Merge branch 'mlxsw-Mirror-to-CPU-preparations'

Ido Schimmel says:

====================
mlxsw: Mirror to CPU preparations

A future patch set will add the ability to trap packets that were
dropped due to buffer related reasons (e.g., early drop). Internally
this is implemented by mirroring these packets towards the CPU port.
This patch set adds the required infrastructure to enable such
mirroring.

Patches #1-#2 extend two registers needed for above mentioned
functionality.

Patches #3-#6 gradually add support for setting the mirroring target of
a SPAN (mirroring) agent as the CPU port. This is only supported from
Spectrum-2 onwards, so an error is returned for Spectrum-1.

Patches #7-#8 add the ability to set a policer on a SPAN agent. This is
required because unlike regularly trapped packets, a policer cannot be
set on the trap group with which the mirroring trap is associated.

Patches #9-#12 parse the mirror reason field from the Completion Queue
Element (CQE). Unlike other trapped packets, the trap identifier of
mirrored packets only indicates that the packet was mirrored, but not
why. The reason (e.g., tail drop) is encoded in the mirror reason field.

Patch #13 utilizes the mirror reason field in order to lookup the
matching Rx listener. This allows us to maintain the abstraction that an
Rx listener is mapped to a single trap reason. Without taking the mirror
reason into account we would need to register a single Rx listener for
all mirrored packets.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 8331bbe9 6a8c101e
...@@ -1524,7 +1524,8 @@ static bool __is_rx_listener_equal(const struct mlxsw_rx_listener *rxl_a, ...@@ -1524,7 +1524,8 @@ static bool __is_rx_listener_equal(const struct mlxsw_rx_listener *rxl_a,
{ {
return (rxl_a->func == rxl_b->func && return (rxl_a->func == rxl_b->func &&
rxl_a->local_port == rxl_b->local_port && rxl_a->local_port == rxl_b->local_port &&
rxl_a->trap_id == rxl_b->trap_id); rxl_a->trap_id == rxl_b->trap_id &&
rxl_a->mirror_reason == rxl_b->mirror_reason);
} }
static struct mlxsw_rx_listener_item * static struct mlxsw_rx_listener_item *
...@@ -2044,7 +2045,8 @@ void mlxsw_core_skb_receive(struct mlxsw_core *mlxsw_core, struct sk_buff *skb, ...@@ -2044,7 +2045,8 @@ void mlxsw_core_skb_receive(struct mlxsw_core *mlxsw_core, struct sk_buff *skb,
rxl = &rxl_item->rxl; rxl = &rxl_item->rxl;
if ((rxl->local_port == MLXSW_PORT_DONT_CARE || if ((rxl->local_port == MLXSW_PORT_DONT_CARE ||
rxl->local_port == local_port) && rxl->local_port == local_port) &&
rxl->trap_id == rx_info->trap_id) { rxl->trap_id == rx_info->trap_id &&
rxl->mirror_reason == rx_info->mirror_reason) {
if (rxl_item->enabled) if (rxl_item->enabled)
found = true; found = true;
break; break;
......
...@@ -61,6 +61,7 @@ void mlxsw_core_ptp_transmitted(struct mlxsw_core *mlxsw_core, ...@@ -61,6 +61,7 @@ void mlxsw_core_ptp_transmitted(struct mlxsw_core *mlxsw_core,
struct mlxsw_rx_listener { struct mlxsw_rx_listener {
void (*func)(struct sk_buff *skb, u8 local_port, void *priv); void (*func)(struct sk_buff *skb, u8 local_port, void *priv);
u8 local_port; u8 local_port;
u8 mirror_reason;
u16 trap_id; u16 trap_id;
}; };
...@@ -176,6 +177,7 @@ struct mlxsw_rx_info { ...@@ -176,6 +177,7 @@ struct mlxsw_rx_info {
u16 lag_id; u16 lag_id;
} u; } u;
u8 lag_port_index; u8 lag_port_index;
u8 mirror_reason;
int trap_id; int trap_id;
}; };
......
...@@ -547,9 +547,9 @@ static void mlxsw_pci_cqe_rdq_handle(struct mlxsw_pci *mlxsw_pci, ...@@ -547,9 +547,9 @@ static void mlxsw_pci_cqe_rdq_handle(struct mlxsw_pci *mlxsw_pci,
{ {
struct pci_dev *pdev = mlxsw_pci->pdev; struct pci_dev *pdev = mlxsw_pci->pdev;
struct mlxsw_pci_queue_elem_info *elem_info; struct mlxsw_pci_queue_elem_info *elem_info;
struct mlxsw_rx_info rx_info = {};
char *wqe; char *wqe;
struct sk_buff *skb; struct sk_buff *skb;
struct mlxsw_rx_info rx_info;
u16 byte_count; u16 byte_count;
int err; int err;
...@@ -582,6 +582,10 @@ static void mlxsw_pci_cqe_rdq_handle(struct mlxsw_pci *mlxsw_pci, ...@@ -582,6 +582,10 @@ static void mlxsw_pci_cqe_rdq_handle(struct mlxsw_pci *mlxsw_pci,
if (mlxsw_pci->max_cqe_ver >= MLXSW_PCI_CQE_V2) if (mlxsw_pci->max_cqe_ver >= MLXSW_PCI_CQE_V2)
cookie_index = mlxsw_pci_cqe2_user_def_val_orig_pkt_len_get(cqe); cookie_index = mlxsw_pci_cqe2_user_def_val_orig_pkt_len_get(cqe);
mlxsw_skb_cb(skb)->cookie_index = cookie_index; mlxsw_skb_cb(skb)->cookie_index = cookie_index;
} else if (rx_info.trap_id >= MLXSW_TRAP_ID_MIRROR_SESSION0 &&
rx_info.trap_id <= MLXSW_TRAP_ID_MIRROR_SESSION7 &&
mlxsw_pci->max_cqe_ver >= MLXSW_PCI_CQE_V2) {
rx_info.mirror_reason = mlxsw_pci_cqe2_mirror_reason_get(cqe);
} }
byte_count = mlxsw_pci_cqe_byte_count_get(cqe); byte_count = mlxsw_pci_cqe_byte_count_get(cqe);
......
...@@ -176,7 +176,7 @@ MLXSW_ITEM32(pci, cqe, byte_count, 0x04, 0, 14); ...@@ -176,7 +176,7 @@ MLXSW_ITEM32(pci, cqe, byte_count, 0x04, 0, 14);
/* pci_cqe_trap_id /* pci_cqe_trap_id
* Trap ID that captured the packet. * Trap ID that captured the packet.
*/ */
MLXSW_ITEM32(pci, cqe, trap_id, 0x08, 0, 9); MLXSW_ITEM32(pci, cqe, trap_id, 0x08, 0, 10);
/* pci_cqe_crc /* pci_cqe_crc
* Length include CRC. Indicates the length field includes * Length include CRC. Indicates the length field includes
...@@ -213,6 +213,11 @@ mlxsw_pci_cqe_item_helpers(dqn, 0, 12, 12); ...@@ -213,6 +213,11 @@ mlxsw_pci_cqe_item_helpers(dqn, 0, 12, 12);
*/ */
MLXSW_ITEM32(pci, cqe2, user_def_val_orig_pkt_len, 0x14, 0, 20); MLXSW_ITEM32(pci, cqe2, user_def_val_orig_pkt_len, 0x14, 0, 20);
/* pci_cqe_mirror_reason
* Mirror reason.
*/
MLXSW_ITEM32(pci, cqe2, mirror_reason, 0x18, 24, 8);
/* pci_cqe_owner /* pci_cqe_owner
* Ownership bit. * Ownership bit.
*/ */
......
...@@ -5778,7 +5778,7 @@ MLXSW_ITEM32(reg, hpkt, trap_group, 0x00, 12, 6); ...@@ -5778,7 +5778,7 @@ MLXSW_ITEM32(reg, hpkt, trap_group, 0x00, 12, 6);
* Note: A trap ID can only be associated with a single trap group. The device * Note: A trap ID can only be associated with a single trap group. The device
* will associate the trap ID with the last trap group configured. * will associate the trap ID with the last trap group configured.
*/ */
MLXSW_ITEM32(reg, hpkt, trap_id, 0x00, 0, 9); MLXSW_ITEM32(reg, hpkt, trap_id, 0x00, 0, 10);
enum { enum {
MLXSW_REG_HPKT_CTRL_PACKET_DEFAULT, MLXSW_REG_HPKT_CTRL_PACKET_DEFAULT,
...@@ -8662,6 +8662,13 @@ MLXSW_REG_DEFINE(mpat, MLXSW_REG_MPAT_ID, MLXSW_REG_MPAT_LEN); ...@@ -8662,6 +8662,13 @@ MLXSW_REG_DEFINE(mpat, MLXSW_REG_MPAT_ID, MLXSW_REG_MPAT_LEN);
*/ */
MLXSW_ITEM32(reg, mpat, pa_id, 0x00, 28, 4); MLXSW_ITEM32(reg, mpat, pa_id, 0x00, 28, 4);
/* reg_mpat_session_id
* Mirror Session ID.
* Used for MIRROR_SESSION<i> trap.
* Access: RW
*/
MLXSW_ITEM32(reg, mpat, session_id, 0x00, 24, 4);
/* reg_mpat_system_port /* reg_mpat_system_port
* A unique port identifier for the final destination of the packet. * A unique port identifier for the final destination of the packet.
* Access: RW * Access: RW
...@@ -8719,6 +8726,18 @@ enum mlxsw_reg_mpat_span_type { ...@@ -8719,6 +8726,18 @@ enum mlxsw_reg_mpat_span_type {
*/ */
MLXSW_ITEM32(reg, mpat, span_type, 0x04, 0, 4); MLXSW_ITEM32(reg, mpat, span_type, 0x04, 0, 4);
/* reg_mpat_pide
* Policer enable.
* Access: RW
*/
MLXSW_ITEM32(reg, mpat, pide, 0x0C, 15, 1);
/* reg_mpat_pid
* Policer ID.
* Access: RW
*/
MLXSW_ITEM32(reg, mpat, pid, 0x0C, 0, 14);
/* Remote SPAN - Ethernet VLAN /* Remote SPAN - Ethernet VLAN
* - - - - - - - - - - - - - - * - - - - - - - - - - - - - -
*/ */
...@@ -9502,6 +9521,14 @@ MLXSW_ITEM32(reg, mogcr, ptp_iftc, 0x00, 1, 1); ...@@ -9502,6 +9521,14 @@ MLXSW_ITEM32(reg, mogcr, ptp_iftc, 0x00, 1, 1);
*/ */
MLXSW_ITEM32(reg, mogcr, ptp_eftc, 0x00, 0, 1); MLXSW_ITEM32(reg, mogcr, ptp_eftc, 0x00, 0, 1);
/* reg_mogcr_mirroring_pid_base
* Base policer id for mirroring policers.
* Must have an even value (e.g. 1000, not 1001).
* Reserved when SwitchX/-2, Switch-IB/2, Spectrum-1 and Quantum.
* Access: RW
*/
MLXSW_ITEM32(reg, mogcr, mirroring_pid_base, 0x0C, 0, 14);
/* MPAGR - Monitoring Port Analyzer Global Register /* MPAGR - Monitoring Port Analyzer Global Register
* ------------------------------------------------ * ------------------------------------------------
* This register is used for global port analyzer configurations. * This register is used for global port analyzer configurations.
......
...@@ -136,11 +136,13 @@ mlxsw_sp_act_mirror_add(void *priv, u8 local_in_port, ...@@ -136,11 +136,13 @@ mlxsw_sp_act_mirror_add(void *priv, u8 local_in_port,
const struct net_device *out_dev, const struct net_device *out_dev,
bool ingress, int *p_span_id) bool ingress, int *p_span_id)
{ {
struct mlxsw_sp_span_agent_parms agent_parms = {};
struct mlxsw_sp_port *mlxsw_sp_port; struct mlxsw_sp_port *mlxsw_sp_port;
struct mlxsw_sp *mlxsw_sp = priv; struct mlxsw_sp *mlxsw_sp = priv;
int err; int err;
err = mlxsw_sp_span_agent_get(mlxsw_sp, out_dev, p_span_id); agent_parms.to_dev = out_dev;
err = mlxsw_sp_span_agent_get(mlxsw_sp, p_span_id, &agent_parms);
if (err) if (err)
return err; return err;
......
...@@ -27,6 +27,7 @@ mlxsw_sp_mall_port_mirror_add(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -27,6 +27,7 @@ mlxsw_sp_mall_port_mirror_add(struct mlxsw_sp_port *mlxsw_sp_port,
struct mlxsw_sp_mall_entry *mall_entry) struct mlxsw_sp_mall_entry *mall_entry)
{ {
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
struct mlxsw_sp_span_agent_parms agent_parms = {};
struct mlxsw_sp_span_trigger_parms parms; struct mlxsw_sp_span_trigger_parms parms;
enum mlxsw_sp_span_trigger trigger; enum mlxsw_sp_span_trigger trigger;
int err; int err;
...@@ -36,8 +37,9 @@ mlxsw_sp_mall_port_mirror_add(struct mlxsw_sp_port *mlxsw_sp_port, ...@@ -36,8 +37,9 @@ mlxsw_sp_mall_port_mirror_add(struct mlxsw_sp_port *mlxsw_sp_port,
return -EINVAL; return -EINVAL;
} }
err = mlxsw_sp_span_agent_get(mlxsw_sp, mall_entry->mirror.to_dev, agent_parms.to_dev = mall_entry->mirror.to_dev;
&mall_entry->mirror.span_id); err = mlxsw_sp_span_agent_get(mlxsw_sp, &mall_entry->mirror.span_id,
&agent_parms);
if (err) if (err)
return err; return err;
......
...@@ -1295,10 +1295,13 @@ static int mlxsw_sp_qevent_mirror_configure(struct mlxsw_sp *mlxsw_sp, ...@@ -1295,10 +1295,13 @@ static int mlxsw_sp_qevent_mirror_configure(struct mlxsw_sp *mlxsw_sp,
{ {
struct mlxsw_sp_port *mlxsw_sp_port = qevent_binding->mlxsw_sp_port; struct mlxsw_sp_port *mlxsw_sp_port = qevent_binding->mlxsw_sp_port;
struct mlxsw_sp_span_trigger_parms trigger_parms = {}; struct mlxsw_sp_span_trigger_parms trigger_parms = {};
struct mlxsw_sp_span_agent_parms agent_parms = {
.to_dev = mall_entry->mirror.to_dev,
};
int span_id; int span_id;
int err; int err;
err = mlxsw_sp_span_agent_get(mlxsw_sp, mall_entry->mirror.to_dev, &span_id); err = mlxsw_sp_span_agent_get(mlxsw_sp, &span_id, &agent_parms);
if (err) if (err)
return err; return err;
......
...@@ -21,6 +21,8 @@ struct mlxsw_sp_span_parms { ...@@ -21,6 +21,8 @@ struct mlxsw_sp_span_parms {
union mlxsw_sp_l3addr daddr; union mlxsw_sp_l3addr daddr;
union mlxsw_sp_l3addr saddr; union mlxsw_sp_l3addr saddr;
u16 vid; u16 vid;
u16 policer_id;
bool policer_enable;
}; };
enum mlxsw_sp_span_trigger { enum mlxsw_sp_span_trigger {
...@@ -35,11 +37,19 @@ struct mlxsw_sp_span_trigger_parms { ...@@ -35,11 +37,19 @@ struct mlxsw_sp_span_trigger_parms {
int span_id; int span_id;
}; };
struct mlxsw_sp_span_agent_parms {
const struct net_device *to_dev;
u16 policer_id;
bool policer_enable;
};
struct mlxsw_sp_span_entry_ops; struct mlxsw_sp_span_entry_ops;
struct mlxsw_sp_span_ops { struct mlxsw_sp_span_ops {
int (*init)(struct mlxsw_sp *mlxsw_sp); int (*init)(struct mlxsw_sp *mlxsw_sp);
u32 (*buffsize_get)(int mtu, u32 speed); u32 (*buffsize_get)(int mtu, u32 speed);
int (*policer_id_base_set)(struct mlxsw_sp *mlxsw_sp,
u16 policer_id_base);
}; };
struct mlxsw_sp_span_entry { struct mlxsw_sp_span_entry {
...@@ -52,7 +62,8 @@ struct mlxsw_sp_span_entry { ...@@ -52,7 +62,8 @@ struct mlxsw_sp_span_entry {
struct mlxsw_sp_span_entry_ops { struct mlxsw_sp_span_entry_ops {
bool (*can_handle)(const struct net_device *to_dev); bool (*can_handle)(const struct net_device *to_dev);
int (*parms_set)(const struct net_device *to_dev, int (*parms_set)(struct mlxsw_sp *mlxsw_sp,
const struct net_device *to_dev,
struct mlxsw_sp_span_parms *sparmsp); struct mlxsw_sp_span_parms *sparmsp);
int (*configure)(struct mlxsw_sp_span_entry *span_entry, int (*configure)(struct mlxsw_sp_span_entry *span_entry,
struct mlxsw_sp_span_parms sparms); struct mlxsw_sp_span_parms sparms);
...@@ -73,8 +84,8 @@ void mlxsw_sp_span_entry_invalidate(struct mlxsw_sp *mlxsw_sp, ...@@ -73,8 +84,8 @@ void mlxsw_sp_span_entry_invalidate(struct mlxsw_sp *mlxsw_sp,
int mlxsw_sp_span_port_mtu_update(struct mlxsw_sp_port *port, u16 mtu); int mlxsw_sp_span_port_mtu_update(struct mlxsw_sp_port *port, u16 mtu);
void mlxsw_sp_span_speed_update_work(struct work_struct *work); void mlxsw_sp_span_speed_update_work(struct work_struct *work);
int mlxsw_sp_span_agent_get(struct mlxsw_sp *mlxsw_sp, int mlxsw_sp_span_agent_get(struct mlxsw_sp *mlxsw_sp, int *p_span_id,
const struct net_device *to_dev, int *p_span_id); const struct mlxsw_sp_span_agent_parms *parms);
void mlxsw_sp_span_agent_put(struct mlxsw_sp *mlxsw_sp, int span_id); void mlxsw_sp_span_agent_put(struct mlxsw_sp *mlxsw_sp, int span_id);
int mlxsw_sp_span_analyzed_port_get(struct mlxsw_sp_port *mlxsw_sp_port, int mlxsw_sp_span_analyzed_port_get(struct mlxsw_sp_port *mlxsw_sp_port,
bool ingress); bool ingress);
......
...@@ -107,8 +107,16 @@ enum { ...@@ -107,8 +107,16 @@ enum {
MLXSW_TRAP_ID_ACL2 = 0x1C2, MLXSW_TRAP_ID_ACL2 = 0x1C2,
MLXSW_TRAP_ID_DISCARD_INGRESS_ACL = 0x1C3, MLXSW_TRAP_ID_DISCARD_INGRESS_ACL = 0x1C3,
MLXSW_TRAP_ID_DISCARD_EGRESS_ACL = 0x1C4, MLXSW_TRAP_ID_DISCARD_EGRESS_ACL = 0x1C4,
MLXSW_TRAP_ID_MIRROR_SESSION0 = 0x220,
MLXSW_TRAP_ID_MIRROR_SESSION1 = 0x221,
MLXSW_TRAP_ID_MIRROR_SESSION2 = 0x222,
MLXSW_TRAP_ID_MIRROR_SESSION3 = 0x223,
MLXSW_TRAP_ID_MIRROR_SESSION4 = 0x224,
MLXSW_TRAP_ID_MIRROR_SESSION5 = 0x225,
MLXSW_TRAP_ID_MIRROR_SESSION6 = 0x226,
MLXSW_TRAP_ID_MIRROR_SESSION7 = 0x227,
MLXSW_TRAP_ID_MAX = 0x1FF MLXSW_TRAP_ID_MAX = 0x3FF,
}; };
enum mlxsw_event_trap_id { enum mlxsw_event_trap_id {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment