Commit 35124ca4 authored by Adam Wujek's avatar Adam Wujek 💬

lib: implement netconsole (via uart_read_byte)

Mirror serial console to netconsole.
To use netconsole executre the following command on a host connected to wrpc:
nc -u <IP> 55

Send of a command is triggered by a newline.
To see output in the netconsole any command (even empty line) has to be sent
first.
Signed-off-by: Adam Wujek's avatarAdam Wujek <adam.wujek@cern.ch>
parent cea444a3
......@@ -379,6 +379,13 @@ config CMD_LEAPSEC
This enables leapsec command, which can be used to adjust leap seconds
value.
config NETCONSOLE
depends on WR_NODE && IP && !NET_VERBOSE
boolean "Include netconsole via UDP"
default y
help
Include netconsole to be run via UDP
#
# This is a set of configuration options that should not be changed by
# normal users. If the "developer" menu is used, the binary is tainted.
......
......@@ -18,6 +18,16 @@
( ((( (unsigned long long)baudrate * 8ULL) << (16 - 7)) + \
(CPU_CLOCK >> 8)) / (CPU_CLOCK >> 7) )
#ifdef CONFIG_NETCONSOLE
#define HAS_NETCONSOLE 1
int netconsole_read_byte(void);
int netconsole_write_string(const char *);
#else
#define HAS_NETCONSOLE 0
static int netconsole_read_byte(void) {return -1;}
static int netconsole_write_string(const char *s) {return -1;}
#endif
static inline uint32_t suart_calc_baud( int baudrate )
{
uint64_t n = (((uint64_t) (baudrate)) << 12 ) + (CPU_CLOCK >> 8);
......@@ -48,6 +58,9 @@ void suart_write_byte(struct simple_uart_device *dev, int b)
int suart_write_string(struct simple_uart_device *dev, const char *s)
{
const char *t = s;
if (HAS_NETCONSOLE)
netconsole_write_string(s);
while (*s)
suart_write_byte(dev, *(s++));
return s - t;
......@@ -72,6 +85,12 @@ int suart_poll(struct simple_uart_device *dev)
int suart_read_byte(struct simple_uart_device *dev)
{
int ret;
/* check if there is anything from netconsole first */
if (HAS_NETCONSOLE && (ret = netconsole_read_byte()) >= 0)
return ret;
if (!suart_poll(dev))
return -1;
......
/*
* This work is part of the White Rabbit project
*
* Released according to the GNU GPL, version 2 or any later version.
*/
#ifndef __NETCONSOLE_H__
#define __NETCONSOLE_H__
void netconsole_init(void);
int netconsole_poll(void);
int netconsole_read_byte(void);
int netconsole_write_string(const char *s);
#endif /* __NETCONSOLE_H__ */
......@@ -13,6 +13,7 @@ obj-$(CONFIG_SYSLOG) += lib/syslog.o
obj-$(CONFIG_LATENCY_PROBE) += lib/latency.o
obj-$(CONFIG_SNMP) += lib/snmp.o
obj-$(CONFIG_LLDP) += lib/lldp.o
obj-$(CONFIG_NETCONSOLE) += lib/netconsole.o
# below requires $(AUTOCONF_PPSI) to be present before build
REQUIRE_AUTOCONF_PPSI += \
......
/*
* This work is part of the White Rabbit project
*
* Copyright (C) 2018 CERN (www.cern.ch)
* Author: Adam Wujek <adam.wujek@cern.ch>
*
* Released according to the GNU GPL, version 2 or any later version.
*/
#include <wrc.h>
//#include <wrpc.h>
#include <string.h>
#include "ipv4.h"
#include "ptpd_netif.h"
#include "shell.h"
#include "netconsole.h"
static uint8_t __netconsole_queue[128];
static struct wrpc_socket __static_netconsole_socket = {
.queue.buff = __netconsole_queue,
.queue.size = sizeof(__netconsole_queue),
};
static struct wrpc_socket *netconsole_socket;
static unsigned char *cmd_rx_p = NULL;
/* net headers + cmd len */
static uint8_t tx_buf[UDP_END + SH_MAX_LINE_LEN + 1];
static uint8_t rx_buf[UDP_END + SH_MAX_LINE_LEN + 1];
struct wr_sockaddr netconsole_sock_addr;
static int netconsole_has_peer = 0;
struct wr_udp_addr netconsole_udp_addr;
void netconsole_init(void)
{
netconsole_socket = ptpd_netif_create_socket(
&__static_netconsole_socket, NULL,
PTPD_SOCK_UDP, 55);
/* TODO: find a better port number */
}
int netconsole_read_byte(void)
{
if (cmd_rx_p && *cmd_rx_p != 0)
return *(cmd_rx_p++);
return -1;
}
int netconsole_write_string(const char *s)
{
int len;
if (!netconsole_has_peer)
return 0;
/* Prevent recursive calls when net verbose configured.
* NOTE: Even with the following if, NET_IS_VERBOSE does not work
* with netconsole */
if (NET_IS_VERBOSE)
netconsole_has_peer = 0;
strncpy((char *) &tx_buf[UDP_END], s, SH_MAX_LINE_LEN);
len = min(strlen(s), SH_MAX_LINE_LEN);
len += UDP_END;
fill_udp((uint8_t *)tx_buf, len, &netconsole_udp_addr);
ptpd_netif_sendto(netconsole_socket,
&netconsole_sock_addr, tx_buf, len, 0);
if (NET_IS_VERBOSE)
netconsole_has_peer = 1;
return 0;
}
int netconsole_poll(void)
{
int len;
if (ip_status == IP_TRAINING)
return 0; /* can't do netconsole w/o an address... */
if ((len = ptpd_netif_recvfrom(netconsole_socket,
&netconsole_sock_addr, rx_buf,
sizeof(rx_buf), NULL)
) > 0) {
if (check_dest_ip(rx_buf)) {
/* wrong destination IP */
return 0;
}
rx_buf[len] = 0;
/* copy source and destination address */
memcpy(&netconsole_udp_addr.daddr, rx_buf + IP_SOURCE, 4);
memcpy(&netconsole_udp_addr.saddr, rx_buf + IP_DEST, 4);
memcpy(&netconsole_udp_addr.dport, rx_buf + UDP_SPORT, 2);
memcpy(&netconsole_udp_addr.sport, rx_buf + UDP_DPORT, 2);
cmd_rx_p = &rx_buf[UDP_END];
netconsole_has_peer = 1;
return 1;
}
return 0;
}
......@@ -34,6 +34,7 @@
#include <dev/rxts_calibrator.h>
#include <dev/flash.h>
#include <dev/gpio.h>
#include <netconsole.h>
#include <wrc_ptp.h>
#include <system_checks.h>
......@@ -320,6 +321,11 @@ static void create_tasks(void)
#ifdef CONFIG_WR_DIAG
wrc_task_create( "diags", NULL, wrc_wr_diags );
#endif
#ifdef CONFIG_NETCONSOLE
t = wrc_task_create( "netconsole", netconsole_init, netconsole_poll );
wrc_task_set_enable( t, is_link_up );
#endif
}
int main(void) __attribute__ ((weak));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment