blob: 241479a1d30a5017bc35054cd6158dab1b5bc58a [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
7from framework import VppTestCase, VppTestRunner
8from vpp_neighbor import VppNeighbor, find_nbr
Neale Ranns15002542017-09-10 04:39:11 -07009from vpp_ip_route import VppIpRoute, VppRoutePath, find_route, \
Neale Rannse2fe0972020-11-26 08:37:27 +000010 VppIpTable, DpoProto, FibPathType, VppIpInterfaceAddress
Neale Ranns37029302018-08-10 05:30:06 -070011from vpp_papi import VppEnum
Jakub Grajciar2df2f752020-12-01 11:23:44 +010012from vpp_ip import VppIpPuntRedirect
Neale Ranns39f9d8b2017-02-16 21:57:05 -080013
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -070014import scapy.compat
Neale Ranns39f9d8b2017-02-16 21:57:05 -080015from scapy.packet import Raw
Neale Ranns30d0fd42017-05-30 07:30:04 -070016from scapy.layers.l2 import Ether, ARP, Dot1Q
Neale Ranns240dcb22020-04-23 09:04:59 +000017from scapy.layers.inet import IP, UDP, TCP
Neale Rannscd35e532018-08-31 02:51:45 -070018from scapy.layers.inet6 import IPv6
Neale Ranns37be7362017-02-21 17:30:26 -080019from scapy.contrib.mpls import MPLS
Neale Ranns14260392018-09-28 05:00:57 -070020from scapy.layers.inet6 import IPv6
Neale Ranns39f9d8b2017-02-16 21:57:05 -080021
Paul Vinciguerra4271c972019-05-14 13:25:49 -040022
23NUM_PKTS = 67
24
Neale Ranns39f9d8b2017-02-16 21:57:05 -080025# not exported by scapy, so redefined here
26arp_opts = {"who-has": 1, "is-at": 2}
27
28
29class ARPTestCase(VppTestCase):
30 """ ARP Test Case """
31
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070032 @classmethod
33 def setUpClass(cls):
34 super(ARPTestCase, cls).setUpClass()
35
36 @classmethod
37 def tearDownClass(cls):
38 super(ARPTestCase, cls).tearDownClass()
39
Neale Ranns39f9d8b2017-02-16 21:57:05 -080040 def setUp(self):
41 super(ARPTestCase, self).setUp()
42
43 # create 3 pg interfaces
44 self.create_pg_interfaces(range(4))
45
46 # pg0 configured with ip4 and 6 addresses used for input
47 # pg1 configured with ip4 and 6 addresses used for output
48 # pg2 is unnumbered to pg0
49 for i in self.pg_interfaces:
50 i.admin_up()
51
52 self.pg0.config_ip4()
53 self.pg0.config_ip6()
54 self.pg0.resolve_arp()
55
56 self.pg1.config_ip4()
57 self.pg1.config_ip6()
58
59 # pg3 in a different VRF
Neale Ranns15002542017-09-10 04:39:11 -070060 self.tbl = VppIpTable(self, 1)
61 self.tbl.add_vpp_config()
62
Neale Ranns39f9d8b2017-02-16 21:57:05 -080063 self.pg3.set_table_ip4(1)
64 self.pg3.config_ip4()
65
Neale Ranns4008ac92017-02-13 23:20:04 -080066 def tearDown(self):
Neale Ranns4b919a52017-03-11 05:55:21 -080067 self.pg0.unconfig_ip4()
68 self.pg0.unconfig_ip6()
69
70 self.pg1.unconfig_ip4()
71 self.pg1.unconfig_ip6()
72
73 self.pg3.unconfig_ip4()
Neale Ranns15002542017-09-10 04:39:11 -070074 self.pg3.set_table_ip4(0)
Neale Ranns4b919a52017-03-11 05:55:21 -080075
Neale Ranns4008ac92017-02-13 23:20:04 -080076 for i in self.pg_interfaces:
Neale Ranns4008ac92017-02-13 23:20:04 -080077 i.admin_down()
78
Neale Ranns15002542017-09-10 04:39:11 -070079 super(ARPTestCase, self).tearDown()
80
Neale Ranns39f9d8b2017-02-16 21:57:05 -080081 def verify_arp_req(self, rx, smac, sip, dip):
82 ether = rx[Ether]
83 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
84 self.assertEqual(ether.src, smac)
85
86 arp = rx[ARP]
87 self.assertEqual(arp.hwtype, 1)
88 self.assertEqual(arp.ptype, 0x800)
89 self.assertEqual(arp.hwlen, 6)
90 self.assertEqual(arp.plen, 4)
91 self.assertEqual(arp.op, arp_opts["who-has"])
92 self.assertEqual(arp.hwsrc, smac)
93 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
94 self.assertEqual(arp.psrc, sip)
95 self.assertEqual(arp.pdst, dip)
96
97 def verify_arp_resp(self, rx, smac, dmac, sip, dip):
98 ether = rx[Ether]
99 self.assertEqual(ether.dst, dmac)
100 self.assertEqual(ether.src, smac)
101
102 arp = rx[ARP]
103 self.assertEqual(arp.hwtype, 1)
104 self.assertEqual(arp.ptype, 0x800)
105 self.assertEqual(arp.hwlen, 6)
106 self.assertEqual(arp.plen, 4)
107 self.assertEqual(arp.op, arp_opts["is-at"])
108 self.assertEqual(arp.hwsrc, smac)
109 self.assertEqual(arp.hwdst, dmac)
110 self.assertEqual(arp.psrc, sip)
111 self.assertEqual(arp.pdst, dip)
112
Matthew Smithcb9ab472017-05-16 21:35:56 -0500113 def verify_arp_vrrp_resp(self, rx, smac, dmac, sip, dip):
114 ether = rx[Ether]
115 self.assertEqual(ether.dst, dmac)
116 self.assertEqual(ether.src, smac)
117
118 arp = rx[ARP]
119 self.assertEqual(arp.hwtype, 1)
120 self.assertEqual(arp.ptype, 0x800)
121 self.assertEqual(arp.hwlen, 6)
122 self.assertEqual(arp.plen, 4)
123 self.assertEqual(arp.op, arp_opts["is-at"])
124 self.assertNotEqual(arp.hwsrc, smac)
125 self.assertTrue("00:00:5e:00:01" in arp.hwsrc or
126 "00:00:5E:00:01" in arp.hwsrc)
127 self.assertEqual(arp.hwdst, dmac)
128 self.assertEqual(arp.psrc, sip)
129 self.assertEqual(arp.pdst, dip)
130
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800131 def verify_ip(self, rx, smac, dmac, sip, dip):
132 ether = rx[Ether]
133 self.assertEqual(ether.dst, dmac)
134 self.assertEqual(ether.src, smac)
135
136 ip = rx[IP]
137 self.assertEqual(ip.src, sip)
138 self.assertEqual(ip.dst, dip)
139
Neale Ranns37be7362017-02-21 17:30:26 -0800140 def verify_ip_o_mpls(self, rx, smac, dmac, label, sip, dip):
141 ether = rx[Ether]
142 self.assertEqual(ether.dst, dmac)
143 self.assertEqual(ether.src, smac)
144
145 mpls = rx[MPLS]
146 self.assertTrue(mpls.label, label)
147
148 ip = rx[IP]
149 self.assertEqual(ip.src, sip)
150 self.assertEqual(ip.dst, dip)
151
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800152 def test_arp(self):
153 """ ARP """
154
155 #
156 # Generate some hosts on the LAN
157 #
Neale Rannsca193612017-06-14 06:50:08 -0700158 self.pg1.generate_remote_hosts(11)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800159
160 #
Neale Rannscbe25aa2019-09-30 10:53:31 +0000161 # watch for:
162 # - all neighbour events
163 # - all neighbor events on pg1
164 # - neighbor events for host[1] on pg1
165 #
166 self.vapi.want_ip_neighbor_events(enable=1,
167 pid=os.getpid())
168 self.vapi.want_ip_neighbor_events(enable=1,
169 pid=os.getpid(),
170 sw_if_index=self.pg1.sw_if_index)
171 self.vapi.want_ip_neighbor_events(enable=1,
172 pid=os.getpid(),
173 sw_if_index=self.pg1.sw_if_index,
174 ip=self.pg1.remote_hosts[1].ip4)
175
176 self.logger.info(self.vapi.cli("sh ip neighbor-watcher"))
177
178 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800179 # Send IP traffic to one of these unresolved hosts.
180 # expect the generation of an ARP request
181 #
182 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
183 IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[1].ip4) /
184 UDP(sport=1234, dport=1234) /
185 Raw())
186
187 self.pg0.add_stream(p)
188 self.pg_enable_capture(self.pg_interfaces)
189 self.pg_start()
190
191 rx = self.pg1.get_capture(1)
192
193 self.verify_arp_req(rx[0],
194 self.pg1.local_mac,
195 self.pg1.local_ip4,
196 self.pg1._remote_hosts[1].ip4)
197
198 #
199 # And a dynamic ARP entry for host 1
200 #
201 dyn_arp = VppNeighbor(self,
202 self.pg1.sw_if_index,
203 self.pg1.remote_hosts[1].mac,
204 self.pg1.remote_hosts[1].ip4)
205 dyn_arp.add_vpp_config()
Neale Rannscbe25aa2019-09-30 10:53:31 +0000206 self.assertTrue(dyn_arp.query_vpp_config())
207
Neale Rannsdc617b82020-08-20 08:22:56 +0000208 self.logger.info(self.vapi.cli("show ip neighbor-watcher"))
209
Neale Rannscbe25aa2019-09-30 10:53:31 +0000210 # this matches all of the listnerers
211 es = [self.vapi.wait_for_event(1, "ip_neighbor_event")
212 for i in range(3)]
213 for e in es:
214 self.assertEqual(str(e.neighbor.ip_address),
215 self.pg1.remote_hosts[1].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800216
217 #
218 # now we expect IP traffic forwarded
219 #
220 dyn_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
221 IP(src=self.pg0.remote_ip4,
222 dst=self.pg1._remote_hosts[1].ip4) /
223 UDP(sport=1234, dport=1234) /
224 Raw())
225
226 self.pg0.add_stream(dyn_p)
227 self.pg_enable_capture(self.pg_interfaces)
228 self.pg_start()
229
230 rx = self.pg1.get_capture(1)
231
232 self.verify_ip(rx[0],
233 self.pg1.local_mac,
234 self.pg1.remote_hosts[1].mac,
235 self.pg0.remote_ip4,
236 self.pg1._remote_hosts[1].ip4)
237
238 #
239 # And a Static ARP entry for host 2
240 #
241 static_arp = VppNeighbor(self,
242 self.pg1.sw_if_index,
243 self.pg1.remote_hosts[2].mac,
244 self.pg1.remote_hosts[2].ip4,
245 is_static=1)
246 static_arp.add_vpp_config()
Neale Rannscbe25aa2019-09-30 10:53:31 +0000247 es = [self.vapi.wait_for_event(1, "ip_neighbor_event")
248 for i in range(2)]
249 for e in es:
250 self.assertEqual(str(e.neighbor.ip_address),
251 self.pg1.remote_hosts[2].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800252
253 static_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
254 IP(src=self.pg0.remote_ip4,
255 dst=self.pg1._remote_hosts[2].ip4) /
256 UDP(sport=1234, dport=1234) /
257 Raw())
258
259 self.pg0.add_stream(static_p)
260 self.pg_enable_capture(self.pg_interfaces)
261 self.pg_start()
262
263 rx = self.pg1.get_capture(1)
264
265 self.verify_ip(rx[0],
266 self.pg1.local_mac,
267 self.pg1.remote_hosts[2].mac,
268 self.pg0.remote_ip4,
269 self.pg1._remote_hosts[2].ip4)
270
271 #
Neale Rannscbe25aa2019-09-30 10:53:31 +0000272 # remove all the listeners
273 #
274 self.vapi.want_ip_neighbor_events(enable=0,
275 pid=os.getpid())
276 self.vapi.want_ip_neighbor_events(enable=0,
277 pid=os.getpid(),
278 sw_if_index=self.pg1.sw_if_index)
279 self.vapi.want_ip_neighbor_events(enable=0,
280 pid=os.getpid(),
281 sw_if_index=self.pg1.sw_if_index,
282 ip=self.pg1.remote_hosts[1].ip4)
283
284 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800285 # flap the link. dynamic ARPs get flush, statics don't
286 #
287 self.pg1.admin_down()
288 self.pg1.admin_up()
289
290 self.pg0.add_stream(static_p)
291 self.pg_enable_capture(self.pg_interfaces)
292 self.pg_start()
293 rx = self.pg1.get_capture(1)
294
295 self.verify_ip(rx[0],
296 self.pg1.local_mac,
297 self.pg1.remote_hosts[2].mac,
298 self.pg0.remote_ip4,
299 self.pg1._remote_hosts[2].ip4)
300
301 self.pg0.add_stream(dyn_p)
302 self.pg_enable_capture(self.pg_interfaces)
303 self.pg_start()
304
305 rx = self.pg1.get_capture(1)
306 self.verify_arp_req(rx[0],
307 self.pg1.local_mac,
308 self.pg1.local_ip4,
309 self.pg1._remote_hosts[1].ip4)
310
Neale Rannscbe25aa2019-09-30 10:53:31 +0000311 self.assertFalse(dyn_arp.query_vpp_config())
312 self.assertTrue(static_arp.query_vpp_config())
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800313 #
314 # Send an ARP request from one of the so-far unlearned remote hosts
315 #
316 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
317 src=self.pg1._remote_hosts[3].mac) /
318 ARP(op="who-has",
319 hwsrc=self.pg1._remote_hosts[3].mac,
320 pdst=self.pg1.local_ip4,
321 psrc=self.pg1._remote_hosts[3].ip4))
322
323 self.pg1.add_stream(p)
324 self.pg_enable_capture(self.pg_interfaces)
325 self.pg_start()
326
327 rx = self.pg1.get_capture(1)
328 self.verify_arp_resp(rx[0],
329 self.pg1.local_mac,
330 self.pg1._remote_hosts[3].mac,
331 self.pg1.local_ip4,
332 self.pg1._remote_hosts[3].ip4)
333
334 #
335 # VPP should have learned the mapping for the remote host
336 #
337 self.assertTrue(find_nbr(self,
338 self.pg1.sw_if_index,
339 self.pg1._remote_hosts[3].ip4))
Neale Ranns4b919a52017-03-11 05:55:21 -0800340 #
341 # Fire in an ARP request before the interface becomes IP enabled
342 #
343 self.pg2.generate_remote_hosts(4)
344
345 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
346 ARP(op="who-has",
347 hwsrc=self.pg2.remote_mac,
348 pdst=self.pg1.local_ip4,
349 psrc=self.pg2.remote_hosts[3].ip4))
Neale Ranns30d0fd42017-05-30 07:30:04 -0700350 pt = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
351 Dot1Q(vlan=0) /
352 ARP(op="who-has",
353 hwsrc=self.pg2.remote_mac,
354 pdst=self.pg1.local_ip4,
355 psrc=self.pg2.remote_hosts[3].ip4))
Neale Ranns4b919a52017-03-11 05:55:21 -0800356 self.send_and_assert_no_replies(self.pg2, p,
357 "interface not IP enabled")
358
359 #
360 # Make pg2 un-numbered to pg1
361 #
362 self.pg2.set_unnumbered(self.pg1.sw_if_index)
363
Neale Rannsac3e72c2019-10-06 01:04:26 -0700364 #
365 # test the unnumbered dump both by all interfaces and just the enabled
366 # one
367 #
Neale Ranns404d88e2018-08-08 06:37:33 -0700368 unnum = self.vapi.ip_unnumbered_dump()
Neale Rannsac3e72c2019-10-06 01:04:26 -0700369 self.assertTrue(len(unnum))
370 self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
371 self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)
372 unnum = self.vapi.ip_unnumbered_dump(self.pg2.sw_if_index)
373 self.assertTrue(len(unnum))
Neale Ranns404d88e2018-08-08 06:37:33 -0700374 self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
375 self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)
376
Neale Ranns4b919a52017-03-11 05:55:21 -0800377 #
378 # We should respond to ARP requests for the unnumbered to address
379 # once an attached route to the source is known
380 #
381 self.send_and_assert_no_replies(
382 self.pg2, p,
383 "ARP req for unnumbered address - no source")
384
385 attached_host = VppIpRoute(self, self.pg2.remote_hosts[3].ip4, 32,
386 [VppRoutePath("0.0.0.0",
387 self.pg2.sw_if_index)])
388 attached_host.add_vpp_config()
389
390 self.pg2.add_stream(p)
391 self.pg_enable_capture(self.pg_interfaces)
392 self.pg_start()
393
394 rx = self.pg2.get_capture(1)
395 self.verify_arp_resp(rx[0],
396 self.pg2.local_mac,
397 self.pg2.remote_mac,
398 self.pg1.local_ip4,
399 self.pg2.remote_hosts[3].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800400
Neale Ranns30d0fd42017-05-30 07:30:04 -0700401 self.pg2.add_stream(pt)
402 self.pg_enable_capture(self.pg_interfaces)
403 self.pg_start()
404
405 rx = self.pg2.get_capture(1)
406 self.verify_arp_resp(rx[0],
407 self.pg2.local_mac,
408 self.pg2.remote_mac,
409 self.pg1.local_ip4,
410 self.pg2.remote_hosts[3].ip4)
411
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800412 #
Neale Ranns3983ac22017-03-10 11:53:27 -0800413 # A neighbor entry that has no associated FIB-entry
414 #
415 arp_no_fib = VppNeighbor(self,
416 self.pg1.sw_if_index,
417 self.pg1.remote_hosts[4].mac,
418 self.pg1.remote_hosts[4].ip4,
419 is_no_fib_entry=1)
420 arp_no_fib.add_vpp_config()
421
422 #
423 # check we have the neighbor, but no route
424 #
425 self.assertTrue(find_nbr(self,
426 self.pg1.sw_if_index,
427 self.pg1._remote_hosts[4].ip4))
428 self.assertFalse(find_route(self,
429 self.pg1._remote_hosts[4].ip4,
430 32))
431 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800432 # pg2 is unnumbered to pg1, so we can form adjacencies out of pg2
433 # from within pg1's subnet
Neale Ranns3983ac22017-03-10 11:53:27 -0800434 #
435 arp_unnum = VppNeighbor(self,
436 self.pg2.sw_if_index,
437 self.pg1.remote_hosts[5].mac,
438 self.pg1.remote_hosts[5].ip4)
439 arp_unnum.add_vpp_config()
440
441 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
442 IP(src=self.pg0.remote_ip4,
443 dst=self.pg1._remote_hosts[5].ip4) /
444 UDP(sport=1234, dport=1234) /
445 Raw())
446
447 self.pg0.add_stream(p)
448 self.pg_enable_capture(self.pg_interfaces)
449 self.pg_start()
450
451 rx = self.pg2.get_capture(1)
452
453 self.verify_ip(rx[0],
454 self.pg2.local_mac,
455 self.pg1.remote_hosts[5].mac,
456 self.pg0.remote_ip4,
457 self.pg1._remote_hosts[5].ip4)
458
459 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800460 # ARP requests from hosts in pg1's subnet sent on pg2 are replied to
461 # with the unnumbered interface's address as the source
462 #
463 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
464 ARP(op="who-has",
465 hwsrc=self.pg2.remote_mac,
466 pdst=self.pg1.local_ip4,
467 psrc=self.pg1.remote_hosts[6].ip4))
468
469 self.pg2.add_stream(p)
470 self.pg_enable_capture(self.pg_interfaces)
471 self.pg_start()
472
473 rx = self.pg2.get_capture(1)
474 self.verify_arp_resp(rx[0],
475 self.pg2.local_mac,
476 self.pg2.remote_mac,
477 self.pg1.local_ip4,
478 self.pg1.remote_hosts[6].ip4)
479
480 #
481 # An attached host route out of pg2 for an undiscovered hosts generates
482 # an ARP request with the unnumbered address as the source
483 #
484 att_unnum = VppIpRoute(self, self.pg1.remote_hosts[7].ip4, 32,
485 [VppRoutePath("0.0.0.0",
486 self.pg2.sw_if_index)])
487 att_unnum.add_vpp_config()
488
489 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
490 IP(src=self.pg0.remote_ip4,
491 dst=self.pg1._remote_hosts[7].ip4) /
492 UDP(sport=1234, dport=1234) /
493 Raw())
494
495 self.pg0.add_stream(p)
496 self.pg_enable_capture(self.pg_interfaces)
497 self.pg_start()
498
499 rx = self.pg2.get_capture(1)
500
501 self.verify_arp_req(rx[0],
502 self.pg2.local_mac,
503 self.pg1.local_ip4,
504 self.pg1._remote_hosts[7].ip4)
505
506 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
507 ARP(op="who-has",
508 hwsrc=self.pg2.remote_mac,
509 pdst=self.pg1.local_ip4,
510 psrc=self.pg1.remote_hosts[7].ip4))
511
512 self.pg2.add_stream(p)
513 self.pg_enable_capture(self.pg_interfaces)
514 self.pg_start()
515
516 rx = self.pg2.get_capture(1)
517 self.verify_arp_resp(rx[0],
518 self.pg2.local_mac,
519 self.pg2.remote_mac,
520 self.pg1.local_ip4,
521 self.pg1.remote_hosts[7].ip4)
522
523 #
524 # An attached host route as yet unresolved out of pg2 for an
525 # undiscovered host, an ARP requests begets a response.
526 #
527 att_unnum1 = VppIpRoute(self, self.pg1.remote_hosts[8].ip4, 32,
528 [VppRoutePath("0.0.0.0",
529 self.pg2.sw_if_index)])
530 att_unnum1.add_vpp_config()
531
532 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
533 ARP(op="who-has",
534 hwsrc=self.pg2.remote_mac,
535 pdst=self.pg1.local_ip4,
536 psrc=self.pg1.remote_hosts[8].ip4))
537
538 self.pg2.add_stream(p)
539 self.pg_enable_capture(self.pg_interfaces)
540 self.pg_start()
541
542 rx = self.pg2.get_capture(1)
543 self.verify_arp_resp(rx[0],
544 self.pg2.local_mac,
545 self.pg2.remote_mac,
546 self.pg1.local_ip4,
547 self.pg1.remote_hosts[8].ip4)
548
549 #
Neale Ranns30d0fd42017-05-30 07:30:04 -0700550 # Send an ARP request from one of the so-far unlearned remote hosts
551 # with a VLAN0 tag
552 #
553 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
554 src=self.pg1._remote_hosts[9].mac) /
555 Dot1Q(vlan=0) /
556 ARP(op="who-has",
557 hwsrc=self.pg1._remote_hosts[9].mac,
558 pdst=self.pg1.local_ip4,
559 psrc=self.pg1._remote_hosts[9].ip4))
560
561 self.pg1.add_stream(p)
562 self.pg_enable_capture(self.pg_interfaces)
563 self.pg_start()
564
565 rx = self.pg1.get_capture(1)
566 self.verify_arp_resp(rx[0],
567 self.pg1.local_mac,
568 self.pg1._remote_hosts[9].mac,
569 self.pg1.local_ip4,
570 self.pg1._remote_hosts[9].ip4)
571
572 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700573 # Add a hierarchy of routes for a host in the sub-net.
Neale Rannsca193612017-06-14 06:50:08 -0700574 # Should still get an ARP resp since the cover is attached
575 #
576 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_mac) /
577 ARP(op="who-has",
578 hwsrc=self.pg1.remote_mac,
579 pdst=self.pg1.local_ip4,
580 psrc=self.pg1.remote_hosts[10].ip4))
581
582 r1 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 30,
583 [VppRoutePath(self.pg1.remote_hosts[10].ip4,
584 self.pg1.sw_if_index)])
585 r1.add_vpp_config()
586
587 self.pg1.add_stream(p)
588 self.pg_enable_capture(self.pg_interfaces)
589 self.pg_start()
590 rx = self.pg1.get_capture(1)
591 self.verify_arp_resp(rx[0],
592 self.pg1.local_mac,
593 self.pg1.remote_mac,
594 self.pg1.local_ip4,
595 self.pg1.remote_hosts[10].ip4)
596
597 r2 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 32,
598 [VppRoutePath(self.pg1.remote_hosts[10].ip4,
599 self.pg1.sw_if_index)])
600 r2.add_vpp_config()
601
602 self.pg1.add_stream(p)
603 self.pg_enable_capture(self.pg_interfaces)
604 self.pg_start()
605 rx = self.pg1.get_capture(1)
606 self.verify_arp_resp(rx[0],
607 self.pg1.local_mac,
608 self.pg1.remote_mac,
609 self.pg1.local_ip4,
610 self.pg1.remote_hosts[10].ip4)
611
612 #
613 # add an ARP entry that's not on the sub-net and so whose
614 # adj-fib fails the refinement check. then send an ARP request
615 # from that source
616 #
617 a1 = VppNeighbor(self,
618 self.pg0.sw_if_index,
619 self.pg0.remote_mac,
620 "100.100.100.50")
621 a1.add_vpp_config()
622
623 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
624 ARP(op="who-has",
625 hwsrc=self.pg0.remote_mac,
626 psrc="100.100.100.50",
627 pdst=self.pg0.remote_ip4))
628 self.send_and_assert_no_replies(self.pg0, p,
629 "ARP req for from failed adj-fib")
630
631 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800632 # ERROR Cases
633 # 1 - don't respond to ARP request for address not within the
634 # interface's sub-net
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700635 # 1b - nor within the unnumbered subnet
636 # 1c - nor within the subnet of a different interface
637 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800638 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
639 ARP(op="who-has",
640 hwsrc=self.pg0.remote_mac,
641 pdst="10.10.10.3",
642 psrc=self.pg0.remote_ip4))
643 self.send_and_assert_no_replies(self.pg0, p,
644 "ARP req for non-local destination")
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700645 self.assertFalse(find_nbr(self,
646 self.pg0.sw_if_index,
647 "10.10.10.3"))
648
Neale Ranns4b919a52017-03-11 05:55:21 -0800649 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
650 ARP(op="who-has",
651 hwsrc=self.pg2.remote_mac,
652 pdst="10.10.10.3",
653 psrc=self.pg1.remote_hosts[7].ip4))
654 self.send_and_assert_no_replies(
655 self.pg0, p,
656 "ARP req for non-local destination - unnum")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800657
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700658 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
659 ARP(op="who-has",
660 hwsrc=self.pg0.remote_mac,
661 pdst=self.pg1.local_ip4,
662 psrc=self.pg1.remote_ip4))
663 self.send_and_assert_no_replies(self.pg0, p,
664 "ARP req diff sub-net")
665 self.assertFalse(find_nbr(self,
666 self.pg0.sw_if_index,
667 self.pg1.remote_ip4))
668
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800669 #
670 # 2 - don't respond to ARP request from an address not within the
671 # interface's sub-net
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700672 # 2b - to a proxied address
673 # 2c - not within a different interface's sub-net
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800674 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
675 ARP(op="who-has",
676 hwsrc=self.pg0.remote_mac,
677 psrc="10.10.10.3",
678 pdst=self.pg0.local_ip4))
679 self.send_and_assert_no_replies(self.pg0, p,
680 "ARP req for non-local source")
Neale Ranns4b919a52017-03-11 05:55:21 -0800681 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
682 ARP(op="who-has",
683 hwsrc=self.pg2.remote_mac,
684 psrc="10.10.10.3",
685 pdst=self.pg0.local_ip4))
686 self.send_and_assert_no_replies(
687 self.pg0, p,
688 "ARP req for non-local source - unnum")
Neale Rannsca193612017-06-14 06:50:08 -0700689 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
690 ARP(op="who-has",
691 hwsrc=self.pg0.remote_mac,
692 psrc=self.pg1.remote_ip4,
693 pdst=self.pg0.local_ip4))
694 self.send_and_assert_no_replies(self.pg0, p,
695 "ARP req for non-local source 2c")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800696
697 #
698 # 3 - don't respond to ARP request from an address that belongs to
699 # the router
700 #
701 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
702 ARP(op="who-has",
703 hwsrc=self.pg0.remote_mac,
704 psrc=self.pg0.local_ip4,
705 pdst=self.pg0.local_ip4))
706 self.send_and_assert_no_replies(self.pg0, p,
707 "ARP req for non-local source")
708
709 #
710 # 4 - don't respond to ARP requests that has mac source different
711 # from ARP request HW source
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800712 #
713 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
714 ARP(op="who-has",
715 hwsrc="00:00:00:DE:AD:BE",
716 psrc=self.pg0.remote_ip4,
717 pdst=self.pg0.local_ip4))
718 self.send_and_assert_no_replies(self.pg0, p,
719 "ARP req for non-local source")
720
721 #
zhaoqinglingb4c42cd2017-12-23 15:20:59 +0800722 # 5 - don't respond to ARP requests for address within the
723 # interface's sub-net but not the interface's address
724 #
725 self.pg0.generate_remote_hosts(2)
726 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
727 ARP(op="who-has",
728 hwsrc=self.pg0.remote_mac,
729 psrc=self.pg0.remote_hosts[0].ip4,
730 pdst=self.pg0.remote_hosts[1].ip4))
731 self.send_and_assert_no_replies(self.pg0, p,
732 "ARP req for non-local destination")
733
734 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800735 # cleanup
736 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800737 static_arp.remove_vpp_config()
Neale Ranns3983ac22017-03-10 11:53:27 -0800738 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800739
Neale Ranns4b919a52017-03-11 05:55:21 -0800740 # need this to flush the adj-fibs
741 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
742 self.pg2.admin_down()
Neale Rannsca193612017-06-14 06:50:08 -0700743 self.pg1.admin_down()
Neale Ranns4b919a52017-03-11 05:55:21 -0800744
Neale Ranns24b170a2017-08-15 05:33:11 -0700745 def test_proxy_mirror_arp(self):
746 """ Interface Mirror Proxy ARP """
747
748 #
749 # When VPP has an interface whose address is also applied to a TAP
750 # interface on the host, then VPP's TAP interface will be unnumbered
751 # to the 'real' interface and do proxy ARP from the host.
752 # the curious aspect of this setup is that ARP requests from the host
753 # will come from the VPP's own address.
754 #
755 self.pg0.generate_remote_hosts(2)
756
757 arp_req_from_me = (Ether(src=self.pg2.remote_mac,
758 dst="ff:ff:ff:ff:ff:ff") /
759 ARP(op="who-has",
760 hwsrc=self.pg2.remote_mac,
761 pdst=self.pg0.remote_hosts[1].ip4,
762 psrc=self.pg0.local_ip4))
763
764 #
765 # Configure Proxy ARP for the subnet on PG0addresses on pg0
766 #
Ole Troan5c2a2372020-11-19 16:01:23 +0100767 self.vapi.proxy_arp_add_del(proxy={'table_id': 0,
768 'low': self.pg0._local_ip4_subnet,
769 'hi': self.pg0._local_ip4_bcast},
770 is_add=1)
Neale Ranns24b170a2017-08-15 05:33:11 -0700771
772 # Make pg2 un-numbered to pg0
773 #
774 self.pg2.set_unnumbered(self.pg0.sw_if_index)
775
776 #
777 # Enable pg2 for proxy ARP
778 #
779 self.pg2.set_proxy_arp()
780
781 #
782 # Send the ARP request with an originating address that
783 # is VPP's own address
784 #
Neale Ranns240dcb22020-04-23 09:04:59 +0000785 rx = self.send_and_expect(self.pg2, [arp_req_from_me], self.pg2)
Neale Ranns24b170a2017-08-15 05:33:11 -0700786 self.verify_arp_resp(rx[0],
787 self.pg2.local_mac,
788 self.pg2.remote_mac,
789 self.pg0.remote_hosts[1].ip4,
790 self.pg0.local_ip4)
791
792 #
793 # validate we have not learned an ARP entry as a result of this
794 #
795 self.assertFalse(find_nbr(self,
796 self.pg2.sw_if_index,
797 self.pg0.local_ip4))
798
799 #
Neale Ranns240dcb22020-04-23 09:04:59 +0000800 # setup a punt redirect so packets from the uplink go to the tap
801 #
Jakub Grajciar2df2f752020-12-01 11:23:44 +0100802 redirect = VppIpPuntRedirect(self, self.pg0.sw_if_index,
803 self.pg2.sw_if_index, self.pg0.local_ip4)
804 redirect.add_vpp_config()
Neale Ranns240dcb22020-04-23 09:04:59 +0000805
806 p_tcp = (Ether(src=self.pg0.remote_mac,
807 dst=self.pg0.local_mac,) /
808 IP(src=self.pg0.remote_ip4,
809 dst=self.pg0.local_ip4) /
810 TCP(sport=80, dport=80) /
811 Raw())
812 rx = self.send_and_expect(self.pg0, [p_tcp], self.pg2)
813
814 # there's no ARP entry so this is an ARP req
815 self.assertTrue(rx[0].haslayer(ARP))
816
817 # and ARP entry for VPP's pg0 address on the host interface
818 n1 = VppNeighbor(self,
819 self.pg2.sw_if_index,
820 self.pg2.remote_mac,
821 self.pg0.local_ip4,
822 is_no_fib_entry=True).add_vpp_config()
823 # now the packets shold forward
824 rx = self.send_and_expect(self.pg0, [p_tcp], self.pg2)
825 self.assertFalse(rx[0].haslayer(ARP))
826 self.assertEqual(rx[0][Ether].dst, self.pg2.remote_mac)
827
828 #
829 # flush the neighbor cache on the uplink
830 #
831 af = VppEnum.vl_api_address_family_t
832 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, self.pg0.sw_if_index)
833
834 # ensure we can still resolve the ARPs on the uplink
835 self.pg0.resolve_arp()
836
837 self.assertTrue(find_nbr(self,
838 self.pg0.sw_if_index,
839 self.pg0.remote_ip4))
840
841 #
Neale Ranns24b170a2017-08-15 05:33:11 -0700842 # cleanup
843 #
Ole Troan5c2a2372020-11-19 16:01:23 +0100844 self.vapi.proxy_arp_add_del(proxy={'table_id': 0,
845 'low': self.pg0._local_ip4_subnet,
846 'hi': self.pg0._local_ip4_bcast},
Neale Ranns24b170a2017-08-15 05:33:11 -0700847 is_add=0)
Jakub Grajciar2df2f752020-12-01 11:23:44 +0100848 redirect.remove_vpp_config()
Neale Ranns24b170a2017-08-15 05:33:11 -0700849
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800850 def test_proxy_arp(self):
851 """ Proxy ARP """
852
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700853 self.pg1.generate_remote_hosts(2)
854
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800855 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700856 # Proxy ARP request packets for each interface
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800857 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800858 arp_req_pg0 = (Ether(src=self.pg0.remote_mac,
859 dst="ff:ff:ff:ff:ff:ff") /
860 ARP(op="who-has",
861 hwsrc=self.pg0.remote_mac,
862 pdst="10.10.10.3",
863 psrc=self.pg0.remote_ip4))
Neale Ranns30d0fd42017-05-30 07:30:04 -0700864 arp_req_pg0_tagged = (Ether(src=self.pg0.remote_mac,
865 dst="ff:ff:ff:ff:ff:ff") /
866 Dot1Q(vlan=0) /
867 ARP(op="who-has",
868 hwsrc=self.pg0.remote_mac,
869 pdst="10.10.10.3",
870 psrc=self.pg0.remote_ip4))
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800871 arp_req_pg1 = (Ether(src=self.pg1.remote_mac,
872 dst="ff:ff:ff:ff:ff:ff") /
873 ARP(op="who-has",
874 hwsrc=self.pg1.remote_mac,
875 pdst="10.10.10.3",
876 psrc=self.pg1.remote_ip4))
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700877 arp_req_pg2 = (Ether(src=self.pg2.remote_mac,
878 dst="ff:ff:ff:ff:ff:ff") /
879 ARP(op="who-has",
880 hwsrc=self.pg2.remote_mac,
881 pdst="10.10.10.3",
882 psrc=self.pg1.remote_hosts[1].ip4))
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800883 arp_req_pg3 = (Ether(src=self.pg3.remote_mac,
884 dst="ff:ff:ff:ff:ff:ff") /
885 ARP(op="who-has",
886 hwsrc=self.pg3.remote_mac,
887 pdst="10.10.10.3",
888 psrc=self.pg3.remote_ip4))
889
890 #
891 # Configure Proxy ARP for 10.10.10.0 -> 10.10.10.124
892 #
Ole Troan5c2a2372020-11-19 16:01:23 +0100893 self.vapi.proxy_arp_add_del(proxy={'table_id': 0,
894 'low': "10.10.10.2",
895 'hi': "10.10.10.124"},
896 is_add=1)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800897
898 #
899 # No responses are sent when the interfaces are not enabled for proxy
900 # ARP
901 #
902 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
903 "ARP req from unconfigured interface")
904 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
905 "ARP req from unconfigured interface")
906
907 #
908 # Make pg2 un-numbered to pg1
909 # still won't reply.
910 #
911 self.pg2.set_unnumbered(self.pg1.sw_if_index)
912
913 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
914 "ARP req from unnumbered interface")
915
916 #
917 # Enable each interface to reply to proxy ARPs
918 #
919 for i in self.pg_interfaces:
920 i.set_proxy_arp()
921
922 #
923 # Now each of the interfaces should reply to a request to a proxied
924 # address
925 #
926 self.pg0.add_stream(arp_req_pg0)
927 self.pg_enable_capture(self.pg_interfaces)
928 self.pg_start()
929
930 rx = self.pg0.get_capture(1)
931 self.verify_arp_resp(rx[0],
932 self.pg0.local_mac,
933 self.pg0.remote_mac,
934 "10.10.10.3",
935 self.pg0.remote_ip4)
936
Neale Ranns30d0fd42017-05-30 07:30:04 -0700937 self.pg0.add_stream(arp_req_pg0_tagged)
938 self.pg_enable_capture(self.pg_interfaces)
939 self.pg_start()
940
941 rx = self.pg0.get_capture(1)
942 self.verify_arp_resp(rx[0],
943 self.pg0.local_mac,
944 self.pg0.remote_mac,
945 "10.10.10.3",
946 self.pg0.remote_ip4)
947
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800948 self.pg1.add_stream(arp_req_pg1)
949 self.pg_enable_capture(self.pg_interfaces)
950 self.pg_start()
951
952 rx = self.pg1.get_capture(1)
953 self.verify_arp_resp(rx[0],
954 self.pg1.local_mac,
955 self.pg1.remote_mac,
956 "10.10.10.3",
957 self.pg1.remote_ip4)
958
959 self.pg2.add_stream(arp_req_pg2)
960 self.pg_enable_capture(self.pg_interfaces)
961 self.pg_start()
962
963 rx = self.pg2.get_capture(1)
964 self.verify_arp_resp(rx[0],
965 self.pg2.local_mac,
966 self.pg2.remote_mac,
967 "10.10.10.3",
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700968 self.pg1.remote_hosts[1].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800969
970 #
971 # A request for an address out of the configured range
972 #
973 arp_req_pg1_hi = (Ether(src=self.pg1.remote_mac,
974 dst="ff:ff:ff:ff:ff:ff") /
975 ARP(op="who-has",
976 hwsrc=self.pg1.remote_mac,
977 pdst="10.10.10.125",
978 psrc=self.pg1.remote_ip4))
979 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_hi,
980 "ARP req out of range HI")
981 arp_req_pg1_low = (Ether(src=self.pg1.remote_mac,
982 dst="ff:ff:ff:ff:ff:ff") /
983 ARP(op="who-has",
984 hwsrc=self.pg1.remote_mac,
985 pdst="10.10.10.1",
986 psrc=self.pg1.remote_ip4))
987 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_low,
988 "ARP req out of range Low")
989
990 #
991 # Request for an address in the proxy range but from an interface
992 # in a different VRF
993 #
994 self.send_and_assert_no_replies(self.pg3, arp_req_pg3,
995 "ARP req from different VRF")
996
997 #
998 # Disable Each interface for proxy ARP
999 # - expect none to respond
1000 #
1001 for i in self.pg_interfaces:
1002 i.set_proxy_arp(0)
1003
1004 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
1005 "ARP req from disable")
1006 self.send_and_assert_no_replies(self.pg1, arp_req_pg1,
1007 "ARP req from disable")
1008 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
1009 "ARP req from disable")
Neale Ranns37be7362017-02-21 17:30:26 -08001010
1011 #
1012 # clean up on interface 2
1013 #
Neale Ranns4b919a52017-03-11 05:55:21 -08001014 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns37be7362017-02-21 17:30:26 -08001015
1016 def test_mpls(self):
1017 """ MPLS """
1018
1019 #
1020 # Interface 2 does not yet have ip4 config
1021 #
1022 self.pg2.config_ip4()
1023 self.pg2.generate_remote_hosts(2)
1024
1025 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001026 # Add a route with out going label via an ARP unresolved next-hop
Neale Ranns37be7362017-02-21 17:30:26 -08001027 #
1028 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1029 [VppRoutePath(self.pg2.remote_hosts[1].ip4,
1030 self.pg2.sw_if_index,
1031 labels=[55])])
1032 ip_10_0_0_1.add_vpp_config()
1033
1034 #
1035 # packets should generate an ARP request
1036 #
1037 p = (Ether(src=self.pg0.remote_mac,
1038 dst=self.pg0.local_mac) /
1039 IP(src=self.pg0.remote_ip4, dst="10.0.0.1") /
1040 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01001041 Raw(b'\xa5' * 100))
Neale Ranns37be7362017-02-21 17:30:26 -08001042
1043 self.pg0.add_stream(p)
1044 self.pg_enable_capture(self.pg_interfaces)
1045 self.pg_start()
1046
1047 rx = self.pg2.get_capture(1)
1048 self.verify_arp_req(rx[0],
1049 self.pg2.local_mac,
1050 self.pg2.local_ip4,
1051 self.pg2._remote_hosts[1].ip4)
1052
1053 #
1054 # now resolve the neighbours
1055 #
1056 self.pg2.configure_ipv4_neighbors()
1057
1058 #
1059 # Now packet should be properly MPLS encapped.
1060 # This verifies that MPLS link-type adjacencies are completed
1061 # when the ARP entry resolves
1062 #
1063 self.pg0.add_stream(p)
1064 self.pg_enable_capture(self.pg_interfaces)
1065 self.pg_start()
1066
1067 rx = self.pg2.get_capture(1)
1068 self.verify_ip_o_mpls(rx[0],
1069 self.pg2.local_mac,
1070 self.pg2.remote_hosts[1].mac,
1071 55,
1072 self.pg0.remote_ip4,
1073 "10.0.0.1")
Neale Ranns4b919a52017-03-11 05:55:21 -08001074 self.pg2.unconfig_ip4()
Neale Ranns37be7362017-02-21 17:30:26 -08001075
Matthew Smithcb9ab472017-05-16 21:35:56 -05001076 def test_arp_vrrp(self):
1077 """ ARP reply with VRRP virtual src hw addr """
1078
1079 #
1080 # IP packet destined for pg1 remote host arrives on pg0 resulting
1081 # in an ARP request for the address of the remote host on pg1
1082 #
1083 p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1084 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1085 UDP(sport=1234, dport=1234) /
1086 Raw())
1087
Neale Ranns37029302018-08-10 05:30:06 -07001088 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
Matthew Smithcb9ab472017-05-16 21:35:56 -05001089
1090 self.verify_arp_req(rx1[0],
1091 self.pg1.local_mac,
1092 self.pg1.local_ip4,
1093 self.pg1.remote_ip4)
1094
1095 #
1096 # ARP reply for address of pg1 remote host arrives on pg1 with
1097 # the hw src addr set to a value in the VRRP IPv4 range of
1098 # MAC addresses
1099 #
1100 p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1101 ARP(op="is-at", hwdst=self.pg1.local_mac,
1102 hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
1103 psrc=self.pg1.remote_ip4))
1104
Neale Ranns37029302018-08-10 05:30:06 -07001105 self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
Matthew Smithcb9ab472017-05-16 21:35:56 -05001106
1107 #
1108 # IP packet destined for pg1 remote host arrives on pg0 again.
1109 # VPP should have an ARP entry for that address now and the packet
1110 # should be sent out pg1.
1111 #
Neale Ranns37029302018-08-10 05:30:06 -07001112 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
Matthew Smithcb9ab472017-05-16 21:35:56 -05001113
1114 self.verify_ip(rx1[0],
1115 self.pg1.local_mac,
1116 "00:00:5e:00:01:09",
1117 self.pg0.remote_ip4,
1118 self.pg1.remote_ip4)
1119
1120 self.pg1.admin_down()
1121 self.pg1.admin_up()
1122
Neale Rannsdcd6d622017-05-26 02:59:16 -07001123 def test_arp_duplicates(self):
1124 """ ARP Duplicates"""
1125
1126 #
1127 # Generate some hosts on the LAN
1128 #
1129 self.pg1.generate_remote_hosts(3)
1130
1131 #
1132 # Add host 1 on pg1 and pg2
1133 #
1134 arp_pg1 = VppNeighbor(self,
1135 self.pg1.sw_if_index,
1136 self.pg1.remote_hosts[1].mac,
1137 self.pg1.remote_hosts[1].ip4)
1138 arp_pg1.add_vpp_config()
1139 arp_pg2 = VppNeighbor(self,
1140 self.pg2.sw_if_index,
1141 self.pg2.remote_mac,
1142 self.pg1.remote_hosts[1].ip4)
1143 arp_pg2.add_vpp_config()
1144
1145 #
1146 # IP packet destined for pg1 remote host arrives on pg1 again.
1147 #
1148 p = (Ether(dst=self.pg0.local_mac,
1149 src=self.pg0.remote_mac) /
1150 IP(src=self.pg0.remote_ip4,
1151 dst=self.pg1.remote_hosts[1].ip4) /
1152 UDP(sport=1234, dport=1234) /
1153 Raw())
1154
1155 self.pg0.add_stream(p)
1156 self.pg_enable_capture(self.pg_interfaces)
1157 self.pg_start()
1158
1159 rx1 = self.pg1.get_capture(1)
1160
1161 self.verify_ip(rx1[0],
1162 self.pg1.local_mac,
1163 self.pg1.remote_hosts[1].mac,
1164 self.pg0.remote_ip4,
1165 self.pg1.remote_hosts[1].ip4)
1166
1167 #
1168 # remove the duplicate on pg1
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001169 # packet stream should generate ARPs out of pg1
Neale Rannsdcd6d622017-05-26 02:59:16 -07001170 #
1171 arp_pg1.remove_vpp_config()
1172
1173 self.pg0.add_stream(p)
1174 self.pg_enable_capture(self.pg_interfaces)
1175 self.pg_start()
1176
1177 rx1 = self.pg1.get_capture(1)
1178
1179 self.verify_arp_req(rx1[0],
1180 self.pg1.local_mac,
1181 self.pg1.local_ip4,
1182 self.pg1.remote_hosts[1].ip4)
1183
1184 #
1185 # Add it back
1186 #
1187 arp_pg1.add_vpp_config()
1188
1189 self.pg0.add_stream(p)
1190 self.pg_enable_capture(self.pg_interfaces)
1191 self.pg_start()
1192
1193 rx1 = self.pg1.get_capture(1)
1194
1195 self.verify_ip(rx1[0],
1196 self.pg1.local_mac,
1197 self.pg1.remote_hosts[1].mac,
1198 self.pg0.remote_ip4,
1199 self.pg1.remote_hosts[1].ip4)
1200
Neale Ranns15002542017-09-10 04:39:11 -07001201 def test_arp_static(self):
1202 """ ARP Static"""
1203 self.pg2.generate_remote_hosts(3)
1204
1205 #
1206 # Add a static ARP entry
1207 #
1208 static_arp = VppNeighbor(self,
1209 self.pg2.sw_if_index,
1210 self.pg2.remote_hosts[1].mac,
1211 self.pg2.remote_hosts[1].ip4,
1212 is_static=1)
1213 static_arp.add_vpp_config()
1214
1215 #
1216 # Add the connected prefix to the interface
1217 #
1218 self.pg2.config_ip4()
1219
1220 #
1221 # We should now find the adj-fib
1222 #
1223 self.assertTrue(find_nbr(self,
1224 self.pg2.sw_if_index,
1225 self.pg2.remote_hosts[1].ip4,
1226 is_static=1))
1227 self.assertTrue(find_route(self,
1228 self.pg2.remote_hosts[1].ip4,
1229 32))
1230
1231 #
1232 # remove the connected
1233 #
1234 self.pg2.unconfig_ip4()
1235
1236 #
1237 # put the interface into table 1
1238 #
1239 self.pg2.set_table_ip4(1)
1240
1241 #
1242 # configure the same connected and expect to find the
1243 # adj fib in the new table
1244 #
1245 self.pg2.config_ip4()
1246 self.assertTrue(find_route(self,
1247 self.pg2.remote_hosts[1].ip4,
1248 32,
1249 table_id=1))
1250
1251 #
1252 # clean-up
1253 #
1254 self.pg2.unconfig_ip4()
Neale Rannscbe25aa2019-09-30 10:53:31 +00001255 static_arp.remove_vpp_config()
Neale Ranns15002542017-09-10 04:39:11 -07001256 self.pg2.set_table_ip4(0)
1257
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001258 def test_arp_static_replace_dynamic_same_mac(self):
1259 """ ARP Static can replace Dynamic (same mac) """
1260 self.pg2.generate_remote_hosts(1)
1261
1262 dyn_arp = VppNeighbor(self,
1263 self.pg2.sw_if_index,
1264 self.pg2.remote_hosts[0].mac,
1265 self.pg2.remote_hosts[0].ip4)
1266 static_arp = VppNeighbor(self,
1267 self.pg2.sw_if_index,
1268 self.pg2.remote_hosts[0].mac,
1269 self.pg2.remote_hosts[0].ip4,
1270 is_static=1)
1271
1272 #
1273 # Add a dynamic ARP entry
1274 #
1275 dyn_arp.add_vpp_config()
1276
1277 #
1278 # We should find the dynamic nbr
1279 #
1280 self.assertFalse(find_nbr(self,
1281 self.pg2.sw_if_index,
1282 self.pg2.remote_hosts[0].ip4,
1283 is_static=1))
1284 self.assertTrue(find_nbr(self,
1285 self.pg2.sw_if_index,
1286 self.pg2.remote_hosts[0].ip4,
1287 is_static=0,
1288 mac=self.pg2.remote_hosts[0].mac))
1289
1290 #
1291 # Add a static ARP entry with the same mac
1292 #
1293 static_arp.add_vpp_config()
1294
1295 #
1296 # We should now find the static nbr with the same mac
1297 #
1298 self.assertFalse(find_nbr(self,
1299 self.pg2.sw_if_index,
1300 self.pg2.remote_hosts[0].ip4,
1301 is_static=0))
1302 self.assertTrue(find_nbr(self,
1303 self.pg2.sw_if_index,
1304 self.pg2.remote_hosts[0].ip4,
1305 is_static=1,
1306 mac=self.pg2.remote_hosts[0].mac))
1307
1308 #
1309 # clean-up
1310 #
1311 static_arp.remove_vpp_config()
1312
1313 def test_arp_static_replace_dynamic_diff_mac(self):
1314 """ ARP Static can replace Dynamic (diff mac) """
1315 self.pg2.generate_remote_hosts(2)
1316
1317 dyn_arp = VppNeighbor(self,
1318 self.pg2.sw_if_index,
1319 self.pg2.remote_hosts[0].mac,
1320 self.pg2.remote_hosts[0].ip4)
1321 static_arp = VppNeighbor(self,
1322 self.pg2.sw_if_index,
1323 self.pg2.remote_hosts[1].mac,
1324 self.pg2.remote_hosts[0].ip4,
1325 is_static=1)
1326
1327 #
1328 # Add a dynamic ARP entry
1329 #
1330 dyn_arp.add_vpp_config()
1331
1332 #
1333 # We should find the dynamic nbr
1334 #
1335 self.assertFalse(find_nbr(self,
1336 self.pg2.sw_if_index,
1337 self.pg2.remote_hosts[0].ip4,
1338 is_static=1))
1339 self.assertTrue(find_nbr(self,
1340 self.pg2.sw_if_index,
1341 self.pg2.remote_hosts[0].ip4,
1342 is_static=0,
1343 mac=self.pg2.remote_hosts[0].mac))
1344
1345 #
1346 # Add a static ARP entry with a changed mac
1347 #
1348 static_arp.add_vpp_config()
1349
1350 #
1351 # We should now find the static nbr with a changed mac
1352 #
1353 self.assertFalse(find_nbr(self,
1354 self.pg2.sw_if_index,
1355 self.pg2.remote_hosts[0].ip4,
1356 is_static=0))
1357 self.assertTrue(find_nbr(self,
1358 self.pg2.sw_if_index,
1359 self.pg2.remote_hosts[0].ip4,
1360 is_static=1,
1361 mac=self.pg2.remote_hosts[1].mac))
1362
1363 #
1364 # clean-up
1365 #
1366 static_arp.remove_vpp_config()
1367
Neale Rannsc819fc62018-02-16 02:44:05 -08001368 def test_arp_incomplete(self):
1369 """ ARP Incomplete"""
1370 self.pg1.generate_remote_hosts(3)
1371
1372 p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1373 IP(src=self.pg0.remote_ip4,
1374 dst=self.pg1.remote_hosts[1].ip4) /
1375 UDP(sport=1234, dport=1234) /
1376 Raw())
1377 p1 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1378 IP(src=self.pg0.remote_ip4,
1379 dst=self.pg1.remote_hosts[2].ip4) /
1380 UDP(sport=1234, dport=1234) /
1381 Raw())
1382
1383 #
1384 # a packet to an unresolved destination generates an ARP request
1385 #
1386 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1387 self.verify_arp_req(rx[0],
1388 self.pg1.local_mac,
1389 self.pg1.local_ip4,
1390 self.pg1._remote_hosts[1].ip4)
1391
1392 #
1393 # add a neighbour for remote host 1
1394 #
1395 static_arp = VppNeighbor(self,
1396 self.pg1.sw_if_index,
1397 self.pg1.remote_hosts[1].mac,
1398 self.pg1.remote_hosts[1].ip4,
1399 is_static=1)
1400 static_arp.add_vpp_config()
1401
1402 #
1403 # change the interface's MAC
1404 #
Neale Rannsc819fc62018-02-16 02:44:05 -08001405 self.vapi.sw_interface_set_mac_address(self.pg1.sw_if_index,
Neale Ranns77f91622020-11-23 16:25:27 +00001406 "00:00:00:33:33:33")
Neale Rannsc819fc62018-02-16 02:44:05 -08001407
1408 #
1409 # now ARP requests come from the new source mac
1410 #
1411 rx = self.send_and_expect(self.pg0, [p1], self.pg1)
1412 self.verify_arp_req(rx[0],
1413 "00:00:00:33:33:33",
1414 self.pg1.local_ip4,
1415 self.pg1._remote_hosts[2].ip4)
1416
1417 #
1418 # packets to the resolved host also have the new source mac
1419 #
1420 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1421 self.verify_ip(rx[0],
1422 "00:00:00:33:33:33",
1423 self.pg1.remote_hosts[1].mac,
1424 self.pg0.remote_ip4,
1425 self.pg1.remote_hosts[1].ip4)
1426
1427 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001428 # set the mac address on the interface that does not have a
Neale Rannsc819fc62018-02-16 02:44:05 -08001429 # configured subnet and thus no glean
1430 #
1431 self.vapi.sw_interface_set_mac_address(self.pg2.sw_if_index,
Neale Ranns77f91622020-11-23 16:25:27 +00001432 "00:00:00:33:33:33")
Neale Rannsc819fc62018-02-16 02:44:05 -08001433
Neale Ranns59ae61e2018-06-07 18:09:49 -07001434 def test_garp(self):
1435 """ GARP """
1436
1437 #
1438 # Generate some hosts on the LAN
1439 #
1440 self.pg1.generate_remote_hosts(4)
Neale Ranns22eefd72020-09-23 11:25:21 +00001441 self.pg2.generate_remote_hosts(4)
Neale Ranns59ae61e2018-06-07 18:09:49 -07001442
1443 #
1444 # And an ARP entry
1445 #
1446 arp = VppNeighbor(self,
1447 self.pg1.sw_if_index,
1448 self.pg1.remote_hosts[1].mac,
1449 self.pg1.remote_hosts[1].ip4)
1450 arp.add_vpp_config()
1451
1452 self.assertTrue(find_nbr(self,
1453 self.pg1.sw_if_index,
1454 self.pg1.remote_hosts[1].ip4,
1455 mac=self.pg1.remote_hosts[1].mac))
1456
1457 #
1458 # Send a GARP (request) to swap the host 1's address to that of host 2
1459 #
1460 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1461 src=self.pg1.remote_hosts[2].mac) /
1462 ARP(op="who-has",
1463 hwdst=self.pg1.local_mac,
1464 hwsrc=self.pg1.remote_hosts[2].mac,
1465 pdst=self.pg1.remote_hosts[1].ip4,
1466 psrc=self.pg1.remote_hosts[1].ip4))
1467
1468 self.pg1.add_stream(p1)
1469 self.pg_enable_capture(self.pg_interfaces)
1470 self.pg_start()
1471
1472 self.assertTrue(find_nbr(self,
1473 self.pg1.sw_if_index,
1474 self.pg1.remote_hosts[1].ip4,
1475 mac=self.pg1.remote_hosts[2].mac))
1476
1477 #
1478 # Send a GARP (reply) to swap the host 1's address to that of host 3
1479 #
1480 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1481 src=self.pg1.remote_hosts[3].mac) /
1482 ARP(op="is-at",
1483 hwdst=self.pg1.local_mac,
1484 hwsrc=self.pg1.remote_hosts[3].mac,
1485 pdst=self.pg1.remote_hosts[1].ip4,
1486 psrc=self.pg1.remote_hosts[1].ip4))
1487
1488 self.pg1.add_stream(p1)
1489 self.pg_enable_capture(self.pg_interfaces)
1490 self.pg_start()
1491
1492 self.assertTrue(find_nbr(self,
1493 self.pg1.sw_if_index,
1494 self.pg1.remote_hosts[1].ip4,
1495 mac=self.pg1.remote_hosts[3].mac))
1496
1497 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001498 # GARPs (request nor replies) for host we don't know yet
Neale Ranns59ae61e2018-06-07 18:09:49 -07001499 # don't result in new neighbour entries
1500 #
1501 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1502 src=self.pg1.remote_hosts[3].mac) /
1503 ARP(op="who-has",
1504 hwdst=self.pg1.local_mac,
1505 hwsrc=self.pg1.remote_hosts[3].mac,
1506 pdst=self.pg1.remote_hosts[2].ip4,
1507 psrc=self.pg1.remote_hosts[2].ip4))
1508
1509 self.pg1.add_stream(p1)
1510 self.pg_enable_capture(self.pg_interfaces)
1511 self.pg_start()
1512
1513 self.assertFalse(find_nbr(self,
1514 self.pg1.sw_if_index,
1515 self.pg1.remote_hosts[2].ip4))
1516
1517 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1518 src=self.pg1.remote_hosts[3].mac) /
1519 ARP(op="is-at",
1520 hwdst=self.pg1.local_mac,
1521 hwsrc=self.pg1.remote_hosts[3].mac,
1522 pdst=self.pg1.remote_hosts[2].ip4,
1523 psrc=self.pg1.remote_hosts[2].ip4))
1524
1525 self.pg1.add_stream(p1)
1526 self.pg_enable_capture(self.pg_interfaces)
1527 self.pg_start()
1528
1529 self.assertFalse(find_nbr(self,
1530 self.pg1.sw_if_index,
1531 self.pg1.remote_hosts[2].ip4))
1532
Neale Ranns22eefd72020-09-23 11:25:21 +00001533 #
1534 # IP address in different subnets are not learnt
1535 #
1536 self.pg2.configure_ipv4_neighbors()
1537
1538 for op in ["is-at", "who-has"]:
1539 p1 = [(Ether(dst="ff:ff:ff:ff:ff:ff",
1540 src=self.pg2.remote_hosts[1].mac) /
1541 ARP(op=op,
1542 hwdst=self.pg2.local_mac,
1543 hwsrc=self.pg2.remote_hosts[1].mac,
1544 pdst=self.pg2.remote_hosts[1].ip4,
1545 psrc=self.pg2.remote_hosts[1].ip4)),
1546 (Ether(dst="ff:ff:ff:ff:ff:ff",
1547 src=self.pg2.remote_hosts[1].mac) /
1548 ARP(op=op,
1549 hwdst="ff:ff:ff:ff:ff:ff",
1550 hwsrc=self.pg2.remote_hosts[1].mac,
1551 pdst=self.pg2.remote_hosts[1].ip4,
1552 psrc=self.pg2.remote_hosts[1].ip4))]
1553
1554 self.send_and_assert_no_replies(self.pg1, p1)
1555 self.assertFalse(find_nbr(self,
1556 self.pg1.sw_if_index,
1557 self.pg2.remote_hosts[1].ip4))
1558
1559 # they are all dropped because the subnet's don't match
1560 self.assertEqual(4, self.statistics.get_err_counter(
1561 "/err/arp-reply/IP4 destination address not local to subnet"))
1562
Neale Ranns77f91622020-11-23 16:25:27 +00001563 def test_arp_incomplete2(self):
Neale Ranns14260392018-09-28 05:00:57 -07001564 """ Incomplete Entries """
Neale Rannsc8352bc2018-08-29 10:23:58 -07001565
1566 #
Neale Rannscd35e532018-08-31 02:51:45 -07001567 # ensure that we throttle the ARP and ND requests
Neale Rannsc8352bc2018-08-29 10:23:58 -07001568 #
1569 self.pg0.generate_remote_hosts(2)
1570
Neale Rannscd35e532018-08-31 02:51:45 -07001571 #
1572 # IPv4/ARP
1573 #
Neale Rannsc8352bc2018-08-29 10:23:58 -07001574 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1575 [VppRoutePath(self.pg0.remote_hosts[1].ip4,
Neale Rannscd35e532018-08-31 02:51:45 -07001576 self.pg0.sw_if_index)])
Neale Rannsc8352bc2018-08-29 10:23:58 -07001577 ip_10_0_0_1.add_vpp_config()
1578
1579 p1 = (Ether(dst=self.pg1.local_mac,
1580 src=self.pg1.remote_mac) /
1581 IP(src=self.pg1.remote_ip4,
1582 dst="10.0.0.1") /
1583 UDP(sport=1234, dport=1234) /
1584 Raw())
1585
1586 self.pg1.add_stream(p1 * 257)
1587 self.pg_enable_capture(self.pg_interfaces)
1588 self.pg_start()
1589 rx = self.pg0._get_capture(1)
1590
1591 #
1592 # how many we get is going to be dependent on the time for packet
1593 # processing but it should be small
1594 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001595 self.assertLess(len(rx), 64)
Neale Rannsc8352bc2018-08-29 10:23:58 -07001596
Neale Rannscd35e532018-08-31 02:51:45 -07001597 #
1598 # IPv6/ND
1599 #
1600 ip_10_1 = VppIpRoute(self, "10::1", 128,
1601 [VppRoutePath(self.pg0.remote_hosts[1].ip6,
1602 self.pg0.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07001603 proto=DpoProto.DPO_PROTO_IP6)])
Neale Rannscd35e532018-08-31 02:51:45 -07001604 ip_10_1.add_vpp_config()
1605
1606 p1 = (Ether(dst=self.pg1.local_mac,
1607 src=self.pg1.remote_mac) /
1608 IPv6(src=self.pg1.remote_ip6,
1609 dst="10::1") /
1610 UDP(sport=1234, dport=1234) /
1611 Raw())
1612
1613 self.pg1.add_stream(p1 * 257)
1614 self.pg_enable_capture(self.pg_interfaces)
1615 self.pg_start()
1616 rx = self.pg0._get_capture(1)
1617
1618 #
1619 # how many we get is going to be dependent on the time for packet
1620 # processing but it should be small
1621 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001622 self.assertLess(len(rx), 64)
Neale Rannscd35e532018-08-31 02:51:45 -07001623
Neale Ranns7425f922019-01-23 00:36:16 -08001624 def test_arp_forus(self):
1625 """ ARP for for-us """
1626
1627 #
1628 # Test that VPP responds with ARP requests to addresses that
1629 # are connected and local routes.
1630 # Use one of the 'remote' addresses in the subnet as a local address
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001631 # The intention of this route is that it then acts like a secondary
Neale Ranns7425f922019-01-23 00:36:16 -08001632 # address added to an interface
1633 #
1634 self.pg0.generate_remote_hosts(2)
1635
Neale Ranns097fa662018-05-01 05:17:55 -07001636 forus = VppIpRoute(
1637 self, self.pg0.remote_hosts[1].ip4, 32,
1638 [VppRoutePath("0.0.0.0",
1639 self.pg0.sw_if_index,
1640 type=FibPathType.FIB_PATH_TYPE_LOCAL)])
Neale Ranns7425f922019-01-23 00:36:16 -08001641 forus.add_vpp_config()
1642
1643 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
1644 src=self.pg0.remote_mac) /
1645 ARP(op="who-has",
1646 hwdst=self.pg0.local_mac,
1647 hwsrc=self.pg0.remote_mac,
1648 pdst=self.pg0.remote_hosts[1].ip4,
1649 psrc=self.pg0.remote_ip4))
1650
1651 rx = self.send_and_expect(self.pg0, [p], self.pg0)
1652
1653 self.verify_arp_resp(rx[0],
1654 self.pg0.local_mac,
1655 self.pg0.remote_mac,
1656 self.pg0.remote_hosts[1].ip4,
1657 self.pg0.remote_ip4)
1658
Neale Rannsfca3c6a2019-12-31 03:49:34 +00001659 def test_arp_table_swap(self):
1660 #
1661 # Generate some hosts on the LAN
1662 #
1663 N_NBRS = 4
1664 self.pg1.generate_remote_hosts(N_NBRS)
1665
1666 for n in range(N_NBRS):
1667 # a route thru each neighbour
1668 VppIpRoute(self, "10.0.0.%d" % n, 32,
1669 [VppRoutePath(self.pg1.remote_hosts[n].ip4,
1670 self.pg1.sw_if_index)]).add_vpp_config()
1671
1672 # resolve each neighbour
1673 p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1674 ARP(op="is-at", hwdst=self.pg1.local_mac,
1675 hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
1676 psrc=self.pg1.remote_hosts[n].ip4))
1677
1678 self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
1679
1680 self.logger.info(self.vapi.cli("sh ip neighbors"))
1681
1682 #
1683 # swap the table pg1 is in
1684 #
1685 table = VppIpTable(self, 100).add_vpp_config()
1686
1687 self.pg1.unconfig_ip4()
1688 self.pg1.set_table_ip4(100)
1689 self.pg1.config_ip4()
1690
1691 #
1692 # all neighbours are cleared
1693 #
1694 for n in range(N_NBRS):
1695 self.assertFalse(find_nbr(self,
1696 self.pg1.sw_if_index,
1697 self.pg1.remote_hosts[n].ip4))
1698
1699 #
1700 # packets to all neighbours generate ARP requests
1701 #
1702 for n in range(N_NBRS):
1703 # a route thru each neighbour
1704 VppIpRoute(self, "10.0.0.%d" % n, 32,
1705 [VppRoutePath(self.pg1.remote_hosts[n].ip4,
1706 self.pg1.sw_if_index)],
1707 table_id=100).add_vpp_config()
1708
1709 p = (Ether(src=self.pg1.remote_hosts[n].mac,
1710 dst=self.pg1.local_mac) /
1711 IP(src=self.pg1.remote_hosts[n].ip4,
1712 dst="10.0.0.%d" % n) /
1713 Raw(b'0x5' * 100))
1714 rxs = self.send_and_expect(self.pg1, [p], self.pg1)
1715 for rx in rxs:
1716 self.verify_arp_req(rx,
1717 self.pg1.local_mac,
1718 self.pg1.local_ip4,
1719 self.pg1.remote_hosts[n].ip4)
1720
1721 self.pg1.unconfig_ip4()
1722 self.pg1.set_table_ip4(0)
1723
Neale Rannse2fe0972020-11-26 08:37:27 +00001724 def test_glean_src_select(self):
1725 """ Multi Connecteds """
1726
1727 #
1728 # configure multiple connected subnets on an interface
1729 # and ensure that ARP requests for hosts on those subnets
1730 # pick up the correct source address
1731 #
1732 conn1 = VppIpInterfaceAddress(self, self.pg1,
1733 "10.0.0.1", 24).add_vpp_config()
1734 conn2 = VppIpInterfaceAddress(self, self.pg1,
1735 "10.0.1.1", 24).add_vpp_config()
1736
1737 p1 = (Ether(src=self.pg0.remote_mac,
1738 dst=self.pg0.local_mac) /
1739 IP(src=self.pg1.remote_ip4,
1740 dst="10.0.0.128") /
1741 Raw(b'0x5' * 100))
1742
1743 rxs = self.send_and_expect(self.pg0, [p1], self.pg1)
1744 for rx in rxs:
1745 self.verify_arp_req(rx,
1746 self.pg1.local_mac,
1747 "10.0.0.1",
1748 "10.0.0.128")
1749
1750 p2 = (Ether(src=self.pg0.remote_mac,
1751 dst=self.pg0.local_mac) /
1752 IP(src=self.pg1.remote_ip4,
1753 dst="10.0.1.128") /
1754 Raw(b'0x5' * 100))
1755
1756 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
1757 for rx in rxs:
1758 self.verify_arp_req(rx,
1759 self.pg1.local_mac,
1760 "10.0.1.1",
1761 "10.0.1.128")
1762
1763 #
1764 # add a local address in the same subnet
1765 # the source addresses are equivalent. VPP happens to
1766 # choose the last one that was added
1767 conn3 = VppIpInterfaceAddress(self, self.pg1,
1768 "10.0.1.2", 24).add_vpp_config()
1769
1770 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
1771 for rx in rxs:
1772 self.verify_arp_req(rx,
1773 self.pg1.local_mac,
1774 "10.0.1.2",
1775 "10.0.1.128")
1776
1777 #
1778 # remove
1779 #
1780 conn3.remove_vpp_config()
1781 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
1782 for rx in rxs:
1783 self.verify_arp_req(rx,
1784 self.pg1.local_mac,
1785 "10.0.1.1",
1786 "10.0.1.128")
1787
1788 #
1789 # add back, this time remove the first one
1790 #
1791 conn3 = VppIpInterfaceAddress(self, self.pg1,
1792 "10.0.1.2", 24).add_vpp_config()
1793
1794 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
1795 for rx in rxs:
1796 self.verify_arp_req(rx,
1797 self.pg1.local_mac,
1798 "10.0.1.2",
1799 "10.0.1.128")
1800
1801 conn1.remove_vpp_config()
1802 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
1803 for rx in rxs:
1804 self.verify_arp_req(rx,
1805 self.pg1.local_mac,
1806 "10.0.1.2",
1807 "10.0.1.128")
1808
1809 # cleanup
1810 conn3.remove_vpp_config()
1811 conn2.remove_vpp_config()
1812
Neale Rannsdcd6d622017-05-26 02:59:16 -07001813
Neale Ranns14260392018-09-28 05:00:57 -07001814class NeighborStatsTestCase(VppTestCase):
Neale Ranns37029302018-08-10 05:30:06 -07001815 """ ARP/ND Counters """
Neale Ranns14260392018-09-28 05:00:57 -07001816
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001817 @classmethod
1818 def setUpClass(cls):
1819 super(NeighborStatsTestCase, cls).setUpClass()
1820
1821 @classmethod
1822 def tearDownClass(cls):
1823 super(NeighborStatsTestCase, cls).tearDownClass()
1824
Neale Ranns14260392018-09-28 05:00:57 -07001825 def setUp(self):
1826 super(NeighborStatsTestCase, self).setUp()
1827
1828 self.create_pg_interfaces(range(2))
1829
1830 # pg0 configured with ip4 and 6 addresses used for input
1831 # pg1 configured with ip4 and 6 addresses used for output
1832 # pg2 is unnumbered to pg0
1833 for i in self.pg_interfaces:
1834 i.admin_up()
1835 i.config_ip4()
1836 i.config_ip6()
1837 i.resolve_arp()
1838 i.resolve_ndp()
1839
1840 def tearDown(self):
1841 super(NeighborStatsTestCase, self).tearDown()
1842
1843 for i in self.pg_interfaces:
1844 i.unconfig_ip4()
1845 i.unconfig_ip6()
1846 i.admin_down()
1847
1848 def test_arp_stats(self):
1849 """ ARP Counters """
1850
1851 self.vapi.cli("adj counters enable")
1852 self.pg1.generate_remote_hosts(2)
1853
1854 arp1 = VppNeighbor(self,
1855 self.pg1.sw_if_index,
1856 self.pg1.remote_hosts[0].mac,
1857 self.pg1.remote_hosts[0].ip4)
1858 arp1.add_vpp_config()
1859 arp2 = VppNeighbor(self,
1860 self.pg1.sw_if_index,
1861 self.pg1.remote_hosts[1].mac,
1862 self.pg1.remote_hosts[1].ip4)
1863 arp2.add_vpp_config()
1864
1865 p1 = (Ether(dst=self.pg0.local_mac,
1866 src=self.pg0.remote_mac) /
1867 IP(src=self.pg0.remote_ip4,
1868 dst=self.pg1.remote_hosts[0].ip4) /
1869 UDP(sport=1234, dport=1234) /
1870 Raw())
1871 p2 = (Ether(dst=self.pg0.local_mac,
1872 src=self.pg0.remote_mac) /
1873 IP(src=self.pg0.remote_ip4,
1874 dst=self.pg1.remote_hosts[1].ip4) /
1875 UDP(sport=1234, dport=1234) /
1876 Raw())
1877
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001878 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
1879 rx = self.send_and_expect(self.pg0, p2 * NUM_PKTS, self.pg1)
Neale Ranns14260392018-09-28 05:00:57 -07001880
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001881 self.assertEqual(NUM_PKTS, arp1.get_stats()['packets'])
1882 self.assertEqual(NUM_PKTS, arp2.get_stats()['packets'])
Neale Ranns14260392018-09-28 05:00:57 -07001883
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001884 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
1885 self.assertEqual(NUM_PKTS*2, arp1.get_stats()['packets'])
Neale Ranns14260392018-09-28 05:00:57 -07001886
1887 def test_nd_stats(self):
1888 """ ND Counters """
1889
1890 self.vapi.cli("adj counters enable")
1891 self.pg0.generate_remote_hosts(3)
1892
1893 nd1 = VppNeighbor(self,
1894 self.pg0.sw_if_index,
1895 self.pg0.remote_hosts[1].mac,
Neale Ranns37029302018-08-10 05:30:06 -07001896 self.pg0.remote_hosts[1].ip6)
Neale Ranns14260392018-09-28 05:00:57 -07001897 nd1.add_vpp_config()
1898 nd2 = VppNeighbor(self,
1899 self.pg0.sw_if_index,
1900 self.pg0.remote_hosts[2].mac,
Neale Ranns37029302018-08-10 05:30:06 -07001901 self.pg0.remote_hosts[2].ip6)
Neale Ranns14260392018-09-28 05:00:57 -07001902 nd2.add_vpp_config()
1903
1904 p1 = (Ether(dst=self.pg1.local_mac,
1905 src=self.pg1.remote_mac) /
1906 IPv6(src=self.pg1.remote_ip6,
1907 dst=self.pg0.remote_hosts[1].ip6) /
1908 UDP(sport=1234, dport=1234) /
1909 Raw())
1910 p2 = (Ether(dst=self.pg1.local_mac,
1911 src=self.pg1.remote_mac) /
1912 IPv6(src=self.pg1.remote_ip6,
1913 dst=self.pg0.remote_hosts[2].ip6) /
1914 UDP(sport=1234, dport=1234) /
1915 Raw())
1916
1917 rx = self.send_and_expect(self.pg1, p1 * 16, self.pg0)
1918 rx = self.send_and_expect(self.pg1, p2 * 16, self.pg0)
1919
1920 self.assertEqual(16, nd1.get_stats()['packets'])
1921 self.assertEqual(16, nd2.get_stats()['packets'])
1922
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001923 rx = self.send_and_expect(self.pg1, p1 * NUM_PKTS, self.pg0)
1924 self.assertEqual(NUM_PKTS+16, nd1.get_stats()['packets'])
Neale Ranns14260392018-09-28 05:00:57 -07001925
1926
Neale Rannscbe25aa2019-09-30 10:53:31 +00001927class NeighborAgeTestCase(VppTestCase):
1928 """ ARP/ND Aging """
1929
1930 @classmethod
1931 def setUpClass(cls):
1932 super(NeighborAgeTestCase, cls).setUpClass()
1933
1934 @classmethod
1935 def tearDownClass(cls):
1936 super(NeighborAgeTestCase, cls).tearDownClass()
1937
1938 def setUp(self):
1939 super(NeighborAgeTestCase, self).setUp()
1940
1941 self.create_pg_interfaces(range(1))
1942
1943 # pg0 configured with ip4 and 6 addresses used for input
1944 # pg1 configured with ip4 and 6 addresses used for output
1945 # pg2 is unnumbered to pg0
1946 for i in self.pg_interfaces:
1947 i.admin_up()
1948 i.config_ip4()
1949 i.config_ip6()
1950 i.resolve_arp()
1951 i.resolve_ndp()
1952
1953 def tearDown(self):
1954 super(NeighborAgeTestCase, self).tearDown()
1955
1956 for i in self.pg_interfaces:
1957 i.unconfig_ip4()
1958 i.unconfig_ip6()
1959 i.admin_down()
1960
1961 def wait_for_no_nbr(self, intf, address,
1962 n_tries=50, s_time=1):
1963 while (n_tries):
1964 if not find_nbr(self, intf, address):
1965 return True
1966 n_tries = n_tries - 1
1967 self.sleep(s_time)
1968
1969 return False
1970
1971 def verify_arp_req(self, rx, smac, sip, dip):
1972 ether = rx[Ether]
1973 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
1974 self.assertEqual(ether.src, smac)
1975
1976 arp = rx[ARP]
1977 self.assertEqual(arp.hwtype, 1)
1978 self.assertEqual(arp.ptype, 0x800)
1979 self.assertEqual(arp.hwlen, 6)
1980 self.assertEqual(arp.plen, 4)
1981 self.assertEqual(arp.op, arp_opts["who-has"])
1982 self.assertEqual(arp.hwsrc, smac)
1983 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
1984 self.assertEqual(arp.psrc, sip)
1985 self.assertEqual(arp.pdst, dip)
1986
1987 def test_age(self):
1988 """ Aging/Recycle """
1989
1990 self.vapi.cli("set logging unthrottle 0")
1991 self.vapi.cli("set logging size %d" % 0xffff)
1992
1993 self.pg0.generate_remote_hosts(201)
1994
1995 vaf = VppEnum.vl_api_address_family_t
1996
1997 #
1998 # start listening on all interfaces
1999 #
2000 self.pg_enable_capture(self.pg_interfaces)
2001
2002 #
2003 # Set the neighbor configuration:
2004 # limi = 200
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002005 # age = 0 seconds
Neale Rannscbe25aa2019-09-30 10:53:31 +00002006 # recycle = false
2007 #
2008 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
2009 max_number=200,
2010 max_age=0,
2011 recycle=False)
2012
2013 self.vapi.cli("sh ip neighbor-config")
2014
2015 # add the 198 neighbours that should pass (-1 for one created in setup)
2016 for ii in range(200):
2017 VppNeighbor(self,
2018 self.pg0.sw_if_index,
2019 self.pg0.remote_hosts[ii].mac,
2020 self.pg0.remote_hosts[ii].ip4).add_vpp_config()
2021
2022 # one more neighbor over the limit should fail
2023 with self.vapi.assert_negative_api_retval():
2024 VppNeighbor(self,
2025 self.pg0.sw_if_index,
2026 self.pg0.remote_hosts[200].mac,
2027 self.pg0.remote_hosts[200].ip4).add_vpp_config()
2028
2029 #
2030 # change the config to allow recycling the old neighbors
2031 #
2032 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
2033 max_number=200,
2034 max_age=0,
2035 recycle=True)
2036
2037 # now new additions are allowed
2038 VppNeighbor(self,
2039 self.pg0.sw_if_index,
2040 self.pg0.remote_hosts[200].mac,
2041 self.pg0.remote_hosts[200].ip4).add_vpp_config()
2042
2043 # add the first neighbor we configured has been re-used
2044 self.assertFalse(find_nbr(self,
2045 self.pg0.sw_if_index,
2046 self.pg0.remote_hosts[0].ip4))
2047 self.assertTrue(find_nbr(self,
2048 self.pg0.sw_if_index,
2049 self.pg0.remote_hosts[200].ip4))
2050
2051 #
2052 # change the config to age old neighbors
2053 #
2054 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
2055 max_number=200,
2056 max_age=2,
2057 recycle=True)
2058
2059 self.vapi.cli("sh ip4 neighbor-sorted")
2060
2061 #
2062 # expect probes from all these ARP entries as they age
2063 # 3 probes for each neighbor 3*200 = 600
2064 rxs = self.pg0.get_capture(600, timeout=8)
2065
2066 for ii in range(3):
2067 for jj in range(200):
2068 rx = rxs[ii*200 + jj]
2069 # rx.show()
2070
2071 #
2072 # 3 probes sent then 1 more second to see if a reply comes, before
2073 # they age out
2074 #
2075 for jj in range(1, 201):
2076 self.wait_for_no_nbr(self.pg0.sw_if_index,
2077 self.pg0.remote_hosts[jj].ip4)
2078
2079 self.assertFalse(self.vapi.ip_neighbor_dump(sw_if_index=0xffffffff,
2080 af=vaf.ADDRESS_IP4))
2081
2082 #
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002083 # load up some neighbours again with 2s aging enabled
2084 # they should be removed after 10s (2s age + 4s for probes + gap)
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002085 # check for the add and remove events
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002086 #
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002087 enum = VppEnum.vl_api_ip_neighbor_event_flags_t
2088
2089 self.vapi.want_ip_neighbor_events_v2(enable=1)
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002090 for ii in range(10):
2091 VppNeighbor(self,
2092 self.pg0.sw_if_index,
2093 self.pg0.remote_hosts[ii].mac,
2094 self.pg0.remote_hosts[ii].ip4).add_vpp_config()
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002095
2096 e = self.vapi.wait_for_event(1, "ip_neighbor_event_v2")
2097 self.assertEqual(e.flags,
2098 enum.IP_NEIGHBOR_API_EVENT_FLAG_ADDED)
2099 self.assertEqual(str(e.neighbor.ip_address),
2100 self.pg0.remote_hosts[ii].ip4)
2101 self.assertEqual(e.neighbor.mac_address,
2102 self.pg0.remote_hosts[ii].mac)
2103
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002104 self.sleep(10)
2105 self.assertFalse(self.vapi.ip_neighbor_dump(sw_if_index=0xffffffff,
2106 af=vaf.ADDRESS_IP4))
2107
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002108 evs = []
2109 for ii in range(10):
2110 e = self.vapi.wait_for_event(1, "ip_neighbor_event_v2")
2111 self.assertEqual(e.flags,
2112 enum.IP_NEIGHBOR_API_EVENT_FLAG_REMOVED)
2113 evs.append(e)
2114
2115 # check we got the correct mac/ip pairs - done separately
2116 # because we don't care about the order the remove notifications
2117 # arrive
2118 for ii in range(10):
2119 found = False
2120 mac = self.pg0.remote_hosts[ii].mac
2121 ip = self.pg0.remote_hosts[ii].ip4
2122
2123 for e in evs:
2124 if (e.neighbor.mac_address == mac and
2125 str(e.neighbor.ip_address) == ip):
2126 found = True
2127 break
2128 self.assertTrue(found)
2129
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002130 #
2131 # check if we can set age and recycle with empty neighbor list
2132 #
2133 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
2134 max_number=200,
2135 max_age=1000,
2136 recycle=True)
2137
2138 #
Neale Rannscbe25aa2019-09-30 10:53:31 +00002139 # load up some neighbours again, then disable the aging
2140 # they should still be there in 10 seconds time
2141 #
2142 for ii in range(10):
2143 VppNeighbor(self,
2144 self.pg0.sw_if_index,
2145 self.pg0.remote_hosts[ii].mac,
2146 self.pg0.remote_hosts[ii].ip4).add_vpp_config()
2147 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
2148 max_number=200,
2149 max_age=0,
2150 recycle=False)
2151
2152 self.sleep(10)
2153 self.assertTrue(find_nbr(self,
2154 self.pg0.sw_if_index,
2155 self.pg0.remote_hosts[0].ip4))
2156
2157
Neale Rannsc87fbb42020-04-02 17:08:28 +00002158class NeighborReplaceTestCase(VppTestCase):
2159 """ ARP/ND Replacement """
2160
2161 @classmethod
2162 def setUpClass(cls):
2163 super(NeighborReplaceTestCase, cls).setUpClass()
2164
2165 @classmethod
2166 def tearDownClass(cls):
2167 super(NeighborReplaceTestCase, cls).tearDownClass()
2168
2169 def setUp(self):
2170 super(NeighborReplaceTestCase, self).setUp()
2171
2172 self.create_pg_interfaces(range(4))
2173
2174 # pg0 configured with ip4 and 6 addresses used for input
2175 # pg1 configured with ip4 and 6 addresses used for output
2176 # pg2 is unnumbered to pg0
2177 for i in self.pg_interfaces:
2178 i.admin_up()
2179 i.config_ip4()
2180 i.config_ip6()
2181 i.resolve_arp()
2182 i.resolve_ndp()
2183
2184 def tearDown(self):
2185 super(NeighborReplaceTestCase, self).tearDown()
2186
2187 for i in self.pg_interfaces:
2188 i.unconfig_ip4()
2189 i.unconfig_ip6()
2190 i.admin_down()
2191
2192 def test_replace(self):
2193 """ replace """
2194
2195 N_HOSTS = 16
2196
2197 for i in self.pg_interfaces:
2198 i.generate_remote_hosts(N_HOSTS)
2199 i.configure_ipv4_neighbors()
2200 i.configure_ipv6_neighbors()
2201
2202 # replace them all
2203 self.vapi.ip_neighbor_replace_begin()
2204 self.vapi.ip_neighbor_replace_end()
2205
2206 for i in self.pg_interfaces:
2207 for h in range(N_HOSTS):
2208 self.assertFalse(find_nbr(self,
2209 self.pg0.sw_if_index,
2210 self.pg0.remote_hosts[h].ip4))
2211 self.assertFalse(find_nbr(self,
2212 self.pg0.sw_if_index,
2213 self.pg0.remote_hosts[h].ip6))
2214
2215 #
2216 # and them all back via the API
2217 #
2218 for i in self.pg_interfaces:
2219 for h in range(N_HOSTS):
2220 VppNeighbor(self,
2221 i.sw_if_index,
2222 i.remote_hosts[h].mac,
2223 i.remote_hosts[h].ip4).add_vpp_config()
2224 VppNeighbor(self,
2225 i.sw_if_index,
2226 i.remote_hosts[h].mac,
2227 i.remote_hosts[h].ip6).add_vpp_config()
2228
2229 #
2230 # begin the replacement again, this time touch some
2231 # the neighbours on pg1 so they are not deleted
2232 #
2233 self.vapi.ip_neighbor_replace_begin()
2234
2235 # update from the API all neighbours on pg1
2236 for h in range(N_HOSTS):
2237 VppNeighbor(self,
2238 self.pg1.sw_if_index,
2239 self.pg1.remote_hosts[h].mac,
2240 self.pg1.remote_hosts[h].ip4).add_vpp_config()
2241 VppNeighbor(self,
2242 self.pg1.sw_if_index,
2243 self.pg1.remote_hosts[h].mac,
2244 self.pg1.remote_hosts[h].ip6).add_vpp_config()
2245
2246 # update from the data-plane all neighbours on pg3
2247 self.pg3.configure_ipv4_neighbors()
2248 self.pg3.configure_ipv6_neighbors()
2249
2250 # complete the replacement
2251 self.logger.info(self.vapi.cli("sh ip neighbors"))
2252 self.vapi.ip_neighbor_replace_end()
2253
2254 for i in self.pg_interfaces:
2255 if i == self.pg1 or i == self.pg3:
2256 # neighbours on pg1 and pg3 are still present
2257 for h in range(N_HOSTS):
2258 self.assertTrue(find_nbr(self,
2259 i.sw_if_index,
2260 i.remote_hosts[h].ip4))
2261 self.assertTrue(find_nbr(self,
2262 i.sw_if_index,
2263 i.remote_hosts[h].ip6))
2264 else:
2265 # all other neighbours are toast
2266 for h in range(N_HOSTS):
2267 self.assertFalse(find_nbr(self,
2268 i.sw_if_index,
2269 i.remote_hosts[h].ip4))
2270 self.assertFalse(find_nbr(self,
2271 i.sw_if_index,
2272 i.remote_hosts[h].ip6))
2273
2274
Neale Ranns240dcb22020-04-23 09:04:59 +00002275class NeighborFlush(VppTestCase):
2276 """ Neighbor Flush """
2277
2278 @classmethod
2279 def setUpClass(cls):
2280 super(NeighborFlush, cls).setUpClass()
2281
2282 @classmethod
2283 def tearDownClass(cls):
2284 super(NeighborFlush, cls).tearDownClass()
2285
2286 def setUp(self):
2287 super(NeighborFlush, self).setUp()
2288
2289 self.create_pg_interfaces(range(2))
2290
2291 for i in self.pg_interfaces:
2292 i.admin_up()
2293 i.config_ip4()
2294 i.config_ip6()
2295 i.resolve_arp()
2296 i.resolve_ndp()
2297
2298 def tearDown(self):
2299 super(NeighborFlush, self).tearDown()
2300
2301 for i in self.pg_interfaces:
2302 i.unconfig_ip4()
2303 i.unconfig_ip6()
2304 i.admin_down()
2305
2306 def test_flush(self):
2307 """ Neighbour Flush """
2308
2309 e = VppEnum
2310 nf = e.vl_api_ip_neighbor_flags_t
2311 af = e.vl_api_address_family_t
2312 N_HOSTS = 16
2313 static = [False, True]
2314 self.pg0.generate_remote_hosts(N_HOSTS)
2315 self.pg1.generate_remote_hosts(N_HOSTS)
2316
2317 for s in static:
2318 # a few v4 and v6 dynamic neoghbors
2319 for n in range(N_HOSTS):
2320 VppNeighbor(self,
2321 self.pg0.sw_if_index,
2322 self.pg0.remote_hosts[n].mac,
2323 self.pg0.remote_hosts[n].ip4,
2324 is_static=s).add_vpp_config()
2325 VppNeighbor(self,
2326 self.pg1.sw_if_index,
2327 self.pg1.remote_hosts[n].mac,
2328 self.pg1.remote_hosts[n].ip6,
2329 is_static=s).add_vpp_config()
2330
2331 # flush the interfaces individually
2332 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, self.pg0.sw_if_index)
2333
2334 # check we haven't flushed that which we shouldn't
2335 for n in range(N_HOSTS):
2336 self.assertTrue(find_nbr(self,
2337 self.pg1.sw_if_index,
2338 self.pg1.remote_hosts[n].ip6,
2339 is_static=s))
2340
2341 self.vapi.ip_neighbor_flush(af.ADDRESS_IP6, self.pg1.sw_if_index)
2342
2343 for n in range(N_HOSTS):
2344 self.assertFalse(find_nbr(self,
2345 self.pg0.sw_if_index,
2346 self.pg0.remote_hosts[n].ip4))
2347 self.assertFalse(find_nbr(self,
2348 self.pg1.sw_if_index,
2349 self.pg1.remote_hosts[n].ip6))
2350
2351 # add the nieghbours back
2352 for n in range(N_HOSTS):
2353 VppNeighbor(self,
2354 self.pg0.sw_if_index,
2355 self.pg0.remote_hosts[n].mac,
2356 self.pg0.remote_hosts[n].ip4,
2357 is_static=s).add_vpp_config()
2358 VppNeighbor(self,
2359 self.pg1.sw_if_index,
2360 self.pg1.remote_hosts[n].mac,
2361 self.pg1.remote_hosts[n].ip6,
2362 is_static=s).add_vpp_config()
2363
2364 self.logger.info(self.vapi.cli("sh ip neighbor"))
2365
2366 # flush both interfaces at the same time
2367 self.vapi.ip_neighbor_flush(af.ADDRESS_IP6, 0xffffffff)
2368
2369 # check we haven't flushed that which we shouldn't
2370 for n in range(N_HOSTS):
2371 self.assertTrue(find_nbr(self,
2372 self.pg0.sw_if_index,
2373 self.pg0.remote_hosts[n].ip4,
2374 is_static=s))
2375
2376 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, 0xffffffff)
2377
2378 for n in range(N_HOSTS):
2379 self.assertFalse(find_nbr(self,
2380 self.pg0.sw_if_index,
2381 self.pg0.remote_hosts[n].ip4))
2382 self.assertFalse(find_nbr(self,
2383 self.pg1.sw_if_index,
2384 self.pg1.remote_hosts[n].ip6))
2385
2386
Neale Ranns37be7362017-02-21 17:30:26 -08002387if __name__ == '__main__':
2388 unittest.main(testRunner=VppTestRunner)