nsx-t logo

TGW EVPN/VXLAN Configuration

In a previous post I showed how to configure EVPN in NSX-T 3.0 with Juniper vMX, where the MP-BGP session originated from an Edge node through the T0 Gateway and VRFs were terminated on T0 and connected to T1. Today I’ll cover the next step in the evolution of that feature in VCF 9.1 — Distributed Transit Gateway with EVPN/VXLAN, where Edge nodes disappear from the picture entirely and N/S traffic flows directly from each ESX host through a VXLAN tunnel to an external BGW.

Below is the full configuration from my test environment using VyOS as the BGW and four ESXi hosts in the homelab.int domain.


What is DTGW with EVPN/VXLAN

DTGW (Distributed Transit Gateway) is a new option for connecting VCF to the physical network, available since VCF 9.0. VCF 9.1 adds support for EVPN/VXLAN as the uplink type instead of a traditional VLAN — the same BGP EVPN Type-5 mechanism familiar from physical fabrics like Arista, Cisco Nexus, and Juniper.

In short, the differences compared to the old NSX-T 3.0 approach:

NSX-T 3.0 / EVPN on T0 VCF 9.1 / DTGW EVPN/VXLAN
BGP EVPN originates from Edge node BGP EVPN originates from Route Controller (VNA)
Traffic: VM → Edge → BGW Traffic: VM → Host TEP → BGW (no Edge)
VXLAN tunnels terminate on Edge VXLAN tunnels terminate on each ESX host (TEP)
VRFs on T0 Gateway VRFs managed by DTGW + Route Controller
Edge node lifecycle required No Edge — no Edge lifecycle

The BGP EVPN Type-5 mechanism, Route Distinguisher, and Route Target work identically to what I described in the previous NSX-T EVPN post — only the tunnel termination point and management model change.

Requirements and limitations

Requirements Limitations in VCF 9.1
VCF 9.1 / NSX 9.1 No N-S Services (SNAT, LB) — planned for a future VCF release
BGW supporting BGP EVPN Type-5 (MP-BGP) L3 only (Route Type-5) — no L2 extension to the fabric
Underlay MTU min. 1600 (VXLAN overhead ~50 B) Access Mode: Private requires manual NAT on the BGW side
DVS port group required for the RC BGP peering network VyOS VRF table ID must be <1–200 if you plan to use NAT

Test environment

Element Value Note
Hosty ESXi ESXi11 – ESXi14 domain homelab.int
VLAN TEP Host 10.231.104.0/24 vmk Host TEP
VLAN BGP Peering 10.231.106.0/24 eth2.506 on VyOS
Peer VyOS (BGW) 10.231.106.1 BGP update-source
Peer RC (BGP VIP) 10.231.106.10 Route Controller floating IP
ASN VyOS 64515 BGP system-as
ASN Route Controller 64520 remote-as in VyOS
L3VNI / VNI 65000 tenant VRF identifier
VRF (VyOS) test table 65000
Subnet VM (External IP Block) 10.231.200.0/24 VM addresses in Public mode
RD VyOS (global) 64515:10
RD VyOS (VRF) 10.231.106.1:10 unique per-VRF
Export RT VyOS 64515:10
Import RT VyOS 64515:10 + 64520:10 also imports RT from RC
Export RT RC 64520:10 configured in NSX External Connectivity
Import RT RC 64515:10 imports RT from VyOS
Diagram

TGW home lab with vxlan

Connectivity check before configuration

Before deploying the RC it is worth verifying that the ESXi hosts can reach the address that will be used as the VXLAN source-address on the VyOS side. Ping from vmk0 and vmk1 to the BGW address:

[root@ESXi11:~] ping -I vmk10 10.231.106.1 -S vxlan
PING 10.231.106.1 (10.231.106.1): 56 data bytes
64 bytes from 10.231.106.1: icmp_seq=0 ttl=64 time=0.425 ms
64 bytes from 10.231.106.1: icmp_seq=1 ttl=64 time=0.424 ms
64 bytes from 10.231.106.1: icmp_seq=2 ttl=64 time=0.394 ms
3 packets transmitted, 3 packets received, 0% packet loss

