# Nic

_Provium / Reference_

> A Nic userdata is a per-(bridge, vm) handle. Use it to read NIC counters, capture per-NIC pcap, or simulate link-down / link-up on a single attachment.

A Nic represents one virtual NIC: the binding between a VM and a Bridge. You get one from either side of that pair (`vm:nic(bridge_name)` or `bridge:nic(vm)`), and it gives you per-NIC observability and link control.

## Constructing

| Source | Returns |
|---|---|
| `vm:nic("bridge_name")` | NIC for the named bridge attachment. |
| `vm:nic("eth0")` | NIC for the Nth attached bridge sorted by bridge name (`eth<N>`, `enp0s<N>`, `ens<N>`). |
| `bridge:nic(vm)` | NIC for the (bridge, vm) pair. When `vm` is a userdata, the link-state ops drive QMP. |

The guest-name lookup (`eth0`) is deterministic per build but may not match the kernel's actual device-probe order on every distro. For portable tests, prefer `vm:nic("bridge_name")` and `bridge:nic(vm)`.

## Methods

### `nic:counters()`

Returns a table of per-NIC counters read from `/sys/class/net/<tap>/statistics/`. The counters are presented from the **guest's perspective**: the host's `tx_bytes` on the TAP is what the guest received, so it appears as `rx_bytes` in the table.

| Field | Description |
|---|---|
| `rx_bytes` | Bytes the guest received (host TAP's `tx_bytes`). |
| `tx_bytes` | Bytes the guest sent (host TAP's `rx_bytes`). |
| `rx_packets` | Packets received. |
| `tx_packets` | Packets sent. |
| `errors` | Sum of host TAP's `rx_errors` and `tx_errors`. |

Returns zeros when the host TAP isn't yet realised (VM not booted). If you need to assert a NIC has produced traffic, gate the read on `vm:state() == "booted"` or `wait_until` on a non-zero counter.

### `nic:capture()`

Spawn `tcpdump -i <tap>` on this NIC's host TAP interface. Returns a [Capture](/provium/reference/streams.md) stream. Errors if the VM hasn't been booted yet (the per-VM TAP doesn't exist):

```
nic:capture: vm `a` has no TAP on bridge `lan` (not booted?). Call lab:boot() / vm:boot() first.
```

The capture pins the bridge's `active_captures` counter, so `vm:snapshot()` can detect a live capture and refuse the snapshot (no half-captured pcap).

Compare with `bridge:capture()` which captures the whole bridge, not a single NIC.

### `nic:disconnect()`

Detach the NIC from the bridge **and** issue a QMP `set_link(false)` against the matching netdev so the guest sees a link-down event. Without a VM userdata at construction time (bare-string `bridge:nic("name")` form), the QMP step is skipped — the call is [graph-state only](/provium/writing-tests/bridges-and-impairments.md#declared-vs-realised).

### `nic:reconnect()`

Reverse of `:disconnect()`. Re-attaches the NIC and issues a `set_link(true)`.

### `nic:vm_name()` / `nic:bridge()`

Accessors. `:vm_name()` returns the VM's name; `:bridge()` returns the bridge's name.

## Example: link-down recovery

```lua
test("guest reconnects after link flap", function(t)
    local lan = provium:bridge("lan")
    local a   = provium:vm("a", "peios"):boot()
    local b   = provium:vm("b", "peios"):boot()
    lan:attach({a, b})
    a:run("ip addr add 10.0.0.1/24 dev eth0 && ip link set eth0 up")
    b:run("ip addr add 10.0.0.2/24 dev eth0 && ip link set eth0 up")

    -- Baseline.
    a:run("ping -c 1 -W 1 10.0.0.2"):assert_ok()

    local nic = a:nic("lan")
    nic:disconnect()
    -- Pings should fail now.
    local r = a:run("ping -c 1 -W 1 10.0.0.2")
    t:assert(not r:ok())

    nic:reconnect()
    -- And succeed after reconnect.
    a:run("ping -c 1 -W 1 10.0.0.2"):assert_ok()
end)
```

## See also

- [Bridge](/provium/reference/bridge.md) — bridge-wide controls (partition, impairments, capture).
- [Streams](/provium/reference/streams.md) — what `nic:capture()` returns.
- [Bridges and impairments](/provium/writing-tests/bridges-and-impairments.md) — patterns for using NIC and bridge handles together.

Related content:

- [Bridges and impairments](/provium/writing-tests/bridges-and-impairments.md)
- [Bridge](/provium/reference/bridge.md)
- [Streams](/provium/reference/streams.md)
