Skip to content

Router Lab I: ContainerLab and BGP

Introduction

You can find material for Lab I in the bgp directory.

ContainerLab 101

Deployment

Once ContainerLab is installed and the required image (cEOS) is imported, we can deploy one lab with

Bash
sudo containerlab deploy -t start.clab.yaml

You can check that three containers are up and running and that their interfaces and connections are properly configured.

Bash
1
2
3
4
5
 docker ps
CONTAINER ID   IMAGE              COMMAND                  CREATED         STATUS         PORTS     NAMES
12e0d2759a6c   ceos:4.28.3        "bash -c '/mnt/flash…"   7 minutes ago   Up 7 minutes             R3
14cdeaef4c91   ceos:4.28.3        "bash -c '/mnt/flash…"   7 minutes ago   Up 7 minutes             R2
8543bfd15a06   ceos:4.28.3        "bash -c '/mnt/flash…"   7 minutes ago   Up 7 minutes             R1

Bash Interface

cEOS supports four interfaces, but we only use its Cli and Bash interfaces in this lab. You can use the docker exec command to launch these two interfaces without an account and password. For example, use the following command to start a bash shell on device R1.

Bash Session
docker exec -it R1 bash

You get the typical shell found on RedHat-family Linux distributions and could use familiar commands like ping, traceroute and ip.

Bash Session
bash-4.2# cat /etc/redhat-release 
CentOS Linux release 7.9.2009 (Core)
bash-4.2# uname -r
5.4.0-135-generic
bash-4.2# ip address # We omit some results for brevity.
...
2: lo0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 65535 qdisc noqueue state UP group default qlen 1000
    link/ether 02:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
    inet 1.1.1.1/24 brd 255.255.255.255 scope global lo0
       valid_lft forever preferred_lft forever
...
1117: eth1@if1116: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether aa:c1:ab:ea:2c:70 brd ff:ff:ff:ff:ff:ff link-netnsid 1
    inet 10.1.1.1/24 brd 255.255.255.255 scope global eth1
       valid_lft forever preferred_lft forever
bash-4.2# ping 10.1.1.2 -c 4
PING 10.1.1.2 (10.1.1.2) 56(84) bytes of data.
64 bytes from 10.1.1.2: icmp_seq=1 ttl=64 time=0.067 ms
64 bytes from 10.1.1.2: icmp_seq=2 ttl=64 time=0.046 ms
64 bytes from 10.1.1.2: icmp_seq=3 ttl=64 time=0.046 ms
64 bytes from 10.1.1.2: icmp_seq=4 ttl=64 time=0.043 ms

--- 10.1.1.2 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3050ms
rtt min/avg/max/mdev = 0.043/0.050/0.067/0.011 ms
bash-4.2# traceroute 10.1.1.2
traceroute to 10.1.1.2 (10.1.1.2), 30 hops max, 60 byte packets
 1  10.1.1.2 (10.1.1.2)  0.134 ms  0.016 ms  0.014 ms

However, the bash interface is not very necessary in this lab. Instead, we play with the Cli interface almost all the time.

Cli Interface

You can use the following command to start the device console on device R1.

Bash Session
❯ docker exec -it R1 Cli
R1>
In the Cli interface, you get the device console and configure the device using its domain-specific commands. You can find a complete guide of all available commands on Arista's official document.

Note

Available commands and their usage may change on newer cEOS versions. Currently, we use cEOS 4.29.2F.

For example, we can check the routing table using show ip route.

Text Only
R1>show ip route

VRF: default
Codes: C - connected, S - static, K - kernel, 
       O - OSPF, IA - OSPF inter area, E1 - OSPF external type 1,
       E2 - OSPF external type 2, N1 - OSPF NSSA external type 1,
       N2 - OSPF NSSA external type2, B - Other BGP Routes,
       B I - iBGP, B E - eBGP, R - RIP, I L1 - IS-IS level 1,
       I L2 - IS-IS level 2, O3 - OSPFv3, A B - BGP Aggregate,
       A O - OSPF Summary, NG - Nexthop Group Static Route,
       V - VXLAN Control Service, M - Martian,
       DH - DHCP client installed default route,
       DP - Dynamic Policy Route, L - VRF Leaked,
       G  - gRIBI, RC - Route Cache Route

Gateway of last resort is not set

 C        1.1.1.0/24 is directly connected, Loopback0
 C        10.1.1.0/24 is directly connected, Ethernet1

