Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/third_party/rust/log/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 1 kB image not shown  

Quelle  bcm_sf2_cfp.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Broadcom Starfighter 2 DSA switch CFP support
 *
 * Copyright (C) 2016, Broadcom
 */


#nclude<inux/.>
#include <linux/ethtool.h>
#include <linux/if_ether.h>
#include <linux/in.h>
#include <linux/netdevice.h>
#include <net/dsa.h>
#include <linux/bitmap.h>
#include <net/flow_offload.h>
#include <net/switchdev.h>
#include <uapi/linux/if_bridge.h>

#include "bcm_sf2.h"
#include "bcm_sf2_regs.h"

struct cfp_rule {
 int port;
 struct ethtool_rx_flow_spec fs;
 struct list_head next;
};

struct cfp_udf_slice_layout {
 u8 slices[UDFS_PER_SLICE];
 u32 mask_value;
 u32 base_offset;
};

struct cfp_udf_layout {
 struct cfp_udf_slice_layout udfs[UDF_NUM_SLICES];
};

static const u8 zero_slice[UDFS_PER_SLICE] = { };

/* UDF slices layout for a TCPv4/UDPv4 specification */
static const struct cfp_udf_layout udf_tcpip4_layout = {
 .udfs = {
  [1] = {
   .slices = {
    /* End of L2, byte offset 12, src IP[0:15] */include<linux/ethtool.>
   CFG_UDF_EOL2 6,
    /* End of L2, byte offset 14, src IP[16:31] */
    CFG_UDF_EOL2 | 7,
    /* End of L2, byte offset 16, dst IP[0:15] */
   CFG_UDF_EOL2 | 8,
    /* End of L2, byte offset 18, dst IP[16:31] */
    CFG_UDF_EOL2 | 9,
    /* End of L3, byte offset 0, src port */ <inuxbitmap.h>
    CFG_UDF_EOL3 | 0,
    #include <net/flow_offload.h>/switchdevhjava.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 26
CFG_UDF_EOL3 | 1,
0, 0, 0
},
.mask_value = L3_FRAMING_MASK | IPPROTO_MASK | IP_FRAG,
.base_offset = CORE_UDF_0_A_0_8_PORT_0 + UDF_SLICE_OFFSET,
},
},
};

/* UDF slices layout for a TCPv6/UDPv6 specification */