[root@ESXi11:~] ping -I vmk11 10.231.106.1 -S vxlan
PING 10.231.106.1 (10.231.106.1): 56 data bytes
64 bytes from 10.231.106.1: icmp_seq=0 ttl=64 time=0.748 ms
64 bytes from 10.231.106.1: icmp_seq=1 ttl=64 time=0.820 ms
64 bytes from 10.231.106.1: icmp_seq=2 ttl=64 time=0.340 ms
3 packets transmitted, 3 packets received, 0% packet loss

No response at this stage means VXLAN tunnels will not work even if the BGP session is Established. We set the MTU to 9000; VXLAN adds ~50 B of overhead so there is plenty of headroom.


VyOS configuration (BGW)

Interfaces — VXLAN, bridge
# trunk VLAN on eth2, MTU 9000 (underlay)
set interfaces ethernet eth2 mtu '9000'
set interfaces ethernet eth2 vif 506 address '10.231.106.1/24'
set interfaces ethernet eth2 vif 504 address '10.231.104.1/24'

# VXLAN — VNI 65000 = tenant L3VNI
# source-address = BGP peering address
set interfaces vxlan vxlan65000 mtu '1500'
set interfaces vxlan vxlan65000 port '4789'
set interfaces vxlan vxlan65000 source-address '10.231.106.1'
set interfaces vxlan vxlan65000 vni '65000'

# bridge connects VXLAN to VRF "test"
set interfaces bridge br1 address '10.231.251.1/24'
set interfaces bridge br1 member interface vxlan65000
set interfaces bridge br1 vrf 'test'
Global BGP and Route Controller session
set protocols bgp system-as '64515'
set protocols bgp parameters router-id '10.231.106.1'
set protocols bgp parameters bestpath as-path multipath-relax

set protocols bgp address-family ipv4-unicast redistribute connected
set protocols bgp address-family ipv4-unicast redistribute static
set protocols bgp address-family ipv4-unicast import vrf 'test'

set protocols bgp address-family l2vpn-evpn advertise ipv4 unicast
set protocols bgp address-family l2vpn-evpn advertise-all-vni
set protocols bgp address-family l2vpn-evpn advertise-default-gw
set protocols bgp address-family l2vpn-evpn advertise-svi-ip
set protocols bgp address-family l2vpn-evpn default-originate ipv4

# sesja BGP z Route Controllerem (BGP VIP)
set protocols bgp neighbor 10.231.106.10 remote-as '64520'
set protocols bgp neighbor 10.231.106.10 update-source '10.231.106.1'
set protocols bgp neighbor 10.231.106.10 address-family ipv4-unicast default-originate
set protocols bgp neighbor 10.231.106.10 address-family ipv4-vpn route-server-client
set protocols bgp neighbor 10.231.106.10 address-family l2vpn-evpn soft-reconfiguration inbound

A few notes on the RC neighbor parameters:

  • default-originate — VyOS advertises the default route to the RC which then distributes it to ESX hosts
  • soft-reconfiguration inbound — reset BGP policy without dropping the session, useful during testing
  • route-server-client — facilitates route propagation between BGP clients through the RC
VRF “test”

Note — VyOS requires the table ID to be in the range 1–200 if you plan to use connection-mark for NAT from within the VRF. In this example I use table '65000' which works fine for routing, but consider changing it to e.g. 100 if you plan to add NAT later.

set vrf name test table '65000'
set vrf name test vni '65000'

set vrf name test protocols bgp system-as '64515'
set vrf name test protocols bgp parameters router-id '10.231.106.1'

set vrf name test protocols bgp address-family ipv4-unicast import vrf 'default'
set vrf name test protocols bgp address-family ipv4-unicast redistribute connected
set vrf name test protocols bgp address-family ipv4-unicast redistribute static

