blob: b263007bcd9b2dceec7a09c7733e1a91500e5628 [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 Ranns097fa662018-05-01 05:17:55 -070010 VppIpTable, DpoProto, FibPathType
Neale Ranns37029302018-08-10 05:30:06 -070011from vpp_papi import VppEnum
Neale Ranns39f9d8b2017-02-16 21:57:05 -080012
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -070013import scapy.compat
Neale Ranns39f9d8b2017-02-16 21:57:05 -080014from scapy.packet import Raw
Neale Ranns30d0fd42017-05-30 07:30:04 -070015from scapy.layers.l2 import Ether, ARP, Dot1Q
Neale Ranns240dcb22020-04-23 09:04:59 +000016from scapy.layers.inet import IP, UDP, TCP
Neale Rannscd35e532018-08-31 02:51:45 -070017from scapy.layers.inet6 import IPv6
Neale Ranns37be7362017-02-21 17:30:26 -080018from scapy.contrib.mpls import MPLS
Neale Ranns14260392018-09-28 05:00:57 -070019from scapy.layers.inet6 import IPv6
Neale Ranns39f9d8b2017-02-16 21:57:05 -080020
Paul Vinciguerra4271c972019-05-14 13:25:49 -040021
22NUM_PKTS = 67
23
Neale Ranns39f9d8b2017-02-16 21:57:05 -080024# not exported by scapy, so redefined here
25arp_opts = {"who-has": 1, "is-at": 2}
26
27
28class ARPTestCase(VppTestCase):
29 """ ARP Test Case """
30
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070031 @classmethod
32 def setUpClass(cls):
33 super(ARPTestCase, cls).setUpClass()
34
35 @classmethod
36 def tearDownClass(cls):
37 super(ARPTestCase, cls).tearDownClass()
38
Neale Ranns39f9d8b2017-02-16 21:57:05 -080039 def setUp(self):
40 super(ARPTestCase, self).setUp()
41
42 # create 3 pg interfaces
43 self.create_pg_interfaces(range(4))
44
45 # pg0 configured with ip4 and 6 addresses used for input
46 # pg1 configured with ip4 and 6 addresses used for output
47 # pg2 is unnumbered to pg0
48 for i in self.pg_interfaces:
49 i.admin_up()
50
51 self.pg0.config_ip4()
52 self.pg0.config_ip6()
53 self.pg0.resolve_arp()
54
55 self.pg1.config_ip4()
56 self.pg1.config_ip6()
57
58 # pg3 in a different VRF
Neale Ranns15002542017-09-10 04:39:11 -070059 self.tbl = VppIpTable(self, 1)
60 self.tbl.add_vpp_config()
61
Neale Ranns39f9d8b2017-02-16 21:57:05 -080062 self.pg3.set_table_ip4(1)
63 self.pg3.config_ip4()
64
Neale Ranns4008ac92017-02-13 23:20:04 -080065 def tearDown(self):
Neale Ranns4b919a52017-03-11 05:55:21 -080066 self.pg0.unconfig_ip4()
67 self.pg0.unconfig_ip6()
68
69 self.pg1.unconfig_ip4()
70 self.pg1.unconfig_ip6()
71
72 self.pg3.unconfig_ip4()
Neale Ranns15002542017-09-10 04:39:11 -070073 self.pg3.set_table_ip4(0)
Neale Ranns4b919a52017-03-11 05:55:21 -080074
Neale Ranns4008ac92017-02-13 23:20:04 -080075 for i in self.pg_interfaces:
Neale Ranns4008ac92017-02-13 23:20:04 -080076 i.admin_down()
77
Neale Ranns15002542017-09-10 04:39:11 -070078 super(ARPTestCase, self).tearDown()
79
Neale Ranns39f9d8b2017-02-16 21:57:05 -080080 def verify_arp_req(self, rx, smac, sip, dip):
81 ether = rx[Ether]
82 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
83 self.assertEqual(ether.src, smac)
84
85 arp = rx[ARP]
86 self.assertEqual(arp.hwtype, 1)
87 self.assertEqual(arp.ptype, 0x800)
88 self.assertEqual(arp.hwlen, 6)
89 self.assertEqual(arp.plen, 4)
90 self.assertEqual(arp.op, arp_opts["who-has"])
91 self.assertEqual(arp.hwsrc, smac)
92 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
93 self.assertEqual(arp.psrc, sip)
94 self.assertEqual(arp.pdst, dip)
95
96 def verify_arp_resp(self, rx, smac, dmac, sip, dip):
97 ether = rx[Ether]
98 self.assertEqual(ether.dst, dmac)
99 self.assertEqual(ether.src, smac)
100
101 arp = rx[ARP]
102 self.assertEqual(arp.hwtype, 1)
103 self.assertEqual(arp.ptype, 0x800)
104 self.assertEqual(arp.hwlen, 6)
105 self.assertEqual(arp.plen, 4)
106 self.assertEqual(arp.op, arp_opts["is-at"])
107 self.assertEqual(arp.hwsrc, smac)
108 self.assertEqual(arp.hwdst, dmac)
109 self.assertEqual(arp.psrc, sip)
110 self.assertEqual(arp.pdst, dip)
111
Matthew Smithcb9ab472017-05-16 21:35:56 -0500112 def verify_arp_vrrp_resp(self, rx, smac, dmac, sip, dip):
113 ether = rx[Ether]
114 self.assertEqual(ether.dst, dmac)
115 self.assertEqual(ether.src, smac)
116
117 arp = rx[ARP]
118 self.assertEqual(arp.hwtype, 1)
119 self.assertEqual(arp.ptype, 0x800)
120 self.assertEqual(arp.hwlen, 6)
121 self.assertEqual(arp.plen, 4)
122 self.assertEqual(arp.op, arp_opts["is-at"])
123 self.assertNotEqual(arp.hwsrc, smac)
124 self.assertTrue("00:00:5e:00:01" in arp.hwsrc or
125 "00:00:5E:00:01" in arp.hwsrc)
126 self.assertEqual(arp.hwdst, dmac)
127 self.assertEqual(arp.psrc, sip)
128 self.assertEqual(arp.pdst, dip)
129
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800130 def verify_ip(self, rx, smac, dmac, sip, dip):
131 ether = rx[Ether]
132 self.assertEqual(ether.dst, dmac)
133 self.assertEqual(ether.src, smac)
134
135 ip = rx[IP]
136 self.assertEqual(ip.src, sip)
137 self.assertEqual(ip.dst, dip)
138
Neale Ranns37be7362017-02-21 17:30:26 -0800139 def verify_ip_o_mpls(self, rx, smac, dmac, label, sip, dip):
140 ether = rx[Ether]
141 self.assertEqual(ether.dst, dmac)
142 self.assertEqual(ether.src, smac)
143
144 mpls = rx[MPLS]
145 self.assertTrue(mpls.label, label)
146
147 ip = rx[IP]
148 self.assertEqual(ip.src, sip)
149 self.assertEqual(ip.dst, dip)
150
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800151 def test_arp(self):
152 """ ARP """
153
154 #
155 # Generate some hosts on the LAN
156 #
Neale Rannsca193612017-06-14 06:50:08 -0700157 self.pg1.generate_remote_hosts(11)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800158
159 #
Neale Rannscbe25aa2019-09-30 10:53:31 +0000160 # watch for:
161 # - all neighbour events
162 # - all neighbor events on pg1
163 # - neighbor events for host[1] on pg1
164 #
165 self.vapi.want_ip_neighbor_events(enable=1,
166 pid=os.getpid())
167 self.vapi.want_ip_neighbor_events(enable=1,
168 pid=os.getpid(),
169 sw_if_index=self.pg1.sw_if_index)
170 self.vapi.want_ip_neighbor_events(enable=1,
171 pid=os.getpid(),
172 sw_if_index=self.pg1.sw_if_index,
173 ip=self.pg1.remote_hosts[1].ip4)
174
175 self.logger.info(self.vapi.cli("sh ip neighbor-watcher"))
176
177 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800178 # Send IP traffic to one of these unresolved hosts.
179 # expect the generation of an ARP request
180 #
181 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
182 IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[1].ip4) /
183 UDP(sport=1234, dport=1234) /
184 Raw())
185
186 self.pg0.add_stream(p)
187 self.pg_enable_capture(self.pg_interfaces)
188 self.pg_start()
189
190 rx = self.pg1.get_capture(1)
191
192 self.verify_arp_req(rx[0],
193 self.pg1.local_mac,
194 self.pg1.local_ip4,
195 self.pg1._remote_hosts[1].ip4)
196
197 #
198 # And a dynamic ARP entry for host 1
199 #
200 dyn_arp = VppNeighbor(self,
201 self.pg1.sw_if_index,
202 self.pg1.remote_hosts[1].mac,
203 self.pg1.remote_hosts[1].ip4)
204 dyn_arp.add_vpp_config()
Neale Rannscbe25aa2019-09-30 10:53:31 +0000205 self.assertTrue(dyn_arp.query_vpp_config())
206
Neale Rannsdc617b82020-08-20 08:22:56 +0000207 self.logger.info(self.vapi.cli("show ip neighbor-watcher"))
208
Neale Rannscbe25aa2019-09-30 10:53:31 +0000209 # this matches all of the listnerers
210 es = [self.vapi.wait_for_event(1, "ip_neighbor_event")
211 for i in range(3)]
212 for e in es:
213 self.assertEqual(str(e.neighbor.ip_address),
214 self.pg1.remote_hosts[1].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800215
216 #
217 # now we expect IP traffic forwarded
218 #
219 dyn_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
220 IP(src=self.pg0.remote_ip4,
221 dst=self.pg1._remote_hosts[1].ip4) /
222 UDP(sport=1234, dport=1234) /
223 Raw())
224
225 self.pg0.add_stream(dyn_p)
226 self.pg_enable_capture(self.pg_interfaces)
227 self.pg_start()
228
229 rx = self.pg1.get_capture(1)
230
231 self.verify_ip(rx[0],
232 self.pg1.local_mac,
233 self.pg1.remote_hosts[1].mac,
234 self.pg0.remote_ip4,
235 self.pg1._remote_hosts[1].ip4)
236
237 #
238 # And a Static ARP entry for host 2
239 #
240 static_arp = VppNeighbor(self,
241 self.pg1.sw_if_index,
242 self.pg1.remote_hosts[2].mac,
243 self.pg1.remote_hosts[2].ip4,
244 is_static=1)
245 static_arp.add_vpp_config()
Neale Rannscbe25aa2019-09-30 10:53:31 +0000246 es = [self.vapi.wait_for_event(1, "ip_neighbor_event")
247 for i in range(2)]
248 for e in es:
249 self.assertEqual(str(e.neighbor.ip_address),
250 self.pg1.remote_hosts[2].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800251
252 static_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
253 IP(src=self.pg0.remote_ip4,
254 dst=self.pg1._remote_hosts[2].ip4) /
255 UDP(sport=1234, dport=1234) /
256 Raw())
257
258 self.pg0.add_stream(static_p)
259 self.pg_enable_capture(self.pg_interfaces)
260 self.pg_start()
261
262 rx = self.pg1.get_capture(1)
263
264 self.verify_ip(rx[0],
265 self.pg1.local_mac,
266 self.pg1.remote_hosts[2].mac,
267 self.pg0.remote_ip4,
268 self.pg1._remote_hosts[2].ip4)
269
270 #
Neale Rannscbe25aa2019-09-30 10:53:31 +0000271 # remove all the listeners
272 #
273 self.vapi.want_ip_neighbor_events(enable=0,
274 pid=os.getpid())
275 self.vapi.want_ip_neighbor_events(enable=0,
276 pid=os.getpid(),
277 sw_if_index=self.pg1.sw_if_index)
278 self.vapi.want_ip_neighbor_events(enable=0,
279 pid=os.getpid(),
280 sw_if_index=self.pg1.sw_if_index,
281 ip=self.pg1.remote_hosts[1].ip4)
282
283 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800284 # flap the link. dynamic ARPs get flush, statics don't
285 #
286 self.pg1.admin_down()
287 self.pg1.admin_up()
288
289 self.pg0.add_stream(static_p)
290 self.pg_enable_capture(self.pg_interfaces)
291 self.pg_start()
292 rx = self.pg1.get_capture(1)
293
294 self.verify_ip(rx[0],
295 self.pg1.local_mac,
296 self.pg1.remote_hosts[2].mac,
297 self.pg0.remote_ip4,
298 self.pg1._remote_hosts[2].ip4)
299
300 self.pg0.add_stream(dyn_p)
301 self.pg_enable_capture(self.pg_interfaces)
302 self.pg_start()
303
304 rx = self.pg1.get_capture(1)
305 self.verify_arp_req(rx[0],
306 self.pg1.local_mac,
307 self.pg1.local_ip4,
308 self.pg1._remote_hosts[1].ip4)
309
Neale Rannscbe25aa2019-09-30 10:53:31 +0000310 self.assertFalse(dyn_arp.query_vpp_config())
311 self.assertTrue(static_arp.query_vpp_config())
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800312 #
313 # Send an ARP request from one of the so-far unlearned remote hosts
314 #
315 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
316 src=self.pg1._remote_hosts[3].mac) /
317 ARP(op="who-has",
318 hwsrc=self.pg1._remote_hosts[3].mac,
319 pdst=self.pg1.local_ip4,
320 psrc=self.pg1._remote_hosts[3].ip4))
321
322 self.pg1.add_stream(p)
323 self.pg_enable_capture(self.pg_interfaces)
324 self.pg_start()
325
326 rx = self.pg1.get_capture(1)
327 self.verify_arp_resp(rx[0],
328 self.pg1.local_mac,
329 self.pg1._remote_hosts[3].mac,
330 self.pg1.local_ip4,
331 self.pg1._remote_hosts[3].ip4)
332
333 #
334 # VPP should have learned the mapping for the remote host
335 #
336 self.assertTrue(find_nbr(self,
337 self.pg1.sw_if_index,
338 self.pg1._remote_hosts[3].ip4))
Neale Ranns4b919a52017-03-11 05:55:21 -0800339 #
340 # Fire in an ARP request before the interface becomes IP enabled
341 #
342 self.pg2.generate_remote_hosts(4)
343
344 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
345 ARP(op="who-has",
346 hwsrc=self.pg2.remote_mac,
347 pdst=self.pg1.local_ip4,
348 psrc=self.pg2.remote_hosts[3].ip4))
Neale Ranns30d0fd42017-05-30 07:30:04 -0700349 pt = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
350 Dot1Q(vlan=0) /
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 Ranns4b919a52017-03-11 05:55:21 -0800355 self.send_and_assert_no_replies(self.pg2, p,
356 "interface not IP enabled")
357
358 #
359 # Make pg2 un-numbered to pg1
360 #
361 self.pg2.set_unnumbered(self.pg1.sw_if_index)
362
Neale Rannsac3e72c2019-10-06 01:04:26 -0700363 #
364 # test the unnumbered dump both by all interfaces and just the enabled
365 # one
366 #
Neale Ranns404d88e2018-08-08 06:37:33 -0700367 unnum = self.vapi.ip_unnumbered_dump()
Neale Rannsac3e72c2019-10-06 01:04:26 -0700368 self.assertTrue(len(unnum))
369 self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
370 self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)
371 unnum = self.vapi.ip_unnumbered_dump(self.pg2.sw_if_index)
372 self.assertTrue(len(unnum))
Neale Ranns404d88e2018-08-08 06:37:33 -0700373 self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
374 self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)
375
Neale Ranns4b919a52017-03-11 05:55:21 -0800376 #
377 # We should respond to ARP requests for the unnumbered to address
378 # once an attached route to the source is known
379 #
380 self.send_and_assert_no_replies(
381 self.pg2, p,
382 "ARP req for unnumbered address - no source")
383
384 attached_host = VppIpRoute(self, self.pg2.remote_hosts[3].ip4, 32,
385 [VppRoutePath("0.0.0.0",
386 self.pg2.sw_if_index)])
387 attached_host.add_vpp_config()
388
389 self.pg2.add_stream(p)
390 self.pg_enable_capture(self.pg_interfaces)
391 self.pg_start()
392
393 rx = self.pg2.get_capture(1)
394 self.verify_arp_resp(rx[0],
395 self.pg2.local_mac,
396 self.pg2.remote_mac,
397 self.pg1.local_ip4,
398 self.pg2.remote_hosts[3].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800399
Neale Ranns30d0fd42017-05-30 07:30:04 -0700400 self.pg2.add_stream(pt)
401 self.pg_enable_capture(self.pg_interfaces)
402 self.pg_start()
403
404 rx = self.pg2.get_capture(1)
405 self.verify_arp_resp(rx[0],
406 self.pg2.local_mac,
407 self.pg2.remote_mac,
408 self.pg1.local_ip4,
409 self.pg2.remote_hosts[3].ip4)
410
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800411 #
Neale Ranns3983ac22017-03-10 11:53:27 -0800412 # A neighbor entry that has no associated FIB-entry
413 #
414 arp_no_fib = VppNeighbor(self,
415 self.pg1.sw_if_index,
416 self.pg1.remote_hosts[4].mac,
417 self.pg1.remote_hosts[4].ip4,
418 is_no_fib_entry=1)
419 arp_no_fib.add_vpp_config()
420
421 #
422 # check we have the neighbor, but no route
423 #
424 self.assertTrue(find_nbr(self,
425 self.pg1.sw_if_index,
426 self.pg1._remote_hosts[4].ip4))
427 self.assertFalse(find_route(self,
428 self.pg1._remote_hosts[4].ip4,
429 32))
430 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800431 # pg2 is unnumbered to pg1, so we can form adjacencies out of pg2
432 # from within pg1's subnet
Neale Ranns3983ac22017-03-10 11:53:27 -0800433 #
434 arp_unnum = VppNeighbor(self,
435 self.pg2.sw_if_index,
436 self.pg1.remote_hosts[5].mac,
437 self.pg1.remote_hosts[5].ip4)
438 arp_unnum.add_vpp_config()
439
440 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
441 IP(src=self.pg0.remote_ip4,
442 dst=self.pg1._remote_hosts[5].ip4) /
443 UDP(sport=1234, dport=1234) /
444 Raw())
445
446 self.pg0.add_stream(p)
447 self.pg_enable_capture(self.pg_interfaces)
448 self.pg_start()
449
450 rx = self.pg2.get_capture(1)
451
452 self.verify_ip(rx[0],
453 self.pg2.local_mac,
454 self.pg1.remote_hosts[5].mac,
455 self.pg0.remote_ip4,
456 self.pg1._remote_hosts[5].ip4)
457
458 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800459 # ARP requests from hosts in pg1's subnet sent on pg2 are replied to
460 # with the unnumbered interface's address as the source
461 #
462 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
463 ARP(op="who-has",
464 hwsrc=self.pg2.remote_mac,
465 pdst=self.pg1.local_ip4,
466 psrc=self.pg1.remote_hosts[6].ip4))
467
468 self.pg2.add_stream(p)
469 self.pg_enable_capture(self.pg_interfaces)
470 self.pg_start()
471
472 rx = self.pg2.get_capture(1)
473 self.verify_arp_resp(rx[0],
474 self.pg2.local_mac,
475 self.pg2.remote_mac,
476 self.pg1.local_ip4,
477 self.pg1.remote_hosts[6].ip4)
478
479 #
480 # An attached host route out of pg2 for an undiscovered hosts generates
481 # an ARP request with the unnumbered address as the source
482 #
483 att_unnum = VppIpRoute(self, self.pg1.remote_hosts[7].ip4, 32,
484 [VppRoutePath("0.0.0.0",
485 self.pg2.sw_if_index)])
486 att_unnum.add_vpp_config()
487
488 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
489 IP(src=self.pg0.remote_ip4,
490 dst=self.pg1._remote_hosts[7].ip4) /
491 UDP(sport=1234, dport=1234) /
492 Raw())
493
494 self.pg0.add_stream(p)
495 self.pg_enable_capture(self.pg_interfaces)
496 self.pg_start()
497
498 rx = self.pg2.get_capture(1)
499
500 self.verify_arp_req(rx[0],
501 self.pg2.local_mac,
502 self.pg1.local_ip4,
503 self.pg1._remote_hosts[7].ip4)
504
505 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
506 ARP(op="who-has",
507 hwsrc=self.pg2.remote_mac,
508 pdst=self.pg1.local_ip4,
509 psrc=self.pg1.remote_hosts[7].ip4))
510
511 self.pg2.add_stream(p)
512 self.pg_enable_capture(self.pg_interfaces)
513 self.pg_start()
514
515 rx = self.pg2.get_capture(1)
516 self.verify_arp_resp(rx[0],
517 self.pg2.local_mac,
518 self.pg2.remote_mac,
519 self.pg1.local_ip4,
520 self.pg1.remote_hosts[7].ip4)
521
522 #
523 # An attached host route as yet unresolved out of pg2 for an
524 # undiscovered host, an ARP requests begets a response.
525 #
526 att_unnum1 = VppIpRoute(self, self.pg1.remote_hosts[8].ip4, 32,
527 [VppRoutePath("0.0.0.0",
528 self.pg2.sw_if_index)])
529 att_unnum1.add_vpp_config()
530
531 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
532 ARP(op="who-has",
533 hwsrc=self.pg2.remote_mac,
534 pdst=self.pg1.local_ip4,
535 psrc=self.pg1.remote_hosts[8].ip4))
536
537 self.pg2.add_stream(p)
538 self.pg_enable_capture(self.pg_interfaces)
539 self.pg_start()
540
541 rx = self.pg2.get_capture(1)
542 self.verify_arp_resp(rx[0],
543 self.pg2.local_mac,
544 self.pg2.remote_mac,
545 self.pg1.local_ip4,
546 self.pg1.remote_hosts[8].ip4)
547
548 #
Neale Ranns30d0fd42017-05-30 07:30:04 -0700549 # Send an ARP request from one of the so-far unlearned remote hosts
550 # with a VLAN0 tag
551 #
552 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
553 src=self.pg1._remote_hosts[9].mac) /
554 Dot1Q(vlan=0) /
555 ARP(op="who-has",
556 hwsrc=self.pg1._remote_hosts[9].mac,
557 pdst=self.pg1.local_ip4,
558 psrc=self.pg1._remote_hosts[9].ip4))
559
560 self.pg1.add_stream(p)
561 self.pg_enable_capture(self.pg_interfaces)
562 self.pg_start()
563
564 rx = self.pg1.get_capture(1)
565 self.verify_arp_resp(rx[0],
566 self.pg1.local_mac,
567 self.pg1._remote_hosts[9].mac,
568 self.pg1.local_ip4,
569 self.pg1._remote_hosts[9].ip4)
570
571 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700572 # Add a hierarchy of routes for a host in the sub-net.
Neale Rannsca193612017-06-14 06:50:08 -0700573 # Should still get an ARP resp since the cover is attached
574 #
575 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_mac) /
576 ARP(op="who-has",
577 hwsrc=self.pg1.remote_mac,
578 pdst=self.pg1.local_ip4,
579 psrc=self.pg1.remote_hosts[10].ip4))
580
581 r1 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 30,
582 [VppRoutePath(self.pg1.remote_hosts[10].ip4,
583 self.pg1.sw_if_index)])
584 r1.add_vpp_config()
585
586 self.pg1.add_stream(p)
587 self.pg_enable_capture(self.pg_interfaces)
588 self.pg_start()
589 rx = self.pg1.get_capture(1)
590 self.verify_arp_resp(rx[0],
591 self.pg1.local_mac,
592 self.pg1.remote_mac,
593 self.pg1.local_ip4,
594 self.pg1.remote_hosts[10].ip4)
595
596 r2 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 32,
597 [VppRoutePath(self.pg1.remote_hosts[10].ip4,
598 self.pg1.sw_if_index)])
599 r2.add_vpp_config()
600
601 self.pg1.add_stream(p)
602 self.pg_enable_capture(self.pg_interfaces)
603 self.pg_start()
604 rx = self.pg1.get_capture(1)
605 self.verify_arp_resp(rx[0],
606 self.pg1.local_mac,
607 self.pg1.remote_mac,
608 self.pg1.local_ip4,
609 self.pg1.remote_hosts[10].ip4)
610
611 #
612 # add an ARP entry that's not on the sub-net and so whose
613 # adj-fib fails the refinement check. then send an ARP request
614 # from that source
615 #
616 a1 = VppNeighbor(self,
617 self.pg0.sw_if_index,
618 self.pg0.remote_mac,
619 "100.100.100.50")
620 a1.add_vpp_config()
621
622 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
623 ARP(op="who-has",
624 hwsrc=self.pg0.remote_mac,
625 psrc="100.100.100.50",
626 pdst=self.pg0.remote_ip4))
627 self.send_and_assert_no_replies(self.pg0, p,
628 "ARP req for from failed adj-fib")
629
630 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800631 # ERROR Cases
632 # 1 - don't respond to ARP request for address not within the
633 # interface's sub-net
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700634 # 1b - nor within the unnumbered subnet
635 # 1c - nor within the subnet of a different interface
636 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800637 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
638 ARP(op="who-has",
639 hwsrc=self.pg0.remote_mac,
640 pdst="10.10.10.3",
641 psrc=self.pg0.remote_ip4))
642 self.send_and_assert_no_replies(self.pg0, p,
643 "ARP req for non-local destination")
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700644 self.assertFalse(find_nbr(self,
645 self.pg0.sw_if_index,
646 "10.10.10.3"))
647
Neale Ranns4b919a52017-03-11 05:55:21 -0800648 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
649 ARP(op="who-has",
650 hwsrc=self.pg2.remote_mac,
651 pdst="10.10.10.3",
652 psrc=self.pg1.remote_hosts[7].ip4))
653 self.send_and_assert_no_replies(
654 self.pg0, p,
655 "ARP req for non-local destination - unnum")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800656
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700657 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
658 ARP(op="who-has",
659 hwsrc=self.pg0.remote_mac,
660 pdst=self.pg1.local_ip4,
661 psrc=self.pg1.remote_ip4))
662 self.send_and_assert_no_replies(self.pg0, p,
663 "ARP req diff sub-net")
664 self.assertFalse(find_nbr(self,
665 self.pg0.sw_if_index,
666 self.pg1.remote_ip4))
667
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800668 #
669 # 2 - don't respond to ARP request from an address not within the
670 # interface's sub-net
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700671 # 2b - to a proxied address
672 # 2c - not within a different interface's sub-net
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800673 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
674 ARP(op="who-has",
675 hwsrc=self.pg0.remote_mac,
676 psrc="10.10.10.3",
677 pdst=self.pg0.local_ip4))
678 self.send_and_assert_no_replies(self.pg0, p,
679 "ARP req for non-local source")
Neale Ranns4b919a52017-03-11 05:55:21 -0800680 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
681 ARP(op="who-has",
682 hwsrc=self.pg2.remote_mac,
683 psrc="10.10.10.3",
684 pdst=self.pg0.local_ip4))
685 self.send_and_assert_no_replies(
686 self.pg0, p,
687 "ARP req for non-local source - unnum")
Neale Rannsca193612017-06-14 06:50:08 -0700688 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
689 ARP(op="who-has",
690 hwsrc=self.pg0.remote_mac,
691 psrc=self.pg1.remote_ip4,
692 pdst=self.pg0.local_ip4))
693 self.send_and_assert_no_replies(self.pg0, p,
694 "ARP req for non-local source 2c")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800695
696 #
697 # 3 - don't respond to ARP request from an address that belongs to
698 # the router
699 #
700 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
701 ARP(op="who-has",
702 hwsrc=self.pg0.remote_mac,
703 psrc=self.pg0.local_ip4,
704 pdst=self.pg0.local_ip4))
705 self.send_and_assert_no_replies(self.pg0, p,
706 "ARP req for non-local source")
707
708 #
709 # 4 - don't respond to ARP requests that has mac source different
710 # from ARP request HW source
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800711 #
712 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
713 ARP(op="who-has",
714 hwsrc="00:00:00:DE:AD:BE",
715 psrc=self.pg0.remote_ip4,
716 pdst=self.pg0.local_ip4))
717 self.send_and_assert_no_replies(self.pg0, p,
718 "ARP req for non-local source")
719
720 #
zhaoqinglingb4c42cd2017-12-23 15:20:59 +0800721 # 5 - don't respond to ARP requests for address within the
722 # interface's sub-net but not the interface's address
723 #
724 self.pg0.generate_remote_hosts(2)
725 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
726 ARP(op="who-has",
727 hwsrc=self.pg0.remote_mac,
728 psrc=self.pg0.remote_hosts[0].ip4,
729 pdst=self.pg0.remote_hosts[1].ip4))
730 self.send_and_assert_no_replies(self.pg0, p,
731 "ARP req for non-local destination")
732
733 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800734 # cleanup
735 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800736 static_arp.remove_vpp_config()
Neale Ranns3983ac22017-03-10 11:53:27 -0800737 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800738
Neale Ranns4b919a52017-03-11 05:55:21 -0800739 # need this to flush the adj-fibs
740 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
741 self.pg2.admin_down()
Neale Rannsca193612017-06-14 06:50:08 -0700742 self.pg1.admin_down()
Neale Ranns4b919a52017-03-11 05:55:21 -0800743
Neale Ranns24b170a2017-08-15 05:33:11 -0700744 def test_proxy_mirror_arp(self):
745 """ Interface Mirror Proxy ARP """
746
747 #
748 # When VPP has an interface whose address is also applied to a TAP
749 # interface on the host, then VPP's TAP interface will be unnumbered
750 # to the 'real' interface and do proxy ARP from the host.
751 # the curious aspect of this setup is that ARP requests from the host
752 # will come from the VPP's own address.
753 #
754 self.pg0.generate_remote_hosts(2)
755
756 arp_req_from_me = (Ether(src=self.pg2.remote_mac,
757 dst="ff:ff:ff:ff:ff:ff") /
758 ARP(op="who-has",
759 hwsrc=self.pg2.remote_mac,
760 pdst=self.pg0.remote_hosts[1].ip4,
761 psrc=self.pg0.local_ip4))
762
763 #
764 # Configure Proxy ARP for the subnet on PG0addresses on pg0
765 #
Neale Ranns37029302018-08-10 05:30:06 -0700766 self.vapi.proxy_arp_add_del(self.pg0._local_ip4_subnet,
767 self.pg0._local_ip4_bcast)
Neale Ranns24b170a2017-08-15 05:33:11 -0700768
769 # Make pg2 un-numbered to pg0
770 #
771 self.pg2.set_unnumbered(self.pg0.sw_if_index)
772
773 #
774 # Enable pg2 for proxy ARP
775 #
776 self.pg2.set_proxy_arp()
777
778 #
779 # Send the ARP request with an originating address that
780 # is VPP's own address
781 #
Neale Ranns240dcb22020-04-23 09:04:59 +0000782 rx = self.send_and_expect(self.pg2, [arp_req_from_me], self.pg2)
Neale Ranns24b170a2017-08-15 05:33:11 -0700783 self.verify_arp_resp(rx[0],
784 self.pg2.local_mac,
785 self.pg2.remote_mac,
786 self.pg0.remote_hosts[1].ip4,
787 self.pg0.local_ip4)
788
789 #
790 # validate we have not learned an ARP entry as a result of this
791 #
792 self.assertFalse(find_nbr(self,
793 self.pg2.sw_if_index,
794 self.pg0.local_ip4))
795
796 #
Neale Ranns240dcb22020-04-23 09:04:59 +0000797 # setup a punt redirect so packets from the uplink go to the tap
798 #
799 self.vapi.ip_punt_redirect(self.pg0.sw_if_index,
800 self.pg2.sw_if_index,
801 self.pg0.local_ip4)
802
803 p_tcp = (Ether(src=self.pg0.remote_mac,
804 dst=self.pg0.local_mac,) /
805 IP(src=self.pg0.remote_ip4,
806 dst=self.pg0.local_ip4) /
807 TCP(sport=80, dport=80) /
808 Raw())
809 rx = self.send_and_expect(self.pg0, [p_tcp], self.pg2)
810
811 # there's no ARP entry so this is an ARP req
812 self.assertTrue(rx[0].haslayer(ARP))
813
814 # and ARP entry for VPP's pg0 address on the host interface
815 n1 = VppNeighbor(self,
816 self.pg2.sw_if_index,
817 self.pg2.remote_mac,
818 self.pg0.local_ip4,
819 is_no_fib_entry=True).add_vpp_config()
820 # now the packets shold forward
821 rx = self.send_and_expect(self.pg0, [p_tcp], self.pg2)
822 self.assertFalse(rx[0].haslayer(ARP))
823 self.assertEqual(rx[0][Ether].dst, self.pg2.remote_mac)
824
825 #
826 # flush the neighbor cache on the uplink
827 #
828 af = VppEnum.vl_api_address_family_t
829 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, self.pg0.sw_if_index)
830
831 # ensure we can still resolve the ARPs on the uplink
832 self.pg0.resolve_arp()
833
834 self.assertTrue(find_nbr(self,
835 self.pg0.sw_if_index,
836 self.pg0.remote_ip4))
837
838 #
Neale Ranns24b170a2017-08-15 05:33:11 -0700839 # cleanup
840 #
841 self.pg2.set_proxy_arp(0)
Neale Ranns37029302018-08-10 05:30:06 -0700842 self.vapi.proxy_arp_add_del(self.pg0._local_ip4_subnet,
843 self.pg0._local_ip4_bcast,
Neale Ranns24b170a2017-08-15 05:33:11 -0700844 is_add=0)
845
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800846 def test_proxy_arp(self):
847 """ Proxy ARP """
848
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700849 self.pg1.generate_remote_hosts(2)
850
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800851 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700852 # Proxy ARP request packets for each interface
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800853 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800854 arp_req_pg0 = (Ether(src=self.pg0.remote_mac,
855 dst="ff:ff:ff:ff:ff:ff") /
856 ARP(op="who-has",
857 hwsrc=self.pg0.remote_mac,
858 pdst="10.10.10.3",
859 psrc=self.pg0.remote_ip4))
Neale Ranns30d0fd42017-05-30 07:30:04 -0700860 arp_req_pg0_tagged = (Ether(src=self.pg0.remote_mac,
861 dst="ff:ff:ff:ff:ff:ff") /
862 Dot1Q(vlan=0) /
863 ARP(op="who-has",
864 hwsrc=self.pg0.remote_mac,
865 pdst="10.10.10.3",
866 psrc=self.pg0.remote_ip4))
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800867 arp_req_pg1 = (Ether(src=self.pg1.remote_mac,
868 dst="ff:ff:ff:ff:ff:ff") /
869 ARP(op="who-has",
870 hwsrc=self.pg1.remote_mac,
871 pdst="10.10.10.3",
872 psrc=self.pg1.remote_ip4))
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700873 arp_req_pg2 = (Ether(src=self.pg2.remote_mac,
874 dst="ff:ff:ff:ff:ff:ff") /
875 ARP(op="who-has",
876 hwsrc=self.pg2.remote_mac,
877 pdst="10.10.10.3",
878 psrc=self.pg1.remote_hosts[1].ip4))
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800879 arp_req_pg3 = (Ether(src=self.pg3.remote_mac,
880 dst="ff:ff:ff:ff:ff:ff") /
881 ARP(op="who-has",
882 hwsrc=self.pg3.remote_mac,
883 pdst="10.10.10.3",
884 psrc=self.pg3.remote_ip4))
885
886 #
887 # Configure Proxy ARP for 10.10.10.0 -> 10.10.10.124
888 #
889 self.vapi.proxy_arp_add_del(inet_pton(AF_INET, "10.10.10.2"),
890 inet_pton(AF_INET, "10.10.10.124"))
891
892 #
893 # No responses are sent when the interfaces are not enabled for proxy
894 # ARP
895 #
896 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
897 "ARP req from unconfigured interface")
898 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
899 "ARP req from unconfigured interface")
900
901 #
902 # Make pg2 un-numbered to pg1
903 # still won't reply.
904 #
905 self.pg2.set_unnumbered(self.pg1.sw_if_index)
906
907 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
908 "ARP req from unnumbered interface")
909
910 #
911 # Enable each interface to reply to proxy ARPs
912 #
913 for i in self.pg_interfaces:
914 i.set_proxy_arp()
915
916 #
917 # Now each of the interfaces should reply to a request to a proxied
918 # address
919 #
920 self.pg0.add_stream(arp_req_pg0)
921 self.pg_enable_capture(self.pg_interfaces)
922 self.pg_start()
923
924 rx = self.pg0.get_capture(1)
925 self.verify_arp_resp(rx[0],
926 self.pg0.local_mac,
927 self.pg0.remote_mac,
928 "10.10.10.3",
929 self.pg0.remote_ip4)
930
Neale Ranns30d0fd42017-05-30 07:30:04 -0700931 self.pg0.add_stream(arp_req_pg0_tagged)
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 Ranns39f9d8b2017-02-16 21:57:05 -0800942 self.pg1.add_stream(arp_req_pg1)
943 self.pg_enable_capture(self.pg_interfaces)
944 self.pg_start()
945
946 rx = self.pg1.get_capture(1)
947 self.verify_arp_resp(rx[0],
948 self.pg1.local_mac,
949 self.pg1.remote_mac,
950 "10.10.10.3",
951 self.pg1.remote_ip4)
952
953 self.pg2.add_stream(arp_req_pg2)
954 self.pg_enable_capture(self.pg_interfaces)
955 self.pg_start()
956
957 rx = self.pg2.get_capture(1)
958 self.verify_arp_resp(rx[0],
959 self.pg2.local_mac,
960 self.pg2.remote_mac,
961 "10.10.10.3",
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700962 self.pg1.remote_hosts[1].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800963
964 #
965 # A request for an address out of the configured range
966 #
967 arp_req_pg1_hi = (Ether(src=self.pg1.remote_mac,
968 dst="ff:ff:ff:ff:ff:ff") /
969 ARP(op="who-has",
970 hwsrc=self.pg1.remote_mac,
971 pdst="10.10.10.125",
972 psrc=self.pg1.remote_ip4))
973 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_hi,
974 "ARP req out of range HI")
975 arp_req_pg1_low = (Ether(src=self.pg1.remote_mac,
976 dst="ff:ff:ff:ff:ff:ff") /
977 ARP(op="who-has",
978 hwsrc=self.pg1.remote_mac,
979 pdst="10.10.10.1",
980 psrc=self.pg1.remote_ip4))
981 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_low,
982 "ARP req out of range Low")
983
984 #
985 # Request for an address in the proxy range but from an interface
986 # in a different VRF
987 #
988 self.send_and_assert_no_replies(self.pg3, arp_req_pg3,
989 "ARP req from different VRF")
990
991 #
992 # Disable Each interface for proxy ARP
993 # - expect none to respond
994 #
995 for i in self.pg_interfaces:
996 i.set_proxy_arp(0)
997
998 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
999 "ARP req from disable")
1000 self.send_and_assert_no_replies(self.pg1, arp_req_pg1,
1001 "ARP req from disable")
1002 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
1003 "ARP req from disable")
Neale Ranns37be7362017-02-21 17:30:26 -08001004
1005 #
1006 # clean up on interface 2
1007 #
Neale Ranns4b919a52017-03-11 05:55:21 -08001008 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns37be7362017-02-21 17:30:26 -08001009
1010 def test_mpls(self):
1011 """ MPLS """
1012
1013 #
1014 # Interface 2 does not yet have ip4 config
1015 #
1016 self.pg2.config_ip4()
1017 self.pg2.generate_remote_hosts(2)
1018
1019 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001020 # Add a route with out going label via an ARP unresolved next-hop
Neale Ranns37be7362017-02-21 17:30:26 -08001021 #
1022 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1023 [VppRoutePath(self.pg2.remote_hosts[1].ip4,
1024 self.pg2.sw_if_index,
1025 labels=[55])])
1026 ip_10_0_0_1.add_vpp_config()
1027
1028 #
1029 # packets should generate an ARP request
1030 #
1031 p = (Ether(src=self.pg0.remote_mac,
1032 dst=self.pg0.local_mac) /
1033 IP(src=self.pg0.remote_ip4, dst="10.0.0.1") /
1034 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01001035 Raw(b'\xa5' * 100))
Neale Ranns37be7362017-02-21 17:30:26 -08001036
1037 self.pg0.add_stream(p)
1038 self.pg_enable_capture(self.pg_interfaces)
1039 self.pg_start()
1040
1041 rx = self.pg2.get_capture(1)
1042 self.verify_arp_req(rx[0],
1043 self.pg2.local_mac,
1044 self.pg2.local_ip4,
1045 self.pg2._remote_hosts[1].ip4)
1046
1047 #
1048 # now resolve the neighbours
1049 #
1050 self.pg2.configure_ipv4_neighbors()
1051
1052 #
1053 # Now packet should be properly MPLS encapped.
1054 # This verifies that MPLS link-type adjacencies are completed
1055 # when the ARP entry resolves
1056 #
1057 self.pg0.add_stream(p)
1058 self.pg_enable_capture(self.pg_interfaces)
1059 self.pg_start()
1060
1061 rx = self.pg2.get_capture(1)
1062 self.verify_ip_o_mpls(rx[0],
1063 self.pg2.local_mac,
1064 self.pg2.remote_hosts[1].mac,
1065 55,
1066 self.pg0.remote_ip4,
1067 "10.0.0.1")
Neale Ranns4b919a52017-03-11 05:55:21 -08001068 self.pg2.unconfig_ip4()
Neale Ranns37be7362017-02-21 17:30:26 -08001069
Matthew Smithcb9ab472017-05-16 21:35:56 -05001070 def test_arp_vrrp(self):
1071 """ ARP reply with VRRP virtual src hw addr """
1072
1073 #
1074 # IP packet destined for pg1 remote host arrives on pg0 resulting
1075 # in an ARP request for the address of the remote host on pg1
1076 #
1077 p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1078 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1079 UDP(sport=1234, dport=1234) /
1080 Raw())
1081
Neale Ranns37029302018-08-10 05:30:06 -07001082 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
Matthew Smithcb9ab472017-05-16 21:35:56 -05001083
1084 self.verify_arp_req(rx1[0],
1085 self.pg1.local_mac,
1086 self.pg1.local_ip4,
1087 self.pg1.remote_ip4)
1088
1089 #
1090 # ARP reply for address of pg1 remote host arrives on pg1 with
1091 # the hw src addr set to a value in the VRRP IPv4 range of
1092 # MAC addresses
1093 #
1094 p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1095 ARP(op="is-at", hwdst=self.pg1.local_mac,
1096 hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
1097 psrc=self.pg1.remote_ip4))
1098
Neale Ranns37029302018-08-10 05:30:06 -07001099 self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
Matthew Smithcb9ab472017-05-16 21:35:56 -05001100
1101 #
1102 # IP packet destined for pg1 remote host arrives on pg0 again.
1103 # VPP should have an ARP entry for that address now and the packet
1104 # should be sent out pg1.
1105 #
Neale Ranns37029302018-08-10 05:30:06 -07001106 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
Matthew Smithcb9ab472017-05-16 21:35:56 -05001107
1108 self.verify_ip(rx1[0],
1109 self.pg1.local_mac,
1110 "00:00:5e:00:01:09",
1111 self.pg0.remote_ip4,
1112 self.pg1.remote_ip4)
1113
1114 self.pg1.admin_down()
1115 self.pg1.admin_up()
1116
Neale Rannsdcd6d622017-05-26 02:59:16 -07001117 def test_arp_duplicates(self):
1118 """ ARP Duplicates"""
1119
1120 #
1121 # Generate some hosts on the LAN
1122 #
1123 self.pg1.generate_remote_hosts(3)
1124
1125 #
1126 # Add host 1 on pg1 and pg2
1127 #
1128 arp_pg1 = VppNeighbor(self,
1129 self.pg1.sw_if_index,
1130 self.pg1.remote_hosts[1].mac,
1131 self.pg1.remote_hosts[1].ip4)
1132 arp_pg1.add_vpp_config()
1133 arp_pg2 = VppNeighbor(self,
1134 self.pg2.sw_if_index,
1135 self.pg2.remote_mac,
1136 self.pg1.remote_hosts[1].ip4)
1137 arp_pg2.add_vpp_config()
1138
1139 #
1140 # IP packet destined for pg1 remote host arrives on pg1 again.
1141 #
1142 p = (Ether(dst=self.pg0.local_mac,
1143 src=self.pg0.remote_mac) /
1144 IP(src=self.pg0.remote_ip4,
1145 dst=self.pg1.remote_hosts[1].ip4) /
1146 UDP(sport=1234, dport=1234) /
1147 Raw())
1148
1149 self.pg0.add_stream(p)
1150 self.pg_enable_capture(self.pg_interfaces)
1151 self.pg_start()
1152
1153 rx1 = self.pg1.get_capture(1)
1154
1155 self.verify_ip(rx1[0],
1156 self.pg1.local_mac,
1157 self.pg1.remote_hosts[1].mac,
1158 self.pg0.remote_ip4,
1159 self.pg1.remote_hosts[1].ip4)
1160
1161 #
1162 # remove the duplicate on pg1
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001163 # packet stream should generate ARPs out of pg1
Neale Rannsdcd6d622017-05-26 02:59:16 -07001164 #
1165 arp_pg1.remove_vpp_config()
1166
1167 self.pg0.add_stream(p)
1168 self.pg_enable_capture(self.pg_interfaces)
1169 self.pg_start()
1170
1171 rx1 = self.pg1.get_capture(1)
1172
1173 self.verify_arp_req(rx1[0],
1174 self.pg1.local_mac,
1175 self.pg1.local_ip4,
1176 self.pg1.remote_hosts[1].ip4)
1177
1178 #
1179 # Add it back
1180 #
1181 arp_pg1.add_vpp_config()
1182
1183 self.pg0.add_stream(p)
1184 self.pg_enable_capture(self.pg_interfaces)
1185 self.pg_start()
1186
1187 rx1 = self.pg1.get_capture(1)
1188
1189 self.verify_ip(rx1[0],
1190 self.pg1.local_mac,
1191 self.pg1.remote_hosts[1].mac,
1192 self.pg0.remote_ip4,
1193 self.pg1.remote_hosts[1].ip4)
1194
Neale Ranns15002542017-09-10 04:39:11 -07001195 def test_arp_static(self):
1196 """ ARP Static"""
1197 self.pg2.generate_remote_hosts(3)
1198
1199 #
1200 # Add a static ARP entry
1201 #
1202 static_arp = VppNeighbor(self,
1203 self.pg2.sw_if_index,
1204 self.pg2.remote_hosts[1].mac,
1205 self.pg2.remote_hosts[1].ip4,
1206 is_static=1)
1207 static_arp.add_vpp_config()
1208
1209 #
1210 # Add the connected prefix to the interface
1211 #
1212 self.pg2.config_ip4()
1213
1214 #
1215 # We should now find the adj-fib
1216 #
1217 self.assertTrue(find_nbr(self,
1218 self.pg2.sw_if_index,
1219 self.pg2.remote_hosts[1].ip4,
1220 is_static=1))
1221 self.assertTrue(find_route(self,
1222 self.pg2.remote_hosts[1].ip4,
1223 32))
1224
1225 #
1226 # remove the connected
1227 #
1228 self.pg2.unconfig_ip4()
1229
1230 #
1231 # put the interface into table 1
1232 #
1233 self.pg2.set_table_ip4(1)
1234
1235 #
1236 # configure the same connected and expect to find the
1237 # adj fib in the new table
1238 #
1239 self.pg2.config_ip4()
1240 self.assertTrue(find_route(self,
1241 self.pg2.remote_hosts[1].ip4,
1242 32,
1243 table_id=1))
1244
1245 #
1246 # clean-up
1247 #
1248 self.pg2.unconfig_ip4()
Neale Rannscbe25aa2019-09-30 10:53:31 +00001249 static_arp.remove_vpp_config()
Neale Ranns15002542017-09-10 04:39:11 -07001250 self.pg2.set_table_ip4(0)
1251
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001252 def test_arp_static_replace_dynamic_same_mac(self):
1253 """ ARP Static can replace Dynamic (same mac) """
1254 self.pg2.generate_remote_hosts(1)
1255
1256 dyn_arp = VppNeighbor(self,
1257 self.pg2.sw_if_index,
1258 self.pg2.remote_hosts[0].mac,
1259 self.pg2.remote_hosts[0].ip4)
1260 static_arp = VppNeighbor(self,
1261 self.pg2.sw_if_index,
1262 self.pg2.remote_hosts[0].mac,
1263 self.pg2.remote_hosts[0].ip4,
1264 is_static=1)
1265
1266 #
1267 # Add a dynamic ARP entry
1268 #
1269 dyn_arp.add_vpp_config()
1270
1271 #
1272 # We should find the dynamic nbr
1273 #
1274 self.assertFalse(find_nbr(self,
1275 self.pg2.sw_if_index,
1276 self.pg2.remote_hosts[0].ip4,
1277 is_static=1))
1278 self.assertTrue(find_nbr(self,
1279 self.pg2.sw_if_index,
1280 self.pg2.remote_hosts[0].ip4,
1281 is_static=0,
1282 mac=self.pg2.remote_hosts[0].mac))
1283
1284 #
1285 # Add a static ARP entry with the same mac
1286 #
1287 static_arp.add_vpp_config()
1288
1289 #
1290 # We should now find the static nbr with the same mac
1291 #
1292 self.assertFalse(find_nbr(self,
1293 self.pg2.sw_if_index,
1294 self.pg2.remote_hosts[0].ip4,
1295 is_static=0))
1296 self.assertTrue(find_nbr(self,
1297 self.pg2.sw_if_index,
1298 self.pg2.remote_hosts[0].ip4,
1299 is_static=1,
1300 mac=self.pg2.remote_hosts[0].mac))
1301
1302 #
1303 # clean-up
1304 #
1305 static_arp.remove_vpp_config()
1306
1307 def test_arp_static_replace_dynamic_diff_mac(self):
1308 """ ARP Static can replace Dynamic (diff mac) """
1309 self.pg2.generate_remote_hosts(2)
1310
1311 dyn_arp = VppNeighbor(self,
1312 self.pg2.sw_if_index,
1313 self.pg2.remote_hosts[0].mac,
1314 self.pg2.remote_hosts[0].ip4)
1315 static_arp = VppNeighbor(self,
1316 self.pg2.sw_if_index,
1317 self.pg2.remote_hosts[1].mac,
1318 self.pg2.remote_hosts[0].ip4,
1319 is_static=1)
1320
1321 #
1322 # Add a dynamic ARP entry
1323 #
1324 dyn_arp.add_vpp_config()
1325
1326 #
1327 # We should find the dynamic nbr
1328 #
1329 self.assertFalse(find_nbr(self,
1330 self.pg2.sw_if_index,
1331 self.pg2.remote_hosts[0].ip4,
1332 is_static=1))
1333 self.assertTrue(find_nbr(self,
1334 self.pg2.sw_if_index,
1335 self.pg2.remote_hosts[0].ip4,
1336 is_static=0,
1337 mac=self.pg2.remote_hosts[0].mac))
1338
1339 #
1340 # Add a static ARP entry with a changed mac
1341 #
1342 static_arp.add_vpp_config()
1343
1344 #
1345 # We should now find the static nbr with a changed mac
1346 #
1347 self.assertFalse(find_nbr(self,
1348 self.pg2.sw_if_index,
1349 self.pg2.remote_hosts[0].ip4,
1350 is_static=0))
1351 self.assertTrue(find_nbr(self,
1352 self.pg2.sw_if_index,
1353 self.pg2.remote_hosts[0].ip4,
1354 is_static=1,
1355 mac=self.pg2.remote_hosts[1].mac))
1356
1357 #
1358 # clean-up
1359 #
1360 static_arp.remove_vpp_config()
1361
Neale Rannsc819fc62018-02-16 02:44:05 -08001362 def test_arp_incomplete(self):
1363 """ ARP Incomplete"""
1364 self.pg1.generate_remote_hosts(3)
1365
1366 p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1367 IP(src=self.pg0.remote_ip4,
1368 dst=self.pg1.remote_hosts[1].ip4) /
1369 UDP(sport=1234, dport=1234) /
1370 Raw())
1371 p1 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1372 IP(src=self.pg0.remote_ip4,
1373 dst=self.pg1.remote_hosts[2].ip4) /
1374 UDP(sport=1234, dport=1234) /
1375 Raw())
1376
1377 #
1378 # a packet to an unresolved destination generates an ARP request
1379 #
1380 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1381 self.verify_arp_req(rx[0],
1382 self.pg1.local_mac,
1383 self.pg1.local_ip4,
1384 self.pg1._remote_hosts[1].ip4)
1385
1386 #
1387 # add a neighbour for remote host 1
1388 #
1389 static_arp = VppNeighbor(self,
1390 self.pg1.sw_if_index,
1391 self.pg1.remote_hosts[1].mac,
1392 self.pg1.remote_hosts[1].ip4,
1393 is_static=1)
1394 static_arp.add_vpp_config()
1395
1396 #
1397 # change the interface's MAC
1398 #
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001399 mac = [scapy.compat.chb(0x00), scapy.compat.chb(0x00),
1400 scapy.compat.chb(0x00), scapy.compat.chb(0x33),
1401 scapy.compat.chb(0x33), scapy.compat.chb(0x33)]
Neale Rannsc819fc62018-02-16 02:44:05 -08001402 mac_string = ''.join(mac)
1403
1404 self.vapi.sw_interface_set_mac_address(self.pg1.sw_if_index,
1405 mac_string)
1406
1407 #
1408 # now ARP requests come from the new source mac
1409 #
1410 rx = self.send_and_expect(self.pg0, [p1], self.pg1)
1411 self.verify_arp_req(rx[0],
1412 "00:00:00:33:33:33",
1413 self.pg1.local_ip4,
1414 self.pg1._remote_hosts[2].ip4)
1415
1416 #
1417 # packets to the resolved host also have the new source mac
1418 #
1419 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1420 self.verify_ip(rx[0],
1421 "00:00:00:33:33:33",
1422 self.pg1.remote_hosts[1].mac,
1423 self.pg0.remote_ip4,
1424 self.pg1.remote_hosts[1].ip4)
1425
1426 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001427 # set the mac address on the interface that does not have a
Neale Rannsc819fc62018-02-16 02:44:05 -08001428 # configured subnet and thus no glean
1429 #
1430 self.vapi.sw_interface_set_mac_address(self.pg2.sw_if_index,
1431 mac_string)
1432
Neale Ranns59ae61e2018-06-07 18:09:49 -07001433 def test_garp(self):
1434 """ GARP """
1435
1436 #
1437 # Generate some hosts on the LAN
1438 #
1439 self.pg1.generate_remote_hosts(4)
Neale Ranns22eefd72020-09-23 11:25:21 +00001440 self.pg2.generate_remote_hosts(4)
Neale Ranns59ae61e2018-06-07 18:09:49 -07001441
1442 #
1443 # And an ARP entry
1444 #
1445 arp = VppNeighbor(self,
1446 self.pg1.sw_if_index,
1447 self.pg1.remote_hosts[1].mac,
1448 self.pg1.remote_hosts[1].ip4)
1449 arp.add_vpp_config()
1450
1451 self.assertTrue(find_nbr(self,
1452 self.pg1.sw_if_index,
1453 self.pg1.remote_hosts[1].ip4,
1454 mac=self.pg1.remote_hosts[1].mac))
1455
1456 #
1457 # Send a GARP (request) to swap the host 1's address to that of host 2
1458 #
1459 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1460 src=self.pg1.remote_hosts[2].mac) /
1461 ARP(op="who-has",
1462 hwdst=self.pg1.local_mac,
1463 hwsrc=self.pg1.remote_hosts[2].mac,
1464 pdst=self.pg1.remote_hosts[1].ip4,
1465 psrc=self.pg1.remote_hosts[1].ip4))
1466
1467 self.pg1.add_stream(p1)
1468 self.pg_enable_capture(self.pg_interfaces)
1469 self.pg_start()
1470
1471 self.assertTrue(find_nbr(self,
1472 self.pg1.sw_if_index,
1473 self.pg1.remote_hosts[1].ip4,
1474 mac=self.pg1.remote_hosts[2].mac))
1475
1476 #
1477 # Send a GARP (reply) to swap the host 1's address to that of host 3
1478 #
1479 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1480 src=self.pg1.remote_hosts[3].mac) /
1481 ARP(op="is-at",
1482 hwdst=self.pg1.local_mac,
1483 hwsrc=self.pg1.remote_hosts[3].mac,
1484 pdst=self.pg1.remote_hosts[1].ip4,
1485 psrc=self.pg1.remote_hosts[1].ip4))
1486
1487 self.pg1.add_stream(p1)
1488 self.pg_enable_capture(self.pg_interfaces)
1489 self.pg_start()
1490
1491 self.assertTrue(find_nbr(self,
1492 self.pg1.sw_if_index,
1493 self.pg1.remote_hosts[1].ip4,
1494 mac=self.pg1.remote_hosts[3].mac))
1495
1496 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001497 # GARPs (request nor replies) for host we don't know yet
Neale Ranns59ae61e2018-06-07 18:09:49 -07001498 # don't result in new neighbour entries
1499 #
1500 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1501 src=self.pg1.remote_hosts[3].mac) /
1502 ARP(op="who-has",
1503 hwdst=self.pg1.local_mac,
1504 hwsrc=self.pg1.remote_hosts[3].mac,
1505 pdst=self.pg1.remote_hosts[2].ip4,
1506 psrc=self.pg1.remote_hosts[2].ip4))
1507
1508 self.pg1.add_stream(p1)
1509 self.pg_enable_capture(self.pg_interfaces)
1510 self.pg_start()
1511
1512 self.assertFalse(find_nbr(self,
1513 self.pg1.sw_if_index,
1514 self.pg1.remote_hosts[2].ip4))
1515
1516 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1517 src=self.pg1.remote_hosts[3].mac) /
1518 ARP(op="is-at",
1519 hwdst=self.pg1.local_mac,
1520 hwsrc=self.pg1.remote_hosts[3].mac,
1521 pdst=self.pg1.remote_hosts[2].ip4,
1522 psrc=self.pg1.remote_hosts[2].ip4))
1523
1524 self.pg1.add_stream(p1)
1525 self.pg_enable_capture(self.pg_interfaces)
1526 self.pg_start()
1527
1528 self.assertFalse(find_nbr(self,
1529 self.pg1.sw_if_index,
1530 self.pg1.remote_hosts[2].ip4))
1531
Neale Ranns22eefd72020-09-23 11:25:21 +00001532 #
1533 # IP address in different subnets are not learnt
1534 #
1535 self.pg2.configure_ipv4_neighbors()
1536
1537 for op in ["is-at", "who-has"]:
1538 p1 = [(Ether(dst="ff:ff:ff:ff:ff:ff",
1539 src=self.pg2.remote_hosts[1].mac) /
1540 ARP(op=op,
1541 hwdst=self.pg2.local_mac,
1542 hwsrc=self.pg2.remote_hosts[1].mac,
1543 pdst=self.pg2.remote_hosts[1].ip4,
1544 psrc=self.pg2.remote_hosts[1].ip4)),
1545 (Ether(dst="ff:ff:ff:ff:ff:ff",
1546 src=self.pg2.remote_hosts[1].mac) /
1547 ARP(op=op,
1548 hwdst="ff:ff:ff:ff:ff:ff",
1549 hwsrc=self.pg2.remote_hosts[1].mac,
1550 pdst=self.pg2.remote_hosts[1].ip4,
1551 psrc=self.pg2.remote_hosts[1].ip4))]
1552
1553 self.send_and_assert_no_replies(self.pg1, p1)
1554 self.assertFalse(find_nbr(self,
1555 self.pg1.sw_if_index,
1556 self.pg2.remote_hosts[1].ip4))
1557
1558 # they are all dropped because the subnet's don't match
1559 self.assertEqual(4, self.statistics.get_err_counter(
1560 "/err/arp-reply/IP4 destination address not local to subnet"))
1561
Neale Rannsc8352bc2018-08-29 10:23:58 -07001562 def test_arp_incomplete(self):
Neale Ranns14260392018-09-28 05:00:57 -07001563 """ Incomplete Entries """
Neale Rannsc8352bc2018-08-29 10:23:58 -07001564
1565 #
Neale Rannscd35e532018-08-31 02:51:45 -07001566 # ensure that we throttle the ARP and ND requests
Neale Rannsc8352bc2018-08-29 10:23:58 -07001567 #
1568 self.pg0.generate_remote_hosts(2)
1569
Neale Rannscd35e532018-08-31 02:51:45 -07001570 #
1571 # IPv4/ARP
1572 #
Neale Rannsc8352bc2018-08-29 10:23:58 -07001573 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1574 [VppRoutePath(self.pg0.remote_hosts[1].ip4,
Neale Rannscd35e532018-08-31 02:51:45 -07001575 self.pg0.sw_if_index)])
Neale Rannsc8352bc2018-08-29 10:23:58 -07001576 ip_10_0_0_1.add_vpp_config()
1577
1578 p1 = (Ether(dst=self.pg1.local_mac,
1579 src=self.pg1.remote_mac) /
1580 IP(src=self.pg1.remote_ip4,
1581 dst="10.0.0.1") /
1582 UDP(sport=1234, dport=1234) /
1583 Raw())
1584
1585 self.pg1.add_stream(p1 * 257)
1586 self.pg_enable_capture(self.pg_interfaces)
1587 self.pg_start()
1588 rx = self.pg0._get_capture(1)
1589
1590 #
1591 # how many we get is going to be dependent on the time for packet
1592 # processing but it should be small
1593 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001594 self.assertLess(len(rx), 64)
Neale Rannsc8352bc2018-08-29 10:23:58 -07001595
Neale Rannscd35e532018-08-31 02:51:45 -07001596 #
1597 # IPv6/ND
1598 #
1599 ip_10_1 = VppIpRoute(self, "10::1", 128,
1600 [VppRoutePath(self.pg0.remote_hosts[1].ip6,
1601 self.pg0.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07001602 proto=DpoProto.DPO_PROTO_IP6)])
Neale Rannscd35e532018-08-31 02:51:45 -07001603 ip_10_1.add_vpp_config()
1604
1605 p1 = (Ether(dst=self.pg1.local_mac,
1606 src=self.pg1.remote_mac) /
1607 IPv6(src=self.pg1.remote_ip6,
1608 dst="10::1") /
1609 UDP(sport=1234, dport=1234) /
1610 Raw())
1611
1612 self.pg1.add_stream(p1 * 257)
1613 self.pg_enable_capture(self.pg_interfaces)
1614 self.pg_start()
1615 rx = self.pg0._get_capture(1)
1616
1617 #
1618 # how many we get is going to be dependent on the time for packet
1619 # processing but it should be small
1620 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001621 self.assertLess(len(rx), 64)
Neale Rannscd35e532018-08-31 02:51:45 -07001622
Neale Ranns7425f922019-01-23 00:36:16 -08001623 def test_arp_forus(self):
1624 """ ARP for for-us """
1625
1626 #
1627 # Test that VPP responds with ARP requests to addresses that
1628 # are connected and local routes.
1629 # Use one of the 'remote' addresses in the subnet as a local address
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001630 # The intention of this route is that it then acts like a secondary
Neale Ranns7425f922019-01-23 00:36:16 -08001631 # address added to an interface
1632 #
1633 self.pg0.generate_remote_hosts(2)
1634
Neale Ranns097fa662018-05-01 05:17:55 -07001635 forus = VppIpRoute(
1636 self, self.pg0.remote_hosts[1].ip4, 32,
1637 [VppRoutePath("0.0.0.0",
1638 self.pg0.sw_if_index,
1639 type=FibPathType.FIB_PATH_TYPE_LOCAL)])
Neale Ranns7425f922019-01-23 00:36:16 -08001640 forus.add_vpp_config()
1641
1642 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
1643 src=self.pg0.remote_mac) /
1644 ARP(op="who-has",
1645 hwdst=self.pg0.local_mac,
1646 hwsrc=self.pg0.remote_mac,
1647 pdst=self.pg0.remote_hosts[1].ip4,
1648 psrc=self.pg0.remote_ip4))
1649
1650 rx = self.send_and_expect(self.pg0, [p], self.pg0)
1651
1652 self.verify_arp_resp(rx[0],
1653 self.pg0.local_mac,
1654 self.pg0.remote_mac,
1655 self.pg0.remote_hosts[1].ip4,
1656 self.pg0.remote_ip4)
1657
Neale Rannsfca3c6a2019-12-31 03:49:34 +00001658 def test_arp_table_swap(self):
1659 #
1660 # Generate some hosts on the LAN
1661 #
1662 N_NBRS = 4
1663 self.pg1.generate_remote_hosts(N_NBRS)
1664
1665 for n in range(N_NBRS):
1666 # a route thru each neighbour
1667 VppIpRoute(self, "10.0.0.%d" % n, 32,
1668 [VppRoutePath(self.pg1.remote_hosts[n].ip4,
1669 self.pg1.sw_if_index)]).add_vpp_config()
1670
1671 # resolve each neighbour
1672 p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1673 ARP(op="is-at", hwdst=self.pg1.local_mac,
1674 hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
1675 psrc=self.pg1.remote_hosts[n].ip4))
1676
1677 self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
1678
1679 self.logger.info(self.vapi.cli("sh ip neighbors"))
1680
1681 #
1682 # swap the table pg1 is in
1683 #
1684 table = VppIpTable(self, 100).add_vpp_config()
1685
1686 self.pg1.unconfig_ip4()
1687 self.pg1.set_table_ip4(100)
1688 self.pg1.config_ip4()
1689
1690 #
1691 # all neighbours are cleared
1692 #
1693 for n in range(N_NBRS):
1694 self.assertFalse(find_nbr(self,
1695 self.pg1.sw_if_index,
1696 self.pg1.remote_hosts[n].ip4))
1697
1698 #
1699 # packets to all neighbours generate ARP requests
1700 #
1701 for n in range(N_NBRS):
1702 # a route thru each neighbour
1703 VppIpRoute(self, "10.0.0.%d" % n, 32,
1704 [VppRoutePath(self.pg1.remote_hosts[n].ip4,
1705 self.pg1.sw_if_index)],
1706 table_id=100).add_vpp_config()
1707
1708 p = (Ether(src=self.pg1.remote_hosts[n].mac,
1709 dst=self.pg1.local_mac) /
1710 IP(src=self.pg1.remote_hosts[n].ip4,
1711 dst="10.0.0.%d" % n) /
1712 Raw(b'0x5' * 100))
1713 rxs = self.send_and_expect(self.pg1, [p], self.pg1)
1714 for rx in rxs:
1715 self.verify_arp_req(rx,
1716 self.pg1.local_mac,
1717 self.pg1.local_ip4,
1718 self.pg1.remote_hosts[n].ip4)
1719
1720 self.pg1.unconfig_ip4()
1721 self.pg1.set_table_ip4(0)
1722
Neale Rannsdcd6d622017-05-26 02:59:16 -07001723
Neale Ranns14260392018-09-28 05:00:57 -07001724class NeighborStatsTestCase(VppTestCase):
Neale Ranns37029302018-08-10 05:30:06 -07001725 """ ARP/ND Counters """
Neale Ranns14260392018-09-28 05:00:57 -07001726
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001727 @classmethod
1728 def setUpClass(cls):
1729 super(NeighborStatsTestCase, cls).setUpClass()
1730
1731 @classmethod
1732 def tearDownClass(cls):
1733 super(NeighborStatsTestCase, cls).tearDownClass()
1734
Neale Ranns14260392018-09-28 05:00:57 -07001735 def setUp(self):
1736 super(NeighborStatsTestCase, self).setUp()
1737
1738 self.create_pg_interfaces(range(2))
1739
1740 # pg0 configured with ip4 and 6 addresses used for input
1741 # pg1 configured with ip4 and 6 addresses used for output
1742 # pg2 is unnumbered to pg0
1743 for i in self.pg_interfaces:
1744 i.admin_up()
1745 i.config_ip4()
1746 i.config_ip6()
1747 i.resolve_arp()
1748 i.resolve_ndp()
1749
1750 def tearDown(self):
1751 super(NeighborStatsTestCase, self).tearDown()
1752
1753 for i in self.pg_interfaces:
1754 i.unconfig_ip4()
1755 i.unconfig_ip6()
1756 i.admin_down()
1757
1758 def test_arp_stats(self):
1759 """ ARP Counters """
1760
1761 self.vapi.cli("adj counters enable")
1762 self.pg1.generate_remote_hosts(2)
1763
1764 arp1 = VppNeighbor(self,
1765 self.pg1.sw_if_index,
1766 self.pg1.remote_hosts[0].mac,
1767 self.pg1.remote_hosts[0].ip4)
1768 arp1.add_vpp_config()
1769 arp2 = VppNeighbor(self,
1770 self.pg1.sw_if_index,
1771 self.pg1.remote_hosts[1].mac,
1772 self.pg1.remote_hosts[1].ip4)
1773 arp2.add_vpp_config()
1774
1775 p1 = (Ether(dst=self.pg0.local_mac,
1776 src=self.pg0.remote_mac) /
1777 IP(src=self.pg0.remote_ip4,
1778 dst=self.pg1.remote_hosts[0].ip4) /
1779 UDP(sport=1234, dport=1234) /
1780 Raw())
1781 p2 = (Ether(dst=self.pg0.local_mac,
1782 src=self.pg0.remote_mac) /
1783 IP(src=self.pg0.remote_ip4,
1784 dst=self.pg1.remote_hosts[1].ip4) /
1785 UDP(sport=1234, dport=1234) /
1786 Raw())
1787
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001788 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
1789 rx = self.send_and_expect(self.pg0, p2 * NUM_PKTS, self.pg1)
Neale Ranns14260392018-09-28 05:00:57 -07001790
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001791 self.assertEqual(NUM_PKTS, arp1.get_stats()['packets'])
1792 self.assertEqual(NUM_PKTS, arp2.get_stats()['packets'])
Neale Ranns14260392018-09-28 05:00:57 -07001793
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001794 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
1795 self.assertEqual(NUM_PKTS*2, arp1.get_stats()['packets'])
Neale Ranns14260392018-09-28 05:00:57 -07001796
1797 def test_nd_stats(self):
1798 """ ND Counters """
1799
1800 self.vapi.cli("adj counters enable")
1801 self.pg0.generate_remote_hosts(3)
1802
1803 nd1 = VppNeighbor(self,
1804 self.pg0.sw_if_index,
1805 self.pg0.remote_hosts[1].mac,
Neale Ranns37029302018-08-10 05:30:06 -07001806 self.pg0.remote_hosts[1].ip6)
Neale Ranns14260392018-09-28 05:00:57 -07001807 nd1.add_vpp_config()
1808 nd2 = VppNeighbor(self,
1809 self.pg0.sw_if_index,
1810 self.pg0.remote_hosts[2].mac,
Neale Ranns37029302018-08-10 05:30:06 -07001811 self.pg0.remote_hosts[2].ip6)
Neale Ranns14260392018-09-28 05:00:57 -07001812 nd2.add_vpp_config()
1813
1814 p1 = (Ether(dst=self.pg1.local_mac,
1815 src=self.pg1.remote_mac) /
1816 IPv6(src=self.pg1.remote_ip6,
1817 dst=self.pg0.remote_hosts[1].ip6) /
1818 UDP(sport=1234, dport=1234) /
1819 Raw())
1820 p2 = (Ether(dst=self.pg1.local_mac,
1821 src=self.pg1.remote_mac) /
1822 IPv6(src=self.pg1.remote_ip6,
1823 dst=self.pg0.remote_hosts[2].ip6) /
1824 UDP(sport=1234, dport=1234) /
1825 Raw())
1826
1827 rx = self.send_and_expect(self.pg1, p1 * 16, self.pg0)
1828 rx = self.send_and_expect(self.pg1, p2 * 16, self.pg0)
1829
1830 self.assertEqual(16, nd1.get_stats()['packets'])
1831 self.assertEqual(16, nd2.get_stats()['packets'])
1832
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001833 rx = self.send_and_expect(self.pg1, p1 * NUM_PKTS, self.pg0)
1834 self.assertEqual(NUM_PKTS+16, nd1.get_stats()['packets'])
Neale Ranns14260392018-09-28 05:00:57 -07001835
1836
Neale Rannscbe25aa2019-09-30 10:53:31 +00001837class NeighborAgeTestCase(VppTestCase):
1838 """ ARP/ND Aging """
1839
1840 @classmethod
1841 def setUpClass(cls):
1842 super(NeighborAgeTestCase, cls).setUpClass()
1843
1844 @classmethod
1845 def tearDownClass(cls):
1846 super(NeighborAgeTestCase, cls).tearDownClass()
1847
1848 def setUp(self):
1849 super(NeighborAgeTestCase, self).setUp()
1850
1851 self.create_pg_interfaces(range(1))
1852
1853 # pg0 configured with ip4 and 6 addresses used for input
1854 # pg1 configured with ip4 and 6 addresses used for output
1855 # pg2 is unnumbered to pg0
1856 for i in self.pg_interfaces:
1857 i.admin_up()
1858 i.config_ip4()
1859 i.config_ip6()
1860 i.resolve_arp()
1861 i.resolve_ndp()
1862
1863 def tearDown(self):
1864 super(NeighborAgeTestCase, self).tearDown()
1865
1866 for i in self.pg_interfaces:
1867 i.unconfig_ip4()
1868 i.unconfig_ip6()
1869 i.admin_down()
1870
1871 def wait_for_no_nbr(self, intf, address,
1872 n_tries=50, s_time=1):
1873 while (n_tries):
1874 if not find_nbr(self, intf, address):
1875 return True
1876 n_tries = n_tries - 1
1877 self.sleep(s_time)
1878
1879 return False
1880
1881 def verify_arp_req(self, rx, smac, sip, dip):
1882 ether = rx[Ether]
1883 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
1884 self.assertEqual(ether.src, smac)
1885
1886 arp = rx[ARP]
1887 self.assertEqual(arp.hwtype, 1)
1888 self.assertEqual(arp.ptype, 0x800)
1889 self.assertEqual(arp.hwlen, 6)
1890 self.assertEqual(arp.plen, 4)
1891 self.assertEqual(arp.op, arp_opts["who-has"])
1892 self.assertEqual(arp.hwsrc, smac)
1893 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
1894 self.assertEqual(arp.psrc, sip)
1895 self.assertEqual(arp.pdst, dip)
1896
1897 def test_age(self):
1898 """ Aging/Recycle """
1899
1900 self.vapi.cli("set logging unthrottle 0")
1901 self.vapi.cli("set logging size %d" % 0xffff)
1902
1903 self.pg0.generate_remote_hosts(201)
1904
1905 vaf = VppEnum.vl_api_address_family_t
1906
1907 #
1908 # start listening on all interfaces
1909 #
1910 self.pg_enable_capture(self.pg_interfaces)
1911
1912 #
1913 # Set the neighbor configuration:
1914 # limi = 200
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03001915 # age = 0 seconds
Neale Rannscbe25aa2019-09-30 10:53:31 +00001916 # recycle = false
1917 #
1918 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
1919 max_number=200,
1920 max_age=0,
1921 recycle=False)
1922
1923 self.vapi.cli("sh ip neighbor-config")
1924
1925 # add the 198 neighbours that should pass (-1 for one created in setup)
1926 for ii in range(200):
1927 VppNeighbor(self,
1928 self.pg0.sw_if_index,
1929 self.pg0.remote_hosts[ii].mac,
1930 self.pg0.remote_hosts[ii].ip4).add_vpp_config()
1931
1932 # one more neighbor over the limit should fail
1933 with self.vapi.assert_negative_api_retval():
1934 VppNeighbor(self,
1935 self.pg0.sw_if_index,
1936 self.pg0.remote_hosts[200].mac,
1937 self.pg0.remote_hosts[200].ip4).add_vpp_config()
1938
1939 #
1940 # change the config to allow recycling the old neighbors
1941 #
1942 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
1943 max_number=200,
1944 max_age=0,
1945 recycle=True)
1946
1947 # now new additions are allowed
1948 VppNeighbor(self,
1949 self.pg0.sw_if_index,
1950 self.pg0.remote_hosts[200].mac,
1951 self.pg0.remote_hosts[200].ip4).add_vpp_config()
1952
1953 # add the first neighbor we configured has been re-used
1954 self.assertFalse(find_nbr(self,
1955 self.pg0.sw_if_index,
1956 self.pg0.remote_hosts[0].ip4))
1957 self.assertTrue(find_nbr(self,
1958 self.pg0.sw_if_index,
1959 self.pg0.remote_hosts[200].ip4))
1960
1961 #
1962 # change the config to age old neighbors
1963 #
1964 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
1965 max_number=200,
1966 max_age=2,
1967 recycle=True)
1968
1969 self.vapi.cli("sh ip4 neighbor-sorted")
1970
1971 #
1972 # expect probes from all these ARP entries as they age
1973 # 3 probes for each neighbor 3*200 = 600
1974 rxs = self.pg0.get_capture(600, timeout=8)
1975
1976 for ii in range(3):
1977 for jj in range(200):
1978 rx = rxs[ii*200 + jj]
1979 # rx.show()
1980
1981 #
1982 # 3 probes sent then 1 more second to see if a reply comes, before
1983 # they age out
1984 #
1985 for jj in range(1, 201):
1986 self.wait_for_no_nbr(self.pg0.sw_if_index,
1987 self.pg0.remote_hosts[jj].ip4)
1988
1989 self.assertFalse(self.vapi.ip_neighbor_dump(sw_if_index=0xffffffff,
1990 af=vaf.ADDRESS_IP4))
1991
1992 #
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03001993 # load up some neighbours again with 2s aging enabled
1994 # they should be removed after 10s (2s age + 4s for probes + gap)
1995 #
1996 for ii in range(10):
1997 VppNeighbor(self,
1998 self.pg0.sw_if_index,
1999 self.pg0.remote_hosts[ii].mac,
2000 self.pg0.remote_hosts[ii].ip4).add_vpp_config()
2001 self.sleep(10)
2002 self.assertFalse(self.vapi.ip_neighbor_dump(sw_if_index=0xffffffff,
2003 af=vaf.ADDRESS_IP4))
2004
2005 #
2006 # check if we can set age and recycle with empty neighbor list
2007 #
2008 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
2009 max_number=200,
2010 max_age=1000,
2011 recycle=True)
2012
2013 #
Neale Rannscbe25aa2019-09-30 10:53:31 +00002014 # load up some neighbours again, then disable the aging
2015 # they should still be there in 10 seconds time
2016 #
2017 for ii in range(10):
2018 VppNeighbor(self,
2019 self.pg0.sw_if_index,
2020 self.pg0.remote_hosts[ii].mac,
2021 self.pg0.remote_hosts[ii].ip4).add_vpp_config()
2022 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
2023 max_number=200,
2024 max_age=0,
2025 recycle=False)
2026
2027 self.sleep(10)
2028 self.assertTrue(find_nbr(self,
2029 self.pg0.sw_if_index,
2030 self.pg0.remote_hosts[0].ip4))
2031
2032
Neale Rannsc87fbb42020-04-02 17:08:28 +00002033class NeighborReplaceTestCase(VppTestCase):
2034 """ ARP/ND Replacement """
2035
2036 @classmethod
2037 def setUpClass(cls):
2038 super(NeighborReplaceTestCase, cls).setUpClass()
2039
2040 @classmethod
2041 def tearDownClass(cls):
2042 super(NeighborReplaceTestCase, cls).tearDownClass()
2043
2044 def setUp(self):
2045 super(NeighborReplaceTestCase, self).setUp()
2046
2047 self.create_pg_interfaces(range(4))
2048
2049 # pg0 configured with ip4 and 6 addresses used for input
2050 # pg1 configured with ip4 and 6 addresses used for output
2051 # pg2 is unnumbered to pg0
2052 for i in self.pg_interfaces:
2053 i.admin_up()
2054 i.config_ip4()
2055 i.config_ip6()
2056 i.resolve_arp()
2057 i.resolve_ndp()
2058
2059 def tearDown(self):
2060 super(NeighborReplaceTestCase, self).tearDown()
2061
2062 for i in self.pg_interfaces:
2063 i.unconfig_ip4()
2064 i.unconfig_ip6()
2065 i.admin_down()
2066
2067 def test_replace(self):
2068 """ replace """
2069
2070 N_HOSTS = 16
2071
2072 for i in self.pg_interfaces:
2073 i.generate_remote_hosts(N_HOSTS)
2074 i.configure_ipv4_neighbors()
2075 i.configure_ipv6_neighbors()
2076
2077 # replace them all
2078 self.vapi.ip_neighbor_replace_begin()
2079 self.vapi.ip_neighbor_replace_end()
2080
2081 for i in self.pg_interfaces:
2082 for h in range(N_HOSTS):
2083 self.assertFalse(find_nbr(self,
2084 self.pg0.sw_if_index,
2085 self.pg0.remote_hosts[h].ip4))
2086 self.assertFalse(find_nbr(self,
2087 self.pg0.sw_if_index,
2088 self.pg0.remote_hosts[h].ip6))
2089
2090 #
2091 # and them all back via the API
2092 #
2093 for i in self.pg_interfaces:
2094 for h in range(N_HOSTS):
2095 VppNeighbor(self,
2096 i.sw_if_index,
2097 i.remote_hosts[h].mac,
2098 i.remote_hosts[h].ip4).add_vpp_config()
2099 VppNeighbor(self,
2100 i.sw_if_index,
2101 i.remote_hosts[h].mac,
2102 i.remote_hosts[h].ip6).add_vpp_config()
2103
2104 #
2105 # begin the replacement again, this time touch some
2106 # the neighbours on pg1 so they are not deleted
2107 #
2108 self.vapi.ip_neighbor_replace_begin()
2109
2110 # update from the API all neighbours on pg1
2111 for h in range(N_HOSTS):
2112 VppNeighbor(self,
2113 self.pg1.sw_if_index,
2114 self.pg1.remote_hosts[h].mac,
2115 self.pg1.remote_hosts[h].ip4).add_vpp_config()
2116 VppNeighbor(self,
2117 self.pg1.sw_if_index,
2118 self.pg1.remote_hosts[h].mac,
2119 self.pg1.remote_hosts[h].ip6).add_vpp_config()
2120
2121 # update from the data-plane all neighbours on pg3
2122 self.pg3.configure_ipv4_neighbors()
2123 self.pg3.configure_ipv6_neighbors()
2124
2125 # complete the replacement
2126 self.logger.info(self.vapi.cli("sh ip neighbors"))
2127 self.vapi.ip_neighbor_replace_end()
2128
2129 for i in self.pg_interfaces:
2130 if i == self.pg1 or i == self.pg3:
2131 # neighbours on pg1 and pg3 are still present
2132 for h in range(N_HOSTS):
2133 self.assertTrue(find_nbr(self,
2134 i.sw_if_index,
2135 i.remote_hosts[h].ip4))
2136 self.assertTrue(find_nbr(self,
2137 i.sw_if_index,
2138 i.remote_hosts[h].ip6))
2139 else:
2140 # all other neighbours are toast
2141 for h in range(N_HOSTS):
2142 self.assertFalse(find_nbr(self,
2143 i.sw_if_index,
2144 i.remote_hosts[h].ip4))
2145 self.assertFalse(find_nbr(self,
2146 i.sw_if_index,
2147 i.remote_hosts[h].ip6))
2148
2149
Neale Ranns240dcb22020-04-23 09:04:59 +00002150class NeighborFlush(VppTestCase):
2151 """ Neighbor Flush """
2152
2153 @classmethod
2154 def setUpClass(cls):
2155 super(NeighborFlush, cls).setUpClass()
2156
2157 @classmethod
2158 def tearDownClass(cls):
2159 super(NeighborFlush, cls).tearDownClass()
2160
2161 def setUp(self):
2162 super(NeighborFlush, self).setUp()
2163
2164 self.create_pg_interfaces(range(2))
2165
2166 for i in self.pg_interfaces:
2167 i.admin_up()
2168 i.config_ip4()
2169 i.config_ip6()
2170 i.resolve_arp()
2171 i.resolve_ndp()
2172
2173 def tearDown(self):
2174 super(NeighborFlush, self).tearDown()
2175
2176 for i in self.pg_interfaces:
2177 i.unconfig_ip4()
2178 i.unconfig_ip6()
2179 i.admin_down()
2180
2181 def test_flush(self):
2182 """ Neighbour Flush """
2183
2184 e = VppEnum
2185 nf = e.vl_api_ip_neighbor_flags_t
2186 af = e.vl_api_address_family_t
2187 N_HOSTS = 16
2188 static = [False, True]
2189 self.pg0.generate_remote_hosts(N_HOSTS)
2190 self.pg1.generate_remote_hosts(N_HOSTS)
2191
2192 for s in static:
2193 # a few v4 and v6 dynamic neoghbors
2194 for n in range(N_HOSTS):
2195 VppNeighbor(self,
2196 self.pg0.sw_if_index,
2197 self.pg0.remote_hosts[n].mac,
2198 self.pg0.remote_hosts[n].ip4,
2199 is_static=s).add_vpp_config()
2200 VppNeighbor(self,
2201 self.pg1.sw_if_index,
2202 self.pg1.remote_hosts[n].mac,
2203 self.pg1.remote_hosts[n].ip6,
2204 is_static=s).add_vpp_config()
2205
2206 # flush the interfaces individually
2207 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, self.pg0.sw_if_index)
2208
2209 # check we haven't flushed that which we shouldn't
2210 for n in range(N_HOSTS):
2211 self.assertTrue(find_nbr(self,
2212 self.pg1.sw_if_index,
2213 self.pg1.remote_hosts[n].ip6,
2214 is_static=s))
2215
2216 self.vapi.ip_neighbor_flush(af.ADDRESS_IP6, self.pg1.sw_if_index)
2217
2218 for n in range(N_HOSTS):
2219 self.assertFalse(find_nbr(self,
2220 self.pg0.sw_if_index,
2221 self.pg0.remote_hosts[n].ip4))
2222 self.assertFalse(find_nbr(self,
2223 self.pg1.sw_if_index,
2224 self.pg1.remote_hosts[n].ip6))
2225
2226 # add the nieghbours back
2227 for n in range(N_HOSTS):
2228 VppNeighbor(self,
2229 self.pg0.sw_if_index,
2230 self.pg0.remote_hosts[n].mac,
2231 self.pg0.remote_hosts[n].ip4,
2232 is_static=s).add_vpp_config()
2233 VppNeighbor(self,
2234 self.pg1.sw_if_index,
2235 self.pg1.remote_hosts[n].mac,
2236 self.pg1.remote_hosts[n].ip6,
2237 is_static=s).add_vpp_config()
2238
2239 self.logger.info(self.vapi.cli("sh ip neighbor"))
2240
2241 # flush both interfaces at the same time
2242 self.vapi.ip_neighbor_flush(af.ADDRESS_IP6, 0xffffffff)
2243
2244 # check we haven't flushed that which we shouldn't
2245 for n in range(N_HOSTS):
2246 self.assertTrue(find_nbr(self,
2247 self.pg0.sw_if_index,
2248 self.pg0.remote_hosts[n].ip4,
2249 is_static=s))
2250
2251 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, 0xffffffff)
2252
2253 for n in range(N_HOSTS):
2254 self.assertFalse(find_nbr(self,
2255 self.pg0.sw_if_index,
2256 self.pg0.remote_hosts[n].ip4))
2257 self.assertFalse(find_nbr(self,
2258 self.pg1.sw_if_index,
2259 self.pg1.remote_hosts[n].ip6))
2260
2261
Neale Ranns37be7362017-02-21 17:30:26 -08002262if __name__ == '__main__':
2263 unittest.main(testRunner=VppTestRunner)