Page MenuHomeFreeBSD

D58940.id184421.diff
No OneTemporary

D58940.id184421.diff

diff --git a/share/man/man4/ice.4 b/share/man/man4/ice.4
--- a/share/man/man4/ice.4
+++ b/share/man/man4/ice.4
@@ -124,6 +124,8 @@
.It
.Sx IOVCTL OPTIONS
.It
+.Sx FAILURE INJECTION
+.It
.Sx SUPPORT
.It
.Sx SEE ALSO
@@ -1190,6 +1192,43 @@
.Pp
For more information on standard and mandatory parameters, see
.Xr iovctl.conf 5 .
+.Sh FAILURE INJECTION
+Kernels compiled with
+.Bd -ragged -offset indent
+.Cd "options DRIVER_FAILPOINTS"
+.Ed
+expose destructive, test-only driver fail points below
+.Va debug.fail_point.ice .
+Ordinary kernels omit these controls.
+.Pp
+Set
+.Va debug.fail_point.ice.device
+to the exact PF device name before a fail point can fire.
+An empty device selector disables every ICE fail point even if an individual
+point remains armed.
+For SR-IOV tests,
+.Va debug.fail_point.ice.iov.vf
+selects a PF-local VF index, and a value of -1 selects every VF on the chosen
+PF.
+.Pp
+List the available selectors and fail points with:
+.Bd -literal -offset indent
+sysctl -aN debug.fail_point.ice
+.Ed
+.Pp
+The individual points accept the syntax described by
+.Xr fail 9 .
+For example, the following injects one
+.Er EIO
+after allocating VF 0's VSI on
+.Li ice0 :
+.Bd -literal -offset indent
+sysctl debug.fail_point.ice.device=ice0
+sysctl debug.fail_point.ice.iov.vf=0
+sysctl debug.fail_point.ice.iov.add_after_vsi_alloc='1*return(5)'
+.Ed
+.Pp
+Clear the individual point and device selector after each destructive test.
.Sh SUPPORT
For general information and support, go to the Intel support website at:
.Lk http://www.intel.com/support/ .
@@ -1202,7 +1241,8 @@
.Xr led 4 ,
.Xr vlan 4 ,
.Xr ifconfig 8 ,
-.Xr sysctl 8
+.Xr sysctl 8 ,
+.Xr fail 9
.Sh HISTORY
The
.Nm
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -435,6 +435,13 @@
#
options SYSCTL_DEBUG
+#
+# Compile test-only failure-injection hooks in supporting device drivers.
+# These expose destructive controls below debug.fail_point and are omitted
+# by default.
+#
+options DRIVER_FAILPOINTS
+
#
# Enable textdump by default, this disables kernel core dumps.
#
diff --git a/sys/conf/options b/sys/conf/options
--- a/sys/conf/options
+++ b/sys/conf/options
@@ -52,6 +52,7 @@
DDB_CAPTURE_MAXBUFSIZE opt_ddb.h
DDB_CTF opt_ddb.h
DDB_NUMSYM opt_ddb.h
+DRIVER_FAILPOINTS
EARLY_PRINTF opt_global.h
EXTERR_STRINGS opt_global.h
FULL_BUF_TRACKING opt_global.h
diff --git a/sys/dev/ice/ice_fault.h b/sys/dev/ice/ice_fault.h
new file mode 100644
--- /dev/null
+++ b/sys/dev/ice/ice_fault.h
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*-
+ * Copyright (c) 2026 BBOX.io
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _ICE_FAULT_H_
+#define _ICE_FAULT_H_
+
+#include "ice_opts.h"
+
+#ifdef DRIVER_FAILPOINTS
+
+#include <sys/fail.h>
+
+struct ice_softc;
+
+SYSCTL_DECL(_debug_fail_point_ice);
+
+bool ice_fail_point_device_matches(struct ice_softc *sc);
+
+#define ICE_FAIL_POINT_CODE_COND(_sc, _parent, _name, _cond, _flags, _code...) \
+ KFAIL_POINT_CODE_COND(_parent, _name, \
+ ice_fail_point_device_matches((_sc)) && (_cond), _flags, _code)
+#define ICE_FAIL_POINT_CODE(_sc, _parent, _name, _flags, _code...) \
+ ICE_FAIL_POINT_CODE_COND(_sc, _parent, _name, true, _flags, _code)
+
+#else /* !DRIVER_FAILPOINTS */
+
+#define ICE_FAIL_POINT_CODE_COND(_sc, _parent, _name, _cond, _flags, _code...) \
+ do { } while (0)
+#define ICE_FAIL_POINT_CODE(_sc, _parent, _name, _flags, _code...) \
+ do { } while (0)
+
+#endif /* DRIVER_FAILPOINTS */
+
+#endif /* _ICE_FAULT_H_ */
diff --git a/sys/dev/ice/ice_iov.c b/sys/dev/ice/ice_iov.c
--- a/sys/dev/ice/ice_iov.c
+++ b/sys/dev/ice/ice_iov.c
@@ -38,6 +38,7 @@
*/
#include "ice_iov.h"
+#include "ice_fault.h"
#include <net/if_vf_status.h>
@@ -49,6 +50,16 @@
#define ICE_VF_STATUS_MIRROR_INGRESS_ACTIVE "mirror-ingress-active"
#define ICE_VF_STATUS_MIRROR_EGRESS_ACTIVE "mirror-egress-active"
+#ifdef DRIVER_FAILPOINTS
+static SYSCTL_NODE(_debug_fail_point_ice, OID_AUTO, iov,
+ CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "ice SR-IOV fail points");
+
+static int ice_iov_fail_vf = -1;
+SYSCTL_INT(_debug_fail_point_ice_iov, OID_AUTO, vf,
+ CTLFLAG_RW | CTLFLAG_MPSAFE, &ice_iov_fail_vf, 0,
+ "VF eligible for ice SR-IOV fail points (-1 selects every VF)");
+#endif /* DRIVER_FAILPOINTS */
+
static struct ice_vf *ice_iov_get_vf(struct ice_softc *sc, int vf_num);
static void ice_iov_ready_vf(struct ice_softc *sc, struct ice_vf *vf);
static void ice_reset_vf(struct ice_softc *sc, struct ice_vf *vf,
@@ -94,6 +105,28 @@
static enum virtchnl_status_code ice_iov_err_to_virt_err(int ice_err);
static int ice_vf_validate_mac(struct ice_vf *vf, const uint8_t *addr);
+#ifdef DRIVER_FAILPOINTS
+static bool
+ice_iov_fail_vf_matches(uint16_t vfnum)
+{
+ return (ice_iov_fail_vf == -1 || ice_iov_fail_vf == vfnum);
+}
+#endif
+
+#define ICE_IOV_FAIL_POINT(_sc, _vfnum, _name, _error, _label) do { \
+ ICE_FAIL_POINT_CODE_COND(_sc, _debug_fail_point_ice_iov, _name, \
+ ice_iov_fail_vf_matches((_vfnum)), \
+ FAIL_POINT_NONSLEEPABLE, { \
+ (_error) = RETURN_VALUE; \
+ if ((_error) <= 0) \
+ (_error) = EIO; \
+ device_printf((_sc)->dev, \
+ "injecting VF %u failure at %s: %d\n", \
+ (unsigned int)(_vfnum), #_name, (_error)); \
+ goto _label; \
+ }); \
+} while (0)
+
/**
* ice_iov_attach - Initialize SR-IOV PF host support
* @sc: device softc structure
@@ -247,6 +280,8 @@
return (ENOMEM);
vf->vsi = vsi;
vsi->vf_num = vfnum;
+ ICE_IOV_FAIL_POINT(sc, vfnum, add_after_vsi_alloc, error,
+ release_vsi);
vf_num_queues = nvlist_get_number(params, "num-queues");
/* Validate and clamp value if invalid */
@@ -266,6 +301,8 @@
/* Reserve VF queue allocation from PF queues */
ice_alloc_vsi_qmap(vsi, vf_num_queues, vf_num_queues);
vsi->num_tx_queues = vsi->num_rx_queues = vf_num_queues;
+ ICE_IOV_FAIL_POINT(sc, vfnum, add_after_queue_maps, error,
+ release_vsi);
/* Assign Tx queues from PF space */
error = ice_resmgr_assign_scattered(&sc->tx_qmgr, vsi->tx_qmap,
@@ -275,6 +312,8 @@
ice_err_str(error));
goto release_vsi;
}
+ ICE_IOV_FAIL_POINT(sc, vfnum, add_after_tx_reservation, error,
+ release_vsi);
/* Assign Rx queues from PF space */
error = ice_resmgr_assign_scattered(&sc->rx_qmgr, vsi->rx_qmap,
@@ -284,6 +323,8 @@
ice_err_str(error));
goto release_vsi;
}
+ ICE_IOV_FAIL_POINT(sc, vfnum, add_after_rx_reservation, error,
+ release_vsi);
vsi->max_frame_size = ICE_MAX_FRAME_SIZE;
@@ -301,6 +342,8 @@
txq->me = i;
txq->vsi = vsi;
}
+ ICE_IOV_FAIL_POINT(sc, vfnum, add_after_tx_queue_memory, error,
+ free_txqs);
/* Allocate queue structure memory */
vsi->rx_queues = (struct ice_rx_queue *)
@@ -316,6 +359,8 @@
rxq->me = i;
rxq->vsi = vsi;
}
+ ICE_IOV_FAIL_POINT(sc, vfnum, add_after_rx_queue_memory, error,
+ free_rxqs);
/* Allocate space to store the IRQ vector data */
vf->num_irq_vectors = vf_num_queues + 1;
@@ -329,6 +374,8 @@
error = ENOMEM;
goto free_rxqs;
}
+ ICE_IOV_FAIL_POINT(sc, vfnum, add_after_tx_irq_memory, error,
+ free_txirqvs);
vf->rx_irqvs = (struct ice_irq_vector *)
malloc(sizeof(struct ice_irq_vector) * (vf->num_irq_vectors),
M_ICE, M_NOWAIT);
@@ -339,6 +386,8 @@
error = ENOMEM;
goto free_txirqvs;
}
+ ICE_IOV_FAIL_POINT(sc, vfnum, add_after_rx_irq_memory, error,
+ free_rxirqvs);
/* Assign VF interrupts from PF space */
if (!(vf->vf_imap =
@@ -348,12 +397,16 @@
error = ENOMEM;
goto free_rxirqvs;
}
+ ICE_IOV_FAIL_POINT(sc, vfnum, add_after_imap_memory, error,
+ free_imap);
error = ice_resmgr_assign_contiguous(&sc->dev_imgr, vf->vf_imap, vf->num_irq_vectors);
if (error) {
device_printf(dev, "Unable to assign VF-%d interrupt mapping: %s\n",
vfnum, ice_err_str(error));
goto free_imap;
}
+ ICE_IOV_FAIL_POINT(sc, vfnum, add_after_imap_reservation, error,
+ release_imap);
if (nvlist_exists_binary(params, "mac-addr")) {
mac = nvlist_get_binary(params, "mac-addr", &size);
@@ -388,6 +441,8 @@
vfnum, ice_err_str(error));
goto release_imap;
}
+ ICE_IOV_FAIL_POINT(sc, vfnum, add_after_vsi_init, error,
+ release_imap);
/* Add the broadcast address */
error = ice_add_vsi_mac_filter(vsi, broadcastaddr);
@@ -396,6 +451,8 @@
vfnum, ice_err_str(error));
goto release_imap;
}
+ ICE_IOV_FAIL_POINT(sc, vfnum, add_after_broadcast_filter, error,
+ release_imap);
atomic_set_32(&vf->vf_flags, VF_FLAG_ENABLED);
ice_iov_ready_vf(sc, vf);
@@ -698,6 +755,8 @@
vf = ice_iov_get_vf(sc, vsi->vf_num);
atomic_clear_32(&vf->vf_flags, VF_FLAG_INITIALIZED);
atomic_set_32(&vf->vf_flags, VF_FLAG_REBUILD_FAILED);
+ ICE_IOV_FAIL_POINT(sc, vf->vf_num, rebuild_before_initialize, error,
+ fail);
/* A new hardware VSI starts a new raw statistics epoch. */
accumulated_stats = vsi->hw_stats.cur;
@@ -722,6 +781,11 @@
atomic_clear_32(&vf->vf_flags, VF_FLAG_REBUILD_FAILED);
ice_iov_ready_vf(sc, vf);
return (0);
+
+#ifdef DRIVER_FAILPOINTS
+fail:
+ return (error);
+#endif /* DRIVER_FAILPOINTS */
}
/**
@@ -1906,6 +1970,14 @@
struct ice_hw *hw = &sc->hw;
vqs = (struct virtchnl_queue_select *)msg_buf;
+ ICE_FAIL_POINT_CODE_COND(sc, _debug_fail_point_ice_iov,
+ get_stats_bad_vsi, ice_iov_fail_vf_matches(vf->vf_num),
+ FAIL_POINT_NONSLEEPABLE, {
+ vqs->vsi_id = vsi->idx + 1;
+ device_printf(sc->dev,
+ "injecting invalid GET_STATS VSI ID for VF %u\n",
+ (unsigned int)vf->vf_num);
+ });
if (vqs->vsi_id != vsi->idx) {
device_printf(sc->dev,
diff --git a/sys/dev/ice/ice_lib.c b/sys/dev/ice/ice_lib.c
--- a/sys/dev/ice/ice_lib.c
+++ b/sys/dev/ice/ice_lib.c
@@ -42,6 +42,7 @@
#include "ice_lib.h"
#include "ice_iflib.h"
+#include "ice_fault.h"
#ifdef PCI_IOV
#include "ice_iov.h"
#endif
@@ -62,6 +63,33 @@
*/
MALLOC_DEFINE(M_ICE, "ice", "Intel(R) 100Gb Network Driver lib allocations");
+#ifdef DRIVER_FAILPOINTS
+
+/*
+ * ICE fail points are global, but only the selected PF may trigger them. An
+ * empty selector disables every point even if a stale failpoint setting
+ * remains armed.
+ */
+SYSCTL_NODE(_debug_fail_point, OID_AUTO, ice,
+ CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "ice driver fail points");
+
+static char ice_fail_device[32];
+SYSCTL_STRING(_debug_fail_point_ice, OID_AUTO, device,
+ CTLFLAG_RW | CTLFLAG_MPSAFE, ice_fail_device,
+ sizeof(ice_fail_device), "device eligible for ice fail points");
+
+bool
+ice_fail_point_device_matches(struct ice_softc *sc)
+{
+ const char *nameunit;
+
+ nameunit = device_get_nameunit(sc->dev);
+ return (ice_fail_device[0] != '\0' && nameunit != NULL &&
+ strcmp(nameunit, ice_fail_device) == 0);
+}
+
+#endif /* DRIVER_FAILPOINTS */
+
/*
* Helper function prototypes
*/
diff --git a/sys/dev/ice/ice_opts.h b/sys/dev/ice/ice_opts.h
--- a/sys/dev/ice/ice_opts.h
+++ b/sys/dev/ice/ice_opts.h
@@ -43,5 +43,6 @@
#include "opt_inet.h"
#include "opt_inet6.h"
#include "opt_rss.h"
+#include "opt_driver_failpoints.h"
#endif
diff --git a/sys/modules/ice/Makefile b/sys/modules/ice/Makefile
--- a/sys/modules/ice/Makefile
+++ b/sys/modules/ice/Makefile
@@ -8,6 +8,7 @@
# Option headers
SRCS += opt_inet.h opt_inet6.h opt_rss.h opt_iflib.h
+SRCS += opt_driver_failpoints.h
# Core source
SRCS += ice_lib.c ice_osdep.c ice_resmgr.c ice_strings.c

File Metadata

Mime Type
text/plain
Expires
Sat, Aug 22, 11:04 AM (9 h, 7 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
37055660
Default Alt Text
D58940.id184421.diff (12 KB)

Event Timeline