Commit a563ada9 authored by Adam Wujek's avatar Adam Wujek 💬

Merge branch "rubi-faults"

Signed-off-by: Adam Wujek's avatarAdam Wujek <adam.wujek@cern.ch>
parents d6aefd73 d7c142a7
......@@ -100,6 +100,15 @@ menu "PTP Protocol Options"
endmenu
config ASSERT
bool "Build assertion checks in the code"
default y
help
Build assertions in the code, to catch unexpected situations.
When an assertion fails the code loops over repeating the
error message every second. OTOH, panic() is always built,
with no Kconfig -- and it does the same, unconditionally.
config EXT_WR
bool
default y if ARCH_WRS || ARCH_WRPC
......@@ -188,3 +197,11 @@ config OPTIMIZATION
int
default 0 if DISABLE_OPTIMIZATION
default 2
config WRPC_FAULTS
bool "Add the fault injection mechanism and shell command for wrpc"
depends on ARCH_WRPC
help
This adds a "fault" shell command, with subcommands.
The same mechanisms are available in the wr switch, through
the configuration file.
......@@ -21,6 +21,7 @@ OBJ-y += $A/crt0.o \
lib/libc-functions.o \
lib/dump-funcs.o \
lib/cmdline.o \
lib/assert.o \
lib/div64.o
# We only support "bare" time operations
......
#ifndef __ARCH_H__
#define __ARCH_H__
#include <ppsi/assert.h>
static inline int sleep(unsigned int seconds)
{
static volatile int i;
for (i = 0; i < 1000 * 1000 * seconds; i++)
;
return 0;
}
/* Architecture-specific defines, included by top-level stuff */
......
......@@ -22,6 +22,7 @@ OBJ-y += $A/crt0.o \
lib/libc-functions.o \
lib/dump-funcs.o \
lib/cmdline.o \
lib/assert.o \
lib/div64.o
# We only support "bare" time operations
......
#ifndef __ARCH_H__
#define __ARCH_H__
#include <ppsi/assert.h>
static inline int sleep(unsigned int seconds)
{
static volatile int i;
for (i = 0; i < 1000 * 1000 * seconds; i++)
;
return 0;
}
/* Architecture-specific defines, included by top-level stuff */
......
......@@ -12,6 +12,7 @@ OBJ-y += $A/sim-startup.o \
lib/conf.o \
lib/dump-funcs.o \
lib/libc-functions.o \
lib/assert.o \
lib/div64.o
# Support only "sim" time operations
......
#ifndef __ARCH_H__
#define __ARCH_H__
#include <ppsi/assert.h>
/* Architecture-specific defines, included by top-level stuff */
......
......@@ -13,6 +13,7 @@ OBJ-y += $A/unix-startup.o \
lib/libc-functions.o \
lib/dump-funcs.o \
lib/drop.o \
lib/assert.o \
lib/div64.o
# The user can set TIME=, but we pick unix time by default
......
......@@ -5,5 +5,6 @@
#include <arpa/inet.h> /* ntohs etc */
#include <stdlib.h> /* abs */
#include <ppsi/assert.h>
#endif /* __ARCH_H__ */
......@@ -23,8 +23,11 @@ OBJ-y += \
$A/wrpc-calibration.o \
$A/wrc_ptp_ppsi.o \
lib/dump-funcs.o \
lib/drop.o \
lib/div64.o
OBJ-$(CONFIG_WRPC_FAULTS) += $A/faults.o
# We only support "wrpc" time operations
TIME := wrpc
include time-wrpc/Makefile
......
/*
* Copyright (C) 2017 GSI (www.gsi.de)
* Author: Alessandro Rubini
*
* Released according to the GNU GPL, version 2 or any later version.
*/
#include <ppsi/ppsi.h>
#include "wrpc.h"
#include <errno.h>
#include "shell.h"
#include "syscon.h"
extern struct pp_instance ppi_static;
extern int frame_rx_delay_us;
static int cmd_fault(const char *args[])
{
struct pp_globals *ppg = ppi_static.glbs;
if (args[0] && !strcmp(args[0], "drop")) {
if (args[1])
fromdec(args[1], &ppg->rxdrop);
if (args[2])
fromdec(args[2], &ppg->txdrop);
ppsi_drop_init(ppg, timer_get_tics());
pp_printf("dropping %i/1000 rx, %i/1000 tx\n",
ppg->rxdrop, ppg->txdrop);
return 0;
}
if (args[0] && !strcmp(args[0], "delay")) {
if (args[1])
fromdec(args[1], &frame_rx_delay_us);
pp_printf("delaying %i us on rx frame\n", frame_rx_delay_us);
return 0;
}
pp_printf("Use: \"fault drop [<rxdrop> <txdrop>]\" (0..999)\n");
pp_printf(" \"fault delay [<usecs>]\"\n");
return -EINVAL;
}
DEFINE_WRC_COMMAND(fault) = {
.name = "fault",
.exec = cmd_fault,
};
#ifndef __ARCH_H__
#define __ARCH_H__
#include <assert.h> /* wrpc-sw includes assert already */
/* This arch exports wr functions, so include this for consistency checking */
#include "../proto-ext-whiterabbit/wr-api.h"
......
......@@ -8,16 +8,17 @@ ARCH_PP_PRINTF_CFLAGS += -include ../$A/include/strnlen.h
OBJ-y += $A/wrs-startup.o \
$A/main-loop.o \
$A/wrs-io.o \
$A/wrs-conf.o \
$A/wrs-calibration.o \
$A/wrs-ipcserver.o \
$A/shmem.o \
$A/util.o \
arch-unix/unix-conf.o \
lib/cmdline.o \
lib/conf.o \
lib/libc-functions.o \
lib/dump-funcs.o \
lib/drop.o \
lib/assert.o \
lib/div64.o
# We only support "wrs" time operations
......
#ifndef __ARCH_H__
#define __ARCH_H__
#include <ppsi/assert.h>
/* This arch exports wr functions, so include this for consistency checking */
#include "../proto-ext-whiterabbit/wr-api.h"
......
/*
* Copyright (C) 2014 CERN (www.cern.ch)
* Author: Alessandro Rubini
*
* Released according to GNU LGPL, version 2.1 or any later
*/
#include <ppsi/ppsi.h>
struct pp_argline pp_arch_arglines[] = {
GLOB_OPTION_INT("rx-drop", ARG_INT, NULL, rxdrop),
GLOB_OPTION_INT("tx-drop", ARG_INT, NULL, txdrop),
{}
};
......@@ -200,7 +200,7 @@ int pp_state_machine(struct pp_instance *ppi, uint8_t *packet, int plen)
int state, err = 0;
int msgtype;
if (plen) {
if (plen > 0) {
msgtype = packet[0] & 0xf;
pp_diag(ppi, frames, 1,
"RECV %02d bytes at %9d.%09d (type %x, %s)\n", plen,
......
#ifndef __ASSERT_H__
#define __ASSERT_H__
/*
* Both panic and assert loop over the console, re-printing the
* message, so you can connnect to a paniced node and see the message
* that caused the panic. assert_warn(condition) is once only, like
* warn_on(!condition) in the kernel.
*/
extern void panic(const char *fmt, ...)
__attribute__((format(printf,1,2)));
#define assert(cond, fmt, ...) \
if (CONFIG_HAS_ASSERT && !(cond)) \
__assert(__func__, __LINE__, 1 /* forever */, fmt, ## __VA_ARGS__)
#define assert_warn(cond, fmt, ...) \
if (CONFIG_HAS_ASSERT && !(cond)) \
__assert(__func__, __LINE__, 0 /* once */, fmt, ## __VA_ARGS__)
extern void __assert(const char *func, int line, int forever,
const char *fmt, ...)
__attribute__((format(printf, 4, 5)));
#ifdef CONFIG_ASSERT
# define CONFIG_HAS_ASSERT 1
#else
# define CONFIG_HAS_ASSERT 0
#endif
#endif /* __ASSERT_H__ */
......@@ -27,6 +27,12 @@
#undef ARRAY_SIZE
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
#ifdef CONFIG_WRPC_FAULTS
# define CONFIG_HAS_WRPC_FAULTS 1
#else
# define CONFIG_HAS_WRPC_FAULTS 0
#endif
/* We can't include pp-printf.h when building freestading, so have it here */
extern int pp_printf(const char *fmt, ...)
__attribute__((format(printf, 1, 2)));
......
#include <stdarg.h>
#include <ppsi/ppsi.h>
#include <ppsi/assert.h>
#if __STDC_HOSTED__
#include <unistd.h> /* bare archs have no sleep, but a sw loop */
#endif
void panic(const char *fmt, ...)
{
va_list args;
while (1) {
pp_printf("Panic: ");
va_start(args, fmt);
pp_vprintf(fmt, args);
va_end(args);
sleep(1);
}
}
void __assert(const char *func, int line, int forever,
const char *fmt, ...)
{
va_list args;
while (1) {
pp_printf("Assertion failed (%s:%i)", func, line);
if (fmt && fmt[0]) {
pp_printf(": ");
va_start(args, fmt);
pp_vprintf(fmt, args);
va_end(args);
} else {
pp_printf(".\n");
}
if (!forever)
break;
sleep(1);
}
}
......@@ -221,7 +221,7 @@ static struct pp_argname arg_mech[] = {
{"request-response", PP_E2E_MECH},
{"delay", PP_E2E_MECH},
{"e2e", PP_E2E_MECH},
#ifdef CONFIG_HAS_P2P
#if CONFIG_HAS_P2P == 1
{"peer-delay", PP_P2P_MECH},
{"pdelay", PP_P2P_MECH},
{"p2p", PP_P2P_MECH},
......
......@@ -136,5 +136,5 @@ int wr_calibration(struct pp_instance *ppi, unsigned char *pkt, int plen)
ppi->next_delay = wrp->wrStateTimeout;
return e;
return 0; /* ignore error */
}
......@@ -43,8 +43,6 @@ int wr_locked(struct pp_instance *ppi, unsigned char *pkt, int plen)
ppi->next_state = WRS_RESP_CALIB_REQ;
}
if (e != 0)
ppi->next_state = PPS_FAULTY;
ppi->next_delay = wrp->wrStateTimeout;
return e;
......
......@@ -43,8 +43,6 @@ int wr_m_lock(struct pp_instance *ppi, unsigned char *pkt, int plen)
ppi->next_state = WRS_CALIBRATION;
}
if (e != 0)
ppi->next_state = PPS_FAULTY;
ppi->next_delay = wrp->wrStateTimeout;
return e;
......
......@@ -49,8 +49,9 @@ int wr_present(struct pp_instance *ppi, unsigned char *pkt, int plen)
if (e == 0)
st_com_execute_slave(ppi);
else
ppi->next_state = PPS_FAULTY;
else {
/* nothing, just stay here again */
}
ppi->next_delay = WR_DSPOR(ppi)->wrStateTimeout;
......
......@@ -101,8 +101,7 @@ out:
ppi->next_state = PPS_LISTENING;
break;
case PP_SEND_ERROR:
goto out_fault;
/* fall through: a lost frame is not the end of the world */
case PP_SEND_NO_STAMP:
/* nothing, just keep the ball rolling */
e = 0;
......@@ -113,10 +112,5 @@ out:
ppi->next_delay = pp_next_delay_3(ppi,
PP_TO_ANN_SEND, PP_TO_SYNC_SEND, PP_TO_REQUEST);
return e;
out_fault:
ppi->next_state = PPS_FAULTY;
ppi->next_delay = 500; /* just a delay to releif the system */
return e;
}
......@@ -51,8 +51,9 @@ int pp_passive(struct pp_instance *ppi, unsigned char *pkt, int plen)
if (e == 0)
e = st_com_execute_slave(ppi);
if (e != 0)
ppi->next_state = PPS_FAULTY;
if (e != 0) {
/* ignore: a lost frame is not the end of the world */
}
ppi->next_delay = PP_DEFAULT_NEXT_DELAY_MS;
......
......@@ -87,7 +87,7 @@ int pp_slave(struct pp_instance *ppi, unsigned char *pkt, int plen)
goto out;
}
e = pp_lib_may_issue_request(ppi);
pp_lib_may_issue_request(ppi);
/*
* The management of messages is now table-driven
......@@ -100,8 +100,6 @@ int pp_slave(struct pp_instance *ppi, unsigned char *pkt, int plen)
pp_diag(ppi, frames, 1, "Ignored frame %i\n",
hdr->messageType);
}
if (e)
goto out;
/*
* This function, common to passive,listening etc,
......@@ -114,7 +112,7 @@ out:
case PP_SEND_OK: /* 0 */
break;
case PP_SEND_ERROR:
ppi->next_state = PPS_FAULTY;
/* ignore: a lost frame is not the end of the world */
break;
case PP_SEND_NO_STAMP:
/* nothing, just keep the ball rolling */
......
......@@ -7,8 +7,11 @@
#include <ppsi/ppsi.h>
#include "ptpdump.h"
#include <syscon.h> /* wrpc-sw */
#include <ptpd_netif.h> /* wrpc-sw */
int frame_rx_delay_us; /* set by faults.c */
/*
* we know we create one socket only in wrpc. The buffer size used to be
* 512. Let's keep it unchanged, because we might enqueue a few frames.
......@@ -57,6 +60,8 @@ static int wrpc_net_recv(struct pp_instance *ppi, void *pkt, int len,
struct wr_sockaddr addr;
sock = ppi->ch[PP_NP_EVT].custom;
got = ptpd_netif_recvfrom(sock, &addr, pkt, len, &wr_ts);
if (got <= 0)
return got;
if (t) {
t->secs = wr_ts.sec;
......@@ -69,17 +74,24 @@ static int wrpc_net_recv(struct pp_instance *ppi, void *pkt, int len,
/* wrpc-sw may pass this in USER_CFLAGS, to remove footprint */
#ifndef CONFIG_NO_PTPDUMP
/* The header is separate, so dump payload only */
if (got > 0 && pp_diag_allow(ppi, frames, 2))
if (pp_diag_allow(ppi, frames, 2))
dump_payloadpkt("recv: ", pkt, got, t);
#endif
if (CONFIG_HAS_WRPC_FAULTS && ppsi_drop_rx()) {
pp_diag(ppi, frames, 1, "Drop received frame\n");
return -2;
}
if (CONFIG_HAS_WRPC_FAULTS)
usleep(frame_rx_delay_us);
return got;
}
static int wrpc_net_send(struct pp_instance *ppi, void *pkt, int len,
int msgtype)
{
int snt;
int snt, drop;
struct wrpc_socket *sock;
struct wr_timestamp wr_ts;
struct wr_sockaddr addr;
......@@ -90,10 +102,22 @@ static int wrpc_net_send(struct pp_instance *ppi, void *pkt, int len,
[PP_P2P_MECH] = PP_PDELAY_MACADDRESS,
};
/*
* To fake a packet loss, we must corrupt the frame; we need
* to transmit it for real, if we want to get back our
* hardware stamp. Thus, remember if we drop, and use this info.
*/
if (CONFIG_HAS_WRPC_FAULTS)
drop = ppsi_drop_tx();
sock = ppi->ch[PP_NP_EVT].custom;
addr.ethertype = htons(ETH_P_1588);
memcpy(&addr.mac, macaddr[is_pdelay], sizeof(mac_addr_t));
if (CONFIG_HAS_WRPC_FAULTS && drop) {
addr.ethertype = 1;
addr.mac[0] = 0x22; /* pfilter uses mac; drop for nodes too */
}
snt = ptpd_netif_sendto(sock, &addr, pkt, len, &wr_ts);
......@@ -107,6 +131,11 @@ static int wrpc_net_send(struct pp_instance *ppi, void *pkt, int len,
__func__, snt, (long)t->secs,
(long)(t->scaled_nsecs >> 16));
}
if (CONFIG_HAS_WRPC_FAULTS && drop) {
pp_diag(ppi, frames, 1, "Drop sent frame\n");
return -2;
}
/* wrpc-sw may pass this in USER_CFLAGS, to remove footprint */
#ifndef CONFIG_NO_PTPDUMP
/* The header is separate, so dump payload only */
......
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