blob: 67d64a20faa3a9d1f28e19ab37810f90cccedf1b [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
11from scapy.layers.l2 import Ether, ARP
12from 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 Ranns4b919a52017-03-11 05:55:21 -0800145 self.pg1.generate_remote_hosts(9)
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))
289 self.send_and_assert_no_replies(self.pg2, p,
290 "interface not IP enabled")
291
292 #
293 # Make pg2 un-numbered to pg1
294 #
295 self.pg2.set_unnumbered(self.pg1.sw_if_index)
296
297 #
298 # We should respond to ARP requests for the unnumbered to address
299 # once an attached route to the source is known
300 #
301 self.send_and_assert_no_replies(
302 self.pg2, p,
303 "ARP req for unnumbered address - no source")
304
305 attached_host = VppIpRoute(self, self.pg2.remote_hosts[3].ip4, 32,
306 [VppRoutePath("0.0.0.0",
307 self.pg2.sw_if_index)])
308 attached_host.add_vpp_config()
309
310 self.pg2.add_stream(p)
311 self.pg_enable_capture(self.pg_interfaces)
312 self.pg_start()
313
314 rx = self.pg2.get_capture(1)
315 self.verify_arp_resp(rx[0],
316 self.pg2.local_mac,
317 self.pg2.remote_mac,
318 self.pg1.local_ip4,
319 self.pg2.remote_hosts[3].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800320
321 #
Neale Ranns3983ac22017-03-10 11:53:27 -0800322 # A neighbor entry that has no associated FIB-entry
323 #
324 arp_no_fib = VppNeighbor(self,
325 self.pg1.sw_if_index,
326 self.pg1.remote_hosts[4].mac,
327 self.pg1.remote_hosts[4].ip4,
328 is_no_fib_entry=1)
329 arp_no_fib.add_vpp_config()
330
331 #
332 # check we have the neighbor, but no route
333 #
334 self.assertTrue(find_nbr(self,
335 self.pg1.sw_if_index,
336 self.pg1._remote_hosts[4].ip4))
337 self.assertFalse(find_route(self,
338 self.pg1._remote_hosts[4].ip4,
339 32))
340 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800341 # pg2 is unnumbered to pg1, so we can form adjacencies out of pg2
342 # from within pg1's subnet
Neale Ranns3983ac22017-03-10 11:53:27 -0800343 #
344 arp_unnum = VppNeighbor(self,
345 self.pg2.sw_if_index,
346 self.pg1.remote_hosts[5].mac,
347 self.pg1.remote_hosts[5].ip4)
348 arp_unnum.add_vpp_config()
349
350 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
351 IP(src=self.pg0.remote_ip4,
352 dst=self.pg1._remote_hosts[5].ip4) /
353 UDP(sport=1234, dport=1234) /
354 Raw())
355
356 self.pg0.add_stream(p)
357 self.pg_enable_capture(self.pg_interfaces)
358 self.pg_start()
359
360 rx = self.pg2.get_capture(1)
361
362 self.verify_ip(rx[0],
363 self.pg2.local_mac,
364 self.pg1.remote_hosts[5].mac,
365 self.pg0.remote_ip4,
366 self.pg1._remote_hosts[5].ip4)
367
368 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800369 # ARP requests from hosts in pg1's subnet sent on pg2 are replied to
370 # with the unnumbered interface's address as the source
371 #
372 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
373 ARP(op="who-has",
374 hwsrc=self.pg2.remote_mac,
375 pdst=self.pg1.local_ip4,
376 psrc=self.pg1.remote_hosts[6].ip4))
377
378 self.pg2.add_stream(p)
379 self.pg_enable_capture(self.pg_interfaces)
380 self.pg_start()
381
382 rx = self.pg2.get_capture(1)
383 self.verify_arp_resp(rx[0],
384 self.pg2.local_mac,
385 self.pg2.remote_mac,
386 self.pg1.local_ip4,
387 self.pg1.remote_hosts[6].ip4)
388
389 #
390 # An attached host route out of pg2 for an undiscovered hosts generates
391 # an ARP request with the unnumbered address as the source
392 #
393 att_unnum = VppIpRoute(self, self.pg1.remote_hosts[7].ip4, 32,
394 [VppRoutePath("0.0.0.0",
395 self.pg2.sw_if_index)])
396 att_unnum.add_vpp_config()
397
398 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
399 IP(src=self.pg0.remote_ip4,
400 dst=self.pg1._remote_hosts[7].ip4) /
401 UDP(sport=1234, dport=1234) /
402 Raw())
403
404 self.pg0.add_stream(p)
405 self.pg_enable_capture(self.pg_interfaces)
406 self.pg_start()
407
408 rx = self.pg2.get_capture(1)
409
410 self.verify_arp_req(rx[0],
411 self.pg2.local_mac,
412 self.pg1.local_ip4,
413 self.pg1._remote_hosts[7].ip4)
414
415 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
416 ARP(op="who-has",
417 hwsrc=self.pg2.remote_mac,
418 pdst=self.pg1.local_ip4,
419 psrc=self.pg1.remote_hosts[7].ip4))
420
421 self.pg2.add_stream(p)
422 self.pg_enable_capture(self.pg_interfaces)
423 self.pg_start()
424
425 rx = self.pg2.get_capture(1)
426 self.verify_arp_resp(rx[0],
427 self.pg2.local_mac,
428 self.pg2.remote_mac,
429 self.pg1.local_ip4,
430 self.pg1.remote_hosts[7].ip4)
431
432 #
433 # An attached host route as yet unresolved out of pg2 for an
434 # undiscovered host, an ARP requests begets a response.
435 #
436 att_unnum1 = VppIpRoute(self, self.pg1.remote_hosts[8].ip4, 32,
437 [VppRoutePath("0.0.0.0",
438 self.pg2.sw_if_index)])
439 att_unnum1.add_vpp_config()
440
441 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
442 ARP(op="who-has",
443 hwsrc=self.pg2.remote_mac,
444 pdst=self.pg1.local_ip4,
445 psrc=self.pg1.remote_hosts[8].ip4))
446
447 self.pg2.add_stream(p)
448 self.pg_enable_capture(self.pg_interfaces)
449 self.pg_start()
450
451 rx = self.pg2.get_capture(1)
452 self.verify_arp_resp(rx[0],
453 self.pg2.local_mac,
454 self.pg2.remote_mac,
455 self.pg1.local_ip4,
456 self.pg1.remote_hosts[8].ip4)
457
458 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800459 # ERROR Cases
460 # 1 - don't respond to ARP request for address not within the
461 # interface's sub-net
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700462 # 1b - nor within the unnumbered subnet
463 # 1c - nor within the subnet of a different interface
464 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800465 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
466 ARP(op="who-has",
467 hwsrc=self.pg0.remote_mac,
468 pdst="10.10.10.3",
469 psrc=self.pg0.remote_ip4))
470 self.send_and_assert_no_replies(self.pg0, p,
471 "ARP req for non-local destination")
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700472 self.assertFalse(find_nbr(self,
473 self.pg0.sw_if_index,
474 "10.10.10.3"))
475
Neale Ranns4b919a52017-03-11 05:55:21 -0800476 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
477 ARP(op="who-has",
478 hwsrc=self.pg2.remote_mac,
479 pdst="10.10.10.3",
480 psrc=self.pg1.remote_hosts[7].ip4))
481 self.send_and_assert_no_replies(
482 self.pg0, p,
483 "ARP req for non-local destination - unnum")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800484
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700485 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
486 ARP(op="who-has",
487 hwsrc=self.pg0.remote_mac,
488 pdst=self.pg1.local_ip4,
489 psrc=self.pg1.remote_ip4))
490 self.send_and_assert_no_replies(self.pg0, p,
491 "ARP req diff sub-net")
492 self.assertFalse(find_nbr(self,
493 self.pg0.sw_if_index,
494 self.pg1.remote_ip4))
495
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800496 #
497 # 2 - don't respond to ARP request from an address not within the
498 # interface's sub-net
499 #
500 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
501 ARP(op="who-has",
502 hwsrc=self.pg0.remote_mac,
503 psrc="10.10.10.3",
504 pdst=self.pg0.local_ip4))
505 self.send_and_assert_no_replies(self.pg0, p,
506 "ARP req for non-local source")
Neale Ranns4b919a52017-03-11 05:55:21 -0800507 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
508 ARP(op="who-has",
509 hwsrc=self.pg2.remote_mac,
510 psrc="10.10.10.3",
511 pdst=self.pg0.local_ip4))
512 self.send_and_assert_no_replies(
513 self.pg0, p,
514 "ARP req for non-local source - unnum")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800515
516 #
517 # 3 - don't respond to ARP request from an address that belongs to
518 # the router
519 #
520 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
521 ARP(op="who-has",
522 hwsrc=self.pg0.remote_mac,
523 psrc=self.pg0.local_ip4,
524 pdst=self.pg0.local_ip4))
525 self.send_and_assert_no_replies(self.pg0, p,
526 "ARP req for non-local source")
527
528 #
529 # 4 - don't respond to ARP requests that has mac source different
530 # from ARP request HW source
531 # the router
532 #
533 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
534 ARP(op="who-has",
535 hwsrc="00:00:00:DE:AD:BE",
536 psrc=self.pg0.remote_ip4,
537 pdst=self.pg0.local_ip4))
538 self.send_and_assert_no_replies(self.pg0, p,
539 "ARP req for non-local source")
540
541 #
542 # cleanup
543 #
544 dyn_arp.remove_vpp_config()
545 static_arp.remove_vpp_config()
Neale Ranns3983ac22017-03-10 11:53:27 -0800546 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800547
Neale Ranns4b919a52017-03-11 05:55:21 -0800548 # need this to flush the adj-fibs
549 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
550 self.pg2.admin_down()
551
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800552 def test_proxy_arp(self):
553 """ Proxy ARP """
554
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700555 self.pg1.generate_remote_hosts(2)
556
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800557 #
558 # Proxy ARP rewquest packets for each interface
559 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800560 arp_req_pg0 = (Ether(src=self.pg0.remote_mac,
561 dst="ff:ff:ff:ff:ff:ff") /
562 ARP(op="who-has",
563 hwsrc=self.pg0.remote_mac,
564 pdst="10.10.10.3",
565 psrc=self.pg0.remote_ip4))
566 arp_req_pg1 = (Ether(src=self.pg1.remote_mac,
567 dst="ff:ff:ff:ff:ff:ff") /
568 ARP(op="who-has",
569 hwsrc=self.pg1.remote_mac,
570 pdst="10.10.10.3",
571 psrc=self.pg1.remote_ip4))
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700572 arp_req_pg2 = (Ether(src=self.pg2.remote_mac,
573 dst="ff:ff:ff:ff:ff:ff") /
574 ARP(op="who-has",
575 hwsrc=self.pg2.remote_mac,
576 pdst="10.10.10.3",
577 psrc=self.pg1.remote_hosts[1].ip4))
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800578 arp_req_pg3 = (Ether(src=self.pg3.remote_mac,
579 dst="ff:ff:ff:ff:ff:ff") /
580 ARP(op="who-has",
581 hwsrc=self.pg3.remote_mac,
582 pdst="10.10.10.3",
583 psrc=self.pg3.remote_ip4))
584
585 #
586 # Configure Proxy ARP for 10.10.10.0 -> 10.10.10.124
587 #
588 self.vapi.proxy_arp_add_del(inet_pton(AF_INET, "10.10.10.2"),
589 inet_pton(AF_INET, "10.10.10.124"))
590
591 #
592 # No responses are sent when the interfaces are not enabled for proxy
593 # ARP
594 #
595 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
596 "ARP req from unconfigured interface")
597 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
598 "ARP req from unconfigured interface")
599
600 #
601 # Make pg2 un-numbered to pg1
602 # still won't reply.
603 #
604 self.pg2.set_unnumbered(self.pg1.sw_if_index)
605
606 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
607 "ARP req from unnumbered interface")
608
609 #
610 # Enable each interface to reply to proxy ARPs
611 #
612 for i in self.pg_interfaces:
613 i.set_proxy_arp()
614
615 #
616 # Now each of the interfaces should reply to a request to a proxied
617 # address
618 #
619 self.pg0.add_stream(arp_req_pg0)
620 self.pg_enable_capture(self.pg_interfaces)
621 self.pg_start()
622
623 rx = self.pg0.get_capture(1)
624 self.verify_arp_resp(rx[0],
625 self.pg0.local_mac,
626 self.pg0.remote_mac,
627 "10.10.10.3",
628 self.pg0.remote_ip4)
629
630 self.pg1.add_stream(arp_req_pg1)
631 self.pg_enable_capture(self.pg_interfaces)
632 self.pg_start()
633
634 rx = self.pg1.get_capture(1)
635 self.verify_arp_resp(rx[0],
636 self.pg1.local_mac,
637 self.pg1.remote_mac,
638 "10.10.10.3",
639 self.pg1.remote_ip4)
640
641 self.pg2.add_stream(arp_req_pg2)
642 self.pg_enable_capture(self.pg_interfaces)
643 self.pg_start()
644
645 rx = self.pg2.get_capture(1)
646 self.verify_arp_resp(rx[0],
647 self.pg2.local_mac,
648 self.pg2.remote_mac,
649 "10.10.10.3",
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700650 self.pg1.remote_hosts[1].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800651
652 #
653 # A request for an address out of the configured range
654 #
655 arp_req_pg1_hi = (Ether(src=self.pg1.remote_mac,
656 dst="ff:ff:ff:ff:ff:ff") /
657 ARP(op="who-has",
658 hwsrc=self.pg1.remote_mac,
659 pdst="10.10.10.125",
660 psrc=self.pg1.remote_ip4))
661 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_hi,
662 "ARP req out of range HI")
663 arp_req_pg1_low = (Ether(src=self.pg1.remote_mac,
664 dst="ff:ff:ff:ff:ff:ff") /
665 ARP(op="who-has",
666 hwsrc=self.pg1.remote_mac,
667 pdst="10.10.10.1",
668 psrc=self.pg1.remote_ip4))
669 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_low,
670 "ARP req out of range Low")
671
672 #
673 # Request for an address in the proxy range but from an interface
674 # in a different VRF
675 #
676 self.send_and_assert_no_replies(self.pg3, arp_req_pg3,
677 "ARP req from different VRF")
678
679 #
680 # Disable Each interface for proxy ARP
681 # - expect none to respond
682 #
683 for i in self.pg_interfaces:
684 i.set_proxy_arp(0)
685
686 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
687 "ARP req from disable")
688 self.send_and_assert_no_replies(self.pg1, arp_req_pg1,
689 "ARP req from disable")
690 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
691 "ARP req from disable")
Neale Ranns37be7362017-02-21 17:30:26 -0800692
693 #
694 # clean up on interface 2
695 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800696 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns37be7362017-02-21 17:30:26 -0800697
698 def test_mpls(self):
699 """ MPLS """
700
701 #
702 # Interface 2 does not yet have ip4 config
703 #
704 self.pg2.config_ip4()
705 self.pg2.generate_remote_hosts(2)
706
707 #
708 # Add a reoute with out going label via an ARP unresolved next-hop
709 #
710 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
711 [VppRoutePath(self.pg2.remote_hosts[1].ip4,
712 self.pg2.sw_if_index,
713 labels=[55])])
714 ip_10_0_0_1.add_vpp_config()
715
716 #
717 # packets should generate an ARP request
718 #
719 p = (Ether(src=self.pg0.remote_mac,
720 dst=self.pg0.local_mac) /
721 IP(src=self.pg0.remote_ip4, dst="10.0.0.1") /
722 UDP(sport=1234, dport=1234) /
723 Raw('\xa5' * 100))
724
725 self.pg0.add_stream(p)
726 self.pg_enable_capture(self.pg_interfaces)
727 self.pg_start()
728
729 rx = self.pg2.get_capture(1)
730 self.verify_arp_req(rx[0],
731 self.pg2.local_mac,
732 self.pg2.local_ip4,
733 self.pg2._remote_hosts[1].ip4)
734
735 #
736 # now resolve the neighbours
737 #
738 self.pg2.configure_ipv4_neighbors()
739
740 #
741 # Now packet should be properly MPLS encapped.
742 # This verifies that MPLS link-type adjacencies are completed
743 # when the ARP entry resolves
744 #
745 self.pg0.add_stream(p)
746 self.pg_enable_capture(self.pg_interfaces)
747 self.pg_start()
748
749 rx = self.pg2.get_capture(1)
750 self.verify_ip_o_mpls(rx[0],
751 self.pg2.local_mac,
752 self.pg2.remote_hosts[1].mac,
753 55,
754 self.pg0.remote_ip4,
755 "10.0.0.1")
Neale Ranns4b919a52017-03-11 05:55:21 -0800756 self.pg2.unconfig_ip4()
Neale Ranns37be7362017-02-21 17:30:26 -0800757
Matthew Smithcb9ab472017-05-16 21:35:56 -0500758 def test_arp_vrrp(self):
759 """ ARP reply with VRRP virtual src hw addr """
760
761 #
762 # IP packet destined for pg1 remote host arrives on pg0 resulting
763 # in an ARP request for the address of the remote host on pg1
764 #
765 p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
766 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
767 UDP(sport=1234, dport=1234) /
768 Raw())
769
770 self.pg0.add_stream(p0)
771 self.pg_enable_capture(self.pg_interfaces)
772 self.pg_start()
773
774 rx1 = self.pg1.get_capture(1)
775
776 self.verify_arp_req(rx1[0],
777 self.pg1.local_mac,
778 self.pg1.local_ip4,
779 self.pg1.remote_ip4)
780
781 #
782 # ARP reply for address of pg1 remote host arrives on pg1 with
783 # the hw src addr set to a value in the VRRP IPv4 range of
784 # MAC addresses
785 #
786 p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
787 ARP(op="is-at", hwdst=self.pg1.local_mac,
788 hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
789 psrc=self.pg1.remote_ip4))
790
791 self.pg1.add_stream(p1)
792 self.pg_enable_capture(self.pg_interfaces)
793 self.pg_start()
794
795 #
796 # IP packet destined for pg1 remote host arrives on pg0 again.
797 # VPP should have an ARP entry for that address now and the packet
798 # should be sent out pg1.
799 #
800 self.pg0.add_stream(p0)
801 self.pg_enable_capture(self.pg_interfaces)
802 self.pg_start()
803
804 rx1 = self.pg1.get_capture(1)
805
806 self.verify_ip(rx1[0],
807 self.pg1.local_mac,
808 "00:00:5e:00:01:09",
809 self.pg0.remote_ip4,
810 self.pg1.remote_ip4)
811
812 self.pg1.admin_down()
813 self.pg1.admin_up()
814
Neale Ranns37be7362017-02-21 17:30:26 -0800815if __name__ == '__main__':
816 unittest.main(testRunner=VppTestRunner)