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

Quelle  lan966x_police.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0+

#include "lan966x_main.h"

/* 0-8 : 9 port policers */
#define POL_IDX_PORT 0

/* Policer order: Serial (QoS -> Port -> VCAP) */
#define POL_ORDER 0x1d3

struct lan966x_tc_policer {
 /* kilobit per second */
 u32 rate;
 /* bytes */
 u32 burst;
};

static int lan966x_police_add(struct lan966x_port *port,
         struct lan966x_tc_policer *pol,
         u16 pol_idx)
{
 struct lan966x *lan966x = port->lan966x;

 /* Rate unit is 33 1/3 kpps */
 pol->rate = DIV_ROUND_UP(pol->rate * 3, 100);
 /* Avoid zero burst size */
 pol->burst = pol->burst ?: 1;
 /* Unit is 4kB */
 pol->burst = DIV_ROUND_UP(pol->burst, 4096);

 if (pol->rate > GENMASK(15, 0) ||
     pol->burst > GENMASK(6, 0))
  return -EINVAL;

 lan_wr(ANA_POL_MODE_DROP_ON_YELLOW_ENA_SET(0) |
        ANA_POL_MODE_MARK_ALL_FRMS_RED_ENA_SET(0) |
        ANA_POL_MODE_IPG_SIZE_SET(20) |
        ANA_POL_MODE_FRM_MODE_SET(1) |
        ANA_POL_MODE_OVERSHOOT_ENA_SET(1),
        lan966x, ANA_POL_MODE(pol_idx));

 lan_wr(ANA_POL_PIR_STATE_PIR_LVL_SET(0),
        lan966x, ANA_POL_PIR_STATE(pol_idx));

 lan_wr(ANA_POL_PIR_CFG_PIR_RATE_SET(pol->rate) |
        ANA_POL_PIR_CFG_PIR_BURST_SET(pol->burst),
        lan966x, ANA_POL_PIR_CFG(pol_idx));

 return 0;
}

static void lan966x_police_del(struct lan966x_port *port, u16 pol_idx)
{
 struct lan966x *lan966x = port->lan966x;

 lan_wr(ANA_POL_MODE_DROP_ON_YELLOW_ENA_SET(0) |
        ANA_POL_MODE_MARK_ALL_FRMS_RED_ENA_SET(0) |
        ANA_POL_MODE_IPG_SIZE_SET(20) |
        ANA_POL_MODE_FRM_MODE_SET(2) |
        ANA_POL_MODE_OVERSHOOT_ENA_SET(1),
        lan966x, ANA_POL_MODE(pol_idx));

 lan_wr(ANA_POL_PIR_STATE_PIR_LVL_SET(0),
        lan966x, ANA_POL_PIR_STATE(pol_idx));

 lan_wr(ANA_POL_PIR_CFG_PIR_RATE_SET(GENMASK(14, 0)) |
        ANA_POL_PIR_CFG_PIR_BURST_SET(0),
        lan966x, ANA_POL_PIR_CFG(pol_idx));
}

static int lan966x_police_validate(struct lan966x_port *port,
       const struct flow_action *action,
       const struct flow_action_entry *act,
       unsigned long police_id,
       bool ingress,
       struct netlink_ext_ack *extack)
{
 if (act->police.exceed.act_id != FLOW_ACTION_DROP) {
  NL_SET_ERR_MSG_MOD(extack,
       "Offload not supported when exceed action is not drop");
  return -EOPNOTSUPP;
 }

 if (act->police.notexceed.act_id != FLOW_ACTION_PIPE &&
     act->police.notexceed.act_id != FLOW_ACTION_ACCEPT) {
  NL_SET_ERR_MSG_MOD(extack,
       "Offload not supported when conform action is not pipe or ok");
  return -EOPNOTSUPP;
 }

