blob: 69b00ea6ff2783d42d070584ef09565afcd43bea [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 Ranns097fa662018-05-01 05:17:55 -07009 VppIpTable, DpoProto, FibPathType
Neale Ranns37029302018-08-10 05:30:06 -070010from vpp_papi import VppEnum
Neale Ranns39f9d8b2017-02-16 21:57:05 -080011
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -070012import scapy.compat
Neale Ranns39f9d8b2017-02-16 21:57:05 -080013from scapy.packet import Raw
Neale Ranns30d0fd42017-05-30 07:30:04 -070014from scapy.layers.l2 import Ether, ARP, Dot1Q
Neale Ranns39f9d8b2017-02-16 21:57:05 -080015from scapy.layers.inet import IP, UDP
Neale Rannscd35e532018-08-31 02:51:45 -070016from scapy.layers.inet6 import IPv6
Neale Ranns37be7362017-02-21 17:30:26 -080017from scapy.contrib.mpls import MPLS
Neale Ranns14260392018-09-28 05:00:57 -070018from scapy.layers.inet6 import IPv6
Neale Ranns39f9d8b2017-02-16 21:57:05 -080019
Paul Vinciguerra4271c972019-05-14 13:25:49 -040020
21NUM_PKTS = 67
22
Neale Ranns39f9d8b2017-02-16 21:57:05 -080023# not exported by scapy, so redefined here
24arp_opts = {"who-has": 1, "is-at": 2}
25
26
27class ARPTestCase(VppTestCase):
28 """ ARP Test Case """
29
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070030 @classmethod
31 def setUpClass(cls):
32 super(ARPTestCase, cls).setUpClass()
33
34 @classmethod
35 def tearDownClass(cls):
36 super(ARPTestCase, cls).tearDownClass()
37
Neale Ranns39f9d8b2017-02-16 21:57:05 -080038 def setUp(self):
39 super(ARPTestCase, self).setUp()
40
41 # create 3 pg interfaces
42 self.create_pg_interfaces(range(4))
43
44 # pg0 configured with ip4 and 6 addresses used for input
45 # pg1 configured with ip4 and 6 addresses used for output
46 # pg2 is unnumbered to pg0
47 for i in self.pg_interfaces:
48 i.admin_up()
49
50 self.pg0.config_ip4()
51 self.pg0.config_ip6()
52 self.pg0.resolve_arp()
53
54 self.pg1.config_ip4()
55 self.pg1.config_ip6()
56
57 # pg3 in a different VRF
Neale Ranns15002542017-09-10 04:39:11 -070058 self.tbl = VppIpTable(self, 1)
59 self.tbl.add_vpp_config()
60
Neale Ranns39f9d8b2017-02-16 21:57:05 -080061 self.pg3.set_table_ip4(1)
62 self.pg3.config_ip4()
63
Neale Ranns4008ac92017-02-13 23:20:04 -080064 def tearDown(self):
Neale Ranns4b919a52017-03-11 05:55:21 -080065 self.pg0.unconfig_ip4()
66 self.pg0.unconfig_ip6()
67
68 self.pg1.unconfig_ip4()
69 self.pg1.unconfig_ip6()
70
71 self.pg3.unconfig_ip4()
Neale Ranns15002542017-09-10 04:39:11 -070072 self.pg3.set_table_ip4(0)
Neale Ranns4b919a52017-03-11 05:55:21 -080073
Neale Ranns4008ac92017-02-13 23:20:04 -080074 for i in self.pg_interfaces:
Neale Ranns4008ac92017-02-13 23:20:04 -080075 i.admin_down()
76
Neale Ranns15002542017-09-10 04:39:11 -070077 super(ARPTestCase, self).tearDown()
78
Neale Ranns39f9d8b2017-02-16 21:57:05 -080079 def verify_arp_req(self, rx, smac, sip, dip):
80 ether = rx[Ether]
81 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
82 self.assertEqual(ether.src, smac)
83
84 arp = rx[ARP]
85 self.assertEqual(arp.hwtype, 1)
86 self.assertEqual(arp.ptype, 0x800)
87 self.assertEqual(arp.hwlen, 6)
88 self.assertEqual(arp.plen, 4)
89 self.assertEqual(arp.op, arp_opts["who-has"])
90 self.assertEqual(arp.hwsrc, smac)
91 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
92 self.assertEqual(arp.psrc, sip)
93 self.assertEqual(arp.pdst, dip)
94
95 def verify_arp_resp(self, rx, smac, dmac, sip, dip):
96 ether = rx[Ether]
97 self.assertEqual(ether.dst, dmac)
98 self.assertEqual(ether.src, smac)
99
100 arp = rx[ARP]
101 self.assertEqual(arp.hwtype, 1)
102 self.assertEqual(arp.ptype, 0x800)
103 self.assertEqual(arp.hwlen, 6)
104 self.assertEqual(arp.plen, 4)
105 self.assertEqual(arp.op, arp_opts["is-at"])
106 self.assertEqual(arp.hwsrc, smac)
107 self.assertEqual(arp.hwdst, dmac)
108 self.assertEqual(arp.psrc, sip)
109 self.assertEqual(arp.pdst, dip)
110
Matthew Smithcb9ab472017-05-16 21:35:56 -0500111 def verify_arp_vrrp_resp(self, rx, smac, dmac, sip, dip):
112 ether = rx[Ether]
113 self.assertEqual(ether.dst, dmac)
114 self.assertEqual(ether.src, smac)
115
116 arp = rx[ARP]
117 self.assertEqual(arp.hwtype, 1)
118 self.assertEqual(arp.ptype, 0x800)
119 self.assertEqual(arp.hwlen, 6)
120 self.assertEqual(arp.plen, 4)
121 self.assertEqual(arp.op, arp_opts["is-at"])
122 self.assertNotEqual(arp.hwsrc, smac)
123 self.assertTrue("00:00:5e:00:01" in arp.hwsrc or
124 "00:00:5E:00:01" in arp.hwsrc)
125 self.assertEqual(arp.hwdst, dmac)
126 self.assertEqual(arp.psrc, sip)
127 self.assertEqual(arp.pdst, dip)
128
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800129 def verify_ip(self, rx, smac, dmac, sip, dip):
130 ether = rx[Ether]
131 self.assertEqual(ether.dst, dmac)
132 self.assertEqual(ether.src, smac)
133
134 ip = rx[IP]
135 self.assertEqual(ip.src, sip)
136 self.assertEqual(ip.dst, dip)
137
Neale Ranns37be7362017-02-21 17:30:26 -0800138 def verify_ip_o_mpls(self, rx, smac, dmac, label, sip, dip):
139 ether = rx[Ether]
140 self.assertEqual(ether.dst, dmac)
141 self.assertEqual(ether.src, smac)
142
143 mpls = rx[MPLS]
144 self.assertTrue(mpls.label, label)
145
146 ip = rx[IP]
147 self.assertEqual(ip.src, sip)
148 self.assertEqual(ip.dst, dip)
149
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800150 def test_arp(self):
151 """ ARP """
152
153 #
154 # Generate some hosts on the LAN
155 #
Neale Rannsca193612017-06-14 06:50:08 -0700156 self.pg1.generate_remote_hosts(11)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800157
158 #
159 # Send IP traffic to one of these unresolved hosts.
160 # expect the generation of an ARP request
161 #
162 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
163 IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[1].ip4) /
164 UDP(sport=1234, dport=1234) /
165 Raw())
166
167 self.pg0.add_stream(p)
168 self.pg_enable_capture(self.pg_interfaces)
169 self.pg_start()
170
171 rx = self.pg1.get_capture(1)
172
173 self.verify_arp_req(rx[0],
174 self.pg1.local_mac,
175 self.pg1.local_ip4,
176 self.pg1._remote_hosts[1].ip4)
177
178 #
179 # And a dynamic ARP entry for host 1
180 #
181 dyn_arp = VppNeighbor(self,
182 self.pg1.sw_if_index,
183 self.pg1.remote_hosts[1].mac,
184 self.pg1.remote_hosts[1].ip4)
185 dyn_arp.add_vpp_config()
186
187 #
188 # now we expect IP traffic forwarded
189 #
190 dyn_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
191 IP(src=self.pg0.remote_ip4,
192 dst=self.pg1._remote_hosts[1].ip4) /
193 UDP(sport=1234, dport=1234) /
194 Raw())
195
196 self.pg0.add_stream(dyn_p)
197 self.pg_enable_capture(self.pg_interfaces)
198 self.pg_start()
199
200 rx = self.pg1.get_capture(1)
201
202 self.verify_ip(rx[0],
203 self.pg1.local_mac,
204 self.pg1.remote_hosts[1].mac,
205 self.pg0.remote_ip4,
206 self.pg1._remote_hosts[1].ip4)
207
208 #
209 # And a Static ARP entry for host 2
210 #
211 static_arp = VppNeighbor(self,
212 self.pg1.sw_if_index,
213 self.pg1.remote_hosts[2].mac,
214 self.pg1.remote_hosts[2].ip4,
215 is_static=1)
216 static_arp.add_vpp_config()
217
218 static_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
219 IP(src=self.pg0.remote_ip4,
220 dst=self.pg1._remote_hosts[2].ip4) /
221 UDP(sport=1234, dport=1234) /
222 Raw())
223
224 self.pg0.add_stream(static_p)
225 self.pg_enable_capture(self.pg_interfaces)
226 self.pg_start()
227
228 rx = self.pg1.get_capture(1)
229
230 self.verify_ip(rx[0],
231 self.pg1.local_mac,
232 self.pg1.remote_hosts[2].mac,
233 self.pg0.remote_ip4,
234 self.pg1._remote_hosts[2].ip4)
235
236 #
237 # flap the link. dynamic ARPs get flush, statics don't
238 #
239 self.pg1.admin_down()
240 self.pg1.admin_up()
241
242 self.pg0.add_stream(static_p)
243 self.pg_enable_capture(self.pg_interfaces)
244 self.pg_start()
245 rx = self.pg1.get_capture(1)
246
247 self.verify_ip(rx[0],
248 self.pg1.local_mac,
249 self.pg1.remote_hosts[2].mac,
250 self.pg0.remote_ip4,
251 self.pg1._remote_hosts[2].ip4)
252
253 self.pg0.add_stream(dyn_p)
254 self.pg_enable_capture(self.pg_interfaces)
255 self.pg_start()
256
257 rx = self.pg1.get_capture(1)
258 self.verify_arp_req(rx[0],
259 self.pg1.local_mac,
260 self.pg1.local_ip4,
261 self.pg1._remote_hosts[1].ip4)
262
263 #
264 # Send an ARP request from one of the so-far unlearned remote hosts
265 #
266 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
267 src=self.pg1._remote_hosts[3].mac) /
268 ARP(op="who-has",
269 hwsrc=self.pg1._remote_hosts[3].mac,
270 pdst=self.pg1.local_ip4,
271 psrc=self.pg1._remote_hosts[3].ip4))
272
273 self.pg1.add_stream(p)
274 self.pg_enable_capture(self.pg_interfaces)
275 self.pg_start()
276
277 rx = self.pg1.get_capture(1)
278 self.verify_arp_resp(rx[0],
279 self.pg1.local_mac,
280 self.pg1._remote_hosts[3].mac,
281 self.pg1.local_ip4,
282 self.pg1._remote_hosts[3].ip4)
283
284 #
285 # VPP should have learned the mapping for the remote host
286 #
287 self.assertTrue(find_nbr(self,
288 self.pg1.sw_if_index,
289 self.pg1._remote_hosts[3].ip4))
Neale Ranns4b919a52017-03-11 05:55:21 -0800290 #
291 # Fire in an ARP request before the interface becomes IP enabled
292 #
293 self.pg2.generate_remote_hosts(4)
294
295 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
296 ARP(op="who-has",
297 hwsrc=self.pg2.remote_mac,
298 pdst=self.pg1.local_ip4,
299 psrc=self.pg2.remote_hosts[3].ip4))
Neale Ranns30d0fd42017-05-30 07:30:04 -0700300 pt = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
301 Dot1Q(vlan=0) /
302 ARP(op="who-has",
303 hwsrc=self.pg2.remote_mac,
304 pdst=self.pg1.local_ip4,
305 psrc=self.pg2.remote_hosts[3].ip4))
Neale Ranns4b919a52017-03-11 05:55:21 -0800306 self.send_and_assert_no_replies(self.pg2, p,
307 "interface not IP enabled")
308
309 #
310 # Make pg2 un-numbered to pg1
311 #
312 self.pg2.set_unnumbered(self.pg1.sw_if_index)
313
Neale Ranns404d88e2018-08-08 06:37:33 -0700314 unnum = self.vapi.ip_unnumbered_dump()
315 self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
316 self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)
317
Neale Ranns4b919a52017-03-11 05:55:21 -0800318 #
319 # We should respond to ARP requests for the unnumbered to address
320 # once an attached route to the source is known
321 #
322 self.send_and_assert_no_replies(
323 self.pg2, p,
324 "ARP req for unnumbered address - no source")
325
326 attached_host = VppIpRoute(self, self.pg2.remote_hosts[3].ip4, 32,
327 [VppRoutePath("0.0.0.0",
328 self.pg2.sw_if_index)])
329 attached_host.add_vpp_config()
330
331 self.pg2.add_stream(p)
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)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800341
Neale Ranns30d0fd42017-05-30 07:30:04 -0700342 self.pg2.add_stream(pt)
343 self.pg_enable_capture(self.pg_interfaces)
344 self.pg_start()
345
346 rx = self.pg2.get_capture(1)
347 self.verify_arp_resp(rx[0],
348 self.pg2.local_mac,
349 self.pg2.remote_mac,
350 self.pg1.local_ip4,
351 self.pg2.remote_hosts[3].ip4)
352
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800353 #
Neale Ranns3983ac22017-03-10 11:53:27 -0800354 # A neighbor entry that has no associated FIB-entry
355 #
356 arp_no_fib = VppNeighbor(self,
357 self.pg1.sw_if_index,
358 self.pg1.remote_hosts[4].mac,
359 self.pg1.remote_hosts[4].ip4,
360 is_no_fib_entry=1)
361 arp_no_fib.add_vpp_config()
362
363 #
364 # check we have the neighbor, but no route
365 #
366 self.assertTrue(find_nbr(self,
367 self.pg1.sw_if_index,
368 self.pg1._remote_hosts[4].ip4))
369 self.assertFalse(find_route(self,
370 self.pg1._remote_hosts[4].ip4,
371 32))
372 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800373 # pg2 is unnumbered to pg1, so we can form adjacencies out of pg2
374 # from within pg1's subnet
Neale Ranns3983ac22017-03-10 11:53:27 -0800375 #
376 arp_unnum = VppNeighbor(self,
377 self.pg2.sw_if_index,
378 self.pg1.remote_hosts[5].mac,
379 self.pg1.remote_hosts[5].ip4)
380 arp_unnum.add_vpp_config()
381
382 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
383 IP(src=self.pg0.remote_ip4,
384 dst=self.pg1._remote_hosts[5].ip4) /
385 UDP(sport=1234, dport=1234) /
386 Raw())
387
388 self.pg0.add_stream(p)
389 self.pg_enable_capture(self.pg_interfaces)
390 self.pg_start()
391
392 rx = self.pg2.get_capture(1)
393
394 self.verify_ip(rx[0],
395 self.pg2.local_mac,
396 self.pg1.remote_hosts[5].mac,
397 self.pg0.remote_ip4,
398 self.pg1._remote_hosts[5].ip4)
399
400 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800401 # ARP requests from hosts in pg1's subnet sent on pg2 are replied to
402 # with the unnumbered interface's address as the source
403 #
404 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
405 ARP(op="who-has",
406 hwsrc=self.pg2.remote_mac,
407 pdst=self.pg1.local_ip4,
408 psrc=self.pg1.remote_hosts[6].ip4))
409
410 self.pg2.add_stream(p)
411 self.pg_enable_capture(self.pg_interfaces)
412 self.pg_start()
413
414 rx = self.pg2.get_capture(1)
415 self.verify_arp_resp(rx[0],
416 self.pg2.local_mac,
417 self.pg2.remote_mac,
418 self.pg1.local_ip4,
419 self.pg1.remote_hosts[6].ip4)
420
421 #
422 # An attached host route out of pg2 for an undiscovered hosts generates
423 # an ARP request with the unnumbered address as the source
424 #
425 att_unnum = VppIpRoute(self, self.pg1.remote_hosts[7].ip4, 32,
426 [VppRoutePath("0.0.0.0",
427 self.pg2.sw_if_index)])
428 att_unnum.add_vpp_config()
429
430 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
431 IP(src=self.pg0.remote_ip4,
432 dst=self.pg1._remote_hosts[7].ip4) /
433 UDP(sport=1234, dport=1234) /
434 Raw())
435
436 self.pg0.add_stream(p)
437 self.pg_enable_capture(self.pg_interfaces)
438 self.pg_start()
439
440 rx = self.pg2.get_capture(1)
441
442 self.verify_arp_req(rx[0],
443 self.pg2.local_mac,
444 self.pg1.local_ip4,
445 self.pg1._remote_hosts[7].ip4)
446
447 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
448 ARP(op="who-has",
449 hwsrc=self.pg2.remote_mac,
450 pdst=self.pg1.local_ip4,
451 psrc=self.pg1.remote_hosts[7].ip4))
452
453 self.pg2.add_stream(p)
454 self.pg_enable_capture(self.pg_interfaces)
455 self.pg_start()
456
457 rx = self.pg2.get_capture(1)
458 self.verify_arp_resp(rx[0],
459 self.pg2.local_mac,
460 self.pg2.remote_mac,
461 self.pg1.local_ip4,
462 self.pg1.remote_hosts[7].ip4)
463
464 #
465 # An attached host route as yet unresolved out of pg2 for an
466 # undiscovered host, an ARP requests begets a response.
467 #
468 att_unnum1 = VppIpRoute(self, self.pg1.remote_hosts[8].ip4, 32,
469 [VppRoutePath("0.0.0.0",
470 self.pg2.sw_if_index)])
471 att_unnum1.add_vpp_config()
472
473 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
474 ARP(op="who-has",
475 hwsrc=self.pg2.remote_mac,
476 pdst=self.pg1.local_ip4,
477 psrc=self.pg1.remote_hosts[8].ip4))
478
479 self.pg2.add_stream(p)
480 self.pg_enable_capture(self.pg_interfaces)
481 self.pg_start()
482
483 rx = self.pg2.get_capture(1)
484 self.verify_arp_resp(rx[0],
485 self.pg2.local_mac,
486 self.pg2.remote_mac,
487 self.pg1.local_ip4,
488 self.pg1.remote_hosts[8].ip4)
489
490 #
Neale Ranns30d0fd42017-05-30 07:30:04 -0700491 # Send an ARP request from one of the so-far unlearned remote hosts
492 # with a VLAN0 tag
493 #
494 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
495 src=self.pg1._remote_hosts[9].mac) /
496 Dot1Q(vlan=0) /
497 ARP(op="who-has",
498 hwsrc=self.pg1._remote_hosts[9].mac,
499 pdst=self.pg1.local_ip4,
500 psrc=self.pg1._remote_hosts[9].ip4))
501
502 self.pg1.add_stream(p)
503 self.pg_enable_capture(self.pg_interfaces)
504 self.pg_start()
505
506 rx = self.pg1.get_capture(1)
507 self.verify_arp_resp(rx[0],
508 self.pg1.local_mac,
509 self.pg1._remote_hosts[9].mac,
510 self.pg1.local_ip4,
511 self.pg1._remote_hosts[9].ip4)
512
513 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700514 # Add a hierarchy of routes for a host in the sub-net.
Neale Rannsca193612017-06-14 06:50:08 -0700515 # Should still get an ARP resp since the cover is attached
516 #
517 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_mac) /
518 ARP(op="who-has",
519 hwsrc=self.pg1.remote_mac,
520 pdst=self.pg1.local_ip4,
521 psrc=self.pg1.remote_hosts[10].ip4))
522
523 r1 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 30,
524 [VppRoutePath(self.pg1.remote_hosts[10].ip4,
525 self.pg1.sw_if_index)])
526 r1.add_vpp_config()
527
528 self.pg1.add_stream(p)
529 self.pg_enable_capture(self.pg_interfaces)
530 self.pg_start()
531 rx = self.pg1.get_capture(1)
532 self.verify_arp_resp(rx[0],
533 self.pg1.local_mac,
534 self.pg1.remote_mac,
535 self.pg1.local_ip4,
536 self.pg1.remote_hosts[10].ip4)
537
538 r2 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 32,
539 [VppRoutePath(self.pg1.remote_hosts[10].ip4,
540 self.pg1.sw_if_index)])
541 r2.add_vpp_config()
542
543 self.pg1.add_stream(p)
544 self.pg_enable_capture(self.pg_interfaces)
545 self.pg_start()
546 rx = self.pg1.get_capture(1)
547 self.verify_arp_resp(rx[0],
548 self.pg1.local_mac,
549 self.pg1.remote_mac,
550 self.pg1.local_ip4,
551 self.pg1.remote_hosts[10].ip4)
552
553 #
554 # add an ARP entry that's not on the sub-net and so whose
555 # adj-fib fails the refinement check. then send an ARP request
556 # from that source
557 #
558 a1 = VppNeighbor(self,
559 self.pg0.sw_if_index,
560 self.pg0.remote_mac,
561 "100.100.100.50")
562 a1.add_vpp_config()
563
564 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
565 ARP(op="who-has",
566 hwsrc=self.pg0.remote_mac,
567 psrc="100.100.100.50",
568 pdst=self.pg0.remote_ip4))
569 self.send_and_assert_no_replies(self.pg0, p,
570 "ARP req for from failed adj-fib")
571
572 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800573 # ERROR Cases
574 # 1 - don't respond to ARP request for address not within the
575 # interface's sub-net
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700576 # 1b - nor within the unnumbered subnet
577 # 1c - nor within the subnet of a different interface
578 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800579 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
580 ARP(op="who-has",
581 hwsrc=self.pg0.remote_mac,
582 pdst="10.10.10.3",
583 psrc=self.pg0.remote_ip4))
584 self.send_and_assert_no_replies(self.pg0, p,
585 "ARP req for non-local destination")
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700586 self.assertFalse(find_nbr(self,
587 self.pg0.sw_if_index,
588 "10.10.10.3"))
589
Neale Ranns4b919a52017-03-11 05:55:21 -0800590 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
591 ARP(op="who-has",
592 hwsrc=self.pg2.remote_mac,
593 pdst="10.10.10.3",
594 psrc=self.pg1.remote_hosts[7].ip4))
595 self.send_and_assert_no_replies(
596 self.pg0, p,
597 "ARP req for non-local destination - unnum")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800598
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700599 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
600 ARP(op="who-has",
601 hwsrc=self.pg0.remote_mac,
602 pdst=self.pg1.local_ip4,
603 psrc=self.pg1.remote_ip4))
604 self.send_and_assert_no_replies(self.pg0, p,
605 "ARP req diff sub-net")
606 self.assertFalse(find_nbr(self,
607 self.pg0.sw_if_index,
608 self.pg1.remote_ip4))
609
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800610 #
611 # 2 - don't respond to ARP request from an address not within the
612 # interface's sub-net
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700613 # 2b - to a proxied address
614 # 2c - not within a different interface's sub-net
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800615 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
616 ARP(op="who-has",
617 hwsrc=self.pg0.remote_mac,
618 psrc="10.10.10.3",
619 pdst=self.pg0.local_ip4))
620 self.send_and_assert_no_replies(self.pg0, p,
621 "ARP req for non-local source")
Neale Ranns4b919a52017-03-11 05:55:21 -0800622 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
623 ARP(op="who-has",
624 hwsrc=self.pg2.remote_mac,
625 psrc="10.10.10.3",
626 pdst=self.pg0.local_ip4))
627 self.send_and_assert_no_replies(
628 self.pg0, p,
629 "ARP req for non-local source - unnum")
Neale Rannsca193612017-06-14 06:50:08 -0700630 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
631 ARP(op="who-has",
632 hwsrc=self.pg0.remote_mac,
633 psrc=self.pg1.remote_ip4,
634 pdst=self.pg0.local_ip4))
635 self.send_and_assert_no_replies(self.pg0, p,
636 "ARP req for non-local source 2c")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800637
638 #
639 # 3 - don't respond to ARP request from an address that belongs to
640 # the router
641 #
642 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
643 ARP(op="who-has",
644 hwsrc=self.pg0.remote_mac,
645 psrc=self.pg0.local_ip4,
646 pdst=self.pg0.local_ip4))
647 self.send_and_assert_no_replies(self.pg0, p,
648 "ARP req for non-local source")
649
650 #
651 # 4 - don't respond to ARP requests that has mac source different
652 # from ARP request HW source
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800653 #
654 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
655 ARP(op="who-has",
656 hwsrc="00:00:00:DE:AD:BE",
657 psrc=self.pg0.remote_ip4,
658 pdst=self.pg0.local_ip4))
659 self.send_and_assert_no_replies(self.pg0, p,
660 "ARP req for non-local source")
661
662 #
zhaoqinglingb4c42cd2017-12-23 15:20:59 +0800663 # 5 - don't respond to ARP requests for address within the
664 # interface's sub-net but not the interface's address
665 #
666 self.pg0.generate_remote_hosts(2)
667 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
668 ARP(op="who-has",
669 hwsrc=self.pg0.remote_mac,
670 psrc=self.pg0.remote_hosts[0].ip4,
671 pdst=self.pg0.remote_hosts[1].ip4))
672 self.send_and_assert_no_replies(self.pg0, p,
673 "ARP req for non-local destination")
674
675 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800676 # cleanup
677 #
678 dyn_arp.remove_vpp_config()
679 static_arp.remove_vpp_config()
Neale Ranns3983ac22017-03-10 11:53:27 -0800680 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800681
Neale Ranns4b919a52017-03-11 05:55:21 -0800682 # need this to flush the adj-fibs
683 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
684 self.pg2.admin_down()
Neale Rannsca193612017-06-14 06:50:08 -0700685 self.pg1.admin_down()
Neale Ranns4b919a52017-03-11 05:55:21 -0800686
Neale Ranns24b170a2017-08-15 05:33:11 -0700687 def test_proxy_mirror_arp(self):
688 """ Interface Mirror Proxy ARP """
689
690 #
691 # When VPP has an interface whose address is also applied to a TAP
692 # interface on the host, then VPP's TAP interface will be unnumbered
693 # to the 'real' interface and do proxy ARP from the host.
694 # the curious aspect of this setup is that ARP requests from the host
695 # will come from the VPP's own address.
696 #
697 self.pg0.generate_remote_hosts(2)
698
699 arp_req_from_me = (Ether(src=self.pg2.remote_mac,
700 dst="ff:ff:ff:ff:ff:ff") /
701 ARP(op="who-has",
702 hwsrc=self.pg2.remote_mac,
703 pdst=self.pg0.remote_hosts[1].ip4,
704 psrc=self.pg0.local_ip4))
705
706 #
707 # Configure Proxy ARP for the subnet on PG0addresses on pg0
708 #
Neale Ranns37029302018-08-10 05:30:06 -0700709 self.vapi.proxy_arp_add_del(self.pg0._local_ip4_subnet,
710 self.pg0._local_ip4_bcast)
Neale Ranns24b170a2017-08-15 05:33:11 -0700711
712 # Make pg2 un-numbered to pg0
713 #
714 self.pg2.set_unnumbered(self.pg0.sw_if_index)
715
716 #
717 # Enable pg2 for proxy ARP
718 #
719 self.pg2.set_proxy_arp()
720
721 #
722 # Send the ARP request with an originating address that
723 # is VPP's own address
724 #
725 self.pg2.add_stream(arp_req_from_me)
726 self.pg_enable_capture(self.pg_interfaces)
727 self.pg_start()
728
729 rx = self.pg2.get_capture(1)
730 self.verify_arp_resp(rx[0],
731 self.pg2.local_mac,
732 self.pg2.remote_mac,
733 self.pg0.remote_hosts[1].ip4,
734 self.pg0.local_ip4)
735
736 #
737 # validate we have not learned an ARP entry as a result of this
738 #
739 self.assertFalse(find_nbr(self,
740 self.pg2.sw_if_index,
741 self.pg0.local_ip4))
742
743 #
744 # cleanup
745 #
746 self.pg2.set_proxy_arp(0)
Neale Ranns37029302018-08-10 05:30:06 -0700747 self.vapi.proxy_arp_add_del(self.pg0._local_ip4_subnet,
748 self.pg0._local_ip4_bcast,
Neale Ranns24b170a2017-08-15 05:33:11 -0700749 is_add=0)
750
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800751 def test_proxy_arp(self):
752 """ Proxy ARP """
753
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700754 self.pg1.generate_remote_hosts(2)
755
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800756 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700757 # Proxy ARP request packets for each interface
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800758 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800759 arp_req_pg0 = (Ether(src=self.pg0.remote_mac,
760 dst="ff:ff:ff:ff:ff:ff") /
761 ARP(op="who-has",
762 hwsrc=self.pg0.remote_mac,
763 pdst="10.10.10.3",
764 psrc=self.pg0.remote_ip4))
Neale Ranns30d0fd42017-05-30 07:30:04 -0700765 arp_req_pg0_tagged = (Ether(src=self.pg0.remote_mac,
766 dst="ff:ff:ff:ff:ff:ff") /
767 Dot1Q(vlan=0) /
768 ARP(op="who-has",
769 hwsrc=self.pg0.remote_mac,
770 pdst="10.10.10.3",
771 psrc=self.pg0.remote_ip4))
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800772 arp_req_pg1 = (Ether(src=self.pg1.remote_mac,
773 dst="ff:ff:ff:ff:ff:ff") /
774 ARP(op="who-has",
775 hwsrc=self.pg1.remote_mac,
776 pdst="10.10.10.3",
777 psrc=self.pg1.remote_ip4))
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700778 arp_req_pg2 = (Ether(src=self.pg2.remote_mac,
779 dst="ff:ff:ff:ff:ff:ff") /
780 ARP(op="who-has",
781 hwsrc=self.pg2.remote_mac,
782 pdst="10.10.10.3",
783 psrc=self.pg1.remote_hosts[1].ip4))
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800784 arp_req_pg3 = (Ether(src=self.pg3.remote_mac,
785 dst="ff:ff:ff:ff:ff:ff") /
786 ARP(op="who-has",
787 hwsrc=self.pg3.remote_mac,
788 pdst="10.10.10.3",
789 psrc=self.pg3.remote_ip4))
790
791 #
792 # Configure Proxy ARP for 10.10.10.0 -> 10.10.10.124
793 #
794 self.vapi.proxy_arp_add_del(inet_pton(AF_INET, "10.10.10.2"),
795 inet_pton(AF_INET, "10.10.10.124"))
796
797 #
798 # No responses are sent when the interfaces are not enabled for proxy
799 # ARP
800 #
801 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
802 "ARP req from unconfigured interface")
803 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
804 "ARP req from unconfigured interface")
805
806 #
807 # Make pg2 un-numbered to pg1
808 # still won't reply.
809 #
810 self.pg2.set_unnumbered(self.pg1.sw_if_index)
811
812 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
813 "ARP req from unnumbered interface")
814
815 #
816 # Enable each interface to reply to proxy ARPs
817 #
818 for i in self.pg_interfaces:
819 i.set_proxy_arp()
820
821 #
822 # Now each of the interfaces should reply to a request to a proxied
823 # address
824 #
825 self.pg0.add_stream(arp_req_pg0)
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 Ranns30d0fd42017-05-30 07:30:04 -0700836 self.pg0.add_stream(arp_req_pg0_tagged)
837 self.pg_enable_capture(self.pg_interfaces)
838 self.pg_start()
839
840 rx = self.pg0.get_capture(1)
841 self.verify_arp_resp(rx[0],
842 self.pg0.local_mac,
843 self.pg0.remote_mac,
844 "10.10.10.3",
845 self.pg0.remote_ip4)
846
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800847 self.pg1.add_stream(arp_req_pg1)
848 self.pg_enable_capture(self.pg_interfaces)
849 self.pg_start()
850
851 rx = self.pg1.get_capture(1)
852 self.verify_arp_resp(rx[0],
853 self.pg1.local_mac,
854 self.pg1.remote_mac,
855 "10.10.10.3",
856 self.pg1.remote_ip4)
857
858 self.pg2.add_stream(arp_req_pg2)
859 self.pg_enable_capture(self.pg_interfaces)
860 self.pg_start()
861
862 rx = self.pg2.get_capture(1)
863 self.verify_arp_resp(rx[0],
864 self.pg2.local_mac,
865 self.pg2.remote_mac,
866 "10.10.10.3",
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700867 self.pg1.remote_hosts[1].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800868
869 #
870 # A request for an address out of the configured range
871 #
872 arp_req_pg1_hi = (Ether(src=self.pg1.remote_mac,
873 dst="ff:ff:ff:ff:ff:ff") /
874 ARP(op="who-has",
875 hwsrc=self.pg1.remote_mac,
876 pdst="10.10.10.125",
877 psrc=self.pg1.remote_ip4))
878 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_hi,
879 "ARP req out of range HI")
880 arp_req_pg1_low = (Ether(src=self.pg1.remote_mac,
881 dst="ff:ff:ff:ff:ff:ff") /
882 ARP(op="who-has",
883 hwsrc=self.pg1.remote_mac,
884 pdst="10.10.10.1",
885 psrc=self.pg1.remote_ip4))
886 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_low,
887 "ARP req out of range Low")
888
889 #
890 # Request for an address in the proxy range but from an interface
891 # in a different VRF
892 #
893 self.send_and_assert_no_replies(self.pg3, arp_req_pg3,
894 "ARP req from different VRF")
895
896 #
897 # Disable Each interface for proxy ARP
898 # - expect none to respond
899 #
900 for i in self.pg_interfaces:
901 i.set_proxy_arp(0)
902
903 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
904 "ARP req from disable")
905 self.send_and_assert_no_replies(self.pg1, arp_req_pg1,
906 "ARP req from disable")
907 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
908 "ARP req from disable")
Neale Ranns37be7362017-02-21 17:30:26 -0800909
910 #
911 # clean up on interface 2
912 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800913 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns37be7362017-02-21 17:30:26 -0800914
915 def test_mpls(self):
916 """ MPLS """
917
918 #
919 # Interface 2 does not yet have ip4 config
920 #
921 self.pg2.config_ip4()
922 self.pg2.generate_remote_hosts(2)
923
924 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700925 # Add a route with out going label via an ARP unresolved next-hop
Neale Ranns37be7362017-02-21 17:30:26 -0800926 #
927 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
928 [VppRoutePath(self.pg2.remote_hosts[1].ip4,
929 self.pg2.sw_if_index,
930 labels=[55])])
931 ip_10_0_0_1.add_vpp_config()
932
933 #
934 # packets should generate an ARP request
935 #
936 p = (Ether(src=self.pg0.remote_mac,
937 dst=self.pg0.local_mac) /
938 IP(src=self.pg0.remote_ip4, dst="10.0.0.1") /
939 UDP(sport=1234, dport=1234) /
940 Raw('\xa5' * 100))
941
942 self.pg0.add_stream(p)
943 self.pg_enable_capture(self.pg_interfaces)
944 self.pg_start()
945
946 rx = self.pg2.get_capture(1)
947 self.verify_arp_req(rx[0],
948 self.pg2.local_mac,
949 self.pg2.local_ip4,
950 self.pg2._remote_hosts[1].ip4)
951
952 #
953 # now resolve the neighbours
954 #
955 self.pg2.configure_ipv4_neighbors()
956
957 #
958 # Now packet should be properly MPLS encapped.
959 # This verifies that MPLS link-type adjacencies are completed
960 # when the ARP entry resolves
961 #
962 self.pg0.add_stream(p)
963 self.pg_enable_capture(self.pg_interfaces)
964 self.pg_start()
965
966 rx = self.pg2.get_capture(1)
967 self.verify_ip_o_mpls(rx[0],
968 self.pg2.local_mac,
969 self.pg2.remote_hosts[1].mac,
970 55,
971 self.pg0.remote_ip4,
972 "10.0.0.1")
Neale Ranns4b919a52017-03-11 05:55:21 -0800973 self.pg2.unconfig_ip4()
Neale Ranns37be7362017-02-21 17:30:26 -0800974
Matthew Smithcb9ab472017-05-16 21:35:56 -0500975 def test_arp_vrrp(self):
976 """ ARP reply with VRRP virtual src hw addr """
977
978 #
979 # IP packet destined for pg1 remote host arrives on pg0 resulting
980 # in an ARP request for the address of the remote host on pg1
981 #
982 p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
983 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
984 UDP(sport=1234, dport=1234) /
985 Raw())
986
Neale Ranns37029302018-08-10 05:30:06 -0700987 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
Matthew Smithcb9ab472017-05-16 21:35:56 -0500988
989 self.verify_arp_req(rx1[0],
990 self.pg1.local_mac,
991 self.pg1.local_ip4,
992 self.pg1.remote_ip4)
993
994 #
995 # ARP reply for address of pg1 remote host arrives on pg1 with
996 # the hw src addr set to a value in the VRRP IPv4 range of
997 # MAC addresses
998 #
999 p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1000 ARP(op="is-at", hwdst=self.pg1.local_mac,
1001 hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
1002 psrc=self.pg1.remote_ip4))
1003
Neale Ranns37029302018-08-10 05:30:06 -07001004 self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
Matthew Smithcb9ab472017-05-16 21:35:56 -05001005
1006 #
1007 # IP packet destined for pg1 remote host arrives on pg0 again.
1008 # VPP should have an ARP entry for that address now and the packet
1009 # should be sent out pg1.
1010 #
Neale Ranns37029302018-08-10 05:30:06 -07001011 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
Matthew Smithcb9ab472017-05-16 21:35:56 -05001012
1013 self.verify_ip(rx1[0],
1014 self.pg1.local_mac,
1015 "00:00:5e:00:01:09",
1016 self.pg0.remote_ip4,
1017 self.pg1.remote_ip4)
1018
1019 self.pg1.admin_down()
1020 self.pg1.admin_up()
1021
Neale Rannsdcd6d622017-05-26 02:59:16 -07001022 def test_arp_duplicates(self):
1023 """ ARP Duplicates"""
1024
1025 #
1026 # Generate some hosts on the LAN
1027 #
1028 self.pg1.generate_remote_hosts(3)
1029
1030 #
1031 # Add host 1 on pg1 and pg2
1032 #
1033 arp_pg1 = VppNeighbor(self,
1034 self.pg1.sw_if_index,
1035 self.pg1.remote_hosts[1].mac,
1036 self.pg1.remote_hosts[1].ip4)
1037 arp_pg1.add_vpp_config()
1038 arp_pg2 = VppNeighbor(self,
1039 self.pg2.sw_if_index,
1040 self.pg2.remote_mac,
1041 self.pg1.remote_hosts[1].ip4)
1042 arp_pg2.add_vpp_config()
1043
1044 #
1045 # IP packet destined for pg1 remote host arrives on pg1 again.
1046 #
1047 p = (Ether(dst=self.pg0.local_mac,
1048 src=self.pg0.remote_mac) /
1049 IP(src=self.pg0.remote_ip4,
1050 dst=self.pg1.remote_hosts[1].ip4) /
1051 UDP(sport=1234, dport=1234) /
1052 Raw())
1053
1054 self.pg0.add_stream(p)
1055 self.pg_enable_capture(self.pg_interfaces)
1056 self.pg_start()
1057
1058 rx1 = self.pg1.get_capture(1)
1059
1060 self.verify_ip(rx1[0],
1061 self.pg1.local_mac,
1062 self.pg1.remote_hosts[1].mac,
1063 self.pg0.remote_ip4,
1064 self.pg1.remote_hosts[1].ip4)
1065
1066 #
1067 # remove the duplicate on pg1
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001068 # packet stream should generate ARPs out of pg1
Neale Rannsdcd6d622017-05-26 02:59:16 -07001069 #
1070 arp_pg1.remove_vpp_config()
1071
1072 self.pg0.add_stream(p)
1073 self.pg_enable_capture(self.pg_interfaces)
1074 self.pg_start()
1075
1076 rx1 = self.pg1.get_capture(1)
1077
1078 self.verify_arp_req(rx1[0],
1079 self.pg1.local_mac,
1080 self.pg1.local_ip4,
1081 self.pg1.remote_hosts[1].ip4)
1082
1083 #
1084 # Add it back
1085 #
1086 arp_pg1.add_vpp_config()
1087
1088 self.pg0.add_stream(p)
1089 self.pg_enable_capture(self.pg_interfaces)
1090 self.pg_start()
1091
1092 rx1 = self.pg1.get_capture(1)
1093
1094 self.verify_ip(rx1[0],
1095 self.pg1.local_mac,
1096 self.pg1.remote_hosts[1].mac,
1097 self.pg0.remote_ip4,
1098 self.pg1.remote_hosts[1].ip4)
1099
Neale Ranns15002542017-09-10 04:39:11 -07001100 def test_arp_static(self):
1101 """ ARP Static"""
1102 self.pg2.generate_remote_hosts(3)
1103
1104 #
1105 # Add a static ARP entry
1106 #
1107 static_arp = VppNeighbor(self,
1108 self.pg2.sw_if_index,
1109 self.pg2.remote_hosts[1].mac,
1110 self.pg2.remote_hosts[1].ip4,
1111 is_static=1)
1112 static_arp.add_vpp_config()
1113
1114 #
1115 # Add the connected prefix to the interface
1116 #
1117 self.pg2.config_ip4()
1118
1119 #
1120 # We should now find the adj-fib
1121 #
1122 self.assertTrue(find_nbr(self,
1123 self.pg2.sw_if_index,
1124 self.pg2.remote_hosts[1].ip4,
1125 is_static=1))
1126 self.assertTrue(find_route(self,
1127 self.pg2.remote_hosts[1].ip4,
1128 32))
1129
1130 #
1131 # remove the connected
1132 #
1133 self.pg2.unconfig_ip4()
1134
1135 #
1136 # put the interface into table 1
1137 #
1138 self.pg2.set_table_ip4(1)
1139
1140 #
1141 # configure the same connected and expect to find the
1142 # adj fib in the new table
1143 #
1144 self.pg2.config_ip4()
1145 self.assertTrue(find_route(self,
1146 self.pg2.remote_hosts[1].ip4,
1147 32,
1148 table_id=1))
1149
1150 #
1151 # clean-up
1152 #
1153 self.pg2.unconfig_ip4()
1154 self.pg2.set_table_ip4(0)
1155
Neale Rannsc819fc62018-02-16 02:44:05 -08001156 def test_arp_incomplete(self):
1157 """ ARP Incomplete"""
1158 self.pg1.generate_remote_hosts(3)
1159
1160 p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1161 IP(src=self.pg0.remote_ip4,
1162 dst=self.pg1.remote_hosts[1].ip4) /
1163 UDP(sport=1234, dport=1234) /
1164 Raw())
1165 p1 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1166 IP(src=self.pg0.remote_ip4,
1167 dst=self.pg1.remote_hosts[2].ip4) /
1168 UDP(sport=1234, dport=1234) /
1169 Raw())
1170
1171 #
1172 # a packet to an unresolved destination generates an ARP request
1173 #
1174 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1175 self.verify_arp_req(rx[0],
1176 self.pg1.local_mac,
1177 self.pg1.local_ip4,
1178 self.pg1._remote_hosts[1].ip4)
1179
1180 #
1181 # add a neighbour for remote host 1
1182 #
1183 static_arp = VppNeighbor(self,
1184 self.pg1.sw_if_index,
1185 self.pg1.remote_hosts[1].mac,
1186 self.pg1.remote_hosts[1].ip4,
1187 is_static=1)
1188 static_arp.add_vpp_config()
1189
1190 #
1191 # change the interface's MAC
1192 #
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001193 mac = [scapy.compat.chb(0x00), scapy.compat.chb(0x00),
1194 scapy.compat.chb(0x00), scapy.compat.chb(0x33),
1195 scapy.compat.chb(0x33), scapy.compat.chb(0x33)]
Neale Rannsc819fc62018-02-16 02:44:05 -08001196 mac_string = ''.join(mac)
1197
1198 self.vapi.sw_interface_set_mac_address(self.pg1.sw_if_index,
1199 mac_string)
1200
1201 #
1202 # now ARP requests come from the new source mac
1203 #
1204 rx = self.send_and_expect(self.pg0, [p1], self.pg1)
1205 self.verify_arp_req(rx[0],
1206 "00:00:00:33:33:33",
1207 self.pg1.local_ip4,
1208 self.pg1._remote_hosts[2].ip4)
1209
1210 #
1211 # packets to the resolved host also have the new source mac
1212 #
1213 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1214 self.verify_ip(rx[0],
1215 "00:00:00:33:33:33",
1216 self.pg1.remote_hosts[1].mac,
1217 self.pg0.remote_ip4,
1218 self.pg1.remote_hosts[1].ip4)
1219
1220 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001221 # set the mac address on the interface that does not have a
Neale Rannsc819fc62018-02-16 02:44:05 -08001222 # configured subnet and thus no glean
1223 #
1224 self.vapi.sw_interface_set_mac_address(self.pg2.sw_if_index,
1225 mac_string)
1226
Neale Ranns59ae61e2018-06-07 18:09:49 -07001227 def test_garp(self):
1228 """ GARP """
1229
1230 #
1231 # Generate some hosts on the LAN
1232 #
1233 self.pg1.generate_remote_hosts(4)
1234
1235 #
1236 # And an ARP entry
1237 #
1238 arp = VppNeighbor(self,
1239 self.pg1.sw_if_index,
1240 self.pg1.remote_hosts[1].mac,
1241 self.pg1.remote_hosts[1].ip4)
1242 arp.add_vpp_config()
1243
1244 self.assertTrue(find_nbr(self,
1245 self.pg1.sw_if_index,
1246 self.pg1.remote_hosts[1].ip4,
1247 mac=self.pg1.remote_hosts[1].mac))
1248
1249 #
1250 # Send a GARP (request) to swap the host 1's address to that of host 2
1251 #
1252 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1253 src=self.pg1.remote_hosts[2].mac) /
1254 ARP(op="who-has",
1255 hwdst=self.pg1.local_mac,
1256 hwsrc=self.pg1.remote_hosts[2].mac,
1257 pdst=self.pg1.remote_hosts[1].ip4,
1258 psrc=self.pg1.remote_hosts[1].ip4))
1259
1260 self.pg1.add_stream(p1)
1261 self.pg_enable_capture(self.pg_interfaces)
1262 self.pg_start()
1263
1264 self.assertTrue(find_nbr(self,
1265 self.pg1.sw_if_index,
1266 self.pg1.remote_hosts[1].ip4,
1267 mac=self.pg1.remote_hosts[2].mac))
1268
1269 #
1270 # Send a GARP (reply) to swap the host 1's address to that of host 3
1271 #
1272 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1273 src=self.pg1.remote_hosts[3].mac) /
1274 ARP(op="is-at",
1275 hwdst=self.pg1.local_mac,
1276 hwsrc=self.pg1.remote_hosts[3].mac,
1277 pdst=self.pg1.remote_hosts[1].ip4,
1278 psrc=self.pg1.remote_hosts[1].ip4))
1279
1280 self.pg1.add_stream(p1)
1281 self.pg_enable_capture(self.pg_interfaces)
1282 self.pg_start()
1283
1284 self.assertTrue(find_nbr(self,
1285 self.pg1.sw_if_index,
1286 self.pg1.remote_hosts[1].ip4,
1287 mac=self.pg1.remote_hosts[3].mac))
1288
1289 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001290 # GARPs (request nor replies) for host we don't know yet
Neale Ranns59ae61e2018-06-07 18:09:49 -07001291 # don't result in new neighbour entries
1292 #
1293 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1294 src=self.pg1.remote_hosts[3].mac) /
1295 ARP(op="who-has",
1296 hwdst=self.pg1.local_mac,
1297 hwsrc=self.pg1.remote_hosts[3].mac,
1298 pdst=self.pg1.remote_hosts[2].ip4,
1299 psrc=self.pg1.remote_hosts[2].ip4))
1300
1301 self.pg1.add_stream(p1)
1302 self.pg_enable_capture(self.pg_interfaces)
1303 self.pg_start()
1304
1305 self.assertFalse(find_nbr(self,
1306 self.pg1.sw_if_index,
1307 self.pg1.remote_hosts[2].ip4))
1308
1309 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1310 src=self.pg1.remote_hosts[3].mac) /
1311 ARP(op="is-at",
1312 hwdst=self.pg1.local_mac,
1313 hwsrc=self.pg1.remote_hosts[3].mac,
1314 pdst=self.pg1.remote_hosts[2].ip4,
1315 psrc=self.pg1.remote_hosts[2].ip4))
1316
1317 self.pg1.add_stream(p1)
1318 self.pg_enable_capture(self.pg_interfaces)
1319 self.pg_start()
1320
1321 self.assertFalse(find_nbr(self,
1322 self.pg1.sw_if_index,
1323 self.pg1.remote_hosts[2].ip4))
1324
Neale Rannsc8352bc2018-08-29 10:23:58 -07001325 def test_arp_incomplete(self):
Neale Ranns14260392018-09-28 05:00:57 -07001326 """ Incomplete Entries """
Neale Rannsc8352bc2018-08-29 10:23:58 -07001327
1328 #
Neale Rannscd35e532018-08-31 02:51:45 -07001329 # ensure that we throttle the ARP and ND requests
Neale Rannsc8352bc2018-08-29 10:23:58 -07001330 #
1331 self.pg0.generate_remote_hosts(2)
1332
Neale Rannscd35e532018-08-31 02:51:45 -07001333 #
1334 # IPv4/ARP
1335 #
Neale Rannsc8352bc2018-08-29 10:23:58 -07001336 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1337 [VppRoutePath(self.pg0.remote_hosts[1].ip4,
Neale Rannscd35e532018-08-31 02:51:45 -07001338 self.pg0.sw_if_index)])
Neale Rannsc8352bc2018-08-29 10:23:58 -07001339 ip_10_0_0_1.add_vpp_config()
1340
1341 p1 = (Ether(dst=self.pg1.local_mac,
1342 src=self.pg1.remote_mac) /
1343 IP(src=self.pg1.remote_ip4,
1344 dst="10.0.0.1") /
1345 UDP(sport=1234, dport=1234) /
1346 Raw())
1347
1348 self.pg1.add_stream(p1 * 257)
1349 self.pg_enable_capture(self.pg_interfaces)
1350 self.pg_start()
1351 rx = self.pg0._get_capture(1)
1352
1353 #
1354 # how many we get is going to be dependent on the time for packet
1355 # processing but it should be small
1356 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001357 self.assertLess(len(rx), 64)
Neale Rannsc8352bc2018-08-29 10:23:58 -07001358
Neale Rannscd35e532018-08-31 02:51:45 -07001359 #
1360 # IPv6/ND
1361 #
1362 ip_10_1 = VppIpRoute(self, "10::1", 128,
1363 [VppRoutePath(self.pg0.remote_hosts[1].ip6,
1364 self.pg0.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07001365 proto=DpoProto.DPO_PROTO_IP6)])
Neale Rannscd35e532018-08-31 02:51:45 -07001366 ip_10_1.add_vpp_config()
1367
1368 p1 = (Ether(dst=self.pg1.local_mac,
1369 src=self.pg1.remote_mac) /
1370 IPv6(src=self.pg1.remote_ip6,
1371 dst="10::1") /
1372 UDP(sport=1234, dport=1234) /
1373 Raw())
1374
1375 self.pg1.add_stream(p1 * 257)
1376 self.pg_enable_capture(self.pg_interfaces)
1377 self.pg_start()
1378 rx = self.pg0._get_capture(1)
1379
1380 #
1381 # how many we get is going to be dependent on the time for packet
1382 # processing but it should be small
1383 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001384 self.assertLess(len(rx), 64)
Neale Rannscd35e532018-08-31 02:51:45 -07001385
Neale Ranns7425f922019-01-23 00:36:16 -08001386 def test_arp_forus(self):
1387 """ ARP for for-us """
1388
1389 #
1390 # Test that VPP responds with ARP requests to addresses that
1391 # are connected and local routes.
1392 # Use one of the 'remote' addresses in the subnet as a local address
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001393 # The intention of this route is that it then acts like a secondary
Neale Ranns7425f922019-01-23 00:36:16 -08001394 # address added to an interface
1395 #
1396 self.pg0.generate_remote_hosts(2)
1397
Neale Ranns097fa662018-05-01 05:17:55 -07001398 forus = VppIpRoute(
1399 self, self.pg0.remote_hosts[1].ip4, 32,
1400 [VppRoutePath("0.0.0.0",
1401 self.pg0.sw_if_index,
1402 type=FibPathType.FIB_PATH_TYPE_LOCAL)])
Neale Ranns7425f922019-01-23 00:36:16 -08001403 forus.add_vpp_config()
1404
1405 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
1406 src=self.pg0.remote_mac) /
1407 ARP(op="who-has",
1408 hwdst=self.pg0.local_mac,
1409 hwsrc=self.pg0.remote_mac,
1410 pdst=self.pg0.remote_hosts[1].ip4,
1411 psrc=self.pg0.remote_ip4))
1412
1413 rx = self.send_and_expect(self.pg0, [p], self.pg0)
1414
1415 self.verify_arp_resp(rx[0],
1416 self.pg0.local_mac,
1417 self.pg0.remote_mac,
1418 self.pg0.remote_hosts[1].ip4,
1419 self.pg0.remote_ip4)
1420
Neale Rannsdcd6d622017-05-26 02:59:16 -07001421
Neale Ranns14260392018-09-28 05:00:57 -07001422class NeighborStatsTestCase(VppTestCase):
Neale Ranns37029302018-08-10 05:30:06 -07001423 """ ARP/ND Counters """
Neale Ranns14260392018-09-28 05:00:57 -07001424
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001425 @classmethod
1426 def setUpClass(cls):
1427 super(NeighborStatsTestCase, cls).setUpClass()
1428
1429 @classmethod
1430 def tearDownClass(cls):
1431 super(NeighborStatsTestCase, cls).tearDownClass()
1432
Neale Ranns14260392018-09-28 05:00:57 -07001433 def setUp(self):
1434 super(NeighborStatsTestCase, self).setUp()
1435
1436 self.create_pg_interfaces(range(2))
1437
1438 # pg0 configured with ip4 and 6 addresses used for input
1439 # pg1 configured with ip4 and 6 addresses used for output
1440 # pg2 is unnumbered to pg0
1441 for i in self.pg_interfaces:
1442 i.admin_up()
1443 i.config_ip4()
1444 i.config_ip6()
1445 i.resolve_arp()
1446 i.resolve_ndp()
1447
1448 def tearDown(self):
1449 super(NeighborStatsTestCase, self).tearDown()
1450
1451 for i in self.pg_interfaces:
1452 i.unconfig_ip4()
1453 i.unconfig_ip6()
1454 i.admin_down()
1455
1456 def test_arp_stats(self):
1457 """ ARP Counters """
1458
1459 self.vapi.cli("adj counters enable")
1460 self.pg1.generate_remote_hosts(2)
1461
1462 arp1 = VppNeighbor(self,
1463 self.pg1.sw_if_index,
1464 self.pg1.remote_hosts[0].mac,
1465 self.pg1.remote_hosts[0].ip4)
1466 arp1.add_vpp_config()
1467 arp2 = VppNeighbor(self,
1468 self.pg1.sw_if_index,
1469 self.pg1.remote_hosts[1].mac,
1470 self.pg1.remote_hosts[1].ip4)
1471 arp2.add_vpp_config()
1472
1473 p1 = (Ether(dst=self.pg0.local_mac,
1474 src=self.pg0.remote_mac) /
1475 IP(src=self.pg0.remote_ip4,
1476 dst=self.pg1.remote_hosts[0].ip4) /
1477 UDP(sport=1234, dport=1234) /
1478 Raw())
1479 p2 = (Ether(dst=self.pg0.local_mac,
1480 src=self.pg0.remote_mac) /
1481 IP(src=self.pg0.remote_ip4,
1482 dst=self.pg1.remote_hosts[1].ip4) /
1483 UDP(sport=1234, dport=1234) /
1484 Raw())
1485
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001486 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
1487 rx = self.send_and_expect(self.pg0, p2 * NUM_PKTS, self.pg1)
Neale Ranns14260392018-09-28 05:00:57 -07001488
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001489 self.assertEqual(NUM_PKTS, arp1.get_stats()['packets'])
1490 self.assertEqual(NUM_PKTS, arp2.get_stats()['packets'])
Neale Ranns14260392018-09-28 05:00:57 -07001491
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001492 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
1493 self.assertEqual(NUM_PKTS*2, arp1.get_stats()['packets'])
Neale Ranns14260392018-09-28 05:00:57 -07001494
1495 def test_nd_stats(self):
1496 """ ND Counters """
1497
1498 self.vapi.cli("adj counters enable")
1499 self.pg0.generate_remote_hosts(3)
1500
1501 nd1 = VppNeighbor(self,
1502 self.pg0.sw_if_index,
1503 self.pg0.remote_hosts[1].mac,
Neale Ranns37029302018-08-10 05:30:06 -07001504 self.pg0.remote_hosts[1].ip6)
Neale Ranns14260392018-09-28 05:00:57 -07001505 nd1.add_vpp_config()
1506 nd2 = VppNeighbor(self,
1507 self.pg0.sw_if_index,
1508 self.pg0.remote_hosts[2].mac,
Neale Ranns37029302018-08-10 05:30:06 -07001509 self.pg0.remote_hosts[2].ip6)
Neale Ranns14260392018-09-28 05:00:57 -07001510 nd2.add_vpp_config()
1511
1512 p1 = (Ether(dst=self.pg1.local_mac,
1513 src=self.pg1.remote_mac) /
1514 IPv6(src=self.pg1.remote_ip6,
1515 dst=self.pg0.remote_hosts[1].ip6) /
1516 UDP(sport=1234, dport=1234) /
1517 Raw())
1518 p2 = (Ether(dst=self.pg1.local_mac,
1519 src=self.pg1.remote_mac) /
1520 IPv6(src=self.pg1.remote_ip6,
1521 dst=self.pg0.remote_hosts[2].ip6) /
1522 UDP(sport=1234, dport=1234) /
1523 Raw())
1524
1525 rx = self.send_and_expect(self.pg1, p1 * 16, self.pg0)
1526 rx = self.send_and_expect(self.pg1, p2 * 16, self.pg0)
1527
1528 self.assertEqual(16, nd1.get_stats()['packets'])
1529 self.assertEqual(16, nd2.get_stats()['packets'])
1530
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001531 rx = self.send_and_expect(self.pg1, p1 * NUM_PKTS, self.pg0)
1532 self.assertEqual(NUM_PKTS+16, nd1.get_stats()['packets'])
Neale Ranns14260392018-09-28 05:00:57 -07001533
1534
Neale Ranns37be7362017-02-21 17:30:26 -08001535if __name__ == '__main__':
1536 unittest.main(testRunner=VppTestRunner)