# RD and RT per-VRF — different from global!
set vrf name test protocols bgp address-family l2vpn-evpn rd '10.231.106.1:10'
set vrf name test protocols bgp address-family l2vpn-evpn route-target export '64515:10'
set vrf name test protocols bgp address-family l2vpn-evpn route-target import '64520:10'
set vrf name test protocols bgp address-family l2vpn-evpn route-target import '64515:10'
set vrf name test protocols bgp address-family l2vpn-evpn vni 65000

set vrf name test protocols bgp address-family l2vpn-evpn advertise ipv4 unicast
set vrf name test protocols bgp address-family l2vpn-evpn advertise-default-gw
set vrf name test protocols bgp address-family l2vpn-evpn advertise-svi-ip

Route Target logic:

Side Export RT Import RT Effect
VyOS (BGW) 64515:10 64515:10, 64520:10 VyOS imports routes from RC and its own
Route Controller (NSX) 64520:10 64515:10 RC imports routes from VyOS (default route and external networks)
VyOS configuration verification — VNI and bridge

After finishing the VyOS configuration, verify that the VNI is active and the bridge is properly set up:

vyos@vyos:~$ show bgp l2vpn evpn vni
Advertise Gateway Macip: Enabled
Advertise SVI Macip: Enabled
Advertise All VNI flag: Enabled
BUM flooding: Head-end replication
VXLAN flooding: Enabled
Number of L2 VNIs: 1
Number of L3 VNIs: 1
Flags: * - Kernel
  VNI        Type RD                    Import RT                 Export RT                 Tenant VRF
  65000      L2   10.231.106.1:2        64515:10                  64515:10                  default
* 65000      L3   10.231.106.1:10       64515:10, ...             64515:10                  test

# * = Kernel = active in kernel table (L3 VNI)
# L2 VNI without asterisk = bridge with no VPC subnet assigned (normal before adding a VM)
vyos@vyos:~$ show evpn vni 65000
VNI: 65000
  Type: L3
  Tenant VRF: test
  Vlan: 1
  Bridge: br1
  Local Vtep Ip: 10.231.106.1
  Vxlan-Intf: vxlan65000
  SVI-If: br1
  State: Up
  VNI Filter: none
  System MAC: c2:8f:db:73:82:3c
  Router MAC: c2:8f:db:73:82:3c
  L2 VNIs:

State: Up and Local Vtep Ip matching the source-address of the vxlan65000 interface — this is the address that will appear as the VTEP in BGP EVPN Type-5 advertisements to the RC.

vyos@vyos:~$ show bridge br1 detail
Interface br1 is up, line protocol is up
  Link ups:      13    last: 2026/05/07 10:28:54.00
  Link downs:    14    last: 2026/05/07 10:28:54.00
  vrf: test
  index 17 metric 0 mtu 1500 speed 0 txqlen 1000
  flags: <UP,LOWER_UP,BROADCAST,RUNNING,MULTICAST>
  Type: Ethernet
  HWaddr: c2:8f:db:73:82:3c   # this MAC == Router MAC in EVPN
  inet 10.231.251.1/24
  Interface Type Bridge
  Interface Slave Type Vrf
  Bridge VLAN-aware: no
  protodown: off

The MAC address of bridge br1 (c2:8f:db:73:82:3c) is used as the Router MAC in RT-5 advertisements. This is why the RD on the VyOS side and on the RC side must be different — each side needs its own unique values.


NSX / VCF configuration

Step 1 — Deploy the Route Controller

Navigate to NSX Manager –> Network –> EVPN –> Route Controllers and click Add Route Controller.

Add Route Controller

Fill in the details:

  • Route Controller Name: evpn-test
  • Node Form Factor: small

Click Add and fill in the Node 1 details — Management Network information for the virtual appliance:

evpn-router_controller

  • Management IP, Gateway, DNS — values from your mgmt network
  • Datastore, Cluster, Host — select from your vCenter