 if (act->police.notexceed.act_id == FLOW_ACTION_ACCEPT &&
     !flow_action_is_last_entry(action, act)) {
  NL_SET_ERR_MSG_MOD(extack,
       "Offload not supported when conform action is ok, but action is not last");
  return -EOPNOTSUPP;
 }

 if (act->police.peakrate_bytes_ps ||
     act->police.avrate || act->police.overhead) {
  NL_SET_ERR_MSG_MOD(extack,
       "Offload not supported when peakrate/avrate/overhead is configured");
  return -EOPNOTSUPP;
 }

 if (act->police.rate_pkt_ps) {
  NL_SET_ERR_MSG_MOD(extack,
       "QoS offload not support packets per second");
  return -EOPNOTSUPP;
 }

 if (!ingress) {
  NL_SET_ERR_MSG_MOD(extack,
       "Policer is not supported on egress");
  return -EOPNOTSUPP;
 }

 if (port->tc.ingress_shared_block) {
  NL_SET_ERR_MSG_MOD(extack,
       "Policer is not supported on shared ingress blocks");
  return -EOPNOTSUPP;
 }

 if (port->tc.police_id && port->tc.police_id != police_id) {
  NL_SET_ERR_MSG_MOD(extack,
       "Only one policer per port is supported");
  return -EEXIST;
 }

 return 0;
}

int lan966x_police_port_add(struct lan966x_port *port,
       struct flow_action *action,
       struct flow_action_entry *act,
       unsigned long police_id,
       bool ingress,
       struct netlink_ext_ack *extack)
{
 struct lan966x *lan966x = port->lan966x;
 struct rtnl_link_stats64 new_stats;
 struct lan966x_tc_policer pol;
 struct flow_stats *old_stats;
 int err;

 err = lan966x_police_validate(port, action, act, police_id, ingress,
          extack);
 if (err)
  return err;

 memset(&pol, 0, sizeof(pol));

 pol.rate = div_u64(act->police.rate_bytes_ps, 1000) * 8;
 pol.burst = act->police.burst;

 err = lan966x_police_add(port, &pol, POL_IDX_PORT + port->chip_port);
 if (err) {
  NL_SET_ERR_MSG_MOD(extack,
       "Failed to add policer to port");
  return err;
 }

 lan_rmw(ANA_POL_CFG_PORT_POL_ENA_SET(1) |
  ANA_POL_CFG_POL_ORDER_SET(POL_ORDER),
  ANA_POL_CFG_PORT_POL_ENA |
  ANA_POL_CFG_POL_ORDER,
  lan966x, ANA_POL_CFG(port->chip_port));

 port->tc.police_id = police_id;

 /* Setup initial stats */
 old_stats = &port->tc.police_stat;
 lan966x_stats_get(port->dev, &new_stats);
 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;

 return 0;
}

int lan966x_police_port_del(struct lan966x_port *port,
       unsigned long police_id,
       struct netlink_ext_ack *extack)
{
 struct lan966x *lan966x = port->lan966x;

 if (port->tc.police_id != police_id) {
  NL_SET_ERR_MSG_MOD(extack,
       "Invalid policer id");
  return -EINVAL;
 }

 lan966x_police_del(port, POL_IDX_PORT + port->chip_port);

 lan_rmw(ANA_POL_CFG_PORT_POL_ENA_SET(0) |
  ANA_POL_CFG_POL_ORDER_SET(POL_ORDER),
  ANA_POL_CFG_PORT_POL_ENA |
  ANA_POL_CFG_POL_ORDER,
  lan966x, ANA_POL_CFG(port->chip_port));

 port->tc.police_id = 0;

 return 0;
}

void lan966x_police_port_stats(struct lan966x_port *port,
          struct flow_stats *stats)
{
 struct rtnl_link_stats64 new_stats;
 struct flow_stats *old_stats;

 old_stats = &port->tc.police_stat;
 lan966x_stats_get(port->dev, &new_stats);

 flow_stats_update(stats,
     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;
}

Messung V0.5
C=97 H=100 G=98

¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet)  ¤

*© 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.