EVPN L2VNI
This guide stands up the smallest possible EVPN-VXLAN network: two leaf
switches that bridge a single L2 segment between two hosts. The result: a
host on leaf1 can ARP and ping a host on leaf2 as if they were on the
same wire, even though packets between them are encapsulated in VXLAN and
forwarded over a routed underlay.
What you'll build
| Underlay | OSPFv2 in area 0 over a single /30 link |
| Overlay | iBGP between the two loopbacks with the l2vpn-evpn AFI |
| L2 service | VXLAN VNI 10, host-facing ports enslaved to a Linux bridge |
The same recipe scales to a leaf-spine fabric — add more leafs, point each new iBGP session at a route reflector, and assign each customer L2 segment its own VNI. Two leafs is the minimum that demonstrates VTEP-to-VTEP MAC distribution; no third device is required.
Prerequisites
flockdinstalled onleaf1andleaf2. See Installation.- Each leaf has at least two interfaces: one toward the other leaf (the transit link) and one toward its locally-attached host.
- Each host runs a stock Linux that can
ping.
This example uses two interfaces per leaf, named with Debian's predictable
naming scheme: enp0s3 (transit, toward the other leaf) and enp0s4
(host-facing). Substitute whatever your environment uses.
Step 1 — Underlay IP addressing
Set the loopback IP and transit IP on each leaf.
On leaf1:
# ip addr add 10.0.1.1/32 dev lo
# ip link set lo up
# ip addr add 10.0.0.1/30 dev enp0s3
# ip link set enp0s3 up
On leaf2:
# ip addr add 10.0.2.1/32 dev lo
# ip link set lo up
# ip addr add 10.0.0.2/30 dev enp0s3
# ip link set enp0s3 up
The host-facing port joins the bridge in the next step, so it needs no IP on the leaf side — just bring it up on each leaf:
leaf1# ip link set enp0s4 up
leaf2# ip link set enp0s4 up
Assign IPs to the hosts themselves so they can talk over the L2 segment:
host-a# ip addr add 10.10.10.1/24 dev <port toward leaf1>
host-b# ip addr add 10.10.10.2/24 dev <port toward leaf2>
Step 2 — VXLAN and bridge
flockd does not create VXLAN or bridge interfaces — it learns about them
from the kernel and drives BGP-EVPN signalling for them. Create them with
ip link.
On leaf1:
# Create the VXLAN tunnel interface for L2VNI 10.
#
# id 10 L2VNI value
# local 10.0.1.1 our VTEP source IP (the loopback)
# dstport 4789 standard VXLAN UDP port
# nolearning EVPN drives MAC learning, not the data plane
ip link add vxlan10 type vxlan id 10 local 10.0.1.1 dstport 4789 nolearning
# Create the bridge that joins the VXLAN with the host-facing port.
ip link add br10 type bridge
# Enslave the VXLAN and the host-facing port to the bridge.
# enp0s4 here is the host-facing interface — substitute your own.
ip link set vxlan10 master br10
ip link set enp0s4 master br10
# Bring it all up.
ip link set vxlan10 up
ip link set br10 up
On leaf2:
# Create the VXLAN tunnel interface for L2VNI 10.
#
# id 10 L2VNI value
# local 10.0.2.1 our VTEP source IP (the loopback)
# dstport 4789 standard VXLAN UDP port
# nolearning EVPN drives MAC learning, not the data plane
ip link add vxlan10 type vxlan id 10 local 10.0.2.1 dstport 4789 nolearning
# Create the bridge that joins the VXLAN with the host-facing port.
ip link add br10 type bridge
# Enslave the VXLAN and the host-facing port to the bridge.
# enp0s4 here is the host-facing interface — substitute your own.
ip link set vxlan10 master br10
ip link set enp0s4 master br10
# Bring it all up.
ip link set vxlan10 up
ip link set br10 up
Step 3 — flockd configuration
flockd watches /etc/flockd/flockd.json and re-reads it on change, so no
daemon restart is needed — saving the file is enough.
/etc/flockd/flockd.json on leaf1:
{
"ospfv2": {
"vrfs": {
"default": {
"router_id": "10.0.1.1",
"areas": {
"0.0.0.0": {
"intfs": {
"lo": {},
"enp0s3": {
"hello_interval": 1,
"ospf_intf_type": "point-to-point"
}
}
}
}
}
}
},
"bgp": {
"asn": 65000,
"id": "10.0.1.1",
"vrfs": {
"default": {
"neighs": {
"10.0.2.1 10.0.1.1": {
"asn": 65000,
"afis": {
"l2vpn-evpn": {}
}
}
}
}
}
}
}
/etc/flockd/flockd.json on leaf2:
{
"ospfv2": {
"vrfs": {
"default": {
"router_id": "10.0.2.1",
"areas": {
"0.0.0.0": {
"intfs": {
"lo": {},
"enp0s3": {
"hello_interval": 1,
"ospf_intf_type": "point-to-point"
}
}
}
}
}
}
},
"bgp": {
"asn": 65000,
"id": "10.0.2.1",
"vrfs": {
"default": {
"neighs": {
"10.0.1.1 10.0.2.1": {
"asn": 65000,
"afis": {
"l2vpn-evpn": {}
}
}
}
}
}
}
}
The two configs are deliberately symmetric. Each one:
- Runs OSPFv2 area 0 on
lo(so the loopback is reachable from the peer) and on the transit interface. - Peers over iBGP from its loopback to the other leaf's loopback.
- Enables the
l2vpn-evpnAFI on that neighbor — the only address family needed for an L2VNI service. IPv4 underlay reachability is provided by OSPFv2, not by this BGP session.
Step 4 — Verify the control plane
flockc is the local gRPC client. Run the queries below on either leaf;
allow ten seconds or so for OSPF and BGP to converge.
Check both protocols are enabled:
flock@leaf1:~$ flockc sys overview
{..."enabled_protocols":["BGPv4","OSPFv2","Static"], ...}
OSPFv2 adjacency on enp0s3 reaches Full:
flock@leaf1:~$ flockc ospfv2 instances
[{"my_router":{"id":"10.0.1.1", ...}, ..., "stats":{...,"neigh_state_count":{...,"full":1}}}]
BGP neighbor reaches established:
flock@leaf1:~$ flockc bgp overview
{"id":"10.0.1.1","asn":65000, ...,"neighbor_summary":{"default":{"count":1,"established":1,"send_converged":1,"recv_converged":1}}}
Local NVE for VNI 10:
flock@leaf1:~$ flockc bgp evpn nve walk
[{"vni":10,"local_vtep_ip":"10.0.1.1","rd":"1:10.0.1.1:2","local_macs":[{"mac":[...],"ip":null,"seq":0}]}]
The single entry shows VNI 10, local VTEP IP 10.0.1.1, and the host's
MAC that the bridge has learned.
EVPN RIB:
flock@leaf1:~$ flockc bgp evpn rib walk
[{"prefix":{"rd":"1:10.0.1.1:2","net":{"route":{"Type2MacIp":{...,"mac_addr":[...]}}}}, ...},
{"prefix":{"rd":"1:10.0.1.1:2","net":{"route":{"Type3Imet":{...,"originating_router_ip":"10.0.1.1"}}}}, ...},
{"prefix":{"rd":"1:10.0.2.1:2","net":{"route":{"Type2MacIp":{...,"mac_addr":[...]}}}}, ...},
{"prefix":{"rd":"1:10.0.2.1:2","net":{"route":{"Type3Imet":{...,"originating_router_ip":"10.0.2.1"}}}}, ...}]
Four entries: a Type-3 (Inclusive Multicast Ethernet Tag, IMET) route from each VTEP — the announcement "I'm a VTEP for VNI 10" — and a Type-2 (MAC/IP advertisement) route for each locally-learned host MAC.
Step 5 — Generate traffic
Ping host-b from host-a:
host-a# ping -c 3 10.10.10.2
The first packet may be lost while ARP completes over VXLAN; subsequent packets succeed. This proves the data plane carries L2 traffic between the two hosts over the VXLAN tunnel using the MACs distributed by the EVPN control plane.
Cleanup
To tear down the VXLAN/bridge interfaces on each leaf:
# ip link delete br10
# ip link delete vxlan10
Remove the bgp and ospfv2 blocks from /etc/flockd/flockd.json to stop
the protocols.
Where to go next
- The BGP Component chapter covers the full EVPN configuration surface, including L3VNI for inter-subnet routing, Ethernet Segments for multi-homing, and route targets.
- For a leaf-spine fabric with a route reflector, replace each leaf's single
iBGP neighbor with a peering to the RR and configure
route_reflector_clienton the RR.