// SPDX-License-Identifier: GPL-2.0 /* Copyright 2020 NXP */ #include <net/tc_act/tc_gate.h> #include <linux/dsa/8021q.h> #include "sja1105_vl.h" #define SJA1105_SIZE_VL_STATUS … /* Insert into the global gate list, sorted by gate action time. */ static int sja1105_insert_gate_entry(struct sja1105_gating_config *gating_cfg, struct sja1105_rule *rule, u8 gate_state, s64 entry_time, struct netlink_ext_ack *extack) { … } /* The gate entries contain absolute times in their e->interval field. Convert * that to proper intervals (i.e. "0, 5, 10, 15" to "5, 5, 5, 5"). */ static void sja1105_gating_cfg_time_to_interval(struct sja1105_gating_config *gating_cfg, u64 cycle_time) { … } static void sja1105_free_gating_config(struct sja1105_gating_config *gating_cfg) { … } static int sja1105_compose_gating_subschedule(struct sja1105_private *priv, struct netlink_ext_ack *extack) { … } /* The switch flow classification core implements TTEthernet, which 'thinks' in * terms of Virtual Links (VL), a concept borrowed from ARINC 664 part 7. * However it also has one other operating mode (VLLUPFORMAT=0) where it acts * somewhat closer to a pre-standard implementation of IEEE 802.1Qci * (Per-Stream Filtering and Policing), which is what the driver is going to be * implementing. * * VL Lookup * Key = {DMAC && VLANID +---------+ Key = { (DMAC[47:16] & VLMASK == * && VLAN PCP | | VLMARKER) * && INGRESS PORT} +---------+ (both fixed) * (exact match, | && DMAC[15:0] == VLID * all specified in rule) | (specified in rule) * v && INGRESS PORT } * ------------ * 0 (PSFP) / \ 1 (ARINC664) * +-----------/ VLLUPFORMAT \----------+ * | \ (fixed) / | * | \ / | * 0 (forwarding) v ------------ | * ------------ | * / \ 1 (QoS classification) | * +---/ ISCRITICAL \-----------+ | * | \ (per rule) / | | * | \ / VLID taken from VLID taken from * v ------------ index of rule contents of rule * select that matched that matched * DESTPORTS | | * | +---------+--------+ * | | * | v * | VL Forwarding * | (indexed by VLID) * | +---------+ * | +--------------| | * | | select TYPE +---------+ * | v * | 0 (rate ------------ 1 (time * | constrained) / \ triggered) * | +------/ TYPE \------------+ * | | \ (per VLID) / | * | v \ / v * | VL Policing ------------ VL Policing * | (indexed by VLID) (indexed by VLID) * | +---------+ +---------+ * | | TYPE=0 | | TYPE=1 | * | +---------+ +---------+ * | select SHARINDX select SHARINDX to * | to rate-limit re-enter VL Forwarding * | groups of VL's with new VLID for egress * | to same quota | * | | | * | select MAXLEN -> exceed => drop select MAXLEN -> exceed => drop * | | | * | v v * | VL Forwarding VL Forwarding * | (indexed by SHARINDX) (indexed by SHARINDX) * | +---------+ +---------+ * | | TYPE=0 | | TYPE=1 | * | +---------+ +---------+ * | select PRIORITY, select PRIORITY, * | PARTITION, DESTPORTS PARTITION, DESTPORTS * | | | * | v v * | VL Policing VL Policing * | (indexed by SHARINDX) (indexed by SHARINDX) * | +---------+ +---------+ * | | TYPE=0 | | TYPE=1 | * | +---------+ +---------+ * | | | * | v | * | select BAG, -> exceed => drop | * | JITTER v * | | ---------------------------------------------- * | | / Reception Window is open for this VL \ * | | / (the Schedule Table executes an entry i \ * | | / M <= i < N, for which these conditions hold): \ no * | | +----/ \-+ * | | |yes \ WINST[M] == 1 && WINSTINDEX[M] == VLID / | * | | | \ WINEND[N] == 1 && WINSTINDEX[N] == VLID / | * | | | \ / | * | | | \ (the VL window has opened and not yet closed)/ | * | | | ---------------------------------------------- | * | | v v * | | dispatch to DESTPORTS when the Schedule Table drop * | | executes an entry i with TXEN == 1 && VLINDEX == i * v v * dispatch immediately to DESTPORTS * * The per-port classification key is always composed of {DMAC, VID, PCP} and * is non-maskable. This 'looks like' the NULL stream identification function * from IEEE 802.1CB clause 6, except for the extra VLAN PCP. When the switch * ports operate as VLAN-unaware, we do allow the user to not specify the VLAN * ID and PCP, and then the port-based defaults will be used. * * In TTEthernet, routing is something that needs to be done manually for each * Virtual Link. So the flow action must always include one of: * a. 'redirect', 'trap' or 'drop': select the egress port list * Additionally, the following actions may be applied on a Virtual Link, * turning it into 'critical' traffic: * b. 'police': turn it into a rate-constrained VL, with bandwidth limitation * given by the maximum frame length, bandwidth allocation gap (BAG) and * maximum jitter. * c. 'gate': turn it into a time-triggered VL, which can be only be received * and forwarded according to a given schedule. */ static bool sja1105_vl_key_lower(struct sja1105_vl_lookup_entry *a, struct sja1105_vl_lookup_entry *b) { … } /* FIXME: this should change when the bridge upper of the port changes. */ static u16 sja1105_port_get_tag_8021q_vid(struct dsa_port *dp) { … } static int sja1105_init_virtual_links(struct sja1105_private *priv, struct netlink_ext_ack *extack) { … } int sja1105_vl_redirect(struct sja1105_private *priv, int port, struct netlink_ext_ack *extack, unsigned long cookie, struct sja1105_key *key, unsigned long destports, bool append) { … } int sja1105_vl_delete(struct sja1105_private *priv, int port, struct sja1105_rule *rule, struct netlink_ext_ack *extack) { … } int sja1105_vl_gate(struct sja1105_private *priv, int port, struct netlink_ext_ack *extack, unsigned long cookie, struct sja1105_key *key, u32 index, s32 prio, u64 base_time, u64 cycle_time, u64 cycle_time_ext, u32 num_entries, struct action_gate_entry *entries) { … } static int sja1105_find_vlid(struct sja1105_private *priv, int port, struct sja1105_key *key) { … } int sja1105_vl_stats(struct sja1105_private *priv, int port, struct sja1105_rule *rule, struct flow_stats *stats, struct netlink_ext_ack *extack) { … }