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++;
|
||||
}
|
||||
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]])) {
|
||||
print_string("vlan_ptr "); print_short(vlan_ptr); write_char(':');
|
||||
write_char('>'); print_string_x(&vlan_names[0]); write_char('<'); write_char('\n');
|
||||
}
|
||||
return;
|
||||
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)
|
||||
{
|
||||
@@ -1044,6 +1114,8 @@ void cmd_parser(void) __banked
|
||||
write_char(cmd_history[p]);
|
||||
p = (p + 1) & CMD_HISTORY_MASK;
|
||||
}
|
||||
} else if (cmd_compare(0, "ingress")) {
|
||||
parse_ingress();
|
||||
}
|
||||
else {
|
||||
print_string("Unknown command\n");
|
||||
@@ -1070,7 +1142,6 @@ void cmd_parser(void) __banked
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void clear_command_history(void) __banked
|
||||
{
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
deletes the VLAN
|
||||
|
||||
vlan show
|
||||
Dumps the current ingress vlan settings.
|
||||
|
||||
pvid <port> <VLAN-ID>
|
||||
assigns PVID to a port. ports are numbered as on the casing
|
||||
|
||||
ingress <port> [tagged|untagged|all]
|
||||
Allows ingress only for the named packages at the given port
|
||||
ingress [p]<t|u|a>...
|
||||
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,17 +48,39 @@ 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);
|
||||
else
|
||||
} else {
|
||||
reg_bit_clear(RTL837x_REG_INGRESS, port << 1);
|
||||
if (type & 0x2)
|
||||
}
|
||||
if (type & 0x2) {
|
||||
reg_bit_set(RTL837x_REG_INGRESS, (port << 1) + 1);
|
||||
else
|
||||
} else {
|
||||
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)
|
||||
reg_bit_clear(RTL837X_VLAN_PORT_EGR_TAG, i << 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
|
||||
print_string("\n");
|
||||
@@ -235,6 +258,7 @@ void vlan_setup(void) __banked
|
||||
|
||||
#ifdef DEBUG
|
||||
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 0x4e14: "); print_reg(0x4e14);
|
||||
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!");
|
||||
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_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "rtl837x_regs.h"
|
||||
|
||||
#define STAT_COUNTER_TX_PKTS 46
|
||||
#define STAT_COUNTER_RX_PKTS 47
|
||||
@@ -13,6 +14,19 @@
|
||||
reg_read_m(RTL837X_STAT_GET); \
|
||||
} 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 {
|
||||
uint16_t vlan;
|
||||
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;
|
||||
void vlan_create(void) __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_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_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;
|
||||
@@ -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_disable(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
|
||||
|
||||
+2
-1
@@ -95,6 +95,7 @@ extern __xdata struct dhcp_state dhcp_state;
|
||||
__xdata volatile uint8_t sbuf_ptr;
|
||||
__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];
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user