System designTroubleshooting

GigE camera on link local address: open it by IP from Linux

Why a GigE camera on a 169.254.x.x link local address opens by name but not by IP on Linux, and how to give the host interface a 169.254.0.0/16 address.

LumaSpec Vision9 min read Share on LinkedIn

On this page 9 sections
  1. 01The symptom you can reproduce
  2. 02Why the name works and the address does not
  3. 03Fix the host, not the camera
  4. 04Worked example: one camera, one NIC, the numbers
  5. 05Verify it worked
  6. 06Move the camera off link-local for production
  7. 07When the interface already has 169.254 and it still fails
  8. 08Checklist: camera on a link-local address
  9. 09Questions

You connected a new GigE camera straight into a Linux host, enumeration lists it with a 169.254.x.x address, and opening it by that address fails while opening it by name works. The camera is healthy and so is your code: the interface has no address in 169.254.0.0/16, so the kernel has no route to the camera and refuses the send before any packet leaves the machine. This troubleshooting guide traces the failure from the GigE Vision boot sequence down to the route table, gives the exact commands that put a link-local address on the NIC under NetworkManager, systemd-networkd or plain iproute2, and shows the addressing arithmetic that proves the repair. Ten minutes on the host beats an hour of swapping SDKs.

The symptom you can reproduce

Fresh camera, one shielded copper lead into a spare NIC, host side 192.168.1.1/24. Three commands tell the whole story:

# arv-tool-0.8
My-Cam (169.254.112.30)

# arv-tool-0.8 -a "169.254.112.30"
Can't connect to device at address '169.254.112.30'

# arv-tool-0.8 -n "My-Cam"
My-Cam        # opens, reads the GenICam XML, streams

The wildcard * behaves like the name while this camera is the only one connected. With debug output (-d all:3) the address attempt logs one discovery socket per interface, then Error: Error sending message: Invalid argument from the interface layer. That line appears immediately, not after a timeout: the stack rejected the send outright.

What happens before that refusal varies between stacks: some enumerate the camera, some enumerate nothing, and a third group enumerates it but cannot open it. For the wider tree — nothing enumerates at all, the wrong interface is selected, services are missing — start from Linux GigE Vision camera discovery troubleshooting.

The failure is generic to the GigE Vision protocol, not to one sensor or one SDK, and it shows up on the bench with any camera you unpack:

Area scan camerasHikrobot MV-CT0MG0060/R/NN/NN 6 MP Area Scan Camera, 3rd Gen., GigE, Mono, BASEMV-CT0MG0060/R/NN/NN
Sensor format
1/1.8"
Lens mount
C-mount
Interface
GigE
Resolution
6-10 MP
$909.00View partBuild a system with it

Why the name works and the address does not

Every GigE Vision camera climbs the same address ladder at boot: a configured persistent IP if one is set, otherwise DHCP, otherwise a self-assigned address somewhere in 169.254.0.0/16. A camera from the box has no persistent IP, and a bench link has no DHCP server, so it lands on link-local — which is why nearly every new camera enumerates at 169.254.x.x.

The 169.254.0.0/16 block is link-scoped: routers never carry it, and a Linux host transmits into it only from an interface that itself holds an address in the block. A NIC sitting on 192.168.1.1/24 gives the kernel neither a source address nor a route for 169.254.112.30.

Enumeration and opening travel different paths:

  • Discovery is a UDP broadcast to port 3956 on each interface's broadcast address. A broadcast crosses mismatched subnets on a direct copper link, and most camera stacks answer it, so the name lookup succeeds.
  • Opening by address is unicast: a packet addressed to 169.254.112.30. The socket is bound to 192.168.1.1, the kernel cannot pair that source with that destination, and the send is refused on the spot.

Whether a given camera answers a broadcast aimed at a foreign subnet varies between stacks, which is why some SDKs list it and others stay silent. None of them can open it by address until the host owns an address inside the block.

Fix the host, not the camera

  1. Identify the NIC and its connection name:
