mirror of
https://github.com/logicog/RTLPlayground.git
synced 2026-08-30 14:52:51 +08:00
Console: Add Ingress type & VLAN show table
Added new `vlan show` command to dump current VLAN settings. Supports printing PVID & ingress filtering per port. Added new `ingress [p]<mode>` command to setup ingress filtering. Added wrappers for enabling/disabling vlan filtering. Currently not configurable, but state in console is read via ASIC registers. Full VLAN dump & web support of new commands will be added later.
This commit is contained in:
+73
-2
@@ -342,16 +342,86 @@ void parse_vlan(void)
|
|||||||
w++;
|
w++;
|
||||||
}
|
}
|
||||||
vlan_create();
|
vlan_create();
|
||||||
|
} else if (cmd_words_b[1] > 0 && cmd_compare(1, "show")) {
|
||||||
|
vlan_dump();
|
||||||
|
} else {
|
||||||
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmd_words_b[2] > 0 && isletter(cmd_buffer[cmd_words_b[2]])) {
|
if (cmd_words_b[2] > 0 && isletter(cmd_buffer[cmd_words_b[2]])) {
|
||||||
print_string("vlan_ptr "); print_short(vlan_ptr); write_char(':');
|
print_string("vlan_ptr "); print_short(vlan_ptr); write_char(':');
|
||||||
write_char('>'); print_string_x(&vlan_names[0]); write_char('<'); write_char('\n');
|
write_char('>'); print_string_x(&vlan_names[0]); write_char('<'); write_char('\n');
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
err:
|
err:
|
||||||
print_string("Error: vlan <vlan-id> [port][t/u]...");
|
print_string("Error: vlan (<vlan-id>|show) [port][t/u]...");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool vlan_ingress_mode_parse(char c, vlan_ingress_mode_t *mode)
|
||||||
|
{
|
||||||
|
switch (c) {
|
||||||
|
case 'u':
|
||||||
|
*mode = VLAN_UNTAGGED;
|
||||||
|
return true;
|
||||||
|
case 't':
|
||||||
|
*mode = VLAN_TAGGED;
|
||||||
|
return true;
|
||||||
|
case 'a':
|
||||||
|
*mode = VLAN_ALL;
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
*mode = VLAN_INVALID;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void parse_ingress(void)
|
||||||
|
{
|
||||||
|
if (cmd_words_b[1] <= 0) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
__xdata uint8_t log_port = 0;
|
||||||
|
__xdata vlan_ingress_mode_t mode = VLAN_INVALID;
|
||||||
|
__xdata uint8_t w = 1;
|
||||||
|
|
||||||
|
if (vlan_ingress_mode_parse(cmd_buffer[cmd_words_b[w]], &mode)) {
|
||||||
|
// Setting mode for all ports at once
|
||||||
|
for (log_port = machine.min_port; log_port <= machine.max_port; log_port++) {
|
||||||
|
if (!port_ingress_filter(log_port, mode)) {
|
||||||
|
print_string("Error setting ingress filter for port "); print_byte(machine.log_to_phys_port[log_port]); write_char('\n');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
print_string("All ports ingress filter set to: ");
|
||||||
|
print_port_ingress_filter_mode(mode); write_char('\n');
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
for(w = 1; cmd_words_b[w] > 0; w++) {
|
||||||
|
if (!isnumber(cmd_buffer[cmd_words_b[w]])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (cmd_buffer[cmd_words_b[w]] - '1' > 9) {
|
||||||
|
print_string("Invalid physical port number: "); write_char(cmd_buffer[cmd_words_b[w]]); write_char('\n');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
log_port = machine.phys_to_log_port[cmd_buffer[cmd_words_b[w]] - '1'];
|
||||||
|
if (!vlan_ingress_mode_parse(cmd_buffer[cmd_words_b[w] + 1], &mode)) {
|
||||||
|
print_string("Invalid ingress mode for port "); write_char(cmd_buffer[cmd_words_b[w]]); print_string(" in ingress command\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (!port_ingress_filter(log_port, mode)) {
|
||||||
|
print_string("Error setting ingress filter for port "); write_char(cmd_buffer[cmd_words_b[w]]); write_char('\n');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
print_string("Port "); write_char(cmd_buffer[cmd_words_b[w]]);
|
||||||
|
print_string(" ingress filter set to: ");
|
||||||
|
print_port_ingress_filter_mode(mode); write_char('\n');
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
err:
|
||||||
|
print_string("Error: ingress [p]<u/t/a>... \n");
|
||||||
|
}
|
||||||
|
|
||||||
void parse_mirror(void)
|
void parse_mirror(void)
|
||||||
{
|
{
|
||||||
@@ -1044,6 +1114,8 @@ void cmd_parser(void) __banked
|
|||||||
write_char(cmd_history[p]);
|
write_char(cmd_history[p]);
|
||||||
p = (p + 1) & CMD_HISTORY_MASK;
|
p = (p + 1) & CMD_HISTORY_MASK;
|
||||||
}
|
}
|
||||||
|
} else if (cmd_compare(0, "ingress")) {
|
||||||
|
parse_ingress();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
print_string("Unknown command\n");
|
print_string("Unknown command\n");
|
||||||
@@ -1070,7 +1142,6 @@ void cmd_parser(void) __banked
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void clear_command_history(void) __banked
|
void clear_command_history(void) __banked
|
||||||
{
|
{
|
||||||
for (cmd_history_ptr = 0; cmd_history_ptr < CMD_HISTORY_SIZE; cmd_history_ptr++)
|
for (cmd_history_ptr = 0; cmd_history_ptr < CMD_HISTORY_SIZE; cmd_history_ptr++)
|
||||||
|
|||||||
+23
-4
@@ -38,10 +38,18 @@ an even port uses bits [11:0]. The base register is
|
|||||||
RTL837x_PVID_BASE_REG (0x4e1c) and the registers go to 0x4e2c so that also
|
RTL837x_PVID_BASE_REG (0x4e1c) and the registers go to 0x4e2c so that also
|
||||||
the CPU-Port may have a PVID.
|
the CPU-Port may have a PVID.
|
||||||
|
|
||||||
Register RTL837x_REG_INGRESS (0x4e10) allows to define the iingress rules of
|
Register RTL837x_REG_INGRESS (0x4e10) allows to define the ingress rules of
|
||||||
a port. 2 bits define a rule and bits 0-19 are being used. A value of 00
|
a port. 2 bits define a rule and bits 0-19 are being used. A value of 00
|
||||||
defines no filtering, 01 (0x01) allows only tagged packets, while 10 (0x02)
|
defines no filtering, 01 (0x01) allows only tagged packets, while 10 (0x02)
|
||||||
allows only untagged packets to enter a port. The default PVID is 1.
|
allows only untagged packets to enter a port.
|
||||||
|
|
||||||
|
Register RTL837X_VLAN_PORT_IGR_FLTR (0x4e18) enables or disables ingres VLAN
|
||||||
|
filtering, each bit corresponds to given port (port0 -> bit0, port9 -> bit9).
|
||||||
|
When enabled, incomming package's vlan tag is checked against VLAN membership
|
||||||
|
on given port. When package contains VLAN not in member list, package is dropped.
|
||||||
|
|
||||||
|
The default PVID on all port is 1, ingress VLAN filtering is enabled and all types of
|
||||||
|
frames are accepted on input on all ports.
|
||||||
|
|
||||||
By default, the ports transmit Ethernet frames with Realtek's proprietary
|
By default, the ports transmit Ethernet frames with Realtek's proprietary
|
||||||
tag format. By setting bit 6 (0x40) of the respective port configuration
|
tag format. By setting bit 6 (0x40) of the respective port configuration
|
||||||
@@ -68,9 +76,20 @@ vlan <VLAN-ID> p[t/u]...
|
|||||||
vlan <VLAN-ID> d
|
vlan <VLAN-ID> d
|
||||||
deletes the VLAN
|
deletes the VLAN
|
||||||
|
|
||||||
|
vlan show
|
||||||
|
Dumps the current ingress vlan settings.
|
||||||
|
|
||||||
pvid <port> <VLAN-ID>
|
pvid <port> <VLAN-ID>
|
||||||
assigns PVID to a port. ports are numbered as on the casing
|
assigns PVID to a port. ports are numbered as on the casing
|
||||||
|
|
||||||
ingress <port> [tagged|untagged|all]
|
ingress [p]<t|u|a>...
|
||||||
Allows ingress only for the named packages at the given port
|
Allows ingress packages on port `p` only when `t`agged, `u`ntagged or `a`ny.
|
||||||
|
Multiple ports can be given at once as in vlan. When `p` is missing, all ports
|
||||||
|
are assigned the same mode. CPU port can not be changed.
|
||||||
|
|
||||||
|
Use `vlan show` to see current configuration.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
`ingress 1t 2a` -> Set port 1 as tagged input only, set port 2 accepting any frames.
|
||||||
|
`ingress a` -> Set all ports to accept both tagged and untagged frames (default behaviour).
|
||||||
```
|
```
|
||||||
|
|||||||
+104
-6
@@ -48,16 +48,38 @@ void port_mirror_del(void) __banked
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void port_ingress_filter(__xdata uint8_t port, __xdata uint8_t type) __banked
|
bool port_ingress_filter(__xdata uint8_t port, __xdata vlan_ingress_mode_t type) __banked
|
||||||
{
|
{
|
||||||
if (type & 0x1)
|
if (port > 9 || type >= VLAN_INVALID) {
|
||||||
|
print_string("Invalid port or ingress filter type\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type & 0x1) {
|
||||||
reg_bit_set(RTL837x_REG_INGRESS, port << 1);
|
reg_bit_set(RTL837x_REG_INGRESS, port << 1);
|
||||||
else
|
} else {
|
||||||
reg_bit_clear(RTL837x_REG_INGRESS, port << 1);
|
reg_bit_clear(RTL837x_REG_INGRESS, port << 1);
|
||||||
if (type & 0x2)
|
}
|
||||||
|
if (type & 0x2) {
|
||||||
reg_bit_set(RTL837x_REG_INGRESS, (port << 1) + 1);
|
reg_bit_set(RTL837x_REG_INGRESS, (port << 1) + 1);
|
||||||
else
|
} else {
|
||||||
reg_bit_clear(RTL837x_REG_INGRESS, (port << 1) + 1);
|
reg_bit_clear(RTL837x_REG_INGRESS, (port << 1) + 1);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
vlan_ingress_mode_t port_ingress_filter_get(__xdata uint8_t port) __banked
|
||||||
|
{
|
||||||
|
reg_read_m(RTL837x_REG_INGRESS);
|
||||||
|
if (port > 9) {
|
||||||
|
return VLAN_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Each port is represented by 2 bits in the ingress register, starting from bit 0 for port 0
|
||||||
|
const uint8_t sfr_index = 3 - (port / 4);
|
||||||
|
const uint8_t shift = (port % 4) << 1;
|
||||||
|
|
||||||
|
return (vlan_ingress_mode_t)((sfr_data[sfr_index] >> shift) & 0x03);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -210,7 +232,8 @@ void vlan_setup(void) __banked
|
|||||||
// EGRESS filtering for port: removal of additional VLAN tag (mode 0x3 for each port)
|
// EGRESS filtering for port: removal of additional VLAN tag (mode 0x3 for each port)
|
||||||
reg_bit_clear(RTL837X_VLAN_PORT_EGR_TAG, i << 1);
|
reg_bit_clear(RTL837X_VLAN_PORT_EGR_TAG, i << 1);
|
||||||
reg_bit_clear(RTL837X_VLAN_PORT_EGR_TAG, (i << 1) + 1);
|
reg_bit_clear(RTL837X_VLAN_PORT_EGR_TAG, (i << 1) + 1);
|
||||||
reg_bit_set(RTL837X_VLAN_PORT_IGR_FLTR, i);
|
// Enable INGRESS filtering for port: discard packets not belonging to member VLAN on that port
|
||||||
|
port_ingress_vlan_filter_set(i, true);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
print_string("\n");
|
print_string("\n");
|
||||||
@@ -235,6 +258,7 @@ void vlan_setup(void) __banked
|
|||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
print_string("\nvlan_setup, REG 0x6738: "); print_reg(0x6738);
|
print_string("\nvlan_setup, REG 0x6738: "); print_reg(0x6738);
|
||||||
|
print_string("\nvlan_setup, REG 0x4e10: "); print_reg(0x4e10);
|
||||||
print_string("\nvlan_setup, REG 0x4e18: "); print_reg(0x4e18);
|
print_string("\nvlan_setup, REG 0x4e18: "); print_reg(0x4e18);
|
||||||
print_string("\nvlan_setup, REG 0x4e14: "); print_reg(0x4e14);
|
print_string("\nvlan_setup, REG 0x4e14: "); print_reg(0x4e14);
|
||||||
print_string("\nvlan_setup, REG 0x4e30: "); print_reg(0x4e30);
|
print_string("\nvlan_setup, REG 0x4e30: "); print_reg(0x4e30);
|
||||||
@@ -636,3 +660,77 @@ void port_lag_hash_set(__xdata uint8_t lag, __xdata uint8_t hash_bits) __banked
|
|||||||
print_string("Link aggregation group must be 0-3!");
|
print_string("Link aggregation group must be 0-3!");
|
||||||
REG_WRITE(RTL837X_TRK_HASH_CTRL_BASE + (lag << 2), 0, 0, 0, hash_bits);
|
REG_WRITE(RTL837X_TRK_HASH_CTRL_BASE + (lag << 2), 0, 0, 0, hash_bits);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void print_port_ingress_filter_mode(vlan_ingress_mode_t mode) __banked
|
||||||
|
{
|
||||||
|
switch (mode) {
|
||||||
|
case VLAN_UNTAGGED:
|
||||||
|
print_string("Untag.");
|
||||||
|
break;
|
||||||
|
case VLAN_TAGGED:
|
||||||
|
print_string("Tagged");
|
||||||
|
break;
|
||||||
|
case VLAN_ALL:
|
||||||
|
print_string("Any");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
print_string("!!err!!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_phys_port(uint8_t port) __banked
|
||||||
|
{
|
||||||
|
if (port >= machine.min_port && port <= machine.max_port)
|
||||||
|
write_char(machine.log_to_phys_port[port] + '0');
|
||||||
|
else if (port == 9)
|
||||||
|
write_char('9');
|
||||||
|
else
|
||||||
|
write_char('?');
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_vlan_ingress_port(uint8_t log_port) __banked
|
||||||
|
{
|
||||||
|
print_phys_port(log_port);write_char('\t');
|
||||||
|
print_short(port_pvid_get(log_port));write_char('\t');
|
||||||
|
print_port_ingress_filter_mode(port_ingress_filter_get(log_port));write_char('\t');
|
||||||
|
port_ingress_vlan_filter_get(log_port) ? print_string("Enabled") : print_string("Disabled");
|
||||||
|
write_char('\n');
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Dumps the VLAN ingress configuration
|
||||||
|
*/
|
||||||
|
void vlan_dump(void) __banked
|
||||||
|
{
|
||||||
|
print_string("Ingress VLAN configuration:\n");
|
||||||
|
print_string("Port\tPVID\tType\tFiltering\n");
|
||||||
|
for (uint8_t port = machine.min_port; port <= machine.max_port; port++) {
|
||||||
|
print_vlan_ingress_port(port);
|
||||||
|
}
|
||||||
|
print_vlan_ingress_port(9);
|
||||||
|
|
||||||
|
write_char('\n');
|
||||||
|
print_string("Type - Which frame types are allowed: untagged, tagged or any\n");
|
||||||
|
print_string("Filtering - Whether packets not belonging to member VLANs on that port are dropped\n");
|
||||||
|
print_string("PVID - Assumed VLAN for untagged packets\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Set the ingress VLAN filtering */
|
||||||
|
bool port_ingress_vlan_filter_set(__xdata uint8_t port, __xdata bool enabled) __banked
|
||||||
|
{
|
||||||
|
if (port < machine.min_port || port > machine.max_port && port != 9) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
reg_bit_set(RTL837X_VLAN_PORT_IGR_FLTR, port);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get the ingress VLAN filtering status */
|
||||||
|
bool port_ingress_vlan_filter_get(__xdata uint8_t port) __banked
|
||||||
|
{
|
||||||
|
if (port < machine.min_port || port > machine.max_port && port != 9) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return reg_bit_test(RTL837X_VLAN_PORT_IGR_FLTR, port);
|
||||||
|
}
|
||||||
|
|||||||
+19
-1
@@ -2,6 +2,7 @@
|
|||||||
#define _RTL837X_PORT_H_
|
#define _RTL837X_PORT_H_
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include "rtl837x_regs.h"
|
||||||
|
|
||||||
#define STAT_COUNTER_TX_PKTS 46
|
#define STAT_COUNTER_TX_PKTS 46
|
||||||
#define STAT_COUNTER_RX_PKTS 47
|
#define STAT_COUNTER_RX_PKTS 47
|
||||||
@@ -13,6 +14,19 @@
|
|||||||
reg_read_m(RTL837X_STAT_GET); \
|
reg_read_m(RTL837X_STAT_GET); \
|
||||||
} while (sfr_data[3] & 0x1);
|
} while (sfr_data[3] & 0x1);
|
||||||
|
|
||||||
|
// Possible values for ingress filter type
|
||||||
|
typedef enum {
|
||||||
|
VLAN_ALL = INGR_ALLOW_ALL,
|
||||||
|
VLAN_TAGGED = INGR_ALLOW_TAGGED,
|
||||||
|
VLAN_UNTAGGED = INGR_ALLOW_UNTAGGED,
|
||||||
|
VLAN_INVALID = 3
|
||||||
|
} vlan_ingress_mode_e;
|
||||||
|
|
||||||
|
// Since we lack a way to force enum to be 1 byte,
|
||||||
|
// This is a typedef for the VLAN ingress filter type
|
||||||
|
// which holds vlan_ingress_mode_e values
|
||||||
|
typedef uint8_t vlan_ingress_mode_t;
|
||||||
|
|
||||||
struct vlan_settings {
|
struct vlan_settings {
|
||||||
uint16_t vlan;
|
uint16_t vlan;
|
||||||
uint16_t members;
|
uint16_t members;
|
||||||
@@ -31,9 +45,10 @@ void port_pvid_set(uint8_t port, __xdata uint16_t pvid) __banked;
|
|||||||
uint16_t port_pvid_get(uint8_t port) __banked;
|
uint16_t port_pvid_get(uint8_t port) __banked;
|
||||||
void vlan_create(void) __banked;
|
void vlan_create(void) __banked;
|
||||||
void vlan_delete(uint16_t vlan) __banked;
|
void vlan_delete(uint16_t vlan) __banked;
|
||||||
|
void vlan_dump(void) __banked;
|
||||||
void port_mirror_set(register uint8_t port, __xdata uint16_t rx_pmask, __xdata uint16_t tx_pmask) __banked;
|
void port_mirror_set(register uint8_t port, __xdata uint16_t rx_pmask, __xdata uint16_t tx_pmask) __banked;
|
||||||
void port_mirror_del(void) __banked;
|
void port_mirror_del(void) __banked;
|
||||||
void port_ingress_filter(__xdata uint8_t port, __xdata uint8_t type) __banked;
|
bool port_ingress_filter(__xdata uint8_t port, __xdata vlan_ingress_mode_t type) __banked;
|
||||||
void port_l2_setup(void) __banked;
|
void port_l2_setup(void) __banked;
|
||||||
void port_lag_members_set(__xdata uint8_t lag, __xdata uint16_t members) __banked;
|
void port_lag_members_set(__xdata uint8_t lag, __xdata uint16_t members) __banked;
|
||||||
void port_lag_hash_set(__xdata uint8_t lag, __xdata uint8_t hash) __banked;
|
void port_lag_hash_set(__xdata uint8_t lag, __xdata uint8_t hash) __banked;
|
||||||
@@ -43,4 +58,7 @@ void port_eee_status_all(void) __banked;
|
|||||||
void port_eee_enable(__xdata uint8_t port, __xdata uint8_t speed) __banked;
|
void port_eee_enable(__xdata uint8_t port, __xdata uint8_t speed) __banked;
|
||||||
void port_eee_disable(uint8_t port) __banked;
|
void port_eee_disable(uint8_t port) __banked;
|
||||||
void port_eee_status(uint8_t port) __banked;
|
void port_eee_status(uint8_t port) __banked;
|
||||||
|
void print_port_ingress_filter_mode(vlan_ingress_mode_t mode) __banked;
|
||||||
|
bool port_ingress_vlan_filter_set(__xdata uint8_t port, __xdata bool enabled) __banked;
|
||||||
|
bool port_ingress_vlan_filter_get(__xdata uint8_t port) __banked;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+2
-1
@@ -95,6 +95,7 @@ extern __xdata struct dhcp_state dhcp_state;
|
|||||||
__xdata volatile uint8_t sbuf_ptr;
|
__xdata volatile uint8_t sbuf_ptr;
|
||||||
__xdata uint8_t sbuf[SBUF_SIZE];
|
__xdata uint8_t sbuf[SBUF_SIZE];
|
||||||
|
|
||||||
|
// Registry data in sfr is in *big endian* order, so sfr_data[0] is the MSB and sfr_data[3] the LSB
|
||||||
__xdata uint8_t sfr_data[4];
|
__xdata uint8_t sfr_data[4];
|
||||||
|
|
||||||
extern __xdata uint8_t gpio_last_value[8];
|
extern __xdata uint8_t gpio_last_value[8];
|
||||||
@@ -462,7 +463,7 @@ void reg_bit_clear(uint16_t reg_addr, char bit)
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This sets a bit in the 32bit wide switch register reg_addr
|
* This tests a bit in the 32bit wide switch register reg_addr
|
||||||
*/
|
*/
|
||||||
uint8_t reg_bit_test(uint16_t reg_addr, char bit)
|
uint8_t reg_bit_test(uint16_t reg_addr, char bit)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user