Commit 5af946f4 authored by Daniel Machon's avatar Daniel Machon Committed by David S. Miller
Browse files

net: sparx5: add support for matchall mirror stats



Add support for tc matchall mirror stats. When a new matchall mirror
rule is added, the baseline stats for that port is saved.

Signed-off-by: default avatarDaniel Machon <daniel.machon@microchip.com>
Reviewed-by: default avatarSteen Hegelund <Steen.Hegelund@microchip.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 2ac99ed9
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -174,6 +174,7 @@ struct sparx5_port {
	struct phylink_config phylink_config;
	struct phylink *phylink;
	struct phylink_pcs phylink_pcs;
	struct flow_stats mirror_stats;
	u16 portno;
	/* Ingress default VLAN (pvid) */
	u16 pvid;
@@ -562,6 +563,8 @@ void sparx5_new_base_time(struct sparx5 *sparx5, const u32 cycle_time,
/* sparx5_mirror.c */
int sparx5_mirror_add(struct sparx5_mall_entry *entry);
void sparx5_mirror_del(struct sparx5_mall_entry *entry);
void sparx5_mirror_stats(struct sparx5_mall_entry *entry,
			 struct flow_stats *fstats);

/* Clock period in picoseconds */
static inline u32 sparx5_clk_period(enum sparx5_core_clockfreq cclock)
+37 −0
Original line number Diff line number Diff line
@@ -196,3 +196,40 @@ void sparx5_mirror_del(struct sparx5_mall_entry *entry)
				  mirror_idx,
				  SPX5_MIRROR_MONITOR_PORT_DEFAULT);
}

void sparx5_mirror_stats(struct sparx5_mall_entry *entry,
			 struct flow_stats *fstats)
{
	struct sparx5_port *port = entry->port;
	struct rtnl_link_stats64 new_stats;
	struct flow_stats *old_stats;

	old_stats = &entry->port->mirror_stats;
	sparx5_get_stats64(port->ndev, &new_stats);

	if (entry->ingress) {
		flow_stats_update(fstats,
				  new_stats.rx_bytes - old_stats->bytes,
				  new_stats.rx_packets - old_stats->pkts,
				  new_stats.rx_dropped - old_stats->drops,
				  old_stats->lastused,
				  FLOW_ACTION_HW_STATS_IMMEDIATE);

		old_stats->bytes = new_stats.rx_bytes;
		old_stats->pkts = new_stats.rx_packets;
		old_stats->drops = new_stats.rx_dropped;
		old_stats->lastused = jiffies;
	} else {
		flow_stats_update(fstats,
				  new_stats.tx_bytes - old_stats->bytes,
				  new_stats.tx_packets - old_stats->pkts,
				  new_stats.tx_dropped - old_stats->drops,
				  old_stats->lastused,
				  FLOW_ACTION_HW_STATS_IMMEDIATE);

		old_stats->bytes = new_stats.tx_bytes;
		old_stats->pkts = new_stats.tx_packets;
		old_stats->drops = new_stats.tx_dropped;
		old_stats->lastused = jiffies;
	}
}
+27 −0
Original line number Diff line number Diff line
@@ -96,6 +96,8 @@ static int sparx5_tc_matchall_replace(struct net_device *ndev,
			}
			return err;
		}
		/* Get baseline stats for this port */
		sparx5_mirror_stats(mall_entry, &tmo->stats);
		break;
	case FLOW_ACTION_GOTO:
		err = vcap_enable_lookups(sparx5->vcap_ctrl, ndev,
@@ -162,6 +164,29 @@ static int sparx5_tc_matchall_destroy(struct net_device *ndev,
	return err;
}

static int sparx5_tc_matchall_stats(struct net_device *ndev,
				    struct tc_cls_matchall_offload *tmo,
				    bool ingress)
{
	struct sparx5_port *port = netdev_priv(ndev);
	struct sparx5 *sparx5 = port->sparx5;
	struct sparx5_mall_entry *entry;

	entry = sparx5_tc_matchall_entry_find(&sparx5->mall_entries,
					      tmo->cookie);
	if (!entry)
		return -ENOENT;

	if (entry->type == FLOW_ACTION_MIRRED) {
		sparx5_mirror_stats(entry, &tmo->stats);
	} else {
		NL_SET_ERR_MSG_MOD(tmo->common.extack, "Unsupported action");
		return -EOPNOTSUPP;
	}

	return 0;
}

int sparx5_tc_matchall(struct net_device *ndev,
		       struct tc_cls_matchall_offload *tmo,
		       bool ingress)
@@ -171,6 +196,8 @@ int sparx5_tc_matchall(struct net_device *ndev,
		return sparx5_tc_matchall_replace(ndev, tmo, ingress);
	case TC_CLSMATCHALL_DESTROY:
		return sparx5_tc_matchall_destroy(ndev, tmo, ingress);
	case TC_CLSMATCHALL_STATS:
		return sparx5_tc_matchall_stats(ndev, tmo, ingress);
	default:
		return -EOPNOTSUPP;
	}