ip -br addr                # eth1 UP  192.168.1.1/24
nmcli connection show      # "Wired connection 1"
  1. Under NetworkManager, keep DHCP and turn link-local on:
nmcli connection modify "Wired connection 1" ipv4.method auto ipv4.link-local enabled
nmcli connection up "Wired connection 1"

On releases without that property, configure both addresses through the manual method:

nmcli connection modify "Wired connection 1" ipv4.method manual \
  ipv4.addresses "192.168.1.1/24, 169.254.100.1/16"
nmcli connection up "Wired connection 1"
  1. Under systemd-networkd, give the camera NIC its own .network file — no DHCP, link-local only:
[Match]
Name=eth1

[Network]
DHCP=no
LinkLocalAddressing=ipv4

Then run networkctl reload && networkctl reconfigure eth1. With DHCP=yes, networkd assigns the link-local address after DHCP yields nothing, which also works on a bench link.

  1. To prove the diagnosis in thirty seconds, skip persistence entirely:
sudo ip addr add 169.254.100.1/16 dev eth1

The address is live immediately and disappears at the next reboot, so nothing else on the host changes.

Pick the host address once and keep it: any value in the block that is not the camera's own, always with the /16 mask. A /24 mask on 169.254.100.0 would leave the camera's randomly drawn third octet outside your subnet and reproduce the original refusal.

Worked example: one camera, one NIC, the numbers

Camera fresh from the box, enumerating at 169.254.112.30. Host eth1 on 192.168.1.1/24. Before the fix:

ip route get 169.254.112.30
# either: via 10.0.0.1 dev eth0    (the corporate side takes it)
# or:     RTNETLINK answers: Network is unreachable

Add the address and check the maths:

network = address AND netmask 169.254.112.30 AND 255.255.0.0 = 169.254.0.0 169.254.100.1 AND 255.255.0.0 = 169.254.0.0 host part, camera: 112 x 256 + 30 = 28,702 host part, host: 100 x 256 + 1 = 25,601

Same network, distinct host parts — a legal pair. After the change:

ip route get 169.254.112.30
169.254.112.30 dev eth1 src 169.254.100.1

That single line is the whole repair: the kernel now has an output interface and a valid source. arv-tool-0.8 -a "169.254.112.30" returns the camera, and the name path behaves identically. Control packets flow on UDP 3956 from 169.254.100.1 to 169.254.112.30, both inside the block.

The /16 holds 65,534 usable addresses (2 to the 16th, minus network and broadcast), so a fixed 169.254.100.1 colliding with a camera's random pick is not a realistic event. Glance at the enumeration output before choosing anyway.

Verify it worked

Four checks, in this order:

  1. ip addr show eth1 lists inet 169.254.100.1/16 beside 192.168.1.1/24.
  2. ip route get 169.254.112.30 names dev eth1 with src 169.254.100.1.
  3. arv-tool-0.8 -a "169.254.112.30" prints the camera and its feature tree.
  4. A short acquisition runs with frames arriving and no resend storm.

If the open now succeeds but streaming misbehaves, addressing was the only routing problem and the next suspects are host-side: set the GigE camera packet size before starting acquisition, and on embedded boards the GigE camera buffer timeouts fixed by socket buffer tuning. A local firewall that drops UDP 3956 produces a near-identical stall at the open step; the firewall case where ping works but discovery fails lists the ports to open.

Link-local is a bench convenience, not a commissioning plan. In a running cell, put the camera on a subnet you control:

  1. Open the camera by name once.
  2. In the GenICam feature tree, set GevCurrentIPConfigurationPersistentIP to true, GevPersistentIPAddress to 192.168.1.10 and GevPersistentSubnetMask to 255.255.255.0. Set GevPersistentDefaultGateway only if the controller lives off that link.
  3. Power-cycle. The camera boots straight to the persistent address, and the host needs no link-local address at all.

A small DHCP server on the camera NIC reaches the same outcome through the second rung of the boot ladder. The GigE Vision protocol also defines a broadcast force-IP packet that overrides the address until the next power cycle — useful to recover a camera parked on a forgotten subnet, but it is a rescue move, not configuration.