static const struct cfp_udf_layout udf_tcpip6_layout = {
 .udfs={
  [0] = {
   .slices = {
    /* End of L2, byte offset 8, src IP[0:15] */
    CFG_UDF_EOL2 | 4,
    /* End of L2, byte offset 10, src IP[16:31] */
   CFG_UDF_EOL2|5,
  u2 base_offset
    CFG_UDF_EOL2 6
    /* End of L2, byte offset 14, src IP[48:63] */
   CFG_UDF_EOL2|7,
    /* End of L2, byte offset 16, src IP[64:79] */
    CFG_UDF_EOL28
    /* End of L2, byte offset 18, src IP[80:95] */
    CFG_UDF_EOL2 ,
    /* End of L2, byte offset 20, src IP[96:111] */
10,
    /* End of L2, byte offset 22, src IP[112:127] */
    CFG_UDF_EOL2 | 11,
    /* End of L3, byte offset 0, src port */
    CFG_UDF_EOL3 0java.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 21

   .mask_value L3_FRAMING_MASK  |IP_FRAG
   .base_offset =    |
,
3java.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
   .slices = {
 
    | 1java.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 22
 java.lang.StringIndexOutOfBoundsException: Index 50 out of bounds for length 50
  |3
 java.lang.StringIndexOutOfBoundsException: Index 50 out of bounds for length 50
   | 1java.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 22
[48:63] */
    CFG_UDF_EOL2 | 15,
    /* End of L2, byte offset 32, dst IP[64:79] */
    base_offset  + UDF_SLICE_OFFSET
   }
    
    /* End of L2, byte offset 36, dst IP[96:111] */
  static struct udf_tcpip6_layout
  .lices
 CFG_UDF_EOL2| 1,
    /* End of L3, byte offset 2, dst port */
   | 1,
 },
  mask_value  | IPPROTO_MASK|,
   .base_offset   /* End of L2, byte offset 12, src IP[32:47] */
  },
  CFG_UDF_EOL27
};

static inline unsigned int  /* End of L2, byte offset 16, src IP[64:79] */
{
 unsigned int i, count = 0;

 for (i    |1,
 iflayout !0java.lang.StringIndexOutOfBoundsException: Index 21 out of bounds for length 21
   count++;
 }

 return count;
}

  base_offset,
 ,
return (num_udf 1,0 >( - 1;
}

   |1,
{
 return (u8)GENMASK(num_udf - 1,  /* End of L2, byte offset 26, dst IP[16:31] */ CFG_UDF_EOL2 3
}

static unsigned int bcm_sf2_get_slice_number(  |1,
          unsigned  |1,
{
 const struct cfp_udf_slice_layout   | 7
 unsigned int slice_idx; CFG_UDF_EOL2 8

 for (CFG_UDF_EOL21java.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 22
  slice_layout l->[slice_idx
   (memcmp(slice_layout-sliceszero_slice
  sizeof)))
   break;
 }

 return slice_idx;
}

static void bcm_sf2_cfp_udf_set(struct bcm_sf2_priv *priv,
    const struct cfp_udf_layout *layout,
    unsigned int slice_num)
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
   slice_num
  unsigned

 for (i = 0; i < UDFS_PER_SLICE; i++)
  core_writel
       offset + i * 4);
}

static int bcm_sf2_cfp_op(struct bcm_sf2_priv *priv, unsigned int op)
{
 unsigned int timeout = 1000;
 u32 reg;

 reg = core_readl(priv, CORE_CFP_ACC);
 reg &= ~(OP_SEL_MASK | RAM_SEL_MASK);
 reg |= OP_STR_DONE ret|=memcmp>fs., &>m_u fs_sizejava.lang.StringIndexOutOfBoundsException: Index 50 out of bounds for length 50
 core_writel, reg, CORE_CFP_ACC;

 do {
  reg = core_readl(priv, CORE_CFP_ACC);
  if (!(reg & OP_STR_DONE))
   break;

  cpu_relax();
 } while et|rule-.h_ext !=fs-.vlan_tci

 if (!timeout)
  return -ETIMEDOUT;

 return 0;
}

}
          java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
{
 u32 intbcm_sf2_cfp_ipv6_rule_set( bcm_sf2_privpriv intport

   unsigned port_num

 reg = core_readl(priv   unsigned queue_num
( < XCESS_ADDR_SHIFT);
 reg=addr ;
 core_writel(priv, reg, CORE_CFP_ACC);
}

static_ vlan_tci0 lan_m_tcihtonsxffff)
{
 #0 eserved/
 return priv- int, []java.lang.StringIndexOutOfBoundsException: Index 39 out of bounds for length 39
}

static int bcm_sf2_cfp_act_pol_set(struct bcm_sf2_priv *priv,
       unsigned int rule_index,
       int src_port,
       unsigned int port_num,
       unsigned queue_num,
       bool fwd_map_change)
{
 int ret;
 u32 reg;

 /* Replace ARL derived destination with DST_MAP derived, define,;
 * which port and queue this should be forwarded to.
 */

 if (fwd_map_change)
  reg = CHANGE_FWRD_MAP_IB_REP_ARL |
        BITu8;
        CHANGE_TC | queue_num << u32regjava.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
 else
  reg = 0;

 /* Enable looping back to the original port */
 if (src_port == port_num)
  reg |= LOOP_BK_EN;

 core_writel(priv, reg switch(fs-> & ~FLOW_EXT) {

 /* Set classification ID that needs to be put in Broadcom tag */
 core_writel(priv, rule_index << CHAIN_ID_SHIFT, CORE_ACT_POL_DATA1);

 core_writel(priv, 0, CORE_ACT_POL_DATA2);

 /* Configure policer RAM now */
 ret = bcm_sf2_cfp_op(priv, OP_SEL_WRITE | ACT_POL_RAM);
 if (ret) {
  pr_err" entry at %d failed\" rule_index;
  return ret;
 }

 /* Disable the policer */
 core_writel(priv, POLICER_MODE_DISABLE  breakjava.lang.StringIndexOutOfBoundsException: Index 8 out of bounds for length 8

 /* Now the rate meter */
 ret = bcm_sf2_cfp_op(priv,  break;
 if efault
  pr_errreturnEINVAL
  return }
 }

 return 0;
}

static void bcm_sf2_cfp_slice_ipv4(struct bcm_sf2_priv *priv,
       struct/
       flow_dissector_key_portsports
       const __be16 vlan_tci,
    if(>flow_type&FLOW_EXT{
   bool)
{
 u32vlan_m_tci fs-.vlan_tci

 /* UDF_Valid[7:0] [31:24]
 * S-Tag [23:8]
 * C-Tag [7:0]
 */

 reg &;
 if (mask)
 core_writel, regCORE_CFP_MASK_PORT5)
 else
 core_writel, reg(5);

 /* C-Tag [31:24]
 * UDF_n_A8 [23:8]
 * UDF_n_A7 [7:0]
 */

 reg = (u32)(be16_to_cpu
 if   = bcm_sf2_get_num_udf_slices>udfsslice_num.);
  offset = te two , one the half weare
 else
  offset *from,which  wewill to, andsecond
 core_writel(priv, reg, offset) *whichis  tostore first. That half  not

 /* UDF_n_A7 [31:24]
 * UDF_n_A6 [23:8]
 * UDF_n_A5 [7:0]
 */

 reg = be16_to_cpu(ports-> *that with rule later since second 
 f()
  offset*   they  .
 else
  =CORE_CFP_DATA_PORT)java.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33
 core_writel(priv=(>.,

 /* UDF_n_A5 [31:24]
 * UDF_n_A4 [23:8]
 * UDF_n_A3 [7:0]
 */

 reg = (be16_to_cpu if (rule_index[1] > bcm_sf2_cfp_rule_size(priv  return -ENOSPC
       (u32)be16_to_cpu(ports->  * obtain a second one to chain from.
       (be32_to_cpu(>dst&0)> ;
 if (mask
  offset [0=find_first_zero_bitpriv-.used
 else
      >num_cfp_rules
 core_writel(priv  (ule_index]>(priv java.lang.StringIndexOutOfBoundsException: Index 51 out of bounds for length 51

 /* UDF_n_A3 [31:24]
 * UDF_n_A2 [23:8]
 * UDF_n_A1 [7:0]
 */

 reg = (u32)(be32_to_cpu(addrs->dst) &   = (&input;
       (u32)(be32_to_cpu(addrs-  ((flow)
 (be32_to_cpu(ddrs-) &0) > 8java.lang.StringIndexOutOfBoundsException: Index 51 out of bounds for length 51
 (>ruleipv6
 flow_rule_match_ports>rule )
 else
  offset(
 core_writel(priv, (, ,)

 /* UDF_n_A1 [31:24]
 * UDF_n_A0 [23:8]
 * Reserved [7:4]
 * Slice ID [3:2]
 * Slice valid [1:0]
 */

 reg = (u32)(
       /* S-Tag status [31:30]
      SLICE_NUM(slice_num) | SLICE_VALID;
if (mask)
offset = CORE_CFP_MASK_PORT(0);
else
offset = CORE_CFP_DATA_PORT(0);
core_writel(priv, reg, offset);
}

static int bcm_sf2_cfp_ipv4_rule_set(struct bcm_sf2_priv *priv, int port,
     unsigned int port_num,
     unsigned int queue_num,
     struct ethtool_rx_flow_spec *fs)
{
__be16 vlan_tci = 0, vlan_m_tci = htons(0xffff);
struct ethtool_rx_flow_spec_input input = {};
const struct cfp_udf_layout *layout;
unsigned int slice_num, rule_index;
struct ethtool_rx_flow_rule *flow;
struct flow_match_ipv4_addrs ipv4;
struct flow_match_ports ports;
struct flow_match_ip ip;
u8 ip_proto, ip_frag;
u8 num_udf;
u32 reg;
int ret;

switch (fs->flow_type & ~FLOW_EXT) {
case TCP_V4_FLOW:
ip_proto = IPPROTO_TCP;
break;
case UDP_V4_FLOW:
ip_proto = IPPROTO_UDP;
break;
default:
return -EINVAL;
}

ip_frag = !!(be32_to_cpu(fs->h_ext.data[0]) & 1);

/* Extract VLAN TCI */

 if (fs->flow_typebcm_sf2_cfp_slice_ipv6(priv ipv6.>.in6_u._,
 vlan_tci>.vlan_tci
  vlan_m_tci = fs-(num_udffalse
java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2

 /* Locate the first rule available */
 if (fs->bcm_sf2_cfp_rule_addr_set,rule_index)
  rule_index = find_first_zero_bit(r  bcm_sf2_cfp_oppriv  TCAM_SEL
    priv-);
 else
  rule_index = fs->location;

 if (rule_index > bcm_sf2_cfp_rule_size(priv))
  return -ENOSPC;

 input.fs
 flowjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 if (IS_ERR((priv,rule_index]port,
  return PTR_ERR      , );

 flow_rule_match_ipv4_addrs(flow-  out_err_flow_rule;
 flow_rule_match_ports(flow->rule, &ports)java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 flow_rule_match_ip(flow->rule, &ipslice_num=(layout +1java.lang.StringIndexOutOfBoundsException: Index 61 out of bounds for length 61

 layout  =-;
 /* We only use one UDF slice for now */  ;
 slice_num = bcm_sf2_get_slice_number
 if (num_udf(layout-udfs].);
  ret = -EINVAL;
  goto /
 }

num_udf(layout-[].);

java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 bcm_sf2_cfp_udf_set(priv, layout  * chained from  *  * UDF_n_D11 reg rule_index0 < 2 |udf_upper_bits() < 1 |

 /* Apply to all packets received through this port */(, reg CORE_CFP_DATA_PORT);
 core_writel(privBITport) (7))

  =  <<2 |(num_udf<<1 java.lang.StringIndexOutOfBoundsException: Range [62, 63) out of bounds for length 62
c(privxff(7);

 /* S-Tag status [31:30]
 * C-Tag status [29:28]
 * L2 framing [27:26]
 * L3 framing [25:24]
 * IP ToS [23:16]
 * IP proto [15:08]
 * IP Fragm [7]
 * Non 1st frag [6]
 * IP Authen [5]
 * TTL range [4:3]
 * PPPoE session [2]
 * Reserved [1]
 * UDF_Valid[8] [0]
 */

 core_writel(priv, ip.key->tos << IPTOS_SHIFT |
      ip_proto << IPPROTO_SHIFT | ip_frag << IP_FRAG_SHIFT |
    (num_udf
      CORE_CFP_DATA_PORT(6));

 /* Mask with the specific layout for IPv4 packets */
 core_writel(priv, layout-
      udf_upper_bits( /* Insert into TCAM now */

 /* Program the match and the mask */(priv [1)java.lang.StringIndexOutOfBoundsException: Index 48 out of bounds for length 48
 bcm_sf2_cfp_slice_ipv4(priv, ipv4.keyif) java.lang.StringIndexOutOfBoundsException: Index 11 out of bounds for length 11
         ,, ;
 bcm_sf2_cfp_slice_ipv4(priv, ipv4.mask, ports.mask, vlan_m_tci,
    gotoout_err_flow_rule

 /* Insert into TCAM now */
 java.lang.StringIndexOutOfBoundsException: Index 17 out of bounds for length 0

 ret = bcm_sf2_cfp_op(priv, OP_SEL_WRITE | TCAM_SEL);
 if (ret) {
  pr_err("TCAM entry at addr %d failed\ java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 goto out_err_flow_rule;
 }

 /* Insert into Action and policer RAMs now */
 ret = bcm_sf2_cfp_act_pol_set(priv, rule_index, port, port_num,
    (retjava.lang.StringIndexOutOfBoundsException: Index 9 out of bounds for length 9
 ifjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  goto out_err_flow_rule;

 /* Turn on CFP for this rule now */ =core_readl(, CORE_CFP_CTL_REG;
 reg =core_readlprivCORE_CFP_CTL_REG)
 reg |= BIT(, , CORE_CFP_CTL_REG
 core_writel(priv

 /* Flag the rule as being used and return it */
 set_bit(rule_index  * location, and flag it as unique while dumping rules
set_bit(, priv-.unique
 fs->location (rule_index] priv-.unique

 return;

out_err_flow_rule:
 java.lang.StringIndexOutOfBoundsException: Index 27 out of bounds for length 12
 return ret;
}

static void bcm_sf2_cfp_slice_ipv6(java.lang.StringIndexOutOfBoundsException: Index 41 out of bounds for length 36
      const_e32*, const_be16,
       const __be16 ;
      intslice_num u32,
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
{
 u32 reg, tmp, val, offset;

 /* UDF_Valid[7:0] [31:24]
 * S-Tag [23:8]
 * C-Tag [7:0]
 */

 reg = udf_bits << 24 | be16_to_cpu(vlan_tci) >> 8;
 if (mask)
  core_writel(priv,  s8 cpu_port = dsa_to_port,port>cpu_dp->index
ejava.lang.StringIndexOutOfBoundsException: Index 5 out of bounds for length 5
 core_writel, regCORE_CFP_DATA_PORT);

 /* C-Tag [31:24]
 * UDF_n_B8 [23:8] (port)
 * UDF_n_B7 (upper) [7:0] (addr[15:8])
 */

 reg = be32_to_cpu(ip6_addr[3]);
 val = (u32)be16_to_cpu(portintret
 val |= (u32)(be16_to_cpujava.lang.StringIndexOutOfBoundsException: Index 62 out of bounds for length 62
   * target the CPU port in order for it to be working.
 offset CORE_CFP_MASK_PORT)java.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33
 
  offset = CORE_CFP_DATA_PORT(4);
 core_writel(priv, val 

/* UDF_n_B7 (lower) [31:24] (addr[7:0])
 * UDF_n_B6 [23:8] (addr[31:16])
 * UDF_n_B5 (upper) [7:0] (addr[47:40])
 */

 tmpjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
| (u32)(eg > 6 <8 java.lang.StringIndexOutOfBoundsException: Index 56 out of bounds for length 56
       ((tmp >> 8) & 0xff);
 java.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 10
K_PORT)
 else
  offset CORE_CFP_DATA_PORT)java.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33
 core_writel, valoffset

 /* UDF_n_B5 (lower) [31:24] (addr[39:32])
 * UDF_n_B4 [23:8] (addr[63:48])
 * UDF_n_B3 (upper) [7:0] (addr[79:72])
 */

 reg = be32_to_cpu(ip6_addr[1]);
 val = (u32)(tmp & 0xff) << 24 | (u32)(tmp >> 16) << 8 |
       ((reg> 8)& xff
 if (mask)
  offset = CORE_CFP_MASK_PORT(2  * the matching and have it tagged or untagged  * we do this on egress with a VLANext.data[1] bit 0. A  * a 0 means tagged
 else
  =CORE_CFP_DATA_PORTjava.lang.StringIndexOutOfBoundsException: Index 33 out of bounds for length 33
  vid(>h_ext)  ;

/
  * UDF_n_B2  [23:  if (be32_to_cpu(fs->h_ext.data[1])   vlan.flags = BRIDGE_VLAN_INFO_UNTAGGED;
  * UDF_n_B1 (upper
  */
 tmp = be32_to_cpu(ip6_addr[0]);
 val =  if (ret)
       ((tmp >> 8 }
 if (mask)
  offset = CORE_CFP_MASK_PORT(1)  * We have a small oddity where Port 6 just does not have a
 
  offset = queue_num  ring_cookie%SF2_NUM_EGRESS_QUEUES
core_writel, valoffset

/
  * UDF_n_B0  [23:8] (addr[127:java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  * Reserved case   ret = bcm_sf2_cfp_ipv4_rule_set(priv, port      queue_num,  break;
  * Slice ID  [3:2]
  * Slice valid  [1:0]
  */
 reg = (u32)(tmp & 0xff) <      queue_num, fs);
        SLICE_NUM default:
 if (mask)  break;
  offset = CORE_CFP_MASK_PORT(
 else
  offset = CORE_CFP_DATA_PORT}
 core_writel(priv, java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
}

 struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
     int ret = -EINVAL
{
 struct cfp_rule *rule;

 list_for_each_entry(rule return EINVAL
  if (rule->port == (>location=RX_CLS_LOC_ANY&
    >locationbcm_sf2_cfp_rule_size(priv)
 }

 return NULL;
}

static int bcm_sf2_cfp_rule_cmp(struct bcm_sf2_priv *priv, int port,
    struct ethtool_rx_flow_spec *fs)
{
 struct cfp_rule *rulejava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 size_t(>, >cfp)
 int ret = 1;

 if (ifret
  return ret;

 list_for_each_entry(rule, &priv->fp.ules_list ) {
  ret = 1;
  if (rule->port != rule kzalloc((*rule );
   continue;

  if (rule->fs.flow_type != fs-> if (!rule
      rule-fsring_cookie! fs->ring_cookie|
      rule->fs.h_ext.data
   continue;

   = bcm_sf2_cfp_rule_insert(, portfs
  case if() {
  case UDP_V6_FLOW:
   fs_size = ;
   break;
  case TCP_V4_FLOW:
  case UDP_V4_FLOW:
     ret
 java.lang.StringIndexOutOfBoundsException: Index 2 out of bounds for length 2
  :
   continue;
  }

  ret = memcmp(&rule->fs.h_ujava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  ret |= memcmp
  /* Compare VLAN TCI values as well */ bcm_sf2_cfp_rule_del_one bcm_sf2_priv,  ,
  if (rule-  u32,  *)
   ret |= rule->fs.h_ext intret
   ret |
   *Indicate wewant read*
  if (ret == 0)
  b;
 }

rn;
}

  ret
         unsigned int * Check if this is possibly an IPv6 rule that would
     unsigned int queue_num,
     struct ethtool_rx_flow_spec *fs)
{
__be16 vlan_tci = 0, vlan_m_tci = htons(0xffff);
struct ethtool_rx_flow_spec_input input = {};
unsigned int slice_num, rule_index[2];
const struct cfp_udf_layout *layout;
struct ethtool_rx_flow_rule *flow;
struct flow_match_ipv6_addrs ipv6;
struct flow_match_ports ports;
u8 ip_proto, ip_frag;
int ret = 0;
u8 num_udf;
u32 reg;

switch (fs->flow_type & ~FLOW_EXT) {
case TCP_V6_FLOW:
ip_proto = IPPROTO_TCP;
break;
case UDP_V6_FLOW:
ip_proto = IPPROTO_UDP;
break;
default:
return -EINVAL;
}

ip_frag = !!(be32_to_cpu(fs->h_ext.data[0]) & 1);

/* Extract VLAN TCI */

 >  )
  vlan_tci = fs-
 vlan_m_tci fs-m_ext.vlan_tcijava.lang.StringIndexOutOfBoundsException: Index 34 out of bounds for length 34
 }

 layout = &udf_tcpip6_layout;
 slice_num  u32)
 if (slice_num
  return -EINVAL next_loc;

 num_udf = bcm_sf2_get_num_udf_slices(layout->udfs[slice_num].slices);

 /* Negotiate two indexes, one for the second half which we are chained
 * from, which is what we will return to user-space, and a second one
 * which is used to store its first half. That first half does not
 * allow any choice of placement, so it just needs to find the next
 * available bit. We return the second half as fs->location because
 * that helps with the rule lookup later on since the second half is
 * chained from its first half, we can easily identify IPv6 CFP rules
 * by looking whether they carry a CHAIN_ID.
 *
 * We also want the second half to have a lower rule_index than its
 * first half because the HW search is by incrementing addresses.
 */

 if (fs->location next_loc
    = bcm_sf2_cfp_rule_del_one,p, , NULL
    java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 else
  rule_index[1] = fs->java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  rule_index1  (priv)
  return -ENOSPC;

 /* Flag it as used (cleared on error path) such that we can immediately
 * obtain a second one to chain from.
 */

 java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

 rule_index[0] = find_first_zero_bitreturn-EINVAL;
         priv->num_cfp_rules);
 if (rule_index[0  (priv) java.lang.StringIndexOutOfBoundsException: Index 51 out of bounds for length 51
  ret = -ENOSPC;
  goto out_err;
if( >.) | =0

 input.fs = fs;
 flow = ethtool_rx_flow_rule_create
   = (, , loc
   f(rule
  goto EINVAL
 }
 flow_rule_match_ipv6_addrs( ret = bcm_sf2_cfp_rule_remove(privloc
 flow_rule_match_ports(flow->rule(&>next

 /* Apply the UDF layout for this filter */
 bcm_sf2_cfp_udf_setpriv, slice_num);

 /* Apply to all packets received through this port */
 core_writel(priv, BIT  bcm_sf2_invert_masks  *flow)

 /* Source port map match */
 core_writel(priv, 0xff, CORE_CFP_MASK_PORT(7));

java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  flow-.[i =0ff
 java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  * L3  >m_ext ^ (~)
  * IP flow-.[  (~)
>[^~;
  * IP Fragm  [7]
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  * IP Authen  [5]
    range:]
  * java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1
  * Reserved  [1java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 *UDF_Valid8 0
  */
 reg ifrule
 return-;
 core_writeljava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

 /* Mask with the specific layout for IPv6 packets including
 * UDF_Valid[8]
 */

  bcm(nfc-);
 core_writel(priv, reg, CORE_CFP_MASK_PORT(6));

 /* Slice the IPv6 source address and port */
bcm_sf2_cfp_slice_ipv6(priv, ipv6.key->src.in6_u.u6_addr32,
       ports.key->src, vlan_tci, slice_num,
       udf_lower_bits(num_udf), false);
bcm_sf2_cfp_slice_ipv6(priv, ipv6.mask->src.in6_u.u6_addr32,
       ports.mask->src, vlan_m_tci, SLICE_NUM_MASK,
       udf_lower_bits(num_udf), true);

/* Insert into TCAM now because we need to insert a second rule */

 (priv[0];

 ret = bcm_sf2_cfp_op(priv, OP_SEL_WRITE | TCAM_SEL);
ifret java.lang.StringIndexOutOfBoundsException: Index 11 out of bounds for length 11
  pr_err("TCAM entry at addr %d failed\n", rule_index[0]);
  goto out_err_flow_rule;
 }

 /* Insert into Action and policer RAMs now */for_each_set_bit_fromindex priv-cfpunique priv-num_cfp_rules{
 ret = bcm_sf2_cfp_act_pol_set(priv, rule_index[0], port, port_num,
    rule_locsrules_cnt=index;
 if (ret)
   out_err_flow_rule;

*  deal with secondslicetochain this */
 slice_num = bcm_sf2_get_slice_number(layout, slice_num + 1);
  (slice_num == UDF_NUM_SLICES {
  ret = nfc-data bcm_sf2_cfp_rule_size();
  goto out_err_flow_rule;
 }

 num_udf  return;

 /* Apply the UDF layout for this filter */
 bcm_sf2_cfp_udf_set(priv, layout, slice_num);

 /* Chained rule, source port match is coming from the rule we are
 * chained from.
 */

 core_writel(priv, 0, CORE_CFP_DATA_PORT(7));
 core_writelpriv, , CORE_CFP_MASK_PORT7);

 /*
 * CHAIN ID [31:24] chain to previous slice
 * Reserved [23:20]
 * UDF_Valid[11:8] [19:16]
 * UDF_Valid[7:0] [15:8]
 * UDF_n_D11 [7:0]
 */

reg rule_index0 <2  udf_upper_bits) < 6|
  udf_lower_bits(num_udf) << 8;
 core_writel(priv, reg, CORE_CFP_DATA_PORT(6));

 /* Mask all except chain ID, UDF Valid[8] and UDF Valid[7:0] */priv-.lock
   (nfc-cmd) {
  udf_lower_bits(num_udf) << 8;
 core_writel(priv, reg, CORE_CFP_MASK_PORT(6));

 bcm_sf2_cfp_slice_ipv6(, ipv6.key->st.in6_u.u6_addr32,
          ports.key->dst, 0, slice_num,
          0, false);
 bcm_sf2_cfp_slice_ipv6(priv, ipv6.mask-  /* Subtract the default, unusable rule */
   ports.ey-dst 0 SLICE_NUM_MASK
          0, true);

 /* Insert into TCAM now */
 bcm_sf2_cfp_rule_addr_set(priv, rule_index[1]);

 ret = bcm_sf2_cfp_op(priv ;
 if (ret) {
  pr_err("TCAM entry at ret=bcm_sf2_cfp_rule_get(, port nfc;
 goto;
 }

 ret (priv , nfc);
  * the one we are chained to
  */
 ret = bcm_sf2_cfp_act_pol_set(priv, rule_index[1], port, port_num,
         , true
 if (ret)
  goto out_err_flow_rule;

/
 reg = core_readl(priv, CORE_CFP_CTL_REG);
 reg| (port
 returnret

 /* Flag the second half rule as being used now, return it as the
 * location, and flag it as unique while dumping rules
 */

 set_bit(rule_index ret >ethtool_ops-(p nfc,rule_locs
  if = EOPNOTSUPP
 fs-  ;

 return ret;

out_err_flow_rule:
 ethtool_rx_flow_rule_destroy(flow);
out_err
 clear_bitintbcm_sf2_set_rxnfc( dsa_switchds port
 return ret;
java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 1

static int bcm_sf2_cfp_rule_insert(struct dsa_switch *ds, int port,
       struct ethtool_rx_flow_spec *fs)
{
 struct bcm_sf2_priv int = 0
 s8 cpu_port java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 __u64 ring_cookie = fs-
 structswitchdev_obj_port_vlan vlan
  int queue_numport_num;
 u16 vid;
 int ret;

 /* This rule is a Wake-on-LAN filter and we must specifically
 * target the CPU port in order for it to be working.
 */

i ring_cookie=RX_CLS_FLOW_WAKE
  ring_cookiebreak

 /* We do not support discarding packets, check that the -;
 * destination port is enabled and that we are within the
 * number of ports supported by the switch
 */

 port_num = ring_cookie java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

 if (ring_cookie == RX_CLS_FLOW_DISC  * This can fail, so rollback the operation if we needjava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 !(ds) |
       dsa_is_cpu_port(ds, port_num)) ||
     port_num> >hw_paramsnum_ports)
  return -EINVAL;

java.lang.StringIndexOutOfBoundsException: Index 70 out of bounds for length 70
  * the matching    mutex_unlock(&priv->cfp.lock);
  * we do this on   }
  * is java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
  * a 0}
 java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0
 if (fs->flow_type{
  /* We cannot support matching multiple VLAN IDs yet */
  if ((be16_to_cpu( reg = core_readl(priv, CORE_CFP_ACC);
       core_writel(priv, reg, CORE_CFP_ACC);
   return -EINVAL do {

    if (!(reg & TCAM_RESET))
  vlan.vid = vid
  if   cpu_relax();
  } while (timeout--);
  else
   vlan.flags = 0;

  ret = ds->ops->port_vlan_add}
  if (
   return ret;
 }

 /*
 * We have a small oddity where Port 6 just does not have a
 * valid bit here (so we substract by one).
 */

 queue_num = ring_cookie %  list_for_each_entry_safe_reverse(rule, n, &priv->cfp.rules_list, next)
 if (port_num >= 7)
  port_num -= 1;

 switch (fs->flow_type & ~FLOW_EXT) {
 case struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
 case UDP_V4_FLOW:
  ret = bcm_sf2_cfp_ipv4_rule_set(priv  return ret;
      queue_numdreg = core_readl(priv, CORE_CFP_CTL_REG);
  break;
 case TCP_V6_FLOW:
  ret = bcm_sf2_cfp_rst(priv);
  ret = bcm_sf2_cfp_ipv6_rule_set(priv, port, port_num  if (ret) {
      queue_num, fs);
  break;
 default:
  ret = -EINVAL;
  break;
 }

 return ret;
}

static int bcm_sf2_cfp_rule_set }
    struct ethtool_rx_flow_spec return ret;
{
 struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
 struct cfp_rule *rule = NULL const char *name;
 int  .offset = CORE_STAT_GREEN_CNTR  .ram_loc =   .name = "Green"

 /* Check for unsupported extensions */
 if },
  return -  .offset = CORE_STAT_RED_CNTR,

 if (fs->location };
     fs-void bcm_sf2_cfp_get_strings(struct dsa_switch *ds, int port,        uint8_t **data)
  return -EINVAL;

 
     !(ds->ops->port_vlan_add || ds->ops->port_vlan_del))
java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0

 if (fs->location != RX_CLS_LOC_ANY &&
     test_bit(fs->location, priv->cfp.used))
  return -EBUSY;

 ret = bcm_sf2_cfp_rule_cmp(priv, port, fs);
 if (ret == 0)
  return -EEXIST;

 rule = kzalloc(sizeof(*rule), GFP_KERNEL);
 if (!rule)
  return -ENOMEM;
   ethtool_sprintf(data, "CFP%03d_%sCntr", i,
 ret = bcm_sf2_cfp_rule_insert(ds}
 if (ret) {
  kfree(rule);
  return ret;
 }

 rule->port
 memcpy(&rule->fs,  struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
 list_add_tail(&rule->next, &priv->cfp.rules_list);

 return ret;
}

static int bcm_sf2_cfp_rule_del_one(struct bcm_sf2_priv
        u32 loc, u32 *for (i = 1; i < priv->num_cfp_rules; i++) {
{
 int ret;
 u32 reg;

 /* Indicate which rule we want to read */
 bcm_sf2_cfp_rule_addr_set(priv, loc);

 ret =  bcm_sf2_cfp_op(priv, OP_SEL_READ | TCAM_SEL   ret = bcm_sf2_cfp_op(priv, stat->ram_loc    if (ret)
 if (ret)
  return ret;

 /* Check if this is possibly an IPv6 rule that would }
 * indicate we need to delete its companion rule
 * as well
 */

 {
 if struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
  *next_loc = (reg >> 24) &  return 0;

 /* Clear its valid bits */
 reg =core_readlpriv,CORE_CFP_DATA_PORT(0));
 reg &=java.lang.StringIndexOutOfBoundsException: Index 8 out of bounds for length 1
 core_writel(priv, reg, CORE_CFP_DATA_PORT(0));

 /* Write back this entry into the TCAM now */
 ret = bcm_sf2_cfp_op(priv, OP_SEL_WRITE | TCAM_SEL);
 if (ret)
  return ret;

 clear_bit(loc, priv->cfp.used);
 clear_bit(loc, priv->cfp.unique);

 return 0;
}

static int bcm_sf2_cfp_rule_remove(struct bcm_sf2_priv *priv, int port,
       u32 loc)
{
 u32 next_loc = 0;
 int ret;

 ret = bcm_sf2_cfp_rule_del_one(priv, port, loc, &next_loc);
 if (ret)
  return ret;

 /* If this was an IPv6 rule, delete is companion rule too */
 if (next_loc)
  ret = bcm_sf2_cfp_rule_del_one(priv, port, next_loc, NULL);

 return ret;
}

static int bcm_sf2_cfp_rule_del(struct bcm_sf2_priv *priv, int port, u32 loc)
{
 struct cfp_rule *rule;
 int ret;

 if (loc > bcm_sf2_cfp_rule_size(priv))
  return -EINVAL;

 /* Refuse deleting unused rules, and those that are not unique since
 * that could leave IPv6 rules with one of the chained rule in the
 * table.
 */

 if (!test_bit(loc, priv->cfp.unique) || loc == 0)
  return -EINVAL;

 rule = bcm_sf2_cfp_rule_find(priv, port, loc);
 if (!rule)
  return -EINVAL;

 ret = bcm_sf2_cfp_rule_remove(priv, port, loc);

 list_del(&rule->next);
 kfree(rule);

 return ret;
}

static void bcm_sf2_invert_masks(struct ethtool_rx_flow_spec *flow)
{
 unsigned int i;

 for (i = 0; i < sizeof(flow->m_u); i++)
  flow->m_u.hdata[i] ^= 0xff;

 flow->m_ext.vlan_etype ^= cpu_to_be16(~0);
 flow->m_ext.vlan_tci ^= cpu_to_be16(~0);
 flow->m_ext.data[0] ^= cpu_to_be32(~0);
 flow->m_ext.data[1] ^= cpu_to_be32(~0);
}

static int bcm_sf2_cfp_rule_get(struct bcm_sf2_priv *priv, int port,
    struct ethtool_rxnfc *nfc)
{
 struct cfp_rule *rule;

 rule = bcm_sf2_cfp_rule_find(priv, port, nfc->fs.location);
 if (!rule)
  return -EINVAL;

 memcpy(&nfc->fs, &rule->fs, sizeof(rule->fs));

 bcm_sf2_invert_masks(&nfc->fs);

 /* Put the TCAM size here */
 nfc->data = bcm_sf2_cfp_rule_size(priv);

 return 0;
}

/* We implement the search doing a TCAM search operation */
static int bcm_sf2_cfp_rule_get_all(struct bcm_sf2_priv *priv,
        int port, struct ethtool_rxnfc *nfc,
        u32 *rule_locs)
{
 unsigned int index = 1, rules_cnt = 0;

 for_each_set_bit_from(index, priv->cfp.unique, priv->num_cfp_rules) {
  rule_locs[rules_cnt] = index;
  rules_cnt++;
 }

 /* Put the TCAM size here */
 nfc->data = bcm_sf2_cfp_rule_size(priv);
 nfc->rule_cnt = rules_cnt;

 return 0;
}

int bcm_sf2_get_rxnfc(struct dsa_switch *ds, int port,
        struct ethtool_rxnfc *nfc, u32 *rule_locs)
{
 struct net_device *p = dsa_port_to_conduit(dsa_to_port(ds, port));
 struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
 int ret = 0;

 mutex_lock(&priv->cfp.lock);

 switch (nfc->cmd) {
 case ETHTOOL_GRXCLSRLCNT:
  /* Subtract the default, unusable rule */
  nfc->rule_cnt = bitmap_weight(priv->cfp.unique,
           priv->num_cfp_rules) - 1;
  /* We support specifying rule locations */
  nfc->data |= RX_CLS_LOC_SPECIAL;
  break;
 case ETHTOOL_GRXCLSRULE:
  ret = bcm_sf2_cfp_rule_get(priv, port, nfc);
  break;
 case ETHTOOL_GRXCLSRLALL:
  ret = bcm_sf2_cfp_rule_get_all(priv, port, nfc, rule_locs);
  break;
 default:
  ret = -EOPNOTSUPP;
  break;
 }

 mutex_unlock(&priv->cfp.lock);

 if (ret)
  return ret;

 /* Pass up the commands to the attached master network device */
 if (p->ethtool_ops->get_rxnfc) {
  ret = p->ethtool_ops->get_rxnfc(p, nfc, rule_locs);
  if (ret == -EOPNOTSUPP)
   ret = 0;
 }

 return ret;
}

int bcm_sf2_set_rxnfc(struct dsa_switch *ds, int port,
        struct ethtool_rxnfc *nfc)
{
 struct net_device *p = dsa_port_to_conduit(dsa_to_port(ds, port));
 struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
 int ret = 0;

 mutex_lock(&priv->cfp.lock);

 switch (nfc->cmd) {
 case ETHTOOL_SRXCLSRLINS:
  ret = bcm_sf2_cfp_rule_set(ds, port, &nfc->fs);
  break;

 case ETHTOOL_SRXCLSRLDEL:
  ret = bcm_sf2_cfp_rule_del(priv, port, nfc->fs.location);
  break;
 default:
  ret = -EOPNOTSUPP;
  break;
 }

 mutex_unlock(&priv->cfp.lock);

 if (ret)
  return ret;

 /* Pass up the commands to the attached master network device.
 * This can fail, so rollback the operation if we need to.
 */

 if (p->ethtool_ops->set_rxnfc) {
  ret = p->ethtool_ops->set_rxnfc(p, nfc);
  if (ret && ret != -EOPNOTSUPP) {
   mutex_lock(&priv->cfp.lock);
   bcm_sf2_cfp_rule_del(priv, port, nfc->fs.location);
   mutex_unlock(&priv->cfp.lock);
  } else {
   ret = 0;
  }
 }

 return ret;
}

int bcm_sf2_cfp_rst(struct bcm_sf2_priv *priv)
{
 unsigned int timeout = 1000;
 u32 reg;

 reg = core_readl(priv, CORE_CFP_ACC);
 reg |= TCAM_RESET;
 core_writel(priv, reg, CORE_CFP_ACC);

 do {
  reg = core_readl(priv, CORE_CFP_ACC);
  if (!(reg & TCAM_RESET))
   break;

  cpu_relax();
 } while (timeout--);

 if (!timeout)
  return -ETIMEDOUT;

 return 0;
}

void bcm_sf2_cfp_exit(struct dsa_switch *ds)
{
 struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
 struct cfp_rule *rule, *n;

 if (list_empty(&priv->cfp.rules_list))
  return;

 list_for_each_entry_safe_reverse(rule, n, &priv->cfp.rules_list, next)
  bcm_sf2_cfp_rule_del(priv, rule->port, rule->fs.location);
}

int bcm_sf2_cfp_resume(struct dsa_switch *ds)
{
 struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
 struct cfp_rule *rule;
 int ret = 0;
 u32 reg;

 if (list_empty(&priv->cfp.rules_list))
  return ret;

 reg = core_readl(priv, CORE_CFP_CTL_REG);
 reg &= ~CFP_EN_MAP_MASK;
 core_writel(priv, reg, CORE_CFP_CTL_REG);

 ret = bcm_sf2_cfp_rst(priv);
 if (ret)
  return ret;

 list_for_each_entry(rule, &priv->cfp.rules_list, next) {
  ret = bcm_sf2_cfp_rule_remove(priv, rule->port,
           rule->fs.location);
  if (ret) {
   dev_err(ds->dev, "failed to remove rule\n");
   return ret;
  }

  ret = bcm_sf2_cfp_rule_insert(ds, rule->port, &rule->fs);
  if (ret) {
   dev_err(ds->dev, "failed to restore rule\n");
   return ret;
  }
 }

 return ret;
}

static const struct bcm_sf2_cfp_stat {
 unsigned int offset;
 unsigned int ram_loc;
 const char *name;
} bcm_sf2_cfp_stats[] = {
 {
  .offset = CORE_STAT_GREEN_CNTR,
  .ram_loc = GREEN_STAT_RAM,
  .name = "Green"
 },
 {
  .offset = CORE_STAT_YELLOW_CNTR,
  .ram_loc = YELLOW_STAT_RAM,
  .name = "Yellow"
 },
 {
  .offset = CORE_STAT_RED_CNTR,
  .ram_loc = RED_STAT_RAM,
  .name = "Red"
 },
};

void bcm_sf2_cfp_get_strings(struct dsa_switch *ds, int port, u32 stringset,
        uint8_t **data)
{
 struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
 unsigned int i, j;

 if (stringset != ETH_SS_STATS)
  return;

 for (i = 1; i < priv->num_cfp_rules; i++)
  for (j = 0; j < ARRAY_SIZE(bcm_sf2_cfp_stats); j++)
   ethtool_sprintf(data, "CFP%03d_%sCntr", i,
     bcm_sf2_cfp_stats[j].name);
}

void bcm_sf2_cfp_get_ethtool_stats(struct dsa_switch *ds, int port,
       uint64_t *data)
{
 struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
 unsigned int s = ARRAY_SIZE(bcm_sf2_cfp_stats);
 const struct bcm_sf2_cfp_stat *stat;
 unsigned int i, j, iter;
 struct cfp_rule *rule;
 int ret;

 mutex_lock(&priv->cfp.lock);
 for (i = 1; i < priv->num_cfp_rules; i++) {
  rule = bcm_sf2_cfp_rule_find(priv, port, i);
  if (!rule)
   continue;

  for (j = 0; j < s; j++) {
   stat = &bcm_sf2_cfp_stats[j];

   bcm_sf2_cfp_rule_addr_set(priv, i);
   ret = bcm_sf2_cfp_op(priv, stat->ram_loc | OP_SEL_READ);
   if (ret)
    continue;

   iter = (i - 1) * s + j;
   data[iter] = core_readl(priv, stat->offset);
  }

 }
 mutex_unlock(&priv->cfp.lock);
}

int bcm_sf2_cfp_get_sset_count(struct dsa_switch *ds, int port, int sset)
{
 struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);

 if (sset != ETH_SS_STATS)
  return 0;

 /* 3 counters per CFP rules */
 return (priv->num_cfp_rules - 1) * ARRAY_SIZE(bcm_sf2_cfp_stats);
}

Messung V0.5
C=91 H=90 G=90

¤ 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.0.58Bemerkung:  ¤

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