blob: b33a70b2a3c59df8fb3a01ed2010fba051e3a0e4 [file] [log] [blame]
Renato Botelho do Coutoead1e532019-10-31 13:31:07 -05001#!/usr/bin/env python3
Neale Ranns39f9d8b2017-02-16 21:57:05 -08002
3import unittest
Neale Rannscbe25aa2019-09-30 10:53:31 +00004import os
Neale Ranns39f9d8b2017-02-16 21:57:05 -08005from socket import AF_INET, AF_INET6, inet_pton
6
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00007from framework import tag_fixme_vpp_workers
Neale Ranns39f9d8b2017-02-16 21:57:05 -08008from framework import VppTestCase, VppTestRunner
9from vpp_neighbor import VppNeighbor, find_nbr
Neale Ranns15002542017-09-10 04:39:11 -070010from vpp_ip_route import VppIpRoute, VppRoutePath, find_route, \
Neale Rannse2fe0972020-11-26 08:37:27 +000011 VppIpTable, DpoProto, FibPathType, VppIpInterfaceAddress
Neale Ranns37029302018-08-10 05:30:06 -070012from vpp_papi import VppEnum
Jakub Grajciar2df2f752020-12-01 11:23:44 +010013from vpp_ip import VppIpPuntRedirect
Neale Ranns39f9d8b2017-02-16 21:57:05 -080014
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -070015import scapy.compat
Neale Ranns39f9d8b2017-02-16 21:57:05 -080016from scapy.packet import Raw
Neale Ranns30d0fd42017-05-30 07:30:04 -070017from scapy.layers.l2 import Ether, ARP, Dot1Q
Neale Ranns240dcb22020-04-23 09:04:59 +000018from scapy.layers.inet import IP, UDP, TCP
Neale Rannscd35e532018-08-31 02:51:45 -070019from scapy.layers.inet6 import IPv6
Neale Ranns37be7362017-02-21 17:30:26 -080020from scapy.contrib.mpls import MPLS
Neale Ranns14260392018-09-28 05:00:57 -070021from scapy.layers.inet6 import IPv6
Neale Ranns39f9d8b2017-02-16 21:57:05 -080022
Paul Vinciguerra4271c972019-05-14 13:25:49 -040023
24NUM_PKTS = 67
25
Neale Ranns39f9d8b2017-02-16 21:57:05 -080026# not exported by scapy, so redefined here
27arp_opts = {"who-has": 1, "is-at": 2}
28
29
30class ARPTestCase(VppTestCase):
31 """ ARP Test Case """
32
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070033 @classmethod
34 def setUpClass(cls):
35 super(ARPTestCase, cls).setUpClass()
36
37 @classmethod
38 def tearDownClass(cls):
39 super(ARPTestCase, cls).tearDownClass()
40
Neale Ranns39f9d8b2017-02-16 21:57:05 -080041 def setUp(self):
42 super(ARPTestCase, self).setUp()
43
44 # create 3 pg interfaces
45 self.create_pg_interfaces(range(4))
46
47 # pg0 configured with ip4 and 6 addresses used for input
48 # pg1 configured with ip4 and 6 addresses used for output
49 # pg2 is unnumbered to pg0
50 for i in self.pg_interfaces:
51 i.admin_up()
52
53 self.pg0.config_ip4()
54 self.pg0.config_ip6()
55 self.pg0.resolve_arp()
56
57 self.pg1.config_ip4()
58 self.pg1.config_ip6()
59
60 # pg3 in a different VRF
Neale Ranns15002542017-09-10 04:39:11 -070061 self.tbl = VppIpTable(self, 1)
62 self.tbl.add_vpp_config()
63
Neale Ranns39f9d8b2017-02-16 21:57:05 -080064 self.pg3.set_table_ip4(1)
65 self.pg3.config_ip4()
66
Neale Ranns4008ac92017-02-13 23:20:04 -080067 def tearDown(self):
Neale Ranns4b919a52017-03-11 05:55:21 -080068 self.pg0.unconfig_ip4()
69 self.pg0.unconfig_ip6()
70
71 self.pg1.unconfig_ip4()
72 self.pg1.unconfig_ip6()
73
74 self.pg3.unconfig_ip4()
Neale Ranns15002542017-09-10 04:39:11 -070075 self.pg3.set_table_ip4(0)
Neale Ranns4b919a52017-03-11 05:55:21 -080076
Neale Ranns4008ac92017-02-13 23:20:04 -080077 for i in self.pg_interfaces:
Neale Ranns4008ac92017-02-13 23:20:04 -080078 i.admin_down()
79
Neale Ranns15002542017-09-10 04:39:11 -070080 super(ARPTestCase, self).tearDown()
81
Neale Ranns39f9d8b2017-02-16 21:57:05 -080082 def verify_arp_req(self, rx, smac, sip, dip):
83 ether = rx[Ether]
84 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
85 self.assertEqual(ether.src, smac)
Elias Rudberg71845712020-12-10 14:20:43 +010086 self.assertEqual(ether.type, 0x0806)
Neale Ranns39f9d8b2017-02-16 21:57:05 -080087
88 arp = rx[ARP]
89 self.assertEqual(arp.hwtype, 1)
90 self.assertEqual(arp.ptype, 0x800)
91 self.assertEqual(arp.hwlen, 6)
92 self.assertEqual(arp.plen, 4)
93 self.assertEqual(arp.op, arp_opts["who-has"])
94 self.assertEqual(arp.hwsrc, smac)
95 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
96 self.assertEqual(arp.psrc, sip)
97 self.assertEqual(arp.pdst, dip)
98
99 def verify_arp_resp(self, rx, smac, dmac, sip, dip):
100 ether = rx[Ether]
101 self.assertEqual(ether.dst, dmac)
102 self.assertEqual(ether.src, smac)
Elias Rudberg71845712020-12-10 14:20:43 +0100103 self.assertEqual(ether.type, 0x0806)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800104
105 arp = rx[ARP]
106 self.assertEqual(arp.hwtype, 1)
107 self.assertEqual(arp.ptype, 0x800)
108 self.assertEqual(arp.hwlen, 6)
109 self.assertEqual(arp.plen, 4)
110 self.assertEqual(arp.op, arp_opts["is-at"])
111 self.assertEqual(arp.hwsrc, smac)
112 self.assertEqual(arp.hwdst, dmac)
113 self.assertEqual(arp.psrc, sip)
114 self.assertEqual(arp.pdst, dip)
115
Matthew Smithcb9ab472017-05-16 21:35:56 -0500116 def verify_arp_vrrp_resp(self, rx, smac, dmac, sip, dip):
117 ether = rx[Ether]
118 self.assertEqual(ether.dst, dmac)
119 self.assertEqual(ether.src, smac)
120
121 arp = rx[ARP]
122 self.assertEqual(arp.hwtype, 1)
123 self.assertEqual(arp.ptype, 0x800)
124 self.assertEqual(arp.hwlen, 6)
125 self.assertEqual(arp.plen, 4)
126 self.assertEqual(arp.op, arp_opts["is-at"])
127 self.assertNotEqual(arp.hwsrc, smac)
128 self.assertTrue("00:00:5e:00:01" in arp.hwsrc or
129 "00:00:5E:00:01" in arp.hwsrc)
130 self.assertEqual(arp.hwdst, dmac)
131 self.assertEqual(arp.psrc, sip)
132 self.assertEqual(arp.pdst, dip)
133
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800134 def verify_ip(self, rx, smac, dmac, sip, dip):
135 ether = rx[Ether]
136 self.assertEqual(ether.dst, dmac)
137 self.assertEqual(ether.src, smac)
Elias Rudberg71845712020-12-10 14:20:43 +0100138 self.assertEqual(ether.type, 0x0800)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800139
140 ip = rx[IP]
141 self.assertEqual(ip.src, sip)
142 self.assertEqual(ip.dst, dip)
143
Neale Ranns37be7362017-02-21 17:30:26 -0800144 def verify_ip_o_mpls(self, rx, smac, dmac, label, sip, dip):
145 ether = rx[Ether]
146 self.assertEqual(ether.dst, dmac)
147 self.assertEqual(ether.src, smac)
Elias Rudberg71845712020-12-10 14:20:43 +0100148 self.assertEqual(ether.type, 0x8847)
Neale Ranns37be7362017-02-21 17:30:26 -0800149
150 mpls = rx[MPLS]
151 self.assertTrue(mpls.label, label)
152
153 ip = rx[IP]
154 self.assertEqual(ip.src, sip)
155 self.assertEqual(ip.dst, dip)
156
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800157 def test_arp(self):
158 """ ARP """
159
160 #
161 # Generate some hosts on the LAN
162 #
Neale Rannsca193612017-06-14 06:50:08 -0700163 self.pg1.generate_remote_hosts(11)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800164
165 #
Neale Rannscbe25aa2019-09-30 10:53:31 +0000166 # watch for:
167 # - all neighbour events
168 # - all neighbor events on pg1
169 # - neighbor events for host[1] on pg1
170 #
171 self.vapi.want_ip_neighbor_events(enable=1,
172 pid=os.getpid())
173 self.vapi.want_ip_neighbor_events(enable=1,
174 pid=os.getpid(),
175 sw_if_index=self.pg1.sw_if_index)
176 self.vapi.want_ip_neighbor_events(enable=1,
177 pid=os.getpid(),
178 sw_if_index=self.pg1.sw_if_index,
179 ip=self.pg1.remote_hosts[1].ip4)
180
181 self.logger.info(self.vapi.cli("sh ip neighbor-watcher"))
182
183 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800184 # Send IP traffic to one of these unresolved hosts.
185 # expect the generation of an ARP request
186 #
187 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
188 IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[1].ip4) /
189 UDP(sport=1234, dport=1234) /
190 Raw())
191
192 self.pg0.add_stream(p)
193 self.pg_enable_capture(self.pg_interfaces)
194 self.pg_start()
195
196 rx = self.pg1.get_capture(1)
197
198 self.verify_arp_req(rx[0],
199 self.pg1.local_mac,
200 self.pg1.local_ip4,
201 self.pg1._remote_hosts[1].ip4)
202
203 #
204 # And a dynamic ARP entry for host 1
205 #
206 dyn_arp = VppNeighbor(self,
207 self.pg1.sw_if_index,
208 self.pg1.remote_hosts[1].mac,
209 self.pg1.remote_hosts[1].ip4)
210 dyn_arp.add_vpp_config()
Neale Rannscbe25aa2019-09-30 10:53:31 +0000211 self.assertTrue(dyn_arp.query_vpp_config())
212
Neale Rannsdc617b82020-08-20 08:22:56 +0000213 self.logger.info(self.vapi.cli("show ip neighbor-watcher"))
214
Neale Rannscbe25aa2019-09-30 10:53:31 +0000215 # this matches all of the listnerers
216 es = [self.vapi.wait_for_event(1, "ip_neighbor_event")
217 for i in range(3)]
218 for e in es:
219 self.assertEqual(str(e.neighbor.ip_address),
220 self.pg1.remote_hosts[1].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800221
222 #
223 # now we expect IP traffic forwarded
224 #
225 dyn_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
226 IP(src=self.pg0.remote_ip4,
227 dst=self.pg1._remote_hosts[1].ip4) /
228 UDP(sport=1234, dport=1234) /
229 Raw())
230
231 self.pg0.add_stream(dyn_p)
232 self.pg_enable_capture(self.pg_interfaces)
233 self.pg_start()
234
235 rx = self.pg1.get_capture(1)
236
237 self.verify_ip(rx[0],
238 self.pg1.local_mac,
239 self.pg1.remote_hosts[1].mac,
240 self.pg0.remote_ip4,
241 self.pg1._remote_hosts[1].ip4)
242
243 #
244 # And a Static ARP entry for host 2
245 #
246 static_arp = VppNeighbor(self,
247 self.pg1.sw_if_index,
248 self.pg1.remote_hosts[2].mac,
249 self.pg1.remote_hosts[2].ip4,
250 is_static=1)
251 static_arp.add_vpp_config()
Neale Rannscbe25aa2019-09-30 10:53:31 +0000252 es = [self.vapi.wait_for_event(1, "ip_neighbor_event")
253 for i in range(2)]
254 for e in es:
255 self.assertEqual(str(e.neighbor.ip_address),
256 self.pg1.remote_hosts[2].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800257
258 static_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
259 IP(src=self.pg0.remote_ip4,
260 dst=self.pg1._remote_hosts[2].ip4) /
261 UDP(sport=1234, dport=1234) /
262 Raw())
263
264 self.pg0.add_stream(static_p)
265 self.pg_enable_capture(self.pg_interfaces)
266 self.pg_start()
267
268 rx = self.pg1.get_capture(1)
269
270 self.verify_ip(rx[0],
271 self.pg1.local_mac,
272 self.pg1.remote_hosts[2].mac,
273 self.pg0.remote_ip4,
274 self.pg1._remote_hosts[2].ip4)
275
276 #
Neale Rannscbe25aa2019-09-30 10:53:31 +0000277 # remove all the listeners
278 #
279 self.vapi.want_ip_neighbor_events(enable=0,
280 pid=os.getpid())
281 self.vapi.want_ip_neighbor_events(enable=0,
282 pid=os.getpid(),
283 sw_if_index=self.pg1.sw_if_index)
284 self.vapi.want_ip_neighbor_events(enable=0,
285 pid=os.getpid(),
286 sw_if_index=self.pg1.sw_if_index,
287 ip=self.pg1.remote_hosts[1].ip4)
288
289 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800290 # flap the link. dynamic ARPs get flush, statics don't
291 #
292 self.pg1.admin_down()
293 self.pg1.admin_up()
294
295 self.pg0.add_stream(static_p)
296 self.pg_enable_capture(self.pg_interfaces)
297 self.pg_start()
298 rx = self.pg1.get_capture(1)
299
300 self.verify_ip(rx[0],
301 self.pg1.local_mac,
302 self.pg1.remote_hosts[2].mac,
303 self.pg0.remote_ip4,
304 self.pg1._remote_hosts[2].ip4)
305
306 self.pg0.add_stream(dyn_p)
307 self.pg_enable_capture(self.pg_interfaces)
308 self.pg_start()
309
310 rx = self.pg1.get_capture(1)
311 self.verify_arp_req(rx[0],
312 self.pg1.local_mac,
313 self.pg1.local_ip4,
314 self.pg1._remote_hosts[1].ip4)
315
Neale Rannscbe25aa2019-09-30 10:53:31 +0000316 self.assertFalse(dyn_arp.query_vpp_config())
317 self.assertTrue(static_arp.query_vpp_config())
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800318 #
319 # Send an ARP request from one of the so-far unlearned remote hosts
320 #
321 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
322 src=self.pg1._remote_hosts[3].mac) /
323 ARP(op="who-has",
324 hwsrc=self.pg1._remote_hosts[3].mac,
325 pdst=self.pg1.local_ip4,
326 psrc=self.pg1._remote_hosts[3].ip4))
327
328 self.pg1.add_stream(p)
329 self.pg_enable_capture(self.pg_interfaces)
330 self.pg_start()
331
332 rx = self.pg1.get_capture(1)
333 self.verify_arp_resp(rx[0],
334 self.pg1.local_mac,
335 self.pg1._remote_hosts[3].mac,
336 self.pg1.local_ip4,
337 self.pg1._remote_hosts[3].ip4)
338
339 #
340 # VPP should have learned the mapping for the remote host
341 #
342 self.assertTrue(find_nbr(self,
343 self.pg1.sw_if_index,
344 self.pg1._remote_hosts[3].ip4))
Neale Ranns4b919a52017-03-11 05:55:21 -0800345 #
346 # Fire in an ARP request before the interface becomes IP enabled
347 #
348 self.pg2.generate_remote_hosts(4)
349
350 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
351 ARP(op="who-has",
352 hwsrc=self.pg2.remote_mac,
353 pdst=self.pg1.local_ip4,
354 psrc=self.pg2.remote_hosts[3].ip4))
Neale Ranns30d0fd42017-05-30 07:30:04 -0700355 pt = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
356 Dot1Q(vlan=0) /
357 ARP(op="who-has",
358 hwsrc=self.pg2.remote_mac,
359 pdst=self.pg1.local_ip4,
360 psrc=self.pg2.remote_hosts[3].ip4))
Neale Ranns4b919a52017-03-11 05:55:21 -0800361 self.send_and_assert_no_replies(self.pg2, p,
362 "interface not IP enabled")
363
364 #
365 # Make pg2 un-numbered to pg1
366 #
367 self.pg2.set_unnumbered(self.pg1.sw_if_index)
368
Neale Rannsac3e72c2019-10-06 01:04:26 -0700369 #
370 # test the unnumbered dump both by all interfaces and just the enabled
371 # one
372 #
Neale Ranns404d88e2018-08-08 06:37:33 -0700373 unnum = self.vapi.ip_unnumbered_dump()
Neale Rannsac3e72c2019-10-06 01:04:26 -0700374 self.assertTrue(len(unnum))
375 self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
376 self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)
377 unnum = self.vapi.ip_unnumbered_dump(self.pg2.sw_if_index)
378 self.assertTrue(len(unnum))
Neale Ranns404d88e2018-08-08 06:37:33 -0700379 self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
380 self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)
381
Neale Ranns4b919a52017-03-11 05:55:21 -0800382 #
383 # We should respond to ARP requests for the unnumbered to address
384 # once an attached route to the source is known
385 #
386 self.send_and_assert_no_replies(
387 self.pg2, p,
388 "ARP req for unnumbered address - no source")
389
390 attached_host = VppIpRoute(self, self.pg2.remote_hosts[3].ip4, 32,
391 [VppRoutePath("0.0.0.0",
392 self.pg2.sw_if_index)])
393 attached_host.add_vpp_config()
394
395 self.pg2.add_stream(p)
396 self.pg_enable_capture(self.pg_interfaces)
397 self.pg_start()
398
399 rx = self.pg2.get_capture(1)
400 self.verify_arp_resp(rx[0],
401 self.pg2.local_mac,
402 self.pg2.remote_mac,
403 self.pg1.local_ip4,
404 self.pg2.remote_hosts[3].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800405
Neale Ranns30d0fd42017-05-30 07:30:04 -0700406 self.pg2.add_stream(pt)
407 self.pg_enable_capture(self.pg_interfaces)
408 self.pg_start()
409
410 rx = self.pg2.get_capture(1)
411 self.verify_arp_resp(rx[0],
412 self.pg2.local_mac,
413 self.pg2.remote_mac,
414 self.pg1.local_ip4,
415 self.pg2.remote_hosts[3].ip4)
416
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800417 #
Neale Ranns3983ac22017-03-10 11:53:27 -0800418 # A neighbor entry that has no associated FIB-entry
419 #
420 arp_no_fib = VppNeighbor(self,
421 self.pg1.sw_if_index,
422 self.pg1.remote_hosts[4].mac,
423 self.pg1.remote_hosts[4].ip4,
424 is_no_fib_entry=1)
425 arp_no_fib.add_vpp_config()
426
427 #
428 # check we have the neighbor, but no route
429 #
430 self.assertTrue(find_nbr(self,
431 self.pg1.sw_if_index,
432 self.pg1._remote_hosts[4].ip4))
433 self.assertFalse(find_route(self,
434 self.pg1._remote_hosts[4].ip4,
435 32))
436 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800437 # pg2 is unnumbered to pg1, so we can form adjacencies out of pg2
438 # from within pg1's subnet
Neale Ranns3983ac22017-03-10 11:53:27 -0800439 #
440 arp_unnum = VppNeighbor(self,
441 self.pg2.sw_if_index,
442 self.pg1.remote_hosts[5].mac,
443 self.pg1.remote_hosts[5].ip4)
444 arp_unnum.add_vpp_config()
445
446 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
447 IP(src=self.pg0.remote_ip4,
448 dst=self.pg1._remote_hosts[5].ip4) /
449 UDP(sport=1234, dport=1234) /
450 Raw())
451
452 self.pg0.add_stream(p)
453 self.pg_enable_capture(self.pg_interfaces)
454 self.pg_start()
455
456 rx = self.pg2.get_capture(1)
457
458 self.verify_ip(rx[0],
459 self.pg2.local_mac,
460 self.pg1.remote_hosts[5].mac,
461 self.pg0.remote_ip4,
462 self.pg1._remote_hosts[5].ip4)
463
464 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800465 # ARP requests from hosts in pg1's subnet sent on pg2 are replied to
466 # with the unnumbered interface's address as the source
467 #
468 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
469 ARP(op="who-has",
470 hwsrc=self.pg2.remote_mac,
471 pdst=self.pg1.local_ip4,
472 psrc=self.pg1.remote_hosts[6].ip4))
473
474 self.pg2.add_stream(p)
475 self.pg_enable_capture(self.pg_interfaces)
476 self.pg_start()
477
478 rx = self.pg2.get_capture(1)
479 self.verify_arp_resp(rx[0],
480 self.pg2.local_mac,
481 self.pg2.remote_mac,
482 self.pg1.local_ip4,
483 self.pg1.remote_hosts[6].ip4)
484
485 #
486 # An attached host route out of pg2 for an undiscovered hosts generates
487 # an ARP request with the unnumbered address as the source
488 #
489 att_unnum = VppIpRoute(self, self.pg1.remote_hosts[7].ip4, 32,
490 [VppRoutePath("0.0.0.0",
491 self.pg2.sw_if_index)])
492 att_unnum.add_vpp_config()
493
494 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
495 IP(src=self.pg0.remote_ip4,
496 dst=self.pg1._remote_hosts[7].ip4) /
497 UDP(sport=1234, dport=1234) /
498 Raw())
499
500 self.pg0.add_stream(p)
501 self.pg_enable_capture(self.pg_interfaces)
502 self.pg_start()
503
504 rx = self.pg2.get_capture(1)
505
506 self.verify_arp_req(rx[0],
507 self.pg2.local_mac,
508 self.pg1.local_ip4,
509 self.pg1._remote_hosts[7].ip4)
510
511 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
512 ARP(op="who-has",
513 hwsrc=self.pg2.remote_mac,
514 pdst=self.pg1.local_ip4,
515 psrc=self.pg1.remote_hosts[7].ip4))
516
517 self.pg2.add_stream(p)
518 self.pg_enable_capture(self.pg_interfaces)
519 self.pg_start()
520
521 rx = self.pg2.get_capture(1)
522 self.verify_arp_resp(rx[0],
523 self.pg2.local_mac,
524 self.pg2.remote_mac,
525 self.pg1.local_ip4,
526 self.pg1.remote_hosts[7].ip4)
527
528 #
529 # An attached host route as yet unresolved out of pg2 for an
530 # undiscovered host, an ARP requests begets a response.
531 #
532 att_unnum1 = VppIpRoute(self, self.pg1.remote_hosts[8].ip4, 32,
533 [VppRoutePath("0.0.0.0",
534 self.pg2.sw_if_index)])
535 att_unnum1.add_vpp_config()
536
537 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
538 ARP(op="who-has",
539 hwsrc=self.pg2.remote_mac,
540 pdst=self.pg1.local_ip4,
541 psrc=self.pg1.remote_hosts[8].ip4))
542
543 self.pg2.add_stream(p)
544 self.pg_enable_capture(self.pg_interfaces)
545 self.pg_start()
546
547 rx = self.pg2.get_capture(1)
548 self.verify_arp_resp(rx[0],
549 self.pg2.local_mac,
550 self.pg2.remote_mac,
551 self.pg1.local_ip4,
552 self.pg1.remote_hosts[8].ip4)
553
554 #
Neale Ranns30d0fd42017-05-30 07:30:04 -0700555 # Send an ARP request from one of the so-far unlearned remote hosts
556 # with a VLAN0 tag
557 #
558 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
559 src=self.pg1._remote_hosts[9].mac) /
560 Dot1Q(vlan=0) /
561 ARP(op="who-has",
562 hwsrc=self.pg1._remote_hosts[9].mac,
563 pdst=self.pg1.local_ip4,
564 psrc=self.pg1._remote_hosts[9].ip4))
565
566 self.pg1.add_stream(p)
567 self.pg_enable_capture(self.pg_interfaces)
568 self.pg_start()
569
570 rx = self.pg1.get_capture(1)
571 self.verify_arp_resp(rx[0],
572 self.pg1.local_mac,
573 self.pg1._remote_hosts[9].mac,
574 self.pg1.local_ip4,
575 self.pg1._remote_hosts[9].ip4)
576
577 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700578 # Add a hierarchy of routes for a host in the sub-net.
Neale Rannsca193612017-06-14 06:50:08 -0700579 # Should still get an ARP resp since the cover is attached
580 #
581 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_mac) /
582 ARP(op="who-has",
583 hwsrc=self.pg1.remote_mac,
584 pdst=self.pg1.local_ip4,
585 psrc=self.pg1.remote_hosts[10].ip4))
586
587 r1 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 30,
588 [VppRoutePath(self.pg1.remote_hosts[10].ip4,
589 self.pg1.sw_if_index)])
590 r1.add_vpp_config()
591
592 self.pg1.add_stream(p)
593 self.pg_enable_capture(self.pg_interfaces)
594 self.pg_start()
595 rx = self.pg1.get_capture(1)
596 self.verify_arp_resp(rx[0],
597 self.pg1.local_mac,
598 self.pg1.remote_mac,
599 self.pg1.local_ip4,
600 self.pg1.remote_hosts[10].ip4)
601
602 r2 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 32,
603 [VppRoutePath(self.pg1.remote_hosts[10].ip4,
604 self.pg1.sw_if_index)])
605 r2.add_vpp_config()
606
607 self.pg1.add_stream(p)
608 self.pg_enable_capture(self.pg_interfaces)
609 self.pg_start()
610 rx = self.pg1.get_capture(1)
611 self.verify_arp_resp(rx[0],
612 self.pg1.local_mac,
613 self.pg1.remote_mac,
614 self.pg1.local_ip4,
615 self.pg1.remote_hosts[10].ip4)
616
617 #
618 # add an ARP entry that's not on the sub-net and so whose
619 # adj-fib fails the refinement check. then send an ARP request
620 # from that source
621 #
622 a1 = VppNeighbor(self,
623 self.pg0.sw_if_index,
624 self.pg0.remote_mac,
625 "100.100.100.50")
626 a1.add_vpp_config()
627
628 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
629 ARP(op="who-has",
630 hwsrc=self.pg0.remote_mac,
631 psrc="100.100.100.50",
632 pdst=self.pg0.remote_ip4))
633 self.send_and_assert_no_replies(self.pg0, p,
634 "ARP req for from failed adj-fib")
635
636 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800637 # ERROR Cases
638 # 1 - don't respond to ARP request for address not within the
639 # interface's sub-net
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700640 # 1b - nor within the unnumbered subnet
641 # 1c - nor within the subnet of a different interface
642 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800643 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
644 ARP(op="who-has",
645 hwsrc=self.pg0.remote_mac,
646 pdst="10.10.10.3",
647 psrc=self.pg0.remote_ip4))
648 self.send_and_assert_no_replies(self.pg0, p,
649 "ARP req for non-local destination")
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700650 self.assertFalse(find_nbr(self,
651 self.pg0.sw_if_index,
652 "10.10.10.3"))
653
Neale Ranns4b919a52017-03-11 05:55:21 -0800654 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
655 ARP(op="who-has",
656 hwsrc=self.pg2.remote_mac,
657 pdst="10.10.10.3",
658 psrc=self.pg1.remote_hosts[7].ip4))
659 self.send_and_assert_no_replies(
660 self.pg0, p,
661 "ARP req for non-local destination - unnum")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800662
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700663 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
664 ARP(op="who-has",
665 hwsrc=self.pg0.remote_mac,
666 pdst=self.pg1.local_ip4,
667 psrc=self.pg1.remote_ip4))
668 self.send_and_assert_no_replies(self.pg0, p,
669 "ARP req diff sub-net")
670 self.assertFalse(find_nbr(self,
671 self.pg0.sw_if_index,
672 self.pg1.remote_ip4))
673
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800674 #
675 # 2 - don't respond to ARP request from an address not within the
676 # interface's sub-net
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700677 # 2b - to a proxied address
678 # 2c - not within a different interface's sub-net
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800679 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
680 ARP(op="who-has",
681 hwsrc=self.pg0.remote_mac,
682 psrc="10.10.10.3",
683 pdst=self.pg0.local_ip4))
684 self.send_and_assert_no_replies(self.pg0, p,
685 "ARP req for non-local source")
Neale Ranns4b919a52017-03-11 05:55:21 -0800686 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
687 ARP(op="who-has",
688 hwsrc=self.pg2.remote_mac,
689 psrc="10.10.10.3",
690 pdst=self.pg0.local_ip4))
691 self.send_and_assert_no_replies(
692 self.pg0, p,
693 "ARP req for non-local source - unnum")
Neale Rannsca193612017-06-14 06:50:08 -0700694 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
695 ARP(op="who-has",
696 hwsrc=self.pg0.remote_mac,
697 psrc=self.pg1.remote_ip4,
698 pdst=self.pg0.local_ip4))
699 self.send_and_assert_no_replies(self.pg0, p,
700 "ARP req for non-local source 2c")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800701
702 #
703 # 3 - don't respond to ARP request from an address that belongs to
704 # the router
705 #
706 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
707 ARP(op="who-has",
708 hwsrc=self.pg0.remote_mac,
709 psrc=self.pg0.local_ip4,
710 pdst=self.pg0.local_ip4))
711 self.send_and_assert_no_replies(self.pg0, p,
712 "ARP req for non-local source")
713
714 #
715 # 4 - don't respond to ARP requests that has mac source different
716 # from ARP request HW source
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800717 #
718 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
719 ARP(op="who-has",
720 hwsrc="00:00:00:DE:AD:BE",
721 psrc=self.pg0.remote_ip4,
722 pdst=self.pg0.local_ip4))
723 self.send_and_assert_no_replies(self.pg0, p,
724 "ARP req for non-local source")
725
726 #
zhaoqinglingb4c42cd2017-12-23 15:20:59 +0800727 # 5 - don't respond to ARP requests for address within the
728 # interface's sub-net but not the interface's address
729 #
730 self.pg0.generate_remote_hosts(2)
731 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
732 ARP(op="who-has",
733 hwsrc=self.pg0.remote_mac,
734 psrc=self.pg0.remote_hosts[0].ip4,
735 pdst=self.pg0.remote_hosts[1].ip4))
736 self.send_and_assert_no_replies(self.pg0, p,
737 "ARP req for non-local destination")
738
739 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800740 # cleanup
741 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800742 static_arp.remove_vpp_config()
Neale Ranns3983ac22017-03-10 11:53:27 -0800743 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800744
Neale Ranns4b919a52017-03-11 05:55:21 -0800745 # need this to flush the adj-fibs
746 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
747 self.pg2.admin_down()
Neale Rannsca193612017-06-14 06:50:08 -0700748 self.pg1.admin_down()
Neale Ranns4b919a52017-03-11 05:55:21 -0800749
Neale Ranns24b170a2017-08-15 05:33:11 -0700750 def test_proxy_mirror_arp(self):
751 """ Interface Mirror Proxy ARP """
752
753 #
754 # When VPP has an interface whose address is also applied to a TAP
755 # interface on the host, then VPP's TAP interface will be unnumbered
756 # to the 'real' interface and do proxy ARP from the host.
757 # the curious aspect of this setup is that ARP requests from the host
758 # will come from the VPP's own address.
759 #
760 self.pg0.generate_remote_hosts(2)
761
762 arp_req_from_me = (Ether(src=self.pg2.remote_mac,
763 dst="ff:ff:ff:ff:ff:ff") /
764 ARP(op="who-has",
765 hwsrc=self.pg2.remote_mac,
766 pdst=self.pg0.remote_hosts[1].ip4,
767 psrc=self.pg0.local_ip4))
768
769 #
770 # Configure Proxy ARP for the subnet on PG0addresses on pg0
771 #
Ole Troan5c2a2372020-11-19 16:01:23 +0100772 self.vapi.proxy_arp_add_del(proxy={'table_id': 0,
773 'low': self.pg0._local_ip4_subnet,
774 'hi': self.pg0._local_ip4_bcast},
775 is_add=1)
Neale Ranns24b170a2017-08-15 05:33:11 -0700776
777 # Make pg2 un-numbered to pg0
778 #
779 self.pg2.set_unnumbered(self.pg0.sw_if_index)
780
781 #
782 # Enable pg2 for proxy ARP
783 #
784 self.pg2.set_proxy_arp()
785
786 #
787 # Send the ARP request with an originating address that
788 # is VPP's own address
789 #
Neale Ranns240dcb22020-04-23 09:04:59 +0000790 rx = self.send_and_expect(self.pg2, [arp_req_from_me], self.pg2)
Neale Ranns24b170a2017-08-15 05:33:11 -0700791 self.verify_arp_resp(rx[0],
792 self.pg2.local_mac,
793 self.pg2.remote_mac,
794 self.pg0.remote_hosts[1].ip4,
795 self.pg0.local_ip4)
796
797 #
798 # validate we have not learned an ARP entry as a result of this
799 #
800 self.assertFalse(find_nbr(self,
801 self.pg2.sw_if_index,
802 self.pg0.local_ip4))
803
804 #
Neale Ranns240dcb22020-04-23 09:04:59 +0000805 # setup a punt redirect so packets from the uplink go to the tap
806 #
Jakub Grajciar2df2f752020-12-01 11:23:44 +0100807 redirect = VppIpPuntRedirect(self, self.pg0.sw_if_index,
808 self.pg2.sw_if_index, self.pg0.local_ip4)
809 redirect.add_vpp_config()
Neale Ranns240dcb22020-04-23 09:04:59 +0000810
811 p_tcp = (Ether(src=self.pg0.remote_mac,
812 dst=self.pg0.local_mac,) /
813 IP(src=self.pg0.remote_ip4,
814 dst=self.pg0.local_ip4) /
815 TCP(sport=80, dport=80) /
816 Raw())
817 rx = self.send_and_expect(self.pg0, [p_tcp], self.pg2)
818
819 # there's no ARP entry so this is an ARP req
820 self.assertTrue(rx[0].haslayer(ARP))
821
822 # and ARP entry for VPP's pg0 address on the host interface
823 n1 = VppNeighbor(self,
824 self.pg2.sw_if_index,
825 self.pg2.remote_mac,
826 self.pg0.local_ip4,
827 is_no_fib_entry=True).add_vpp_config()
828 # now the packets shold forward
829 rx = self.send_and_expect(self.pg0, [p_tcp], self.pg2)
830 self.assertFalse(rx[0].haslayer(ARP))
831 self.assertEqual(rx[0][Ether].dst, self.pg2.remote_mac)
832
833 #
834 # flush the neighbor cache on the uplink
835 #
836 af = VppEnum.vl_api_address_family_t
837 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, self.pg0.sw_if_index)
838
839 # ensure we can still resolve the ARPs on the uplink
840 self.pg0.resolve_arp()
841
842 self.assertTrue(find_nbr(self,
843 self.pg0.sw_if_index,
844 self.pg0.remote_ip4))
845
846 #
Neale Ranns24b170a2017-08-15 05:33:11 -0700847 # cleanup
848 #
Ole Troan5c2a2372020-11-19 16:01:23 +0100849 self.vapi.proxy_arp_add_del(proxy={'table_id': 0,
850 'low': self.pg0._local_ip4_subnet,
851 'hi': self.pg0._local_ip4_bcast},
Neale Ranns24b170a2017-08-15 05:33:11 -0700852 is_add=0)
Jakub Grajciar2df2f752020-12-01 11:23:44 +0100853 redirect.remove_vpp_config()
Neale Ranns24b170a2017-08-15 05:33:11 -0700854
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800855 def test_proxy_arp(self):
856 """ Proxy ARP """
857
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700858 self.pg1.generate_remote_hosts(2)
859
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800860 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700861 # Proxy ARP request packets for each interface
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800862 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800863 arp_req_pg0 = (Ether(src=self.pg0.remote_mac,
864 dst="ff:ff:ff:ff:ff:ff") /
865 ARP(op="who-has",
866 hwsrc=self.pg0.remote_mac,
867 pdst="10.10.10.3",
868 psrc=self.pg0.remote_ip4))
Neale Ranns30d0fd42017-05-30 07:30:04 -0700869 arp_req_pg0_tagged = (Ether(src=self.pg0.remote_mac,
870 dst="ff:ff:ff:ff:ff:ff") /
871 Dot1Q(vlan=0) /
872 ARP(op="who-has",
873 hwsrc=self.pg0.remote_mac,
874 pdst="10.10.10.3",
875 psrc=self.pg0.remote_ip4))
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800876 arp_req_pg1 = (Ether(src=self.pg1.remote_mac,
877 dst="ff:ff:ff:ff:ff:ff") /
878 ARP(op="who-has",
879 hwsrc=self.pg1.remote_mac,
880 pdst="10.10.10.3",
881 psrc=self.pg1.remote_ip4))
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700882 arp_req_pg2 = (Ether(src=self.pg2.remote_mac,
883 dst="ff:ff:ff:ff:ff:ff") /
884 ARP(op="who-has",
885 hwsrc=self.pg2.remote_mac,
886 pdst="10.10.10.3",
887 psrc=self.pg1.remote_hosts[1].ip4))
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800888 arp_req_pg3 = (Ether(src=self.pg3.remote_mac,
889 dst="ff:ff:ff:ff:ff:ff") /
890 ARP(op="who-has",
891 hwsrc=self.pg3.remote_mac,
892 pdst="10.10.10.3",
893 psrc=self.pg3.remote_ip4))
894
895 #
896 # Configure Proxy ARP for 10.10.10.0 -> 10.10.10.124
897 #
Ole Troan5c2a2372020-11-19 16:01:23 +0100898 self.vapi.proxy_arp_add_del(proxy={'table_id': 0,
899 'low': "10.10.10.2",
900 'hi': "10.10.10.124"},
901 is_add=1)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800902
903 #
904 # No responses are sent when the interfaces are not enabled for proxy
905 # ARP
906 #
907 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
908 "ARP req from unconfigured interface")
909 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
910 "ARP req from unconfigured interface")
911
912 #
913 # Make pg2 un-numbered to pg1
914 # still won't reply.
915 #
916 self.pg2.set_unnumbered(self.pg1.sw_if_index)
917
918 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
919 "ARP req from unnumbered interface")
920
921 #
922 # Enable each interface to reply to proxy ARPs
923 #
924 for i in self.pg_interfaces:
925 i.set_proxy_arp()
926
927 #
928 # Now each of the interfaces should reply to a request to a proxied
929 # address
930 #
931 self.pg0.add_stream(arp_req_pg0)
932 self.pg_enable_capture(self.pg_interfaces)
933 self.pg_start()
934
935 rx = self.pg0.get_capture(1)
936 self.verify_arp_resp(rx[0],
937 self.pg0.local_mac,
938 self.pg0.remote_mac,
939 "10.10.10.3",
940 self.pg0.remote_ip4)
941
Neale Ranns30d0fd42017-05-30 07:30:04 -0700942 self.pg0.add_stream(arp_req_pg0_tagged)
943 self.pg_enable_capture(self.pg_interfaces)
944 self.pg_start()
945
946 rx = self.pg0.get_capture(1)
947 self.verify_arp_resp(rx[0],
948 self.pg0.local_mac,
949 self.pg0.remote_mac,
950 "10.10.10.3",
951 self.pg0.remote_ip4)
952
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800953 self.pg1.add_stream(arp_req_pg1)
954 self.pg_enable_capture(self.pg_interfaces)
955 self.pg_start()
956
957 rx = self.pg1.get_capture(1)
958 self.verify_arp_resp(rx[0],
959 self.pg1.local_mac,
960 self.pg1.remote_mac,
961 "10.10.10.3",
962 self.pg1.remote_ip4)
963
964 self.pg2.add_stream(arp_req_pg2)
965 self.pg_enable_capture(self.pg_interfaces)
966 self.pg_start()
967
968 rx = self.pg2.get_capture(1)
969 self.verify_arp_resp(rx[0],
970 self.pg2.local_mac,
971 self.pg2.remote_mac,
972 "10.10.10.3",
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700973 self.pg1.remote_hosts[1].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800974
975 #
976 # A request for an address out of the configured range
977 #
978 arp_req_pg1_hi = (Ether(src=self.pg1.remote_mac,
979 dst="ff:ff:ff:ff:ff:ff") /
980 ARP(op="who-has",
981 hwsrc=self.pg1.remote_mac,
982 pdst="10.10.10.125",
983 psrc=self.pg1.remote_ip4))
984 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_hi,
985 "ARP req out of range HI")
986 arp_req_pg1_low = (Ether(src=self.pg1.remote_mac,
987 dst="ff:ff:ff:ff:ff:ff") /
988 ARP(op="who-has",
989 hwsrc=self.pg1.remote_mac,
990 pdst="10.10.10.1",
991 psrc=self.pg1.remote_ip4))
992 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_low,
993 "ARP req out of range Low")
994
995 #
996 # Request for an address in the proxy range but from an interface
997 # in a different VRF
998 #
999 self.send_and_assert_no_replies(self.pg3, arp_req_pg3,
1000 "ARP req from different VRF")
1001
1002 #
1003 # Disable Each interface for proxy ARP
1004 # - expect none to respond
1005 #
1006 for i in self.pg_interfaces:
1007 i.set_proxy_arp(0)
1008
1009 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
1010 "ARP req from disable")
1011 self.send_and_assert_no_replies(self.pg1, arp_req_pg1,
1012 "ARP req from disable")
1013 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
1014 "ARP req from disable")
Neale Ranns37be7362017-02-21 17:30:26 -08001015
1016 #
1017 # clean up on interface 2
1018 #
Neale Ranns4b919a52017-03-11 05:55:21 -08001019 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns37be7362017-02-21 17:30:26 -08001020
1021 def test_mpls(self):
1022 """ MPLS """
1023
1024 #
1025 # Interface 2 does not yet have ip4 config
1026 #
1027 self.pg2.config_ip4()
1028 self.pg2.generate_remote_hosts(2)
1029
1030 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001031 # Add a route with out going label via an ARP unresolved next-hop
Neale Ranns37be7362017-02-21 17:30:26 -08001032 #
1033 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1034 [VppRoutePath(self.pg2.remote_hosts[1].ip4,
1035 self.pg2.sw_if_index,
1036 labels=[55])])
1037 ip_10_0_0_1.add_vpp_config()
1038
1039 #
1040 # packets should generate an ARP request
1041 #
1042 p = (Ether(src=self.pg0.remote_mac,
1043 dst=self.pg0.local_mac) /
1044 IP(src=self.pg0.remote_ip4, dst="10.0.0.1") /
1045 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01001046 Raw(b'\xa5' * 100))
Neale Ranns37be7362017-02-21 17:30:26 -08001047
1048 self.pg0.add_stream(p)
1049 self.pg_enable_capture(self.pg_interfaces)
1050 self.pg_start()
1051
1052 rx = self.pg2.get_capture(1)
1053 self.verify_arp_req(rx[0],
1054 self.pg2.local_mac,
1055 self.pg2.local_ip4,
1056 self.pg2._remote_hosts[1].ip4)
1057
1058 #
1059 # now resolve the neighbours
1060 #
1061 self.pg2.configure_ipv4_neighbors()
1062
1063 #
1064 # Now packet should be properly MPLS encapped.
1065 # This verifies that MPLS link-type adjacencies are completed
1066 # when the ARP entry resolves
1067 #
1068 self.pg0.add_stream(p)
1069 self.pg_enable_capture(self.pg_interfaces)
1070 self.pg_start()
1071
1072 rx = self.pg2.get_capture(1)
1073 self.verify_ip_o_mpls(rx[0],
1074 self.pg2.local_mac,
1075 self.pg2.remote_hosts[1].mac,
1076 55,
1077 self.pg0.remote_ip4,
1078 "10.0.0.1")
Neale Ranns4b919a52017-03-11 05:55:21 -08001079 self.pg2.unconfig_ip4()
Neale Ranns37be7362017-02-21 17:30:26 -08001080
Matthew Smithcb9ab472017-05-16 21:35:56 -05001081 def test_arp_vrrp(self):
1082 """ ARP reply with VRRP virtual src hw addr """
1083
1084 #
1085 # IP packet destined for pg1 remote host arrives on pg0 resulting
1086 # in an ARP request for the address of the remote host on pg1
1087 #
1088 p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1089 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1090 UDP(sport=1234, dport=1234) /
1091 Raw())
1092
Neale Ranns37029302018-08-10 05:30:06 -07001093 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
Matthew Smithcb9ab472017-05-16 21:35:56 -05001094
1095 self.verify_arp_req(rx1[0],
1096 self.pg1.local_mac,
1097 self.pg1.local_ip4,
1098 self.pg1.remote_ip4)
1099
1100 #
1101 # ARP reply for address of pg1 remote host arrives on pg1 with
1102 # the hw src addr set to a value in the VRRP IPv4 range of
1103 # MAC addresses
1104 #
1105 p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1106 ARP(op="is-at", hwdst=self.pg1.local_mac,
1107 hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
1108 psrc=self.pg1.remote_ip4))
1109
Neale Ranns37029302018-08-10 05:30:06 -07001110 self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
Matthew Smithcb9ab472017-05-16 21:35:56 -05001111
1112 #
1113 # IP packet destined for pg1 remote host arrives on pg0 again.
1114 # VPP should have an ARP entry for that address now and the packet
1115 # should be sent out pg1.
1116 #
Neale Ranns37029302018-08-10 05:30:06 -07001117 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
Matthew Smithcb9ab472017-05-16 21:35:56 -05001118
1119 self.verify_ip(rx1[0],
1120 self.pg1.local_mac,
1121 "00:00:5e:00:01:09",
1122 self.pg0.remote_ip4,
1123 self.pg1.remote_ip4)
1124
1125 self.pg1.admin_down()
1126 self.pg1.admin_up()
1127
Neale Rannsdcd6d622017-05-26 02:59:16 -07001128 def test_arp_duplicates(self):
1129 """ ARP Duplicates"""
1130
1131 #
1132 # Generate some hosts on the LAN
1133 #
1134 self.pg1.generate_remote_hosts(3)
1135
1136 #
1137 # Add host 1 on pg1 and pg2
1138 #
1139 arp_pg1 = VppNeighbor(self,
1140 self.pg1.sw_if_index,
1141 self.pg1.remote_hosts[1].mac,
1142 self.pg1.remote_hosts[1].ip4)
1143 arp_pg1.add_vpp_config()
1144 arp_pg2 = VppNeighbor(self,
1145 self.pg2.sw_if_index,
1146 self.pg2.remote_mac,
1147 self.pg1.remote_hosts[1].ip4)
1148 arp_pg2.add_vpp_config()
1149
1150 #
1151 # IP packet destined for pg1 remote host arrives on pg1 again.
1152 #
1153 p = (Ether(dst=self.pg0.local_mac,
1154 src=self.pg0.remote_mac) /
1155 IP(src=self.pg0.remote_ip4,
1156 dst=self.pg1.remote_hosts[1].ip4) /
1157 UDP(sport=1234, dport=1234) /
1158 Raw())
1159
1160 self.pg0.add_stream(p)
1161 self.pg_enable_capture(self.pg_interfaces)
1162 self.pg_start()
1163
1164 rx1 = self.pg1.get_capture(1)
1165
1166 self.verify_ip(rx1[0],
1167 self.pg1.local_mac,
1168 self.pg1.remote_hosts[1].mac,
1169 self.pg0.remote_ip4,
1170 self.pg1.remote_hosts[1].ip4)
1171
1172 #
1173 # remove the duplicate on pg1
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001174 # packet stream should generate ARPs out of pg1
Neale Rannsdcd6d622017-05-26 02:59:16 -07001175 #
1176 arp_pg1.remove_vpp_config()
1177
1178 self.pg0.add_stream(p)
1179 self.pg_enable_capture(self.pg_interfaces)
1180 self.pg_start()
1181
1182 rx1 = self.pg1.get_capture(1)
1183
1184 self.verify_arp_req(rx1[0],
1185 self.pg1.local_mac,
1186 self.pg1.local_ip4,
1187 self.pg1.remote_hosts[1].ip4)
1188
1189 #
1190 # Add it back
1191 #
1192 arp_pg1.add_vpp_config()
1193
1194 self.pg0.add_stream(p)
1195 self.pg_enable_capture(self.pg_interfaces)
1196 self.pg_start()
1197
1198 rx1 = self.pg1.get_capture(1)
1199
1200 self.verify_ip(rx1[0],
1201 self.pg1.local_mac,
1202 self.pg1.remote_hosts[1].mac,
1203 self.pg0.remote_ip4,
1204 self.pg1.remote_hosts[1].ip4)
1205
Neale Ranns15002542017-09-10 04:39:11 -07001206 def test_arp_static(self):
1207 """ ARP Static"""
1208 self.pg2.generate_remote_hosts(3)
1209
1210 #
1211 # Add a static ARP entry
1212 #
1213 static_arp = VppNeighbor(self,
1214 self.pg2.sw_if_index,
1215 self.pg2.remote_hosts[1].mac,
1216 self.pg2.remote_hosts[1].ip4,
1217 is_static=1)
1218 static_arp.add_vpp_config()
1219
1220 #
1221 # Add the connected prefix to the interface
1222 #
1223 self.pg2.config_ip4()
1224
1225 #
1226 # We should now find the adj-fib
1227 #
1228 self.assertTrue(find_nbr(self,
1229 self.pg2.sw_if_index,
1230 self.pg2.remote_hosts[1].ip4,
1231 is_static=1))
1232 self.assertTrue(find_route(self,
1233 self.pg2.remote_hosts[1].ip4,
1234 32))
1235
1236 #
1237 # remove the connected
1238 #
1239 self.pg2.unconfig_ip4()
1240
1241 #
1242 # put the interface into table 1
1243 #
1244 self.pg2.set_table_ip4(1)
1245
1246 #
1247 # configure the same connected and expect to find the
1248 # adj fib in the new table
1249 #
1250 self.pg2.config_ip4()
1251 self.assertTrue(find_route(self,
1252 self.pg2.remote_hosts[1].ip4,
1253 32,
1254 table_id=1))
1255
1256 #
1257 # clean-up
1258 #
1259 self.pg2.unconfig_ip4()
Neale Rannscbe25aa2019-09-30 10:53:31 +00001260 static_arp.remove_vpp_config()
Neale Ranns15002542017-09-10 04:39:11 -07001261 self.pg2.set_table_ip4(0)
1262
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001263 def test_arp_static_replace_dynamic_same_mac(self):
1264 """ ARP Static can replace Dynamic (same mac) """
1265 self.pg2.generate_remote_hosts(1)
1266
1267 dyn_arp = VppNeighbor(self,
1268 self.pg2.sw_if_index,
1269 self.pg2.remote_hosts[0].mac,
1270 self.pg2.remote_hosts[0].ip4)
1271 static_arp = VppNeighbor(self,
1272 self.pg2.sw_if_index,
1273 self.pg2.remote_hosts[0].mac,
1274 self.pg2.remote_hosts[0].ip4,
1275 is_static=1)
1276
1277 #
1278 # Add a dynamic ARP entry
1279 #
1280 dyn_arp.add_vpp_config()
1281
1282 #
1283 # We should find the dynamic nbr
1284 #
1285 self.assertFalse(find_nbr(self,
1286 self.pg2.sw_if_index,
1287 self.pg2.remote_hosts[0].ip4,
1288 is_static=1))
1289 self.assertTrue(find_nbr(self,
1290 self.pg2.sw_if_index,
1291 self.pg2.remote_hosts[0].ip4,
1292 is_static=0,
1293 mac=self.pg2.remote_hosts[0].mac))
1294
1295 #
1296 # Add a static ARP entry with the same mac
1297 #
1298 static_arp.add_vpp_config()
1299
1300 #
1301 # We should now find the static nbr with the same mac
1302 #
1303 self.assertFalse(find_nbr(self,
1304 self.pg2.sw_if_index,
1305 self.pg2.remote_hosts[0].ip4,
1306 is_static=0))
1307 self.assertTrue(find_nbr(self,
1308 self.pg2.sw_if_index,
1309 self.pg2.remote_hosts[0].ip4,
1310 is_static=1,
1311 mac=self.pg2.remote_hosts[0].mac))
1312
1313 #
1314 # clean-up
1315 #
1316 static_arp.remove_vpp_config()
1317
1318 def test_arp_static_replace_dynamic_diff_mac(self):
1319 """ ARP Static can replace Dynamic (diff mac) """
1320 self.pg2.generate_remote_hosts(2)
1321
1322 dyn_arp = VppNeighbor(self,
1323 self.pg2.sw_if_index,
1324 self.pg2.remote_hosts[0].mac,
1325 self.pg2.remote_hosts[0].ip4)
1326 static_arp = VppNeighbor(self,
1327 self.pg2.sw_if_index,
1328 self.pg2.remote_hosts[1].mac,
1329 self.pg2.remote_hosts[0].ip4,
1330 is_static=1)
1331
1332 #
1333 # Add a dynamic ARP entry
1334 #
1335 dyn_arp.add_vpp_config()
1336
1337 #
1338 # We should find the dynamic nbr
1339 #
1340 self.assertFalse(find_nbr(self,
1341 self.pg2.sw_if_index,
1342 self.pg2.remote_hosts[0].ip4,
1343 is_static=1))
1344 self.assertTrue(find_nbr(self,
1345 self.pg2.sw_if_index,
1346 self.pg2.remote_hosts[0].ip4,
1347 is_static=0,
1348 mac=self.pg2.remote_hosts[0].mac))
1349
1350 #
1351 # Add a static ARP entry with a changed mac
1352 #
1353 static_arp.add_vpp_config()
1354
1355 #
1356 # We should now find the static nbr with a changed mac
1357 #
1358 self.assertFalse(find_nbr(self,
1359 self.pg2.sw_if_index,
1360 self.pg2.remote_hosts[0].ip4,
1361 is_static=0))
1362 self.assertTrue(find_nbr(self,
1363 self.pg2.sw_if_index,
1364 self.pg2.remote_hosts[0].ip4,
1365 is_static=1,
1366 mac=self.pg2.remote_hosts[1].mac))
1367
1368 #
1369 # clean-up
1370 #
1371 static_arp.remove_vpp_config()
1372
Neale Rannsc819fc62018-02-16 02:44:05 -08001373 def test_arp_incomplete(self):
1374 """ ARP Incomplete"""
1375 self.pg1.generate_remote_hosts(3)
1376
1377 p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1378 IP(src=self.pg0.remote_ip4,
1379 dst=self.pg1.remote_hosts[1].ip4) /
1380 UDP(sport=1234, dport=1234) /
1381 Raw())
1382 p1 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1383 IP(src=self.pg0.remote_ip4,
1384 dst=self.pg1.remote_hosts[2].ip4) /
1385 UDP(sport=1234, dport=1234) /
1386 Raw())
1387
1388 #
1389 # a packet to an unresolved destination generates an ARP request
1390 #
1391 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1392 self.verify_arp_req(rx[0],
1393 self.pg1.local_mac,
1394 self.pg1.local_ip4,
1395 self.pg1._remote_hosts[1].ip4)
1396
1397 #
1398 # add a neighbour for remote host 1
1399 #
1400 static_arp = VppNeighbor(self,
1401 self.pg1.sw_if_index,
1402 self.pg1.remote_hosts[1].mac,
1403 self.pg1.remote_hosts[1].ip4,
1404 is_static=1)
1405 static_arp.add_vpp_config()
1406
1407 #
1408 # change the interface's MAC
1409 #
Neale Rannsc819fc62018-02-16 02:44:05 -08001410 self.vapi.sw_interface_set_mac_address(self.pg1.sw_if_index,
Neale Ranns77f91622020-11-23 16:25:27 +00001411 "00:00:00:33:33:33")
Neale Rannsc819fc62018-02-16 02:44:05 -08001412
1413 #
1414 # now ARP requests come from the new source mac
1415 #
1416 rx = self.send_and_expect(self.pg0, [p1], self.pg1)
1417 self.verify_arp_req(rx[0],
1418 "00:00:00:33:33:33",
1419 self.pg1.local_ip4,
1420 self.pg1._remote_hosts[2].ip4)
1421
1422 #
1423 # packets to the resolved host also have the new source mac
1424 #
1425 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1426 self.verify_ip(rx[0],
1427 "00:00:00:33:33:33",
1428 self.pg1.remote_hosts[1].mac,
1429 self.pg0.remote_ip4,
1430 self.pg1.remote_hosts[1].ip4)
1431
1432 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001433 # set the mac address on the interface that does not have a
Neale Rannsc819fc62018-02-16 02:44:05 -08001434 # configured subnet and thus no glean
1435 #
1436 self.vapi.sw_interface_set_mac_address(self.pg2.sw_if_index,
Neale Ranns77f91622020-11-23 16:25:27 +00001437 "00:00:00:33:33:33")
Neale Rannsc819fc62018-02-16 02:44:05 -08001438
Neale Ranns59ae61e2018-06-07 18:09:49 -07001439 def test_garp(self):
1440 """ GARP """
1441
1442 #
1443 # Generate some hosts on the LAN
1444 #
1445 self.pg1.generate_remote_hosts(4)
Neale Ranns22eefd72020-09-23 11:25:21 +00001446 self.pg2.generate_remote_hosts(4)
Neale Ranns59ae61e2018-06-07 18:09:49 -07001447
1448 #
1449 # And an ARP entry
1450 #
1451 arp = VppNeighbor(self,
1452 self.pg1.sw_if_index,
1453 self.pg1.remote_hosts[1].mac,
1454 self.pg1.remote_hosts[1].ip4)
1455 arp.add_vpp_config()
1456
1457 self.assertTrue(find_nbr(self,
1458 self.pg1.sw_if_index,
1459 self.pg1.remote_hosts[1].ip4,
1460 mac=self.pg1.remote_hosts[1].mac))
1461
1462 #
1463 # Send a GARP (request) to swap the host 1's address to that of host 2
1464 #
1465 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1466 src=self.pg1.remote_hosts[2].mac) /
1467 ARP(op="who-has",
1468 hwdst=self.pg1.local_mac,
1469 hwsrc=self.pg1.remote_hosts[2].mac,
1470 pdst=self.pg1.remote_hosts[1].ip4,
1471 psrc=self.pg1.remote_hosts[1].ip4))
1472
1473 self.pg1.add_stream(p1)
1474 self.pg_enable_capture(self.pg_interfaces)
1475 self.pg_start()
1476
1477 self.assertTrue(find_nbr(self,
1478 self.pg1.sw_if_index,
1479 self.pg1.remote_hosts[1].ip4,
1480 mac=self.pg1.remote_hosts[2].mac))
1481
1482 #
1483 # Send a GARP (reply) to swap the host 1's address to that of host 3
1484 #
1485 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1486 src=self.pg1.remote_hosts[3].mac) /
1487 ARP(op="is-at",
1488 hwdst=self.pg1.local_mac,
1489 hwsrc=self.pg1.remote_hosts[3].mac,
1490 pdst=self.pg1.remote_hosts[1].ip4,
1491 psrc=self.pg1.remote_hosts[1].ip4))
1492
1493 self.pg1.add_stream(p1)
1494 self.pg_enable_capture(self.pg_interfaces)
1495 self.pg_start()
1496
1497 self.assertTrue(find_nbr(self,
1498 self.pg1.sw_if_index,
1499 self.pg1.remote_hosts[1].ip4,
1500 mac=self.pg1.remote_hosts[3].mac))
1501
1502 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001503 # GARPs (request nor replies) for host we don't know yet
Neale Ranns59ae61e2018-06-07 18:09:49 -07001504 # don't result in new neighbour entries
1505 #
1506 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1507 src=self.pg1.remote_hosts[3].mac) /
1508 ARP(op="who-has",
1509 hwdst=self.pg1.local_mac,
1510 hwsrc=self.pg1.remote_hosts[3].mac,
1511 pdst=self.pg1.remote_hosts[2].ip4,
1512 psrc=self.pg1.remote_hosts[2].ip4))
1513
1514 self.pg1.add_stream(p1)
1515 self.pg_enable_capture(self.pg_interfaces)
1516 self.pg_start()
1517
1518 self.assertFalse(find_nbr(self,
1519 self.pg1.sw_if_index,
1520 self.pg1.remote_hosts[2].ip4))
1521
1522 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1523 src=self.pg1.remote_hosts[3].mac) /
1524 ARP(op="is-at",
1525 hwdst=self.pg1.local_mac,
1526 hwsrc=self.pg1.remote_hosts[3].mac,
1527 pdst=self.pg1.remote_hosts[2].ip4,
1528 psrc=self.pg1.remote_hosts[2].ip4))
1529
1530 self.pg1.add_stream(p1)
1531 self.pg_enable_capture(self.pg_interfaces)
1532 self.pg_start()
1533
1534 self.assertFalse(find_nbr(self,
1535 self.pg1.sw_if_index,
1536 self.pg1.remote_hosts[2].ip4))
1537
Neale Ranns22eefd72020-09-23 11:25:21 +00001538 #
1539 # IP address in different subnets are not learnt
1540 #
1541 self.pg2.configure_ipv4_neighbors()
1542
1543 for op in ["is-at", "who-has"]:
1544 p1 = [(Ether(dst="ff:ff:ff:ff:ff:ff",
1545 src=self.pg2.remote_hosts[1].mac) /
1546 ARP(op=op,
1547 hwdst=self.pg2.local_mac,
1548 hwsrc=self.pg2.remote_hosts[1].mac,
1549 pdst=self.pg2.remote_hosts[1].ip4,
1550 psrc=self.pg2.remote_hosts[1].ip4)),
1551 (Ether(dst="ff:ff:ff:ff:ff:ff",
1552 src=self.pg2.remote_hosts[1].mac) /
1553 ARP(op=op,
1554 hwdst="ff:ff:ff:ff:ff:ff",
1555 hwsrc=self.pg2.remote_hosts[1].mac,
1556 pdst=self.pg2.remote_hosts[1].ip4,
1557 psrc=self.pg2.remote_hosts[1].ip4))]
1558
1559 self.send_and_assert_no_replies(self.pg1, p1)
1560 self.assertFalse(find_nbr(self,
1561 self.pg1.sw_if_index,
1562 self.pg2.remote_hosts[1].ip4))
1563
1564 # they are all dropped because the subnet's don't match
1565 self.assertEqual(4, self.statistics.get_err_counter(
1566 "/err/arp-reply/IP4 destination address not local to subnet"))
1567
Neale Ranns77f91622020-11-23 16:25:27 +00001568 def test_arp_incomplete2(self):
Neale Ranns14260392018-09-28 05:00:57 -07001569 """ Incomplete Entries """
Neale Rannsc8352bc2018-08-29 10:23:58 -07001570
1571 #
Neale Rannscd35e532018-08-31 02:51:45 -07001572 # ensure that we throttle the ARP and ND requests
Neale Rannsc8352bc2018-08-29 10:23:58 -07001573 #
1574 self.pg0.generate_remote_hosts(2)
1575
Neale Rannscd35e532018-08-31 02:51:45 -07001576 #
1577 # IPv4/ARP
1578 #
Neale Rannsc8352bc2018-08-29 10:23:58 -07001579 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1580 [VppRoutePath(self.pg0.remote_hosts[1].ip4,
Neale Rannscd35e532018-08-31 02:51:45 -07001581 self.pg0.sw_if_index)])
Neale Rannsc8352bc2018-08-29 10:23:58 -07001582 ip_10_0_0_1.add_vpp_config()
1583
1584 p1 = (Ether(dst=self.pg1.local_mac,
1585 src=self.pg1.remote_mac) /
1586 IP(src=self.pg1.remote_ip4,
1587 dst="10.0.0.1") /
1588 UDP(sport=1234, dport=1234) /
1589 Raw())
1590
1591 self.pg1.add_stream(p1 * 257)
1592 self.pg_enable_capture(self.pg_interfaces)
1593 self.pg_start()
1594 rx = self.pg0._get_capture(1)
1595
1596 #
1597 # how many we get is going to be dependent on the time for packet
1598 # processing but it should be small
1599 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001600 self.assertLess(len(rx), 64)
Neale Rannsc8352bc2018-08-29 10:23:58 -07001601
Neale Rannscd35e532018-08-31 02:51:45 -07001602 #
1603 # IPv6/ND
1604 #
1605 ip_10_1 = VppIpRoute(self, "10::1", 128,
1606 [VppRoutePath(self.pg0.remote_hosts[1].ip6,
1607 self.pg0.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07001608 proto=DpoProto.DPO_PROTO_IP6)])
Neale Rannscd35e532018-08-31 02:51:45 -07001609 ip_10_1.add_vpp_config()
1610
1611 p1 = (Ether(dst=self.pg1.local_mac,
1612 src=self.pg1.remote_mac) /
1613 IPv6(src=self.pg1.remote_ip6,
1614 dst="10::1") /
1615 UDP(sport=1234, dport=1234) /
1616 Raw())
1617
1618 self.pg1.add_stream(p1 * 257)
1619 self.pg_enable_capture(self.pg_interfaces)
1620 self.pg_start()
1621 rx = self.pg0._get_capture(1)
1622
1623 #
1624 # how many we get is going to be dependent on the time for packet
1625 # processing but it should be small
1626 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001627 self.assertLess(len(rx), 64)
Neale Rannscd35e532018-08-31 02:51:45 -07001628
Neale Ranns7425f922019-01-23 00:36:16 -08001629 def test_arp_forus(self):
1630 """ ARP for for-us """
1631
1632 #
1633 # Test that VPP responds with ARP requests to addresses that
1634 # are connected and local routes.
1635 # Use one of the 'remote' addresses in the subnet as a local address
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001636 # The intention of this route is that it then acts like a secondary
Neale Ranns7425f922019-01-23 00:36:16 -08001637 # address added to an interface
1638 #
1639 self.pg0.generate_remote_hosts(2)
1640
Neale Ranns097fa662018-05-01 05:17:55 -07001641 forus = VppIpRoute(
1642 self, self.pg0.remote_hosts[1].ip4, 32,
1643 [VppRoutePath("0.0.0.0",
1644 self.pg0.sw_if_index,
1645 type=FibPathType.FIB_PATH_TYPE_LOCAL)])
Neale Ranns7425f922019-01-23 00:36:16 -08001646 forus.add_vpp_config()
1647
1648 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
1649 src=self.pg0.remote_mac) /
1650 ARP(op="who-has",
1651 hwdst=self.pg0.local_mac,
1652 hwsrc=self.pg0.remote_mac,
1653 pdst=self.pg0.remote_hosts[1].ip4,
1654 psrc=self.pg0.remote_ip4))
1655
1656 rx = self.send_and_expect(self.pg0, [p], self.pg0)
1657
1658 self.verify_arp_resp(rx[0],
1659 self.pg0.local_mac,
1660 self.pg0.remote_mac,
1661 self.pg0.remote_hosts[1].ip4,
1662 self.pg0.remote_ip4)
1663
Neale Rannsfca3c6a2019-12-31 03:49:34 +00001664 def test_arp_table_swap(self):
1665 #
1666 # Generate some hosts on the LAN
1667 #
1668 N_NBRS = 4
1669 self.pg1.generate_remote_hosts(N_NBRS)
1670
1671 for n in range(N_NBRS):
1672 # a route thru each neighbour
1673 VppIpRoute(self, "10.0.0.%d" % n, 32,
1674 [VppRoutePath(self.pg1.remote_hosts[n].ip4,
1675 self.pg1.sw_if_index)]).add_vpp_config()
1676
1677 # resolve each neighbour
1678 p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1679 ARP(op="is-at", hwdst=self.pg1.local_mac,
1680 hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
1681 psrc=self.pg1.remote_hosts[n].ip4))
1682
1683 self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
1684
1685 self.logger.info(self.vapi.cli("sh ip neighbors"))
1686
1687 #
1688 # swap the table pg1 is in
1689 #
1690 table = VppIpTable(self, 100).add_vpp_config()
1691
1692 self.pg1.unconfig_ip4()
1693 self.pg1.set_table_ip4(100)
1694 self.pg1.config_ip4()
1695
1696 #
1697 # all neighbours are cleared
1698 #
1699 for n in range(N_NBRS):
1700 self.assertFalse(find_nbr(self,
1701 self.pg1.sw_if_index,
1702 self.pg1.remote_hosts[n].ip4))
1703
1704 #
1705 # packets to all neighbours generate ARP requests
1706 #
1707 for n in range(N_NBRS):
1708 # a route thru each neighbour
1709 VppIpRoute(self, "10.0.0.%d" % n, 32,
1710 [VppRoutePath(self.pg1.remote_hosts[n].ip4,
1711 self.pg1.sw_if_index)],
1712 table_id=100).add_vpp_config()
1713
1714 p = (Ether(src=self.pg1.remote_hosts[n].mac,
1715 dst=self.pg1.local_mac) /
1716 IP(src=self.pg1.remote_hosts[n].ip4,
1717 dst="10.0.0.%d" % n) /
1718 Raw(b'0x5' * 100))
1719 rxs = self.send_and_expect(self.pg1, [p], self.pg1)
1720 for rx in rxs:
1721 self.verify_arp_req(rx,
1722 self.pg1.local_mac,
1723 self.pg1.local_ip4,
1724 self.pg1.remote_hosts[n].ip4)
1725
1726 self.pg1.unconfig_ip4()
1727 self.pg1.set_table_ip4(0)
1728
Neale Rannse2fe0972020-11-26 08:37:27 +00001729 def test_glean_src_select(self):
1730 """ Multi Connecteds """
1731
1732 #
1733 # configure multiple connected subnets on an interface
1734 # and ensure that ARP requests for hosts on those subnets
1735 # pick up the correct source address
1736 #
1737 conn1 = VppIpInterfaceAddress(self, self.pg1,
1738 "10.0.0.1", 24).add_vpp_config()
1739 conn2 = VppIpInterfaceAddress(self, self.pg1,
1740 "10.0.1.1", 24).add_vpp_config()
1741
1742 p1 = (Ether(src=self.pg0.remote_mac,
1743 dst=self.pg0.local_mac) /
1744 IP(src=self.pg1.remote_ip4,
1745 dst="10.0.0.128") /
1746 Raw(b'0x5' * 100))
1747
1748 rxs = self.send_and_expect(self.pg0, [p1], self.pg1)
1749 for rx in rxs:
1750 self.verify_arp_req(rx,
1751 self.pg1.local_mac,
1752 "10.0.0.1",
1753 "10.0.0.128")
1754
1755 p2 = (Ether(src=self.pg0.remote_mac,
1756 dst=self.pg0.local_mac) /
1757 IP(src=self.pg1.remote_ip4,
1758 dst="10.0.1.128") /
1759 Raw(b'0x5' * 100))
1760
1761 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
1762 for rx in rxs:
1763 self.verify_arp_req(rx,
1764 self.pg1.local_mac,
1765 "10.0.1.1",
1766 "10.0.1.128")
1767
1768 #
1769 # add a local address in the same subnet
1770 # the source addresses are equivalent. VPP happens to
1771 # choose the last one that was added
1772 conn3 = VppIpInterfaceAddress(self, self.pg1,
1773 "10.0.1.2", 24).add_vpp_config()
1774
1775 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
1776 for rx in rxs:
1777 self.verify_arp_req(rx,
1778 self.pg1.local_mac,
1779 "10.0.1.2",
1780 "10.0.1.128")
1781
1782 #
1783 # remove
1784 #
1785 conn3.remove_vpp_config()
1786 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
1787 for rx in rxs:
1788 self.verify_arp_req(rx,
1789 self.pg1.local_mac,
1790 "10.0.1.1",
1791 "10.0.1.128")
1792
1793 #
1794 # add back, this time remove the first one
1795 #
1796 conn3 = VppIpInterfaceAddress(self, self.pg1,
1797 "10.0.1.2", 24).add_vpp_config()
1798
1799 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
1800 for rx in rxs:
1801 self.verify_arp_req(rx,
1802 self.pg1.local_mac,
1803 "10.0.1.2",
1804 "10.0.1.128")
1805
1806 conn1.remove_vpp_config()
1807 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
1808 for rx in rxs:
1809 self.verify_arp_req(rx,
1810 self.pg1.local_mac,
1811 "10.0.1.2",
1812 "10.0.1.128")
1813
Neale Ranns66edaf22021-07-09 13:03:52 +00001814 # apply a connected prefix to an interface in a different table
1815 VppIpRoute(self, "10.0.1.0", 24,
1816 [VppRoutePath("0.0.0.0",
1817 self.pg1.sw_if_index)],
1818 table_id=1).add_vpp_config()
1819
1820 rxs = self.send_and_expect(self.pg3, [p2], self.pg1)
1821 for rx in rxs:
1822 self.verify_arp_req(rx,
1823 self.pg1.local_mac,
1824 "10.0.1.2",
1825 "10.0.1.128")
1826
Neale Rannse2fe0972020-11-26 08:37:27 +00001827 # cleanup
1828 conn3.remove_vpp_config()
1829 conn2.remove_vpp_config()
1830
Neale Rannsdcd6d622017-05-26 02:59:16 -07001831
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00001832@tag_fixme_vpp_workers
Neale Ranns14260392018-09-28 05:00:57 -07001833class NeighborStatsTestCase(VppTestCase):
Neale Ranns37029302018-08-10 05:30:06 -07001834 """ ARP/ND Counters """
Neale Ranns14260392018-09-28 05:00:57 -07001835
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001836 @classmethod
1837 def setUpClass(cls):
1838 super(NeighborStatsTestCase, cls).setUpClass()
1839
1840 @classmethod
1841 def tearDownClass(cls):
1842 super(NeighborStatsTestCase, cls).tearDownClass()
1843
Neale Ranns14260392018-09-28 05:00:57 -07001844 def setUp(self):
1845 super(NeighborStatsTestCase, self).setUp()
1846
1847 self.create_pg_interfaces(range(2))
1848
1849 # pg0 configured with ip4 and 6 addresses used for input
1850 # pg1 configured with ip4 and 6 addresses used for output
1851 # pg2 is unnumbered to pg0
1852 for i in self.pg_interfaces:
1853 i.admin_up()
1854 i.config_ip4()
1855 i.config_ip6()
1856 i.resolve_arp()
1857 i.resolve_ndp()
1858
1859 def tearDown(self):
1860 super(NeighborStatsTestCase, self).tearDown()
1861
1862 for i in self.pg_interfaces:
1863 i.unconfig_ip4()
1864 i.unconfig_ip6()
1865 i.admin_down()
1866
1867 def test_arp_stats(self):
1868 """ ARP Counters """
1869
1870 self.vapi.cli("adj counters enable")
1871 self.pg1.generate_remote_hosts(2)
1872
1873 arp1 = VppNeighbor(self,
1874 self.pg1.sw_if_index,
1875 self.pg1.remote_hosts[0].mac,
1876 self.pg1.remote_hosts[0].ip4)
1877 arp1.add_vpp_config()
1878 arp2 = VppNeighbor(self,
1879 self.pg1.sw_if_index,
1880 self.pg1.remote_hosts[1].mac,
1881 self.pg1.remote_hosts[1].ip4)
1882 arp2.add_vpp_config()
1883
1884 p1 = (Ether(dst=self.pg0.local_mac,
1885 src=self.pg0.remote_mac) /
1886 IP(src=self.pg0.remote_ip4,
1887 dst=self.pg1.remote_hosts[0].ip4) /
1888 UDP(sport=1234, dport=1234) /
1889 Raw())
1890 p2 = (Ether(dst=self.pg0.local_mac,
1891 src=self.pg0.remote_mac) /
1892 IP(src=self.pg0.remote_ip4,
1893 dst=self.pg1.remote_hosts[1].ip4) /
1894 UDP(sport=1234, dport=1234) /
1895 Raw())
1896
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001897 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
1898 rx = self.send_and_expect(self.pg0, p2 * NUM_PKTS, self.pg1)
Neale Ranns14260392018-09-28 05:00:57 -07001899
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001900 self.assertEqual(NUM_PKTS, arp1.get_stats()['packets'])
1901 self.assertEqual(NUM_PKTS, arp2.get_stats()['packets'])
Neale Ranns14260392018-09-28 05:00:57 -07001902
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001903 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
1904 self.assertEqual(NUM_PKTS*2, arp1.get_stats()['packets'])
Neale Ranns14260392018-09-28 05:00:57 -07001905
1906 def test_nd_stats(self):
1907 """ ND Counters """
1908
1909 self.vapi.cli("adj counters enable")
1910 self.pg0.generate_remote_hosts(3)
1911
1912 nd1 = VppNeighbor(self,
1913 self.pg0.sw_if_index,
1914 self.pg0.remote_hosts[1].mac,
Neale Ranns37029302018-08-10 05:30:06 -07001915 self.pg0.remote_hosts[1].ip6)
Neale Ranns14260392018-09-28 05:00:57 -07001916 nd1.add_vpp_config()
1917 nd2 = VppNeighbor(self,
1918 self.pg0.sw_if_index,
1919 self.pg0.remote_hosts[2].mac,
Neale Ranns37029302018-08-10 05:30:06 -07001920 self.pg0.remote_hosts[2].ip6)
Neale Ranns14260392018-09-28 05:00:57 -07001921 nd2.add_vpp_config()
1922
1923 p1 = (Ether(dst=self.pg1.local_mac,
1924 src=self.pg1.remote_mac) /
1925 IPv6(src=self.pg1.remote_ip6,
1926 dst=self.pg0.remote_hosts[1].ip6) /
1927 UDP(sport=1234, dport=1234) /
1928 Raw())
1929 p2 = (Ether(dst=self.pg1.local_mac,
1930 src=self.pg1.remote_mac) /
1931 IPv6(src=self.pg1.remote_ip6,
1932 dst=self.pg0.remote_hosts[2].ip6) /
1933 UDP(sport=1234, dport=1234) /
1934 Raw())
1935
1936 rx = self.send_and_expect(self.pg1, p1 * 16, self.pg0)
1937 rx = self.send_and_expect(self.pg1, p2 * 16, self.pg0)
1938
1939 self.assertEqual(16, nd1.get_stats()['packets'])
1940 self.assertEqual(16, nd2.get_stats()['packets'])
1941
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001942 rx = self.send_and_expect(self.pg1, p1 * NUM_PKTS, self.pg0)
1943 self.assertEqual(NUM_PKTS+16, nd1.get_stats()['packets'])
Neale Ranns14260392018-09-28 05:00:57 -07001944
1945
Neale Rannscbe25aa2019-09-30 10:53:31 +00001946class NeighborAgeTestCase(VppTestCase):
1947 """ ARP/ND Aging """
1948
1949 @classmethod
1950 def setUpClass(cls):
1951 super(NeighborAgeTestCase, cls).setUpClass()
1952
1953 @classmethod
1954 def tearDownClass(cls):
1955 super(NeighborAgeTestCase, cls).tearDownClass()
1956
1957 def setUp(self):
1958 super(NeighborAgeTestCase, self).setUp()
1959
1960 self.create_pg_interfaces(range(1))
1961
1962 # pg0 configured with ip4 and 6 addresses used for input
1963 # pg1 configured with ip4 and 6 addresses used for output
1964 # pg2 is unnumbered to pg0
1965 for i in self.pg_interfaces:
1966 i.admin_up()
1967 i.config_ip4()
1968 i.config_ip6()
1969 i.resolve_arp()
1970 i.resolve_ndp()
1971
1972 def tearDown(self):
1973 super(NeighborAgeTestCase, self).tearDown()
1974
1975 for i in self.pg_interfaces:
1976 i.unconfig_ip4()
1977 i.unconfig_ip6()
1978 i.admin_down()
1979
1980 def wait_for_no_nbr(self, intf, address,
1981 n_tries=50, s_time=1):
1982 while (n_tries):
1983 if not find_nbr(self, intf, address):
1984 return True
1985 n_tries = n_tries - 1
1986 self.sleep(s_time)
1987
1988 return False
1989
1990 def verify_arp_req(self, rx, smac, sip, dip):
1991 ether = rx[Ether]
1992 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
1993 self.assertEqual(ether.src, smac)
1994
1995 arp = rx[ARP]
1996 self.assertEqual(arp.hwtype, 1)
1997 self.assertEqual(arp.ptype, 0x800)
1998 self.assertEqual(arp.hwlen, 6)
1999 self.assertEqual(arp.plen, 4)
2000 self.assertEqual(arp.op, arp_opts["who-has"])
2001 self.assertEqual(arp.hwsrc, smac)
2002 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
2003 self.assertEqual(arp.psrc, sip)
2004 self.assertEqual(arp.pdst, dip)
2005
2006 def test_age(self):
2007 """ Aging/Recycle """
2008
2009 self.vapi.cli("set logging unthrottle 0")
2010 self.vapi.cli("set logging size %d" % 0xffff)
2011
2012 self.pg0.generate_remote_hosts(201)
2013
2014 vaf = VppEnum.vl_api_address_family_t
2015
2016 #
2017 # start listening on all interfaces
2018 #
2019 self.pg_enable_capture(self.pg_interfaces)
2020
2021 #
2022 # Set the neighbor configuration:
2023 # limi = 200
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002024 # age = 0 seconds
Neale Rannscbe25aa2019-09-30 10:53:31 +00002025 # recycle = false
2026 #
2027 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
2028 max_number=200,
2029 max_age=0,
2030 recycle=False)
2031
2032 self.vapi.cli("sh ip neighbor-config")
2033
2034 # add the 198 neighbours that should pass (-1 for one created in setup)
2035 for ii in range(200):
2036 VppNeighbor(self,
2037 self.pg0.sw_if_index,
2038 self.pg0.remote_hosts[ii].mac,
2039 self.pg0.remote_hosts[ii].ip4).add_vpp_config()
2040
2041 # one more neighbor over the limit should fail
2042 with self.vapi.assert_negative_api_retval():
2043 VppNeighbor(self,
2044 self.pg0.sw_if_index,
2045 self.pg0.remote_hosts[200].mac,
2046 self.pg0.remote_hosts[200].ip4).add_vpp_config()
2047
2048 #
2049 # change the config to allow recycling the old neighbors
2050 #
2051 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
2052 max_number=200,
2053 max_age=0,
2054 recycle=True)
2055
2056 # now new additions are allowed
2057 VppNeighbor(self,
2058 self.pg0.sw_if_index,
2059 self.pg0.remote_hosts[200].mac,
2060 self.pg0.remote_hosts[200].ip4).add_vpp_config()
2061
2062 # add the first neighbor we configured has been re-used
2063 self.assertFalse(find_nbr(self,
2064 self.pg0.sw_if_index,
2065 self.pg0.remote_hosts[0].ip4))
2066 self.assertTrue(find_nbr(self,
2067 self.pg0.sw_if_index,
2068 self.pg0.remote_hosts[200].ip4))
2069
2070 #
2071 # change the config to age old neighbors
2072 #
2073 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
2074 max_number=200,
2075 max_age=2,
2076 recycle=True)
2077
2078 self.vapi.cli("sh ip4 neighbor-sorted")
2079
2080 #
2081 # expect probes from all these ARP entries as they age
2082 # 3 probes for each neighbor 3*200 = 600
2083 rxs = self.pg0.get_capture(600, timeout=8)
2084
2085 for ii in range(3):
2086 for jj in range(200):
2087 rx = rxs[ii*200 + jj]
2088 # rx.show()
2089
2090 #
2091 # 3 probes sent then 1 more second to see if a reply comes, before
2092 # they age out
2093 #
2094 for jj in range(1, 201):
2095 self.wait_for_no_nbr(self.pg0.sw_if_index,
2096 self.pg0.remote_hosts[jj].ip4)
2097
2098 self.assertFalse(self.vapi.ip_neighbor_dump(sw_if_index=0xffffffff,
2099 af=vaf.ADDRESS_IP4))
2100
2101 #
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002102 # load up some neighbours again with 2s aging enabled
2103 # they should be removed after 10s (2s age + 4s for probes + gap)
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002104 # check for the add and remove events
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002105 #
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002106 enum = VppEnum.vl_api_ip_neighbor_event_flags_t
2107
2108 self.vapi.want_ip_neighbor_events_v2(enable=1)
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002109 for ii in range(10):
2110 VppNeighbor(self,
2111 self.pg0.sw_if_index,
2112 self.pg0.remote_hosts[ii].mac,
2113 self.pg0.remote_hosts[ii].ip4).add_vpp_config()
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002114
2115 e = self.vapi.wait_for_event(1, "ip_neighbor_event_v2")
2116 self.assertEqual(e.flags,
2117 enum.IP_NEIGHBOR_API_EVENT_FLAG_ADDED)
2118 self.assertEqual(str(e.neighbor.ip_address),
2119 self.pg0.remote_hosts[ii].ip4)
2120 self.assertEqual(e.neighbor.mac_address,
2121 self.pg0.remote_hosts[ii].mac)
2122
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002123 self.sleep(10)
2124 self.assertFalse(self.vapi.ip_neighbor_dump(sw_if_index=0xffffffff,
2125 af=vaf.ADDRESS_IP4))
2126
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002127 evs = []
2128 for ii in range(10):
2129 e = self.vapi.wait_for_event(1, "ip_neighbor_event_v2")
2130 self.assertEqual(e.flags,
2131 enum.IP_NEIGHBOR_API_EVENT_FLAG_REMOVED)
2132 evs.append(e)
2133
2134 # check we got the correct mac/ip pairs - done separately
2135 # because we don't care about the order the remove notifications
2136 # arrive
2137 for ii in range(10):
2138 found = False
2139 mac = self.pg0.remote_hosts[ii].mac
2140 ip = self.pg0.remote_hosts[ii].ip4
2141
2142 for e in evs:
2143 if (e.neighbor.mac_address == mac and
2144 str(e.neighbor.ip_address) == ip):
2145 found = True
2146 break
2147 self.assertTrue(found)
2148
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002149 #
2150 # check if we can set age and recycle with empty neighbor list
2151 #
2152 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
2153 max_number=200,
2154 max_age=1000,
2155 recycle=True)
2156
2157 #
Neale Rannscbe25aa2019-09-30 10:53:31 +00002158 # load up some neighbours again, then disable the aging
2159 # they should still be there in 10 seconds time
2160 #
2161 for ii in range(10):
2162 VppNeighbor(self,
2163 self.pg0.sw_if_index,
2164 self.pg0.remote_hosts[ii].mac,
2165 self.pg0.remote_hosts[ii].ip4).add_vpp_config()
2166 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
2167 max_number=200,
2168 max_age=0,
2169 recycle=False)
2170
2171 self.sleep(10)
2172 self.assertTrue(find_nbr(self,
2173 self.pg0.sw_if_index,
2174 self.pg0.remote_hosts[0].ip4))
2175
2176
Neale Rannsc87fbb42020-04-02 17:08:28 +00002177class NeighborReplaceTestCase(VppTestCase):
2178 """ ARP/ND Replacement """
2179
2180 @classmethod
2181 def setUpClass(cls):
2182 super(NeighborReplaceTestCase, cls).setUpClass()
2183
2184 @classmethod
2185 def tearDownClass(cls):
2186 super(NeighborReplaceTestCase, cls).tearDownClass()
2187
2188 def setUp(self):
2189 super(NeighborReplaceTestCase, self).setUp()
2190
2191 self.create_pg_interfaces(range(4))
2192
2193 # pg0 configured with ip4 and 6 addresses used for input
2194 # pg1 configured with ip4 and 6 addresses used for output
2195 # pg2 is unnumbered to pg0
2196 for i in self.pg_interfaces:
2197 i.admin_up()
2198 i.config_ip4()
2199 i.config_ip6()
2200 i.resolve_arp()
2201 i.resolve_ndp()
2202
2203 def tearDown(self):
2204 super(NeighborReplaceTestCase, self).tearDown()
2205
2206 for i in self.pg_interfaces:
2207 i.unconfig_ip4()
2208 i.unconfig_ip6()
2209 i.admin_down()
2210
2211 def test_replace(self):
2212 """ replace """
2213
2214 N_HOSTS = 16
2215
2216 for i in self.pg_interfaces:
2217 i.generate_remote_hosts(N_HOSTS)
2218 i.configure_ipv4_neighbors()
2219 i.configure_ipv6_neighbors()
2220
2221 # replace them all
2222 self.vapi.ip_neighbor_replace_begin()
2223 self.vapi.ip_neighbor_replace_end()
2224
2225 for i in self.pg_interfaces:
2226 for h in range(N_HOSTS):
2227 self.assertFalse(find_nbr(self,
2228 self.pg0.sw_if_index,
2229 self.pg0.remote_hosts[h].ip4))
2230 self.assertFalse(find_nbr(self,
2231 self.pg0.sw_if_index,
2232 self.pg0.remote_hosts[h].ip6))
2233
2234 #
2235 # and them all back via the API
2236 #
2237 for i in self.pg_interfaces:
2238 for h in range(N_HOSTS):
2239 VppNeighbor(self,
2240 i.sw_if_index,
2241 i.remote_hosts[h].mac,
2242 i.remote_hosts[h].ip4).add_vpp_config()
2243 VppNeighbor(self,
2244 i.sw_if_index,
2245 i.remote_hosts[h].mac,
2246 i.remote_hosts[h].ip6).add_vpp_config()
2247
2248 #
2249 # begin the replacement again, this time touch some
2250 # the neighbours on pg1 so they are not deleted
2251 #
2252 self.vapi.ip_neighbor_replace_begin()
2253
2254 # update from the API all neighbours on pg1
2255 for h in range(N_HOSTS):
2256 VppNeighbor(self,
2257 self.pg1.sw_if_index,
2258 self.pg1.remote_hosts[h].mac,
2259 self.pg1.remote_hosts[h].ip4).add_vpp_config()
2260 VppNeighbor(self,
2261 self.pg1.sw_if_index,
2262 self.pg1.remote_hosts[h].mac,
2263 self.pg1.remote_hosts[h].ip6).add_vpp_config()
2264
2265 # update from the data-plane all neighbours on pg3
2266 self.pg3.configure_ipv4_neighbors()
2267 self.pg3.configure_ipv6_neighbors()
2268
2269 # complete the replacement
2270 self.logger.info(self.vapi.cli("sh ip neighbors"))
2271 self.vapi.ip_neighbor_replace_end()
2272
2273 for i in self.pg_interfaces:
2274 if i == self.pg1 or i == self.pg3:
2275 # neighbours on pg1 and pg3 are still present
2276 for h in range(N_HOSTS):
2277 self.assertTrue(find_nbr(self,
2278 i.sw_if_index,
2279 i.remote_hosts[h].ip4))
2280 self.assertTrue(find_nbr(self,
2281 i.sw_if_index,
2282 i.remote_hosts[h].ip6))
2283 else:
2284 # all other neighbours are toast
2285 for h in range(N_HOSTS):
2286 self.assertFalse(find_nbr(self,
2287 i.sw_if_index,
2288 i.remote_hosts[h].ip4))
2289 self.assertFalse(find_nbr(self,
2290 i.sw_if_index,
2291 i.remote_hosts[h].ip6))
2292
2293
Neale Ranns240dcb22020-04-23 09:04:59 +00002294class NeighborFlush(VppTestCase):
2295 """ Neighbor Flush """
2296
2297 @classmethod
2298 def setUpClass(cls):
2299 super(NeighborFlush, cls).setUpClass()
2300
2301 @classmethod
2302 def tearDownClass(cls):
2303 super(NeighborFlush, cls).tearDownClass()
2304
2305 def setUp(self):
2306 super(NeighborFlush, self).setUp()
2307
2308 self.create_pg_interfaces(range(2))
2309
2310 for i in self.pg_interfaces:
2311 i.admin_up()
2312 i.config_ip4()
2313 i.config_ip6()
2314 i.resolve_arp()
2315 i.resolve_ndp()
2316
2317 def tearDown(self):
2318 super(NeighborFlush, self).tearDown()
2319
2320 for i in self.pg_interfaces:
2321 i.unconfig_ip4()
2322 i.unconfig_ip6()
2323 i.admin_down()
2324
2325 def test_flush(self):
2326 """ Neighbour Flush """
2327
2328 e = VppEnum
2329 nf = e.vl_api_ip_neighbor_flags_t
2330 af = e.vl_api_address_family_t
2331 N_HOSTS = 16
2332 static = [False, True]
2333 self.pg0.generate_remote_hosts(N_HOSTS)
2334 self.pg1.generate_remote_hosts(N_HOSTS)
2335
2336 for s in static:
2337 # a few v4 and v6 dynamic neoghbors
2338 for n in range(N_HOSTS):
2339 VppNeighbor(self,
2340 self.pg0.sw_if_index,
2341 self.pg0.remote_hosts[n].mac,
2342 self.pg0.remote_hosts[n].ip4,
2343 is_static=s).add_vpp_config()
2344 VppNeighbor(self,
2345 self.pg1.sw_if_index,
2346 self.pg1.remote_hosts[n].mac,
2347 self.pg1.remote_hosts[n].ip6,
2348 is_static=s).add_vpp_config()
2349
2350 # flush the interfaces individually
2351 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, self.pg0.sw_if_index)
2352
2353 # check we haven't flushed that which we shouldn't
2354 for n in range(N_HOSTS):
2355 self.assertTrue(find_nbr(self,
2356 self.pg1.sw_if_index,
2357 self.pg1.remote_hosts[n].ip6,
2358 is_static=s))
2359
2360 self.vapi.ip_neighbor_flush(af.ADDRESS_IP6, self.pg1.sw_if_index)
2361
2362 for n in range(N_HOSTS):
2363 self.assertFalse(find_nbr(self,
2364 self.pg0.sw_if_index,
2365 self.pg0.remote_hosts[n].ip4))
2366 self.assertFalse(find_nbr(self,
2367 self.pg1.sw_if_index,
2368 self.pg1.remote_hosts[n].ip6))
2369
2370 # add the nieghbours back
2371 for n in range(N_HOSTS):
2372 VppNeighbor(self,
2373 self.pg0.sw_if_index,
2374 self.pg0.remote_hosts[n].mac,
2375 self.pg0.remote_hosts[n].ip4,
2376 is_static=s).add_vpp_config()
2377 VppNeighbor(self,
2378 self.pg1.sw_if_index,
2379 self.pg1.remote_hosts[n].mac,
2380 self.pg1.remote_hosts[n].ip6,
2381 is_static=s).add_vpp_config()
2382
2383 self.logger.info(self.vapi.cli("sh ip neighbor"))
2384
2385 # flush both interfaces at the same time
2386 self.vapi.ip_neighbor_flush(af.ADDRESS_IP6, 0xffffffff)
2387
2388 # check we haven't flushed that which we shouldn't
2389 for n in range(N_HOSTS):
2390 self.assertTrue(find_nbr(self,
2391 self.pg0.sw_if_index,
2392 self.pg0.remote_hosts[n].ip4,
2393 is_static=s))
2394
2395 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, 0xffffffff)
2396
2397 for n in range(N_HOSTS):
2398 self.assertFalse(find_nbr(self,
2399 self.pg0.sw_if_index,
2400 self.pg0.remote_hosts[n].ip4))
2401 self.assertFalse(find_nbr(self,
2402 self.pg1.sw_if_index,
2403 self.pg1.remote_hosts[n].ip6))
2404
2405
Neale Ranns37be7362017-02-21 17:30:26 -08002406if __name__ == '__main__':
2407 unittest.main(testRunner=VppTestRunner)