brintos

brintos / linux-shallow public Read only

0
0
Text · 3.3 KiB · 7e1ba3f Raw
139 lines · c
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	else60		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	else98		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}139