blob: 0b7ffff8bc3aa21ef1041160aab9dcd62ab185ba [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
4from socket import AF_INET, AF_INET6, inet_pton
5
6from framework import VppTestCase, VppTestRunner
7from vpp_neighbor import VppNeighbor, find_nbr
Neale Ranns15002542017-09-10 04:39:11 -07008from vpp_ip_route import VppIpRoute, VppRoutePath, find_route, \
Neale Ranns097fa662018-05-01 05:17:55 -07009 VppIpTable, DpoProto, FibPathType
Neale Ranns37029302018-08-10 05:30:06 -070010from vpp_papi import VppEnum
Neale Ranns39f9d8b2017-02-16 21:57:05 -080011
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -070012import scapy.compat
Neale Ranns39f9d8b2017-02-16 21:57:05 -080013from scapy.packet import Raw
Neale Ranns30d0fd42017-05-30 07:30:04 -070014from scapy.layers.l2 import Ether, ARP, Dot1Q
Neale Ranns39f9d8b2017-02-16 21:57:05 -080015from scapy.layers.inet import IP, UDP
Neale Rannscd35e532018-08-31 02:51:45 -070016from scapy.layers.inet6 import IPv6
Neale Ranns37be7362017-02-21 17:30:26 -080017from scapy.contrib.mpls import MPLS
Neale Ranns14260392018-09-28 05:00:57 -070018from scapy.layers.inet6 import IPv6
Neale Ranns39f9d8b2017-02-16 21:57:05 -080019
Paul Vinciguerra4271c972019-05-14 13:25:49 -040020
21NUM_PKTS = 67
22
Neale Ranns39f9d8b2017-02-16 21:57:05 -080023# not exported by scapy, so redefined here
24arp_opts = {"who-has": 1, "is-at": 2}
25
26
27class ARPTestCase(VppTestCase):
28 """ ARP Test Case """
29
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070030 @classmethod
31 def setUpClass(cls):
32 super(ARPTestCase, cls).setUpClass()
33
34 @classmethod
35 def tearDownClass(cls):
36 super(ARPTestCase, cls).tearDownClass()
37
Neale Ranns39f9d8b2017-02-16 21:57:05 -080038 def setUp(self):
39 super(ARPTestCase, self).setUp()
40
41 # create 3 pg interfaces
42 self.create_pg_interfaces(range(4))
43
44 # pg0 configured with ip4 and 6 addresses used for input
45 # pg1 configured with ip4 and 6 addresses used for output
46 # pg2 is unnumbered to pg0
47 for i in self.pg_interfaces:
48 i.admin_up()
49
50 self.pg0.config_ip4()
51 self.pg0.config_ip6()
52 self.pg0.resolve_arp()
53
54 self.pg1.config_ip4()
55 self.pg1.config_ip6()
56
57 # pg3 in a different VRF
Neale Ranns15002542017-09-10 04:39:11 -070058 self.tbl = VppIpTable(self, 1)
59 self.tbl.add_vpp_config()
60
Neale Ranns39f9d8b2017-02-16 21:57:05 -080061 self.pg3.set_table_ip4(1)
62 self.pg3.config_ip4()
63
Neale Ranns4008ac92017-02-13 23:20:04 -080064 def tearDown(self):
Neale Ranns4b919a52017-03-11 05:55:21 -080065 self.pg0.unconfig_ip4()
66 self.pg0.unconfig_ip6()
67
68 self.pg1.unconfig_ip4()
69 self.pg1.unconfig_ip6()
70
71 self.pg3.unconfig_ip4()
Neale Ranns15002542017-09-10 04:39:11 -070072 self.pg3.set_table_ip4(0)
Neale Ranns4b919a52017-03-11 05:55:21 -080073
Neale Ranns4008ac92017-02-13 23:20:04 -080074 for i in self.pg_interfaces:
Neale Ranns4008ac92017-02-13 23:20:04 -080075 i.admin_down()
76
Neale Ranns15002542017-09-10 04:39:11 -070077 super(ARPTestCase, self).tearDown()
78
Neale Ranns39f9d8b2017-02-16 21:57:05 -080079 def verify_arp_req(self, rx, smac, sip, dip):
80 ether = rx[Ether]
81 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
82 self.assertEqual(ether.src, smac)
83
84 arp = rx[ARP]
85 self.assertEqual(arp.hwtype, 1)
86 self.assertEqual(arp.ptype, 0x800)
87 self.assertEqual(arp.hwlen, 6)
88 self.assertEqual(arp.plen, 4)
89 self.assertEqual(arp.op, arp_opts["who-has"])
90 self.assertEqual(arp.hwsrc, smac)
91 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
92 self.assertEqual(arp.psrc, sip)
93 self.assertEqual(arp.pdst, dip)
94
95 def verify_arp_resp(self, rx, smac, dmac, sip, dip):
96 ether = rx[Ether]
97 self.assertEqual(ether.dst, dmac)
98 self.assertEqual(ether.src, smac)
99
100 arp = rx[ARP]
101 self.assertEqual(arp.hwtype, 1)
102 self.assertEqual(arp.ptype, 0x800)
103 self.assertEqual(arp.hwlen, 6)
104 self.assertEqual(arp.plen, 4)
105 self.assertEqual(arp.op, arp_opts["is-at"])
106 self.assertEqual(arp.hwsrc, smac)
107 self.assertEqual(arp.hwdst, dmac)
108 self.assertEqual(arp.psrc, sip)
109 self.assertEqual(arp.pdst, dip)
110
Matthew Smithcb9ab472017-05-16 21:35:56 -0500111 def verify_arp_vrrp_resp(self, rx, smac, dmac, sip, dip):
112 ether = rx[Ether]
113 self.assertEqual(ether.dst, dmac)
114 self.assertEqual(ether.src, smac)
115
116 arp = rx[ARP]
117 self.assertEqual(arp.hwtype, 1)
118 self.assertEqual(arp.ptype, 0x800)
119 self.assertEqual(arp.hwlen, 6)
120 self.assertEqual(arp.plen, 4)
121 self.assertEqual(arp.op, arp_opts["is-at"])
122 self.assertNotEqual(arp.hwsrc, smac)
123 self.assertTrue("00:00:5e:00:01" in arp.hwsrc or
124 "00:00:5E:00:01" in arp.hwsrc)
125 self.assertEqual(arp.hwdst, dmac)
126 self.assertEqual(arp.psrc, sip)
127 self.assertEqual(arp.pdst, dip)
128
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800129 def verify_ip(self, rx, smac, dmac, sip, dip):
130 ether = rx[Ether]
131 self.assertEqual(ether.dst, dmac)
132 self.assertEqual(ether.src, smac)
133
134 ip = rx[IP]
135 self.assertEqual(ip.src, sip)
136 self.assertEqual(ip.dst, dip)
137
Neale Ranns37be7362017-02-21 17:30:26 -0800138 def verify_ip_o_mpls(self, rx, smac, dmac, label, sip, dip):
139 ether = rx[Ether]
140 self.assertEqual(ether.dst, dmac)
141 self.assertEqual(ether.src, smac)
142
143 mpls = rx[MPLS]
144 self.assertTrue(mpls.label, label)
145
146 ip = rx[IP]
147 self.assertEqual(ip.src, sip)
148 self.assertEqual(ip.dst, dip)
149
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800150 def test_arp(self):
151 """ ARP """
152
153 #
154 # Generate some hosts on the LAN
155 #
Neale Rannsca193612017-06-14 06:50:08 -0700156 self.pg1.generate_remote_hosts(11)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800157
158 #
159 # Send IP traffic to one of these unresolved hosts.
160 # expect the generation of an ARP request
161 #
162 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
163 IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[1].ip4) /
164 UDP(sport=1234, dport=1234) /
165 Raw())
166
167 self.pg0.add_stream(p)
168 self.pg_enable_capture(self.pg_interfaces)
169 self.pg_start()
170
171 rx = self.pg1.get_capture(1)
172
173 self.verify_arp_req(rx[0],
174 self.pg1.local_mac,
175 self.pg1.local_ip4,
176 self.pg1._remote_hosts[1].ip4)
177
178 #
179 # And a dynamic ARP entry for host 1
180 #
181 dyn_arp = VppNeighbor(self,
182 self.pg1.sw_if_index,
183 self.pg1.remote_hosts[1].mac,
184 self.pg1.remote_hosts[1].ip4)
185 dyn_arp.add_vpp_config()
186
187 #
188 # now we expect IP traffic forwarded
189 #
190 dyn_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
191 IP(src=self.pg0.remote_ip4,
192 dst=self.pg1._remote_hosts[1].ip4) /
193 UDP(sport=1234, dport=1234) /
194 Raw())
195
196 self.pg0.add_stream(dyn_p)
197 self.pg_enable_capture(self.pg_interfaces)
198 self.pg_start()
199
200 rx = self.pg1.get_capture(1)
201
202 self.verify_ip(rx[0],
203 self.pg1.local_mac,
204 self.pg1.remote_hosts[1].mac,
205 self.pg0.remote_ip4,
206 self.pg1._remote_hosts[1].ip4)
207
208 #
209 # And a Static ARP entry for host 2
210 #
211 static_arp = VppNeighbor(self,
212 self.pg1.sw_if_index,
213 self.pg1.remote_hosts[2].mac,
214 self.pg1.remote_hosts[2].ip4,
215 is_static=1)
216 static_arp.add_vpp_config()
217
218 static_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
219 IP(src=self.pg0.remote_ip4,
220 dst=self.pg1._remote_hosts[2].ip4) /
221 UDP(sport=1234, dport=1234) /
222 Raw())
223
224 self.pg0.add_stream(static_p)
225 self.pg_enable_capture(self.pg_interfaces)
226 self.pg_start()
227
228 rx = self.pg1.get_capture(1)
229
230 self.verify_ip(rx[0],
231 self.pg1.local_mac,
232 self.pg1.remote_hosts[2].mac,
233 self.pg0.remote_ip4,
234 self.pg1._remote_hosts[2].ip4)
235
236 #
237 # flap the link. dynamic ARPs get flush, statics don't
238 #
239 self.pg1.admin_down()
240 self.pg1.admin_up()
241
242 self.pg0.add_stream(static_p)
243 self.pg_enable_capture(self.pg_interfaces)
244 self.pg_start()
245 rx = self.pg1.get_capture(1)
246
247 self.verify_ip(rx[0],
248 self.pg1.local_mac,
249 self.pg1.remote_hosts[2].mac,
250 self.pg0.remote_ip4,
251 self.pg1._remote_hosts[2].ip4)
252
253 self.pg0.add_stream(dyn_p)
254 self.pg_enable_capture(self.pg_interfaces)
255 self.pg_start()
256
257 rx = self.pg1.get_capture(1)
258 self.verify_arp_req(rx[0],
259 self.pg1.local_mac,
260 self.pg1.local_ip4,
261 self.pg1._remote_hosts[1].ip4)
262
263 #
264 # Send an ARP request from one of the so-far unlearned remote hosts
265 #
266 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
267 src=self.pg1._remote_hosts[3].mac) /
268 ARP(op="who-has",
269 hwsrc=self.pg1._remote_hosts[3].mac,
270 pdst=self.pg1.local_ip4,
271 psrc=self.pg1._remote_hosts[3].ip4))
272
273 self.pg1.add_stream(p)
274 self.pg_enable_capture(self.pg_interfaces)
275 self.pg_start()
276
277 rx = self.pg1.get_capture(1)
278 self.verify_arp_resp(rx[0],
279 self.pg1.local_mac,
280 self.pg1._remote_hosts[3].mac,
281 self.pg1.local_ip4,
282 self.pg1._remote_hosts[3].ip4)
283
284 #
285 # VPP should have learned the mapping for the remote host
286 #
287 self.assertTrue(find_nbr(self,
288 self.pg1.sw_if_index,
289 self.pg1._remote_hosts[3].ip4))
Neale Ranns4b919a52017-03-11 05:55:21 -0800290 #
291 # Fire in an ARP request before the interface becomes IP enabled
292 #
293 self.pg2.generate_remote_hosts(4)
294
295 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
296 ARP(op="who-has",
297 hwsrc=self.pg2.remote_mac,
298 pdst=self.pg1.local_ip4,
299 psrc=self.pg2.remote_hosts[3].ip4))
Neale Ranns30d0fd42017-05-30 07:30:04 -0700300 pt = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
301 Dot1Q(vlan=0) /
302 ARP(op="who-has",
303 hwsrc=self.pg2.remote_mac,
304 pdst=self.pg1.local_ip4,
305 psrc=self.pg2.remote_hosts[3].ip4))
Neale Ranns4b919a52017-03-11 05:55:21 -0800306 self.send_and_assert_no_replies(self.pg2, p,
307 "interface not IP enabled")
308
309 #
310 # Make pg2 un-numbered to pg1
311 #
312 self.pg2.set_unnumbered(self.pg1.sw_if_index)
313
Neale Rannsac3e72c2019-10-06 01:04:26 -0700314 #
315 # test the unnumbered dump both by all interfaces and just the enabled
316 # one
317 #
Neale Ranns404d88e2018-08-08 06:37:33 -0700318 unnum = self.vapi.ip_unnumbered_dump()
Neale Rannsac3e72c2019-10-06 01:04:26 -0700319 self.assertTrue(len(unnum))
320 self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
321 self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)
322 unnum = self.vapi.ip_unnumbered_dump(self.pg2.sw_if_index)
323 self.assertTrue(len(unnum))
Neale Ranns404d88e2018-08-08 06:37:33 -0700324 self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
325 self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)
326
Neale Ranns4b919a52017-03-11 05:55:21 -0800327 #
328 # We should respond to ARP requests for the unnumbered to address
329 # once an attached route to the source is known
330 #
331 self.send_and_assert_no_replies(
332 self.pg2, p,
333 "ARP req for unnumbered address - no source")
334
335 attached_host = VppIpRoute(self, self.pg2.remote_hosts[3].ip4, 32,
336 [VppRoutePath("0.0.0.0",
337 self.pg2.sw_if_index)])
338 attached_host.add_vpp_config()
339
340 self.pg2.add_stream(p)
341 self.pg_enable_capture(self.pg_interfaces)
342 self.pg_start()
343
344 rx = self.pg2.get_capture(1)
345 self.verify_arp_resp(rx[0],
346 self.pg2.local_mac,
347 self.pg2.remote_mac,
348 self.pg1.local_ip4,
349 self.pg2.remote_hosts[3].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800350
Neale Ranns30d0fd42017-05-30 07:30:04 -0700351 self.pg2.add_stream(pt)
352 self.pg_enable_capture(self.pg_interfaces)
353 self.pg_start()
354
355 rx = self.pg2.get_capture(1)
356 self.verify_arp_resp(rx[0],
357 self.pg2.local_mac,
358 self.pg2.remote_mac,
359 self.pg1.local_ip4,
360 self.pg2.remote_hosts[3].ip4)
361
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800362 #
Neale Ranns3983ac22017-03-10 11:53:27 -0800363 # A neighbor entry that has no associated FIB-entry
364 #
365 arp_no_fib = VppNeighbor(self,
366 self.pg1.sw_if_index,
367 self.pg1.remote_hosts[4].mac,
368 self.pg1.remote_hosts[4].ip4,
369 is_no_fib_entry=1)
370 arp_no_fib.add_vpp_config()
371
372 #
373 # check we have the neighbor, but no route
374 #
375 self.assertTrue(find_nbr(self,
376 self.pg1.sw_if_index,
377 self.pg1._remote_hosts[4].ip4))
378 self.assertFalse(find_route(self,
379 self.pg1._remote_hosts[4].ip4,
380 32))
381 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800382 # pg2 is unnumbered to pg1, so we can form adjacencies out of pg2
383 # from within pg1's subnet
Neale Ranns3983ac22017-03-10 11:53:27 -0800384 #
385 arp_unnum = VppNeighbor(self,
386 self.pg2.sw_if_index,
387 self.pg1.remote_hosts[5].mac,
388 self.pg1.remote_hosts[5].ip4)
389 arp_unnum.add_vpp_config()
390
391 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
392 IP(src=self.pg0.remote_ip4,
393 dst=self.pg1._remote_hosts[5].ip4) /
394 UDP(sport=1234, dport=1234) /
395 Raw())
396
397 self.pg0.add_stream(p)
398 self.pg_enable_capture(self.pg_interfaces)
399 self.pg_start()
400
401 rx = self.pg2.get_capture(1)
402
403 self.verify_ip(rx[0],
404 self.pg2.local_mac,
405 self.pg1.remote_hosts[5].mac,
406 self.pg0.remote_ip4,
407 self.pg1._remote_hosts[5].ip4)
408
409 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800410 # ARP requests from hosts in pg1's subnet sent on pg2 are replied to
411 # with the unnumbered interface's address as the source
412 #
413 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
414 ARP(op="who-has",
415 hwsrc=self.pg2.remote_mac,
416 pdst=self.pg1.local_ip4,
417 psrc=self.pg1.remote_hosts[6].ip4))
418
419 self.pg2.add_stream(p)
420 self.pg_enable_capture(self.pg_interfaces)
421 self.pg_start()
422
423 rx = self.pg2.get_capture(1)
424 self.verify_arp_resp(rx[0],
425 self.pg2.local_mac,
426 self.pg2.remote_mac,
427 self.pg1.local_ip4,
428 self.pg1.remote_hosts[6].ip4)
429
430 #
431 # An attached host route out of pg2 for an undiscovered hosts generates
432 # an ARP request with the unnumbered address as the source
433 #
434 att_unnum = VppIpRoute(self, self.pg1.remote_hosts[7].ip4, 32,
435 [VppRoutePath("0.0.0.0",
436 self.pg2.sw_if_index)])
437 att_unnum.add_vpp_config()
438
439 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
440 IP(src=self.pg0.remote_ip4,
441 dst=self.pg1._remote_hosts[7].ip4) /
442 UDP(sport=1234, dport=1234) /
443 Raw())
444
445 self.pg0.add_stream(p)
446 self.pg_enable_capture(self.pg_interfaces)
447 self.pg_start()
448
449 rx = self.pg2.get_capture(1)
450
451 self.verify_arp_req(rx[0],
452 self.pg2.local_mac,
453 self.pg1.local_ip4,
454 self.pg1._remote_hosts[7].ip4)
455
456 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
457 ARP(op="who-has",
458 hwsrc=self.pg2.remote_mac,
459 pdst=self.pg1.local_ip4,
460 psrc=self.pg1.remote_hosts[7].ip4))
461
462 self.pg2.add_stream(p)
463 self.pg_enable_capture(self.pg_interfaces)
464 self.pg_start()
465
466 rx = self.pg2.get_capture(1)
467 self.verify_arp_resp(rx[0],
468 self.pg2.local_mac,
469 self.pg2.remote_mac,
470 self.pg1.local_ip4,
471 self.pg1.remote_hosts[7].ip4)
472
473 #
474 # An attached host route as yet unresolved out of pg2 for an
475 # undiscovered host, an ARP requests begets a response.
476 #
477 att_unnum1 = VppIpRoute(self, self.pg1.remote_hosts[8].ip4, 32,
478 [VppRoutePath("0.0.0.0",
479 self.pg2.sw_if_index)])
480 att_unnum1.add_vpp_config()
481
482 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
483 ARP(op="who-has",
484 hwsrc=self.pg2.remote_mac,
485 pdst=self.pg1.local_ip4,
486 psrc=self.pg1.remote_hosts[8].ip4))
487
488 self.pg2.add_stream(p)
489 self.pg_enable_capture(self.pg_interfaces)
490 self.pg_start()
491
492 rx = self.pg2.get_capture(1)
493 self.verify_arp_resp(rx[0],
494 self.pg2.local_mac,
495 self.pg2.remote_mac,
496 self.pg1.local_ip4,
497 self.pg1.remote_hosts[8].ip4)
498
499 #
Neale Ranns30d0fd42017-05-30 07:30:04 -0700500 # Send an ARP request from one of the so-far unlearned remote hosts
501 # with a VLAN0 tag
502 #
503 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
504 src=self.pg1._remote_hosts[9].mac) /
505 Dot1Q(vlan=0) /
506 ARP(op="who-has",
507 hwsrc=self.pg1._remote_hosts[9].mac,
508 pdst=self.pg1.local_ip4,
509 psrc=self.pg1._remote_hosts[9].ip4))
510
511 self.pg1.add_stream(p)
512 self.pg_enable_capture(self.pg_interfaces)
513 self.pg_start()
514
515 rx = self.pg1.get_capture(1)
516 self.verify_arp_resp(rx[0],
517 self.pg1.local_mac,
518 self.pg1._remote_hosts[9].mac,
519 self.pg1.local_ip4,
520 self.pg1._remote_hosts[9].ip4)
521
522 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700523 # Add a hierarchy of routes for a host in the sub-net.
Neale Rannsca193612017-06-14 06:50:08 -0700524 # Should still get an ARP resp since the cover is attached
525 #
526 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_mac) /
527 ARP(op="who-has",
528 hwsrc=self.pg1.remote_mac,
529 pdst=self.pg1.local_ip4,
530 psrc=self.pg1.remote_hosts[10].ip4))
531
532 r1 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 30,
533 [VppRoutePath(self.pg1.remote_hosts[10].ip4,
534 self.pg1.sw_if_index)])
535 r1.add_vpp_config()
536
537 self.pg1.add_stream(p)
538 self.pg_enable_capture(self.pg_interfaces)
539 self.pg_start()
540 rx = self.pg1.get_capture(1)
541 self.verify_arp_resp(rx[0],
542 self.pg1.local_mac,
543 self.pg1.remote_mac,
544 self.pg1.local_ip4,
545 self.pg1.remote_hosts[10].ip4)
546
547 r2 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 32,
548 [VppRoutePath(self.pg1.remote_hosts[10].ip4,
549 self.pg1.sw_if_index)])
550 r2.add_vpp_config()
551
552 self.pg1.add_stream(p)
553 self.pg_enable_capture(self.pg_interfaces)
554 self.pg_start()
555 rx = self.pg1.get_capture(1)
556 self.verify_arp_resp(rx[0],
557 self.pg1.local_mac,
558 self.pg1.remote_mac,
559 self.pg1.local_ip4,
560 self.pg1.remote_hosts[10].ip4)
561
562 #
563 # add an ARP entry that's not on the sub-net and so whose
564 # adj-fib fails the refinement check. then send an ARP request
565 # from that source
566 #
567 a1 = VppNeighbor(self,
568 self.pg0.sw_if_index,
569 self.pg0.remote_mac,
570 "100.100.100.50")
571 a1.add_vpp_config()
572
573 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
574 ARP(op="who-has",
575 hwsrc=self.pg0.remote_mac,
576 psrc="100.100.100.50",
577 pdst=self.pg0.remote_ip4))
578 self.send_and_assert_no_replies(self.pg0, p,
579 "ARP req for from failed adj-fib")
580
581 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800582 # ERROR Cases
583 # 1 - don't respond to ARP request for address not within the
584 # interface's sub-net
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700585 # 1b - nor within the unnumbered subnet
586 # 1c - nor within the subnet of a different interface
587 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800588 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
589 ARP(op="who-has",
590 hwsrc=self.pg0.remote_mac,
591 pdst="10.10.10.3",
592 psrc=self.pg0.remote_ip4))
593 self.send_and_assert_no_replies(self.pg0, p,
594 "ARP req for non-local destination")
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700595 self.assertFalse(find_nbr(self,
596 self.pg0.sw_if_index,
597 "10.10.10.3"))
598
Neale Ranns4b919a52017-03-11 05:55:21 -0800599 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
600 ARP(op="who-has",
601 hwsrc=self.pg2.remote_mac,
602 pdst="10.10.10.3",
603 psrc=self.pg1.remote_hosts[7].ip4))
604 self.send_and_assert_no_replies(
605 self.pg0, p,
606 "ARP req for non-local destination - unnum")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800607
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700608 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
609 ARP(op="who-has",
610 hwsrc=self.pg0.remote_mac,
611 pdst=self.pg1.local_ip4,
612 psrc=self.pg1.remote_ip4))
613 self.send_and_assert_no_replies(self.pg0, p,
614 "ARP req diff sub-net")
615 self.assertFalse(find_nbr(self,
616 self.pg0.sw_if_index,
617 self.pg1.remote_ip4))
618
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800619 #
620 # 2 - don't respond to ARP request from an address not within the
621 # interface's sub-net
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700622 # 2b - to a proxied address
623 # 2c - not within a different interface's sub-net
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800624 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
625 ARP(op="who-has",
626 hwsrc=self.pg0.remote_mac,
627 psrc="10.10.10.3",
628 pdst=self.pg0.local_ip4))
629 self.send_and_assert_no_replies(self.pg0, p,
630 "ARP req for non-local source")
Neale Ranns4b919a52017-03-11 05:55:21 -0800631 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
632 ARP(op="who-has",
633 hwsrc=self.pg2.remote_mac,
634 psrc="10.10.10.3",
635 pdst=self.pg0.local_ip4))
636 self.send_and_assert_no_replies(
637 self.pg0, p,
638 "ARP req for non-local source - unnum")
Neale Rannsca193612017-06-14 06:50:08 -0700639 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
640 ARP(op="who-has",
641 hwsrc=self.pg0.remote_mac,
642 psrc=self.pg1.remote_ip4,
643 pdst=self.pg0.local_ip4))
644 self.send_and_assert_no_replies(self.pg0, p,
645 "ARP req for non-local source 2c")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800646
647 #
648 # 3 - don't respond to ARP request from an address that belongs to
649 # the router
650 #
651 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
652 ARP(op="who-has",
653 hwsrc=self.pg0.remote_mac,
654 psrc=self.pg0.local_ip4,
655 pdst=self.pg0.local_ip4))
656 self.send_and_assert_no_replies(self.pg0, p,
657 "ARP req for non-local source")
658
659 #
660 # 4 - don't respond to ARP requests that has mac source different
661 # from ARP request HW source
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800662 #
663 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
664 ARP(op="who-has",
665 hwsrc="00:00:00:DE:AD:BE",
666 psrc=self.pg0.remote_ip4,
667 pdst=self.pg0.local_ip4))
668 self.send_and_assert_no_replies(self.pg0, p,
669 "ARP req for non-local source")
670
671 #
zhaoqinglingb4c42cd2017-12-23 15:20:59 +0800672 # 5 - don't respond to ARP requests for address within the
673 # interface's sub-net but not the interface's address
674 #
675 self.pg0.generate_remote_hosts(2)
676 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
677 ARP(op="who-has",
678 hwsrc=self.pg0.remote_mac,
679 psrc=self.pg0.remote_hosts[0].ip4,
680 pdst=self.pg0.remote_hosts[1].ip4))
681 self.send_and_assert_no_replies(self.pg0, p,
682 "ARP req for non-local destination")
683
684 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800685 # cleanup
686 #
687 dyn_arp.remove_vpp_config()
688 static_arp.remove_vpp_config()
Neale Ranns3983ac22017-03-10 11:53:27 -0800689 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800690
Neale Ranns4b919a52017-03-11 05:55:21 -0800691 # need this to flush the adj-fibs
692 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
693 self.pg2.admin_down()
Neale Rannsca193612017-06-14 06:50:08 -0700694 self.pg1.admin_down()
Neale Ranns4b919a52017-03-11 05:55:21 -0800695
Neale Ranns24b170a2017-08-15 05:33:11 -0700696 def test_proxy_mirror_arp(self):
697 """ Interface Mirror Proxy ARP """
698
699 #
700 # When VPP has an interface whose address is also applied to a TAP
701 # interface on the host, then VPP's TAP interface will be unnumbered
702 # to the 'real' interface and do proxy ARP from the host.
703 # the curious aspect of this setup is that ARP requests from the host
704 # will come from the VPP's own address.
705 #
706 self.pg0.generate_remote_hosts(2)
707
708 arp_req_from_me = (Ether(src=self.pg2.remote_mac,
709 dst="ff:ff:ff:ff:ff:ff") /
710 ARP(op="who-has",
711 hwsrc=self.pg2.remote_mac,
712 pdst=self.pg0.remote_hosts[1].ip4,
713 psrc=self.pg0.local_ip4))
714
715 #
716 # Configure Proxy ARP for the subnet on PG0addresses on pg0
717 #
Neale Ranns37029302018-08-10 05:30:06 -0700718 self.vapi.proxy_arp_add_del(self.pg0._local_ip4_subnet,
719 self.pg0._local_ip4_bcast)
Neale Ranns24b170a2017-08-15 05:33:11 -0700720
721 # Make pg2 un-numbered to pg0
722 #
723 self.pg2.set_unnumbered(self.pg0.sw_if_index)
724
725 #
726 # Enable pg2 for proxy ARP
727 #
728 self.pg2.set_proxy_arp()
729
730 #
731 # Send the ARP request with an originating address that
732 # is VPP's own address
733 #
734 self.pg2.add_stream(arp_req_from_me)
735 self.pg_enable_capture(self.pg_interfaces)
736 self.pg_start()
737
738 rx = self.pg2.get_capture(1)
739 self.verify_arp_resp(rx[0],
740 self.pg2.local_mac,
741 self.pg2.remote_mac,
742 self.pg0.remote_hosts[1].ip4,
743 self.pg0.local_ip4)
744
745 #
746 # validate we have not learned an ARP entry as a result of this
747 #
748 self.assertFalse(find_nbr(self,
749 self.pg2.sw_if_index,
750 self.pg0.local_ip4))
751
752 #
753 # cleanup
754 #
755 self.pg2.set_proxy_arp(0)
Neale Ranns37029302018-08-10 05:30:06 -0700756 self.vapi.proxy_arp_add_del(self.pg0._local_ip4_subnet,
757 self.pg0._local_ip4_bcast,
Neale Ranns24b170a2017-08-15 05:33:11 -0700758 is_add=0)
759
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800760 def test_proxy_arp(self):
761 """ Proxy ARP """
762
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700763 self.pg1.generate_remote_hosts(2)
764
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800765 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700766 # Proxy ARP request packets for each interface
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800767 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800768 arp_req_pg0 = (Ether(src=self.pg0.remote_mac,
769 dst="ff:ff:ff:ff:ff:ff") /
770 ARP(op="who-has",
771 hwsrc=self.pg0.remote_mac,
772 pdst="10.10.10.3",
773 psrc=self.pg0.remote_ip4))
Neale Ranns30d0fd42017-05-30 07:30:04 -0700774 arp_req_pg0_tagged = (Ether(src=self.pg0.remote_mac,
775 dst="ff:ff:ff:ff:ff:ff") /
776 Dot1Q(vlan=0) /
777 ARP(op="who-has",
778 hwsrc=self.pg0.remote_mac,
779 pdst="10.10.10.3",
780 psrc=self.pg0.remote_ip4))
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800781 arp_req_pg1 = (Ether(src=self.pg1.remote_mac,
782 dst="ff:ff:ff:ff:ff:ff") /
783 ARP(op="who-has",
784 hwsrc=self.pg1.remote_mac,
785 pdst="10.10.10.3",
786 psrc=self.pg1.remote_ip4))
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700787 arp_req_pg2 = (Ether(src=self.pg2.remote_mac,
788 dst="ff:ff:ff:ff:ff:ff") /
789 ARP(op="who-has",
790 hwsrc=self.pg2.remote_mac,
791 pdst="10.10.10.3",
792 psrc=self.pg1.remote_hosts[1].ip4))
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800793 arp_req_pg3 = (Ether(src=self.pg3.remote_mac,
794 dst="ff:ff:ff:ff:ff:ff") /
795 ARP(op="who-has",
796 hwsrc=self.pg3.remote_mac,
797 pdst="10.10.10.3",
798 psrc=self.pg3.remote_ip4))
799
800 #
801 # Configure Proxy ARP for 10.10.10.0 -> 10.10.10.124
802 #
803 self.vapi.proxy_arp_add_del(inet_pton(AF_INET, "10.10.10.2"),
804 inet_pton(AF_INET, "10.10.10.124"))
805
806 #
807 # No responses are sent when the interfaces are not enabled for proxy
808 # ARP
809 #
810 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
811 "ARP req from unconfigured interface")
812 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
813 "ARP req from unconfigured interface")
814
815 #
816 # Make pg2 un-numbered to pg1
817 # still won't reply.
818 #
819 self.pg2.set_unnumbered(self.pg1.sw_if_index)
820
821 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
822 "ARP req from unnumbered interface")
823
824 #
825 # Enable each interface to reply to proxy ARPs
826 #
827 for i in self.pg_interfaces:
828 i.set_proxy_arp()
829
830 #
831 # Now each of the interfaces should reply to a request to a proxied
832 # address
833 #
834 self.pg0.add_stream(arp_req_pg0)
835 self.pg_enable_capture(self.pg_interfaces)
836 self.pg_start()
837
838 rx = self.pg0.get_capture(1)
839 self.verify_arp_resp(rx[0],
840 self.pg0.local_mac,
841 self.pg0.remote_mac,
842 "10.10.10.3",
843 self.pg0.remote_ip4)
844
Neale Ranns30d0fd42017-05-30 07:30:04 -0700845 self.pg0.add_stream(arp_req_pg0_tagged)
846 self.pg_enable_capture(self.pg_interfaces)
847 self.pg_start()
848
849 rx = self.pg0.get_capture(1)
850 self.verify_arp_resp(rx[0],
851 self.pg0.local_mac,
852 self.pg0.remote_mac,
853 "10.10.10.3",
854 self.pg0.remote_ip4)
855
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800856 self.pg1.add_stream(arp_req_pg1)
857 self.pg_enable_capture(self.pg_interfaces)
858 self.pg_start()
859
860 rx = self.pg1.get_capture(1)
861 self.verify_arp_resp(rx[0],
862 self.pg1.local_mac,
863 self.pg1.remote_mac,
864 "10.10.10.3",
865 self.pg1.remote_ip4)
866
867 self.pg2.add_stream(arp_req_pg2)
868 self.pg_enable_capture(self.pg_interfaces)
869 self.pg_start()
870
871 rx = self.pg2.get_capture(1)
872 self.verify_arp_resp(rx[0],
873 self.pg2.local_mac,
874 self.pg2.remote_mac,
875 "10.10.10.3",
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700876 self.pg1.remote_hosts[1].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800877
878 #
879 # A request for an address out of the configured range
880 #
881 arp_req_pg1_hi = (Ether(src=self.pg1.remote_mac,
882 dst="ff:ff:ff:ff:ff:ff") /
883 ARP(op="who-has",
884 hwsrc=self.pg1.remote_mac,
885 pdst="10.10.10.125",
886 psrc=self.pg1.remote_ip4))
887 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_hi,
888 "ARP req out of range HI")
889 arp_req_pg1_low = (Ether(src=self.pg1.remote_mac,
890 dst="ff:ff:ff:ff:ff:ff") /
891 ARP(op="who-has",
892 hwsrc=self.pg1.remote_mac,
893 pdst="10.10.10.1",
894 psrc=self.pg1.remote_ip4))
895 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_low,
896 "ARP req out of range Low")
897
898 #
899 # Request for an address in the proxy range but from an interface
900 # in a different VRF
901 #
902 self.send_and_assert_no_replies(self.pg3, arp_req_pg3,
903 "ARP req from different VRF")
904
905 #
906 # Disable Each interface for proxy ARP
907 # - expect none to respond
908 #
909 for i in self.pg_interfaces:
910 i.set_proxy_arp(0)
911
912 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
913 "ARP req from disable")
914 self.send_and_assert_no_replies(self.pg1, arp_req_pg1,
915 "ARP req from disable")
916 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
917 "ARP req from disable")
Neale Ranns37be7362017-02-21 17:30:26 -0800918
919 #
920 # clean up on interface 2
921 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800922 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns37be7362017-02-21 17:30:26 -0800923
924 def test_mpls(self):
925 """ MPLS """
926
927 #
928 # Interface 2 does not yet have ip4 config
929 #
930 self.pg2.config_ip4()
931 self.pg2.generate_remote_hosts(2)
932
933 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700934 # Add a route with out going label via an ARP unresolved next-hop
Neale Ranns37be7362017-02-21 17:30:26 -0800935 #
936 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
937 [VppRoutePath(self.pg2.remote_hosts[1].ip4,
938 self.pg2.sw_if_index,
939 labels=[55])])
940 ip_10_0_0_1.add_vpp_config()
941
942 #
943 # packets should generate an ARP request
944 #
945 p = (Ether(src=self.pg0.remote_mac,
946 dst=self.pg0.local_mac) /
947 IP(src=self.pg0.remote_ip4, dst="10.0.0.1") /
948 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +0100949 Raw(b'\xa5' * 100))
Neale Ranns37be7362017-02-21 17:30:26 -0800950
951 self.pg0.add_stream(p)
952 self.pg_enable_capture(self.pg_interfaces)
953 self.pg_start()
954
955 rx = self.pg2.get_capture(1)
956 self.verify_arp_req(rx[0],
957 self.pg2.local_mac,
958 self.pg2.local_ip4,
959 self.pg2._remote_hosts[1].ip4)
960
961 #
962 # now resolve the neighbours
963 #
964 self.pg2.configure_ipv4_neighbors()
965
966 #
967 # Now packet should be properly MPLS encapped.
968 # This verifies that MPLS link-type adjacencies are completed
969 # when the ARP entry resolves
970 #
971 self.pg0.add_stream(p)
972 self.pg_enable_capture(self.pg_interfaces)
973 self.pg_start()
974
975 rx = self.pg2.get_capture(1)
976 self.verify_ip_o_mpls(rx[0],
977 self.pg2.local_mac,
978 self.pg2.remote_hosts[1].mac,
979 55,
980 self.pg0.remote_ip4,
981 "10.0.0.1")
Neale Ranns4b919a52017-03-11 05:55:21 -0800982 self.pg2.unconfig_ip4()
Neale Ranns37be7362017-02-21 17:30:26 -0800983
Matthew Smithcb9ab472017-05-16 21:35:56 -0500984 def test_arp_vrrp(self):
985 """ ARP reply with VRRP virtual src hw addr """
986
987 #
988 # IP packet destined for pg1 remote host arrives on pg0 resulting
989 # in an ARP request for the address of the remote host on pg1
990 #
991 p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
992 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
993 UDP(sport=1234, dport=1234) /
994 Raw())
995
Neale Ranns37029302018-08-10 05:30:06 -0700996 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
Matthew Smithcb9ab472017-05-16 21:35:56 -0500997
998 self.verify_arp_req(rx1[0],
999 self.pg1.local_mac,
1000 self.pg1.local_ip4,
1001 self.pg1.remote_ip4)
1002
1003 #
1004 # ARP reply for address of pg1 remote host arrives on pg1 with
1005 # the hw src addr set to a value in the VRRP IPv4 range of
1006 # MAC addresses
1007 #
1008 p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1009 ARP(op="is-at", hwdst=self.pg1.local_mac,
1010 hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
1011 psrc=self.pg1.remote_ip4))
1012
Neale Ranns37029302018-08-10 05:30:06 -07001013 self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
Matthew Smithcb9ab472017-05-16 21:35:56 -05001014
1015 #
1016 # IP packet destined for pg1 remote host arrives on pg0 again.
1017 # VPP should have an ARP entry for that address now and the packet
1018 # should be sent out pg1.
1019 #
Neale Ranns37029302018-08-10 05:30:06 -07001020 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
Matthew Smithcb9ab472017-05-16 21:35:56 -05001021
1022 self.verify_ip(rx1[0],
1023 self.pg1.local_mac,
1024 "00:00:5e:00:01:09",
1025 self.pg0.remote_ip4,
1026 self.pg1.remote_ip4)
1027
1028 self.pg1.admin_down()
1029 self.pg1.admin_up()
1030
Neale Rannsdcd6d622017-05-26 02:59:16 -07001031 def test_arp_duplicates(self):
1032 """ ARP Duplicates"""
1033
1034 #
1035 # Generate some hosts on the LAN
1036 #
1037 self.pg1.generate_remote_hosts(3)
1038
1039 #
1040 # Add host 1 on pg1 and pg2
1041 #
1042 arp_pg1 = VppNeighbor(self,
1043 self.pg1.sw_if_index,
1044 self.pg1.remote_hosts[1].mac,
1045 self.pg1.remote_hosts[1].ip4)
1046 arp_pg1.add_vpp_config()
1047 arp_pg2 = VppNeighbor(self,
1048 self.pg2.sw_if_index,
1049 self.pg2.remote_mac,
1050 self.pg1.remote_hosts[1].ip4)
1051 arp_pg2.add_vpp_config()
1052
1053 #
1054 # IP packet destined for pg1 remote host arrives on pg1 again.
1055 #
1056 p = (Ether(dst=self.pg0.local_mac,
1057 src=self.pg0.remote_mac) /
1058 IP(src=self.pg0.remote_ip4,
1059 dst=self.pg1.remote_hosts[1].ip4) /
1060 UDP(sport=1234, dport=1234) /
1061 Raw())
1062
1063 self.pg0.add_stream(p)
1064 self.pg_enable_capture(self.pg_interfaces)
1065 self.pg_start()
1066
1067 rx1 = self.pg1.get_capture(1)
1068
1069 self.verify_ip(rx1[0],
1070 self.pg1.local_mac,
1071 self.pg1.remote_hosts[1].mac,
1072 self.pg0.remote_ip4,
1073 self.pg1.remote_hosts[1].ip4)
1074
1075 #
1076 # remove the duplicate on pg1
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001077 # packet stream should generate ARPs out of pg1
Neale Rannsdcd6d622017-05-26 02:59:16 -07001078 #
1079 arp_pg1.remove_vpp_config()
1080
1081 self.pg0.add_stream(p)
1082 self.pg_enable_capture(self.pg_interfaces)
1083 self.pg_start()
1084
1085 rx1 = self.pg1.get_capture(1)
1086
1087 self.verify_arp_req(rx1[0],
1088 self.pg1.local_mac,
1089 self.pg1.local_ip4,
1090 self.pg1.remote_hosts[1].ip4)
1091
1092 #
1093 # Add it back
1094 #
1095 arp_pg1.add_vpp_config()
1096
1097 self.pg0.add_stream(p)
1098 self.pg_enable_capture(self.pg_interfaces)
1099 self.pg_start()
1100
1101 rx1 = self.pg1.get_capture(1)
1102
1103 self.verify_ip(rx1[0],
1104 self.pg1.local_mac,
1105 self.pg1.remote_hosts[1].mac,
1106 self.pg0.remote_ip4,
1107 self.pg1.remote_hosts[1].ip4)
1108
Neale Ranns15002542017-09-10 04:39:11 -07001109 def test_arp_static(self):
1110 """ ARP Static"""
1111 self.pg2.generate_remote_hosts(3)
1112
1113 #
1114 # Add a static ARP entry
1115 #
1116 static_arp = VppNeighbor(self,
1117 self.pg2.sw_if_index,
1118 self.pg2.remote_hosts[1].mac,
1119 self.pg2.remote_hosts[1].ip4,
1120 is_static=1)
1121 static_arp.add_vpp_config()
1122
1123 #
1124 # Add the connected prefix to the interface
1125 #
1126 self.pg2.config_ip4()
1127
1128 #
1129 # We should now find the adj-fib
1130 #
1131 self.assertTrue(find_nbr(self,
1132 self.pg2.sw_if_index,
1133 self.pg2.remote_hosts[1].ip4,
1134 is_static=1))
1135 self.assertTrue(find_route(self,
1136 self.pg2.remote_hosts[1].ip4,
1137 32))
1138
1139 #
1140 # remove the connected
1141 #
1142 self.pg2.unconfig_ip4()
1143
1144 #
1145 # put the interface into table 1
1146 #
1147 self.pg2.set_table_ip4(1)
1148
1149 #
1150 # configure the same connected and expect to find the
1151 # adj fib in the new table
1152 #
1153 self.pg2.config_ip4()
1154 self.assertTrue(find_route(self,
1155 self.pg2.remote_hosts[1].ip4,
1156 32,
1157 table_id=1))
1158
1159 #
1160 # clean-up
1161 #
1162 self.pg2.unconfig_ip4()
1163 self.pg2.set_table_ip4(0)
1164
Neale Rannsc819fc62018-02-16 02:44:05 -08001165 def test_arp_incomplete(self):
1166 """ ARP Incomplete"""
1167 self.pg1.generate_remote_hosts(3)
1168
1169 p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1170 IP(src=self.pg0.remote_ip4,
1171 dst=self.pg1.remote_hosts[1].ip4) /
1172 UDP(sport=1234, dport=1234) /
1173 Raw())
1174 p1 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1175 IP(src=self.pg0.remote_ip4,
1176 dst=self.pg1.remote_hosts[2].ip4) /
1177 UDP(sport=1234, dport=1234) /
1178 Raw())
1179
1180 #
1181 # a packet to an unresolved destination generates an ARP request
1182 #
1183 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1184 self.verify_arp_req(rx[0],
1185 self.pg1.local_mac,
1186 self.pg1.local_ip4,
1187 self.pg1._remote_hosts[1].ip4)
1188
1189 #
1190 # add a neighbour for remote host 1
1191 #
1192 static_arp = VppNeighbor(self,
1193 self.pg1.sw_if_index,
1194 self.pg1.remote_hosts[1].mac,
1195 self.pg1.remote_hosts[1].ip4,
1196 is_static=1)
1197 static_arp.add_vpp_config()
1198
1199 #
1200 # change the interface's MAC
1201 #
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001202 mac = [scapy.compat.chb(0x00), scapy.compat.chb(0x00),
1203 scapy.compat.chb(0x00), scapy.compat.chb(0x33),
1204 scapy.compat.chb(0x33), scapy.compat.chb(0x33)]
Neale Rannsc819fc62018-02-16 02:44:05 -08001205 mac_string = ''.join(mac)
1206
1207 self.vapi.sw_interface_set_mac_address(self.pg1.sw_if_index,
1208 mac_string)
1209
1210 #
1211 # now ARP requests come from the new source mac
1212 #
1213 rx = self.send_and_expect(self.pg0, [p1], self.pg1)
1214 self.verify_arp_req(rx[0],
1215 "00:00:00:33:33:33",
1216 self.pg1.local_ip4,
1217 self.pg1._remote_hosts[2].ip4)
1218
1219 #
1220 # packets to the resolved host also have the new source mac
1221 #
1222 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1223 self.verify_ip(rx[0],
1224 "00:00:00:33:33:33",
1225 self.pg1.remote_hosts[1].mac,
1226 self.pg0.remote_ip4,
1227 self.pg1.remote_hosts[1].ip4)
1228
1229 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001230 # set the mac address on the interface that does not have a
Neale Rannsc819fc62018-02-16 02:44:05 -08001231 # configured subnet and thus no glean
1232 #
1233 self.vapi.sw_interface_set_mac_address(self.pg2.sw_if_index,
1234 mac_string)
1235
Neale Ranns59ae61e2018-06-07 18:09:49 -07001236 def test_garp(self):
1237 """ GARP """
1238
1239 #
1240 # Generate some hosts on the LAN
1241 #
1242 self.pg1.generate_remote_hosts(4)
1243
1244 #
1245 # And an ARP entry
1246 #
1247 arp = VppNeighbor(self,
1248 self.pg1.sw_if_index,
1249 self.pg1.remote_hosts[1].mac,
1250 self.pg1.remote_hosts[1].ip4)
1251 arp.add_vpp_config()
1252
1253 self.assertTrue(find_nbr(self,
1254 self.pg1.sw_if_index,
1255 self.pg1.remote_hosts[1].ip4,
1256 mac=self.pg1.remote_hosts[1].mac))
1257
1258 #
1259 # Send a GARP (request) to swap the host 1's address to that of host 2
1260 #
1261 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1262 src=self.pg1.remote_hosts[2].mac) /
1263 ARP(op="who-has",
1264 hwdst=self.pg1.local_mac,
1265 hwsrc=self.pg1.remote_hosts[2].mac,
1266 pdst=self.pg1.remote_hosts[1].ip4,
1267 psrc=self.pg1.remote_hosts[1].ip4))
1268
1269 self.pg1.add_stream(p1)
1270 self.pg_enable_capture(self.pg_interfaces)
1271 self.pg_start()
1272
1273 self.assertTrue(find_nbr(self,
1274 self.pg1.sw_if_index,
1275 self.pg1.remote_hosts[1].ip4,
1276 mac=self.pg1.remote_hosts[2].mac))
1277
1278 #
1279 # Send a GARP (reply) to swap the host 1's address to that of host 3
1280 #
1281 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1282 src=self.pg1.remote_hosts[3].mac) /
1283 ARP(op="is-at",
1284 hwdst=self.pg1.local_mac,
1285 hwsrc=self.pg1.remote_hosts[3].mac,
1286 pdst=self.pg1.remote_hosts[1].ip4,
1287 psrc=self.pg1.remote_hosts[1].ip4))
1288
1289 self.pg1.add_stream(p1)
1290 self.pg_enable_capture(self.pg_interfaces)
1291 self.pg_start()
1292
1293 self.assertTrue(find_nbr(self,
1294 self.pg1.sw_if_index,
1295 self.pg1.remote_hosts[1].ip4,
1296 mac=self.pg1.remote_hosts[3].mac))
1297
1298 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001299 # GARPs (request nor replies) for host we don't know yet
Neale Ranns59ae61e2018-06-07 18:09:49 -07001300 # don't result in new neighbour entries
1301 #
1302 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1303 src=self.pg1.remote_hosts[3].mac) /
1304 ARP(op="who-has",
1305 hwdst=self.pg1.local_mac,
1306 hwsrc=self.pg1.remote_hosts[3].mac,
1307 pdst=self.pg1.remote_hosts[2].ip4,
1308 psrc=self.pg1.remote_hosts[2].ip4))
1309
1310 self.pg1.add_stream(p1)
1311 self.pg_enable_capture(self.pg_interfaces)
1312 self.pg_start()
1313
1314 self.assertFalse(find_nbr(self,
1315 self.pg1.sw_if_index,
1316 self.pg1.remote_hosts[2].ip4))
1317
1318 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1319 src=self.pg1.remote_hosts[3].mac) /
1320 ARP(op="is-at",
1321 hwdst=self.pg1.local_mac,
1322 hwsrc=self.pg1.remote_hosts[3].mac,
1323 pdst=self.pg1.remote_hosts[2].ip4,
1324 psrc=self.pg1.remote_hosts[2].ip4))
1325
1326 self.pg1.add_stream(p1)
1327 self.pg_enable_capture(self.pg_interfaces)
1328 self.pg_start()
1329
1330 self.assertFalse(find_nbr(self,
1331 self.pg1.sw_if_index,
1332 self.pg1.remote_hosts[2].ip4))
1333
Neale Rannsc8352bc2018-08-29 10:23:58 -07001334 def test_arp_incomplete(self):
Neale Ranns14260392018-09-28 05:00:57 -07001335 """ Incomplete Entries """
Neale Rannsc8352bc2018-08-29 10:23:58 -07001336
1337 #
Neale Rannscd35e532018-08-31 02:51:45 -07001338 # ensure that we throttle the ARP and ND requests
Neale Rannsc8352bc2018-08-29 10:23:58 -07001339 #
1340 self.pg0.generate_remote_hosts(2)
1341
Neale Rannscd35e532018-08-31 02:51:45 -07001342 #
1343 # IPv4/ARP
1344 #
Neale Rannsc8352bc2018-08-29 10:23:58 -07001345 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1346 [VppRoutePath(self.pg0.remote_hosts[1].ip4,
Neale Rannscd35e532018-08-31 02:51:45 -07001347 self.pg0.sw_if_index)])
Neale Rannsc8352bc2018-08-29 10:23:58 -07001348 ip_10_0_0_1.add_vpp_config()
1349
1350 p1 = (Ether(dst=self.pg1.local_mac,
1351 src=self.pg1.remote_mac) /
1352 IP(src=self.pg1.remote_ip4,
1353 dst="10.0.0.1") /
1354 UDP(sport=1234, dport=1234) /
1355 Raw())
1356
1357 self.pg1.add_stream(p1 * 257)
1358 self.pg_enable_capture(self.pg_interfaces)
1359 self.pg_start()
1360 rx = self.pg0._get_capture(1)
1361
1362 #
1363 # how many we get is going to be dependent on the time for packet
1364 # processing but it should be small
1365 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001366 self.assertLess(len(rx), 64)
Neale Rannsc8352bc2018-08-29 10:23:58 -07001367
Neale Rannscd35e532018-08-31 02:51:45 -07001368 #
1369 # IPv6/ND
1370 #
1371 ip_10_1 = VppIpRoute(self, "10::1", 128,
1372 [VppRoutePath(self.pg0.remote_hosts[1].ip6,
1373 self.pg0.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07001374 proto=DpoProto.DPO_PROTO_IP6)])
Neale Rannscd35e532018-08-31 02:51:45 -07001375 ip_10_1.add_vpp_config()
1376
1377 p1 = (Ether(dst=self.pg1.local_mac,
1378 src=self.pg1.remote_mac) /
1379 IPv6(src=self.pg1.remote_ip6,
1380 dst="10::1") /
1381 UDP(sport=1234, dport=1234) /
1382 Raw())
1383
1384 self.pg1.add_stream(p1 * 257)
1385 self.pg_enable_capture(self.pg_interfaces)
1386 self.pg_start()
1387 rx = self.pg0._get_capture(1)
1388
1389 #
1390 # how many we get is going to be dependent on the time for packet
1391 # processing but it should be small
1392 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001393 self.assertLess(len(rx), 64)
Neale Rannscd35e532018-08-31 02:51:45 -07001394
Neale Ranns7425f922019-01-23 00:36:16 -08001395 def test_arp_forus(self):
1396 """ ARP for for-us """
1397
1398 #
1399 # Test that VPP responds with ARP requests to addresses that
1400 # are connected and local routes.
1401 # Use one of the 'remote' addresses in the subnet as a local address
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001402 # The intention of this route is that it then acts like a secondary
Neale Ranns7425f922019-01-23 00:36:16 -08001403 # address added to an interface
1404 #
1405 self.pg0.generate_remote_hosts(2)
1406
Neale Ranns097fa662018-05-01 05:17:55 -07001407 forus = VppIpRoute(
1408 self, self.pg0.remote_hosts[1].ip4, 32,
1409 [VppRoutePath("0.0.0.0",
1410 self.pg0.sw_if_index,
1411 type=FibPathType.FIB_PATH_TYPE_LOCAL)])
Neale Ranns7425f922019-01-23 00:36:16 -08001412 forus.add_vpp_config()
1413
1414 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
1415 src=self.pg0.remote_mac) /
1416 ARP(op="who-has",
1417 hwdst=self.pg0.local_mac,
1418 hwsrc=self.pg0.remote_mac,
1419 pdst=self.pg0.remote_hosts[1].ip4,
1420 psrc=self.pg0.remote_ip4))
1421
1422 rx = self.send_and_expect(self.pg0, [p], self.pg0)
1423
1424 self.verify_arp_resp(rx[0],
1425 self.pg0.local_mac,
1426 self.pg0.remote_mac,
1427 self.pg0.remote_hosts[1].ip4,
1428 self.pg0.remote_ip4)
1429
Neale Rannsdcd6d622017-05-26 02:59:16 -07001430
Neale Ranns14260392018-09-28 05:00:57 -07001431class NeighborStatsTestCase(VppTestCase):
Neale Ranns37029302018-08-10 05:30:06 -07001432 """ ARP/ND Counters """
Neale Ranns14260392018-09-28 05:00:57 -07001433
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001434 @classmethod
1435 def setUpClass(cls):
1436 super(NeighborStatsTestCase, cls).setUpClass()
1437
1438 @classmethod
1439 def tearDownClass(cls):
1440 super(NeighborStatsTestCase, cls).tearDownClass()
1441
Neale Ranns14260392018-09-28 05:00:57 -07001442 def setUp(self):
1443 super(NeighborStatsTestCase, self).setUp()
1444
1445 self.create_pg_interfaces(range(2))
1446
1447 # pg0 configured with ip4 and 6 addresses used for input
1448 # pg1 configured with ip4 and 6 addresses used for output
1449 # pg2 is unnumbered to pg0
1450 for i in self.pg_interfaces:
1451 i.admin_up()
1452 i.config_ip4()
1453 i.config_ip6()
1454 i.resolve_arp()
1455 i.resolve_ndp()
1456
1457 def tearDown(self):
1458 super(NeighborStatsTestCase, self).tearDown()
1459
1460 for i in self.pg_interfaces:
1461 i.unconfig_ip4()
1462 i.unconfig_ip6()
1463 i.admin_down()
1464
1465 def test_arp_stats(self):
1466 """ ARP Counters """
1467
1468 self.vapi.cli("adj counters enable")
1469 self.pg1.generate_remote_hosts(2)
1470
1471 arp1 = VppNeighbor(self,
1472 self.pg1.sw_if_index,
1473 self.pg1.remote_hosts[0].mac,
1474 self.pg1.remote_hosts[0].ip4)
1475 arp1.add_vpp_config()
1476 arp2 = VppNeighbor(self,
1477 self.pg1.sw_if_index,
1478 self.pg1.remote_hosts[1].mac,
1479 self.pg1.remote_hosts[1].ip4)
1480 arp2.add_vpp_config()
1481
1482 p1 = (Ether(dst=self.pg0.local_mac,
1483 src=self.pg0.remote_mac) /
1484 IP(src=self.pg0.remote_ip4,
1485 dst=self.pg1.remote_hosts[0].ip4) /
1486 UDP(sport=1234, dport=1234) /
1487 Raw())
1488 p2 = (Ether(dst=self.pg0.local_mac,
1489 src=self.pg0.remote_mac) /
1490 IP(src=self.pg0.remote_ip4,
1491 dst=self.pg1.remote_hosts[1].ip4) /
1492 UDP(sport=1234, dport=1234) /
1493 Raw())
1494
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001495 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
1496 rx = self.send_and_expect(self.pg0, p2 * NUM_PKTS, self.pg1)
Neale Ranns14260392018-09-28 05:00:57 -07001497
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001498 self.assertEqual(NUM_PKTS, arp1.get_stats()['packets'])
1499 self.assertEqual(NUM_PKTS, arp2.get_stats()['packets'])
Neale Ranns14260392018-09-28 05:00:57 -07001500
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001501 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
1502 self.assertEqual(NUM_PKTS*2, arp1.get_stats()['packets'])
Neale Ranns14260392018-09-28 05:00:57 -07001503
1504 def test_nd_stats(self):
1505 """ ND Counters """
1506
1507 self.vapi.cli("adj counters enable")
1508 self.pg0.generate_remote_hosts(3)
1509
1510 nd1 = VppNeighbor(self,
1511 self.pg0.sw_if_index,
1512 self.pg0.remote_hosts[1].mac,
Neale Ranns37029302018-08-10 05:30:06 -07001513 self.pg0.remote_hosts[1].ip6)
Neale Ranns14260392018-09-28 05:00:57 -07001514 nd1.add_vpp_config()
1515 nd2 = VppNeighbor(self,
1516 self.pg0.sw_if_index,
1517 self.pg0.remote_hosts[2].mac,
Neale Ranns37029302018-08-10 05:30:06 -07001518 self.pg0.remote_hosts[2].ip6)
Neale Ranns14260392018-09-28 05:00:57 -07001519 nd2.add_vpp_config()
1520
1521 p1 = (Ether(dst=self.pg1.local_mac,
1522 src=self.pg1.remote_mac) /
1523 IPv6(src=self.pg1.remote_ip6,
1524 dst=self.pg0.remote_hosts[1].ip6) /
1525 UDP(sport=1234, dport=1234) /
1526 Raw())
1527 p2 = (Ether(dst=self.pg1.local_mac,
1528 src=self.pg1.remote_mac) /
1529 IPv6(src=self.pg1.remote_ip6,
1530 dst=self.pg0.remote_hosts[2].ip6) /
1531 UDP(sport=1234, dport=1234) /
1532 Raw())
1533
1534 rx = self.send_and_expect(self.pg1, p1 * 16, self.pg0)
1535 rx = self.send_and_expect(self.pg1, p2 * 16, self.pg0)
1536
1537 self.assertEqual(16, nd1.get_stats()['packets'])
1538 self.assertEqual(16, nd2.get_stats()['packets'])
1539
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001540 rx = self.send_and_expect(self.pg1, p1 * NUM_PKTS, self.pg0)
1541 self.assertEqual(NUM_PKTS+16, nd1.get_stats()['packets'])
Neale Ranns14260392018-09-28 05:00:57 -07001542
1543
Neale Ranns37be7362017-02-21 17:30:26 -08001544if __name__ == '__main__':
1545 unittest.main(testRunner=VppTestRunner)