mirror of
https://github.com/logicog/RTLPlayground.git
synced 2026-10-29 17:54:14 +08:00
lacp: keep comments to the frame layout
The comments repeated the documentation, described tests or explained the code to its author. What stays describes the LACPDU structures. The timer constants are decimal, in units of the LACP timer.
This commit is contained in:
1 parent
4a14f50932
commit
73b23808cf
8 files changed
+52
-261
No files matched your search
@@ -79,11 +79,6 @@ bit7 KEEP | 6 VSEL | 5 LEARN_DIS | 4:0 VIDX
|
||||
|
||||
All fields are in network byte order.
|
||||
|
||||
This word has to be written through `HTONS` like every other field of the tag.
|
||||
Writing a constant raw puts the bits in the wrong byte, so `0x0020` reaches the
|
||||
wire as `0x2000`, which is EFID rather than LEARN_DIS. The ASIC then fails to
|
||||
parse the tag and forwards the frame with the `0x8899` header still on it.
|
||||
|
||||
* `EFID_EN`, `EFID`: look the destination up under this filtering ID
|
||||
instead of the port's own
|
||||
* `PRI_EN`, `PRI`: force the given priority on the frame
|
||||
|
||||
@@ -227,52 +227,3 @@ iperf Done.
|
||||
```
|
||||
As you can see, the total throughput was 4.71 GBit/sec which is close to the
|
||||
maximum possible with a single 5GBit link.
|
||||
|
||||
## LACP: how the PDUs reach the CPU
|
||||
|
||||
Slow-protocol frames go to the reserved group `01:80:C2:00:00:02`, and the
|
||||
ASIC's default action for it is *drop*. The engine sets the action to *trap*
|
||||
while it runs. A trap hands the frame to the port named in `EXT_CPU_CTRL`,
|
||||
which names no port out of reset - that is why the trap first looked like no
|
||||
help at all: the receive counters stayed frozen while the partner kept sending,
|
||||
and the frames were counted as ingress discards. `trap_init()` points the
|
||||
register at the CPU port once at startup.
|
||||
|
||||
The *forward* action would reach the CPU as well, since the CPU port is in the
|
||||
forwarding domain, but it leaves the frame in the L2 lookup and so floods it
|
||||
across the ingress VLAN. That leaks LACPDUs to unrelated ports, and the damage
|
||||
is real: a bond's own ports see each other's PDUs and Linux reports an illegal
|
||||
loopback, a second bond on the same switch is poisoned, and the flood escapes
|
||||
through uplinks. Containing it would take a static L2 multicast entry with a
|
||||
CPU-only mask for every PVID in use, since untagged LACPDUs classify into the
|
||||
ingress port's PVID and the forward action is not limited to the LACP ports.
|
||||
|
||||
The trap keys on the address instead, before the VLAN lookup and before the
|
||||
ingress filters, which settles three things at once:
|
||||
|
||||
* Nothing is written per VLAN or per PVID, so delivery no longer depends on
|
||||
which PVIDs the ports happen to carry.
|
||||
* A port that admits tagged frames only still receives: an untagged forwarded
|
||||
LACPDU is dropped by the acceptable-frame-type filter, a trapped one is not.
|
||||
* A port STP holds in blocking still receives, so a group converges without
|
||||
waiting out the forward delay.
|
||||
|
||||
A trapped frame arrives without the VLAN tag the hardware inserts into a
|
||||
forwarded one, so the PDU body sits four bytes earlier; `TRAP_RX_BODY()` gives
|
||||
the offset for both forms.
|
||||
|
||||
`lacp off` puts the action back to *drop*, which acts before the L2 lookup.
|
||||
|
||||
## LACP: what the implementation leaves out
|
||||
|
||||
The four state machines of Clause 43 are present in simplified form. Mux control
|
||||
is coupled rather than independent, one partner system is elected per LAG, and
|
||||
there are no churn detection machines.
|
||||
|
||||
One interoperability rule is worth stating because getting it wrong is silent.
|
||||
The Partner block of an outgoing PDU has to echo the peer's own actor identity
|
||||
verbatim, meaning system and priority, key, port and port priority, and the
|
||||
aggregation flag. A Linux partner's `__record_pdu()` accepts our SYNC bit only
|
||||
when that block mirrors what it sent. Hardcoding the priorities to zero
|
||||
mismatches Linux's default of 0xffff, which clears partner SYNC, moves the state
|
||||
byte from 0x3f to 0x37, and the bond never reaches collecting and distributing.
|
||||
Reference in new issue
Block a user