Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: dsa: b53: Add support for port mirroring

Add support for configuring port mirroring through the cls_matchall
classifier. We do a full ingress or egress capture towards the capture
port. Future improvements could include leveraging the divider to allow
less frames to be captured, as well as matching specific MAC DA/SA.

Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Florian Fainelli and committed by
David S. Miller
ed3af5fd 151da017

+71
+67
drivers/net/dsa/b53/b53_common.c
··· 1450 1450 return DSA_TAG_PROTO_NONE; 1451 1451 } 1452 1452 1453 + int b53_mirror_add(struct dsa_switch *ds, int port, 1454 + struct dsa_mall_mirror_tc_entry *mirror, bool ingress) 1455 + { 1456 + struct b53_device *dev = ds->priv; 1457 + u16 reg, loc; 1458 + 1459 + if (ingress) 1460 + loc = B53_IG_MIR_CTL; 1461 + else 1462 + loc = B53_EG_MIR_CTL; 1463 + 1464 + b53_read16(dev, B53_MGMT_PAGE, loc, &reg); 1465 + reg &= ~MIRROR_MASK; 1466 + reg |= BIT(port); 1467 + b53_write16(dev, B53_MGMT_PAGE, loc, reg); 1468 + 1469 + b53_read16(dev, B53_MGMT_PAGE, B53_MIR_CAP_CTL, &reg); 1470 + reg &= ~CAP_PORT_MASK; 1471 + reg |= mirror->to_local_port; 1472 + reg |= MIRROR_EN; 1473 + b53_write16(dev, B53_MGMT_PAGE, B53_MIR_CAP_CTL, reg); 1474 + 1475 + return 0; 1476 + } 1477 + EXPORT_SYMBOL(b53_mirror_add); 1478 + 1479 + void b53_mirror_del(struct dsa_switch *ds, int port, 1480 + struct dsa_mall_mirror_tc_entry *mirror) 1481 + { 1482 + struct b53_device *dev = ds->priv; 1483 + bool loc_disable = false, other_loc_disable = false; 1484 + u16 reg, loc; 1485 + 1486 + if (mirror->ingress) 1487 + loc = B53_IG_MIR_CTL; 1488 + else 1489 + loc = B53_EG_MIR_CTL; 1490 + 1491 + /* Update the desired ingress/egress register */ 1492 + b53_read16(dev, B53_MGMT_PAGE, loc, &reg); 1493 + reg &= ~BIT(port); 1494 + if (!(reg & MIRROR_MASK)) 1495 + loc_disable = true; 1496 + b53_write16(dev, B53_MGMT_PAGE, loc, reg); 1497 + 1498 + /* Now look at the other one to know if we can disable mirroring 1499 + * entirely 1500 + */ 1501 + if (mirror->ingress) 1502 + b53_read16(dev, B53_MGMT_PAGE, B53_EG_MIR_CTL, &reg); 1503 + else 1504 + b53_read16(dev, B53_MGMT_PAGE, B53_IG_MIR_CTL, &reg); 1505 + if (!(reg & MIRROR_MASK)) 1506 + other_loc_disable = true; 1507 + 1508 + b53_read16(dev, B53_MGMT_PAGE, B53_MIR_CAP_CTL, &reg); 1509 + /* Both no longer have ports, let's disable mirroring */ 1510 + if (loc_disable && other_loc_disable) { 1511 + reg &= ~MIRROR_EN; 1512 + reg &= ~mirror->to_local_port; 1513 + } 1514 + b53_write16(dev, B53_MGMT_PAGE, B53_MIR_CAP_CTL, reg); 1515 + } 1516 + EXPORT_SYMBOL(b53_mirror_del); 1517 + 1453 1518 static const struct dsa_switch_ops b53_switch_ops = { 1454 1519 .get_tag_protocol = b53_get_tag_protocol, 1455 1520 .setup = b53_setup, ··· 1539 1474 .port_fdb_dump = b53_fdb_dump, 1540 1475 .port_fdb_add = b53_fdb_add, 1541 1476 .port_fdb_del = b53_fdb_del, 1477 + .port_mirror_add = b53_mirror_add, 1478 + .port_mirror_del = b53_mirror_del, 1542 1479 }; 1543 1480 1544 1481 struct b53_chip_data {
+4
drivers/net/dsa/b53/b53_priv.h
··· 407 407 int b53_fdb_dump(struct dsa_switch *ds, int port, 408 408 struct switchdev_obj_port_fdb *fdb, 409 409 int (*cb)(struct switchdev_obj *obj)); 410 + int b53_mirror_add(struct dsa_switch *ds, int port, 411 + struct dsa_mall_mirror_tc_entry *mirror, bool ingress); 412 + void b53_mirror_del(struct dsa_switch *ds, int port, 413 + struct dsa_mall_mirror_tc_entry *mirror); 410 414 411 415 #endif