blob: c6d9fc61815b54ba6c6f24ad83badabb10e8c619 [file] [log] [blame]
Neale Ranns39f9d8b2017-02-16 21:57:05 -08001#!/usr/bin/env python
2
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 Rannscd35e532018-08-31 02:51:45 -07009 VppIpTable, DpoProto
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
20# not exported by scapy, so redefined here
21arp_opts = {"who-has": 1, "is-at": 2}
22
23
24class ARPTestCase(VppTestCase):
25 """ ARP Test Case """
26
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070027 @classmethod
28 def setUpClass(cls):
29 super(ARPTestCase, cls).setUpClass()
30
31 @classmethod
32 def tearDownClass(cls):
33 super(ARPTestCase, cls).tearDownClass()
34
Neale Ranns39f9d8b2017-02-16 21:57:05 -080035 def setUp(self):
36 super(ARPTestCase, self).setUp()
37
38 # create 3 pg interfaces
39 self.create_pg_interfaces(range(4))
40
41 # pg0 configured with ip4 and 6 addresses used for input
42 # pg1 configured with ip4 and 6 addresses used for output
43 # pg2 is unnumbered to pg0
44 for i in self.pg_interfaces:
45 i.admin_up()
46
47 self.pg0.config_ip4()
48 self.pg0.config_ip6()
49 self.pg0.resolve_arp()
50
51 self.pg1.config_ip4()
52 self.pg1.config_ip6()
53
54 # pg3 in a different VRF
Neale Ranns15002542017-09-10 04:39:11 -070055 self.tbl = VppIpTable(self, 1)
56 self.tbl.add_vpp_config()
57
Neale Ranns39f9d8b2017-02-16 21:57:05 -080058 self.pg3.set_table_ip4(1)
59 self.pg3.config_ip4()
60
Neale Ranns4008ac92017-02-13 23:20:04 -080061 def tearDown(self):
Neale Ranns4b919a52017-03-11 05:55:21 -080062 self.pg0.unconfig_ip4()
63 self.pg0.unconfig_ip6()
64
65 self.pg1.unconfig_ip4()
66 self.pg1.unconfig_ip6()
67
68 self.pg3.unconfig_ip4()
Neale Ranns15002542017-09-10 04:39:11 -070069 self.pg3.set_table_ip4(0)
Neale Ranns4b919a52017-03-11 05:55:21 -080070
Neale Ranns4008ac92017-02-13 23:20:04 -080071 for i in self.pg_interfaces:
Neale Ranns4008ac92017-02-13 23:20:04 -080072 i.admin_down()
73
Neale Ranns15002542017-09-10 04:39:11 -070074 super(ARPTestCase, self).tearDown()
75
Neale Ranns39f9d8b2017-02-16 21:57:05 -080076 def verify_arp_req(self, rx, smac, sip, dip):
77 ether = rx[Ether]
78 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
79 self.assertEqual(ether.src, smac)
80
81 arp = rx[ARP]
82 self.assertEqual(arp.hwtype, 1)
83 self.assertEqual(arp.ptype, 0x800)
84 self.assertEqual(arp.hwlen, 6)
85 self.assertEqual(arp.plen, 4)
86 self.assertEqual(arp.op, arp_opts["who-has"])
87 self.assertEqual(arp.hwsrc, smac)
88 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
89 self.assertEqual(arp.psrc, sip)
90 self.assertEqual(arp.pdst, dip)
91
92 def verify_arp_resp(self, rx, smac, dmac, sip, dip):
93 ether = rx[Ether]
94 self.assertEqual(ether.dst, dmac)
95 self.assertEqual(ether.src, smac)
96
97 arp = rx[ARP]
98 self.assertEqual(arp.hwtype, 1)
99 self.assertEqual(arp.ptype, 0x800)
100 self.assertEqual(arp.hwlen, 6)
101 self.assertEqual(arp.plen, 4)
102 self.assertEqual(arp.op, arp_opts["is-at"])
103 self.assertEqual(arp.hwsrc, smac)
104 self.assertEqual(arp.hwdst, dmac)
105 self.assertEqual(arp.psrc, sip)
106 self.assertEqual(arp.pdst, dip)
107
Matthew Smithcb9ab472017-05-16 21:35:56 -0500108 def verify_arp_vrrp_resp(self, rx, smac, dmac, sip, dip):
109 ether = rx[Ether]
110 self.assertEqual(ether.dst, dmac)
111 self.assertEqual(ether.src, smac)
112
113 arp = rx[ARP]
114 self.assertEqual(arp.hwtype, 1)
115 self.assertEqual(arp.ptype, 0x800)
116 self.assertEqual(arp.hwlen, 6)
117 self.assertEqual(arp.plen, 4)
118 self.assertEqual(arp.op, arp_opts["is-at"])
119 self.assertNotEqual(arp.hwsrc, smac)
120 self.assertTrue("00:00:5e:00:01" in arp.hwsrc or
121 "00:00:5E:00:01" in arp.hwsrc)
122 self.assertEqual(arp.hwdst, dmac)
123 self.assertEqual(arp.psrc, sip)
124 self.assertEqual(arp.pdst, dip)
125
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800126 def verify_ip(self, rx, smac, dmac, sip, dip):
127 ether = rx[Ether]
128 self.assertEqual(ether.dst, dmac)
129 self.assertEqual(ether.src, smac)
130
131 ip = rx[IP]
132 self.assertEqual(ip.src, sip)
133 self.assertEqual(ip.dst, dip)
134
Neale Ranns37be7362017-02-21 17:30:26 -0800135 def verify_ip_o_mpls(self, rx, smac, dmac, label, sip, dip):
136 ether = rx[Ether]
137 self.assertEqual(ether.dst, dmac)
138 self.assertEqual(ether.src, smac)
139
140 mpls = rx[MPLS]
141 self.assertTrue(mpls.label, label)
142
143 ip = rx[IP]
144 self.assertEqual(ip.src, sip)
145 self.assertEqual(ip.dst, dip)
146
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800147 def test_arp(self):
148 """ ARP """
149
150 #
151 # Generate some hosts on the LAN
152 #
Neale Rannsca193612017-06-14 06:50:08 -0700153 self.pg1.generate_remote_hosts(11)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800154
155 #
156 # Send IP traffic to one of these unresolved hosts.
157 # expect the generation of an ARP request
158 #
159 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
160 IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[1].ip4) /
161 UDP(sport=1234, dport=1234) /
162 Raw())
163
164 self.pg0.add_stream(p)
165 self.pg_enable_capture(self.pg_interfaces)
166 self.pg_start()
167
168 rx = self.pg1.get_capture(1)
169
170 self.verify_arp_req(rx[0],
171 self.pg1.local_mac,
172 self.pg1.local_ip4,
173 self.pg1._remote_hosts[1].ip4)
174
175 #
176 # And a dynamic ARP entry for host 1
177 #
178 dyn_arp = VppNeighbor(self,
179 self.pg1.sw_if_index,
180 self.pg1.remote_hosts[1].mac,
181 self.pg1.remote_hosts[1].ip4)
182 dyn_arp.add_vpp_config()
183
184 #
185 # now we expect IP traffic forwarded
186 #
187 dyn_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
188 IP(src=self.pg0.remote_ip4,
189 dst=self.pg1._remote_hosts[1].ip4) /
190 UDP(sport=1234, dport=1234) /
191 Raw())
192
193 self.pg0.add_stream(dyn_p)
194 self.pg_enable_capture(self.pg_interfaces)
195 self.pg_start()
196
197 rx = self.pg1.get_capture(1)
198
199 self.verify_ip(rx[0],
200 self.pg1.local_mac,
201 self.pg1.remote_hosts[1].mac,
202 self.pg0.remote_ip4,
203 self.pg1._remote_hosts[1].ip4)
204
205 #
206 # And a Static ARP entry for host 2
207 #
208 static_arp = VppNeighbor(self,
209 self.pg1.sw_if_index,
210 self.pg1.remote_hosts[2].mac,
211 self.pg1.remote_hosts[2].ip4,
212 is_static=1)
213 static_arp.add_vpp_config()
214
215 static_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
216 IP(src=self.pg0.remote_ip4,
217 dst=self.pg1._remote_hosts[2].ip4) /
218 UDP(sport=1234, dport=1234) /
219 Raw())
220
221 self.pg0.add_stream(static_p)
222 self.pg_enable_capture(self.pg_interfaces)
223 self.pg_start()
224
225 rx = self.pg1.get_capture(1)
226
227 self.verify_ip(rx[0],
228 self.pg1.local_mac,
229 self.pg1.remote_hosts[2].mac,
230 self.pg0.remote_ip4,
231 self.pg1._remote_hosts[2].ip4)
232
233 #
234 # flap the link. dynamic ARPs get flush, statics don't
235 #
236 self.pg1.admin_down()
237 self.pg1.admin_up()
238
239 self.pg0.add_stream(static_p)
240 self.pg_enable_capture(self.pg_interfaces)
241 self.pg_start()
242 rx = self.pg1.get_capture(1)
243
244 self.verify_ip(rx[0],
245 self.pg1.local_mac,
246 self.pg1.remote_hosts[2].mac,
247 self.pg0.remote_ip4,
248 self.pg1._remote_hosts[2].ip4)
249
250 self.pg0.add_stream(dyn_p)
251 self.pg_enable_capture(self.pg_interfaces)
252 self.pg_start()
253
254 rx = self.pg1.get_capture(1)
255 self.verify_arp_req(rx[0],
256 self.pg1.local_mac,
257 self.pg1.local_ip4,
258 self.pg1._remote_hosts[1].ip4)
259
260 #
261 # Send an ARP request from one of the so-far unlearned remote hosts
262 #
263 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
264 src=self.pg1._remote_hosts[3].mac) /
265 ARP(op="who-has",
266 hwsrc=self.pg1._remote_hosts[3].mac,
267 pdst=self.pg1.local_ip4,
268 psrc=self.pg1._remote_hosts[3].ip4))
269
270 self.pg1.add_stream(p)
271 self.pg_enable_capture(self.pg_interfaces)
272 self.pg_start()
273
274 rx = self.pg1.get_capture(1)
275 self.verify_arp_resp(rx[0],
276 self.pg1.local_mac,
277 self.pg1._remote_hosts[3].mac,
278 self.pg1.local_ip4,
279 self.pg1._remote_hosts[3].ip4)
280
281 #
282 # VPP should have learned the mapping for the remote host
283 #
284 self.assertTrue(find_nbr(self,
285 self.pg1.sw_if_index,
286 self.pg1._remote_hosts[3].ip4))
Neale Ranns4b919a52017-03-11 05:55:21 -0800287 #
288 # Fire in an ARP request before the interface becomes IP enabled
289 #
290 self.pg2.generate_remote_hosts(4)
291
292 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
293 ARP(op="who-has",
294 hwsrc=self.pg2.remote_mac,
295 pdst=self.pg1.local_ip4,
296 psrc=self.pg2.remote_hosts[3].ip4))
Neale Ranns30d0fd42017-05-30 07:30:04 -0700297 pt = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
298 Dot1Q(vlan=0) /
299 ARP(op="who-has",
300 hwsrc=self.pg2.remote_mac,
301 pdst=self.pg1.local_ip4,
302 psrc=self.pg2.remote_hosts[3].ip4))
Neale Ranns4b919a52017-03-11 05:55:21 -0800303 self.send_and_assert_no_replies(self.pg2, p,
304 "interface not IP enabled")
305
306 #
307 # Make pg2 un-numbered to pg1
308 #
309 self.pg2.set_unnumbered(self.pg1.sw_if_index)
310
Neale Ranns404d88e2018-08-08 06:37:33 -0700311 unnum = self.vapi.ip_unnumbered_dump()
312 self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
313 self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)
314
Neale Ranns4b919a52017-03-11 05:55:21 -0800315 #
316 # We should respond to ARP requests for the unnumbered to address
317 # once an attached route to the source is known
318 #
319 self.send_and_assert_no_replies(
320 self.pg2, p,
321 "ARP req for unnumbered address - no source")
322
323 attached_host = VppIpRoute(self, self.pg2.remote_hosts[3].ip4, 32,
324 [VppRoutePath("0.0.0.0",
325 self.pg2.sw_if_index)])
326 attached_host.add_vpp_config()
327
328 self.pg2.add_stream(p)
329 self.pg_enable_capture(self.pg_interfaces)
330 self.pg_start()
331
332 rx = self.pg2.get_capture(1)
333 self.verify_arp_resp(rx[0],
334 self.pg2.local_mac,
335 self.pg2.remote_mac,
336 self.pg1.local_ip4,
337 self.pg2.remote_hosts[3].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800338
Neale Ranns30d0fd42017-05-30 07:30:04 -0700339 self.pg2.add_stream(pt)
340 self.pg_enable_capture(self.pg_interfaces)
341 self.pg_start()
342
343 rx = self.pg2.get_capture(1)
344 self.verify_arp_resp(rx[0],
345 self.pg2.local_mac,
346 self.pg2.remote_mac,
347 self.pg1.local_ip4,
348 self.pg2.remote_hosts[3].ip4)
349
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800350 #
Neale Ranns3983ac22017-03-10 11:53:27 -0800351 # A neighbor entry that has no associated FIB-entry
352 #
353 arp_no_fib = VppNeighbor(self,
354 self.pg1.sw_if_index,
355 self.pg1.remote_hosts[4].mac,
356 self.pg1.remote_hosts[4].ip4,
357 is_no_fib_entry=1)
358 arp_no_fib.add_vpp_config()
359
360 #
361 # check we have the neighbor, but no route
362 #
363 self.assertTrue(find_nbr(self,
364 self.pg1.sw_if_index,
365 self.pg1._remote_hosts[4].ip4))
366 self.assertFalse(find_route(self,
367 self.pg1._remote_hosts[4].ip4,
368 32))
369 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800370 # pg2 is unnumbered to pg1, so we can form adjacencies out of pg2
371 # from within pg1's subnet
Neale Ranns3983ac22017-03-10 11:53:27 -0800372 #
373 arp_unnum = VppNeighbor(self,
374 self.pg2.sw_if_index,
375 self.pg1.remote_hosts[5].mac,
376 self.pg1.remote_hosts[5].ip4)
377 arp_unnum.add_vpp_config()
378
379 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
380 IP(src=self.pg0.remote_ip4,
381 dst=self.pg1._remote_hosts[5].ip4) /
382 UDP(sport=1234, dport=1234) /
383 Raw())
384
385 self.pg0.add_stream(p)
386 self.pg_enable_capture(self.pg_interfaces)
387 self.pg_start()
388
389 rx = self.pg2.get_capture(1)
390
391 self.verify_ip(rx[0],
392 self.pg2.local_mac,
393 self.pg1.remote_hosts[5].mac,
394 self.pg0.remote_ip4,
395 self.pg1._remote_hosts[5].ip4)
396
397 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800398 # ARP requests from hosts in pg1's subnet sent on pg2 are replied to
399 # with the unnumbered interface's address as the source
400 #
401 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
402 ARP(op="who-has",
403 hwsrc=self.pg2.remote_mac,
404 pdst=self.pg1.local_ip4,
405 psrc=self.pg1.remote_hosts[6].ip4))
406
407 self.pg2.add_stream(p)
408 self.pg_enable_capture(self.pg_interfaces)
409 self.pg_start()
410
411 rx = self.pg2.get_capture(1)
412 self.verify_arp_resp(rx[0],
413 self.pg2.local_mac,
414 self.pg2.remote_mac,
415 self.pg1.local_ip4,
416 self.pg1.remote_hosts[6].ip4)
417
418 #
419 # An attached host route out of pg2 for an undiscovered hosts generates
420 # an ARP request with the unnumbered address as the source
421 #
422 att_unnum = VppIpRoute(self, self.pg1.remote_hosts[7].ip4, 32,
423 [VppRoutePath("0.0.0.0",
424 self.pg2.sw_if_index)])
425 att_unnum.add_vpp_config()
426
427 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
428 IP(src=self.pg0.remote_ip4,
429 dst=self.pg1._remote_hosts[7].ip4) /
430 UDP(sport=1234, dport=1234) /
431 Raw())
432
433 self.pg0.add_stream(p)
434 self.pg_enable_capture(self.pg_interfaces)
435 self.pg_start()
436
437 rx = self.pg2.get_capture(1)
438
439 self.verify_arp_req(rx[0],
440 self.pg2.local_mac,
441 self.pg1.local_ip4,
442 self.pg1._remote_hosts[7].ip4)
443
444 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
445 ARP(op="who-has",
446 hwsrc=self.pg2.remote_mac,
447 pdst=self.pg1.local_ip4,
448 psrc=self.pg1.remote_hosts[7].ip4))
449
450 self.pg2.add_stream(p)
451 self.pg_enable_capture(self.pg_interfaces)
452 self.pg_start()
453
454 rx = self.pg2.get_capture(1)
455 self.verify_arp_resp(rx[0],
456 self.pg2.local_mac,
457 self.pg2.remote_mac,
458 self.pg1.local_ip4,
459 self.pg1.remote_hosts[7].ip4)
460
461 #
462 # An attached host route as yet unresolved out of pg2 for an
463 # undiscovered host, an ARP requests begets a response.
464 #
465 att_unnum1 = VppIpRoute(self, self.pg1.remote_hosts[8].ip4, 32,
466 [VppRoutePath("0.0.0.0",
467 self.pg2.sw_if_index)])
468 att_unnum1.add_vpp_config()
469
470 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
471 ARP(op="who-has",
472 hwsrc=self.pg2.remote_mac,
473 pdst=self.pg1.local_ip4,
474 psrc=self.pg1.remote_hosts[8].ip4))
475
476 self.pg2.add_stream(p)
477 self.pg_enable_capture(self.pg_interfaces)
478 self.pg_start()
479
480 rx = self.pg2.get_capture(1)
481 self.verify_arp_resp(rx[0],
482 self.pg2.local_mac,
483 self.pg2.remote_mac,
484 self.pg1.local_ip4,
485 self.pg1.remote_hosts[8].ip4)
486
487 #
Neale Ranns30d0fd42017-05-30 07:30:04 -0700488 # Send an ARP request from one of the so-far unlearned remote hosts
489 # with a VLAN0 tag
490 #
491 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
492 src=self.pg1._remote_hosts[9].mac) /
493 Dot1Q(vlan=0) /
494 ARP(op="who-has",
495 hwsrc=self.pg1._remote_hosts[9].mac,
496 pdst=self.pg1.local_ip4,
497 psrc=self.pg1._remote_hosts[9].ip4))
498
499 self.pg1.add_stream(p)
500 self.pg_enable_capture(self.pg_interfaces)
501 self.pg_start()
502
503 rx = self.pg1.get_capture(1)
504 self.verify_arp_resp(rx[0],
505 self.pg1.local_mac,
506 self.pg1._remote_hosts[9].mac,
507 self.pg1.local_ip4,
508 self.pg1._remote_hosts[9].ip4)
509
510 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700511 # Add a hierarchy of routes for a host in the sub-net.
Neale Rannsca193612017-06-14 06:50:08 -0700512 # Should still get an ARP resp since the cover is attached
513 #
514 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_mac) /
515 ARP(op="who-has",
516 hwsrc=self.pg1.remote_mac,
517 pdst=self.pg1.local_ip4,
518 psrc=self.pg1.remote_hosts[10].ip4))
519
520 r1 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 30,
521 [VppRoutePath(self.pg1.remote_hosts[10].ip4,
522 self.pg1.sw_if_index)])
523 r1.add_vpp_config()
524
525 self.pg1.add_stream(p)
526 self.pg_enable_capture(self.pg_interfaces)
527 self.pg_start()
528 rx = self.pg1.get_capture(1)
529 self.verify_arp_resp(rx[0],
530 self.pg1.local_mac,
531 self.pg1.remote_mac,
532 self.pg1.local_ip4,
533 self.pg1.remote_hosts[10].ip4)
534
535 r2 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 32,
536 [VppRoutePath(self.pg1.remote_hosts[10].ip4,
537 self.pg1.sw_if_index)])
538 r2.add_vpp_config()
539
540 self.pg1.add_stream(p)
541 self.pg_enable_capture(self.pg_interfaces)
542 self.pg_start()
543 rx = self.pg1.get_capture(1)
544 self.verify_arp_resp(rx[0],
545 self.pg1.local_mac,
546 self.pg1.remote_mac,
547 self.pg1.local_ip4,
548 self.pg1.remote_hosts[10].ip4)
549
550 #
551 # add an ARP entry that's not on the sub-net and so whose
552 # adj-fib fails the refinement check. then send an ARP request
553 # from that source
554 #
555 a1 = VppNeighbor(self,
556 self.pg0.sw_if_index,
557 self.pg0.remote_mac,
558 "100.100.100.50")
559 a1.add_vpp_config()
560
561 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
562 ARP(op="who-has",
563 hwsrc=self.pg0.remote_mac,
564 psrc="100.100.100.50",
565 pdst=self.pg0.remote_ip4))
566 self.send_and_assert_no_replies(self.pg0, p,
567 "ARP req for from failed adj-fib")
568
569 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800570 # ERROR Cases
571 # 1 - don't respond to ARP request for address not within the
572 # interface's sub-net
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700573 # 1b - nor within the unnumbered subnet
574 # 1c - nor within the subnet of a different interface
575 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800576 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
577 ARP(op="who-has",
578 hwsrc=self.pg0.remote_mac,
579 pdst="10.10.10.3",
580 psrc=self.pg0.remote_ip4))
581 self.send_and_assert_no_replies(self.pg0, p,
582 "ARP req for non-local destination")
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700583 self.assertFalse(find_nbr(self,
584 self.pg0.sw_if_index,
585 "10.10.10.3"))
586
Neale Ranns4b919a52017-03-11 05:55:21 -0800587 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
588 ARP(op="who-has",
589 hwsrc=self.pg2.remote_mac,
590 pdst="10.10.10.3",
591 psrc=self.pg1.remote_hosts[7].ip4))
592 self.send_and_assert_no_replies(
593 self.pg0, p,
594 "ARP req for non-local destination - unnum")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800595
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700596 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
597 ARP(op="who-has",
598 hwsrc=self.pg0.remote_mac,
599 pdst=self.pg1.local_ip4,
600 psrc=self.pg1.remote_ip4))
601 self.send_and_assert_no_replies(self.pg0, p,
602 "ARP req diff sub-net")
603 self.assertFalse(find_nbr(self,
604 self.pg0.sw_if_index,
605 self.pg1.remote_ip4))
606
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800607 #
608 # 2 - don't respond to ARP request from an address not within the
609 # interface's sub-net
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700610 # 2b - to a proxied address
611 # 2c - not within a different interface's sub-net
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800612 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
613 ARP(op="who-has",
614 hwsrc=self.pg0.remote_mac,
615 psrc="10.10.10.3",
616 pdst=self.pg0.local_ip4))
617 self.send_and_assert_no_replies(self.pg0, p,
618 "ARP req for non-local source")
Neale Ranns4b919a52017-03-11 05:55:21 -0800619 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
620 ARP(op="who-has",
621 hwsrc=self.pg2.remote_mac,
622 psrc="10.10.10.3",
623 pdst=self.pg0.local_ip4))
624 self.send_and_assert_no_replies(
625 self.pg0, p,
626 "ARP req for non-local source - unnum")
Neale Rannsca193612017-06-14 06:50:08 -0700627 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
628 ARP(op="who-has",
629 hwsrc=self.pg0.remote_mac,
630 psrc=self.pg1.remote_ip4,
631 pdst=self.pg0.local_ip4))
632 self.send_and_assert_no_replies(self.pg0, p,
633 "ARP req for non-local source 2c")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800634
635 #
636 # 3 - don't respond to ARP request from an address that belongs to
637 # the router
638 #
639 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.pg0.local_ip4,
643 pdst=self.pg0.local_ip4))
644 self.send_and_assert_no_replies(self.pg0, p,
645 "ARP req for non-local source")
646
647 #
648 # 4 - don't respond to ARP requests that has mac source different
649 # from ARP request HW source
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800650 #
651 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
652 ARP(op="who-has",
653 hwsrc="00:00:00:DE:AD:BE",
654 psrc=self.pg0.remote_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 #
zhaoqinglingb4c42cd2017-12-23 15:20:59 +0800660 # 5 - don't respond to ARP requests for address within the
661 # interface's sub-net but not the interface's address
662 #
663 self.pg0.generate_remote_hosts(2)
664 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
665 ARP(op="who-has",
666 hwsrc=self.pg0.remote_mac,
667 psrc=self.pg0.remote_hosts[0].ip4,
668 pdst=self.pg0.remote_hosts[1].ip4))
669 self.send_and_assert_no_replies(self.pg0, p,
670 "ARP req for non-local destination")
671
672 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800673 # cleanup
674 #
675 dyn_arp.remove_vpp_config()
676 static_arp.remove_vpp_config()
Neale Ranns3983ac22017-03-10 11:53:27 -0800677 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800678
Neale Ranns4b919a52017-03-11 05:55:21 -0800679 # need this to flush the adj-fibs
680 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
681 self.pg2.admin_down()
Neale Rannsca193612017-06-14 06:50:08 -0700682 self.pg1.admin_down()
Neale Ranns4b919a52017-03-11 05:55:21 -0800683
Neale Ranns24b170a2017-08-15 05:33:11 -0700684 def test_proxy_mirror_arp(self):
685 """ Interface Mirror Proxy ARP """
686
687 #
688 # When VPP has an interface whose address is also applied to a TAP
689 # interface on the host, then VPP's TAP interface will be unnumbered
690 # to the 'real' interface and do proxy ARP from the host.
691 # the curious aspect of this setup is that ARP requests from the host
692 # will come from the VPP's own address.
693 #
694 self.pg0.generate_remote_hosts(2)
695
696 arp_req_from_me = (Ether(src=self.pg2.remote_mac,
697 dst="ff:ff:ff:ff:ff:ff") /
698 ARP(op="who-has",
699 hwsrc=self.pg2.remote_mac,
700 pdst=self.pg0.remote_hosts[1].ip4,
701 psrc=self.pg0.local_ip4))
702
703 #
704 # Configure Proxy ARP for the subnet on PG0addresses on pg0
705 #
Neale Ranns37029302018-08-10 05:30:06 -0700706 self.vapi.proxy_arp_add_del(self.pg0._local_ip4_subnet,
707 self.pg0._local_ip4_bcast)
Neale Ranns24b170a2017-08-15 05:33:11 -0700708
709 # Make pg2 un-numbered to pg0
710 #
711 self.pg2.set_unnumbered(self.pg0.sw_if_index)
712
713 #
714 # Enable pg2 for proxy ARP
715 #
716 self.pg2.set_proxy_arp()
717
718 #
719 # Send the ARP request with an originating address that
720 # is VPP's own address
721 #
722 self.pg2.add_stream(arp_req_from_me)
723 self.pg_enable_capture(self.pg_interfaces)
724 self.pg_start()
725
726 rx = self.pg2.get_capture(1)
727 self.verify_arp_resp(rx[0],
728 self.pg2.local_mac,
729 self.pg2.remote_mac,
730 self.pg0.remote_hosts[1].ip4,
731 self.pg0.local_ip4)
732
733 #
734 # validate we have not learned an ARP entry as a result of this
735 #
736 self.assertFalse(find_nbr(self,
737 self.pg2.sw_if_index,
738 self.pg0.local_ip4))
739
740 #
741 # cleanup
742 #
743 self.pg2.set_proxy_arp(0)
Neale Ranns37029302018-08-10 05:30:06 -0700744 self.vapi.proxy_arp_add_del(self.pg0._local_ip4_subnet,
745 self.pg0._local_ip4_bcast,
Neale Ranns24b170a2017-08-15 05:33:11 -0700746 is_add=0)
747
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800748 def test_proxy_arp(self):
749 """ Proxy ARP """
750
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700751 self.pg1.generate_remote_hosts(2)
752
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800753 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700754 # Proxy ARP request packets for each interface
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800755 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800756 arp_req_pg0 = (Ether(src=self.pg0.remote_mac,
757 dst="ff:ff:ff:ff:ff:ff") /
758 ARP(op="who-has",
759 hwsrc=self.pg0.remote_mac,
760 pdst="10.10.10.3",
761 psrc=self.pg0.remote_ip4))
Neale Ranns30d0fd42017-05-30 07:30:04 -0700762 arp_req_pg0_tagged = (Ether(src=self.pg0.remote_mac,
763 dst="ff:ff:ff:ff:ff:ff") /
764 Dot1Q(vlan=0) /
765 ARP(op="who-has",
766 hwsrc=self.pg0.remote_mac,
767 pdst="10.10.10.3",
768 psrc=self.pg0.remote_ip4))
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800769 arp_req_pg1 = (Ether(src=self.pg1.remote_mac,
770 dst="ff:ff:ff:ff:ff:ff") /
771 ARP(op="who-has",
772 hwsrc=self.pg1.remote_mac,
773 pdst="10.10.10.3",
774 psrc=self.pg1.remote_ip4))
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700775 arp_req_pg2 = (Ether(src=self.pg2.remote_mac,
776 dst="ff:ff:ff:ff:ff:ff") /
777 ARP(op="who-has",
778 hwsrc=self.pg2.remote_mac,
779 pdst="10.10.10.3",
780 psrc=self.pg1.remote_hosts[1].ip4))
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800781 arp_req_pg3 = (Ether(src=self.pg3.remote_mac,
782 dst="ff:ff:ff:ff:ff:ff") /
783 ARP(op="who-has",
784 hwsrc=self.pg3.remote_mac,
785 pdst="10.10.10.3",
786 psrc=self.pg3.remote_ip4))
787
788 #
789 # Configure Proxy ARP for 10.10.10.0 -> 10.10.10.124
790 #
791 self.vapi.proxy_arp_add_del(inet_pton(AF_INET, "10.10.10.2"),
792 inet_pton(AF_INET, "10.10.10.124"))
793
794 #
795 # No responses are sent when the interfaces are not enabled for proxy
796 # ARP
797 #
798 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
799 "ARP req from unconfigured interface")
800 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
801 "ARP req from unconfigured interface")
802
803 #
804 # Make pg2 un-numbered to pg1
805 # still won't reply.
806 #
807 self.pg2.set_unnumbered(self.pg1.sw_if_index)
808
809 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
810 "ARP req from unnumbered interface")
811
812 #
813 # Enable each interface to reply to proxy ARPs
814 #
815 for i in self.pg_interfaces:
816 i.set_proxy_arp()
817
818 #
819 # Now each of the interfaces should reply to a request to a proxied
820 # address
821 #
822 self.pg0.add_stream(arp_req_pg0)
823 self.pg_enable_capture(self.pg_interfaces)
824 self.pg_start()
825
826 rx = self.pg0.get_capture(1)
827 self.verify_arp_resp(rx[0],
828 self.pg0.local_mac,
829 self.pg0.remote_mac,
830 "10.10.10.3",
831 self.pg0.remote_ip4)
832
Neale Ranns30d0fd42017-05-30 07:30:04 -0700833 self.pg0.add_stream(arp_req_pg0_tagged)
834 self.pg_enable_capture(self.pg_interfaces)
835 self.pg_start()
836
837 rx = self.pg0.get_capture(1)
838 self.verify_arp_resp(rx[0],
839 self.pg0.local_mac,
840 self.pg0.remote_mac,
841 "10.10.10.3",
842 self.pg0.remote_ip4)
843
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800844 self.pg1.add_stream(arp_req_pg1)
845 self.pg_enable_capture(self.pg_interfaces)
846 self.pg_start()
847
848 rx = self.pg1.get_capture(1)
849 self.verify_arp_resp(rx[0],
850 self.pg1.local_mac,
851 self.pg1.remote_mac,
852 "10.10.10.3",
853 self.pg1.remote_ip4)
854
855 self.pg2.add_stream(arp_req_pg2)
856 self.pg_enable_capture(self.pg_interfaces)
857 self.pg_start()
858
859 rx = self.pg2.get_capture(1)
860 self.verify_arp_resp(rx[0],
861 self.pg2.local_mac,
862 self.pg2.remote_mac,
863 "10.10.10.3",
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700864 self.pg1.remote_hosts[1].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800865
866 #
867 # A request for an address out of the configured range
868 #
869 arp_req_pg1_hi = (Ether(src=self.pg1.remote_mac,
870 dst="ff:ff:ff:ff:ff:ff") /
871 ARP(op="who-has",
872 hwsrc=self.pg1.remote_mac,
873 pdst="10.10.10.125",
874 psrc=self.pg1.remote_ip4))
875 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_hi,
876 "ARP req out of range HI")
877 arp_req_pg1_low = (Ether(src=self.pg1.remote_mac,
878 dst="ff:ff:ff:ff:ff:ff") /
879 ARP(op="who-has",
880 hwsrc=self.pg1.remote_mac,
881 pdst="10.10.10.1",
882 psrc=self.pg1.remote_ip4))
883 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_low,
884 "ARP req out of range Low")
885
886 #
887 # Request for an address in the proxy range but from an interface
888 # in a different VRF
889 #
890 self.send_and_assert_no_replies(self.pg3, arp_req_pg3,
891 "ARP req from different VRF")
892
893 #
894 # Disable Each interface for proxy ARP
895 # - expect none to respond
896 #
897 for i in self.pg_interfaces:
898 i.set_proxy_arp(0)
899
900 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
901 "ARP req from disable")
902 self.send_and_assert_no_replies(self.pg1, arp_req_pg1,
903 "ARP req from disable")
904 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
905 "ARP req from disable")
Neale Ranns37be7362017-02-21 17:30:26 -0800906
907 #
908 # clean up on interface 2
909 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800910 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns37be7362017-02-21 17:30:26 -0800911
912 def test_mpls(self):
913 """ MPLS """
914
915 #
916 # Interface 2 does not yet have ip4 config
917 #
918 self.pg2.config_ip4()
919 self.pg2.generate_remote_hosts(2)
920
921 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700922 # Add a route with out going label via an ARP unresolved next-hop
Neale Ranns37be7362017-02-21 17:30:26 -0800923 #
924 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
925 [VppRoutePath(self.pg2.remote_hosts[1].ip4,
926 self.pg2.sw_if_index,
927 labels=[55])])
928 ip_10_0_0_1.add_vpp_config()
929
930 #
931 # packets should generate an ARP request
932 #
933 p = (Ether(src=self.pg0.remote_mac,
934 dst=self.pg0.local_mac) /
935 IP(src=self.pg0.remote_ip4, dst="10.0.0.1") /
936 UDP(sport=1234, dport=1234) /
937 Raw('\xa5' * 100))
938
939 self.pg0.add_stream(p)
940 self.pg_enable_capture(self.pg_interfaces)
941 self.pg_start()
942
943 rx = self.pg2.get_capture(1)
944 self.verify_arp_req(rx[0],
945 self.pg2.local_mac,
946 self.pg2.local_ip4,
947 self.pg2._remote_hosts[1].ip4)
948
949 #
950 # now resolve the neighbours
951 #
952 self.pg2.configure_ipv4_neighbors()
953
954 #
955 # Now packet should be properly MPLS encapped.
956 # This verifies that MPLS link-type adjacencies are completed
957 # when the ARP entry resolves
958 #
959 self.pg0.add_stream(p)
960 self.pg_enable_capture(self.pg_interfaces)
961 self.pg_start()
962
963 rx = self.pg2.get_capture(1)
964 self.verify_ip_o_mpls(rx[0],
965 self.pg2.local_mac,
966 self.pg2.remote_hosts[1].mac,
967 55,
968 self.pg0.remote_ip4,
969 "10.0.0.1")
Neale Ranns4b919a52017-03-11 05:55:21 -0800970 self.pg2.unconfig_ip4()
Neale Ranns37be7362017-02-21 17:30:26 -0800971
Matthew Smithcb9ab472017-05-16 21:35:56 -0500972 def test_arp_vrrp(self):
973 """ ARP reply with VRRP virtual src hw addr """
974
975 #
976 # IP packet destined for pg1 remote host arrives on pg0 resulting
977 # in an ARP request for the address of the remote host on pg1
978 #
979 p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
980 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
981 UDP(sport=1234, dport=1234) /
982 Raw())
983
Neale Ranns37029302018-08-10 05:30:06 -0700984 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
Matthew Smithcb9ab472017-05-16 21:35:56 -0500985
986 self.verify_arp_req(rx1[0],
987 self.pg1.local_mac,
988 self.pg1.local_ip4,
989 self.pg1.remote_ip4)
990
991 #
992 # ARP reply for address of pg1 remote host arrives on pg1 with
993 # the hw src addr set to a value in the VRRP IPv4 range of
994 # MAC addresses
995 #
996 p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
997 ARP(op="is-at", hwdst=self.pg1.local_mac,
998 hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
999 psrc=self.pg1.remote_ip4))
1000
Neale Ranns37029302018-08-10 05:30:06 -07001001 self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
Matthew Smithcb9ab472017-05-16 21:35:56 -05001002
1003 #
1004 # IP packet destined for pg1 remote host arrives on pg0 again.
1005 # VPP should have an ARP entry for that address now and the packet
1006 # should be sent out pg1.
1007 #
Neale Ranns37029302018-08-10 05:30:06 -07001008 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
Matthew Smithcb9ab472017-05-16 21:35:56 -05001009
1010 self.verify_ip(rx1[0],
1011 self.pg1.local_mac,
1012 "00:00:5e:00:01:09",
1013 self.pg0.remote_ip4,
1014 self.pg1.remote_ip4)
1015
1016 self.pg1.admin_down()
1017 self.pg1.admin_up()
1018
Neale Rannsdcd6d622017-05-26 02:59:16 -07001019 def test_arp_duplicates(self):
1020 """ ARP Duplicates"""
1021
1022 #
1023 # Generate some hosts on the LAN
1024 #
1025 self.pg1.generate_remote_hosts(3)
1026
1027 #
1028 # Add host 1 on pg1 and pg2
1029 #
1030 arp_pg1 = VppNeighbor(self,
1031 self.pg1.sw_if_index,
1032 self.pg1.remote_hosts[1].mac,
1033 self.pg1.remote_hosts[1].ip4)
1034 arp_pg1.add_vpp_config()
1035 arp_pg2 = VppNeighbor(self,
1036 self.pg2.sw_if_index,
1037 self.pg2.remote_mac,
1038 self.pg1.remote_hosts[1].ip4)
1039 arp_pg2.add_vpp_config()
1040
1041 #
1042 # IP packet destined for pg1 remote host arrives on pg1 again.
1043 #
1044 p = (Ether(dst=self.pg0.local_mac,
1045 src=self.pg0.remote_mac) /
1046 IP(src=self.pg0.remote_ip4,
1047 dst=self.pg1.remote_hosts[1].ip4) /
1048 UDP(sport=1234, dport=1234) /
1049 Raw())
1050
1051 self.pg0.add_stream(p)
1052 self.pg_enable_capture(self.pg_interfaces)
1053 self.pg_start()
1054
1055 rx1 = self.pg1.get_capture(1)
1056
1057 self.verify_ip(rx1[0],
1058 self.pg1.local_mac,
1059 self.pg1.remote_hosts[1].mac,
1060 self.pg0.remote_ip4,
1061 self.pg1.remote_hosts[1].ip4)
1062
1063 #
1064 # remove the duplicate on pg1
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001065 # packet stream should generate ARPs out of pg1
Neale Rannsdcd6d622017-05-26 02:59:16 -07001066 #
1067 arp_pg1.remove_vpp_config()
1068
1069 self.pg0.add_stream(p)
1070 self.pg_enable_capture(self.pg_interfaces)
1071 self.pg_start()
1072
1073 rx1 = self.pg1.get_capture(1)
1074
1075 self.verify_arp_req(rx1[0],
1076 self.pg1.local_mac,
1077 self.pg1.local_ip4,
1078 self.pg1.remote_hosts[1].ip4)
1079
1080 #
1081 # Add it back
1082 #
1083 arp_pg1.add_vpp_config()
1084
1085 self.pg0.add_stream(p)
1086 self.pg_enable_capture(self.pg_interfaces)
1087 self.pg_start()
1088
1089 rx1 = self.pg1.get_capture(1)
1090
1091 self.verify_ip(rx1[0],
1092 self.pg1.local_mac,
1093 self.pg1.remote_hosts[1].mac,
1094 self.pg0.remote_ip4,
1095 self.pg1.remote_hosts[1].ip4)
1096
Neale Ranns15002542017-09-10 04:39:11 -07001097 def test_arp_static(self):
1098 """ ARP Static"""
1099 self.pg2.generate_remote_hosts(3)
1100
1101 #
1102 # Add a static ARP entry
1103 #
1104 static_arp = VppNeighbor(self,
1105 self.pg2.sw_if_index,
1106 self.pg2.remote_hosts[1].mac,
1107 self.pg2.remote_hosts[1].ip4,
1108 is_static=1)
1109 static_arp.add_vpp_config()
1110
1111 #
1112 # Add the connected prefix to the interface
1113 #
1114 self.pg2.config_ip4()
1115
1116 #
1117 # We should now find the adj-fib
1118 #
1119 self.assertTrue(find_nbr(self,
1120 self.pg2.sw_if_index,
1121 self.pg2.remote_hosts[1].ip4,
1122 is_static=1))
1123 self.assertTrue(find_route(self,
1124 self.pg2.remote_hosts[1].ip4,
1125 32))
1126
1127 #
1128 # remove the connected
1129 #
1130 self.pg2.unconfig_ip4()
1131
1132 #
1133 # put the interface into table 1
1134 #
1135 self.pg2.set_table_ip4(1)
1136
1137 #
1138 # configure the same connected and expect to find the
1139 # adj fib in the new table
1140 #
1141 self.pg2.config_ip4()
1142 self.assertTrue(find_route(self,
1143 self.pg2.remote_hosts[1].ip4,
1144 32,
1145 table_id=1))
1146
1147 #
1148 # clean-up
1149 #
1150 self.pg2.unconfig_ip4()
1151 self.pg2.set_table_ip4(0)
1152
Neale Rannsc819fc62018-02-16 02:44:05 -08001153 def test_arp_incomplete(self):
1154 """ ARP Incomplete"""
1155 self.pg1.generate_remote_hosts(3)
1156
1157 p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1158 IP(src=self.pg0.remote_ip4,
1159 dst=self.pg1.remote_hosts[1].ip4) /
1160 UDP(sport=1234, dport=1234) /
1161 Raw())
1162 p1 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1163 IP(src=self.pg0.remote_ip4,
1164 dst=self.pg1.remote_hosts[2].ip4) /
1165 UDP(sport=1234, dport=1234) /
1166 Raw())
1167
1168 #
1169 # a packet to an unresolved destination generates an ARP request
1170 #
1171 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1172 self.verify_arp_req(rx[0],
1173 self.pg1.local_mac,
1174 self.pg1.local_ip4,
1175 self.pg1._remote_hosts[1].ip4)
1176
1177 #
1178 # add a neighbour for remote host 1
1179 #
1180 static_arp = VppNeighbor(self,
1181 self.pg1.sw_if_index,
1182 self.pg1.remote_hosts[1].mac,
1183 self.pg1.remote_hosts[1].ip4,
1184 is_static=1)
1185 static_arp.add_vpp_config()
1186
1187 #
1188 # change the interface's MAC
1189 #
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001190 mac = [scapy.compat.chb(0x00), scapy.compat.chb(0x00),
1191 scapy.compat.chb(0x00), scapy.compat.chb(0x33),
1192 scapy.compat.chb(0x33), scapy.compat.chb(0x33)]
Neale Rannsc819fc62018-02-16 02:44:05 -08001193 mac_string = ''.join(mac)
1194
1195 self.vapi.sw_interface_set_mac_address(self.pg1.sw_if_index,
1196 mac_string)
1197
1198 #
1199 # now ARP requests come from the new source mac
1200 #
1201 rx = self.send_and_expect(self.pg0, [p1], self.pg1)
1202 self.verify_arp_req(rx[0],
1203 "00:00:00:33:33:33",
1204 self.pg1.local_ip4,
1205 self.pg1._remote_hosts[2].ip4)
1206
1207 #
1208 # packets to the resolved host also have the new source mac
1209 #
1210 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1211 self.verify_ip(rx[0],
1212 "00:00:00:33:33:33",
1213 self.pg1.remote_hosts[1].mac,
1214 self.pg0.remote_ip4,
1215 self.pg1.remote_hosts[1].ip4)
1216
1217 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001218 # set the mac address on the interface that does not have a
Neale Rannsc819fc62018-02-16 02:44:05 -08001219 # configured subnet and thus no glean
1220 #
1221 self.vapi.sw_interface_set_mac_address(self.pg2.sw_if_index,
1222 mac_string)
1223
Neale Ranns59ae61e2018-06-07 18:09:49 -07001224 def test_garp(self):
1225 """ GARP """
1226
1227 #
1228 # Generate some hosts on the LAN
1229 #
1230 self.pg1.generate_remote_hosts(4)
1231
1232 #
1233 # And an ARP entry
1234 #
1235 arp = VppNeighbor(self,
1236 self.pg1.sw_if_index,
1237 self.pg1.remote_hosts[1].mac,
1238 self.pg1.remote_hosts[1].ip4)
1239 arp.add_vpp_config()
1240
1241 self.assertTrue(find_nbr(self,
1242 self.pg1.sw_if_index,
1243 self.pg1.remote_hosts[1].ip4,
1244 mac=self.pg1.remote_hosts[1].mac))
1245
1246 #
1247 # Send a GARP (request) to swap the host 1's address to that of host 2
1248 #
1249 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1250 src=self.pg1.remote_hosts[2].mac) /
1251 ARP(op="who-has",
1252 hwdst=self.pg1.local_mac,
1253 hwsrc=self.pg1.remote_hosts[2].mac,
1254 pdst=self.pg1.remote_hosts[1].ip4,
1255 psrc=self.pg1.remote_hosts[1].ip4))
1256
1257 self.pg1.add_stream(p1)
1258 self.pg_enable_capture(self.pg_interfaces)
1259 self.pg_start()
1260
1261 self.assertTrue(find_nbr(self,
1262 self.pg1.sw_if_index,
1263 self.pg1.remote_hosts[1].ip4,
1264 mac=self.pg1.remote_hosts[2].mac))
1265
1266 #
1267 # Send a GARP (reply) to swap the host 1's address to that of host 3
1268 #
1269 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1270 src=self.pg1.remote_hosts[3].mac) /
1271 ARP(op="is-at",
1272 hwdst=self.pg1.local_mac,
1273 hwsrc=self.pg1.remote_hosts[3].mac,
1274 pdst=self.pg1.remote_hosts[1].ip4,
1275 psrc=self.pg1.remote_hosts[1].ip4))
1276
1277 self.pg1.add_stream(p1)
1278 self.pg_enable_capture(self.pg_interfaces)
1279 self.pg_start()
1280
1281 self.assertTrue(find_nbr(self,
1282 self.pg1.sw_if_index,
1283 self.pg1.remote_hosts[1].ip4,
1284 mac=self.pg1.remote_hosts[3].mac))
1285
1286 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001287 # GARPs (request nor replies) for host we don't know yet
Neale Ranns59ae61e2018-06-07 18:09:49 -07001288 # don't result in new neighbour entries
1289 #
1290 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1291 src=self.pg1.remote_hosts[3].mac) /
1292 ARP(op="who-has",
1293 hwdst=self.pg1.local_mac,
1294 hwsrc=self.pg1.remote_hosts[3].mac,
1295 pdst=self.pg1.remote_hosts[2].ip4,
1296 psrc=self.pg1.remote_hosts[2].ip4))
1297
1298 self.pg1.add_stream(p1)
1299 self.pg_enable_capture(self.pg_interfaces)
1300 self.pg_start()
1301
1302 self.assertFalse(find_nbr(self,
1303 self.pg1.sw_if_index,
1304 self.pg1.remote_hosts[2].ip4))
1305
1306 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1307 src=self.pg1.remote_hosts[3].mac) /
1308 ARP(op="is-at",
1309 hwdst=self.pg1.local_mac,
1310 hwsrc=self.pg1.remote_hosts[3].mac,
1311 pdst=self.pg1.remote_hosts[2].ip4,
1312 psrc=self.pg1.remote_hosts[2].ip4))
1313
1314 self.pg1.add_stream(p1)
1315 self.pg_enable_capture(self.pg_interfaces)
1316 self.pg_start()
1317
1318 self.assertFalse(find_nbr(self,
1319 self.pg1.sw_if_index,
1320 self.pg1.remote_hosts[2].ip4))
1321
Neale Rannsc8352bc2018-08-29 10:23:58 -07001322 def test_arp_incomplete(self):
Neale Ranns14260392018-09-28 05:00:57 -07001323 """ Incomplete Entries """
Neale Rannsc8352bc2018-08-29 10:23:58 -07001324
1325 #
Neale Rannscd35e532018-08-31 02:51:45 -07001326 # ensure that we throttle the ARP and ND requests
Neale Rannsc8352bc2018-08-29 10:23:58 -07001327 #
1328 self.pg0.generate_remote_hosts(2)
1329
Neale Rannscd35e532018-08-31 02:51:45 -07001330 #
1331 # IPv4/ARP
1332 #
Neale Rannsc8352bc2018-08-29 10:23:58 -07001333 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1334 [VppRoutePath(self.pg0.remote_hosts[1].ip4,
Neale Rannscd35e532018-08-31 02:51:45 -07001335 self.pg0.sw_if_index)])
Neale Rannsc8352bc2018-08-29 10:23:58 -07001336 ip_10_0_0_1.add_vpp_config()
1337
1338 p1 = (Ether(dst=self.pg1.local_mac,
1339 src=self.pg1.remote_mac) /
1340 IP(src=self.pg1.remote_ip4,
1341 dst="10.0.0.1") /
1342 UDP(sport=1234, dport=1234) /
1343 Raw())
1344
1345 self.pg1.add_stream(p1 * 257)
1346 self.pg_enable_capture(self.pg_interfaces)
1347 self.pg_start()
1348 rx = self.pg0._get_capture(1)
1349
1350 #
1351 # how many we get is going to be dependent on the time for packet
1352 # processing but it should be small
1353 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001354 self.assertLess(len(rx), 64)
Neale Rannsc8352bc2018-08-29 10:23:58 -07001355
Neale Rannscd35e532018-08-31 02:51:45 -07001356 #
1357 # IPv6/ND
1358 #
1359 ip_10_1 = VppIpRoute(self, "10::1", 128,
1360 [VppRoutePath(self.pg0.remote_hosts[1].ip6,
1361 self.pg0.sw_if_index,
1362 proto=DpoProto.DPO_PROTO_IP6)],
1363 is_ip6=1)
1364 ip_10_1.add_vpp_config()
1365
1366 p1 = (Ether(dst=self.pg1.local_mac,
1367 src=self.pg1.remote_mac) /
1368 IPv6(src=self.pg1.remote_ip6,
1369 dst="10::1") /
1370 UDP(sport=1234, dport=1234) /
1371 Raw())
1372
1373 self.pg1.add_stream(p1 * 257)
1374 self.pg_enable_capture(self.pg_interfaces)
1375 self.pg_start()
1376 rx = self.pg0._get_capture(1)
1377
1378 #
1379 # how many we get is going to be dependent on the time for packet
1380 # processing but it should be small
1381 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001382 self.assertLess(len(rx), 64)
Neale Rannscd35e532018-08-31 02:51:45 -07001383
Neale Ranns7425f922019-01-23 00:36:16 -08001384 def test_arp_forus(self):
1385 """ ARP for for-us """
1386
1387 #
1388 # Test that VPP responds with ARP requests to addresses that
1389 # are connected and local routes.
1390 # Use one of the 'remote' addresses in the subnet as a local address
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001391 # The intention of this route is that it then acts like a secondary
Neale Ranns7425f922019-01-23 00:36:16 -08001392 # address added to an interface
1393 #
1394 self.pg0.generate_remote_hosts(2)
1395
1396 forus = VppIpRoute(self, self.pg0.remote_hosts[1].ip4, 32,
1397 [VppRoutePath(self.pg0.remote_hosts[1].ip4,
1398 self.pg0.sw_if_index)],
1399 is_local=1)
1400 forus.add_vpp_config()
1401
1402 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
1403 src=self.pg0.remote_mac) /
1404 ARP(op="who-has",
1405 hwdst=self.pg0.local_mac,
1406 hwsrc=self.pg0.remote_mac,
1407 pdst=self.pg0.remote_hosts[1].ip4,
1408 psrc=self.pg0.remote_ip4))
1409
1410 rx = self.send_and_expect(self.pg0, [p], self.pg0)
1411
1412 self.verify_arp_resp(rx[0],
1413 self.pg0.local_mac,
1414 self.pg0.remote_mac,
1415 self.pg0.remote_hosts[1].ip4,
1416 self.pg0.remote_ip4)
1417
Neale Rannsdcd6d622017-05-26 02:59:16 -07001418
Neale Ranns14260392018-09-28 05:00:57 -07001419class NeighborStatsTestCase(VppTestCase):
Neale Ranns37029302018-08-10 05:30:06 -07001420 """ ARP/ND Counters """
Neale Ranns14260392018-09-28 05:00:57 -07001421
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001422 @classmethod
1423 def setUpClass(cls):
1424 super(NeighborStatsTestCase, cls).setUpClass()
1425
1426 @classmethod
1427 def tearDownClass(cls):
1428 super(NeighborStatsTestCase, cls).tearDownClass()
1429
Neale Ranns14260392018-09-28 05:00:57 -07001430 def setUp(self):
1431 super(NeighborStatsTestCase, self).setUp()
1432
1433 self.create_pg_interfaces(range(2))
1434
1435 # pg0 configured with ip4 and 6 addresses used for input
1436 # pg1 configured with ip4 and 6 addresses used for output
1437 # pg2 is unnumbered to pg0
1438 for i in self.pg_interfaces:
1439 i.admin_up()
1440 i.config_ip4()
1441 i.config_ip6()
1442 i.resolve_arp()
1443 i.resolve_ndp()
1444
1445 def tearDown(self):
1446 super(NeighborStatsTestCase, self).tearDown()
1447
1448 for i in self.pg_interfaces:
1449 i.unconfig_ip4()
1450 i.unconfig_ip6()
1451 i.admin_down()
1452
1453 def test_arp_stats(self):
1454 """ ARP Counters """
1455
1456 self.vapi.cli("adj counters enable")
1457 self.pg1.generate_remote_hosts(2)
1458
1459 arp1 = VppNeighbor(self,
1460 self.pg1.sw_if_index,
1461 self.pg1.remote_hosts[0].mac,
1462 self.pg1.remote_hosts[0].ip4)
1463 arp1.add_vpp_config()
1464 arp2 = VppNeighbor(self,
1465 self.pg1.sw_if_index,
1466 self.pg1.remote_hosts[1].mac,
1467 self.pg1.remote_hosts[1].ip4)
1468 arp2.add_vpp_config()
1469
1470 p1 = (Ether(dst=self.pg0.local_mac,
1471 src=self.pg0.remote_mac) /
1472 IP(src=self.pg0.remote_ip4,
1473 dst=self.pg1.remote_hosts[0].ip4) /
1474 UDP(sport=1234, dport=1234) /
1475 Raw())
1476 p2 = (Ether(dst=self.pg0.local_mac,
1477 src=self.pg0.remote_mac) /
1478 IP(src=self.pg0.remote_ip4,
1479 dst=self.pg1.remote_hosts[1].ip4) /
1480 UDP(sport=1234, dport=1234) /
1481 Raw())
1482
1483 rx = self.send_and_expect(self.pg0, p1 * 65, self.pg1)
1484 rx = self.send_and_expect(self.pg0, p2 * 65, self.pg1)
1485
1486 self.assertEqual(65, arp1.get_stats()['packets'])
1487 self.assertEqual(65, arp2.get_stats()['packets'])
1488
1489 rx = self.send_and_expect(self.pg0, p1 * 65, self.pg1)
1490 self.assertEqual(130, arp1.get_stats()['packets'])
1491
1492 def test_nd_stats(self):
1493 """ ND Counters """
1494
1495 self.vapi.cli("adj counters enable")
1496 self.pg0.generate_remote_hosts(3)
1497
1498 nd1 = VppNeighbor(self,
1499 self.pg0.sw_if_index,
1500 self.pg0.remote_hosts[1].mac,
Neale Ranns37029302018-08-10 05:30:06 -07001501 self.pg0.remote_hosts[1].ip6)
Neale Ranns14260392018-09-28 05:00:57 -07001502 nd1.add_vpp_config()
1503 nd2 = VppNeighbor(self,
1504 self.pg0.sw_if_index,
1505 self.pg0.remote_hosts[2].mac,
Neale Ranns37029302018-08-10 05:30:06 -07001506 self.pg0.remote_hosts[2].ip6)
Neale Ranns14260392018-09-28 05:00:57 -07001507 nd2.add_vpp_config()
1508
1509 p1 = (Ether(dst=self.pg1.local_mac,
1510 src=self.pg1.remote_mac) /
1511 IPv6(src=self.pg1.remote_ip6,
1512 dst=self.pg0.remote_hosts[1].ip6) /
1513 UDP(sport=1234, dport=1234) /
1514 Raw())
1515 p2 = (Ether(dst=self.pg1.local_mac,
1516 src=self.pg1.remote_mac) /
1517 IPv6(src=self.pg1.remote_ip6,
1518 dst=self.pg0.remote_hosts[2].ip6) /
1519 UDP(sport=1234, dport=1234) /
1520 Raw())
1521
1522 rx = self.send_and_expect(self.pg1, p1 * 16, self.pg0)
1523 rx = self.send_and_expect(self.pg1, p2 * 16, self.pg0)
1524
1525 self.assertEqual(16, nd1.get_stats()['packets'])
1526 self.assertEqual(16, nd2.get_stats()['packets'])
1527
1528 rx = self.send_and_expect(self.pg1, p1 * 65, self.pg0)
1529 self.assertEqual(81, nd1.get_stats()['packets'])
1530
1531
Neale Ranns37be7362017-02-21 17:30:26 -08001532if __name__ == '__main__':
1533 unittest.main(testRunner=VppTestRunner)