We will endlessly use this command during this lab to debug our configurations, but it's not very interesting currently. Since there is still no any running routing protocol, the router could only reach its two local interfaces.

If you are familiar with network devices, you must be accustomed to typing enable and configure to enter the privileged global configuration mode.

Text Only
1
2
3
R1>enable
R1#configure
R1(config)#

You could learn the current mode from the prompt: # means the privileged mode, the same as a root shell on Linux; () shows the current configuration "scope". You need to enter a specific configuration mode to configure certain resources.

Text Only
1
2
3
4
5
R1(config)#vlan 20
R1(config-vlan-20)#exit
R1(config)#interface Management0
R1(config-if-Ma0)#exit
R1(config)#
For example, you need to enter the BGP configuration mode to add BGP peers, and you need to enter the interface configuration mode to assign an IP address to it. Using commands in incorrect configuration modes gives you an "invalid input" error response at the best, and ruins all your configurations at worst.

Topology

In Lab I, we set up 3 routers on 3 ASes, as shown below.

topology-lab1

Lab 1 Target Network Topology

We use the same naming convention during three labs, so you could remember interface names and IP addresses more easily.

  • For a router N (N is a number from 1 to 9), it has a local IPv4 address N.N.N.N.
  • For a link L (L is also a number from 1 to 9) connecting router N and M, the interface on the side of N is assigned IPv4 address 10.1.L.N, while the interface on the side of M is assigned 10.1.L.M. We use the `/24`` subnet for all addresses for simplicity.

We say that router N is connected with router M only when it could send a packet to M.M.M.M using its local address N.N.N.N. Currently, Router 1 could send a packet to 10.1.1.2 from 10.1.1.1 since they are directly connected. But Router 1 has not learned how to reach 2.2.2.2, so Router 1 and Router 2 have not been connected yet.

BGP Configurations

We start the configuration from Router 1. Launch the Cli of Router 1, and enter the privileged mode using enable and configure. We omit these two steps and assume that you are already in the privileged mode in the following guidelines.

Bash Session
1
2
3
R1>enable
R1#configure
R1(config)#

We can validate the state of BGP using the command show ip bgp summary. It's disabled by default. To make the router work as a BGP router, we need to enter the BGP configuration mode using router bgp <AS number>.

Bash Session
1
2
3
4
5
6
7
8
R1(config)#show ip bgp summary
BGP is disabled for VRF default
R1(config)#router bgp 1
R1(config-router-bgp)#show ip bgp summary
BGP summary information for VRF default
Router identifier 1.1.1.1, local AS number 1
Neighbor Status Codes: m - Under maintenance
  Neighbor V AS           MsgRcvd   MsgSent  InQ OutQ  Up/Down State   PfxRcd PfxAcc

We can see that the BGP is enabled now. But the router still knows nothing about the network as it has not talked to any neighbor yet. We need to configure the BGP neighbors on both endpoints using the command neighbor <IP address> remote-as <AS number> to establish BGP peers. Let's start with R1.

Bash Session
1
2
3
4
5
6
R1(config-router-bgp)#show ip bgp neighbor
R1(config-router-bgp)#neighbor 10.1.1.2 remote-as 2
R1(config-router-bgp)#show ip bgp neighbor
BGP neighbor is 10.1.1.2, remote AS 2, external link
  Last read never, last write never
  ......

Configuring the BGP neighbor relationship on R2 using the same command, we can verify the BGP neighborship using the command show ip bgp neighbor on R1 again.

Bash Session
R2(config)#router bgp 2
R2(config-router-bgp)#neighbor 10.1.1.1 remote-as 1
Bash Session
1
2
3
4
5
R1(config-router-bgp)#
BGP neighbor is 10.1.1.2, remote AS 2, external link
  BGP version 4, remote router ID 2.2.2.2, VRF default
  Last read 00:00:37, last write 00:00:37
  ......

Let's check the routing table on R1 and R2.

Bash Session
R1(config-router-bgp)#show ip route

VRF: default
Codes: C - connected, S - static, K - kernel, 
    O - OSPF, IA - OSPF inter area, E1 - OSPF external type 1,
    E2 - OSPF external type 2, N1 - OSPF NSSA external type 1,
    N2 - OSPF NSSA external type2, B - Other BGP Routes,
    B I - iBGP, B E - eBGP, R - RIP, I L1 - IS-IS level 1,
    I L2 - IS-IS level 2, O3 - OSPFv3, A B - BGP Aggregate,
    A O - OSPF Summary, NG - Nexthop Group Static Route,
    V - VXLAN Control Service, M - Martian,
    DH - DHCP client installed default route,
    DP - Dynamic Policy Route, L - VRF Leaked,
    G  - gRIBI, RC - Route Cache Route

Gateway of last resort is not set

C        1.1.1.0/24 is directly connected, Loopback0
C        10.1.1.0/24 is directly connected, Ethernet1
R1#exit
Bash Session
R2(config-router-bgp)#show ip route

VRF: default
Codes: C - connected, S - static, K - kernel, 
    O - OSPF, IA - OSPF inter area, E1 - OSPF external type 1,
    E2 - OSPF external type 2, N1 - OSPF NSSA external type 1,
    N2 - OSPF NSSA external type2, B - Other BGP Routes,
    B I - iBGP, B E - eBGP, R - RIP, I L1 - IS-IS level 1,
    I L2 - IS-IS level 2, O3 - OSPFv3, A B - BGP Aggregate,
    A O - OSPF Summary, NG - Nexthop Group Static Route,
    V - VXLAN Control Service, M - Martian,
    DH - DHCP client installed default route,
    DP - Dynamic Policy Route, L - VRF Leaked,
    G  - gRIBI, RC - Route Cache Route

Gateway of last resort is not set

C        2.2.2.0/24 is directly connected, Loopback0
C        10.1.1.0/24 is directly connected, Ethernet1
C        10.1.2.0/24 is directly connected, Ethernet2

We can see that the BGP is not advertising any networks to its peers. We can request BGP to advertise a network to its peers using network <network address>. As an example, let's advertise the local address 1.1.1.1 on R1 to its peers, and 2.2.2.2 on R2 to its peers.

Bash Session
R1(config-router-bgp)#network 1.1.1.1/24
Bash Session
R2(config-router-bgp)#network 2.2.2.2/24

Check the routing table again, we could find that the routing information is correctly advertised. B indicates that the route is learned from BGP while E indicates that this is an external route.

Bash Session
R1(config-router-bgp)#show ip route

VRF: default
Codes: C - connected, S - static, K - kernel, 
    O - OSPF, IA - OSPF inter area, E1 - OSPF external type 1,
    E2 - OSPF external type 2, N1 - OSPF NSSA external type 1,
    N2 - OSPF NSSA external type2, B - Other BGP Routes,
    B I - iBGP, B E - eBGP, R - RIP, I L1 - IS-IS level 1,
    I L2 - IS-IS level 2, O3 - OSPFv3, A B - BGP Aggregate,
    A O - OSPF Summary, NG - Nexthop Group Static Route,
    V - VXLAN Control Service, M - Martian,
    DH - DHCP client installed default route,
    DP - Dynamic Policy Route, L - VRF Leaked,
    G  - gRIBI, RC - Route Cache Route

Gateway of last resort is not set

C        1.1.1.0/24 is directly connected, Loopback0
B E      2.2.2.0/24 [200/0] via 10.1.1.2, Ethernet1
C        10.1.1.0/24 is directly connected, Ethernet1
Bash Session
R2(config-router-bgp)#show ip route

VRF: default
Codes: C - connected, S - static, K - kernel, 
    O - OSPF, IA - OSPF inter area, E1 - OSPF external type 1,
    E2 - OSPF external type 2, N1 - OSPF NSSA external type 1,
    N2 - OSPF NSSA external type2, B - Other BGP Routes,
    B I - iBGP, B E - eBGP, R - RIP, I L1 - IS-IS level 1,
    I L2 - IS-IS level 2, O3 - OSPFv3, A B - BGP Aggregate,
    A O - OSPF Summary, NG - Nexthop Group Static Route,
    V - VXLAN Control Service, M - Martian,
    DH - DHCP client installed default route,
    DP - Dynamic Policy Route, L - VRF Leaked,
    G  - gRIBI, RC - Route Cache Route

Gateway of last resort is not set

B E      1.1.1.0/24 [200/0] via 10.1.1.1, Ethernet1
C        2.2.2.0/24 is directly connected, Loopback0
C        10.1.1.0/24 is directly connected, Ethernet1
C        10.1.2.0/24 is directly connected, Ethernet2

We can also use the command redistribute connected to redistribute all "connected" routes altogether. It distributes all network that is directly connected to the router (noted as C in the output of the command show ip route), including the local interface.

We can configure R3 following identical steps. But don't forget to set up the peer relationship between R2 and R3 on R2.

Bash Session
R2(config-router-bgp)#neighbor 10.1.2.3 remote-as 3
Bash Session
1
2
3
R3(config)#router bgp 3
R3(config-router-bgp)#neighbor 10.1.2.2 remote-as 2
R3(config-router-bgp)#network 3.3.3.3/24

Validating routing tables on all three routers, the result shows that they are connected now. We complete our first lab.

Bash Session
R1>show ip route

VRF: default
Codes: C - connected, S - static, K - kernel, 
    O - OSPF, IA - OSPF inter area, E1 - OSPF external type 1,
    E2 - OSPF external type 2, N1 - OSPF NSSA external type 1,
    N2 - OSPF NSSA external type2, B - Other BGP Routes,
    B I - iBGP, B E - eBGP, R - RIP, I L1 - IS-IS level 1,
    I L2 - IS-IS level 2, O3 - OSPFv3, A B - BGP Aggregate,
    A O - OSPF Summary, NG - Nexthop Group Static Route,
    V - VXLAN Control Service, M - Martian,
    DH - DHCP client installed default route,
    DP - Dynamic Policy Route, L - VRF Leaked,
    G  - gRIBI, RC - Route Cache Route

Gateway of last resort is not set

C        1.1.1.0/24 is directly connected, Loopback0
B E      2.2.2.0/24 [200/0] via 10.1.1.2, Ethernet1
B E      3.3.3.0/24 [200/0] via 10.1.1.2, Ethernet1
C        10.1.1.0/24 is directly connected, Ethernet1
Bash Session
R2>show ip route

VRF: default
Codes: C - connected, S - static, K - kernel, 
    O - OSPF, IA - OSPF inter area, E1 - OSPF external type 1,
    E2 - OSPF external type 2, N1 - OSPF NSSA external type 1,
    N2 - OSPF NSSA external type2, B - Other BGP Routes,
    B I - iBGP, B E - eBGP, R - RIP, I L1 - IS-IS level 1,
    I L2 - IS-IS level 2, O3 - OSPFv3, A B - BGP Aggregate,
    A O - OSPF Summary, NG - Nexthop Group Static Route,
    V - VXLAN Control Service, M - Martian,
    DH - DHCP client installed default route,
    DP - Dynamic Policy Route, L - VRF Leaked,
    G  - gRIBI, RC - Route Cache Route

Gateway of last resort is not set

B E      1.1.1.0/24 [200/0] via 10.1.1.1, Ethernet1
C        2.2.2.0/24 is directly connected, Loopback0
B E      3.3.3.0/24 [200/0] via 10.1.2.3, Ethernet2
C        10.1.1.0/24 is directly connected, Ethernet1
C        10.1.2.0/24 is directly connected, Ethernet2
Bash Session
R3>show ip route

VRF: default
Codes: C - connected, S - static, K - kernel, 
    O - OSPF, IA - OSPF inter area, E1 - OSPF external type 1,
    E2 - OSPF external type 2, N1 - OSPF NSSA external type 1,
    N2 - OSPF NSSA external type2, B - Other BGP Routes,
    B I - iBGP, B E - eBGP, R - RIP, I L1 - IS-IS level 1,
    I L2 - IS-IS level 2, O3 - OSPFv3, A B - BGP Aggregate,
    A O - OSPF Summary, NG - Nexthop Group Static Route,
    V - VXLAN Control Service, M - Martian,
    DH - DHCP client installed default route,
    DP - Dynamic Policy Route, L - VRF Leaked,
    G  - gRIBI, RC - Route Cache Route

Gateway of last resort is not set

B E      1.1.1.0/24 [200/0] via 10.1.2.2, Ethernet1
B E      2.2.2.0/24 [200/0] via 10.1.2.2, Ethernet1
C        3.3.3.0/24 is directly connected, Loopback0
C        10.1.2.0/24 is directly connected, Ethernet1

Configuration Review

We give a complete list of commands here for reference. You can start from scratch using sudo containerlab deploy -t start.clab.yaml --reconfigure if you make any mistake.

Bash
1
2
3
4
5
6
7
8
9
R1>enable
R1#configure
R1(config)#router bgp 1
R1(config-router-bgp)#router-id 1.1.1.1
R1(config-router-bgp)#neighbor 10.1.1.2 remote-as 2
R1(config-router-bgp)#redistribute connected
R1(config-router-bgp)#exit
R1(config)#exit
R1#exit
Bash
R2>enable
R2#configure
R2(config)#router bgp 2
R2(config-router-bgp)#router-id 2.2.2.2
R2(config-router-bgp)#neighbor 10.1.1.1 remote-as 1
R2(config-router-bgp)#neighbor 10.1.2.3 remote-as 3
R2(config-router-bgp)#redistribute connected
R2(config-router-bgp)#exit
R2(config)#exit
R2#exit
Bash
1
2
3
4
5
6
7
8
9
R3>enable
R3#configure
R3(config)#router bgp 3
R3(config-router-bgp)#router-id 3.3.3.3
R3(config-router-bgp)#neighbor 10.1.2.2 remote-as 2
R3(config-router-bgp)#redistribute connected
R3(config-router-bgp)#exit
R3(config)#exit
R3#exit

Test

Once the configuration is done, we can test the connectivity between the three routers using the script test.py in the bgp directory.

Bash Session
1
2
3
4
5
❯ ./test.py 
R1 -> R1: True R2: True R3: True 
R2 -> R1: True R2: True R3: True 
R3 -> R1: True R2: True R3: True 
Pass Connectivity Test

BGP Under the Curtain

If you are curious about BGP, you may feel disappointed as you learned nothing about how BGP works internally in this lab yet. Though it is not necessary to know the details of BGP to use it in practice, it's not a bad idea to go deeper into BGP, especially when ContainerLab gives us a chance to do so.

Since network cards in containers are just virtual interfaces isolated by network namespaces, we could capture packets received and sent on network cards using tcpdump in the host machine. Specifically, we can capture packets on a network card in the router using the following command:

Bash
ip netns exec <router> tcpdump -i <interface> -w <router>-<interface>.in.pcap

We provide a capture.sh script in the bgp directory that captures all non-local network interfaces in the background. You could execute it before configuring routers and kill all running tcpdump processes using sudo kill tcpdump after configurations are complete. It dumps packets captured from <interface> on <router> to a pcap file named <router>-<interface>.pcap. You may study the packet trace offline using Wireshark to learn how BGP agents interact.

Here we give an example analyzing a packet trace captured from interface eth1 on router R1 during the router configuration procedure described above.

BGP uses the TCP protocol to exchange routing messages and listens on port 179 to accept TCP connections from other BGP agents. So we can see that router R2 sends an OPEN Message to router R1 at first. It contains the BGP version number (Version 4 defined by RFC 4271), the Autonomous System number (2 as we set), the BGP Identifier (2.2.2.2, which is the IP address of R2's local interface), and the Hold Time (180 seconds). The Hold Time is the maximum time interval that the sender expects to receive a KEEPALIVE or UPDATE message from the receiver of the message.

Text Only
Frame 20: 123 bytes on wire (984 bits), 123 bytes captured (984 bits)
Ethernet II, Src: aa:c1:ab:23:8f:66 (aa:c1:ab:23:8f:66), Dst: aa:c1:ab:e9:a4:33 (aa:c1:ab:e9:a4:33)
Internet Protocol Version 4, Src: 10.1.1.2, Dst: 10.1.1.1
Transmission Control Protocol, Src Port: 43415, Dst Port: 179, Seq: 1, Ack: 1, Len: 57
Border Gateway Protocol - OPEN Message
    Marker: ffffffffffffffffffffffffffffffff
    Length: 57
    Type: OPEN Message (1)
    Version: 4
    My AS: 2
    Hold Time: 180
    BGP Identifier: 2.2.2.2
    Optional Parameters Length: 28
    Optional Parameters
        Optional Parameter: Capability
            Parameter Type: Capability (2)
            Parameter Length: 26
            Capability: Route refresh capability
            Capability: Enhanced route refresh capability
            Capability: Support for 4-octet AS number capability
            Capability: Multiprotocol extensions capability
            Capability: Graceful Restart capability
            Capability: Support for Additional Paths

R2 sends a route message after a while using BGP UPDATE Message. This packet is an IGP packet (ORIGIN: IGP), it traverses only AS 2 (AS_PATH: 2) and tells R1 that you could reach 10.1.2.0/24, 2.2.2.0/24 and 10.1.1.0/24 (Network Layer Reachability Information) via 10.1.1.2/24 as the next hop (NEXT_HOP: 10.1.1.2).

Text Only
Frame 38: 121 bytes on wire (968 bits), 121 bytes captured (968 bits)
Ethernet II, Src: aa:c1:ab:23:8f:66 (aa:c1:ab:23:8f:66), Dst: aa:c1:ab:e9:a4:33 (aa:c1:ab:e9:a4:33)
Internet Protocol Version 4, Src: 10.1.1.2, Dst: 10.1.1.1
Transmission Control Protocol, Src Port: 43415, Dst Port: 179, Seq: 119, Ack: 170, Len: 55
Border Gateway Protocol - UPDATE Message
    Marker: ffffffffffffffffffffffffffffffff
    Length: 55
    Type: UPDATE Message (2)
    Withdrawn Routes Length: 0
    Total Path Attribute Length: 20
    Path attributes
        Path Attribute - ORIGIN: IGP
            Flags: 0x40, Transitive, Well-known, Complete
            Type Code: ORIGIN (1)
            Length: 1
            Origin: IGP (0)
        Path Attribute - AS_PATH: 2 
            Flags: 0x40, Transitive, Well-known, Complete
            Type Code: AS_PATH (2)
            Length: 6
            AS Path segment: 2
                Segment type: AS_SEQUENCE (2)
                Segment length (number of ASN): 1
                AS4: 2
        Path Attribute - NEXT_HOP: 10.1.1.2 
            Flags: 0x40, Transitive, Well-known, Complete
            Type Code: NEXT_HOP (3)
            Length: 4
            Next hop: 10.1.1.2
    Network Layer Reachability Information (NLRI)
        10.1.2.0/24
            NLRI prefix length: 24
            NLRI prefix: 10.1.2.0
        2.2.2.0/24
            NLRI prefix length: 24
            NLRI prefix: 2.2.2.0
        10.1.1.0/24
            NLRI prefix length: 24
            NLRI prefix: 10.1.1.0

Later, we receive another UPDATE message from R2 after R2 learns the route to R3. It tells R1 that it could reach 3.3.3.0/24 via 10.1.1.2.

Text Only
Frame 40: 117 bytes on wire (936 bits), 117 bytes captured (936 bits)
Ethernet II, Src: aa:c1:ab:23:8f:66 (aa:c1:ab:23:8f:66), Dst: aa:c1:ab:e9:a4:33 (aa:c1:ab:e9:a4:33)
Internet Protocol Version 4, Src: 10.1.1.2, Dst: 10.1.1.1
Transmission Control Protocol, Src Port: 43415, Dst Port: 179, Seq: 174, Ack: 170, Len: 51
Border Gateway Protocol - UPDATE Message
    Marker: ffffffffffffffffffffffffffffffff
    Length: 51
    Type: UPDATE Message (2)
    Withdrawn Routes Length: 0
    Total Path Attribute Length: 24
    Path attributes
        Path Attribute - ORIGIN: IGP
            Flags: 0x40, Transitive, Well-known, Complete
            Type Code: ORIGIN (1)
            Length: 1
            Origin: IGP (0)
        Path Attribute - AS_PATH: 2 3 
            Flags: 0x40, Transitive, Well-known, Complete
            Type Code: AS_PATH (2)
            Length: 10
            AS Path segment: 2 3
                Segment type: AS_SEQUENCE (2)
                Segment length (number of ASN): 2
                AS4: 2
                AS4: 3
        Path Attribute - NEXT_HOP: 10.1.1.2 
            Flags: 0x40, Transitive, Well-known, Complete
            Type Code: NEXT_HOP (3)
            Length: 4
            Next hop: 10.1.1.2
    Network Layer Reachability Information (NLRI)
        3.3.3.0/24
            NLRI prefix length: 24
            NLRI prefix: 3.3.3.0

After exchanging all available routes, BGP agents send KEEPALIVE messages periodically to keep these routes alive.

Text Only
1
2
3
4
5
6
7
8
Frame 44: 85 bytes on wire (680 bits), 85 bytes captured (680 bits)
Ethernet II, Src: aa:c1:ab:e9:a4:33 (aa:c1:ab:e9:a4:33), Dst: aa:c1:ab:23:8f:66 (aa:c1:ab:23:8f:66)
Internet Protocol Version 4, Src: 10.1.1.1, Dst: 10.1.1.2
Transmission Control Protocol, Src Port: 179, Dst Port: 43415, Seq: 170, Ack: 225, Len: 19
Border Gateway Protocol - KEEPALIVE Message
    Marker: ffffffffffffffffffffffffffffffff
    Length: 19
    Type: KEEPALIVE Message (4)

In our toy topology, BGP messages are straightforward to understand. As the current base of the Internet, practical BGP deployments are more challenging to understand and operate. With ContainerLab, you could design more complicated topologies, apply more extensive routing policies and examine the captured packets to learn how BGP works, in a more realistic approach than reading textbooks or RFCs.