17 Commits
Author SHA1 Message Date
d00f 01709431dc Merge pull request #446 from DrDoof/feat/dns
dns: resolve host names
2026-10-10 23:52:45 +02:00
d00f de0d413c0c dns: show the last lookup with the servers
The answer to a lookup arrives after the command has returned, so the
console of the web interface never shows it. Plain "dns" now prints the
name and the address, or whether it is still pending or failed.
2026-10-10 17:54:55 +02:00
René van Dorst 4e00f5a592 Merge pull request #398 from mintsoft/lldpd
LLDP implementation
2026-10-10 09:17:00 +00:00
Rob Emery eff3f42ae1 Rewriting sim implementation to be data driven
The value for enabled should be an int, not a string
2026-10-10 09:51:50 +01:00
Rob Emery dda873a633 Moving lldp cmd parsing to be above the is_sfp check to take precedence
Needed to increase buffer size for this to send app.js

The logical port status is what is returned in the array, for
non-sequential systems we need to map through physToLog rather
than just subtracting 1

physToLog is 1 based! not 0; also fixing up typecasts

Reimplementing using an array of objects to represent ports.
The previous approach of a bitmask of logical ports, was just too
simple on devices such as the SWGT024_V2_0_MANAGED which has
gaps in the port assignments.
2026-10-10 09:51:33 +01:00
Rob Emery 9b2bd7f1b8 The tick rate has been changed now so we'll have to approximate
timing with ticks

Fixing up the log_to_phys_port assignment

2000 is about every 10 seconds, so scaling up to once every 30ish

Removing the attempt to block lldp frames,
This does not work however the hard work has been done for us in
the #514 so we can borrow that work later on
2026-10-10 09:50:38 +01:00
Rob Emery 2dfe531fe0 Fixing missing parts to make the tests pass
boot_to_html outputs 1 and 0 not true and false, making the sim match
the real implementation.
lldp.json has a hanging , in the array; so overwriting it
2026-10-10 09:50:27 +01:00
Rob Emery 72c2625121 Icon from https://github.com/logicog/RTLPlayground/pull/429#issuecomment-5687458129 2026-10-10 09:50:27 +01:00
Rob Emery 58fd1a3ccc Adding lldp.json to the simulator
Moving the global on/off onto the LLDP page

Building a table of LLDP status from the S ports. Later on, if
we wish to implement an lldp receiver we can display the remote
details here

Adding support to the cmd parser for the lldp commands
2026-10-10 09:50:01 +01:00
Rob Emery 4f1a2f04d8 Allowing commands like port 1 lldp block and port 2 lldp permit
so we are able to enable/disable lldp transmission on a specific
port.
2026-10-10 09:50:01 +01:00
Rob Emery cedc795b82 Adding UI options to enable/disable LLDP 2026-10-10 09:50:01 +01:00
Rob Emery ccf541a06b Refactor and golfing from https://github.com/logicog/RTLPlayground/pull/398#issuecomment-5654087271
I've tweaked it a little to keep the port_position in as I think
that is clearer than a random "12" in the loop later on
2026-10-10 09:50:01 +01:00
Rob Emery d5124df89e avoid SRAM 2026-10-10 09:50:01 +01:00
Rob Emery 3eacc9c8a5 LLPD_MAC_ADDR_LEN -> MAC_ADDR_LEN and memcopy instead of manually setting bytes 2026-10-10 09:50:01 +01:00
Rob Emery 735672ccf1 Moving to Bank3 2026-10-10 09:49:52 +01:00
Rob Emery 1ebee4d6e9 Implementing basic LLDP server, should send port_id message
to each port once every 30 seconds.
* Additionally fixes the on-ward passing of LLDP frames through
the switch

The ports on the case are marked 1-8 so this should reflect that
rather than being 0-based

We can send the hostname as well, this can be dynamically allocated

Let's send the model as the system description as well
2026-10-10 09:49:24 +01:00
DrDoof 67b8c718fb dns: resolve host names
A small resolver for IPv4 address records, so that clients such as NTP can
be given a host name: "dns server <ip> [<ip>]", "dns lookup <name>" and
"dns". Without a configured server it uses the one DHCP handed out. A query
goes to the servers in turn every two seconds and gives up after six tries;
answers with compressed names and CNAME records ahead of the address are
understood. A name that already is a dotted address is taken without a
query.

The resolver sits in BANK3, the command line in BANK2 next to the helpers it
uses. The System page shows and sets the servers.
2026-09-29 22:40:43 +02:00
22 changed files with 729 additions and 8 deletions

No files matched your search