After filling in the node details click Next (I use a single node in the lab). On the next screen configure the BGP interface:

  • Port Group — DVS port group for VLAN 506 (BGP peering), must exist before deployment
  • Node 1 IP / Node 2 IP — node addresses on the BGP network
  • BGP Floating IP — 10.231.106.10 — active RC VIP, this address goes into VyOS as the neighbor
  • Prefix length — /24

After clicking Finish the RC is deployed automatically. Wait 5–10 minutes, then verify the status:

Click on BGP Neighbors:

An Idle state on one node is normal — the active RC shows Established, the standby shows Idle. If the active node also shows Idle or Active, do Disable –> Enable on the BGP Neighbor in the NSX UI and wait a moment.

Verify on the VyOS side — State/PfxRcd shown as a number (not “Active” / “Connect”) = session established:

vyos@vyos:~$ show bgp l2vpn evpn summary
BGP router identifier 10.231.106.1, local AS number 64515 VRF default vrf-id 0

Neighbor        V         AS   MsgRcvd   MsgSent   TblVer  Up/Down  State/PfxRcd PfxSnt
10.231.106.10   4      64520      2991      3024       15    22:20:56            2     16  N/A

# State/PfxRcd as a number — session Established, RC receives 2 prefixes from VyOS
# other neighbors (10.231.107.11, .12 etc.) — Active = other segments, not this EVPN/VXLAN setup
Step 2 — External Connectivity (Distributed VXLAN Connection)

Navigate to Network –> VPC Connectivity –> External Connectivity and click Add External Connectivity.

Fill in the form:

  • Type — Distributed VXLAN Connection
  • Route Controller — evpn-test (deployed in Step 1)
  • EVPN L3 VNI — 65000 — must match vni 65000 in VyOS
  • Route Distinguisher — 10.231.106.10:65000 — BGP VIP : VNI; must differ from the VyOS RD (10.231.106.1:10)
  • Import Route Target — 64515:10 — import routes exported by VyOS
  • Export Route Target — 64520:10 — VyOS must import this

The creation task completes within a few seconds.

Step 3 — Configure DTGW

Navigate to Network –> VPC Connectivity –> Transit Gateway. You can edit the default TGW or add a new one.

In the TGW edit form:

  • Connectivity (Uplink Type) — change to Distributed VXLAN
  • External Connectivity — select the record matching our RC

After saving, open the VPC Connectivity Profile associated with the TGW and edit it. Define the address pools:

  • External IP Address Block — 10.231.200.0/24 — pool routable from the BGW, used to assign IPs to VMs in Public mode
  • Private TGW IP Address Block — 172.26.0.0/16 — private pool within the TGW

Creating a VPC and Subnet

VPC

In vSphere Client navigate to Virtual Private Clouds –> New Virtual Private Cloud.

  • Name — test-vpc
  • Private VPC IP CIDR — 192.168.0.0/16
  • Advanced Settings –> Connectivity Profile — verify that the profile linked to the DTGW is selected
Optional — Default VPC Service Profile

Before creating a subnet you can edit the Default VPC Service Profile to have DHCP advertise DNS and NTP. Navigate to VPC –> Profiles –> VPC Service Profiles –> edit Default VPC Service Profile.

  • DNS Server — 10.231.106.1 (VyOS)
  • NTP Server — 10.231.106.1 (VyOS)
Subnet (Public mode)

In the VPC view click New Subnet…

  • Subnet Name — public-sub-01
  • VLAN Extension — No (L2 extension feature, not applicable for EVPN/VXLAN)
  • Access Mode — Public
  • IP Block — select from External IP Address Block 10.231.200.8/29

In Advanced Settings:

  • VPC Gateway Connectivity — Yes (default, leave as is)
  • DHCP — DHCP Server

Connecting a VM and verification

Connecting the vNIC to the VPC subnet

In the VM settings under the VPC Subnets tab select test and save.

Verification from the Guest OS

After powering on the VM verify the DHCP address and default gateway:

VyOS verification — BGP EVPN routes

After powering on the VM, /32 routes to each VM should appear in the VyOS VRF test routing table with next-hop = TEP of the ESX host running the VM:

