Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/net/ethernet/mscc/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 5 kB image not shown  

Quelle  ocelot_mrp.c   Sprache: C

 
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/* Microsemi Ocelot Switch driver
 *
 * Copyright (c) 2017, 2019 Microsemi Corporation
 * Copyright 2020-2021 NXP
 */


#include <linux/if_bridge.h>
#include <linux/mrp_bridge.h>
#include <soc/mscc/ocelot_vcap.h>
#include <uapi/linux/mrp_bridge.h>
#include "ocelot.h"
#include "ocelot_vcap.h"

static const u8 mrp_test_dmac[] = { 0x01, 0x15, 0x4e, 0x00, 0x00, 0x01 };
static const u8 mrp_control_dmac[] = { 0x01, 0x15, 0x4e, 0x00, 0x00, 0x02 };

static int ocelot_mrp_find_partner_port(struct ocelot *ocelot,
     struct ocelot_port *p)
{
 int i;

 for (i = 0; i < ocelot->num_phys_ports; ++i) {
  struct ocelot_port *ocelot_port = ocelot->ports[i];

  if (!ocelot_port || p == ocelot_port)
   continue;

  if (ocelot_port->mrp_ring_id == p->mrp_ring_id)
   return i;
 }

 return -1;
}

static int ocelot_mrp_del_vcap(struct ocelot *ocelot, int id)
{
 struct ocelot_vcap_block *block_vcap_is2;
 struct ocelot_vcap_filter *filter;

 block_vcap_is2 = &ocelot->block[VCAP_IS2];
 filter = ocelot_vcap_block_find_filter_by_id(block_vcap_is2, id,
           false);
 if (!filter)
  return 0;

 return ocelot_vcap_filter_del(ocelot, filter);
}

