Commit f536a444 authored by Adam Wujek's avatar Adam Wujek

lib/netconsole: implement netconsole

Use it over WR network simply with:
nc -u <IP> 55
parents e1e05c9b 0d33ac29
......@@ -219,20 +219,33 @@ config SNMP_SET
This option enables support for SET requests for Mini SNMP responder
config SNMP_INIT
depends on SNMP && BUILD_INIT
default y if BUILD_INIT
default n
depends on SNMP && SNMP_SET && FLASH_INIT
default y
boolean "Adds support of changing init script/commands via SNMP"
help
This option adds a branch wrpcInitScriptConfigGroup to the SNMP
config SNMP_SDB
depends on SNMP && GENSDBFS
depends on SNMP && SNMP_SET && GENSDBFS
default y
boolean "Adds support of generation of SDB via SNMP"
help
This option adds a branch wrpcSdbGroup to the SNMP
config SNMP_CMD
depends on SNMP && SNMP_SET
default y
boolean "Allow to run any shell command via SNMP"
help
This option adds a branch wrpcShellCmdGroup to the SNMP
config SNMP_NETCONSOLE
depends on SNMP && NETCONSOLE
default y
boolean "Adds support of enabling/disabling netconsole via SNMP"
help
This option adds a branch wrpcNetconsoleGroup to the SNMP
config SNMP_AUX_DIAG
depends on SNMP && AUX_DIAG
default y if AUX_DIAG
......@@ -380,6 +393,37 @@ 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
choice
prompt "Default mode of netconsole"
depends on NETCONSOLE
default NETCONSOLE_DEF_DISABLE
config NETCONSOLE_DEF_WAIT
boolean "Netconsole is waiting for peer"
help
Netconsole is waiting for peer to send a command
config NETCONSOLE_DEF_DISABLE
boolean "Netconsole is disabled"
help
Use SNMP or shell command to enable netconsole
endchoice
config CMD_NETCONSOLE
depends on NETCONSOLE
boolean "Include shell command to configure netconsole"
default y
help
Include command to configure netconsole
#
# 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.
......
......@@ -3,6 +3,9 @@
*
* Released according to the GNU GPL, version 2 or any later version.
*/
#include <netconsole.h>
#ifndef __BOARD_WRC_H
#define __BOARD_WRC_H
/*
......@@ -61,7 +64,7 @@
#undef CONFIG_DISALLOW_LONG_DIVISION
#define BOARD_MAX_CONSOLE_DEVICES 1
#define BOARD_MAX_CONSOLE_DEVICES (1 + HAS_NETCONSOLE)
#define CONSOLE_UART_BAUDRATE 115200
......
......@@ -13,6 +13,7 @@
#include "board.h"
#include "dev/simple_uart.h"
#include "dev/console.h"
#include <netconsole.h>
static int puts_direct = 0;
......@@ -30,6 +31,7 @@ struct console_uart_priv_data
static struct console_uart_priv_data console_uart_priv;
struct console_device console_uart_dev;
struct console_device* console_devs[BOARD_MAX_CONSOLE_DEVICES];
static struct console_device console_netconsole_dev;
#define CON_ESCAPE_CODE 0x1b
#define CON_SWITCH_BINARY_CODE 'B'
......@@ -271,6 +273,23 @@ void console_ipmi_init( )
#endif
static int con_netconsole_getc(struct console_device* dev)
{
return netconsole_read_byte();
}
static int con_netconsole_put_string(struct console_device* dev, const char *s)
{
return netconsole_write_string(s);
}
static void console_netconsole_init(void)
{
console_netconsole_dev.get_char = con_netconsole_getc;
console_netconsole_dev.put_string = con_netconsole_put_string;
console_register_device( &console_netconsole_dev );
}
int puts(const char *s)
{
if( puts_direct)
......@@ -334,6 +353,9 @@ void console_init()
console_ipmi_init();
#endif
if (HAS_NETCONSOLE)
console_netconsole_init();
pp_printf("Console UART FIFO:: %d\n", suart_is_fifo_supported( &console_uart_priv.uart_dev ) );
}
......
......@@ -48,6 +48,7 @@ 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;
while (*s)
suart_write_byte(dev, *(s++));
return s - t;
......
This diff is collapsed.
/*
* 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__
#ifdef CONFIG_NETCONSOLE
#define HAS_NETCONSOLE 1
#else
#define HAS_NETCONSOLE 0
#endif
#define NETCONSOLE_ENABLED 1
#define NETCONSOLE_DISABLED 2
#define NETCONSOLE_WAIT 3
#define NETCONSOLE_PORT 55
extern struct wr_sockaddr netconsole_sock_addr;
extern int netconsole_status;
extern struct wr_udp_addr netconsole_udp_addr;
void netconsole_init(void);
int netconsole_poll(void);
int netconsole_read_byte(void);
int netconsole_write_string(const char *s);
#endif /* __NETCONSOLE_H__ */
......@@ -9,6 +9,9 @@
#define UI_SHELL_MODE 0
#define UI_GUI_MODE 1
#define SH_MAX_LINE_LEN 80
#define SH_MAX_ARGS 8
extern int wrc_ui_mode;
extern int wrc_stat_running;
......
......@@ -6,8 +6,8 @@ WR-WRPC-MIB DEFINITIONS ::= BEGIN
-- IMPORTS: Include definitions from other mibs here
IMPORTS
OBJECT-TYPE, Integer32, Unsigned32, Counter32, Counter64,
MODULE-IDENTITY, enterprises, TimeTicks FROM SNMPv2-SMI
DisplayString FROM SNMPv2-TC;
MODULE-IDENTITY, enterprises, TimeTicks, IpAddress FROM SNMPv2-SMI
DisplayString, MacAddress FROM SNMPv2-TC;
wrWrpcMIB MODULE-IDENTITY
LAST-UPDATED "201607061700Z"
......@@ -773,7 +773,6 @@ wrpcInitScriptConfigLine OBJECT-TYPE
"Line to be added to the init script."
::= { wrpcInitScriptConfigGroup 2 }
-- ****************************************************************************
wrpcSdbGroup OBJECT IDENTIFIER ::= { wrpcCore 10 }
......@@ -829,7 +828,130 @@ wrpcSdbParam OBJECT-TYPE
address (for I2C EEPROM)."
::= { wrpcSdbGroup 4 }
-- ****************************************************************************
wrpcNetconsoleGroup OBJECT IDENTIFIER ::= { wrpcCore 11 }
wrpcNetconsoleGetGroup OBJECT IDENTIFIER ::= { wrpcNetconsoleGroup 1 }
wrpcNetconsoleSetGroup OBJECT IDENTIFIER ::= { wrpcNetconsoleGroup 2 }
-- **************************************
wrpcNetconsoleGetStatus OBJECT-TYPE
SYNTAX INTEGER {
na(0),
enabled(1),
disable(2),
wait(3)
}
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Status of netconsole
enabled - serial console is copied to a host in the network
disabled - netconsole is not working, to resume it, please set it to _wait_
wait - node is listening for commands to arrive from host, but nothing
is send; when netconsole packet arrives all further messages
from serial console will be copied to netconsole
"
::= { wrpcNetconsoleGetGroup 1 }
wrpcNetconsoleGetPeerMac OBJECT-TYPE
SYNTAX MacAddress
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"MAC address of netconsole's peer"
::= { wrpcNetconsoleGetGroup 2 }
wrpcNetconsoleGetPeerIp OBJECT-TYPE
SYNTAX IpAddress
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"IP address of netconsole's peer"
::= { wrpcNetconsoleGetGroup 3 }
wrpcNetconsoleGetPeerPort OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-only
STATUS current
DESCRIPTION
"Port of netconsole's peer"
::= { wrpcNetconsoleGetGroup 4 }
-- **************************************
wrpcNetconsoleSetApply OBJECT-TYPE
SYNTAX INTEGER {
na(0),
disable(2),
wait(3),
applySuccessful(100),
applyFailed(200),
}
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"Make a change to a netconsole setting:
disable - don't send anything via netconsole nor wait for any input
wait - don't send anything via netconsole, but wait for any input to start sending
applySuccessful - successful to change state of netconsole
applyFailed - failed to change state of netconsole
"
::= { wrpcNetconsoleSetGroup 1 }
-- ****************************************************************************
wrpcShellCmdGroup OBJECT IDENTIFIER ::= { wrpcCore 12 }
wrpcShellCmdRun OBJECT-TYPE
SYNTAX INTEGER {
na(0),
execute(12),
executionSuccessful(100),
executionFailed(200),
executionFailedEmptyLine(201)
executionFailedSetMagicTo44451(202)
}
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"Run a shell command stored in wrpcShellCmdLine. Before command is run
OID wrpcShellCmdMagic has to be filled with 44451. This oid can have
the following values:
execute - to run the command stored in wrpcShellCmdLine
executionSuccessful - trigger of a command was successful,
but this has no information whether the command itslef was successful!
Check the wrpcShellCmdReturnCode!
executionFailed - failed to trigger the command
executionFailedEmptyLine - empty wrpcShellCmdLine
executionFailedSetMagicTo44451 - wrong magic in wrpcShellCmdMagic
"
::= { wrpcShellCmdGroup 1 }
wrpcShellCmdLine OBJECT-TYPE
SYNTAX DisplayString (SIZE(0..80))
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"Specify the command to be run"
::= { wrpcShellCmdGroup 2 }
wrpcShellCmdMagic OBJECT-TYPE
SYNTAX INTEGER {
na(0),
magic(44451)
}
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"To be able to execute command this OID has to contain 44451. After a run of a command this OID is zeroed"
::= { wrpcShellCmdGroup 3 }
wrpcShellCmdReturnCode OBJECT-TYPE
SYNTAX Integer32
MAX-ACCESS read-write
STATUS current
DESCRIPTION
"Return code of last executed command"
::= { wrpcShellCmdGroup 4 }
-- ****************************************************************************
END
......@@ -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"
#ifdef CONFIG_NETCONSOLE_DEF_WAIT
#define NETCONSOLE_DEF_VAL NETCONSOLE_WAIT
#else
#define NETCONSOLE_DEF_VAL NETCONSOLE_DISABLED
#endif
static uint8_t __netconsole_queue[152];
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;
int netconsole_status = NETCONSOLE_DEF_VAL;
struct wr_udp_addr netconsole_udp_addr;
/* init for netconsole task */
void netconsole_init(void)
{
netconsole_socket = ptpd_netif_create_socket(
&__static_netconsole_socket, NULL,
PTPD_SOCK_UDP, NETCONSOLE_PORT);
}
int netconsole_read_byte(void)
{
if (cmd_rx_p && *cmd_rx_p != 0)
return *(cmd_rx_p++);
return -1;
}
/* NOTE: pp_printf will not work in this function
* because it can be called from pp_printf */
int netconsole_write_string(const char *s)
{
static int len = 0;
const uint8_t *p;
static uint8_t *d = NULL;
static int rec_level = 0;
if (netconsole_status != NETCONSOLE_ENABLED)
return 0;
/* Prevent recursive calls when net verbose configured.
* NOTE: Even with the following if, NET_IS_VERBOSE does not work
* with netconsole */
if (rec_level > 0)
return 0;
rec_level++;
p = (uint8_t *)s;
while (1) {
if (!d) {
d = &tx_buf[UDP_END];
len = 0;
}
if (!*p) {
break;
}
*d = *p;
len++;
/* send packet on:
* --newline
* --"#", so prompt is send
* --max line length
*/
if (*d == '\n' || *d == '#' || len == SH_MAX_LINE_LEN) {
len += UDP_END;
netconsole_udp_addr.sport = htons(NETCONSOLE_PORT);
getIP((void *)&netconsole_udp_addr.saddr);
fill_udp((uint8_t *)tx_buf, len, &netconsole_udp_addr);
ptpd_netif_sendto(netconsole_socket,
&netconsole_sock_addr, tx_buf, len,
0);
d = NULL;
/* len is cleared when d == NULL */
p++;
continue;
}
p++;
d++;
}
rec_level--;
return 0;
}
int netconsole_poll(void)
{
int len;
if (ip_status == IP_TRAINING
|| netconsole_status == NETCONSOLE_DISABLED) {
/* can't do netconsole w/o an address...
* or netconsole disabled */
return 0;
}
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 peer's IP address and port */
memcpy(&netconsole_udp_addr.daddr, rx_buf + IP_SOURCE, 4);
memcpy(&netconsole_udp_addr.dport, rx_buf + UDP_SPORT, 2);
cmd_rx_p = &rx_buf[UDP_END];
netconsole_status = NETCONSOLE_ENABLED;
return 1;
}
return 0;
}
This diff is collapsed.
/*
* This work is part of the White Rabbit project
*
* Copyright (C) 2012 GSI (www.gsi.de)
* Author: Wesley W. Terpstra <w.terpstra@gsi.de>
*
* Released according to the GNU GPL, version 2 or any later version.
*/
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <wrc.h>
#include <lib/ipv4.h>
#include <netconsole.h>
#include <shell.h>
static void print_netconsole_status(void) {
char buf[20];
/* print netconsole's status */
switch (netconsole_status) {
case NETCONSOLE_ENABLED:
/* Print peer's MAC and IP */
pp_printf("netconsole's peer: ");
format_mac(buf, (void *)&netconsole_sock_addr.mac);
pp_printf("MAC: %s ", buf);
format_ip(buf, (void *)&netconsole_udp_addr.daddr);
pp_printf("IP: %s ", buf);
pp_printf("port: %d\n", netconsole_udp_addr.dport);
break;
case NETCONSOLE_WAIT:
pp_printf("netconsole is waiting for peer\n");
break;
case NETCONSOLE_DISABLED:
pp_printf("netconsole disabled\n");
break;
default:
break;
}
}
static int cmd_netconsole(const char *args[])
{
if (!args[0]) {
/* do nothing here, later print status */
} else if (!strcasecmp(args[0], "wait")) {
/* Disable netconsole */
netconsole_status = NETCONSOLE_WAIT;
} else if (!strcasecmp(args[0], "disable")) {
/* Disable permanently netconsole */
netconsole_status = NETCONSOLE_DISABLED;
} else if (args[0] && args[1] && args[2]) {
/* Set MAC and IP for netconsole peer */
decode_mac(args[0], (void *)&netconsole_sock_addr.mac);
decode_ip(args[1], (void *)&netconsole_udp_addr.daddr);
netconsole_udp_addr.dport = atoi(args[2]);
netconsole_status = NETCONSOLE_ENABLED;
} else {
pp_printf("uage: netconsole wait | disable | "
"<MAC> <IP> <port> \n");
return -EINVAL;
}
print_netconsole_status();
return 0;
}
DEFINE_WRC_COMMAND(netconsole) = {
.name = "netconsole",
.exec = cmd_netconsole,
};
......@@ -20,9 +20,6 @@
#include "shell.h"
#include "storage.h"
#define SH_MAX_LINE_LEN 80
#define SH_MAX_ARGS 8
/* interactive shell state definitions */
#define SHELL_MAX_COMMANDS 32
......@@ -37,6 +34,7 @@
#define KEY_LEFT (ESCAPE_FLAG | 68)
#define KEY_RIGHT (ESCAPE_FLAG | 67)
#define KEY_ENTER (13)
#define KEY_ENTER10 (10)
#define KEY_ESCAPE (27)
#define KEY_BACKSPACE (127)
#define KEY_DELETE (126)
......@@ -53,6 +51,14 @@
#define HAS_CMD_LEAPSEC 0
#endif
#ifdef CONFIG_CMD_NETCONSOLE
#define HAS_CMD_NETCONSOLE 1
#else
#define HAS_CMD_NETCONSOLE 0
#endif
static char cmd_buf[SH_MAX_LINE_LEN + 1];
static int cmd_pos = 0, cmd_len = 0;
......@@ -150,6 +156,8 @@ int shell_exec(const char *cmd)
shell_is_interacting = 1;
i = _shell_exec();
shell_is_interacting = 0;
/* clean cmd_buf */
cmd_buf[0] = '\0';
return i;
}
......@@ -200,6 +208,7 @@ int shell_interactive()
break;
case KEY_ENTER:
case KEY_ENTER10:
pp_printf("\n");
state = SH_EXEC;
break;
......@@ -394,4 +403,6 @@ void shell_register_commands(void)
REGISTER_WRC_COMMAND(pps);
if (HAS_CMD_LEAPSEC)
REGISTER_WRC_COMMAND(leapsec);
if (HAS_CMD_NETCONSOLE)
REGISTER_WRC_COMMAND(netconsole);
}
......@@ -24,6 +24,7 @@ obj-$(CONFIG_IP) += shell/cmd_ip.o
obj-$(CONFIG_PPSI) += shell/cmd_verbose.o
obj-$(CONFIG_CMD_CONFIG) += shell/cmd_config.o
obj-$(CONFIG_CMD_SLEEP) += shell/cmd_sleep.o
obj-$(CONFIG_CMD_NETCONSOLE) += shell/cmd_netconsole.o
obj-$(CONFIG_CMD_LL) += shell/cmd_ll.o
obj-$(CONFIG_CMD_PPS) += shell/cmd_pps.o
obj-$(CONFIG_CMD_LEAPSEC) += shell/cmd_leapsec.o
......
......@@ -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