Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,59 @@ jobs:
IFACE=$(ls /sys/bus/pci/devices/${DOMAIN}:${BUS}:02.0/net/ 2>/dev/null | head -1)
[ -n "$IFACE" ] && ethtool -T "$IFACE" || echo "WARN: No interface found"

- name: Smoke test — link up delay
if: steps.load.outputs.load_ok == 'true'
run: |
set -euo pipefail

BUS_NR=$(cat /sys/module/netdevsim/parameters/pci_bus_nr 2>/dev/null || echo 31)
BUS=$(printf "%02x" "$BUS_NR")
FAKE_ROOT=$(ls /sys/bus/pci/devices/ 2>/dev/null | grep ":${BUS}:00\.0" | head -1)
DOMAIN="${FAKE_ROOT:+$(echo "$FAKE_ROOT" | cut -d: -f1)}"
: "${DOMAIN:=0000}"

IFACE=$(ls /sys/bus/pci/devices/${DOMAIN}:${BUS}:02.0/net/ 2>/dev/null | head -1)
[ -z "$IFACE" ] && { echo "SKIP: no interface found"; exit 0; }

echo "Interface: $IFACE"

# Bring down first so we start from a known state
sudo ip link set "$IFACE" down
sleep 1

# Set a 3-second link-up delay via debugfs
DEBUGFS="/sys/kernel/debug/netdevsim/netdevsim1/ports/0/link_up_delay_ms"
echo 3000 | sudo tee "$DEBUGFS"
echo "link_up_delay_ms set to $(cat "$DEBUGFS")"

# Bring interface up — carrier should stay off
sudo ip link set "$IFACE" up
sleep 0.5
CARRIER=$(cat /sys/class/net/"$IFACE"/carrier 2>/dev/null || echo 0)
echo "Carrier immediately after up: $CARRIER"
[ "$CARRIER" -eq 0 ] || { echo "FAIL: carrier should be 0 during delay"; exit 1; }

# Wait for the delay to expire
sleep 4
CARRIER=$(cat /sys/class/net/"$IFACE"/carrier 2>/dev/null || echo 0)
echo "Carrier after delay: $CARRIER"
[ "$CARRIER" -eq 1 ] || { echo "FAIL: carrier should be 1 after delay"; exit 1; }

# Verify PTP clock is still readable
PHC_IDX=$(ethtool -T "$IFACE" 2>/dev/null | grep -oP 'PTP Hardware Clock: \K[0-9]+' || true)
if [ -n "$PHC_IDX" ]; then
echo "PHC index: $PHC_IDX"
# Read the clock via sysfs — confirms the PTP device works
cat /sys/class/nsim_ptp/nsim_ptp${PHC_IDX}/clock 2>/dev/null \
&& echo "OK: PTP clock readable" \
|| echo "WARN: could not read PTP clock via sysfs"
fi

# Verify hwtstamp config still works after link-up delay
ethtool -T "$IFACE" | grep -E "PTP Hardware Clock|hardware"

echo "=== LINK UP DELAY TEST PASSED ==="

- name: Cleanup
if: always()
run: |
Expand Down
5 changes: 5 additions & 0 deletions netdevsim/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -1394,6 +1394,11 @@ static int __nsim_dev_port_add(struct nsim_dev *nsim_dev, enum nsim_dev_port_typ
goto err_port_debugfs_exit;
}

if (nsim_dev_port_is_pf(nsim_dev_port))
debugfs_create_u32("link_up_delay_ms", 0600,
nsim_dev_port->ddir,
&nsim_dev_port->ns->link_up_delay_ms);

if (nsim_dev_port_is_vf(nsim_dev_port)) {
err = devl_rate_leaf_create(&nsim_dev_port->devlink_port,
nsim_dev_port, NULL);
Expand Down
40 changes: 40 additions & 0 deletions netdevsim/netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -400,8 +400,42 @@ static int nsim_set_ts_config(struct net_device *netdev,
}
return 0;
}
static void nsim_link_up_work(struct work_struct *work)
{
struct netdevsim *ns =
container_of(work, struct netdevsim, link_up_dwork.work);

netif_carrier_on(ns->netdev);
}

static int nsim_open(struct net_device *dev)
{
struct netdevsim *ns = netdev_priv(dev);
u32 delay = READ_ONCE(ns->link_up_delay_ms);

if (delay)
schedule_delayed_work(&ns->link_up_dwork,
msecs_to_jiffies(delay));
else
netif_carrier_on(dev);

return 0;
}

static int nsim_stop(struct net_device *dev)
{
struct netdevsim *ns = netdev_priv(dev);

cancel_delayed_work_sync(&ns->link_up_dwork);
netif_carrier_off(dev);

return 0;
}

static const struct net_device_ops nsim_netdev_ops = {
.ndo_start_xmit = nsim_start_xmit,
.ndo_open = nsim_open,
.ndo_stop = nsim_stop,
.ndo_set_rx_mode = nsim_set_rx_mode,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
Expand Down Expand Up @@ -525,6 +559,8 @@ static int nsim_init_netdevsim(struct netdevsim *ns)
ns->phc = phc;
ns->netdev->netdev_ops = &nsim_netdev_ops;

INIT_DELAYED_WORK(&ns->link_up_dwork, nsim_link_up_work);

err = nsim_udp_tunnels_info_create(ns->nsim_dev, ns->netdev);
if (err)
goto err_phc_destroy;
Expand All @@ -537,6 +573,8 @@ static int nsim_init_netdevsim(struct netdevsim *ns)
nsim_macsec_init(ns);
nsim_ipsec_init(ns);

netif_carrier_off(ns->netdev);

err = register_netdevice(ns->netdev);
if (err)
goto err_ipsec_teardown;
Expand Down Expand Up @@ -624,6 +662,8 @@ void nsim_destroy(struct netdevsim *ns)
struct net_device *dev = ns->netdev;
struct netdevsim *peer;

cancel_delayed_work_sync(&ns->link_up_dwork);

rtnl_lock();
peer = rtnl_dereference(ns->peer);
if (peer)
Expand Down
3 changes: 3 additions & 0 deletions netdevsim/netdevsim.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,9 @@ struct netdevsim {
struct nsim_ethtool ethtool;
struct netdevsim __rcu *peer;
struct kernel_hwtstamp_config tstamp_config;

u32 link_up_delay_ms;
struct delayed_work link_up_dwork;
};

struct netdevsim *
Expand Down
Loading