if (rule->type != SJA1105_RULE_VL) continue; if (rule->vl.type != SJA1105_VL_TIME_TRIGGERED) continue;
/* Calculate the difference between this gating schedule's * base time, and the base time of the gating schedule with the * longest cycle time. We call it the relative base time (rbt).
*/
rbt = future_base_time(rule->vl.base_time, rule->vl.cycle_time,
its_base_time);
rbt -= its_base_time;
time = rbt;
for (i = 0; i < rule->vl.num_entries; i++) {
u8 gate_state = rule->vl.entries[i].gate_state;
s64 entry_time = time;
while (entry_time < max_cycle_time) {
rc = sja1105_insert_gate_entry(gating_cfg, rule,
gate_state,
entry_time,
extack); if (rc) goto err;
entry_time += rule->vl.cycle_time;
}
time += rule->vl.entries[i].interval;
}
}
/* 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.
*/
staticbool sja1105_vl_key_lower(struct sja1105_vl_lookup_entry *a, struct sja1105_vl_lookup_entry *b)
{ if (a->macaddr < b->macaddr) returntrue; if (a->macaddr > b->macaddr) returnfalse; if (a->vlanid < b->vlanid) returntrue; if (a->vlanid > b->vlanid) returnfalse; if (a->port < b->port) returntrue; if (a->port > b->port) returnfalse; if (a->vlanprior < b->vlanprior) returntrue; if (a->vlanprior > b->vlanprior) returnfalse; /* Keys are equal */ returnfalse;
}
/* FIXME: this should change when the bridge upper of the port changes. */ static u16 sja1105_port_get_tag_8021q_vid(struct dsa_port *dp)
{ unsignedlong bridge_num;
if (!dp->bridge) return dsa_tag_8021q_standalone_vid(dp);
bridge_num = dsa_port_bridge_num_get(dp);
return dsa_tag_8021q_bridge_vid(bridge_num);
}
staticint sja1105_init_virtual_links(struct sja1105_private *priv, struct netlink_ext_ack *extack)
{ struct sja1105_vl_policing_entry *vl_policing; struct sja1105_vl_forwarding_entry *vl_fwd; struct sja1105_vl_lookup_entry *vl_lookup; bool have_critical_virtual_links = false; struct sja1105_table *table; struct sja1105_rule *rule; int num_virtual_links = 0; int max_sharindx = 0; int i, j, k;
/* Figure out the dimensioning of the problem */
list_for_each_entry(rule, &priv->flow_block.rules, list) { if (rule->type != SJA1105_RULE_VL) continue; /* Each VL lookup entry matches on a single ingress port */
num_virtual_links += hweight_long(rule->port_mask);
if (rule->vl.type != SJA1105_VL_NONCRITICAL)
have_critical_virtual_links = true; if (max_sharindx < rule->vl.sharindx)
max_sharindx = rule->vl.sharindx;
}
vl_lookup[k].vlanid = vid;
vl_lookup[k].vlanprior = 0;
} /* For critical VLs, the DESTPORTS mask is taken from * the VL Forwarding Table, so no point in putting it * in the VL Lookup Table
*/ if (rule->vl.type == SJA1105_VL_NONCRITICAL)
vl_lookup[k].destports = rule->vl.destports; else
vl_lookup[k].iscritical = true;
vl_lookup[k].flow_cookie = rule->cookie;
k++;
}
}
/* UM10944.pdf chapter 4.2.3 VL Lookup table: * "the entries in the VL Lookup table must be sorted in ascending * order (i.e. the smallest value must be loaded first) according to * the following sort order: MACADDR, VLANID, PORT, VLANPRIOR."
*/ for (i = 0; i < num_virtual_links; i++) { struct sja1105_vl_lookup_entry *a = &vl_lookup[i];
for (j = i + 1; j < num_virtual_links; j++) { struct sja1105_vl_lookup_entry *b = &vl_lookup[j];
if (sja1105_vl_key_lower(b, a)) { struct sja1105_vl_lookup_entry tmp = *a;
if (cycle_time_ext) {
NL_SET_ERR_MSG_MOD(extack, "Cycle time extension not supported"); return -EOPNOTSUPP;
}
div_s64_rem(base_time, sja1105_delta_to_ns(1), &rem); if (rem) {
NL_SET_ERR_MSG_MOD(extack, "Base time must be multiple of 200 ns"); return -ERANGE;
}
div_s64_rem(cycle_time, sja1105_delta_to_ns(1), &rem); if (rem) {
NL_SET_ERR_MSG_MOD(extack, "Cycle time must be multiple of 200 ns"); return -ERANGE;
}
if (!vlan_aware && key->type != SJA1105_KEY_VLAN_UNAWARE_VL) {
NL_SET_ERR_MSG_MOD(extack, "Can only gate based on DMAC"); return -EOPNOTSUPP;
} elseif (vlan_aware && key->type != SJA1105_KEY_VLAN_AWARE_VL) {
NL_SET_ERR_MSG_MOD(extack, "Can only gate based on {DMAC, VID, PCP}"); return -EOPNOTSUPP;
}
if (!rule) {
rule = kzalloc(sizeof(*rule), GFP_KERNEL); if (!rule) return -ENOMEM;
for (i = 0; i < num_entries; i++) {
div_s64_rem(entries[i].interval,
sja1105_delta_to_ns(1), &rem); if (rem) {
NL_SET_ERR_MSG_MOD(extack, "Interval must be multiple of 200 ns");
rc = -ERANGE; goto out;
}
if (!entries[i].interval) {
NL_SET_ERR_MSG_MOD(extack, "Interval cannot be zero");
rc = -ERANGE; goto out;
}
if (ns_to_sja1105_delta(entries[i].interval) >
SJA1105_TAS_MAX_DELTA) {
NL_SET_ERR_MSG_MOD(extack, "Maximum interval is 52 ms");
rc = -ERANGE; goto out;
}
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.