vyos@vyos:~$ show bgp l2vpn evpn summary
BGP router identifier 10.231.106.1, local AS number 64515 VRF default vrf-id 0
RIB entries 9, using 1296 bytes of memory
Peers 1, using 29 KiB of memory

Neighbor        V         AS   MsgRcvd   MsgSent   TblVer  Up/Down  State/PfxRcd PfxSnt
10.231.106.10   4      64520      2991      3024       15    22:20:56            2     16  N/A

# State/PfxRcd = 2 — RC is advertising 2 prefixes (/32 for 2 VMs)
# PfxSnt = 16 — VyOS is advertising 16 prefixes (connected + default route)
vyos@vyos:~$ show ip route vrf test
B>* 10.231.200.3/32  [20/0] via 10.231.104.3, br1 onlink   # VM1 — TEP 10.231.104.3
B>* 10.231.200.11/32 [20/0] via 10.231.104.7, br1 onlink   # VM2 — TEP 10.231.104.7

# After vMotion VM1 to another host:
# B>* 10.231.200.3/32 [20/0] via 10.231.104.X, br1 onlink  — next-hop changes automatically

A /32 entry with next-hop = ESXi TEP address confirms that the Route Controller is correctly reporting VM location. After a vMotion the next-hop changes automatically — the same GARP-to-RC mechanism as in NSX-T 3.0, just without the Edge node.

RT-5 details in BGP EVPN — mapping VMs to TEPs

Full BGP EVPN table on the VyOS side — two Route Distinguishers are visible: local VyOS and the RC:

vyos@vyos:~$ show bgp l2vpn evpn
BGP table version is 2, local router ID is 10.231.106.1
Status codes: s suppressed, d damped, h history, * valid, > best, i - internal
EVPN type-5 prefix: [5]:[EthTag]:[IPlen]:[IP]

   Network          Next Hop            Metric LocPrf Weight Path

Route Distinguisher: 64520:10          # routes from RC (VMs in VPC)
 *>  [5]:[0]:[32]:[10.231.200.3]       # /32 VM1
                    10.231.104.3                           0 64520 i
                    RT:64520:10 ET:8 Rmac:00:50:56:6a:68:38
 *>  [5]:[0]:[32]:[10.231.200.11]      # /32 VM2
                    10.231.104.7                           0 64520 i
                    RT:64520:10 ET:8 Rmac:00:50:56:65:18:e5

Route Distinguisher: 10.231.106.1:10   # local VyOS routes
 *>  [5]:[0]:[0]:[0.0.0.0]             # default route — advertised to RC
                    10.231.106.1             0         32768 ?
                    ET:8 RT:64515:10 Rmac:c2:8f:db:73:82:3c
 *>  [5]:[0]:[24]:[10.231.104.0]       # TEP VLAN
                    10.231.106.1             0         32768 ?
                    ET:8 RT:64515:10 Rmac:c2:8f:db:73:82:3c
 *>  [5]:[0]:[24]:[10.231.106.0]       # BGP peering VLAN
                    10.231.106.1             0         32768 ?
                    ET:8 RT:64515:10 Rmac:c2:8f:db:73:82:3c
 # ... remaining connected networks

Displayed 16 out of 16 total prefixes

Each /32 under RD 64520:10 is one VM in the NSX VPC. Next-hop (10.231.104.3, 10.231.104.7) = ESX host TEP. Router MAC (Rmac) = TEP MAC address. After a vMotion the RC updates the advertisement via GARP — the next-hop change is visible within a few seconds.

Note — the output shows RD 64520:10 (from the RC), not 10.231.106.10:65000. The Route Distinguisher on the RC side is set as ASN_RC:VNI — the value comes from the External Connectivity configuration in NSX.

ESX verification — nsxcli
[root@ESXi11:~] nsxcli
esxi11.homelab.int> get gateway
  87b192f1-a8c4-40f7-b9e6-1e905aa259c8  Gateway (Logical Router) UUID
  bdc694b7-d236-47c3-93b0-8d2ba4f04608  Gateway (Logical Router) UUID

