mirror of
https://github.com/logicog/RTLPlayground.git
synced 2026-10-29 17:54:14 +08:00
A reserved-multicast trap goes to the port named in EXT_CPU_CTRL, which names no port out of reset, so trapped frames were dropped at ingress. trap_init() points it at the CPU port once at startup, and trap_rma_set() changes only the action field of an RMA register. A trapped frame arrives without the VLAN tag a forwarded one gets, so TRAP_RX_BODY() gives the offset of the payload for both forms. STP now traps its address while it runs instead of steering it with a static L2 entry per VLAN, so turning it on no longer walks the VLAN table and a pvid change no longer needs stp off and on. With STP off the flooding entries are restored as before. A trapped BPDU passes the tagged-only ingress filter that drops a forwarded one, so the stp_setup() warning about such ports goes.
102 lines
4.3 KiB
Markdown
102 lines
4.3 KiB
Markdown
# L2
|
|
|
|
The RTL827x provides access and configuration options to an L2 table that
|
|
is used to associate device-MACs with ports on which those devices can
|
|
be reached in the LAN. The code so far configures automatic learning and
|
|
uses a default for aging of the learned addresses.
|
|
|
|
## L2 Tables
|
|
Access to the tables is done using table access registers. The same access
|
|
registers also provide access to the VLAN configuration tables. An idea of how
|
|
the table works can be gained from the [RTL8369 Datasheet](http://realtek.info/pdf/rtl8366_8369_datasheet_1-1.pdf)
|
|
section 8.17 and in particular table 20.
|
|
|
|
The central table register is RTL837X_TBL_CTRL(0x5cac).
|
|
```
|
|
Register RTL837X_TBL_CTRL bytes: EE EE TT CC
|
|
EE: Entry
|
|
TT: Table type
|
|
CC: Command (Bit 0: Execute, Bit 1: Write)
|
|
TT: 04: TBL_L2_UNICAST, 03: TBL_VLAN
|
|
```
|
|
|
|
An entry is retrieved from the tables by setting the data in registers to the
|
|
desired entry filter, then executing a table command by writing to RTL837X_TBL_CTRL
|
|
with execute bit 0 set, table type set and entry identifier (VLAN-Id or hash for L2).
|
|
Data will be fetched from the table and is available once the execute bit has been
|
|
cleared by the ASIC. Data then is in the output data registers
|
|
|
|
```
|
|
#define RTL837x_L2_DATA_OUT_A 0x5ccc
|
|
#define RTL837x_L2_DATA_OUT_B 0x5cd0
|
|
#define RTL837x_L2_DATA_OUT_C 0x5cd4
|
|
|
|
DATA_OUT_A DATA_OUT_B L2_DATA_OUT_C
|
|
M2 M3 M4 M5 fV VV M0 M1 xx xF xx gg
|
|
|
|
M0-M5: 6 bytes of MAC, M0 is MSB
|
|
V: 12 bits of VLAN-ID
|
|
f: bit 5 set: Entry is valid, otherwise stale
|
|
bit 6: bit 0 of port-number
|
|
bit 7: bit 1 of port-number
|
|
g: bit 0: bit 2 of port-number
|
|
bit 1: bit 3 of port-number (MSB)
|
|
bit 2: bit 0 of entry-age
|
|
bit 3: bit 1 of entry-age
|
|
bit 4: bit 2 of entry-age (MSB)
|
|
F: bit 0: entry is static(1) or learned (0)
|
|
```
|
|
The next entry can be now found in RTL837x_TBL_DATA_0 (entry = RTL837x_TBL_DATA_0_bits(0-11) + 1),
|
|
which can be used to get the next entry by writing this value to RTL837X_TBL_CTRL
|
|
and executing again for the given table type. This entry number is probably a hash, for which
|
|
the algorithm is unknown.
|
|
|
|
Deleting the entire L2 table is done by checking and setting 0x53dc to 0x0, then writing
|
|
0x00010000 to register RTL837x_L2_TBL_CTRL and waiting until the bit 16 that was
|
|
set has cleared.
|
|
|
|
|
|
## API support in the code
|
|
The RTLPlayground code provides support for reading the L2 tables from the
|
|
ASIC and flushing the table in order to quickly forget the learned entries.
|
|
```
|
|
> l2
|
|
MAC VLAN type port
|
|
3c:18:a0:7e:11:00 0x0001 learned 5
|
|
1c:2a:a3:23:00:02 0x0001 learned 7
|
|
```
|
|
|
|
## Static multicast entries
|
|
|
|
Slow-protocol frames such as LACPDUs and STP BPDUs have to reach the CPU
|
|
without being flooded to the other ports. No bridge relays these frames:
|
|
their addresses are in the set that 802.1D-2004 clause 7.12.6 forbids a
|
|
bridge to forward, and what travels the network is the information, with
|
|
every bridge regenerating BPDUs of its own on its designated ports. The reserved-multicast *trap* action
|
|
does that: it delivers to the port named in `EXT_CPU_CTRL` (0x6724), which
|
|
`trap_init()` sets to 9, the CPU port, at startup; with the reset value 0xf it
|
|
names no port and the trapped frame is dropped. STP traps its address while it
|
|
runs (see stp.md). Where the action is left at *forward*, the egress can be
|
|
constrained with a static L2 multicast entry instead: the lookup hits the
|
|
entry's own port mask rather than the VLAN flood mask. Verified on a SWTGW218AS
|
|
both ways, with the CPU bit cleared, where delivery stops, and with the CPU bit
|
|
alone, where nothing egresses.
|
|
|
|
`port_l2mc_set()` writes one such entry. The SMI layout is the L2 multicast
|
|
variant of the table entry:
|
|
|
|
```
|
|
DATA_IN_A = MAC bytes 5..2 -> c2 00 00 <mac_last>
|
|
DATA_IN_B = MAC[1..0] | vid<<16 | IVL<<29 | pmask[1:0]<<30
|
|
DATA_IN_C = pmask[9:2]
|
|
```
|
|
|
|
Lookups are IVL, so an entry made for VID 0 is never matched and a caller adds
|
|
one entry per PVID in use. The write goes through the table access register
|
|
with the table selector set to the L2 lookup table, `TBL_L2_UNICAST` in the
|
|
code, a name that despite appearances covers the multicast entries as well.
|
|
The hardware hashes MAC and VID to pick the bucket slot by itself.
|
|
Writing the same MAC and VID again replaces the entry rather than adding a
|
|
second one, so a caller can retarget the mask at will, for instance back to all
|
|
ports to restore flooding.
|