Skip to content

Commit 99507e7

Browse files
committed
Merge branch 'lan966x-police-mirroring'
Horatiu Vultur says: ==================== net: lan966x: Add police and mirror using tc-matchall Add tc-matchall classifier offload support both for ingress and egress. For this add support for the port police and port mirroring action support. Port police can happen only on ingress while port mirroring is supported both on ingress and egress ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 95698ff + b69e953 commit 99507e7

File tree

7 files changed

+660
-1
lines changed

7 files changed

+660
-1
lines changed

drivers/net/ethernet/microchip/lan966x/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@ lan966x-switch-objs := lan966x_main.o lan966x_phylink.o lan966x_port.o \
1010
lan966x_vlan.o lan966x_fdb.o lan966x_mdb.o \
1111
lan966x_ptp.o lan966x_fdma.o lan966x_lag.o \
1212
lan966x_tc.o lan966x_mqprio.o lan966x_taprio.o \
13-
lan966x_tbf.o lan966x_cbs.o lan966x_ets.o
13+
lan966x_tbf.o lan966x_cbs.o lan966x_ets.o \
14+
lan966x_tc_matchall.o lan966x_police.o lan966x_mirror.o

drivers/net/ethernet/microchip/lan966x/lan966x_main.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,11 @@ struct lan966x {
264264
struct lan966x_rx rx;
265265
struct lan966x_tx tx;
266266
struct napi_struct napi;
267+
268+
/* Mirror */
269+
struct lan966x_port *mirror_monitor;
270+
u32 mirror_mask[2];
271+
u32 mirror_count;
267272
};
268273

