blob: c3005ccaf571b8d500e3d4eadb1bf444b04e034c [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
27 def setUp(self):
28 super(ARPTestCase, self).setUp()
29
30 # create 3 pg interfaces
31 self.create_pg_interfaces(range(4))
32
33 # pg0 configured with ip4 and 6 addresses used for input
34 # pg1 configured with ip4 and 6 addresses used for output
35 # pg2 is unnumbered to pg0
36 for i in self.pg_interfaces:
37 i.admin_up()
38
39 self.pg0.config_ip4()
40 self.pg0.config_ip6()
41 self.pg0.resolve_arp()
42
43 self.pg1.config_ip4()
44 self.pg1.config_ip6()
45
46 # pg3 in a different VRF
Neale Ranns15002542017-09-10 04:39:11 -070047 self.tbl = VppIpTable(self, 1)
48 self.tbl.add_vpp_config()
49
Neale Ranns39f9d8b2017-02-16 21:57:05 -080050 self.pg3.set_table_ip4(1)
51 self.pg3.config_ip4()
52
Neale Ranns4008ac92017-02-13 23:20:04 -080053 def tearDown(self):
Neale Ranns4b919a52017-03-11 05:55:21 -080054 self.pg0.unconfig_ip4()
55 self.pg0.unconfig_ip6()
56
57 self.pg1.unconfig_ip4()
58 self.pg1.unconfig_ip6()
59
60 self.pg3.unconfig_ip4()
Neale Ranns15002542017-09-10 04:39:11 -070061 self.pg3.set_table_ip4(0)
Neale Ranns4b919a52017-03-11 05:55:21 -080062
Neale Ranns4008ac92017-02-13 23:20:04 -080063 for i in self.pg_interfaces:
Neale Ranns4008ac92017-02-13 23:20:04 -080064 i.admin_down()
65
Neale Ranns15002542017-09-10 04:39:11 -070066 super(ARPTestCase, self).tearDown()
67
Neale Ranns39f9d8b2017-02-16 21:57:05 -080068 def verify_arp_req(self, rx, smac, sip, dip):
69 ether = rx[Ether]
70 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
71 self.assertEqual(ether.src, smac)
72
73 arp = rx[ARP]
74 self.assertEqual(arp.hwtype, 1)
75 self.assertEqual(arp.ptype, 0x800)
76 self.assertEqual(arp.hwlen, 6)
77 self.assertEqual(arp.plen, 4)
78 self.assertEqual(arp.op, arp_opts["who-has"])
79 self.assertEqual(arp.hwsrc, smac)
80 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
81 self.assertEqual(arp.psrc, sip)
82 self.assertEqual(arp.pdst, dip)
83
84 def verify_arp_resp(self, rx, smac, dmac, sip, dip):
85 ether = rx[Ether]
86 self.assertEqual(ether.dst, dmac)
87 self.assertEqual(ether.src, smac)
88
89 arp = rx[ARP]
90 self.assertEqual(arp.hwtype, 1)
91 self.assertEqual(arp.ptype, 0x800)
92 self.assertEqual(arp.hwlen, 6)
93 self.assertEqual(arp.plen, 4)
94 self.assertEqual(arp.op, arp_opts["is-at"])
95 self.assertEqual(arp.hwsrc, smac)
96 self.assertEqual(arp.hwdst, dmac)
97 self.assertEqual(arp.psrc, sip)
98 self.assertEqual(arp.pdst, dip)
99
Matthew Smithcb9ab472017-05-16 21:35:56 -0500100 def verify_arp_vrrp_resp(self, rx, smac, dmac, sip, dip):
101 ether = rx[Ether]
102 self.assertEqual(ether.dst, dmac)
103 self.assertEqual(ether.src, smac)
104
105 arp = rx[ARP]
106 self.assertEqual(arp.hwtype, 1)
107 self.assertEqual(arp.ptype, 0x800)
108 self.assertEqual(arp.hwlen, 6)
109 self.assertEqual(arp.plen, 4)
110 self.assertEqual(arp.op, arp_opts["is-at"])
111 self.assertNotEqual(arp.hwsrc, smac)
112 self.assertTrue("00:00:5e:00:01" in arp.hwsrc or
113 "00:00:5E:00:01" in arp.hwsrc)
114 self.assertEqual(arp.hwdst, dmac)
115 self.assertEqual(arp.psrc, sip)
116 self.assertEqual(arp.pdst, dip)
117
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800118 def verify_ip(self, rx, smac, dmac, sip, dip):
119 ether = rx[Ether]
120 self.assertEqual(ether.dst, dmac)
121 self.assertEqual(ether.src, smac)
122
123 ip = rx[IP]
124 self.assertEqual(ip.src, sip)
125 self.assertEqual(ip.dst, dip)
126
Neale Ranns37be7362017-02-21 17:30:26 -0800127 def verify_ip_o_mpls(self, rx, smac, dmac, label, sip, dip):
128 ether = rx[Ether]
129 self.assertEqual(ether.dst, dmac)
130 self.assertEqual(ether.src, smac)
131
132 mpls = rx[MPLS]
133 self.assertTrue(mpls.label, label)
134
135 ip = rx[IP]
136 self.assertEqual(ip.src, sip)
137 self.assertEqual(ip.dst, dip)
138
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800139 def test_arp(self):
140 """ ARP """
141
142 #
143 # Generate some hosts on the LAN
144 #
Neale Rannsca193612017-06-14 06:50:08 -0700145 self.pg1.generate_remote_hosts(11)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800146
147 #
148 # Send IP traffic to one of these unresolved hosts.
149 # expect the generation of an ARP request
150 #
151 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
152 IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[1].ip4) /
153 UDP(sport=1234, dport=1234) /
154 Raw())
155
156 self.pg0.add_stream(p)
157 self.pg_enable_capture(self.pg_interfaces)
158 self.pg_start()
159
160 rx = self.pg1.get_capture(1)
161
162 self.verify_arp_req(rx[0],
163 self.pg1.local_mac,
164 self.pg1.local_ip4,
165 self.pg1._remote_hosts[1].ip4)
166
167 #
168 # And a dynamic ARP entry for host 1
169 #
170 dyn_arp = VppNeighbor(self,
171 self.pg1.sw_if_index,
172 self.pg1.remote_hosts[1].mac,
173 self.pg1.remote_hosts[1].ip4)
174 dyn_arp.add_vpp_config()
175
176 #
177 # now we expect IP traffic forwarded
178 #
179 dyn_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
180 IP(src=self.pg0.remote_ip4,
181 dst=self.pg1._remote_hosts[1].ip4) /
182 UDP(sport=1234, dport=1234) /
183 Raw())
184
185 self.pg0.add_stream(dyn_p)
186 self.pg_enable_capture(self.pg_interfaces)
187 self.pg_start()
188
189 rx = self.pg1.get_capture(1)
190
191 self.verify_ip(rx[0],
192 self.pg1.local_mac,
193 self.pg1.remote_hosts[1].mac,
194 self.pg0.remote_ip4,
195 self.pg1._remote_hosts[1].ip4)
196
197 #
198 # And a Static ARP entry for host 2
199 #
200 static_arp = VppNeighbor(self,
201 self.pg1.sw_if_index,
202 self.pg1.remote_hosts[2].mac,
203 self.pg1.remote_hosts[2].ip4,
204 is_static=1)
205 static_arp.add_vpp_config()
206
207 static_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
208 IP(src=self.pg0.remote_ip4,
209 dst=self.pg1._remote_hosts[2].ip4) /
210 UDP(sport=1234, dport=1234) /
211 Raw())
212
213 self.pg0.add_stream(static_p)
214 self.pg_enable_capture(self.pg_interfaces)
215 self.pg_start()
216
217 rx = self.pg1.get_capture(1)
218
219 self.verify_ip(rx[0],
220 self.pg1.local_mac,
221 self.pg1.remote_hosts[2].mac,
222 self.pg0.remote_ip4,
223 self.pg1._remote_hosts[2].ip4)
224
225 #
226 # flap the link. dynamic ARPs get flush, statics don't
227 #
228 self.pg1.admin_down()
229 self.pg1.admin_up()
230
231 self.pg0.add_stream(static_p)
232 self.pg_enable_capture(self.pg_interfaces)
233 self.pg_start()
234 rx = self.pg1.get_capture(1)
235
236 self.verify_ip(rx[0],
237 self.pg1.local_mac,
238 self.pg1.remote_hosts[2].mac,
239 self.pg0.remote_ip4,
240 self.pg1._remote_hosts[2].ip4)
241
242 self.pg0.add_stream(dyn_p)
243 self.pg_enable_capture(self.pg_interfaces)
244 self.pg_start()
245
246 rx = self.pg1.get_capture(1)
247 self.verify_arp_req(rx[0],
248 self.pg1.local_mac,
249 self.pg1.local_ip4,
250 self.pg1._remote_hosts[1].ip4)
251
252 #
253 # Send an ARP request from one of the so-far unlearned remote hosts
254 #
255 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
256 src=self.pg1._remote_hosts[3].mac) /
257 ARP(op="who-has",
258 hwsrc=self.pg1._remote_hosts[3].mac,
259 pdst=self.pg1.local_ip4,
260 psrc=self.pg1._remote_hosts[3].ip4))
261
262 self.pg1.add_stream(p)
263 self.pg_enable_capture(self.pg_interfaces)
264 self.pg_start()
265
266 rx = self.pg1.get_capture(1)
267 self.verify_arp_resp(rx[0],
268 self.pg1.local_mac,
269 self.pg1._remote_hosts[3].mac,
270 self.pg1.local_ip4,
271 self.pg1._remote_hosts[3].ip4)
272
273 #
274 # VPP should have learned the mapping for the remote host
275 #
276 self.assertTrue(find_nbr(self,
277 self.pg1.sw_if_index,
278 self.pg1._remote_hosts[3].ip4))
Neale Ranns4b919a52017-03-11 05:55:21 -0800279 #
280 # Fire in an ARP request before the interface becomes IP enabled
281 #
282 self.pg2.generate_remote_hosts(4)
283
284 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
285 ARP(op="who-has",
286 hwsrc=self.pg2.remote_mac,
287 pdst=self.pg1.local_ip4,
288 psrc=self.pg2.remote_hosts[3].ip4))
Neale Ranns30d0fd42017-05-30 07:30:04 -0700289 pt = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
290 Dot1Q(vlan=0) /
291 ARP(op="who-has",
292 hwsrc=self.pg2.remote_mac,
293 pdst=self.pg1.local_ip4,
294 psrc=self.pg2.remote_hosts[3].ip4))
Neale Ranns4b919a52017-03-11 05:55:21 -0800295 self.send_and_assert_no_replies(self.pg2, p,
296 "interface not IP enabled")
297
298 #
299 # Make pg2 un-numbered to pg1
300 #
301 self.pg2.set_unnumbered(self.pg1.sw_if_index)
302
Neale Ranns404d88e2018-08-08 06:37:33 -0700303 unnum = self.vapi.ip_unnumbered_dump()
304 self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
305 self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)
306
Neale Ranns4b919a52017-03-11 05:55:21 -0800307 #
308 # We should respond to ARP requests for the unnumbered to address
309 # once an attached route to the source is known
310 #
311 self.send_and_assert_no_replies(
312 self.pg2, p,
313 "ARP req for unnumbered address - no source")
314
315 attached_host = VppIpRoute(self, self.pg2.remote_hosts[3].ip4, 32,
316 [VppRoutePath("0.0.0.0",
317 self.pg2.sw_if_index)])
318 attached_host.add_vpp_config()
319
320 self.pg2.add_stream(p)
321 self.pg_enable_capture(self.pg_interfaces)
322 self.pg_start()
323
324 rx = self.pg2.get_capture(1)
325 self.verify_arp_resp(rx[0],
326 self.pg2.local_mac,
327 self.pg2.remote_mac,
328 self.pg1.local_ip4,
329 self.pg2.remote_hosts[3].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800330
Neale Ranns30d0fd42017-05-30 07:30:04 -0700331 self.pg2.add_stream(pt)
332 self.pg_enable_capture(self.pg_interfaces)
333 self.pg_start()
334
335 rx = self.pg2.get_capture(1)
336 self.verify_arp_resp(rx[0],
337 self.pg2.local_mac,
338 self.pg2.remote_mac,
339 self.pg1.local_ip4,
340 self.pg2.remote_hosts[3].ip4)
341
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800342 #
Neale Ranns3983ac22017-03-10 11:53:27 -0800343 # A neighbor entry that has no associated FIB-entry
344 #
345 arp_no_fib = VppNeighbor(self,
346 self.pg1.sw_if_index,
347 self.pg1.remote_hosts[4].mac,
348 self.pg1.remote_hosts[4].ip4,
349 is_no_fib_entry=1)
350 arp_no_fib.add_vpp_config()
351
352 #
353 # check we have the neighbor, but no route
354 #
355 self.assertTrue(find_nbr(self,
356 self.pg1.sw_if_index,
357 self.pg1._remote_hosts[4].ip4))
358 self.assertFalse(find_route(self,
359 self.pg1._remote_hosts[4].ip4,
360 32))
361 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800362 # pg2 is unnumbered to pg1, so we can form adjacencies out of pg2
363 # from within pg1's subnet
Neale Ranns3983ac22017-03-10 11:53:27 -0800364 #
365 arp_unnum = VppNeighbor(self,
366 self.pg2.sw_if_index,
367 self.pg1.remote_hosts[5].mac,
368 self.pg1.remote_hosts[5].ip4)
369 arp_unnum.add_vpp_config()
370
371 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
372 IP(src=self.pg0.remote_ip4,
373 dst=self.pg1._remote_hosts[5].ip4) /
374 UDP(sport=1234, dport=1234) /
375 Raw())
376
377 self.pg0.add_stream(p)
378 self.pg_enable_capture(self.pg_interfaces)
379 self.pg_start()
380
381 rx = self.pg2.get_capture(1)
382
383 self.verify_ip(rx[0],
384 self.pg2.local_mac,
385 self.pg1.remote_hosts[5].mac,
386 self.pg0.remote_ip4,
387 self.pg1._remote_hosts[5].ip4)
388
389 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800390 # ARP requests from hosts in pg1's subnet sent on pg2 are replied to
391 # with the unnumbered interface's address as the source
392 #
393 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
394 ARP(op="who-has",
395 hwsrc=self.pg2.remote_mac,
396 pdst=self.pg1.local_ip4,
397 psrc=self.pg1.remote_hosts[6].ip4))
398
399 self.pg2.add_stream(p)
400 self.pg_enable_capture(self.pg_interfaces)
401 self.pg_start()
402
403 rx = self.pg2.get_capture(1)
404 self.verify_arp_resp(rx[0],
405 self.pg2.local_mac,
406 self.pg2.remote_mac,
407 self.pg1.local_ip4,
408 self.pg1.remote_hosts[6].ip4)
409
410 #
411 # An attached host route out of pg2 for an undiscovered hosts generates
412 # an ARP request with the unnumbered address as the source
413 #
414 att_unnum = VppIpRoute(self, self.pg1.remote_hosts[7].ip4, 32,
415 [VppRoutePath("0.0.0.0",
416 self.pg2.sw_if_index)])
417 att_unnum.add_vpp_config()
418
419 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
420 IP(src=self.pg0.remote_ip4,
421 dst=self.pg1._remote_hosts[7].ip4) /
422 UDP(sport=1234, dport=1234) /
423 Raw())
424
425 self.pg0.add_stream(p)
426 self.pg_enable_capture(self.pg_interfaces)
427 self.pg_start()
428
429 rx = self.pg2.get_capture(1)
430
431 self.verify_arp_req(rx[0],
432 self.pg2.local_mac,
433 self.pg1.local_ip4,
434 self.pg1._remote_hosts[7].ip4)
435
436 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
437 ARP(op="who-has",
438 hwsrc=self.pg2.remote_mac,
439 pdst=self.pg1.local_ip4,
440 psrc=self.pg1.remote_hosts[7].ip4))
441
442 self.pg2.add_stream(p)
443 self.pg_enable_capture(self.pg_interfaces)
444 self.pg_start()
445
446 rx = self.pg2.get_capture(1)
447 self.verify_arp_resp(rx[0],
448 self.pg2.local_mac,
449 self.pg2.remote_mac,
450 self.pg1.local_ip4,
451 self.pg1.remote_hosts[7].ip4)
452
453 #
454 # An attached host route as yet unresolved out of pg2 for an
455 # undiscovered host, an ARP requests begets a response.
456 #
457 att_unnum1 = VppIpRoute(self, self.pg1.remote_hosts[8].ip4, 32,
458 [VppRoutePath("0.0.0.0",
459 self.pg2.sw_if_index)])
460 att_unnum1.add_vpp_config()
461
462 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
463 ARP(op="who-has",
464 hwsrc=self.pg2.remote_mac,
465 pdst=self.pg1.local_ip4,
466 psrc=self.pg1.remote_hosts[8].ip4))
467
468 self.pg2.add_stream(p)
469 self.pg_enable_capture(self.pg_interfaces)
470 self.pg_start()
471
472 rx = self.pg2.get_capture(1)
473 self.verify_arp_resp(rx[0],
474 self.pg2.local_mac,
475 self.pg2.remote_mac,
476 self.pg1.local_ip4,
477 self.pg1.remote_hosts[8].ip4)
478
479 #
Neale Ranns30d0fd42017-05-30 07:30:04 -0700480 # Send an ARP request from one of the so-far unlearned remote hosts
481 # with a VLAN0 tag
482 #
483 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
484 src=self.pg1._remote_hosts[9].mac) /
485 Dot1Q(vlan=0) /
486 ARP(op="who-has",
487 hwsrc=self.pg1._remote_hosts[9].mac,
488 pdst=self.pg1.local_ip4,
489 psrc=self.pg1._remote_hosts[9].ip4))
490
491 self.pg1.add_stream(p)
492 self.pg_enable_capture(self.pg_interfaces)
493 self.pg_start()
494
495 rx = self.pg1.get_capture(1)
496 self.verify_arp_resp(rx[0],
497 self.pg1.local_mac,
498 self.pg1._remote_hosts[9].mac,
499 self.pg1.local_ip4,
500 self.pg1._remote_hosts[9].ip4)
501
502 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700503 # Add a hierarchy of routes for a host in the sub-net.
Neale Rannsca193612017-06-14 06:50:08 -0700504 # Should still get an ARP resp since the cover is attached
505 #
506 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_mac) /
507 ARP(op="who-has",
508 hwsrc=self.pg1.remote_mac,
509 pdst=self.pg1.local_ip4,
510 psrc=self.pg1.remote_hosts[10].ip4))
511
512 r1 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 30,
513 [VppRoutePath(self.pg1.remote_hosts[10].ip4,
514 self.pg1.sw_if_index)])
515 r1.add_vpp_config()
516
517 self.pg1.add_stream(p)
518 self.pg_enable_capture(self.pg_interfaces)
519 self.pg_start()
520 rx = self.pg1.get_capture(1)
521 self.verify_arp_resp(rx[0],
522 self.pg1.local_mac,
523 self.pg1.remote_mac,
524 self.pg1.local_ip4,
525 self.pg1.remote_hosts[10].ip4)
526
527 r2 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 32,
528 [VppRoutePath(self.pg1.remote_hosts[10].ip4,
529 self.pg1.sw_if_index)])
530 r2.add_vpp_config()
531
532 self.pg1.add_stream(p)
533 self.pg_enable_capture(self.pg_interfaces)
534 self.pg_start()
535 rx = self.pg1.get_capture(1)
536 self.verify_arp_resp(rx[0],
537 self.pg1.local_mac,
538 self.pg1.remote_mac,
539 self.pg1.local_ip4,
540 self.pg1.remote_hosts[10].ip4)
541
542 #
543 # add an ARP entry that's not on the sub-net and so whose
544 # adj-fib fails the refinement check. then send an ARP request
545 # from that source
546 #
547 a1 = VppNeighbor(self,
548 self.pg0.sw_if_index,
549 self.pg0.remote_mac,
550 "100.100.100.50")
551 a1.add_vpp_config()
552
553 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
554 ARP(op="who-has",
555 hwsrc=self.pg0.remote_mac,
556 psrc="100.100.100.50",
557 pdst=self.pg0.remote_ip4))
558 self.send_and_assert_no_replies(self.pg0, p,
559 "ARP req for from failed adj-fib")
560
561 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800562 # ERROR Cases
563 # 1 - don't respond to ARP request for address not within the
564 # interface's sub-net
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700565 # 1b - nor within the unnumbered subnet
566 # 1c - nor within the subnet of a different interface
567 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800568 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
569 ARP(op="who-has",
570 hwsrc=self.pg0.remote_mac,
571 pdst="10.10.10.3",
572 psrc=self.pg0.remote_ip4))
573 self.send_and_assert_no_replies(self.pg0, p,
574 "ARP req for non-local destination")
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700575 self.assertFalse(find_nbr(self,
576 self.pg0.sw_if_index,
577 "10.10.10.3"))
578
Neale Ranns4b919a52017-03-11 05:55:21 -0800579 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
580 ARP(op="who-has",
581 hwsrc=self.pg2.remote_mac,
582 pdst="10.10.10.3",
583 psrc=self.pg1.remote_hosts[7].ip4))
584 self.send_and_assert_no_replies(
585 self.pg0, p,
586 "ARP req for non-local destination - unnum")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800587
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700588 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=self.pg1.local_ip4,
592 psrc=self.pg1.remote_ip4))
593 self.send_and_assert_no_replies(self.pg0, p,
594 "ARP req diff sub-net")
595 self.assertFalse(find_nbr(self,
596 self.pg0.sw_if_index,
597 self.pg1.remote_ip4))
598
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800599 #
600 # 2 - don't respond to ARP request from an address not within the
601 # interface's sub-net
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700602 # 2b - to a proxied address
603 # 2c - not within a different interface's sub-net
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800604 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
605 ARP(op="who-has",
606 hwsrc=self.pg0.remote_mac,
607 psrc="10.10.10.3",
608 pdst=self.pg0.local_ip4))
609 self.send_and_assert_no_replies(self.pg0, p,
610 "ARP req for non-local source")
Neale Ranns4b919a52017-03-11 05:55:21 -0800611 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
612 ARP(op="who-has",
613 hwsrc=self.pg2.remote_mac,
614 psrc="10.10.10.3",
615 pdst=self.pg0.local_ip4))
616 self.send_and_assert_no_replies(
617 self.pg0, p,
618 "ARP req for non-local source - unnum")
Neale Rannsca193612017-06-14 06:50:08 -0700619 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
620 ARP(op="who-has",
621 hwsrc=self.pg0.remote_mac,
622 psrc=self.pg1.remote_ip4,
623 pdst=self.pg0.local_ip4))
624 self.send_and_assert_no_replies(self.pg0, p,
625 "ARP req for non-local source 2c")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800626
627 #
628 # 3 - don't respond to ARP request from an address that belongs to
629 # the router
630 #
631 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
632 ARP(op="who-has",
633 hwsrc=self.pg0.remote_mac,
634 psrc=self.pg0.local_ip4,
635 pdst=self.pg0.local_ip4))
636 self.send_and_assert_no_replies(self.pg0, p,
637 "ARP req for non-local source")
638
639 #
640 # 4 - don't respond to ARP requests that has mac source different
641 # from ARP request HW source
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800642 #
643 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
644 ARP(op="who-has",
645 hwsrc="00:00:00:DE:AD:BE",
646 psrc=self.pg0.remote_ip4,
647 pdst=self.pg0.local_ip4))
648 self.send_and_assert_no_replies(self.pg0, p,
649 "ARP req for non-local source")
650
651 #
zhaoqinglingb4c42cd2017-12-23 15:20:59 +0800652 # 5 - don't respond to ARP requests for address within the
653 # interface's sub-net but not the interface's address
654 #
655 self.pg0.generate_remote_hosts(2)
656 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
657 ARP(op="who-has",
658 hwsrc=self.pg0.remote_mac,
659 psrc=self.pg0.remote_hosts[0].ip4,
660 pdst=self.pg0.remote_hosts[1].ip4))
661 self.send_and_assert_no_replies(self.pg0, p,
662 "ARP req for non-local destination")
663
664 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800665 # cleanup
666 #
667 dyn_arp.remove_vpp_config()
668 static_arp.remove_vpp_config()
Neale Ranns3983ac22017-03-10 11:53:27 -0800669 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800670
Neale Ranns4b919a52017-03-11 05:55:21 -0800671 # need this to flush the adj-fibs
672 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
673 self.pg2.admin_down()
Neale Rannsca193612017-06-14 06:50:08 -0700674 self.pg1.admin_down()
Neale Ranns4b919a52017-03-11 05:55:21 -0800675
Neale Ranns24b170a2017-08-15 05:33:11 -0700676 def test_proxy_mirror_arp(self):
677 """ Interface Mirror Proxy ARP """
678
679 #
680 # When VPP has an interface whose address is also applied to a TAP
681 # interface on the host, then VPP's TAP interface will be unnumbered
682 # to the 'real' interface and do proxy ARP from the host.
683 # the curious aspect of this setup is that ARP requests from the host
684 # will come from the VPP's own address.
685 #
686 self.pg0.generate_remote_hosts(2)
687
688 arp_req_from_me = (Ether(src=self.pg2.remote_mac,
689 dst="ff:ff:ff:ff:ff:ff") /
690 ARP(op="who-has",
691 hwsrc=self.pg2.remote_mac,
692 pdst=self.pg0.remote_hosts[1].ip4,
693 psrc=self.pg0.local_ip4))
694
695 #
696 # Configure Proxy ARP for the subnet on PG0addresses on pg0
697 #
Neale Ranns37029302018-08-10 05:30:06 -0700698 self.vapi.proxy_arp_add_del(self.pg0._local_ip4_subnet,
699 self.pg0._local_ip4_bcast)
Neale Ranns24b170a2017-08-15 05:33:11 -0700700
701 # Make pg2 un-numbered to pg0
702 #
703 self.pg2.set_unnumbered(self.pg0.sw_if_index)
704
705 #
706 # Enable pg2 for proxy ARP
707 #
708 self.pg2.set_proxy_arp()
709
710 #
711 # Send the ARP request with an originating address that
712 # is VPP's own address
713 #
714 self.pg2.add_stream(arp_req_from_me)
715 self.pg_enable_capture(self.pg_interfaces)
716 self.pg_start()
717
718 rx = self.pg2.get_capture(1)
719 self.verify_arp_resp(rx[0],
720 self.pg2.local_mac,
721 self.pg2.remote_mac,
722 self.pg0.remote_hosts[1].ip4,
723 self.pg0.local_ip4)
724
725 #
726 # validate we have not learned an ARP entry as a result of this
727 #
728 self.assertFalse(find_nbr(self,
729 self.pg2.sw_if_index,
730 self.pg0.local_ip4))
731
732 #
733 # cleanup
734 #
735 self.pg2.set_proxy_arp(0)
Neale Ranns37029302018-08-10 05:30:06 -0700736 self.vapi.proxy_arp_add_del(self.pg0._local_ip4_subnet,
737 self.pg0._local_ip4_bcast,
Neale Ranns24b170a2017-08-15 05:33:11 -0700738 is_add=0)
739
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800740 def test_proxy_arp(self):
741 """ Proxy ARP """
742
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700743 self.pg1.generate_remote_hosts(2)
744
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800745 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700746 # Proxy ARP request packets for each interface
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800747 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800748 arp_req_pg0 = (Ether(src=self.pg0.remote_mac,
749 dst="ff:ff:ff:ff:ff:ff") /
750 ARP(op="who-has",
751 hwsrc=self.pg0.remote_mac,
752 pdst="10.10.10.3",
753 psrc=self.pg0.remote_ip4))
Neale Ranns30d0fd42017-05-30 07:30:04 -0700754 arp_req_pg0_tagged = (Ether(src=self.pg0.remote_mac,
755 dst="ff:ff:ff:ff:ff:ff") /
756 Dot1Q(vlan=0) /
757 ARP(op="who-has",
758 hwsrc=self.pg0.remote_mac,
759 pdst="10.10.10.3",
760 psrc=self.pg0.remote_ip4))
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800761 arp_req_pg1 = (Ether(src=self.pg1.remote_mac,
762 dst="ff:ff:ff:ff:ff:ff") /
763 ARP(op="who-has",
764 hwsrc=self.pg1.remote_mac,
765 pdst="10.10.10.3",
766 psrc=self.pg1.remote_ip4))
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700767 arp_req_pg2 = (Ether(src=self.pg2.remote_mac,
768 dst="ff:ff:ff:ff:ff:ff") /
769 ARP(op="who-has",
770 hwsrc=self.pg2.remote_mac,
771 pdst="10.10.10.3",
772 psrc=self.pg1.remote_hosts[1].ip4))
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800773 arp_req_pg3 = (Ether(src=self.pg3.remote_mac,
774 dst="ff:ff:ff:ff:ff:ff") /
775 ARP(op="who-has",
776 hwsrc=self.pg3.remote_mac,
777 pdst="10.10.10.3",
778 psrc=self.pg3.remote_ip4))
779
780 #
781 # Configure Proxy ARP for 10.10.10.0 -> 10.10.10.124
782 #
783 self.vapi.proxy_arp_add_del(inet_pton(AF_INET, "10.10.10.2"),
784 inet_pton(AF_INET, "10.10.10.124"))
785
786 #
787 # No responses are sent when the interfaces are not enabled for proxy
788 # ARP
789 #
790 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
791 "ARP req from unconfigured interface")
792 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
793 "ARP req from unconfigured interface")
794
795 #
796 # Make pg2 un-numbered to pg1
797 # still won't reply.
798 #
799 self.pg2.set_unnumbered(self.pg1.sw_if_index)
800
801 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
802 "ARP req from unnumbered interface")
803
804 #
805 # Enable each interface to reply to proxy ARPs
806 #
807 for i in self.pg_interfaces:
808 i.set_proxy_arp()
809
810 #
811 # Now each of the interfaces should reply to a request to a proxied
812 # address
813 #
814 self.pg0.add_stream(arp_req_pg0)
815 self.pg_enable_capture(self.pg_interfaces)
816 self.pg_start()
817
818 rx = self.pg0.get_capture(1)
819 self.verify_arp_resp(rx[0],
820 self.pg0.local_mac,
821 self.pg0.remote_mac,
822 "10.10.10.3",
823 self.pg0.remote_ip4)
824
Neale Ranns30d0fd42017-05-30 07:30:04 -0700825 self.pg0.add_stream(arp_req_pg0_tagged)
826 self.pg_enable_capture(self.pg_interfaces)
827 self.pg_start()
828
829 rx = self.pg0.get_capture(1)
830 self.verify_arp_resp(rx[0],
831 self.pg0.local_mac,
832 self.pg0.remote_mac,
833 "10.10.10.3",
834 self.pg0.remote_ip4)
835
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800836 self.pg1.add_stream(arp_req_pg1)
837 self.pg_enable_capture(self.pg_interfaces)
838 self.pg_start()
839
840 rx = self.pg1.get_capture(1)
841 self.verify_arp_resp(rx[0],
842 self.pg1.local_mac,
843 self.pg1.remote_mac,
844 "10.10.10.3",
845 self.pg1.remote_ip4)
846
847 self.pg2.add_stream(arp_req_pg2)
848 self.pg_enable_capture(self.pg_interfaces)
849 self.pg_start()
850
851 rx = self.pg2.get_capture(1)
852 self.verify_arp_resp(rx[0],
853 self.pg2.local_mac,
854 self.pg2.remote_mac,
855 "10.10.10.3",
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700856 self.pg1.remote_hosts[1].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800857
858 #
859 # A request for an address out of the configured range
860 #
861 arp_req_pg1_hi = (Ether(src=self.pg1.remote_mac,
862 dst="ff:ff:ff:ff:ff:ff") /
863 ARP(op="who-has",
864 hwsrc=self.pg1.remote_mac,
865 pdst="10.10.10.125",
866 psrc=self.pg1.remote_ip4))
867 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_hi,
868 "ARP req out of range HI")
869 arp_req_pg1_low = (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.1",
874 psrc=self.pg1.remote_ip4))
875 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_low,
876 "ARP req out of range Low")
877
878 #
879 # Request for an address in the proxy range but from an interface
880 # in a different VRF
881 #
882 self.send_and_assert_no_replies(self.pg3, arp_req_pg3,
883 "ARP req from different VRF")
884
885 #
886 # Disable Each interface for proxy ARP
887 # - expect none to respond
888 #
889 for i in self.pg_interfaces:
890 i.set_proxy_arp(0)
891
892 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
893 "ARP req from disable")
894 self.send_and_assert_no_replies(self.pg1, arp_req_pg1,
895 "ARP req from disable")
896 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
897 "ARP req from disable")
Neale Ranns37be7362017-02-21 17:30:26 -0800898
899 #
900 # clean up on interface 2
901 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800902 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns37be7362017-02-21 17:30:26 -0800903
904 def test_mpls(self):
905 """ MPLS """
906
907 #
908 # Interface 2 does not yet have ip4 config
909 #
910 self.pg2.config_ip4()
911 self.pg2.generate_remote_hosts(2)
912
913 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700914 # Add a route with out going label via an ARP unresolved next-hop
Neale Ranns37be7362017-02-21 17:30:26 -0800915 #
916 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
917 [VppRoutePath(self.pg2.remote_hosts[1].ip4,
918 self.pg2.sw_if_index,
919 labels=[55])])
920 ip_10_0_0_1.add_vpp_config()
921
922 #
923 # packets should generate an ARP request
924 #
925 p = (Ether(src=self.pg0.remote_mac,
926 dst=self.pg0.local_mac) /
927 IP(src=self.pg0.remote_ip4, dst="10.0.0.1") /
928 UDP(sport=1234, dport=1234) /
929 Raw('\xa5' * 100))
930
931 self.pg0.add_stream(p)
932 self.pg_enable_capture(self.pg_interfaces)
933 self.pg_start()
934
935 rx = self.pg2.get_capture(1)
936 self.verify_arp_req(rx[0],
937 self.pg2.local_mac,
938 self.pg2.local_ip4,
939 self.pg2._remote_hosts[1].ip4)
940
941 #
942 # now resolve the neighbours
943 #
944 self.pg2.configure_ipv4_neighbors()
945
946 #
947 # Now packet should be properly MPLS encapped.
948 # This verifies that MPLS link-type adjacencies are completed
949 # when the ARP entry resolves
950 #
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_ip_o_mpls(rx[0],
957 self.pg2.local_mac,
958 self.pg2.remote_hosts[1].mac,
959 55,
960 self.pg0.remote_ip4,
961 "10.0.0.1")
Neale Ranns4b919a52017-03-11 05:55:21 -0800962 self.pg2.unconfig_ip4()
Neale Ranns37be7362017-02-21 17:30:26 -0800963
Matthew Smithcb9ab472017-05-16 21:35:56 -0500964 def test_arp_vrrp(self):
965 """ ARP reply with VRRP virtual src hw addr """
966
967 #
968 # IP packet destined for pg1 remote host arrives on pg0 resulting
969 # in an ARP request for the address of the remote host on pg1
970 #
971 p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
972 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
973 UDP(sport=1234, dport=1234) /
974 Raw())
975
Neale Ranns37029302018-08-10 05:30:06 -0700976 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
Matthew Smithcb9ab472017-05-16 21:35:56 -0500977
978 self.verify_arp_req(rx1[0],
979 self.pg1.local_mac,
980 self.pg1.local_ip4,
981 self.pg1.remote_ip4)
982
983 #
984 # ARP reply for address of pg1 remote host arrives on pg1 with
985 # the hw src addr set to a value in the VRRP IPv4 range of
986 # MAC addresses
987 #
988 p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
989 ARP(op="is-at", hwdst=self.pg1.local_mac,
990 hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
991 psrc=self.pg1.remote_ip4))
992
Neale Ranns37029302018-08-10 05:30:06 -0700993 self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
Matthew Smithcb9ab472017-05-16 21:35:56 -0500994
995 #
996 # IP packet destined for pg1 remote host arrives on pg0 again.
997 # VPP should have an ARP entry for that address now and the packet
998 # should be sent out pg1.
999 #
Neale Ranns37029302018-08-10 05:30:06 -07001000 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
Matthew Smithcb9ab472017-05-16 21:35:56 -05001001
1002 self.verify_ip(rx1[0],
1003 self.pg1.local_mac,
1004 "00:00:5e:00:01:09",
1005 self.pg0.remote_ip4,
1006 self.pg1.remote_ip4)
1007
1008 self.pg1.admin_down()
1009 self.pg1.admin_up()
1010
Neale Rannsdcd6d622017-05-26 02:59:16 -07001011 def test_arp_duplicates(self):
1012 """ ARP Duplicates"""
1013
1014 #
1015 # Generate some hosts on the LAN
1016 #
1017 self.pg1.generate_remote_hosts(3)
1018
1019 #
1020 # Add host 1 on pg1 and pg2
1021 #
1022 arp_pg1 = VppNeighbor(self,
1023 self.pg1.sw_if_index,
1024 self.pg1.remote_hosts[1].mac,
1025 self.pg1.remote_hosts[1].ip4)
1026 arp_pg1.add_vpp_config()
1027 arp_pg2 = VppNeighbor(self,
1028 self.pg2.sw_if_index,
1029 self.pg2.remote_mac,
1030 self.pg1.remote_hosts[1].ip4)
1031 arp_pg2.add_vpp_config()
1032
1033 #
1034 # IP packet destined for pg1 remote host arrives on pg1 again.
1035 #
1036 p = (Ether(dst=self.pg0.local_mac,
1037 src=self.pg0.remote_mac) /
1038 IP(src=self.pg0.remote_ip4,
1039 dst=self.pg1.remote_hosts[1].ip4) /
1040 UDP(sport=1234, dport=1234) /
1041 Raw())
1042
1043 self.pg0.add_stream(p)
1044 self.pg_enable_capture(self.pg_interfaces)
1045 self.pg_start()
1046
1047 rx1 = self.pg1.get_capture(1)
1048
1049 self.verify_ip(rx1[0],
1050 self.pg1.local_mac,
1051 self.pg1.remote_hosts[1].mac,
1052 self.pg0.remote_ip4,
1053 self.pg1.remote_hosts[1].ip4)
1054
1055 #
1056 # remove the duplicate on pg1
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001057 # packet stream should generate ARPs out of pg1
Neale Rannsdcd6d622017-05-26 02:59:16 -07001058 #
1059 arp_pg1.remove_vpp_config()
1060
1061 self.pg0.add_stream(p)
1062 self.pg_enable_capture(self.pg_interfaces)
1063 self.pg_start()
1064
1065 rx1 = self.pg1.get_capture(1)
1066
1067 self.verify_arp_req(rx1[0],
1068 self.pg1.local_mac,
1069 self.pg1.local_ip4,
1070 self.pg1.remote_hosts[1].ip4)
1071
1072 #
1073 # Add it back
1074 #
1075 arp_pg1.add_vpp_config()
1076
1077 self.pg0.add_stream(p)
1078 self.pg_enable_capture(self.pg_interfaces)
1079 self.pg_start()
1080
1081 rx1 = self.pg1.get_capture(1)
1082
1083 self.verify_ip(rx1[0],
1084 self.pg1.local_mac,
1085 self.pg1.remote_hosts[1].mac,
1086 self.pg0.remote_ip4,
1087 self.pg1.remote_hosts[1].ip4)
1088
Neale Ranns15002542017-09-10 04:39:11 -07001089 def test_arp_static(self):
1090 """ ARP Static"""
1091 self.pg2.generate_remote_hosts(3)
1092
1093 #
1094 # Add a static ARP entry
1095 #
1096 static_arp = VppNeighbor(self,
1097 self.pg2.sw_if_index,
1098 self.pg2.remote_hosts[1].mac,
1099 self.pg2.remote_hosts[1].ip4,
1100 is_static=1)
1101 static_arp.add_vpp_config()
1102
1103 #
1104 # Add the connected prefix to the interface
1105 #
1106 self.pg2.config_ip4()
1107
1108 #
1109 # We should now find the adj-fib
1110 #
1111 self.assertTrue(find_nbr(self,
1112 self.pg2.sw_if_index,
1113 self.pg2.remote_hosts[1].ip4,
1114 is_static=1))
1115 self.assertTrue(find_route(self,
1116 self.pg2.remote_hosts[1].ip4,
1117 32))
1118
1119 #
1120 # remove the connected
1121 #
1122 self.pg2.unconfig_ip4()
1123
1124 #
1125 # put the interface into table 1
1126 #
1127 self.pg2.set_table_ip4(1)
1128
1129 #
1130 # configure the same connected and expect to find the
1131 # adj fib in the new table
1132 #
1133 self.pg2.config_ip4()
1134 self.assertTrue(find_route(self,
1135 self.pg2.remote_hosts[1].ip4,
1136 32,
1137 table_id=1))
1138
1139 #
1140 # clean-up
1141 #
1142 self.pg2.unconfig_ip4()
1143 self.pg2.set_table_ip4(0)
1144
Neale Rannsc819fc62018-02-16 02:44:05 -08001145 def test_arp_incomplete(self):
1146 """ ARP Incomplete"""
1147 self.pg1.generate_remote_hosts(3)
1148
1149 p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1150 IP(src=self.pg0.remote_ip4,
1151 dst=self.pg1.remote_hosts[1].ip4) /
1152 UDP(sport=1234, dport=1234) /
1153 Raw())
1154 p1 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1155 IP(src=self.pg0.remote_ip4,
1156 dst=self.pg1.remote_hosts[2].ip4) /
1157 UDP(sport=1234, dport=1234) /
1158 Raw())
1159
1160 #
1161 # a packet to an unresolved destination generates an ARP request
1162 #
1163 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1164 self.verify_arp_req(rx[0],
1165 self.pg1.local_mac,
1166 self.pg1.local_ip4,
1167 self.pg1._remote_hosts[1].ip4)
1168
1169 #
1170 # add a neighbour for remote host 1
1171 #
1172 static_arp = VppNeighbor(self,
1173 self.pg1.sw_if_index,
1174 self.pg1.remote_hosts[1].mac,
1175 self.pg1.remote_hosts[1].ip4,
1176 is_static=1)
1177 static_arp.add_vpp_config()
1178
1179 #
1180 # change the interface's MAC
1181 #
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001182 mac = [scapy.compat.chb(0x00), scapy.compat.chb(0x00),
1183 scapy.compat.chb(0x00), scapy.compat.chb(0x33),
1184 scapy.compat.chb(0x33), scapy.compat.chb(0x33)]
Neale Rannsc819fc62018-02-16 02:44:05 -08001185 mac_string = ''.join(mac)
1186
1187 self.vapi.sw_interface_set_mac_address(self.pg1.sw_if_index,
1188 mac_string)
1189
1190 #
1191 # now ARP requests come from the new source mac
1192 #
1193 rx = self.send_and_expect(self.pg0, [p1], self.pg1)
1194 self.verify_arp_req(rx[0],
1195 "00:00:00:33:33:33",
1196 self.pg1.local_ip4,
1197 self.pg1._remote_hosts[2].ip4)
1198
1199 #
1200 # packets to the resolved host also have the new source mac
1201 #
1202 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1203 self.verify_ip(rx[0],
1204 "00:00:00:33:33:33",
1205 self.pg1.remote_hosts[1].mac,
1206 self.pg0.remote_ip4,
1207 self.pg1.remote_hosts[1].ip4)
1208
1209 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001210 # set the mac address on the interface that does not have a
Neale Rannsc819fc62018-02-16 02:44:05 -08001211 # configured subnet and thus no glean
1212 #
1213 self.vapi.sw_interface_set_mac_address(self.pg2.sw_if_index,
1214 mac_string)
1215
Neale Ranns59ae61e2018-06-07 18:09:49 -07001216 def test_garp(self):
1217 """ GARP """
1218
1219 #
1220 # Generate some hosts on the LAN
1221 #
1222 self.pg1.generate_remote_hosts(4)
1223
1224 #
1225 # And an ARP entry
1226 #
1227 arp = VppNeighbor(self,
1228 self.pg1.sw_if_index,
1229 self.pg1.remote_hosts[1].mac,
1230 self.pg1.remote_hosts[1].ip4)
1231 arp.add_vpp_config()
1232
1233 self.assertTrue(find_nbr(self,
1234 self.pg1.sw_if_index,
1235 self.pg1.remote_hosts[1].ip4,
1236 mac=self.pg1.remote_hosts[1].mac))
1237
1238 #
1239 # Send a GARP (request) to swap the host 1's address to that of host 2
1240 #
1241 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1242 src=self.pg1.remote_hosts[2].mac) /
1243 ARP(op="who-has",
1244 hwdst=self.pg1.local_mac,
1245 hwsrc=self.pg1.remote_hosts[2].mac,
1246 pdst=self.pg1.remote_hosts[1].ip4,
1247 psrc=self.pg1.remote_hosts[1].ip4))
1248
1249 self.pg1.add_stream(p1)
1250 self.pg_enable_capture(self.pg_interfaces)
1251 self.pg_start()
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[2].mac))
1257
1258 #
1259 # Send a GARP (reply) to swap the host 1's address to that of host 3
1260 #
1261 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1262 src=self.pg1.remote_hosts[3].mac) /
1263 ARP(op="is-at",
1264 hwdst=self.pg1.local_mac,
1265 hwsrc=self.pg1.remote_hosts[3].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[3].mac))
1277
1278 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001279 # GARPs (request nor replies) for host we don't know yet
Neale Ranns59ae61e2018-06-07 18:09:49 -07001280 # don't result in new neighbour entries
1281 #
1282 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1283 src=self.pg1.remote_hosts[3].mac) /
1284 ARP(op="who-has",
1285 hwdst=self.pg1.local_mac,
1286 hwsrc=self.pg1.remote_hosts[3].mac,
1287 pdst=self.pg1.remote_hosts[2].ip4,
1288 psrc=self.pg1.remote_hosts[2].ip4))
1289
1290 self.pg1.add_stream(p1)
1291 self.pg_enable_capture(self.pg_interfaces)
1292 self.pg_start()
1293
1294 self.assertFalse(find_nbr(self,
1295 self.pg1.sw_if_index,
1296 self.pg1.remote_hosts[2].ip4))
1297
1298 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1299 src=self.pg1.remote_hosts[3].mac) /
1300 ARP(op="is-at",
1301 hwdst=self.pg1.local_mac,
1302 hwsrc=self.pg1.remote_hosts[3].mac,
1303 pdst=self.pg1.remote_hosts[2].ip4,
1304 psrc=self.pg1.remote_hosts[2].ip4))
1305
1306 self.pg1.add_stream(p1)
1307 self.pg_enable_capture(self.pg_interfaces)
1308 self.pg_start()
1309
1310 self.assertFalse(find_nbr(self,
1311 self.pg1.sw_if_index,
1312 self.pg1.remote_hosts[2].ip4))
1313
Neale Rannsc8352bc2018-08-29 10:23:58 -07001314 def test_arp_incomplete(self):
Neale Ranns14260392018-09-28 05:00:57 -07001315 """ Incomplete Entries """
Neale Rannsc8352bc2018-08-29 10:23:58 -07001316
1317 #
Neale Rannscd35e532018-08-31 02:51:45 -07001318 # ensure that we throttle the ARP and ND requests
Neale Rannsc8352bc2018-08-29 10:23:58 -07001319 #
1320 self.pg0.generate_remote_hosts(2)
1321
Neale Rannscd35e532018-08-31 02:51:45 -07001322 #
1323 # IPv4/ARP
1324 #
Neale Rannsc8352bc2018-08-29 10:23:58 -07001325 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1326 [VppRoutePath(self.pg0.remote_hosts[1].ip4,
Neale Rannscd35e532018-08-31 02:51:45 -07001327 self.pg0.sw_if_index)])
Neale Rannsc8352bc2018-08-29 10:23:58 -07001328 ip_10_0_0_1.add_vpp_config()
1329
1330 p1 = (Ether(dst=self.pg1.local_mac,
1331 src=self.pg1.remote_mac) /
1332 IP(src=self.pg1.remote_ip4,
1333 dst="10.0.0.1") /
1334 UDP(sport=1234, dport=1234) /
1335 Raw())
1336
1337 self.pg1.add_stream(p1 * 257)
1338 self.pg_enable_capture(self.pg_interfaces)
1339 self.pg_start()
1340 rx = self.pg0._get_capture(1)
1341
1342 #
1343 # how many we get is going to be dependent on the time for packet
1344 # processing but it should be small
1345 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001346 self.assertLess(len(rx), 64)
Neale Rannsc8352bc2018-08-29 10:23:58 -07001347
Neale Rannscd35e532018-08-31 02:51:45 -07001348 #
1349 # IPv6/ND
1350 #
1351 ip_10_1 = VppIpRoute(self, "10::1", 128,
1352 [VppRoutePath(self.pg0.remote_hosts[1].ip6,
1353 self.pg0.sw_if_index,
1354 proto=DpoProto.DPO_PROTO_IP6)],
1355 is_ip6=1)
1356 ip_10_1.add_vpp_config()
1357
1358 p1 = (Ether(dst=self.pg1.local_mac,
1359 src=self.pg1.remote_mac) /
1360 IPv6(src=self.pg1.remote_ip6,
1361 dst="10::1") /
1362 UDP(sport=1234, dport=1234) /
1363 Raw())
1364
1365 self.pg1.add_stream(p1 * 257)
1366 self.pg_enable_capture(self.pg_interfaces)
1367 self.pg_start()
1368 rx = self.pg0._get_capture(1)
1369
1370 #
1371 # how many we get is going to be dependent on the time for packet
1372 # processing but it should be small
1373 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001374 self.assertLess(len(rx), 64)
Neale Rannscd35e532018-08-31 02:51:45 -07001375
Neale Ranns7425f922019-01-23 00:36:16 -08001376 def test_arp_forus(self):
1377 """ ARP for for-us """
1378
1379 #
1380 # Test that VPP responds with ARP requests to addresses that
1381 # are connected and local routes.
1382 # Use one of the 'remote' addresses in the subnet as a local address
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001383 # The intention of this route is that it then acts like a secondary
Neale Ranns7425f922019-01-23 00:36:16 -08001384 # address added to an interface
1385 #
1386 self.pg0.generate_remote_hosts(2)
1387
1388 forus = VppIpRoute(self, self.pg0.remote_hosts[1].ip4, 32,
1389 [VppRoutePath(self.pg0.remote_hosts[1].ip4,
1390 self.pg0.sw_if_index)],
1391 is_local=1)
1392 forus.add_vpp_config()
1393
1394 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
1395 src=self.pg0.remote_mac) /
1396 ARP(op="who-has",
1397 hwdst=self.pg0.local_mac,
1398 hwsrc=self.pg0.remote_mac,
1399 pdst=self.pg0.remote_hosts[1].ip4,
1400 psrc=self.pg0.remote_ip4))
1401
1402 rx = self.send_and_expect(self.pg0, [p], self.pg0)
1403
1404 self.verify_arp_resp(rx[0],
1405 self.pg0.local_mac,
1406 self.pg0.remote_mac,
1407 self.pg0.remote_hosts[1].ip4,
1408 self.pg0.remote_ip4)
1409
Neale Rannsdcd6d622017-05-26 02:59:16 -07001410
Neale Ranns14260392018-09-28 05:00:57 -07001411class NeighborStatsTestCase(VppTestCase):
Neale Ranns37029302018-08-10 05:30:06 -07001412 """ ARP/ND Counters """
Neale Ranns14260392018-09-28 05:00:57 -07001413
1414 def setUp(self):
1415 super(NeighborStatsTestCase, self).setUp()
1416
1417 self.create_pg_interfaces(range(2))
1418
1419 # pg0 configured with ip4 and 6 addresses used for input
1420 # pg1 configured with ip4 and 6 addresses used for output
1421 # pg2 is unnumbered to pg0
1422 for i in self.pg_interfaces:
1423 i.admin_up()
1424 i.config_ip4()
1425 i.config_ip6()
1426 i.resolve_arp()
1427 i.resolve_ndp()
1428
1429 def tearDown(self):
1430 super(NeighborStatsTestCase, self).tearDown()
1431
1432 for i in self.pg_interfaces:
1433 i.unconfig_ip4()
1434 i.unconfig_ip6()
1435 i.admin_down()
1436
1437 def test_arp_stats(self):
1438 """ ARP Counters """
1439
1440 self.vapi.cli("adj counters enable")
1441 self.pg1.generate_remote_hosts(2)
1442
1443 arp1 = VppNeighbor(self,
1444 self.pg1.sw_if_index,
1445 self.pg1.remote_hosts[0].mac,
1446 self.pg1.remote_hosts[0].ip4)
1447 arp1.add_vpp_config()
1448 arp2 = VppNeighbor(self,
1449 self.pg1.sw_if_index,
1450 self.pg1.remote_hosts[1].mac,
1451 self.pg1.remote_hosts[1].ip4)
1452 arp2.add_vpp_config()
1453
1454 p1 = (Ether(dst=self.pg0.local_mac,
1455 src=self.pg0.remote_mac) /
1456 IP(src=self.pg0.remote_ip4,
1457 dst=self.pg1.remote_hosts[0].ip4) /
1458 UDP(sport=1234, dport=1234) /
1459 Raw())
1460 p2 = (Ether(dst=self.pg0.local_mac,
1461 src=self.pg0.remote_mac) /
1462 IP(src=self.pg0.remote_ip4,
1463 dst=self.pg1.remote_hosts[1].ip4) /
1464 UDP(sport=1234, dport=1234) /
1465 Raw())
1466
1467 rx = self.send_and_expect(self.pg0, p1 * 65, self.pg1)
1468 rx = self.send_and_expect(self.pg0, p2 * 65, self.pg1)
1469
1470 self.assertEqual(65, arp1.get_stats()['packets'])
1471 self.assertEqual(65, arp2.get_stats()['packets'])
1472
1473 rx = self.send_and_expect(self.pg0, p1 * 65, self.pg1)
1474 self.assertEqual(130, arp1.get_stats()['packets'])
1475
1476 def test_nd_stats(self):
1477 """ ND Counters """
1478
1479 self.vapi.cli("adj counters enable")
1480 self.pg0.generate_remote_hosts(3)
1481
1482 nd1 = VppNeighbor(self,
1483 self.pg0.sw_if_index,
1484 self.pg0.remote_hosts[1].mac,
Neale Ranns37029302018-08-10 05:30:06 -07001485 self.pg0.remote_hosts[1].ip6)
Neale Ranns14260392018-09-28 05:00:57 -07001486 nd1.add_vpp_config()
1487 nd2 = VppNeighbor(self,
1488 self.pg0.sw_if_index,
1489 self.pg0.remote_hosts[2].mac,
Neale Ranns37029302018-08-10 05:30:06 -07001490 self.pg0.remote_hosts[2].ip6)
Neale Ranns14260392018-09-28 05:00:57 -07001491 nd2.add_vpp_config()
1492
1493 p1 = (Ether(dst=self.pg1.local_mac,
1494 src=self.pg1.remote_mac) /
1495 IPv6(src=self.pg1.remote_ip6,
1496 dst=self.pg0.remote_hosts[1].ip6) /
1497 UDP(sport=1234, dport=1234) /
1498 Raw())
1499 p2 = (Ether(dst=self.pg1.local_mac,
1500 src=self.pg1.remote_mac) /
1501 IPv6(src=self.pg1.remote_ip6,
1502 dst=self.pg0.remote_hosts[2].ip6) /
1503 UDP(sport=1234, dport=1234) /
1504 Raw())
1505
1506 rx = self.send_and_expect(self.pg1, p1 * 16, self.pg0)
1507 rx = self.send_and_expect(self.pg1, p2 * 16, self.pg0)
1508
1509 self.assertEqual(16, nd1.get_stats()['packets'])
1510 self.assertEqual(16, nd2.get_stats()['packets'])
1511
1512 rx = self.send_and_expect(self.pg1, p1 * 65, self.pg0)
1513 self.assertEqual(81, nd1.get_stats()['packets'])
1514
1515
Neale Ranns37be7362017-02-21 17:30:26 -08001516if __name__ == '__main__':
1517 unittest.main(testRunner=VppTestRunner)