+class NeighborAgeTestCase(VppTestCase):
+ """ ARP/ND Aging """
+
+ @classmethod
+ def setUpClass(cls):
+ super(NeighborAgeTestCase, cls).setUpClass()
+
+ @classmethod
+ def tearDownClass(cls):
+ super(NeighborAgeTestCase, cls).tearDownClass()
+
+ def setUp(self):
+ super(NeighborAgeTestCase, self).setUp()
+
+ self.create_pg_interfaces(range(1))
+
+ # pg0 configured with ip4 and 6 addresses used for input
+ # pg1 configured with ip4 and 6 addresses used for output
+ # pg2 is unnumbered to pg0
+ for i in self.pg_interfaces:
+ i.admin_up()
+ i.config_ip4()
+ i.config_ip6()
+ i.resolve_arp()
+ i.resolve_ndp()
+
+ def tearDown(self):
+ super(NeighborAgeTestCase, self).tearDown()
+
+ for i in self.pg_interfaces:
+ i.unconfig_ip4()
+ i.unconfig_ip6()
+ i.admin_down()
+
+ def wait_for_no_nbr(self, intf, address,
+ n_tries=50, s_time=1):
+ while (n_tries):
+ if not find_nbr(self, intf, address):
+ return True
+ n_tries = n_tries - 1
+ self.sleep(s_time)
+
+ return False
+
+ def verify_arp_req(self, rx, smac, sip, dip):
+ ether = rx[Ether]
+ self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
+ self.assertEqual(ether.src, smac)
+
+ arp = rx[ARP]
+ self.assertEqual(arp.hwtype, 1)
+ self.assertEqual(arp.ptype, 0x800)
+ self.assertEqual(arp.hwlen, 6)
+ self.assertEqual(arp.plen, 4)
+ self.assertEqual(arp.op, arp_opts["who-has"])
+ self.assertEqual(arp.hwsrc, smac)
+ self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
+ self.assertEqual(arp.psrc, sip)
+ self.assertEqual(arp.pdst, dip)
+
+ def test_age(self):
+ """ Aging/Recycle """
+
+ self.vapi.cli("set logging unthrottle 0")
+ self.vapi.cli("set logging size %d" % 0xffff)
+
+ self.pg0.generate_remote_hosts(201)
+
+ vaf = VppEnum.vl_api_address_family_t
+
+ #
+ # start listening on all interfaces
+ #
+ self.pg_enable_capture(self.pg_interfaces)
+
+ #
+ # Set the neighbor configuration:
+ # limi = 200
+ # age = 0 seconds
+ # recycle = false
+ #
+ self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
+ max_number=200,
+ max_age=0,
+ recycle=False)
+
+ self.vapi.cli("sh ip neighbor-config")
+
+ # add the 198 neighbours that should pass (-1 for one created in setup)
+ for ii in range(200):
+ VppNeighbor(self,
+ self.pg0.sw_if_index,
+ self.pg0.remote_hosts[ii].mac,
+ self.pg0.remote_hosts[ii].ip4).add_vpp_config()
+
+ # one more neighbor over the limit should fail
+ with self.vapi.assert_negative_api_retval():
+ VppNeighbor(self,
+ self.pg0.sw_if_index,
+ self.pg0.remote_hosts[200].mac,
+ self.pg0.remote_hosts[200].ip4).add_vpp_config()
+
+ #
+ # change the config to allow recycling the old neighbors
+ #
+ self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
+ max_number=200,
+ max_age=0,
+ recycle=True)
+
+ # now new additions are allowed
+ VppNeighbor(self,
+ self.pg0.sw_if_index,
+ self.pg0.remote_hosts[200].mac,
+ self.pg0.remote_hosts[200].ip4).add_vpp_config()
+
+ # add the first neighbor we configured has been re-used
+ self.assertFalse(find_nbr(self,
+ self.pg0.sw_if_index,
+ self.pg0.remote_hosts[0].ip4))
+ self.assertTrue(find_nbr(self,
+ self.pg0.sw_if_index,
+ self.pg0.remote_hosts[200].ip4))
+
+ #
+ # change the config to age old neighbors
+ #
+ self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
+ max_number=200,
+ max_age=2,
+ recycle=True)
+
+ self.vapi.cli("sh ip4 neighbor-sorted")
+
+ #
+ # expect probes from all these ARP entries as they age
+ # 3 probes for each neighbor 3*200 = 600
+ rxs = self.pg0.get_capture(600, timeout=8)
+
+ for ii in range(3):
+ for jj in range(200):
+ rx = rxs[ii*200 + jj]
+ # rx.show()
+
+ #
+ # 3 probes sent then 1 more second to see if a reply comes, before
+ # they age out
+ #
+ for jj in range(1, 201):
+ self.wait_for_no_nbr(self.pg0.sw_if_index,
+ self.pg0.remote_hosts[jj].ip4)
+
+ self.assertFalse(self.vapi.ip_neighbor_dump(sw_if_index=0xffffffff,
+ af=vaf.ADDRESS_IP4))
+
+ #
+ # load up some neighbours again with 2s aging enabled
+ # they should be removed after 10s (2s age + 4s for probes + gap)
+ #
+ for ii in range(10):
+ VppNeighbor(self,
+ self.pg0.sw_if_index,
+ self.pg0.remote_hosts[ii].mac,
+ self.pg0.remote_hosts[ii].ip4).add_vpp_config()
+ self.sleep(10)
+ self.assertFalse(self.vapi.ip_neighbor_dump(sw_if_index=0xffffffff,
+ af=vaf.ADDRESS_IP4))
+
+ #
+ # check if we can set age and recycle with empty neighbor list
+ #
+ self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
+ max_number=200,
+ max_age=1000,
+ recycle=True)
+
+ #
+ # load up some neighbours again, then disable the aging
+ # they should still be there in 10 seconds time
+ #
+ for ii in range(10):
+ VppNeighbor(self,
+ self.pg0.sw_if_index,
+ self.pg0.remote_hosts[ii].mac,
+ self.pg0.remote_hosts[ii].ip4).add_vpp_config()
+ self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
+ max_number=200,
+ max_age=0,
+ recycle=False)
+
+ self.sleep(10)
+ self.assertTrue(find_nbr(self,
+ self.pg0.sw_if_index,
+ self.pg0.remote_hosts[0].ip4))
+
+