269274
struct lan966x_port_config {
@@ -276,6 +281,15 @@ struct lan966x_port_config {
276281
bool autoneg;
277282
};
278283

284+
struct lan966x_port_tc {
285+
bool ingress_shared_block;
286+
unsigned long police_id;
287+
unsigned long ingress_mirror_id;
288+
unsigned long egress_mirror_id;
289+
struct flow_stats police_stat;
290+
struct flow_stats mirror_stat;
291+
};
292+
279293
struct lan966x_port {
280294
struct net_device *dev;
281295
struct lan966x *lan966x;
@@ -302,6 +316,8 @@ struct lan966x_port {
302316
struct net_device *bond;
303317
bool lag_tx_active;
304318
enum netdev_lag_hash hash_type;
319+
320+
struct lan966x_port_tc tc;
305321
};
306322

307323
extern const struct phylink_mac_ops lan966x_phylink_mac_ops;
@@ -481,6 +497,34 @@ int lan966x_ets_add(struct lan966x_port *port,
481497
int lan966x_ets_del(struct lan966x_port *port,
482498
struct tc_ets_qopt_offload *qopt);
483499

500+
int lan966x_tc_matchall(struct lan966x_port *port,
501+
struct tc_cls_matchall_offload *f,
502+
bool ingress);
503+
504+
int lan966x_police_port_add(struct lan966x_port *port,
505+
struct flow_action *action,
506+
struct flow_action_entry *act,
507+
unsigned long police_id,
508+
bool ingress,
509+
struct netlink_ext_ack *extack);
510+
int lan966x_police_port_del(struct lan966x_port *port,
511+
unsigned long police_id,
512+
struct netlink_ext_ack *extack);
513+
void lan966x_police_port_stats(struct lan966x_port *port,
514+
struct flow_stats *stats);
515+
516+
int lan966x_mirror_port_add(struct lan966x_port *port,
517+
struct flow_action_entry *action,
518+
unsigned long mirror_id,
519+
bool ingress,
520+
struct netlink_ext_ack *extack);
521+
int lan966x_mirror_port_del(struct lan966x_port *port,
522+
bool ingress,
523+
struct netlink_ext_ack *extack);
524+
void lan966x_mirror_port_stats(struct lan966x_port *port,
525+
struct flow_stats *stats,
526+
bool ingress);
527+
484528
static inline void __iomem *lan_addr(void __iomem *base[],
485529
int id, int tinst, int tcnt,
486530
int gbase, int ginst,
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
// SPDX-License-Identifier: GPL-2.0+
2+
3+
#include "lan966x_main.h"
4+
5+
int lan966x_mirror_port_add(struct lan966x_port *port,
6+
struct flow_action_entry *action,
7+
unsigned long mirror_id,
8+
bool ingress,
9+
struct netlink_ext_ack *extack)
10+
{
11+
struct lan966x *lan966x = port->lan966x;
12+
struct lan966x_port *monitor_port;
13+
14+
if (!lan966x_netdevice_check(action->dev)) {
15+
NL_SET_ERR_MSG_MOD(extack,
16+
"Destination not an lan966x port");
17+
return -EOPNOTSUPP;
18+
}
19+
20+
monitor_port = netdev_priv(action->dev);
21+
22+
if (lan966x->mirror_mask[ingress] & BIT(port->chip_port)) {
23+
NL_SET_ERR_MSG_MOD(extack,
24+
"Mirror already exists");
25+
return -EEXIST;
26+
}
27+
28+
if (lan966x->mirror_monitor &&
29+
lan966x->mirror_monitor != monitor_port) {
30+
NL_SET_ERR_MSG_MOD(extack,
31+
"Cannot change mirror port while in use");
32+
return -EBUSY;
33+
}
34+
35+
if (port == monitor_port) {
36+
NL_SET_ERR_MSG_MOD(extack,
37+
"Cannot mirror the monitor port");
38+
return -EINVAL;
39+
}
40+
41+
lan966x->mirror_mask[ingress] |= BIT(port->chip_port);
42+
43+
lan966x->mirror_monitor = monitor_port;
44+
lan_wr(BIT(monitor_port->chip_port), lan966x, ANA_MIRRORPORTS);
45+
46+
if (ingress) {
47+
lan_rmw(ANA_PORT_CFG_SRC_MIRROR_ENA_SET(1),
48+
ANA_PORT_CFG_SRC_MIRROR_ENA,
49+
lan966x, ANA_PORT_CFG(port->chip_port));
50+
} else {
51+
lan_wr(lan966x->mirror_mask[0], lan966x,
52+
ANA_EMIRRORPORTS);
53+
}
54+
55+
lan966x->mirror_count++;
56+
57+
if (ingress)
58+
port->tc.ingress_mirror_id = mirror_id;
59+
else
60+
port->tc.egress_mirror_id = mirror_id;
61+
62+
return 0;
63+
}
64+
65+
int lan966x_mirror_port_del(struct lan966x_port *port,
66+
bool ingress,
67+
struct netlink_ext_ack *extack)
68+
{
69+
struct lan966x *lan966x = port->lan966x;
70+
71+
if (!(lan966x->mirror_mask[ingress] & BIT(port->chip_port))) {
72+
NL_SET_ERR_MSG_MOD(extack,
73+
"There is no mirroring for this port");
74+
return -ENOENT;
75+
}
76+
77+
lan966x->mirror_mask[ingress] &= ~BIT(port->chip_port);
78+
79+
if (ingress) {
80+
lan_rmw(ANA_PORT_CFG_SRC_MIRROR_ENA_SET(0),
81+
ANA_PORT_CFG_SRC_MIRROR_ENA,
82+
lan966x, ANA_PORT_CFG(port->chip_port));
83+
} else {
84+
lan_wr(lan966x->mirror_mask[0], lan966x,
85+
ANA_EMIRRORPORTS);
86+
}
87+
88+
lan966x->mirror_count--;
89+
90+
if (lan966x->mirror_count == 0) {
91+
lan966x->mirror_monitor = NULL;
92+
lan_wr(0, lan966x, ANA_MIRRORPORTS);
93+
}
94+
95+
if (ingress)
96+
port->tc.ingress_mirror_id = 0;
97+
else
98+
port->tc.egress_mirror_id = 0;
99+
100+
return 0;
101+
}
102+
103+
void lan966x_mirror_port_stats(struct lan966x_port *port,
104+
struct flow_stats *stats,
105+
bool ingress)
106+
{
107+
struct rtnl_link_stats64 new_stats;
108+
struct flow_stats *old_stats;
109+
110+
old_stats = &port->tc.mirror_stat;
111+
lan966x_stats_get(port->dev, &new_stats);
112+
113+
if (ingress) {
114+
flow_stats_update(stats,
115+
new_stats.rx_bytes - old_stats->bytes,
116+
new_stats.rx_packets - old_stats->pkts,
117+
new_stats.rx_dropped - old_stats->drops,
118+
old_stats->lastused,
119+
FLOW_ACTION_HW_STATS_IMMEDIATE);
120+
121+
old_stats->bytes = new_stats.rx_bytes;
122+
old_stats->pkts = new_stats.rx_packets;
123+
old_stats->drops = new_stats.rx_dropped;
124+
old_stats->lastused = jiffies;
125+
} else {
126+
flow_stats_update(stats,
127+
new_stats.tx_bytes - old_stats->bytes,
128+
new_stats.tx_packets - old_stats->pkts,
129+
new_stats.tx_dropped - old_stats->drops,
130+
old_stats->lastused,
131+
FLOW_ACTION_HW_STATS_IMMEDIATE);
132+
133+
old_stats->bytes = new_stats.tx_bytes;
134+
old_stats->pkts = new_stats.tx_packets;
135+
old_stats->drops = new_stats.tx_dropped;
136+
old_stats->lastused = jiffies;
137+
}
138+
}

0 commit comments

Comments
 (0)