diff options
author | Neale Ranns <nranns@cisco.com> | 2017-03-11 05:55:21 -0800 |
---|---|---|
committer | Florin Coras <florin.coras@gmail.com> | 2017-03-17 15:49:39 +0000 |
commit | 4b919a56642ccd0a44920feace872aeb5b7a62cf (patch) | |
tree | 17750f4efc80d7863b68f9cd08ab381cd00dd534 /test | |
parent | c60f557590f79b8817382bdd982825b66c4e0a73 (diff) |
Attached hosts
allow this config to function:
set int ip address loop0 169.254.1.1/32 (the default GW address for attached hosts)
set int unnumbered af_packet0 use loop0 ('enable' IP on the host interface)
ip route add 192.168.1.1/32 via af_packet0 (where to find the host)
repeat for each host and host interface.
Inter-host communication is throught the /32 routes.
To allow this:
1 - attached host routes have the ATTACHED flag set, so the ARP code accepts then as legitimate sources
2 - unnumbered interfaces inherit the source address from the IP interface
Change-Id: Ib66c5f0e848c528f79372813adc3a0c11b50717f
Signed-off-by: Neale Ranns <nranns@cisco.com>
Diffstat (limited to 'test')
-rw-r--r-- | test/test_neighbor.py | 176 | ||||
-rw-r--r-- | test/vpp_interface.py | 2 |
2 files changed, 166 insertions, 12 deletions
diff --git a/test/test_neighbor.py b/test/test_neighbor.py index a97a63fc7a6..f2b1cfa47ee 100644 --- a/test/test_neighbor.py +++ b/test/test_neighbor.py @@ -44,9 +44,15 @@ class ARPTestCase(VppTestCase): def tearDown(self): super(ARPTestCase, self).tearDown() + self.pg0.unconfig_ip4() + self.pg0.unconfig_ip6() + + self.pg1.unconfig_ip4() + self.pg1.unconfig_ip6() + + self.pg3.unconfig_ip4() + for i in self.pg_interfaces: - i.unconfig_ip4() - i.unconfig_ip6() i.admin_down() def verify_arp_req(self, rx, smac, sip, dip): @@ -115,7 +121,7 @@ class ARPTestCase(VppTestCase): # # Generate some hosts on the LAN # - self.pg1.generate_remote_hosts(6) + self.pg1.generate_remote_hosts(9) # # Send IP traffic to one of these unresolved hosts. @@ -249,6 +255,47 @@ class ARPTestCase(VppTestCase): self.assertTrue(find_nbr(self, self.pg1.sw_if_index, self.pg1._remote_hosts[3].ip4)) + # + # Fire in an ARP request before the interface becomes IP enabled + # + self.pg2.generate_remote_hosts(4) + + p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / + ARP(op="who-has", + hwsrc=self.pg2.remote_mac, + pdst=self.pg1.local_ip4, + psrc=self.pg2.remote_hosts[3].ip4)) + self.send_and_assert_no_replies(self.pg2, p, + "interface not IP enabled") + + # + # Make pg2 un-numbered to pg1 + # + self.pg2.set_unnumbered(self.pg1.sw_if_index) + + # + # We should respond to ARP requests for the unnumbered to address + # once an attached route to the source is known + # + self.send_and_assert_no_replies( + self.pg2, p, + "ARP req for unnumbered address - no source") + + attached_host = VppIpRoute(self, self.pg2.remote_hosts[3].ip4, 32, + [VppRoutePath("0.0.0.0", + self.pg2.sw_if_index)]) + attached_host.add_vpp_config() + + self.pg2.add_stream(p) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + + rx = self.pg2.get_capture(1) + self.verify_arp_resp(rx[0], + self.pg2.local_mac, + self.pg2.remote_mac, + self.pg1.local_ip4, + self.pg2.remote_hosts[3].ip4) # # A neighbor entry that has no associated FIB-entry @@ -270,12 +317,8 @@ class ARPTestCase(VppTestCase): self.pg1._remote_hosts[4].ip4, 32)) # - # Unnumbered pg2 to pg1 - # - self.pg2.set_unnumbered(self.pg1.sw_if_index) - - # - # now we can form adjacencies out of pg2 from within pg1's subnet + # pg2 is unnumbered to pg1, so we can form adjacencies out of pg2 + # from within pg1's subnet # arp_unnum = VppNeighbor(self, self.pg2.sw_if_index, @@ -302,10 +345,100 @@ class ARPTestCase(VppTestCase): self.pg1._remote_hosts[5].ip4) # + # ARP requests from hosts in pg1's subnet sent on pg2 are replied to + # with the unnumbered interface's address as the source + # + p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / + ARP(op="who-has", + hwsrc=self.pg2.remote_mac, + pdst=self.pg1.local_ip4, + psrc=self.pg1.remote_hosts[6].ip4)) + + self.pg2.add_stream(p) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + + rx = self.pg2.get_capture(1) + self.verify_arp_resp(rx[0], + self.pg2.local_mac, + self.pg2.remote_mac, + self.pg1.local_ip4, + self.pg1.remote_hosts[6].ip4) + + # + # An attached host route out of pg2 for an undiscovered hosts generates + # an ARP request with the unnumbered address as the source + # + att_unnum = VppIpRoute(self, self.pg1.remote_hosts[7].ip4, 32, + [VppRoutePath("0.0.0.0", + self.pg2.sw_if_index)]) + att_unnum.add_vpp_config() + + p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / + IP(src=self.pg0.remote_ip4, + dst=self.pg1._remote_hosts[7].ip4) / + UDP(sport=1234, dport=1234) / + Raw()) + + self.pg0.add_stream(p) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + + rx = self.pg2.get_capture(1) + + self.verify_arp_req(rx[0], + self.pg2.local_mac, + self.pg1.local_ip4, + self.pg1._remote_hosts[7].ip4) + + p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / + ARP(op="who-has", + hwsrc=self.pg2.remote_mac, + pdst=self.pg1.local_ip4, + psrc=self.pg1.remote_hosts[7].ip4)) + + self.pg2.add_stream(p) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + + rx = self.pg2.get_capture(1) + self.verify_arp_resp(rx[0], + self.pg2.local_mac, + self.pg2.remote_mac, + self.pg1.local_ip4, + self.pg1.remote_hosts[7].ip4) + + # + # An attached host route as yet unresolved out of pg2 for an + # undiscovered host, an ARP requests begets a response. + # + att_unnum1 = VppIpRoute(self, self.pg1.remote_hosts[8].ip4, 32, + [VppRoutePath("0.0.0.0", + self.pg2.sw_if_index)]) + att_unnum1.add_vpp_config() + + p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / + ARP(op="who-has", + hwsrc=self.pg2.remote_mac, + pdst=self.pg1.local_ip4, + psrc=self.pg1.remote_hosts[8].ip4)) + + self.pg2.add_stream(p) + self.pg_enable_capture(self.pg_interfaces) + self.pg_start() + + rx = self.pg2.get_capture(1) + self.verify_arp_resp(rx[0], + self.pg2.local_mac, + self.pg2.remote_mac, + self.pg1.local_ip4, + self.pg1.remote_hosts[8].ip4) + + # # ERROR Cases # 1 - don't respond to ARP request for address not within the # interface's sub-net - # + # 1a - nor within the unnumbered subnet p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(op="who-has", hwsrc=self.pg0.remote_mac, @@ -313,6 +446,14 @@ class ARPTestCase(VppTestCase): psrc=self.pg0.remote_ip4)) self.send_and_assert_no_replies(self.pg0, p, "ARP req for non-local destination") + p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / + ARP(op="who-has", + hwsrc=self.pg2.remote_mac, + pdst="10.10.10.3", + psrc=self.pg1.remote_hosts[7].ip4)) + self.send_and_assert_no_replies( + self.pg0, p, + "ARP req for non-local destination - unnum") # # 2 - don't respond to ARP request from an address not within the @@ -325,6 +466,14 @@ class ARPTestCase(VppTestCase): pdst=self.pg0.local_ip4)) self.send_and_assert_no_replies(self.pg0, p, "ARP req for non-local source") + p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / + ARP(op="who-has", + hwsrc=self.pg2.remote_mac, + psrc="10.10.10.3", + pdst=self.pg0.local_ip4)) + self.send_and_assert_no_replies( + self.pg0, p, + "ARP req for non-local source - unnum") # # 3 - don't respond to ARP request from an address that belongs to @@ -358,6 +507,10 @@ class ARPTestCase(VppTestCase): static_arp.remove_vpp_config() self.pg2.unset_unnumbered(self.pg1.sw_if_index) + # need this to flush the adj-fibs + self.pg2.unset_unnumbered(self.pg1.sw_if_index) + self.pg2.admin_down() + def test_proxy_arp(self): """ Proxy ARP """ @@ -500,7 +653,7 @@ class ARPTestCase(VppTestCase): # # clean up on interface 2 # - self.pg2.set_unnumbered(self.pg1.sw_if_index) + self.pg2.unset_unnumbered(self.pg1.sw_if_index) def test_mpls(self): """ MPLS """ @@ -560,6 +713,7 @@ class ARPTestCase(VppTestCase): 55, self.pg0.remote_ip4, "10.0.0.1") + self.pg2.unconfig_ip4() if __name__ == '__main__': unittest.main(testRunner=VppTestRunner) diff --git a/test/vpp_interface.py b/test/vpp_interface.py index 8135bc84d0e..aeaf27a898e 100644 --- a/test/vpp_interface.py +++ b/test/vpp_interface.py @@ -336,7 +336,7 @@ class VppInterface(object): ip_sw_if_index) def unset_unnumbered(self, ip_sw_if_index): - """ Unaet the interface to unnumbered via ip_sw_if_index """ + """ Unset the interface to unnumbered via ip_sw_if_index """ self.test.vapi.sw_interface_set_unnumbered( self.sw_if_index, ip_sw_if_index, |