+3
View File
@@ -69,6 +69,8 @@ SRCS = \
rtlplayground.c \ rtlplayground.c \
boot.c \ boot.c \
sfp.c \ sfp.c \
dns.c \
dns_cli.c \
syslog.c \ syslog.c \
udp_apps.c udp_apps.c
@@ -84,6 +86,7 @@ SRCS += \
rtl837x_pins.c\ rtl837x_pins.c\
rtl837x_port.c \ rtl837x_port.c \
rtl837x_stp.c \ rtl837x_stp.c \
rtl837x_lldp.c \
rtl837x_storm.c rtl837x_storm.c
SRCS += \ SRCS += \
httpd/httpd.c \ httpd/httpd.c \
+22
View File
@@ -16,10 +16,12 @@
#include "rtl837x_stp.h" #include "rtl837x_stp.h"
#include "rtl837x_igmp.h" #include "rtl837x_igmp.h"
#include "rtl837x_bandwidth.h" #include "rtl837x_bandwidth.h"
#include "rtl837x_lldp.h"
#include "rtl837x_storm.h" #include "rtl837x_storm.h"
#include "sfp.h" #include "sfp.h"
#include "dhcp.h" #include "dhcp.h"
#include "syslog.h" #include "syslog.h"
#include "dns.h"
#include "uip/uip.h" #include "uip/uip.h"
#include "version.h" #include "version.h"
@@ -33,6 +35,7 @@
extern __code const struct machine machine; extern __code const struct machine machine;
extern __xdata bool stp_enabled; extern __xdata bool stp_enabled;
extern __code const uint8_t log_to_phys_port[9]; extern __code const uint8_t log_to_phys_port[9];
extern __xdata bool lldp_enabled;
extern volatile __xdata uint32_t ticks; extern volatile __xdata uint32_t ticks;
extern volatile __xdata uint8_t sfr_data[4]; extern volatile __xdata uint8_t sfr_data[4];
@@ -880,6 +883,7 @@ void parse_port(void)
cmd_error("\nUsage:" \ cmd_error("\nUsage:" \
"\nport <port> [show|on|off]" \ "\nport <port> [show|on|off]" \
"\nport <port> [10m|100m|1g|2g5|duplex] [half|full]" \ "\nport <port> [10m|100m|1g|2g5|duplex] [half|full]" \
"\nport <port> lldp [block|permit]" \
"\nport <port> name [custom port name]\n"); "\nport <port> name [custom port name]\n");
return; return;
} }
@@ -912,6 +916,14 @@ void parse_port(void)
print_string("\nName set to: \""); print_string("\nName set to: \"");
print_string_x(port_names[phy_settings.port]); print_string_x(port_names[phy_settings.port]);
print_string("\"\n"); print_string("\"\n");
} else if (cmd_compare(2, "lldp")) {
if (cmd_compare(3, "block")){
lldp_logical_port_status &= ~((uint16_t)1 << phy_settings.port);
} else if (cmd_compare(3, "permit")) {
lldp_logical_port_status |= (uint16_t)1 << phy_settings.port;
} else {
print_string ("Unknown port <port> lldp [block|permit] command\n");
}
} else if (machine.is_sfp[phy_settings.port]) { } else if (machine.is_sfp[phy_settings.port]) {
print_string(" is SFP no PHY information available.\n"); print_string(" is SFP no PHY information available.\n");
} else if (cmd_compare(2, "10m")) { } else if (cmd_compare(2, "10m")) {
@@ -1855,6 +1867,8 @@ void cmd_parser(void) __banked
parse_mtu(); parse_mtu();
} else if (cmd_compare(0, "syslog")) { } else if (cmd_compare(0, "syslog")) {
parse_syslog(); parse_syslog();
} else if (cmd_compare(0, "dns")) {
dns_parse();
} else if (cmd_compare(0, "ip")) { } else if (cmd_compare(0, "ip")) {
if (cmd_compare(1, "dhcp")) { if (cmd_compare(1, "dhcp")) {
dhcp_start(); dhcp_start();
@@ -2027,6 +2041,14 @@ void cmd_parser(void) __banked
parse_ingress(); parse_ingress();
} else if (cmd_compare(0, "session")) { } else if (cmd_compare(0, "session")) {
parse_session(); parse_session();
} else if (cmd_compare(0, "lldp")) {
if (cmd_compare(1, "on")) {
print_string("LLDP enabled\n");
lldp_enabled = 1;
} else {
print_string("LLDP disabled\n");
lldp_enabled = 0;
}
} }
else { else {
cmd_error("Unknown command\n"); cmd_error("Unknown command\n");
+1
View File
@@ -20,6 +20,7 @@ extern __xdata uint8_t err_status;
#define HEALTH_PH_STP 4 #define HEALTH_PH_STP 4
#define HEALTH_PH_CMD 5 #define HEALTH_PH_CMD 5
#define HEALTH_PHASES 6 #define HEALTH_PHASES 6
#define HEALTH_LLDP 7
extern __xdata uint16_t health_rx_frames; extern __xdata uint16_t health_rx_frames;
#define health_rx_frame() health_rx_frames++ #define health_rx_frame() health_rx_frames++
+238
View File
@@ -0,0 +1,238 @@
/*
* DNS resolver for the RTL837x platform
* This code is in the Public Domain
*/
#include <stdint.h>
#include "rtl837x_common.h"
#include "cmd_parser.h"
#include "uip/uip.h"
#include "dhcp.h"
#include "dns.h"
#pragma codeseg BANK3
#pragma constseg BANK3
#define DNS_PORT 53
#define DNS_TRIES 6
#define DNS_TIMEOUT (2 * SYS_TICK_HZ)
extern __xdata struct dhcp_state dhcp_state;
extern volatile __xdata uint32_t ticks;
__xdata struct dns_state dns_state;
__xdata uip_ipaddr_t dns_ip;
uint8_t * __xdata dns_cand[3];
static uint8_t dns_used(__xdata uint8_t *a) __reentrant
{
return a[0] | a[1] | a[2] | a[3];
}
static uint8_t dns_name_is_ip(void) __reentrant
{
__xdata char *s = dns_state.name;
uint8_t i, n;
uint16_t v;
for (i = 0; i < 4; i++) {
v = 0;
n = 0;
while (*s >= '0' && *s <= '9') {
v = v * 10 + (*s++ - '0');
if (++n > 3 || v > 255)
return 0;
}
if (!n)
return 0;
dns_state.addr[i] = v;
if (i < 3 && *s++ != '.')
return 0;
}
return !*s;
}
static void dns_next(void) __reentrant
{
uint8_t k = 0;
if (dns_state.conn) {
uip_udp_remove(dns_state.conn);
dns_state.conn = 0;
}
if (dns_used(dns_state.server[0]))
dns_cand[k++] = dns_state.server[0];
if (dns_used(dns_state.server[1]))
dns_cand[k++] = dns_state.server[1];
if (dns_used(dhcp_state.dns))
dns_cand[k++] = dhcp_state.dns;
if (!k || dns_state.tries >= DNS_TRIES) {
dns_state.status = DNS_FAILED;
if (dns_state.verbose)
print_string(k ? "DNS: no answer\n" : "DNS: no server\n");
return;
}
k = dns_state.tries % k;
uip_ipaddr(dns_ip, dns_cand[k][0], dns_cand[k][1], dns_cand[k][2], dns_cand[k][3]);
dns_state.conn = uip_udp_new(&dns_ip, HTONS(DNS_PORT));
if (!dns_state.conn) {
dns_state.status = DNS_FAILED;
print_string("DNS: no free UDP connection\n");
return;
}
dns_state.send = 1;
}
static void dns_query(void) __reentrant
{
__xdata uint8_t *p = (__xdata uint8_t *)uip_appdata;
__xdata char *n = dns_state.name;
__xdata uint8_t *label;
uint16_t len = 12;
dns_state.id++;
p[0] = dns_state.id >> 8;
p[1] = dns_state.id;
p[2] = 0x01;
p[3] = 0x00;
p[4] = 0;
p[5] = 1;
p[6] = p[7] = p[8] = p[9] = p[10] = p[11] = 0;
while (*n) {
label = p + len++;
*label = 0;
while (*n && *n != '.') {
p[len++] = *n++;
(*label)++;
}
if (*n)
n++;
}
p[len++] = 0;
p[len++] = 0;
p[len++] = 1;
p[len++] = 0;
p[len++] = 1;
uip_udp_send(len);
}
static uint16_t dns_skip_name(__xdata uint8_t *p, uint16_t i, uint16_t len) __reentrant
{
while (i < len) {
if (!p[i])
return i + 1;
if ((p[i] & 0xc0) == 0xc0)
return i + 2;
i += p[i] + 1;
}
return len;
}
static void dns_answer(void) __reentrant
{
__xdata uint8_t *p = (__xdata uint8_t *)uip_appdata;
uint16_t len = uip_datalen();
uint16_t i, an;
if (dns_state.status != DNS_PENDING || len < 12 || !(p[2] & 0x80)
|| p[0] != (uint8_t)(dns_state.id >> 8) || p[1] != (uint8_t)dns_state.id)
return;
an = ((uint16_t)p[6] << 8) | p[7];
i = dns_skip_name(p, 12, len) + 4;
while (!(p[3] & 0x0f) && an-- && i + 10 <= len) {
i = dns_skip_name(p, i, len);
if (i + 10 > len)
break;
if (!p[i] && p[i + 1] == 1 && !p[i + 8] && p[i + 9] == 4 && i + 14 <= len) {
memcpy(dns_state.addr, p + i + 10, 4);
dns_state.status = DNS_DONE;
uip_udp_remove(dns_state.conn);
dns_state.conn = 0;
if (dns_state.verbose) {
print_string("DNS: ");
print_string_x(dns_state.name);
print_string(" is ");
print_ip(dns_state.addr);
write_char('\n');
}
return;
}
i += 10 + (((uint16_t)p[i + 8] << 8) | p[i + 9]);
}
dns_state.tries = DNS_TRIES;
dns_next();
}
void dns_init(void) __banked
{
memset(dns_state.server, 0, sizeof(dns_state.server));
dns_state.name[0] = 0;
dns_state.status = DNS_IDLE;
dns_state.conn = 0;
}
void dns_lookup(void) __banked
{
if (dns_name_is_ip()) {
dns_state.status = DNS_DONE;
return;
}
dns_state.tries = 0;
dns_state.status = DNS_PENDING;
dns_next();
}
void dns_show(void) __banked
{
print_string("DNS servers ");
print_ip(dns_state.server[0]);
write_char(' ');
print_ip(dns_state.server[1]);
print_string(", from DHCP ");
print_ip(dhcp_state.dns);
write_char('\n');
if (!dns_state.name[0])
return;
print_string("Last lookup ");
print_string_x(dns_state.name);
print_string(": ");
if (dns_state.status == DNS_DONE)
print_ip(dns_state.addr);
else if (dns_state.status == DNS_PENDING)
print_string("pending");
else
print_string("failed");
write_char('\n');
}
void dns_callback(uint16_t lport) __banked __reentrant
{
if (!dns_state.conn || lport != dns_state.conn->lport)
return;
if (uip_newdata()) {
dns_answer();
return;
}
if (dns_state.status != DNS_PENDING)
return;
if (dns_state.send) {
dns_state.send = 0;
dns_state.sent = ticks;
dns_query();
return;
}
if (ticks - dns_state.sent >= DNS_TIMEOUT) {
dns_state.tries++;
dns_next();
}
}
+36
View File
@@ -0,0 +1,36 @@
#ifndef _DNS_H_
#define _DNS_H_
#include <stdint.h>
#define DNS_NAME_LEN 48
#define DNS_IDLE 0
#define DNS_PENDING 1
#define DNS_DONE 2
#define DNS_FAILED 3
struct uip_udp_conn;
struct dns_state {
uint8_t server[2][4]; /* configured servers, 0.0.0.0 = unused */
char name[DNS_NAME_LEN]; /* name of the current or last lookup */
uint8_t addr[4]; /* address found by the last lookup */
uint8_t status; /* DNS_* */
uint8_t verbose; /* print the result of the lookup */
uint8_t tries; /* queries sent for the current lookup */
uint8_t send; /* a query is due on the connection */
uint16_t id;
uint32_t sent; /* ticks when the last query went out */
struct uip_udp_conn *conn;
};
extern __xdata struct dns_state dns_state;
void dns_init(void) __banked;
void dns_lookup(void) __banked;
void dns_show(void) __banked;
void dns_callback(uint16_t lport) __banked __reentrant;
void dns_parse(void) __banked __reentrant;
#endif
+63
View File
@@ -0,0 +1,63 @@
/*
* Command line interface of the DNS resolver for the RTL837x platform
* This code is in the Public Domain
*/
#include <stdint.h>
#include "rtl837x_common.h"
#include "cmd_parser.h"
#include "dns.h"
#pragma codeseg BANK2
#pragma constseg BANK2
extern __xdata uint8_t cmd_buffer[CMD_BUF_SIZE];
extern __xdata uint8_t cmd_words_len;
extern __xdata uint8_t cmd_words_b[15];
extern __xdata uint8_t ip[4];
uint8_t cmd_compare(uint8_t start, __code const uint8_t * cmd);
uint8_t parse_ip(uint8_t idx);
void dns_parse(void) __banked __reentrant
{
__xdata uint8_t *s;
uint8_t n;
if (cmd_words_len < 2) {
dns_show();
return;
}
if (cmd_compare(1, "server") && cmd_words_len >= 3 && parse_ip(cmd_words_b[2])) {
memcpy(dns_state.server[0], ip, 4);
memset(dns_state.server[1], 0, 4);
if (cmd_words_len >= 4) {
if (!parse_ip(cmd_words_b[3]))
goto err;
memcpy(dns_state.server[1], ip, 4);
}
return;
}
if (cmd_compare(1, "lookup") && cmd_words_len >= 3) {
if (dns_state.status == DNS_PENDING) {
print_string("DNS: a lookup is already running\n");
return;
}
s = &cmd_buffer[cmd_words_b[2]];
for (n = 0; s[n] && s[n] != ' '; n++) {
if (n == DNS_NAME_LEN - 1)
goto err;
dns_state.name[n] = s[n];
}
dns_state.name[n] = 0;
dns_state.verbose = 1;
dns_lookup();
if (dns_state.status == DNS_DONE) {
print_ip(dns_state.addr);
write_char('\n');
}
return;
}
err:
print_string("Error: dns [server <ip> [<ip>]|lookup <name>]\n");
}
+23
View File
@@ -0,0 +1,23 @@
# DNS
The switch can resolve host names to IPv4 addresses, for the NTP client and
for anything else that is given a name instead of an address.
```
dns server <ip> [<ip>] # one or two servers, 0.0.0.0 removes them
dns lookup <name> # resolve a name and print the address
dns # show the servers and the last lookup
```
The answer to a lookup arrives after the command has returned, so it is
printed on the serial console and in the syslog. In the console of the web
interface, run `dns` afterwards to see it.
Without a configured server the resolver uses the one handed out by DHCP.
Only address records are looked up; a query goes to the servers in turn,
every two seconds, and gives up after six tries. A name that already is a
dotted address is taken as it is, without a query.
The DNS servers are set in the Network card of the System page as well.
Settings made there or on the console are kept only once the configuration is
saved.
+47 -5
View File
@@ -3,7 +3,7 @@ var LANG={
en:{ en:{
nav_dash:"Dashboard",nav_ports:"Ports",nav_stp:"Spanning tree",nav_stats:"Statistics", nav_dash:"Dashboard",nav_ports:"Ports",nav_stp:"Spanning tree",nav_stats:"Statistics",
nav_vlan:"VLANs",nav_l2:"MAC table",nav_mirror:"Mirroring",nav_isolate:"Isolation",nav_lag:"LAG",nav_eee:"EEE", nav_vlan:"VLANs",nav_l2:"MAC table",nav_mirror:"Mirroring",nav_isolate:"Isolation",nav_lag:"LAG",nav_eee:"EEE",
nav_bw:"Bandwidth",nav_system:"System",nav_fw:"Firmware", nav_bw:"Bandwidth",nav_system:"System",nav_fw:"Firmware",nav_lldp:"LLDP",
hdr_dirty:"unsaved changes",hdr_dirty_t:"Running config differs from startup config", hdr_dirty:"unsaved changes",hdr_dirty_t:"Running config differs from startup config",
hdr_save:"Save to flash",hdr_save_t:"Persist running configuration to flash", hdr_save:"Save to flash",hdr_save_t:"Persist running configuration to flash",
th_auto:"System",th_auto_sel:"System (Selenized)",sy_display:"Display",sy_theme:"Theme",sy_display_note:"Stored in this browser only.",th_light:"Light",th_dark:"Dark", th_auto:"System",th_auto_sel:"System (Selenized)",sy_display:"Display",sy_theme:"Theme",sy_display_note:"Stored in this browser only.",th_light:"Light",th_dark:"Dark",
@@ -40,6 +40,7 @@ stp_en_q:"Enable spanning tree?",
stp_en_d:"Ports start blocked and take up to twice the forward delay to reach forwarding; edge ports recover immediately.", stp_en_d:"Ports start blocked and take up to twice the forward delay to reach forwarding; edge ports recover immediately.",
stp_dis_q:"Disable spanning tree?",stp_dis_d:"All ports go straight to forwarding; loop protection is lost.", stp_dis_q:"Disable spanning tree?",stp_dis_d:"All ports go straight to forwarding; loop protection is lost.",
stp_cost_err:"Path cost must be 0-200000000", stp_cost_err:"Path cost must be 0-200000000",
lldp_enabled: "LLDP Enabled",lldp_title:"Service Status",lldp_portname:"Name",lldp_enable:"Send Frames",
st_title:"Port statistics",st_h:"totals since boot",st_txg:"TX good",st_txb:"TX bad",st_rxg:"RX good", st_title:"Port statistics",st_h:"totals since boot",st_txg:"TX good",st_txb:"TX bad",st_rxg:"RX good",
st_rxb:"RX bad",st_details:"Details",st_counters:"MIB counters",st_nonzero:"non-zero only", st_rxb:"RX bad",st_details:"Details",st_counters:"MIB counters",st_nonzero:"non-zero only",
st_autoref:"auto-refresh",st_counter:"Counter",st_value:"Value",st_fail:"failed to load counters", st_autoref:"auto-refresh",st_counter:"Counter",st_value:"Value",st_fail:"failed to load counters",
@@ -89,7 +90,7 @@ sy_ip_err:"Invalid IP / netmask / gateway",sy_host_err:"Hostname: 1-23 printable
sy_net_q:"Apply network settings?",sy_net_d:"The management IP changes to {ip}: this page will need to be reopened there.", sy_net_q:"Apply network settings?",sy_net_d:"The management IP changes to {ip}: this page will need to be reopened there.",
sy_ip_changed:"IP changed, reconnect at http://{ip}/",sy_dhcp_q:"Switch to DHCP?", sy_ip_changed:"IP changed, reconnect at http://{ip}/",sy_dhcp_q:"Switch to DHCP?",
sy_dhcp_d:"The switch requests an address via DHCP. You must find its new IP to reconnect.", sy_dhcp_d:"The switch requests an address via DHCP. You must find its new IP to reconnect.",
sy_sysip_err:"Invalid syslog server IP",sy_sysport_err:"Syslog port must be 1-65535", sy_sysip_err:"Invalid syslog server IP",sy_dns1:"DNS server",sy_dns2:"Second DNS",sy_dns_err:"Invalid DNS server IP",sy_dns_dhcp:"from DHCP: {ip}",sy_sysport_err:"Syslog port must be 1-65535",
sy_pw_len:"Password: 1-20 characters",sy_pw_space:"Password cannot contain spaces",sy_pw_match:"Passwords do not match", sy_pw_len:"Password: 1-20 characters",sy_pw_space:"Password cannot contain spaces",sy_pw_match:"Passwords do not match",
sy_pw_q:"Change admin password?",sy_pw_d:"Takes effect immediately for new logins. Save to flash to persist.", sy_pw_q:"Change admin password?",sy_pw_d:"Takes effect immediately for new logins. Save to flash to persist.",
sy_reboot_q:"Reboot the switch?",sy_reboot_d:"There are UNSAVED changes and they will be lost. Save to flash first if you want to keep them.", sy_reboot_q:"Reboot the switch?",sy_reboot_d:"There are UNSAVED changes and they will be lost. Save to flash first if you want to keep them.",
@@ -781,6 +782,7 @@ var CONF_CMDS=[
/^gw\s+(\d{1,3}\.){3}\d{1,3}$/,/^netmask\s+(\d{1,3}\.){3}\d{1,3}$/, /^gw\s+(\d{1,3}\.){3}\d{1,3}$/,/^netmask\s+(\d{1,3}\.){3}\d{1,3}$/,
/^syslog\s+(on|off)$/,/^syslog\s+ip\s+(\d{1,3}\.){3}\d{1,3}$/,/^syslog\s+port\s+\d{1,5}$/, /^syslog\s+(on|off)$/,/^syslog\s+ip\s+(\d{1,3}\.){3}\d{1,3}$/,/^syslog\s+port\s+\d{1,5}$/,
/^session\s+\d{1,5}$/, /^session\s+\d{1,5}$/,
/^dns\s+server\s+(\d{1,3}\.){3}\d{1,3}(\s+(\d{1,3}\.){3}\d{1,3})?$/,
/^passwd\s+\S+$/,/^hostname\s+\S{1,23}$/, /^passwd\s+\S+$/,/^hostname\s+\S{1,23}$/,
/^vlan\s+\d{1,4}\s+d$/,/^vlan\s+\d{1,4}\s+mgmt$/, /^vlan\s+\d{1,4}\s+d$/,/^vlan\s+\d{1,4}\s+mgmt$/,
/^vlan\s+\d{1,4}(\s+[a-zA-Z]\w*)?(\s+\d{1,2}t?)+$/, /^vlan\s+\d{1,4}(\s+[a-zA-Z]\w*)?(\s+\d{1,2}t?)+$/,
@@ -788,6 +790,7 @@ var CONF_CMDS=[
/^ingress(\s+\d{1,2}[tua])+$/,/^ingress\s+[tua]$/, /^ingress(\s+\d{1,2}[tua])+$/,/^ingress\s+[tua]$/,
/^port\s+\d{1,2}\s+(10m|100m|1g|2g5|5g|10g|auto|on|off)(\s+(half|full))?$/, /^port\s+\d{1,2}\s+(10m|100m|1g|2g5|5g|10g|auto|on|off)(\s+(half|full))?$/,
/^port\s+\d{1,2}\s+name\s+\S+$/, /^port\s+\d{1,2}\s+name\s+\S+$/,
/^port\s+\d{1,2}\s+lldp\s+(permit|block)+$/,
/^eee\s+(on|off)(\s+\d{1,2})?(\s+(100m|1g|2g5))?$/, /^eee\s+(on|off)(\s+\d{1,2})?(\s+(100m|1g|2g5))?$/,
/^mirror(\s+\d{1,2})(\s+\d{1,2}[tr]?)+$/,/^mirror\s+off$/, /^mirror(\s+\d{1,2})(\s+\d{1,2}[tr]?)+$/,/^mirror\s+off$/,
/^lag\s+[1-4](\s+\d{1,2})+$/,/^lag\s+[1-4]\s+d$/,/^laghash\s+[1-4](\s+\w+)+$/, /^lag\s+[1-4](\s+\d{1,2})+$/,/^lag\s+[1-4]\s+d$/,/^laghash\s+[1-4](\s+\w+)+$/,
@@ -798,7 +801,7 @@ var CONF_CMDS=[
/^stp\s+(port\s+\d{1,2}|lag\s+[1-4])\s+cost\s+\d{1,9}$/,/^stp\s+(port\s+\d{1,2}|lag\s+[1-4])\s+prio\s+\d{1,3}$/, /^stp\s+(port\s+\d{1,2}|lag\s+[1-4])\s+cost\s+\d{1,9}$/,/^stp\s+(port\s+\d{1,2}|lag\s+[1-4])\s+prio\s+\d{1,3}$/,
/^stp\s+(port\s+\d{1,2}|lag\s+[1-4])\s+guard\s+(none|bpdu|root)$/,/^stp\s+(port\s+\d{1,2}|lag\s+[1-4])\s+filter\s+(on|off)$/, /^stp\s+(port\s+\d{1,2}|lag\s+[1-4])\s+guard\s+(none|bpdu|root)$/,/^stp\s+(port\s+\d{1,2}|lag\s+[1-4])\s+filter\s+(on|off)$/,
/^stp\s+(port\s+\d{1,2}|lag\s+[1-4])\s+p2p\s+(auto|on|off)$/, /^stp\s+(port\s+\d{1,2}|lag\s+[1-4])\s+p2p\s+(auto|on|off)$/,
/^igmp\s+(on|off)$/,/^mtu\s+\d{1,2}\s+\d+$/, /^igmp\s+(on|off)$/,/^mtu\s+\d{1,2}\s+\d+$/,/^lldp\s+(on|off)$/,
/^bw\s+(in|out)\s+\d{1,2}\s+\S+$/, /^bw\s+(in|out)\s+\d{1,2}\s+\S+$/,
/^storm\s+\d{1,2}\s+(bcast|mcast|ucast|umcast)\s+(off|\d{1,8}\s+(pps|kbps))$/, /^storm\s+\d{1,2}\s+(bcast|mcast|ucast|umcast)\s+(off|\d{1,8}\s+(pps|kbps))$/,
]; ];
@@ -860,6 +863,7 @@ var TABS=[
{id:"mirror",icon:"M12 3v18M7 8l-4 4 4 4M17 8l4 4-4 4"}, {id:"mirror",icon:"M12 3v18M7 8l-4 4 4 4M17 8l4 4-4 4"},
{id:"isolate",icon:"M4 4h6v6H4zM14 14h6v6h-6zM14 4h6v6h-6zM4 14h6v6H4z"}, {id:"isolate",icon:"M4 4h6v6H4zM14 14h6v6h-6zM14 4h6v6h-6zM4 14h6v6H4z"},
{id:"lag", icon:"M7 8a4 4 0 100 8h3M17 8a4 4 0 110 8h-3M9 12h6"}, {id:"lag", icon:"M7 8a4 4 0 100 8h3M17 8a4 4 0 110 8h-3M9 12h6"},
{id:"lldp", icon:"M11 12a1 1 0 002 0 1 1 0 00-2 0M8.5 8.5a5 5 0 000 7M15.5 8.5a5 5 0 010 7M5.6 5.6a9 9 0 000 12.8M18.4 5.6a9 9 0 010 12.8"},
{id:"eee", icon:"M13 2L4 14h6l-1 8 9-12h-6z"}, {id:"eee", icon:"M13 2L4 14h6l-1 8 9-12h-6z"},
{id:"bw", icon:"M4 18a8 8 0 0116 0M12 18l4-6"}, {id:"bw", icon:"M4 18a8 8 0 0116 0M12 18l4-6"},
{id:"system",icon:"M12 8a4 4 0 100 8 4 4 0 000-8zM4 12h2M18 12h2M12 4v2M12 18v2M6 6l1.5 1.5M16.5 16.5L18 18M18 6l-1.5 1.5M7.5 16.5L6 18"}, {id:"system",icon:"M12 8a4 4 0 100 8 4 4 0 000-8zM4 12h2M18 12h2M12 4v2M12 18v2M6 6l1.5 1.5M16.5 16.5L18 18M18 6l-1.5 1.5M7.5 16.5L6 18"},
@@ -1835,6 +1839,32 @@ function lagApply(g){
} }
tabHooks.lag={enter:function(){needPorts(function(){buildLag();lagLoad().catch(function(){})})}}; tabHooks.lag={enter:function(){needPorts(function(){buildLag();lagLoad().catch(function(){})})}};
function lldpLoad(){
return getJSON("/lldp.json").then(function(s){
$("lldp_en").checked=s.on;
var tb=$("lldp_table").tBodies[0];tb.innerHTML="";
byPort(s.portStatus).forEach(function(p){
var tr=tb.insertRow();
tr.insertCell().textContent=p.portNum;
tr.insertCell().textContent=p.name;
var sw=h("label",{class:"switch"},[
h("input",{type:"checkbox",onchange:function(){
postCmd("port "+p.portNum+" lldp "+(this.checked?"permit":"block"))
.then(function(){setTimeout(lldpLoad,300)}).catch(function(){});
}}),h("i")]);
sw.firstChild.checked=p.permitted;
tr.insertCell().appendChild(sw);
});
});
}
$("lldp_en").addEventListener("change",function(){
var el=this;
postCmd("lldp "+(el.checked?"on":"off")).catch(function(){el.checked=!el.checked});
});
tabHooks.lldp={enter:lldpLoad};
function eeeFlags(bits){ function eeeFlags(bits){
var b=parseInt(bits,2); var b=parseInt(bits,2);
return["100M","1G","2.5G"].map(function(s,i){ return["100M","1G","2.5G"].map(function(s,i){
@@ -1993,6 +2023,16 @@ function sysLoad(){
if(S.info.session_timeout)$("sy-sesstmo").value=S.info.session_timeout; if(S.info.session_timeout)$("sy-sesstmo").value=S.info.session_timeout;
}).catch(function(){}); }).catch(function(){});
cfgReload(); cfgReload();
dnsLoad();
}
function dnsLoad(){
return api("/cmd",{method:"POST",body:"dns"}).then(function(r){
var m=r.body.match(/DNS servers ([\d.]+) ([\d.]+), from DHCP ([\d.]+)/);
if(!m)return;
function v(x){return x==="0.0.0.0"?"":x}
$("sy-dns1").value=v(m[1]);$("sy-dns2").value=v(m[2]);
$("sy-dnsdhcp").textContent=m[3]==="0.0.0.0"?"":t("sy_dns_dhcp",{ip:m[3]});
}).catch(function(){});
} }
function cfgParseKnown(txt){ function cfgParseKnown(txt){
var igmp=false,syslog=false; var igmp=false,syslog=false;
@@ -2009,13 +2049,15 @@ function cfgParseKnown(txt){
$("sy-apply").addEventListener("click",function(){ $("sy-apply").addEventListener("click",function(){
var ip=$("sy-ip").value.trim(),mask=$("sy-mask").value.trim(),gw=$("sy-gw").value.trim(); var ip=$("sy-ip").value.trim(),mask=$("sy-mask").value.trim(),gw=$("sy-gw").value.trim();
if(!okIp(ip)||!okIp(mask)||!okIp(gw)){toast(t("sy_ip_err"),"err");return;} if(!okIp(ip)||!okIp(mask)||!okIp(gw)){toast(t("sy_ip_err"),"err");return;}
var d1=$("sy-dns1").value.trim(),d2=$("sy-dns2").value.trim();
if((d1&&!okIp(d1))||(d2&&!okIp(d2))){toast(t("sy_dns_err"),"err");return;}
var cmds=[]; var cmds=[];
var hn=$("sy-host").value.trim(); var hn=$("sy-host").value.trim();
if(hn&&hn!==S.info.hostname){ if(hn&&hn!==S.info.hostname){
if(!/^[\x21-\x7e]{1,23}$/.test(hn)||/["\\]/.test(hn)){toast(t("sy_host_err"),"err");return;} if(!/^[\x21-\x7e]{1,23}$/.test(hn)||/["\\]/.test(hn)){toast(t("sy_host_err"),"err");return;}
cmds.push("hostname "+hn); cmds.push("hostname "+hn);
} }
cmds.push("ip "+ip+"\nnetmask "+mask+"\ngw "+gw); cmds.push("ip "+ip+"\nnetmask "+mask+"\ngw "+gw+"\ndns server "+(d1||"0.0.0.0")+(d2?" "+d2:""));
var changingIp=ip!==S.info.ip_address; var changingIp=ip!==S.info.ip_address;
confirmModal(t("sy_net_q"),changingIp?t("sy_net_d",{ip:ip}):"",function(){ confirmModal(t("sy_net_q"),changingIp?t("sy_net_d",{ip:ip}):"",function(){
postCmds(cmds).then(function(){ postCmds(cmds).then(function(){
@@ -2111,7 +2153,7 @@ tabHooks.system={enter:sysLoad};
var CONF_OVERWRITE=[ var CONF_OVERWRITE=[
/^ip\b/,/^gw\b/,/^netmask\b/,/^hostname\b/, /^ip\b/,/^gw\b/,/^netmask\b/,/^hostname\b/,
/^syslog\s+ip\b/,/^syslog\s+port\b/,/^passwd\b/,/^session\b/, /^syslog\s+ip\b/,/^syslog\s+port\b/,/^dns\s+server\b/,/^passwd\b/,/^session\b/,
/^vlan\s+\d{1,4}\s+mgmt$/,/^vlan\s+\d{1,4}(?!\s+mgmt\b)/, /^vlan\s+\d{1,4}\s+mgmt$/,/^vlan\s+\d{1,4}(?!\s+mgmt\b)/,
/^pvid\s+\d{1,2}\b/, /^pvid\s+\d{1,2}\b/,
/^port\s+\d{1,2}(?!\s+name\b)/,/^port\s+\d{1,2}\s+name\b/, /^port\s+\d{1,2}(?!\s+name\b)/,/^port\s+\d{1,2}\s+name\b/,
+14
View File
@@ -331,6 +331,17 @@ button.danger{background:var(--bad);color:#fff;border-color:transparent}
</div> </div>
</section> </section>
<section class="tab" id="tab-lldp">
<div class="card"><h2 data-i18n="lldp_title">LLDP</h2>
<label class="row"><span class="lb" data-i18n="lldp_enabled">Enabled</span>
<span class="switch"><input type="checkbox" id="lldp_en"><i></i></span>
</label>
<div class="scrollx"><table class="t" id="lldp_table">
<thead><tr><th data-i18n="c_port">Port Number</th><th data-i18n="lldp_portname">Name</th><th data-i18n="lldp_enable">Send Frames</th></tr></thead>
<tbody></tbody></table></div>
</div>
</section>
<section class="tab" id="tab-isolate"> <section class="tab" id="tab-isolate">
<div class="card"><h2 data-i18n="iso_title">Port isolation</h2> <div class="card"><h2 data-i18n="iso_title">Port isolation</h2>
<p class="small mut" style="margin-bottom:10px" data-i18n="iso_intro">A frame entering a port may only leave through the ports ticked in its row.</p> <p class="small mut" style="margin-bottom:10px" data-i18n="iso_intro">A frame entering a port may only leave through the ports ticked in its row.</p>
@@ -378,6 +389,9 @@ button.danger{background:var(--bad);color:#fff;border-color:transparent}
<label class="row"><span class="lb" data-i18n="i_ip">IP address</span><input class="in" id="sy-ip" size="15"></label> <label class="row"><span class="lb" data-i18n="i_ip">IP address</span><input class="in" id="sy-ip" size="15"></label>
<label class="row"><span class="lb" data-i18n="i_mask">Netmask</span><input class="in" id="sy-mask" size="15"></label> <label class="row"><span class="lb" data-i18n="i_mask">Netmask</span><input class="in" id="sy-mask" size="15"></label>
<label class="row"><span class="lb" data-i18n="i_gw">Gateway</span><input class="in" id="sy-gw" size="15"></label> <label class="row"><span class="lb" data-i18n="i_gw">Gateway</span><input class="in" id="sy-gw" size="15"></label>
<label class="row"><span class="lb" data-i18n="sy_dns1">DNS server</span><input class="in" id="sy-dns1" size="15"></label>
<label class="row"><span class="lb" data-i18n="sy_dns2">Second DNS</span><input class="in" id="sy-dns2" size="15"></label>
<p class="small mut" id="sy-dnsdhcp"></p>
<div style="display:flex;gap:10px;margin-top:12px"> <div style="display:flex;gap:10px;margin-top:12px">
<button class="ctl pri" id="sy-apply" data-i18n="c_apply">Apply</button> <button class="ctl pri" id="sy-apply" data-i18n="c_apply">Apply</button>
<button class="ctl" id="sy-dhcp" data-i18n="sy_dhcp" data-i18n-t="sy_dhcp_t">Use DHCP</button> <button class="ctl" id="sy-dhcp" data-i18n="sy_dhcp" data-i18n-t="sy_dhcp_t">Use DHCP</button>
+2
View File
@@ -1034,6 +1034,8 @@ void httpd_appcall(void)
send_lag(); send_lag();
} else if (is_word(q, "/stp.json")) { } else if (is_word(q, "/stp.json")) {
send_stp(); send_stp();
} else if (is_word(q, "/lldp.json")) {
send_lldp();
} else if (is_word(q, "/vlanlist")) { } else if (is_word(q, "/vlanlist")) {
send_vlanlist(); send_vlanlist();
} else if (is_word(q, "/config")) { } else if (is_word(q, "/config")) {
+32 -1
View File
@@ -49,6 +49,9 @@ extern __xdata char sfp_module_model[2][17];
extern __xdata char sfp_module_serial[2][17]; extern __xdata char sfp_module_serial[2][17];
extern __xdata uint8_t sfp_options[2]; extern __xdata uint8_t sfp_options[2];
extern __xdata uint16_t lldp_logical_port_status;
extern __xdata bool lldp_enabled;
__code const uint8_t * __code const HTTP_RESPONCE_JSON = "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Type: application/json\r\n\r\n"; __code const uint8_t * __code const HTTP_RESPONCE_JSON = "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Type: application/json\r\n\r\n";
__code const uint8_t * __code const HTTP_RESPONCE_TXT = "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Type: text/plain\r\n\r\n"; __code const uint8_t * __code const HTTP_RESPONCE_TXT = "HTTP/1.1 200 OK\r\nConnection: close\r\nContent-Type: text/plain\r\n\r\n";
@@ -619,7 +622,6 @@ static void bridge_to_html(void)
byte_to_html(pi_mac[i]); byte_to_html(pi_mac[i]);
} }
void send_stp(void) void send_stp(void)
{ {
uint8_t i, j, st, dsg; uint8_t i, j, st, dsg;
@@ -734,8 +736,37 @@ void send_stp(void)
slen += strtox(outbuf + slen, "]}"); slen += strtox(outbuf + slen, "]}");
} }
void send_lldp(void)
{
dbg_string("send_lldp called\n");
slen = strtox(outbuf, HTTP_RESPONCE_JSON);
slen += strtox(outbuf + slen, "{\"on\":");
bool_to_html(lldp_enabled);
slen += strtox(outbuf + slen, ",\"portStatus\":[");
for (uint8_t i = machine.min_port; i <= machine.max_port; i++) {
slen += strtox(outbuf + slen, "{\"portNum\":");
itoa_html(machine.log_to_phys_port[i]);
slen += strtox(outbuf + slen, ",\"logPort\":");
itoa_html(i);
slen += strtox(outbuf + slen, ",\"name\":\"");
for (uint8_t j = 0; j < PORT_NAME_SIZE && port_names[i][j]; j++) {
json_char_to_html(port_names[i][j]);
}
slen += strtox(outbuf + slen, "\",\"permitted\":");
bool_to_html(1 & (lldp_logical_port_status >> i));
slen += strtox(outbuf + slen, "}");
if (i < machine.max_port)
char_to_html(',');
else
char_to_html(']');
}
char_to_html('}');
}
void send_eee(void) void send_eee(void)
{ {
+1
View File
@@ -23,6 +23,7 @@ void send_config(void);
void send_cmd_log(void); void send_cmd_log(void);
void send_lag(void); void send_lag(void);
void send_stp(void); void send_stp(void);
void send_lldp(void);
void send_vlanlist(void); void send_vlanlist(void);
/* Convert only the lower nibble to ascii HEX char. /* Convert only the lower nibble to ascii HEX char.
+1
View File
@@ -131,6 +131,7 @@ struct flash_region_t {
}; };
extern __xdata char port_names[9][PORT_NAME_SIZE]; extern __xdata char port_names[9][PORT_NAME_SIZE];
extern __xdata uint16_t lldp_logical_port_status;
extern __xdata bool stp_enabled; extern __xdata bool stp_enabled;
+161
View File
@@ -0,0 +1,161 @@
#pragma codeseg BANK3
#pragma constseg BANK3
#include "rtl837x_common.h"
#include "rtl837x_lldp.h"
#include "rtl837x_sfr.h"
#include "rtl837x_common.h"
#include "dhcp.h"
#include "uip.h"
#include "uip/uip.h"
#include "machine.h"
extern __xdata bool lldp_enabled;
extern __code const struct machine machine;
__xdata uint16_t lldp_ticks;
__xdata uint16_t lldp_logical_port_status = 0xffff;
void lldp_init(void) __banked
{
lldp_ticks = 0;
}
void lldp_tick(void) __banked
{
lldp_ticks++;
if (lldp_ticks < LLDP_TX_INTERVAL_TICKS)
return;
lldp_ticks = 0;
if(lldp_enabled == 1)
lldp_send();
}
//Outgoing LLDP packet.
struct lldp_pkt {
struct uip_eth_addr dst;
struct uip_eth_addr src;
struct rtl_tag rtl_tag;
uint16_t ether_type;
uint8_t payload[64];
};
#define LLDP_O ((__xdata struct lldp_pkt *)&uip_buf[RTL_FRAME_DESC_SIZE])
// The type is 7 bits and the length is 9 bits
// we can represent this as the 7 most significant
// bits of the type bit and leave the least significant
// bit as 0 always as we're not going to need 2^9 for
// the length at any point
#define LLDP_TYPE(value) (value << 1)
void lldp_send(void) __banked __reentrant
{
__xdata uint8_t *p;
uint8_t port_position;
lldp_set_addresses();
lldp_set_rtl_wrapper();
p = LLDP_O->payload;
//Chassis ID
*p++ = LLDP_TYPE(LLDP_CHASSIS_ID_TLV_TYPE);
*p++ = LLDP_CHASSIS_ID_TLV_LENGTH;
*p++ = LLDP_CHASSIS_ID_TLV_SUBTYPE;
memcpy(p, uip_ethaddr.addr, MAC_ADDR_LEN);
p += MAC_ADDR_LEN;
//Port ID
*p++ = LLDP_TYPE(LLDP_PORT_ID_TLV_TYPE);
*p++ = LLDP_PORT_ID_TLV_LENGTH;
*p++ = LLDP_PORT_ID_TLV_SUBTYPE;
port_position = (p-LLDP_O->payload);
*p++ = '0'; // filled in per port below
//TTL
*p++ = LLDP_TYPE(LLDP_TTL_TLV_TYPE);
*p++ = LLDP_TTL_TLV_LENGTH;
*p++ = 0x00; //padding
*p++ = LLDP_TTL_TTL_SECONDS;
p += lldp_sysname(p);
p += lldp_sysdesc(p);
// End of LLDPDU TLV
*p++ = 0x00; //padding
*p++ = 0x00; //padding
while (p < (LLDP_O->payload + LLDP_MIN_ETHERNET_PAYLOAD_LENGTH))
*p++ = 0x00;
/*
* uip_len is the Ethernet frame length excluding FCS.
*
* The frame consists of:
*
* dst mac
* src mac
* rtl_tag sizeof(struct rtl_tag)
* EtherType (2 bytes)
* payload (how far we've moved p pointer)
*/
uip_len = MAC_ADDR_LEN + MAC_ADDR_LEN + sizeof(struct rtl_tag) + LLDP_ETHERTYPE_LENGTH + (p - LLDP_O->payload);
for (uint8_t port = machine.min_port; port <= machine.max_port; port++) {
if ((1 << port) & lldp_logical_port_status) {
LLDP_O->payload[port_position] = '0' + machine.log_to_phys_port[port];
LLDP_O->rtl_tag.pmask = HTONS((uint16_t)1 << port);
tcpip_output();
}
}
}
void lldp_set_addresses(void) __banked {
// LLDP destination multicast addr: 01:80:c2:00:00:0e
memcpyc(LLDP_O->dst.addr, "\x01\x80\xc2\x00\x00\x0e", MAC_ADDR_LEN);
memcpy(LLDP_O->src.addr, uip_ethaddr.addr, MAC_ADDR_LEN);
}
void lldp_set_rtl_wrapper(void) __banked {
/*
* This is the RTL CPU tag, not the Ethernet EtherType.
* port 0 -> 0x0001
* port 1 -> 0x0002
* port 2 -> 0x0004
*/
LLDP_O->rtl_tag.tag = HTONS(RTL_FRAME_TAG_ID);
LLDP_O->rtl_tag.version = RTL_FRAME_TAG_VERSION;
LLDP_O->rtl_tag.reason = 0x00;
LLDP_O->rtl_tag.flags = HTONS(RTL_TAG_LEARN_DIS);
LLDP_O->ether_type = HTONS(LLDP_ETHERTYPE);
}
uint8_t lldp_sysname(__xdata uint8_t *p) __banked
{
uint8_t hostname_length = strlen_x(hostname);
*p++ = LLDP_TYPE(LLDP_SYSNAME_TLV_TYPE);
*p++ = hostname_length;
memcpy(p, hostname, hostname_length);
return hostname_length + 2;
}
uint8_t lldp_sysdesc(__xdata uint8_t *p) __banked
{
uint16_t machine_name_length = strlen(machine.machine_name);
*p++ = LLDP_TYPE(LLDP_SYSDESC_TLV_TYPE);
*p++ = machine_name_length;
memcpyc(p, machine.machine_name, machine_name_length);
return machine_name_length + 2;
}
+36
View File
@@ -0,0 +1,36 @@
#ifndef _LLDP_H_
#define _LLDP_H_
#include <stdint.h>
#define LLDP_MIN_ETHERNET_PAYLOAD_LENGTH 46
#define LLDP_ETHERTYPE 0x88cc
#define LLDP_ETHERTYPE_LENGTH 2
#define LLDP_MAX_FRAME 256
#define MAC_ADDR_LEN 6
#define LLDP_TX_INTERVAL_TICKS 6000
#define LLDP_PORT_ID_TLV_TYPE 2
#define LLDP_PORT_ID_TLV_LENGTH 0x02
#define LLDP_PORT_ID_TLV_SUBTYPE 0x07
#define LLDP_TTL_TLV_TYPE 3
#define LLDP_TTL_TLV_LENGTH 2
#define LLDP_TTL_TTL_SECONDS 120
#define LLDP_CHASSIS_ID_TLV_TYPE 1
#define LLDP_CHASSIS_ID_TLV_LENGTH 7
#define LLDP_CHASSIS_ID_TLV_SUBTYPE 4
#define LLDP_SYSNAME_TLV_TYPE 5
#define LLDP_SYSDESC_TLV_TYPE 6
void lldp_init(void) __banked;
void lldp_tick(void) __banked;
void lldp_send(void) __banked;
void lldp_set_addresses(void) __banked;
void lldp_set_rtl_wrapper(void) __banked;
uint8_t lldp_sysname(__xdata uint8_t *p) __banked;
uint8_t lldp_sysdesc(__xdata uint8_t *p) __banked;
#endif
+7
View File
@@ -16,6 +16,7 @@
#include "rtl837x_leds.h" #include "rtl837x_leds.h"
#include "rtl837x_bandwidth.h" #include "rtl837x_bandwidth.h"
#include "rtl837x_init.h" #include "rtl837x_init.h"
#include "rtl837x_lldp.h"
#include "dhcp.h" #include "dhcp.h"
#include "cmd_parser.h" #include "cmd_parser.h"
#include "cmd_editor.h" #include "cmd_editor.h"
@@ -25,6 +26,7 @@
#include "machine.h" #include "machine.h"
#include "phy.h" #include "phy.h"
#include "syslog.h" #include "syslog.h"
#include "dns.h"
#include "httpd/page_impl.h" #include "httpd/page_impl.h"
#include "boot.h" #include "boot.h"
#include "sfp.h" #include "sfp.h"
@@ -127,6 +129,7 @@ __xdata uint8_t tx_seq;
__xdata bool stp_enabled; __xdata bool stp_enabled;
__xdata uint8_t igmpEnabled; __xdata uint8_t igmpEnabled;
__xdata bool lldp_enabled;
__xdata char hostname[24]; /* device hostname, default set at boot, see rtl837x_common.h */ __xdata char hostname[24]; /* device hostname, default set at boot, see rtl837x_common.h */
__code const uint16_t bit_mask[16] = { __code const uint16_t bit_mask[16] = {
@@ -1286,6 +1289,8 @@ static void handle_tick(void)
} }
} }
health_phase(HEALTH_PH_STP); health_phase(HEALTH_PH_STP);
lldp_tick();
health_phase(HEALTH_LLDP);
} }
@@ -1763,6 +1768,7 @@ void main(void)
check_and_flash_update_image(); check_and_flash_update_image();
syslog_init(); syslog_init();
dns_init();
#ifdef DEBUG #ifdef DEBUG
// This register seems to work on the RTL8373 only if also the SDS // This register seems to work on the RTL8373 only if also the SDS
@@ -1792,6 +1798,7 @@ void main(void)
uip_init(); uip_init();
uip_arp_init(); uip_arp_init();
httpd_init(); httpd_init();
lldp_init();
management_vlan = 1; // Default management VLAN is 1 management_vlan = 1; // Default management VLAN is 1
+3
View File
@@ -84,6 +84,9 @@ char port_names[9][PORT_NAME_SIZE];
struct flash_region_t flash_region; struct flash_region_t flash_region;
struct syslog_state syslog_state; struct syslog_state syslog_state;
bool stp_enabled; bool stp_enabled;
bool lldp_enabled;
uint16_t lldp_logical_port_status;
uip_ipaddr_t uip_hostaddr, uip_draddr, uip_netmask; uip_ipaddr_t uip_hostaddr, uip_draddr, uip_netmask;
struct uip_eth_addr uip_ethaddr = { .addr = { 0x02, 0x11, 0x22, 0x33, 0x44, 0x55 } }; struct uip_eth_addr uip_ethaddr = { .addr = { 0x02, 0x11, 0x22, 0x33, 0x44, 0x55 } };
+1
View File
@@ -152,6 +152,7 @@ void send_lag(void) { }
void send_stp(void) { } void send_stp(void) { }
void send_stp_counters(void) { } void send_stp_counters(void) { }
void send_vlanlist(void) { } void send_vlanlist(void) { }
void send_lldp(void) {}
extern uint8_t authenticated; extern uint8_t authenticated;
+35 -1
View File
@@ -454,6 +454,34 @@ void send_mtu(int s)
json_object_put(mtus); json_object_put(mtus);
} }
void send_lldp(int s)
{
struct json_object *c, *portStatuses, *p;
const char *jstring;
char *header = "HTTP/1.1 200 OK\r\n"
"Content-Type: application/json; charset=UTF-8\r\n\r\n";
c = json_object_new_object();
json_object_object_add(c, "on", json_object_new_int(1));
portStatuses = json_object_new_array_ext(PORTS);
for (int i = 1; i <= PORTS; i++) {
p = json_object_new_object();
json_object_object_add(p, "portNum", json_object_new_int(i));
json_object_object_add(p, "logPort", json_object_new_int(i-1));
json_object_object_add(p, "name", json_object_new_string(""));
json_object_object_add(p, "permitted", json_object_new_int(1));
json_object_array_add(portStatuses, p);
}
json_object_object_add(c, "portStatus", portStatuses);
write(s, header, strlen(header));
jstring = json_object_to_json_string_ext(c, JSON_C_TO_STRING_PLAIN);
write(s, jstring, strlen(jstring));
json_object_put(c);
}
void send_cmd_log(int s) void send_cmd_log(int s)
{ {
@@ -468,7 +496,6 @@ void send_cmd_log(int s)
} }
} }
void send_config(int s) void send_config(int s)
{ {
char *header = "HTTP/1.1 200 OK\r\n" char *header = "HTTP/1.1 200 OK\r\n"
@@ -701,6 +728,13 @@ void launch(struct Server *server)
else else
send_vlan(new_socket, vlan); send_vlan(new_socket, vlan);
goto done; goto done;
} else if (!strncmp(&buffer[4], "/lldp.json", 10)) {
printf("LLDP request");
if (!authenticated)
send_unauthorized(new_socket);
else
send_lldp(new_socket);
goto done;
} else if (!strncmp(&buffer[4], "/cmd_log", 8)) { } else if (!strncmp(&buffer[4], "/cmd_log", 8)) {
printf("Request cmd_log\n"); printf("Request cmd_log\n");
if (!authenticated) if (!authenticated)
+1 -1
View File
@@ -3,7 +3,7 @@
#include <netinet/in.h> #include <netinet/in.h>
#define BUFFER_SIZE 131072 #define BUFFER_SIZE 262144
struct Server { struct Server {
int domain; int domain;
+1
View File
@@ -6,4 +6,5 @@ void udp_callbacks(void)
{ {
dhcp_callback(uip_udp_conn->lport); // let the application decide if this is for it or not dhcp_callback(uip_udp_conn->lport); // let the application decide if this is for it or not
syslog_callback(uip_udp_conn->lport); // let the application decide if this is for it or not syslog_callback(uip_udp_conn->lport); // let the application decide if this is for it or not
dns_callback(uip_udp_conn->lport);
} }
+1
View File
@@ -3,6 +3,7 @@
#include "dhcp.h" #include "dhcp.h"
#include "syslog.h" #include "syslog.h"
#include "dns.h"
void udp_callbacks(void); void udp_callbacks(void);