]> git.proxmox.com Git - mirror_frr.git/commitdiff
tests: add EVPN IP learning tests
authorPat Ruddy <pat@voltanet.io>
Fri, 17 Apr 2020 11:29:13 +0000 (12:29 +0100)
committerPat Ruddy <pat@voltanet.io>
Wed, 12 Aug 2020 11:39:33 +0000 (12:39 +0100)
add tests to check IP address/MAC address associations are learned
from netlink NEWNEIGH messages and are propagated to the remote PE

Signed-off-by: Pat Ruddy <pat@voltanet.io>
tests/topotests/bgp-evpn-vxlan_topo1/PE1/evpn.vni.json
tests/topotests/bgp-evpn-vxlan_topo1/PE1/zebra.conf
tests/topotests/bgp-evpn-vxlan_topo1/PE2/evpn.vni.json
tests/topotests/bgp-evpn-vxlan_topo1/PE2/zebra.conf
tests/topotests/bgp-evpn-vxlan_topo1/test_bgp_evpn_vxlan.py

index d9f2182aa09a283f518f890242eeb55b563c3a54..ce16089b89fde46106c763572456fd3e12f85d8d 100644 (file)
@@ -8,7 +8,7 @@
   "mcastGroup":"0.0.0.0",
   "advertiseGatewayMacip":"No",
   "numMacs":5,
-  "numArpNd":2,
+  "numArpNd":3,
   "numRemoteVteps":[
     "10.30.30.30"
   ]
index 938ec7bca9d3bffb4ea21f081732af53bec7ad96..e2699475c9221ee78877ea5b81f85e41e831d838 100644 (file)
@@ -3,8 +3,6 @@ log file zebra.log
 !
 interface lo
  ip address 10.10.10.10/32
-interface PE1-eth0
- ip address 10.10.1.1/24
 interface PE1-eth1
  ip address 10.20.1.1/24
 !
index 13255ab4f22eb3be8259211fe9a36f726f4d6d8f..1ac83c495e2db9021707683b68201f3ad93284b1 100644 (file)
@@ -8,7 +8,7 @@
   "mcastGroup":"0.0.0.0",
   "advertiseGatewayMacip":"No",
   "numMacs":5,
-  "numArpNd":2,
+  "numArpNd":3,
   "numRemoteVteps":[
     "10.10.10.10"
   ]
index 07b83f6395ace00fbc00c20e9dcba9e37e07878e..9738916ab015d393d486b67f1ac10aa3d68a5e99 100644 (file)
@@ -3,6 +3,4 @@ interface lo
  ip address 10.30.30.30/32
 interface PE2-eth0
  ip address 10.20.2.3/24
-interface  PE2-eth1
- ip address 10.10.1.3/24
 !
index ad72540185c864e67ef5d13f6b4dc1af56ce6c2c..7ed4c6e7e22517698384efd44efc67858d012394 100755 (executable)
@@ -29,6 +29,7 @@ import os
 import sys
 import json
 from functools import partial
+from time import sleep
 import pytest
 
 # Save the Current Working Directory to find configuration files.
@@ -97,6 +98,7 @@ def setup_module(mod):
 
     # set up PE bridges with the EVPN member interfaces facing the CE hosts
     pe1.run("ip link add name br101 type bridge stp_state 0")
