blob: 1c7cc2678ff049f2687128228957c4ade17c0a96 [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 Rannsb3b2de72017-03-08 05:17:22 -08008from vpp_ip_route import VppIpRoute, VppRoutePath, find_route
Neale Ranns39f9d8b2017-02-16 21:57:05 -08009
10from scapy.packet import Raw
Neale Ranns30d0fd42017-05-30 07:30:04 -070011from scapy.layers.l2 import Ether, ARP, Dot1Q
Neale Ranns39f9d8b2017-02-16 21:57:05 -080012from scapy.layers.inet import IP, UDP
Neale Ranns37be7362017-02-21 17:30:26 -080013from scapy.contrib.mpls import MPLS
Neale Ranns39f9d8b2017-02-16 21:57:05 -080014
15# not exported by scapy, so redefined here
16arp_opts = {"who-has": 1, "is-at": 2}
17
18
19class ARPTestCase(VppTestCase):
20 """ ARP Test Case """
21
22 def setUp(self):
23 super(ARPTestCase, self).setUp()
24
25 # create 3 pg interfaces
26 self.create_pg_interfaces(range(4))
27
28 # pg0 configured with ip4 and 6 addresses used for input
29 # pg1 configured with ip4 and 6 addresses used for output
30 # pg2 is unnumbered to pg0
31 for i in self.pg_interfaces:
32 i.admin_up()
33
34 self.pg0.config_ip4()
35 self.pg0.config_ip6()
36 self.pg0.resolve_arp()
37
38 self.pg1.config_ip4()
39 self.pg1.config_ip6()
40
41 # pg3 in a different VRF
42 self.pg3.set_table_ip4(1)
43 self.pg3.config_ip4()
44
Neale Ranns4008ac92017-02-13 23:20:04 -080045 def tearDown(self):
46 super(ARPTestCase, self).tearDown()
Neale Ranns4b919a52017-03-11 05:55:21 -080047 self.pg0.unconfig_ip4()
48 self.pg0.unconfig_ip6()
49
50 self.pg1.unconfig_ip4()
51 self.pg1.unconfig_ip6()
52
53 self.pg3.unconfig_ip4()
54
Neale Ranns4008ac92017-02-13 23:20:04 -080055 for i in self.pg_interfaces:
Neale Ranns4008ac92017-02-13 23:20:04 -080056 i.admin_down()
57
Neale Ranns39f9d8b2017-02-16 21:57:05 -080058 def verify_arp_req(self, rx, smac, sip, dip):
59 ether = rx[Ether]
60 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
61 self.assertEqual(ether.src, smac)
62
63 arp = rx[ARP]
64 self.assertEqual(arp.hwtype, 1)
65 self.assertEqual(arp.ptype, 0x800)
66 self.assertEqual(arp.hwlen, 6)
67 self.assertEqual(arp.plen, 4)
68 self.assertEqual(arp.op, arp_opts["who-has"])
69 self.assertEqual(arp.hwsrc, smac)
70 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
71 self.assertEqual(arp.psrc, sip)
72 self.assertEqual(arp.pdst, dip)
73
74 def verify_arp_resp(self, rx, smac, dmac, sip, dip):
75 ether = rx[Ether]
76 self.assertEqual(ether.dst, dmac)
77 self.assertEqual(ether.src, smac)
78
79 arp = rx[ARP]
80 self.assertEqual(arp.hwtype, 1)
81 self.assertEqual(arp.ptype, 0x800)
82 self.assertEqual(arp.hwlen, 6)
83 self.assertEqual(arp.plen, 4)
84 self.assertEqual(arp.op, arp_opts["is-at"])
85 self.assertEqual(arp.hwsrc, smac)
86 self.assertEqual(arp.hwdst, dmac)
87 self.assertEqual(arp.psrc, sip)
88 self.assertEqual(arp.pdst, dip)
89
Matthew Smithcb9ab472017-05-16 21:35:56 -050090 def verify_arp_vrrp_resp(self, rx, smac, dmac, sip, dip):
91 ether = rx[Ether]
92 self.assertEqual(ether.dst, dmac)
93 self.assertEqual(ether.src, smac)
94
95 arp = rx[ARP]
96 self.assertEqual(arp.hwtype, 1)
97 self.assertEqual(arp.ptype, 0x800)
98 self.assertEqual(arp.hwlen, 6)
99 self.assertEqual(arp.plen, 4)
100 self.assertEqual(arp.op, arp_opts["is-at"])
101 self.assertNotEqual(arp.hwsrc, smac)
102 self.assertTrue("00:00:5e:00:01" in arp.hwsrc or
103 "00:00:5E:00:01" in arp.hwsrc)
104 self.assertEqual(arp.hwdst, dmac)
105 self.assertEqual(arp.psrc, sip)
106 self.assertEqual(arp.pdst, dip)
107
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800108 def verify_ip(self, rx, smac, dmac, sip, dip):
109 ether = rx[Ether]
110 self.assertEqual(ether.dst, dmac)
111 self.assertEqual(ether.src, smac)
112
113 ip = rx[IP]
114 self.assertEqual(ip.src, sip)
115 self.assertEqual(ip.dst, dip)
116
Neale Ranns37be7362017-02-21 17:30:26 -0800117 def verify_ip_o_mpls(self, rx, smac, dmac, label, sip, dip):
118 ether = rx[Ether]
119 self.assertEqual(ether.dst, dmac)
120 self.assertEqual(ether.src, smac)
121
122 mpls = rx[MPLS]
123 self.assertTrue(mpls.label, label)
124
125 ip = rx[IP]
126 self.assertEqual(ip.src, sip)
127 self.assertEqual(ip.dst, dip)
128
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800129 def send_and_assert_no_replies(self, intf, pkts, remark):
130 intf.add_stream(pkts)
131 self.pg_enable_capture(self.pg_interfaces)
132 self.pg_start()
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700133 timeout = 1
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800134 for i in self.pg_interfaces:
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700135 i.get_capture(0, timeout=timeout)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800136 i.assert_nothing_captured(remark=remark)
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700137 timeout = 0.1
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800138
139 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
303 #
304 # We should respond to ARP requests for the unnumbered to address
305 # once an attached route to the source is known
306 #
307 self.send_and_assert_no_replies(
308 self.pg2, p,
309 "ARP req for unnumbered address - no source")
310
311 attached_host = VppIpRoute(self, self.pg2.remote_hosts[3].ip4, 32,
312 [VppRoutePath("0.0.0.0",
313 self.pg2.sw_if_index)])
314 attached_host.add_vpp_config()
315
316 self.pg2.add_stream(p)
317 self.pg_enable_capture(self.pg_interfaces)
318 self.pg_start()
319
320 rx = self.pg2.get_capture(1)
321 self.verify_arp_resp(rx[0],
322 self.pg2.local_mac,
323 self.pg2.remote_mac,
324 self.pg1.local_ip4,
325 self.pg2.remote_hosts[3].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800326
Neale Ranns30d0fd42017-05-30 07:30:04 -0700327 self.pg2.add_stream(pt)
328 self.pg_enable_capture(self.pg_interfaces)
329 self.pg_start()
330
331 rx = self.pg2.get_capture(1)
332 self.verify_arp_resp(rx[0],
333 self.pg2.local_mac,
334 self.pg2.remote_mac,
335 self.pg1.local_ip4,
336 self.pg2.remote_hosts[3].ip4)
337
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800338 #
Neale Ranns3983ac22017-03-10 11:53:27 -0800339 # A neighbor entry that has no associated FIB-entry
340 #
341 arp_no_fib = VppNeighbor(self,
342 self.pg1.sw_if_index,
343 self.pg1.remote_hosts[4].mac,
344 self.pg1.remote_hosts[4].ip4,
345 is_no_fib_entry=1)
346 arp_no_fib.add_vpp_config()
347
348 #
349 # check we have the neighbor, but no route
350 #
351 self.assertTrue(find_nbr(self,
352 self.pg1.sw_if_index,
353 self.pg1._remote_hosts[4].ip4))
354 self.assertFalse(find_route(self,
355 self.pg1._remote_hosts[4].ip4,
356 32))
357 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800358 # pg2 is unnumbered to pg1, so we can form adjacencies out of pg2
359 # from within pg1's subnet
Neale Ranns3983ac22017-03-10 11:53:27 -0800360 #
361 arp_unnum = VppNeighbor(self,
362 self.pg2.sw_if_index,
363 self.pg1.remote_hosts[5].mac,
364 self.pg1.remote_hosts[5].ip4)
365 arp_unnum.add_vpp_config()
366
367 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
368 IP(src=self.pg0.remote_ip4,
369 dst=self.pg1._remote_hosts[5].ip4) /
370 UDP(sport=1234, dport=1234) /
371 Raw())
372
373 self.pg0.add_stream(p)
374 self.pg_enable_capture(self.pg_interfaces)
375 self.pg_start()
376
377 rx = self.pg2.get_capture(1)
378
379 self.verify_ip(rx[0],
380 self.pg2.local_mac,
381 self.pg1.remote_hosts[5].mac,
382 self.pg0.remote_ip4,
383 self.pg1._remote_hosts[5].ip4)
384
385 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800386 # ARP requests from hosts in pg1's subnet sent on pg2 are replied to
387 # with the unnumbered interface's address as the source
388 #
389 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
390 ARP(op="who-has",
391 hwsrc=self.pg2.remote_mac,
392 pdst=self.pg1.local_ip4,
393 psrc=self.pg1.remote_hosts[6].ip4))
394
395 self.pg2.add_stream(p)
396 self.pg_enable_capture(self.pg_interfaces)
397 self.pg_start()
398
399 rx = self.pg2.get_capture(1)
400 self.verify_arp_resp(rx[0],
401 self.pg2.local_mac,
402 self.pg2.remote_mac,
403 self.pg1.local_ip4,
404 self.pg1.remote_hosts[6].ip4)
405
406 #
407 # An attached host route out of pg2 for an undiscovered hosts generates
408 # an ARP request with the unnumbered address as the source
409 #
410 att_unnum = VppIpRoute(self, self.pg1.remote_hosts[7].ip4, 32,
411 [VppRoutePath("0.0.0.0",
412 self.pg2.sw_if_index)])
413 att_unnum.add_vpp_config()
414
415 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
416 IP(src=self.pg0.remote_ip4,
417 dst=self.pg1._remote_hosts[7].ip4) /
418 UDP(sport=1234, dport=1234) /
419 Raw())
420
421 self.pg0.add_stream(p)
422 self.pg_enable_capture(self.pg_interfaces)
423 self.pg_start()
424
425 rx = self.pg2.get_capture(1)
426
427 self.verify_arp_req(rx[0],
428 self.pg2.local_mac,
429 self.pg1.local_ip4,
430 self.pg1._remote_hosts[7].ip4)
431
432 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
433 ARP(op="who-has",
434 hwsrc=self.pg2.remote_mac,
435 pdst=self.pg1.local_ip4,
436 psrc=self.pg1.remote_hosts[7].ip4))
437
438 self.pg2.add_stream(p)
439 self.pg_enable_capture(self.pg_interfaces)
440 self.pg_start()
441
442 rx = self.pg2.get_capture(1)
443 self.verify_arp_resp(rx[0],
444 self.pg2.local_mac,
445 self.pg2.remote_mac,
446 self.pg1.local_ip4,
447 self.pg1.remote_hosts[7].ip4)
448
449 #
450 # An attached host route as yet unresolved out of pg2 for an
451 # undiscovered host, an ARP requests begets a response.
452 #
453 att_unnum1 = VppIpRoute(self, self.pg1.remote_hosts[8].ip4, 32,
454 [VppRoutePath("0.0.0.0",
455 self.pg2.sw_if_index)])
456 att_unnum1.add_vpp_config()
457
458 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
459 ARP(op="who-has",
460 hwsrc=self.pg2.remote_mac,
461 pdst=self.pg1.local_ip4,
462 psrc=self.pg1.remote_hosts[8].ip4))
463
464 self.pg2.add_stream(p)
465 self.pg_enable_capture(self.pg_interfaces)
466 self.pg_start()
467
468 rx = self.pg2.get_capture(1)
469 self.verify_arp_resp(rx[0],
470 self.pg2.local_mac,
471 self.pg2.remote_mac,
472 self.pg1.local_ip4,
473 self.pg1.remote_hosts[8].ip4)
474
475 #
Neale Ranns30d0fd42017-05-30 07:30:04 -0700476 # Send an ARP request from one of the so-far unlearned remote hosts
477 # with a VLAN0 tag
478 #
479 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
480 src=self.pg1._remote_hosts[9].mac) /
481 Dot1Q(vlan=0) /
482 ARP(op="who-has",
483 hwsrc=self.pg1._remote_hosts[9].mac,
484 pdst=self.pg1.local_ip4,
485 psrc=self.pg1._remote_hosts[9].ip4))
486
487 self.pg1.add_stream(p)
488 self.pg_enable_capture(self.pg_interfaces)
489 self.pg_start()
490
491 rx = self.pg1.get_capture(1)
492 self.verify_arp_resp(rx[0],
493 self.pg1.local_mac,
494 self.pg1._remote_hosts[9].mac,
495 self.pg1.local_ip4,
496 self.pg1._remote_hosts[9].ip4)
497
498 #
Neale Rannsca193612017-06-14 06:50:08 -0700499 # Add a hierachy of routes for a host in the sub-net.
500 # Should still get an ARP resp since the cover is attached
501 #
502 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_mac) /
503 ARP(op="who-has",
504 hwsrc=self.pg1.remote_mac,
505 pdst=self.pg1.local_ip4,
506 psrc=self.pg1.remote_hosts[10].ip4))
507
508 r1 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 30,
509 [VppRoutePath(self.pg1.remote_hosts[10].ip4,
510 self.pg1.sw_if_index)])
511 r1.add_vpp_config()
512
513 self.pg1.add_stream(p)
514 self.pg_enable_capture(self.pg_interfaces)
515 self.pg_start()
516 rx = self.pg1.get_capture(1)
517 self.verify_arp_resp(rx[0],
518 self.pg1.local_mac,
519 self.pg1.remote_mac,
520 self.pg1.local_ip4,
521 self.pg1.remote_hosts[10].ip4)
522
523 r2 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 32,
524 [VppRoutePath(self.pg1.remote_hosts[10].ip4,
525 self.pg1.sw_if_index)])
526 r2.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 #
539 # add an ARP entry that's not on the sub-net and so whose
540 # adj-fib fails the refinement check. then send an ARP request
541 # from that source
542 #
543 a1 = VppNeighbor(self,
544 self.pg0.sw_if_index,
545 self.pg0.remote_mac,
546 "100.100.100.50")
547 a1.add_vpp_config()
548
549 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
550 ARP(op="who-has",
551 hwsrc=self.pg0.remote_mac,
552 psrc="100.100.100.50",
553 pdst=self.pg0.remote_ip4))
554 self.send_and_assert_no_replies(self.pg0, p,
555 "ARP req for from failed adj-fib")
556
557 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800558 # ERROR Cases
559 # 1 - don't respond to ARP request for address not within the
560 # interface's sub-net
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700561 # 1b - nor within the unnumbered subnet
562 # 1c - nor within the subnet of a different interface
563 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800564 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 pdst="10.10.10.3",
568 psrc=self.pg0.remote_ip4))
569 self.send_and_assert_no_replies(self.pg0, p,
570 "ARP req for non-local destination")
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700571 self.assertFalse(find_nbr(self,
572 self.pg0.sw_if_index,
573 "10.10.10.3"))
574
Neale Ranns4b919a52017-03-11 05:55:21 -0800575 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
576 ARP(op="who-has",
577 hwsrc=self.pg2.remote_mac,
578 pdst="10.10.10.3",
579 psrc=self.pg1.remote_hosts[7].ip4))
580 self.send_and_assert_no_replies(
581 self.pg0, p,
582 "ARP req for non-local destination - unnum")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800583
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700584 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
585 ARP(op="who-has",
586 hwsrc=self.pg0.remote_mac,
587 pdst=self.pg1.local_ip4,
588 psrc=self.pg1.remote_ip4))
589 self.send_and_assert_no_replies(self.pg0, p,
590 "ARP req diff sub-net")
591 self.assertFalse(find_nbr(self,
592 self.pg0.sw_if_index,
593 self.pg1.remote_ip4))
594
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800595 #
596 # 2 - don't respond to ARP request from an address not within the
597 # interface's sub-net
Neale Rannsca193612017-06-14 06:50:08 -0700598 # 2b - to a prxied address
599 # 2c - not within a differents interface's sub-net
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800600 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
601 ARP(op="who-has",
602 hwsrc=self.pg0.remote_mac,
603 psrc="10.10.10.3",
604 pdst=self.pg0.local_ip4))
605 self.send_and_assert_no_replies(self.pg0, p,
606 "ARP req for non-local source")
Neale Ranns4b919a52017-03-11 05:55:21 -0800607 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
608 ARP(op="who-has",
609 hwsrc=self.pg2.remote_mac,
610 psrc="10.10.10.3",
611 pdst=self.pg0.local_ip4))
612 self.send_and_assert_no_replies(
613 self.pg0, p,
614 "ARP req for non-local source - unnum")
Neale Rannsca193612017-06-14 06:50:08 -0700615 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=self.pg1.remote_ip4,
619 pdst=self.pg0.local_ip4))
620 self.send_and_assert_no_replies(self.pg0, p,
621 "ARP req for non-local source 2c")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800622
623 #
624 # 3 - don't respond to ARP request from an address that belongs to
625 # the router
626 #
627 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
628 ARP(op="who-has",
629 hwsrc=self.pg0.remote_mac,
630 psrc=self.pg0.local_ip4,
631 pdst=self.pg0.local_ip4))
632 self.send_and_assert_no_replies(self.pg0, p,
633 "ARP req for non-local source")
634
635 #
636 # 4 - don't respond to ARP requests that has mac source different
637 # from ARP request HW source
638 # the router
639 #
640 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
641 ARP(op="who-has",
642 hwsrc="00:00:00:DE:AD:BE",
643 psrc=self.pg0.remote_ip4,
644 pdst=self.pg0.local_ip4))
645 self.send_and_assert_no_replies(self.pg0, p,
646 "ARP req for non-local source")
647
648 #
649 # cleanup
650 #
651 dyn_arp.remove_vpp_config()
652 static_arp.remove_vpp_config()
Neale Ranns3983ac22017-03-10 11:53:27 -0800653 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800654
Neale Ranns4b919a52017-03-11 05:55:21 -0800655 # need this to flush the adj-fibs
656 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
657 self.pg2.admin_down()
Neale Rannsca193612017-06-14 06:50:08 -0700658 self.pg1.admin_down()
Neale Ranns4b919a52017-03-11 05:55:21 -0800659
Neale Ranns24b170a2017-08-15 05:33:11 -0700660 def test_proxy_mirror_arp(self):
661 """ Interface Mirror Proxy ARP """
662
663 #
664 # When VPP has an interface whose address is also applied to a TAP
665 # interface on the host, then VPP's TAP interface will be unnumbered
666 # to the 'real' interface and do proxy ARP from the host.
667 # the curious aspect of this setup is that ARP requests from the host
668 # will come from the VPP's own address.
669 #
670 self.pg0.generate_remote_hosts(2)
671
672 arp_req_from_me = (Ether(src=self.pg2.remote_mac,
673 dst="ff:ff:ff:ff:ff:ff") /
674 ARP(op="who-has",
675 hwsrc=self.pg2.remote_mac,
676 pdst=self.pg0.remote_hosts[1].ip4,
677 psrc=self.pg0.local_ip4))
678
679 #
680 # Configure Proxy ARP for the subnet on PG0addresses on pg0
681 #
682 self.vapi.proxy_arp_add_del(self.pg0._local_ip4n_subnet,
683 self.pg0._local_ip4n_bcast)
684
685 # Make pg2 un-numbered to pg0
686 #
687 self.pg2.set_unnumbered(self.pg0.sw_if_index)
688
689 #
690 # Enable pg2 for proxy ARP
691 #
692 self.pg2.set_proxy_arp()
693
694 #
695 # Send the ARP request with an originating address that
696 # is VPP's own address
697 #
698 self.pg2.add_stream(arp_req_from_me)
699 self.pg_enable_capture(self.pg_interfaces)
700 self.pg_start()
701
702 rx = self.pg2.get_capture(1)
703 self.verify_arp_resp(rx[0],
704 self.pg2.local_mac,
705 self.pg2.remote_mac,
706 self.pg0.remote_hosts[1].ip4,
707 self.pg0.local_ip4)
708
709 #
710 # validate we have not learned an ARP entry as a result of this
711 #
712 self.assertFalse(find_nbr(self,
713 self.pg2.sw_if_index,
714 self.pg0.local_ip4))
715
716 #
717 # cleanup
718 #
719 self.pg2.set_proxy_arp(0)
720 self.vapi.proxy_arp_add_del(self.pg0._local_ip4n_subnet,
721 self.pg0._local_ip4n_bcast,
722 is_add=0)
723
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800724 def test_proxy_arp(self):
725 """ Proxy ARP """
726
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700727 self.pg1.generate_remote_hosts(2)
728
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800729 #
730 # Proxy ARP rewquest packets for each interface
731 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800732 arp_req_pg0 = (Ether(src=self.pg0.remote_mac,
733 dst="ff:ff:ff:ff:ff:ff") /
734 ARP(op="who-has",
735 hwsrc=self.pg0.remote_mac,
736 pdst="10.10.10.3",
737 psrc=self.pg0.remote_ip4))
Neale Ranns30d0fd42017-05-30 07:30:04 -0700738 arp_req_pg0_tagged = (Ether(src=self.pg0.remote_mac,
739 dst="ff:ff:ff:ff:ff:ff") /
740 Dot1Q(vlan=0) /
741 ARP(op="who-has",
742 hwsrc=self.pg0.remote_mac,
743 pdst="10.10.10.3",
744 psrc=self.pg0.remote_ip4))
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800745 arp_req_pg1 = (Ether(src=self.pg1.remote_mac,
746 dst="ff:ff:ff:ff:ff:ff") /
747 ARP(op="who-has",
748 hwsrc=self.pg1.remote_mac,
749 pdst="10.10.10.3",
750 psrc=self.pg1.remote_ip4))
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700751 arp_req_pg2 = (Ether(src=self.pg2.remote_mac,
752 dst="ff:ff:ff:ff:ff:ff") /
753 ARP(op="who-has",
754 hwsrc=self.pg2.remote_mac,
755 pdst="10.10.10.3",
756 psrc=self.pg1.remote_hosts[1].ip4))
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800757 arp_req_pg3 = (Ether(src=self.pg3.remote_mac,
758 dst="ff:ff:ff:ff:ff:ff") /
759 ARP(op="who-has",
760 hwsrc=self.pg3.remote_mac,
761 pdst="10.10.10.3",
762 psrc=self.pg3.remote_ip4))
763
764 #
765 # Configure Proxy ARP for 10.10.10.0 -> 10.10.10.124
766 #
767 self.vapi.proxy_arp_add_del(inet_pton(AF_INET, "10.10.10.2"),
768 inet_pton(AF_INET, "10.10.10.124"))
769
770 #
771 # No responses are sent when the interfaces are not enabled for proxy
772 # ARP
773 #
774 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
775 "ARP req from unconfigured interface")
776 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
777 "ARP req from unconfigured interface")
778
779 #
780 # Make pg2 un-numbered to pg1
781 # still won't reply.
782 #
783 self.pg2.set_unnumbered(self.pg1.sw_if_index)
784
785 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
786 "ARP req from unnumbered interface")
787
788 #
789 # Enable each interface to reply to proxy ARPs
790 #
791 for i in self.pg_interfaces:
792 i.set_proxy_arp()
793
794 #
795 # Now each of the interfaces should reply to a request to a proxied
796 # address
797 #
798 self.pg0.add_stream(arp_req_pg0)
799 self.pg_enable_capture(self.pg_interfaces)
800 self.pg_start()
801
802 rx = self.pg0.get_capture(1)
803 self.verify_arp_resp(rx[0],
804 self.pg0.local_mac,
805 self.pg0.remote_mac,
806 "10.10.10.3",
807 self.pg0.remote_ip4)
808
Neale Ranns30d0fd42017-05-30 07:30:04 -0700809 self.pg0.add_stream(arp_req_pg0_tagged)
810 self.pg_enable_capture(self.pg_interfaces)
811 self.pg_start()
812
813 rx = self.pg0.get_capture(1)
814 self.verify_arp_resp(rx[0],
815 self.pg0.local_mac,
816 self.pg0.remote_mac,
817 "10.10.10.3",
818 self.pg0.remote_ip4)
819
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800820 self.pg1.add_stream(arp_req_pg1)
821 self.pg_enable_capture(self.pg_interfaces)
822 self.pg_start()
823
824 rx = self.pg1.get_capture(1)
825 self.verify_arp_resp(rx[0],
826 self.pg1.local_mac,
827 self.pg1.remote_mac,
828 "10.10.10.3",
829 self.pg1.remote_ip4)
830
831 self.pg2.add_stream(arp_req_pg2)
832 self.pg_enable_capture(self.pg_interfaces)
833 self.pg_start()
834
835 rx = self.pg2.get_capture(1)
836 self.verify_arp_resp(rx[0],
837 self.pg2.local_mac,
838 self.pg2.remote_mac,
839 "10.10.10.3",
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700840 self.pg1.remote_hosts[1].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800841
842 #
843 # A request for an address out of the configured range
844 #
845 arp_req_pg1_hi = (Ether(src=self.pg1.remote_mac,
846 dst="ff:ff:ff:ff:ff:ff") /
847 ARP(op="who-has",
848 hwsrc=self.pg1.remote_mac,
849 pdst="10.10.10.125",
850 psrc=self.pg1.remote_ip4))
851 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_hi,
852 "ARP req out of range HI")
853 arp_req_pg1_low = (Ether(src=self.pg1.remote_mac,
854 dst="ff:ff:ff:ff:ff:ff") /
855 ARP(op="who-has",
856 hwsrc=self.pg1.remote_mac,
857 pdst="10.10.10.1",
858 psrc=self.pg1.remote_ip4))
859 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_low,
860 "ARP req out of range Low")
861
862 #
863 # Request for an address in the proxy range but from an interface
864 # in a different VRF
865 #
866 self.send_and_assert_no_replies(self.pg3, arp_req_pg3,
867 "ARP req from different VRF")
868
869 #
870 # Disable Each interface for proxy ARP
871 # - expect none to respond
872 #
873 for i in self.pg_interfaces:
874 i.set_proxy_arp(0)
875
876 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
877 "ARP req from disable")
878 self.send_and_assert_no_replies(self.pg1, arp_req_pg1,
879 "ARP req from disable")
880 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
881 "ARP req from disable")
Neale Ranns37be7362017-02-21 17:30:26 -0800882
883 #
884 # clean up on interface 2
885 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800886 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns37be7362017-02-21 17:30:26 -0800887
888 def test_mpls(self):
889 """ MPLS """
890
891 #
892 # Interface 2 does not yet have ip4 config
893 #
894 self.pg2.config_ip4()
895 self.pg2.generate_remote_hosts(2)
896
897 #
898 # Add a reoute with out going label via an ARP unresolved next-hop
899 #
900 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
901 [VppRoutePath(self.pg2.remote_hosts[1].ip4,
902 self.pg2.sw_if_index,
903 labels=[55])])
904 ip_10_0_0_1.add_vpp_config()
905
906 #
907 # packets should generate an ARP request
908 #
909 p = (Ether(src=self.pg0.remote_mac,
910 dst=self.pg0.local_mac) /
911 IP(src=self.pg0.remote_ip4, dst="10.0.0.1") /
912 UDP(sport=1234, dport=1234) /
913 Raw('\xa5' * 100))
914
915 self.pg0.add_stream(p)
916 self.pg_enable_capture(self.pg_interfaces)
917 self.pg_start()
918
919 rx = self.pg2.get_capture(1)
920 self.verify_arp_req(rx[0],
921 self.pg2.local_mac,
922 self.pg2.local_ip4,
923 self.pg2._remote_hosts[1].ip4)
924
925 #
926 # now resolve the neighbours
927 #
928 self.pg2.configure_ipv4_neighbors()
929
930 #
931 # Now packet should be properly MPLS encapped.
932 # This verifies that MPLS link-type adjacencies are completed
933 # when the ARP entry resolves
934 #
935 self.pg0.add_stream(p)
936 self.pg_enable_capture(self.pg_interfaces)
937 self.pg_start()
938
939 rx = self.pg2.get_capture(1)
940 self.verify_ip_o_mpls(rx[0],
941 self.pg2.local_mac,
942 self.pg2.remote_hosts[1].mac,
943 55,
944 self.pg0.remote_ip4,
945 "10.0.0.1")
Neale Ranns4b919a52017-03-11 05:55:21 -0800946 self.pg2.unconfig_ip4()
Neale Ranns37be7362017-02-21 17:30:26 -0800947
Matthew Smithcb9ab472017-05-16 21:35:56 -0500948 def test_arp_vrrp(self):
949 """ ARP reply with VRRP virtual src hw addr """
950
951 #
952 # IP packet destined for pg1 remote host arrives on pg0 resulting
953 # in an ARP request for the address of the remote host on pg1
954 #
955 p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
956 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
957 UDP(sport=1234, dport=1234) /
958 Raw())
959
960 self.pg0.add_stream(p0)
961 self.pg_enable_capture(self.pg_interfaces)
962 self.pg_start()
963
964 rx1 = self.pg1.get_capture(1)
965
966 self.verify_arp_req(rx1[0],
967 self.pg1.local_mac,
968 self.pg1.local_ip4,
969 self.pg1.remote_ip4)
970
971 #
972 # ARP reply for address of pg1 remote host arrives on pg1 with
973 # the hw src addr set to a value in the VRRP IPv4 range of
974 # MAC addresses
975 #
976 p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
977 ARP(op="is-at", hwdst=self.pg1.local_mac,
978 hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
979 psrc=self.pg1.remote_ip4))
980
981 self.pg1.add_stream(p1)
982 self.pg_enable_capture(self.pg_interfaces)
983 self.pg_start()
984
985 #
986 # IP packet destined for pg1 remote host arrives on pg0 again.
987 # VPP should have an ARP entry for that address now and the packet
988 # should be sent out pg1.
989 #
990 self.pg0.add_stream(p0)
991 self.pg_enable_capture(self.pg_interfaces)
992 self.pg_start()
993
994 rx1 = self.pg1.get_capture(1)
995
996 self.verify_ip(rx1[0],
997 self.pg1.local_mac,
998 "00:00:5e:00:01:09",
999 self.pg0.remote_ip4,
1000 self.pg1.remote_ip4)
1001
1002 self.pg1.admin_down()
1003 self.pg1.admin_up()
1004
Neale Rannsdcd6d622017-05-26 02:59:16 -07001005 def test_arp_duplicates(self):
1006 """ ARP Duplicates"""
1007
1008 #
1009 # Generate some hosts on the LAN
1010 #
1011 self.pg1.generate_remote_hosts(3)
1012
1013 #
1014 # Add host 1 on pg1 and pg2
1015 #
1016 arp_pg1 = VppNeighbor(self,
1017 self.pg1.sw_if_index,
1018 self.pg1.remote_hosts[1].mac,
1019 self.pg1.remote_hosts[1].ip4)
1020 arp_pg1.add_vpp_config()
1021 arp_pg2 = VppNeighbor(self,
1022 self.pg2.sw_if_index,
1023 self.pg2.remote_mac,
1024 self.pg1.remote_hosts[1].ip4)
1025 arp_pg2.add_vpp_config()
1026
1027 #
1028 # IP packet destined for pg1 remote host arrives on pg1 again.
1029 #
1030 p = (Ether(dst=self.pg0.local_mac,
1031 src=self.pg0.remote_mac) /
1032 IP(src=self.pg0.remote_ip4,
1033 dst=self.pg1.remote_hosts[1].ip4) /
1034 UDP(sport=1234, dport=1234) /
1035 Raw())
1036
1037 self.pg0.add_stream(p)
1038 self.pg_enable_capture(self.pg_interfaces)
1039 self.pg_start()
1040
1041 rx1 = self.pg1.get_capture(1)
1042
1043 self.verify_ip(rx1[0],
1044 self.pg1.local_mac,
1045 self.pg1.remote_hosts[1].mac,
1046 self.pg0.remote_ip4,
1047 self.pg1.remote_hosts[1].ip4)
1048
1049 #
1050 # remove the duplicate on pg1
1051 # packet stream shoud generate ARPs out of pg1
1052 #
1053 arp_pg1.remove_vpp_config()
1054
1055 self.pg0.add_stream(p)
1056 self.pg_enable_capture(self.pg_interfaces)
1057 self.pg_start()
1058
1059 rx1 = self.pg1.get_capture(1)
1060
1061 self.verify_arp_req(rx1[0],
1062 self.pg1.local_mac,
1063 self.pg1.local_ip4,
1064 self.pg1.remote_hosts[1].ip4)
1065
1066 #
1067 # Add it back
1068 #
1069 arp_pg1.add_vpp_config()
1070
1071 self.pg0.add_stream(p)
1072 self.pg_enable_capture(self.pg_interfaces)
1073 self.pg_start()
1074
1075 rx1 = self.pg1.get_capture(1)
1076
1077 self.verify_ip(rx1[0],
1078 self.pg1.local_mac,
1079 self.pg1.remote_hosts[1].mac,
1080 self.pg0.remote_ip4,
1081 self.pg1.remote_hosts[1].ip4)
1082
1083
Neale Ranns37be7362017-02-21 17:30:26 -08001084if __name__ == '__main__':
1085 unittest.main(testRunner=VppTestRunner)