# Using and testing the ports in Linux
This page applies to both Linux flows ([PetaLinux](petalinux) and [Yocto](yocto)). It shows how
to identify the Ethernet FMC Max ports, bring them up, check the link, and measure throughput
against a PC. The commands are shown for the Yocto image, which logs in as the non-root
`amd-edf` user and therefore uses `sudo`; in PetaLinux the same commands work (drop `sudo` when
logged in as root).
## What you need
* The board booted into Linux with the [Ethernet FMC Max] fitted (see [PetaLinux](petalinux)
or [Yocto](yocto)).
* A UART terminal on the board's USB-UART (115200 baud, 8N1).
* One or more Ethernet cables from the FMC ports to a PC with a Gigabit Ethernet NIC, or to a
switch/router on the same network as the PC.
* `iperf3` on the PC (`sudo apt install iperf3` on Ubuntu/Debian; Windows builds are available
from the iperf3 project). `iperf3`, `ethtool` and `phytool` are already in the board images.
## Identify the ports
Linux renames the network interfaces to predictable `endN` names early in boot (`renamed from
ethN` in the kernel log). The `N` is assigned in probe order and **does not follow the FMC port
number**, and it differs between targets and between the PetaLinux and Yocto images. The
reliable way to identify a port is its MAC address, its controller base address, or its PHY
address in the kernel log:
```
ip -br link
dmesg | grep -E "axienet|macb" | grep -E "renamed|PHY \["
```
| Ethernet FMC Max port | MAC address | PHY in the kernel log |
|-----------------------|---------------------|--------------------------------|
| Port 0 | `00:0a:35:00:01:22` | `axienet-:01` |
| Port 1 | `00:0a:35:00:01:23` | `axienet-:03` |
| Port 2 | `00:0a:35:00:01:24` | `axienet-:0c` |
| Port 3 | `00:0a:35:00:01:25` | `axienet-:0f` |
`` is the address of `axi_ethernet_0`, because all four PHYs sit on its MDIO bus. The
board's own RJ45 (a PS GEM, driver `macb`) also appears in the list.
Example from the Yocto image on a ZCU106 (`zcu106_hpc0`), cables on FMC ports 0 and 3 and on the
board's RJ45:
```
$ ip -br link | grep ^e
end4 UP 00:0a:35:06:21:07
end3 UP 00:0a:35:00:01:22
end0 DOWN 00:0a:35:00:01:23
end1 DOWN 00:0a:35:00:01:24
end2 UP 00:0a:35:00:01:25
$ dmesg | grep "PHY \["
macb ff0e0000.ethernet end4: PHY [ff0e0000.ethernet-ffffffff:0c] driver [TI DP83867] (irq=POLL)
xilinx_axienet a0000000.ethernet end3: PHY [axienet-a0000000:01] driver [TI DP83867] (irq=POLL)
xilinx_axienet a0080000.ethernet end0: PHY [axienet-a0000000:03] driver [TI DP83867] (irq=POLL)
xilinx_axienet a00c0000.ethernet end1: PHY [axienet-a0000000:0c] driver [TI DP83867] (irq=POLL)
xilinx_axienet a0100000.ethernet end2: PHY [axienet-a0000000:0f] driver [TI DP83867] (irq=POLL)
```
With the Yocto images the four-port Zynq UltraScale+ targets (ZCU102 HPC0/HPC1, ZCU106) come up
with this mapping:
| Interface | Device |
|-----------|--------------------------------------------|
| `end3` | Ethernet FMC Max port 0 (`a0000000`) |
| `end0` | Ethernet FMC Max port 1 (`a0080000`) |
| `end1` | Ethernet FMC Max port 2 (`a00c0000`) |
| `end2` | Ethernet FMC Max port 3 (`a0100000`) |
| `end4` | Board RJ45 (PS GEM3, `ff0e0000`) |
and on the ZCU104 (one FMC port) `end0` is FMC port 0 and `end1` is the board RJ45. For the
PetaLinux mapping see [Port configurations](petalinux.md#port-configurations). On other targets,
use the commands above.
## Bring a port up
### DHCP
In the **Yocto** image every Ethernet interface is managed by `systemd-networkd` and requests a
DHCP address as soon as it has a link: plug the cable into a network with a DHCP server and the
address appears in `ip -br addr`. In **PetaLinux**, request an address by hand:
```
sudo udhcpc -i end3
```
### Static IP address
For a direct cable to a PC (no DHCP server), give the board port and the PC NIC addresses on the
same subnet, for example board `192.168.10.10/24`, PC `192.168.10.1/24`:
```
sudo ip link set end3 up
sudo ip addr add 192.168.10.10/24 dev end3
ip -br addr show end3
```
If you use several ports at the same time, see
[Multiple ports on one network](#multiple-ports-on-one-network) below.
## Check the link
`ethtool` shows the negotiated speed and the link state:
```
$ sudo ethtool end3 | grep -E 'Speed|Duplex|Auto-negotiation|Link detected'
Speed: 1000Mb/s
Duplex: Full
Auto-negotiation: on
Link detected: yes
```
The kernel also logs every link change:
```
xilinx_axienet a0000000.ethernet end3: Link is Up - 1Gbps/Full - flow control off
```
`phytool` reads the PHY registers directly over MDIO. Pass the interface name and the PHY's MDIO
address (1, 3, 12 or 15 for ports 0 to 3); for example, to decode the IEEE registers of the
port 0 PHY:
```
sudo phytool print end3/1
```
## Speed negotiation
The DP83867 PHYs and the tri-mode MACs support 10, 100 and 1000 Mb/s, full and half duplex, and
negotiate the speed with the link partner automatically (the AXI Ethernet core follows the speed
the PHY reports over SGMII). To test a lower speed, restrict what the port advertises and let it
re-negotiate:
```
sudo ethtool -s end3 speed 100 duplex full autoneg on # advertise 100 Mb/s only
sudo ethtool end3 | grep Speed
sudo ethtool -s end3 speed 1000 duplex full autoneg on # back to 1 Gb/s
```
The link partner must support the speed you select; the result is visible in the `Link is Up`
kernel message and in `ethtool`.
## Ping
```
ping -c 5 -I end3 192.168.10.1
```
`-I` makes the ping leave through that interface, which matters when several ports are up.
## Throughput with iperf3
Start an iperf3 server on the PC:
```
iperf3 -s
```
Then, on the board, run a 10 second test in each direction through the port under test
(`--bind-dev` forces the traffic through that interface):
```
iperf3 -c --bind-dev end3 -t 10 # board transmits
iperf3 -c --bind-dev end3 -t 10 -R # board receives
```
The relevant figure is the `receiver` line at the end of each run. The table below lists
results measured with the Yocto images: one TCP stream, MTU 1500, link partner a PC with a
Gigabit Ethernet NIC.
| Target | Port | Board transmits (Mbit/s) | Board receives (Mbit/s) |
|---------------|---------------------------|--------------------------|-------------------------|
| `zcu102_hpc0` | FMC port 0 | 941 | 886 |
| `zcu102_hpc0` | FMC port 3 | 941 | 919 |
| `zcu102_hpc1` | FMC port 0 | 941 | 934 |
| `zcu102_hpc1` | FMC port 3 | 941 | 923 |
| `zcu104` | FMC port 0 | 941 | 851 |
| `zcu106_hpc0` | FMC port 0 | 941 | 914 |
| `zcu106_hpc0` | FMC port 3 | 941 | 864 |
| all of these | Board RJ45 (PS GEM3) | 941 | 934 |
941 Mbit/s is the maximum TCP throughput of Gigabit Ethernet at MTU 1500, so transmit runs at
line rate. The receive figure varies more from board to board and run to run; expect roughly
850 to 935 Mbit/s for a single stream. Pings showed no packet loss on any port. Lower results
usually come from the PC side (NIC, power saving, other traffic) or from a link that
negotiated below 1 Gb/s.
## Multiple ports on one network
When two or more ports are connected to the **same** subnet, Linux may answer ARP requests and
send replies through whichever interface it prefers, so traffic does not necessarily use the
port you intend. Either:
* bind each test to its interface (`ping -I endN`, `iperf3 --bind-dev endN`) and check the
per-interface counters (`ip -s link show endN`) to confirm the traffic went through the port; or
* give each port its own subnet, e.g. `end3` = 192.168.1.10/24, `end0` = 192.168.2.10/24,
`end1` = 192.168.3.10/24, `end2` = 192.168.4.10/24, with a matching PC NIC on each.
## If a port does not work
See [Troubleshooting](troubleshooting.md#ports-not-working).
[Ethernet FMC Max]: https://docs.opsero.com/op080/datasheet/overview/