+    pe1.run("ip addr add 10.10.1.1/24 dev br101")
     pe1.run("ip link set dev br101 up")
     pe1.run(
         "ip link add vxlan101 type vxlan id 101 dstport 4789 local 10.10.10.10 nolearning"
@@ -106,6 +108,7 @@ def setup_module(mod):
     pe1.run("ip link set dev PE1-eth0 master br101")
 
     pe2.run("ip link add name br101 type bridge stp_state 0")
+    pe2.run("ip addr add 10.10.1.3/24 dev br101")
     pe2.run("ip link set dev br101 up")
     pe2.run(
         "ip link add vxlan101 type vxlan id 101 dstport 4789 local 10.30.30.30 nolearning"
@@ -194,7 +197,7 @@ def mac_learn_test(host, local):
     mac_output = local.vtysh_cmd("show evpn mac vni 101 mac {} json".format(mac))
     mac_output_json = json.loads(mac_output)
     assertmsg = "Local MAC output does not match interface mac {}".format(mac)
-    assert mac_output_json[mac]["type"] == "local"
+    assert mac_output_json[mac]["type"] == "local", assertmsg
 
 
 def mac_test_local_remote(local, remote):
@@ -275,6 +278,103 @@ def test_local_remote_mac_pe2():
     # Memory leak test template
 
 
+def ip_learn_test(tgen, host, local, remote, ip_addr):
+    "check the host IP gets learned by the VNI"
+    host_output = host.vtysh_cmd("show interface {}-eth0".format(host.name))
+    int_lines = host_output.splitlines()
+    mac_line = int_lines[7].split(": ")
+    mac = mac_line[1]
+    print(host_output)
+
+    # check we have a local association between the MAC and IP
+    local_output = local.vtysh_cmd("show evpn mac vni 101 mac {} json".format(mac))
+    print(local_output)
+    local_output_json = json.loads(local_output)
+    mac_type = local_output_json[mac]["type"]
+    assertmsg = "Failed to learn local IP address on host {}".format(host.name)
+    assert local_output_json[mac]["neighbors"] != "none", assertmsg
+    learned_ip = local_output_json[mac]["neighbors"]["active"][0]
+
+    assertmsg = "local learned mac wrong type: {} ".format(mac_type)
+    assert mac_type == "local", assertmsg
+
+    assertmsg = "learned address mismatch with configured address host: {} learned: {}".format(
+        ip_addr, learned_ip
+    )
+    assert ip_addr == learned_ip, assertmsg
+
+    # now lets check the remote
+    count = 0
+    converged = False
+    while count < 30:
+        remote_output = remote.vtysh_cmd(
+            "show evpn mac vni 101 mac {} json".format(mac)
+        )
+        print(remote_output)
+        remote_output_json = json.loads(remote_output)
+        type = remote_output_json[mac]["type"]
+        if not remote_output_json[mac]["neighbors"] == "none":
+            # due to a kernel quirk, learned IPs can be inactive
+            if (
+                remote_output_json[mac]["neighbors"]["active"]
+                or remote_output_json[mac]["neighbors"]["inactive"]
+            ):
+                converged = True
+                break
+        count += 1
+        sleep(1)
+
+    print("tries: {}".format(count))
+    assertmsg = "{} remote learned mac no address: {} ".format(host.name, mac)
+    # some debug for this failure
+    if not converged == True:
+        log_output = remote.run("cat zebra.log")
+        print(log_output)
+
+    assert converged == True, assertmsg
+    if remote_output_json[mac]["neighbors"]["active"]:
+        learned_ip = remote_output_json[mac]["neighbors"]["active"][0]
+    else:
+        learned_ip = remote_output_json[mac]["neighbors"]["inactive"][0]
+    assertmsg = "remote learned mac wrong type: {} ".format(type)
+    assert type == "remote", assertmsg
+
+    assertmsg = "remote learned address mismatch with configured address host: {} learned: {}".format(
+        ip_addr, learned_ip
+    )
+    assert ip_addr == learned_ip, assertmsg
+
+
+def test_ip_pe1_learn():
+    "run the IP learn test for PE1"
+
+    tgen = get_topogen()
+    host1 = tgen.gears["host1"]
+    pe1 = tgen.gears["PE1"]
+    pe2 = tgen.gears["PE2"]
+    pe2.vtysh_cmd("debug zebra vxlan")
+    pe2.vtysh_cmd("debug zebra kernel")
+    # lets populate that arp cache
+    host1.run("ping -c1 10.10.1.1")
+    ip_learn_test(tgen, host1, pe1, pe2, "10.10.1.55")
+    # tgen.mininet_cli()
+
+
+def test_ip_pe2_learn():
+    "run the IP learn test for PE2"
+
+    tgen = get_topogen()
+    host2 = tgen.gears["host2"]
+    pe1 = tgen.gears["PE1"]
+    pe2 = tgen.gears["PE2"]
+    pe1.vtysh_cmd("debug zebra vxlan")
+    pe1.vtysh_cmd("debug zebra kernel")
+    # lets populate that arp cache
+    host2.run("ping -c1 10.10.1.3")
+    ip_learn_test(tgen, host2, pe2, pe1, "10.10.1.56")
+    # tgen.mininet_cli()
+
+
 def test_memory_leak():
     "Run the memory leak test and report results."
     tgen = get_topogen()