diff options
-rw-r--r-- | src/config/fault.h | 19 | ||||
-rw-r--r-- | src/config/general.h | 1 | ||||
-rw-r--r-- | src/core/fault.c | 53 | ||||
-rw-r--r-- | src/include/ipxe/errfile.h | 1 | ||||
-rw-r--r-- | src/include/ipxe/fault.h | 32 | ||||
-rw-r--r-- | src/net/netdevice.c | 12 |
6 files changed, 110 insertions, 8 deletions
diff --git a/src/config/fault.h b/src/config/fault.h new file mode 100644 index 00000000..a05aecd5 --- /dev/null +++ b/src/config/fault.h @@ -0,0 +1,19 @@ +#ifndef CONFIG_FAULT_H +#define CONFIG_FAULT_H + +/** @file + * + * Fault injection + * + */ + +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + +#include <config/defaults.h> + +/* Drop every N transmitted or received network packets */ +#define NETDEV_DISCARD_RATE 0 + +#include <config/local/fault.h> + +#endif /* CONFIG_FAULT_H */ diff --git a/src/config/general.h b/src/config/general.h index 9a5fbca9..35a9030e 100644 --- a/src/config/general.h +++ b/src/config/general.h @@ -156,7 +156,6 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); * */ -#define NETDEV_DISCARD_RATE 0 /* Drop every N packets (0=>no drop) */ #undef BUILD_SERIAL /* Include an automatic build serial * number. Add "bs" to the list of * make targets. For example: diff --git a/src/core/fault.c b/src/core/fault.c new file mode 100644 index 00000000..91289fde --- /dev/null +++ b/src/core/fault.c @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + * + * You can also choose to distribute this program under the terms of + * the Unmodified Binary Distribution Licence (as given in the file + * COPYING.UBDL), provided that you have satisfied its requirements. + */ + +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + +#include <stdlib.h> +#include <errno.h> +#include <ipxe/fault.h> + +/** @file + * + * Fault injection + * + */ + +/** + * Inject fault with a specified probability + * + * @v rate Reciprocal of fault probability (must be non-zero) + * @ret rc Return status code + */ +int inject_fault_nonzero ( unsigned int rate ) { + + /* Do nothing unless we want to inject a fault now */ + if ( ( random() % rate ) != 0 ) + return 0; + + /* Generate error number here so that faults can be injected + * into files that don't themselves have error file + * identifiers (via errfile.h). + */ + return -EFAULT; +} diff --git a/src/include/ipxe/errfile.h b/src/include/ipxe/errfile.h index b665f490..6553cd87 100644 --- a/src/include/ipxe/errfile.h +++ b/src/include/ipxe/errfile.h @@ -68,6 +68,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #define ERRFILE_fbcon ( ERRFILE_CORE | 0x001c0000 ) #define ERRFILE_ansicol ( ERRFILE_CORE | 0x001d0000 ) #define ERRFILE_ansicoldef ( ERRFILE_CORE | 0x001e0000 ) +#define ERRFILE_fault ( ERRFILE_CORE | 0x001f0000 ) #define ERRFILE_eisa ( ERRFILE_DRIVER | 0x00000000 ) #define ERRFILE_isa ( ERRFILE_DRIVER | 0x00010000 ) diff --git a/src/include/ipxe/fault.h b/src/include/ipxe/fault.h new file mode 100644 index 00000000..32aa0648 --- /dev/null +++ b/src/include/ipxe/fault.h @@ -0,0 +1,32 @@ +#ifndef _IPXE_FAULT_H +#define _IPXE_FAULT_H + +/** @file + * + * Fault injection + * + */ + +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + +#include <config/fault.h> + +extern int inject_fault_nonzero ( unsigned int rate ); + +/** + * Inject fault with a specified probability + * + * @v rate Reciprocal of fault probability (zero for no faults) + * @ret rc Return status code + */ +static inline __attribute__ (( always_inline )) int +inject_fault ( unsigned int rate ) { + + /* Force dead code elimination in non-fault-injecting builds */ + if ( rate == 0 ) + return 0; + + return inject_fault_nonzero ( rate ); +} + +#endif /* _IPXE_FAULT_H */ diff --git a/src/net/netdevice.c b/src/net/netdevice.c index f2821efe..889b00c1 100644 --- a/src/net/netdevice.c +++ b/src/net/netdevice.c @@ -39,6 +39,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include <ipxe/device.h> #include <ipxe/errortab.h> #include <ipxe/profile.h> +#include <ipxe/fault.h> #include <ipxe/vlan.h> #include <ipxe/netdevice.h> @@ -303,11 +304,8 @@ int netdev_tx ( struct net_device *netdev, struct io_buffer *iobuf ) { } /* Discard packet (for test purposes) if applicable */ - if ( ( NETDEV_DISCARD_RATE > 0 ) && - ( ( random() % NETDEV_DISCARD_RATE ) == 0 ) ) { - rc = -EAGAIN; + if ( ( rc = inject_fault ( NETDEV_DISCARD_RATE ) ) != 0 ) goto err; - } /* Transmit packet */ if ( ( rc = netdev->op->transmit ( netdev, iobuf ) ) != 0 ) @@ -457,14 +455,14 @@ static void netdev_tx_flush ( struct net_device *netdev ) { * function takes ownership of the I/O buffer. */ void netdev_rx ( struct net_device *netdev, struct io_buffer *iobuf ) { + int rc; DBGC2 ( netdev, "NETDEV %s received %p (%p+%zx)\n", netdev->name, iobuf, iobuf->data, iob_len ( iobuf ) ); /* Discard packet (for test purposes) if applicable */ - if ( ( NETDEV_DISCARD_RATE > 0 ) && - ( ( random() % NETDEV_DISCARD_RATE ) == 0 ) ) { - netdev_rx_err ( netdev, iobuf, -EAGAIN ); + if ( ( rc = inject_fault ( NETDEV_DISCARD_RATE ) ) != 0 ) { + netdev_rx_err ( netdev, iobuf, rc ); return; } |