When the interface already has 169.254 and it still fails

The fix above covers the common case. If ip addr already shows a 169.254.x.y/16 address on the right NIC and the open still fails:

  1. Several NICs in the host: the SDK binds one socket per interface and may pick the wrong one for this camera. The duplicate PoE camera discovery diagnosis of host interfaces walks the split.
  2. Firewall again: UDP 3956 blocked on the camera zone looks exactly like a routing gap from the SDK side.
  3. Stale forced address: a force-IP from an earlier set-up survives until power cycle, so the address you type is not the address the camera holds. Enumerate with the wildcard and read the truth.
  4. Camera at 0.0.0.0: it is still waiting on DHCP. With no server on the link, one power cycle moves it onto link-local.
  • ip -br addr — the camera NIC carries a 169.254.x.y/16 address alongside its normal one.
  • ip route get <camera-address> — routes via that NIC with a 169.254 source.
  • Firewall — UDP 3956 open on the camera zone.
  • Enumeration — wildcard first, note the real address, then open by address.
  • Production — persistent IP set, gateway only where needed, power cycle done.
  • Lead — seated both ends, link LEDs up; no address repairs a dead cable.

A high-flex lead is the one to standardize on when the camera rides a moving carrier:

Cables3 m GigE camera cable, high-flex (drag chain), screw locks (LS-CBL-0199)LS-CBL-0199$54.00View partBuild a system with it

With the host fixed, adding the next camera becomes configuration instead of debugging. Run the camera finder for the sensor you need, or start at the camera step of the system configurator. Every GigE area scan camera climbs the same address ladder on first boot, so keep the link-local enable in your imaging-host build script. For a cell with many cameras and one controller, bring the NIC and address plan to the contact page and the applications team will review it with you.

Build the whole station

The configurator matches a camera, lens, light, light controller and cables to each other, step by step, and lists only parts that fit what you already picked.

Start with the camera

Questions

Why does a brand-new GigE camera always enumerate at a 169.254.x.x address?

The GigE Vision boot ladder tries a configured persistent IP first, then DHCP, and falls back to a self-assigned address in 169.254.0.0/16 when no server answers. A camera from the box has no persistent IP, and an isolated bench link has no DHCP server, so it always lands on link-local. The address is drawn at random and can change across power cycles until you set a persistent IP.

Why does the same camera work on a Windows laptop with no configuration?

Windows enables automatic private IP addressing (APIPA) on every Ethernet interface by default, so the laptop quietly adds a 169.254.x.x address next to its configured one. Linux leaves IPv4 link-local off unless you enable it per interface, which is why identical camera and cable behave differently between the two hosts. Enable link-local on the Linux NIC and the difference disappears.

Which host address should I pick inside 169.254.0.0/16?

Any address from 169.254.1.0 through 169.254.254.255 that is not the camera's own and does not end in 0 or 255 — the working range RFC 3927 sets aside for link-local use. Always pair it with the /16 mask 255.255.0.0, never a /24, or the camera's randomly drawn third octet can fall outside your subnet and reproduce the original refusal. 169.254.100.1/16 is a safe bench choice.

Will enabling link-local disturb the 192.168.1.x addressing already on that NIC?

No. Linux holds several addresses per interface at once: enabling link-local adds one 169.254.x.x/16 address plus its link-scoped route and leaves the static or DHCP address untouched. Traffic for 192.168.1.0/24 keeps the existing address; traffic for 169.254.0.0/16 uses the new one. Only a mistyped /24 mask on the link-local address would disturb anything.

Do I still need to open UDP 3956 in the firewall after the fix?

Yes. GVCP control runs on UDP port 3956, and a local rule blocking it reproduces a near-identical symptom: the camera enumerates, then the open call stalls or fails. On a firewalled host, allow UDP 3956 in both directions on the camera zone, plus the ephemeral UDP range the camera uses for GVSP streaming, or frames will drop after a successful open.