Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0+
  2
  3#include "lan966x_main.h"
  4
  5int 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
 65int 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
103void 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}