static int ocelot_mrp_redirect_add_vcap(struct ocelot *ocelot, int src_port,
     int dst_port)
{
 const u8 mrp_test_mask[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 struct ocelot_vcap_filter *filter;
 int err;

 filter = kzalloc(sizeof(*filter), GFP_KERNEL);
 if (!filter)
  return -ENOMEM;

 filter->key_type = OCELOT_VCAP_KEY_ETYPE;
 filter->prio = 1;
 filter->id.cookie = OCELOT_VCAP_IS2_MRP_REDIRECT(ocelot, src_port);
 filter->id.tc_offload = false;
 filter->block_id = VCAP_IS2;
 filter->type = OCELOT_VCAP_FILTER_OFFLOAD;
 filter->ingress_port_mask = BIT(src_port);
 ether_addr_copy(filter->key.etype.dmac.value, mrp_test_dmac);
 ether_addr_copy(filter->key.etype.dmac.mask, mrp_test_mask);
 filter->action.mask_mode = OCELOT_MASK_MODE_REDIRECT;
 filter->action.port_mask = BIT(dst_port);

 err = ocelot_vcap_filter_add(ocelot, filter, NULL);
 if (err)
  kfree(filter);

 return err;
}

static void ocelot_populate_mrp_trap_key(struct ocelot_vcap_filter *filter)
{
 const u8 mrp_mask[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 };

 /* Here is possible to use control or test dmac because the mask
 * doesn't cover the LSB
 */

 ether_addr_copy(filter->key.etype.dmac.value, mrp_test_dmac);
 ether_addr_copy(filter->key.etype.dmac.mask, mrp_mask);
}

static int ocelot_mrp_trap_add(struct ocelot *ocelot, int port)
{
 unsigned long cookie = OCELOT_VCAP_IS2_MRP_TRAP(ocelot);

 return ocelot_trap_add(ocelot, port, cookie, false,
          ocelot_populate_mrp_trap_key);
}

static int ocelot_mrp_trap_del(struct ocelot *ocelot, int port)
{
 unsigned long cookie = OCELOT_VCAP_IS2_MRP_TRAP(ocelot);

 return ocelot_trap_del(ocelot, port, cookie);
}

static void ocelot_mrp_save_mac(struct ocelot *ocelot,
    struct ocelot_port *port)
{
 ocelot_mact_learn(ocelot, PGID_BLACKHOLE, mrp_test_dmac,
     OCELOT_STANDALONE_PVID, ENTRYTYPE_LOCKED);
 ocelot_mact_learn(ocelot, PGID_BLACKHOLE, mrp_control_dmac,
     OCELOT_STANDALONE_PVID, ENTRYTYPE_LOCKED);
}

static void ocelot_mrp_del_mac(struct ocelot *ocelot,
          struct ocelot_port *port)
{
 ocelot_mact_forget(ocelot, mrp_test_dmac, OCELOT_STANDALONE_PVID);
 ocelot_mact_forget(ocelot, mrp_control_dmac, OCELOT_STANDALONE_PVID);
}

int ocelot_mrp_add(struct ocelot *ocelot, int port,
     const struct switchdev_obj_mrp *mrp)
{
 struct ocelot_port *ocelot_port = ocelot->ports[port];
 struct ocelot_port_private *priv;
 struct net_device *dev;

 if (!ocelot_port)
  return -EOPNOTSUPP;

 priv = container_of(ocelot_port, struct ocelot_port_private, port);
 dev = priv->dev;

 if (mrp->p_port != dev && mrp->s_port != dev)
  return 0;

 ocelot_port->mrp_ring_id = mrp->ring_id;

 return 0;
}
EXPORT_SYMBOL(ocelot_mrp_add);

int ocelot_mrp_del(struct ocelot *ocelot, int port,
     const struct switchdev_obj_mrp *mrp)
{
 struct ocelot_port *ocelot_port = ocelot->ports[port];

 if (!ocelot_port)
  return -EOPNOTSUPP;

 if (ocelot_port->mrp_ring_id != mrp->ring_id)
  return 0;

 ocelot_port->mrp_ring_id = 0;

 return 0;
}
EXPORT_SYMBOL(ocelot_mrp_del);

int ocelot_mrp_add_ring_role(struct ocelot *ocelot, int port,
        const struct switchdev_obj_ring_role_mrp *mrp)
{
 struct ocelot_port *ocelot_port = ocelot->ports[port];
 int dst_port;
 int err;

 if (!ocelot_port)
  return -EOPNOTSUPP;

 if (mrp->ring_role != BR_MRP_RING_ROLE_MRC && !mrp->sw_backup)
  return -EOPNOTSUPP;

 if (ocelot_port->mrp_ring_id != mrp->ring_id)
  return 0;

 ocelot_mrp_save_mac(ocelot, ocelot_port);

 if (mrp->ring_role != BR_MRP_RING_ROLE_MRC)
  return ocelot_mrp_trap_add(ocelot, port);

 dst_port = ocelot_mrp_find_partner_port(ocelot, ocelot_port);
 if (dst_port == -1)
  return -EINVAL;

 err = ocelot_mrp_redirect_add_vcap(ocelot, port, dst_port);
 if (err)
  return err;

 err = ocelot_mrp_trap_add(ocelot, port);
 if (err) {
  ocelot_mrp_del_vcap(ocelot,
        OCELOT_VCAP_IS2_MRP_REDIRECT(ocelot, port));
  return err;
 }

 return 0;
}
EXPORT_SYMBOL(ocelot_mrp_add_ring_role);

int ocelot_mrp_del_ring_role(struct ocelot *ocelot, int port,
        const struct switchdev_obj_ring_role_mrp *mrp)
{
 struct ocelot_port *ocelot_port = ocelot->ports[port];
 int err, i;

 if (!ocelot_port)
  return -EOPNOTSUPP;

 if (mrp->ring_role != BR_MRP_RING_ROLE_MRC && !mrp->sw_backup)
  return -EOPNOTSUPP;

 if (ocelot_port->mrp_ring_id != mrp->ring_id)
  return 0;

 err = ocelot_mrp_trap_del(ocelot, port);
 if (err)
  return err;

 ocelot_mrp_del_vcap(ocelot, OCELOT_VCAP_IS2_MRP_REDIRECT(ocelot, port));

 for (i = 0; i < ocelot->num_phys_ports; ++i) {
  ocelot_port = ocelot->ports[i];

  if (!ocelot_port)
   continue;

  if (ocelot_port->mrp_ring_id != 0)
   goto out;
 }

 ocelot_mrp_del_mac(ocelot, ocelot->ports[port]);
out:
 return 0;
}
EXPORT_SYMBOL(ocelot_mrp_del_ring_role);

Messung V0.5
C=91 H=96 G=93

¤ Dauer der Verarbeitung: 0.3 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.