esxi11.homelab.int> get gateway 87b192f1-a8c4-40f7-b9e6-1e905aa259c8 forwarding
Mon May 11 2026 UTC 12:04:05.454
Flags: [U: Up], [G: Gateway], [S1|S2|S3: TGW Private|Public|External Route Scope]

                   Network                  Gateway          Type    Interface UUID
===================================================================================
0.0.0.0/0                             10.231.106.1          UGS3    2d08b262-...
10.231.200.8/29                        100.64.0.1           UGS2    a56ae99c-...
100.64.0.0/31                           0.0.0.0             UCI     a56ae99c-...

# S3 = External Route Scope (from RC/gateway)
# S2 = Public Route Scope (VM subnet)
Verification via net-vdr (ESX)

net-vdr is a low-level ESX command that shows the internal routing tables of the Distributed Router:

[root@esxi11:~] net-vdr -Il --brief

DR Id      #Lifs   #Routesv4  State   DR UUID
-------    -----   ---------  -----   ---------
0x1        2       3          A       87b192f1-a8c4-40f7-b9e6-1e905aa259c8 (/transit-gateways/default)
0xa        3       4          A       bdc694b7-d236-47c3-93b0-8d2ba4f04608 (/vpcs/test-vpc,default)

[root@esxi11:~] net-vdr -Rl 87b192f1-a8c4-40f7-b9e6-1e905aa259c8
DR 87b192f1-... Route Table
Legend: [S1|S2|S3: TGW Private|Public|External Route Scope]

Destination      GenMask          Gateway          Flags    Ref  UpTime   HitCount
0.0.0.0          0.0.0.0          10.231.106.1     UGS3     1    314380   28
10.231.200.8     255.255.255.248  100.64.0.1       UGS2     1    314380   39
100.64.0.0       255.255.255.254  0.0.0.0          UCI      1    314380   5

# S3 = default route from RC/BGW (10.231.106.1 = VyOS)
# S2 = Public subnet 10.231.200.8/29

Ping test from ESX host to VM:

[root@ESXi11:~] ping -I vmk0 10.231.200.3
64 bytes from 10.231.200.3: icmp_seq=0 ttl=61 time=1.8 ms
# ttl=61 = 3 hops (VM -> ESX TEP -> VyOS -> ping source)


Common issues

Problem Likely cause Where to look
BGP Neighbor in Idle state Wrong remote-as, no route to BGP VIP, MTU issue show bgp neighbor 10.231.106.10, ping from update-source
No /32 in VRF after VM power-on RT mismatch, wrong L3VNI, RC not receiving notifications show bgp l2vpn evpn, logi NSX Manager
VM cannot ping outside Default route not propagated to ESX host, missing NAT nsxcli: get gateway forwarding, show ip route vrf test
RT-5 routes visible but traffic not flowing Underlay MTU issue, VTEP unreachable, encapsulation problem ping from ESXi to GW-VTEP, tcpdump -i vxlan65000
BGP Active on VyOS side RC still starting up, wrong BGP VIP Disable –> Enable BGP Neighbor in NSX UI, wait 2–3 min

Summary

The VCF side of the configuration is straightforward — Route Controller, External Connectivity, and DTGW are just a few screens in NSX Manager. The real challenge is the BGW side. VyOS works very well for testing thanks to its debugging capabilities through vtysh and FRR.

A few things worth keeping in mind:

  • Route Target must be configured symmetrically — what the RC exports (64520:10), VyOS must import, and vice versa
  • L3VNI must be identical on both sides
  • Underlay MTU must account for the ~50 B VXLAN overhead
  • The VXLAN interface source-address must be reachable from the ESX host TEPs
  • Keep the VyOS VRF table ID in the range 1–200 if you plan to use NAT with connection-mark

 

Posts created 132

Related Posts

Begin typing your search term above and press enter to search. Press ESC to cancel.

Back To Top