blob: a15106af1f9a70da439a0d883680b47bbf2579b7 [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, \
9 VppIpTable
Neale Ranns39f9d8b2017-02-16 21:57:05 -080010
11from scapy.packet import Raw
Neale Ranns30d0fd42017-05-30 07:30:04 -070012from scapy.layers.l2 import Ether, ARP, Dot1Q
Neale Ranns39f9d8b2017-02-16 21:57:05 -080013from scapy.layers.inet import IP, UDP
Neale Ranns37be7362017-02-21 17:30:26 -080014from scapy.contrib.mpls import MPLS
Neale Ranns14260392018-09-28 05:00:57 -070015from scapy.layers.inet6 import IPv6
Neale Ranns39f9d8b2017-02-16 21:57:05 -080016
17# not exported by scapy, so redefined here
18arp_opts = {"who-has": 1, "is-at": 2}
19
20
21class ARPTestCase(VppTestCase):
22 """ ARP Test Case """
23
24 def setUp(self):
25 super(ARPTestCase, self).setUp()
26
27 # create 3 pg interfaces
28 self.create_pg_interfaces(range(4))
29
30 # pg0 configured with ip4 and 6 addresses used for input
31 # pg1 configured with ip4 and 6 addresses used for output
32 # pg2 is unnumbered to pg0
33 for i in self.pg_interfaces:
34 i.admin_up()
35
36 self.pg0.config_ip4()
37 self.pg0.config_ip6()
38 self.pg0.resolve_arp()
39
40 self.pg1.config_ip4()
41 self.pg1.config_ip6()
42
43 # pg3 in a different VRF
Neale Ranns15002542017-09-10 04:39:11 -070044 self.tbl = VppIpTable(self, 1)
45 self.tbl.add_vpp_config()
46
Neale Ranns39f9d8b2017-02-16 21:57:05 -080047 self.pg3.set_table_ip4(1)
48 self.pg3.config_ip4()
49
Neale Ranns4008ac92017-02-13 23:20:04 -080050 def tearDown(self):
Neale Ranns4b919a52017-03-11 05:55:21 -080051 self.pg0.unconfig_ip4()
52 self.pg0.unconfig_ip6()
53
54 self.pg1.unconfig_ip4()
55 self.pg1.unconfig_ip6()
56
57 self.pg3.unconfig_ip4()
Neale Ranns15002542017-09-10 04:39:11 -070058 self.pg3.set_table_ip4(0)
Neale Ranns4b919a52017-03-11 05:55:21 -080059
Neale Ranns4008ac92017-02-13 23:20:04 -080060 for i in self.pg_interfaces:
Neale Ranns4008ac92017-02-13 23:20:04 -080061 i.admin_down()
62
Neale Ranns15002542017-09-10 04:39:11 -070063 super(ARPTestCase, self).tearDown()
64
Neale Ranns39f9d8b2017-02-16 21:57:05 -080065 def verify_arp_req(self, rx, smac, sip, dip):
66 ether = rx[Ether]
67 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
68 self.assertEqual(ether.src, smac)
69
70 arp = rx[ARP]
71 self.assertEqual(arp.hwtype, 1)
72 self.assertEqual(arp.ptype, 0x800)
73 self.assertEqual(arp.hwlen, 6)
74 self.assertEqual(arp.plen, 4)
75 self.assertEqual(arp.op, arp_opts["who-has"])
76 self.assertEqual(arp.hwsrc, smac)
77 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
78 self.assertEqual(arp.psrc, sip)
79 self.assertEqual(arp.pdst, dip)
80
81 def verify_arp_resp(self, rx, smac, dmac, sip, dip):
82 ether = rx[Ether]
83 self.assertEqual(ether.dst, dmac)
84 self.assertEqual(ether.src, smac)
85
86 arp = rx[ARP]
87 self.assertEqual(arp.hwtype, 1)
88 self.assertEqual(arp.ptype, 0x800)
89 self.assertEqual(arp.hwlen, 6)
90 self.assertEqual(arp.plen, 4)
91 self.assertEqual(arp.op, arp_opts["is-at"])
92 self.assertEqual(arp.hwsrc, smac)
93 self.assertEqual(arp.hwdst, dmac)
94 self.assertEqual(arp.psrc, sip)
95 self.assertEqual(arp.pdst, dip)
96
Matthew Smithcb9ab472017-05-16 21:35:56 -050097 def verify_arp_vrrp_resp(self, rx, smac, dmac, sip, dip):
98 ether = rx[Ether]
99 self.assertEqual(ether.dst, dmac)
100 self.assertEqual(ether.src, smac)
101
102 arp = rx[ARP]
103 self.assertEqual(arp.hwtype, 1)
104 self.assertEqual(arp.ptype, 0x800)
105 self.assertEqual(arp.hwlen, 6)
106 self.assertEqual(arp.plen, 4)
107 self.assertEqual(arp.op, arp_opts["is-at"])
108 self.assertNotEqual(arp.hwsrc, smac)
109 self.assertTrue("00:00:5e:00:01" in arp.hwsrc or
110 "00:00:5E:00:01" in arp.hwsrc)
111 self.assertEqual(arp.hwdst, dmac)
112 self.assertEqual(arp.psrc, sip)
113 self.assertEqual(arp.pdst, dip)
114
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800115 def verify_ip(self, rx, smac, dmac, sip, dip):
116 ether = rx[Ether]
117 self.assertEqual(ether.dst, dmac)
118 self.assertEqual(ether.src, smac)
119
120 ip = rx[IP]
121 self.assertEqual(ip.src, sip)
122 self.assertEqual(ip.dst, dip)
123
Neale Ranns37be7362017-02-21 17:30:26 -0800124 def verify_ip_o_mpls(self, rx, smac, dmac, label, sip, dip):
125 ether = rx[Ether]
126 self.assertEqual(ether.dst, dmac)
127 self.assertEqual(ether.src, smac)
128
129 mpls = rx[MPLS]
130 self.assertTrue(mpls.label, label)
131
132 ip = rx[IP]
133 self.assertEqual(ip.src, sip)
134 self.assertEqual(ip.dst, dip)
135
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800136 def test_arp(self):
137 """ ARP """
138
139 #
140 # Generate some hosts on the LAN
141 #
Neale Rannsca193612017-06-14 06:50:08 -0700142 self.pg1.generate_remote_hosts(11)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800143
144 #
145 # Send IP traffic to one of these unresolved hosts.
146 # expect the generation of an ARP request
147 #
148 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
149 IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[1].ip4) /
150 UDP(sport=1234, dport=1234) /
151 Raw())
152
153 self.pg0.add_stream(p)
154 self.pg_enable_capture(self.pg_interfaces)
155 self.pg_start()
156
157 rx = self.pg1.get_capture(1)
158
159 self.verify_arp_req(rx[0],
160 self.pg1.local_mac,
161 self.pg1.local_ip4,
162 self.pg1._remote_hosts[1].ip4)
163
164 #
165 # And a dynamic ARP entry for host 1
166 #
167 dyn_arp = VppNeighbor(self,
168 self.pg1.sw_if_index,
169 self.pg1.remote_hosts[1].mac,
170 self.pg1.remote_hosts[1].ip4)
171 dyn_arp.add_vpp_config()
172
173 #
174 # now we expect IP traffic forwarded
175 #
176 dyn_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
177 IP(src=self.pg0.remote_ip4,
178 dst=self.pg1._remote_hosts[1].ip4) /
179 UDP(sport=1234, dport=1234) /
180 Raw())
181
182 self.pg0.add_stream(dyn_p)
183 self.pg_enable_capture(self.pg_interfaces)
184 self.pg_start()
185
186 rx = self.pg1.get_capture(1)
187
188 self.verify_ip(rx[0],
189 self.pg1.local_mac,
190 self.pg1.remote_hosts[1].mac,
191 self.pg0.remote_ip4,
192 self.pg1._remote_hosts[1].ip4)
193
194 #
195 # And a Static ARP entry for host 2
196 #
197 static_arp = VppNeighbor(self,
198 self.pg1.sw_if_index,
199 self.pg1.remote_hosts[2].mac,
200 self.pg1.remote_hosts[2].ip4,
201 is_static=1)
202 static_arp.add_vpp_config()
203
204 static_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
205 IP(src=self.pg0.remote_ip4,
206 dst=self.pg1._remote_hosts[2].ip4) /
207 UDP(sport=1234, dport=1234) /
208 Raw())
209
210 self.pg0.add_stream(static_p)
211 self.pg_enable_capture(self.pg_interfaces)
212 self.pg_start()
213
214 rx = self.pg1.get_capture(1)
215
216 self.verify_ip(rx[0],
217 self.pg1.local_mac,
218 self.pg1.remote_hosts[2].mac,
219 self.pg0.remote_ip4,
220 self.pg1._remote_hosts[2].ip4)
221
222 #
223 # flap the link. dynamic ARPs get flush, statics don't
224 #
225 self.pg1.admin_down()
226 self.pg1.admin_up()
227
228 self.pg0.add_stream(static_p)
229 self.pg_enable_capture(self.pg_interfaces)
230 self.pg_start()
231 rx = self.pg1.get_capture(1)
232
233 self.verify_ip(rx[0],
234 self.pg1.local_mac,
235 self.pg1.remote_hosts[2].mac,
236 self.pg0.remote_ip4,
237 self.pg1._remote_hosts[2].ip4)
238
239 self.pg0.add_stream(dyn_p)
240 self.pg_enable_capture(self.pg_interfaces)
241 self.pg_start()
242
243 rx = self.pg1.get_capture(1)
244 self.verify_arp_req(rx[0],
245 self.pg1.local_mac,
246 self.pg1.local_ip4,
247 self.pg1._remote_hosts[1].ip4)
248
249 #
250 # Send an ARP request from one of the so-far unlearned remote hosts
251 #
252 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
253 src=self.pg1._remote_hosts[3].mac) /
254 ARP(op="who-has",
255 hwsrc=self.pg1._remote_hosts[3].mac,
256 pdst=self.pg1.local_ip4,
257 psrc=self.pg1._remote_hosts[3].ip4))
258
259 self.pg1.add_stream(p)
260 self.pg_enable_capture(self.pg_interfaces)
261 self.pg_start()
262
263 rx = self.pg1.get_capture(1)
264 self.verify_arp_resp(rx[0],
265 self.pg1.local_mac,
266 self.pg1._remote_hosts[3].mac,
267 self.pg1.local_ip4,
268 self.pg1._remote_hosts[3].ip4)
269
270 #
271 # VPP should have learned the mapping for the remote host
272 #
273 self.assertTrue(find_nbr(self,
274 self.pg1.sw_if_index,
275 self.pg1._remote_hosts[3].ip4))
Neale Ranns4b919a52017-03-11 05:55:21 -0800276 #
277 # Fire in an ARP request before the interface becomes IP enabled
278 #
279 self.pg2.generate_remote_hosts(4)
280
281 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
282 ARP(op="who-has",
283 hwsrc=self.pg2.remote_mac,
284 pdst=self.pg1.local_ip4,
285 psrc=self.pg2.remote_hosts[3].ip4))
Neale Ranns30d0fd42017-05-30 07:30:04 -0700286 pt = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
287 Dot1Q(vlan=0) /
288 ARP(op="who-has",
289 hwsrc=self.pg2.remote_mac,
290 pdst=self.pg1.local_ip4,
291 psrc=self.pg2.remote_hosts[3].ip4))
Neale Ranns4b919a52017-03-11 05:55:21 -0800292 self.send_and_assert_no_replies(self.pg2, p,
293 "interface not IP enabled")
294
295 #
296 # Make pg2 un-numbered to pg1
297 #
298 self.pg2.set_unnumbered(self.pg1.sw_if_index)
299
Neale Ranns404d88e2018-08-08 06:37:33 -0700300 unnum = self.vapi.ip_unnumbered_dump()
301 self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
302 self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)
303
Neale Ranns4b919a52017-03-11 05:55:21 -0800304 #
305 # We should respond to ARP requests for the unnumbered to address
306 # once an attached route to the source is known
307 #
308 self.send_and_assert_no_replies(
309 self.pg2, p,
310 "ARP req for unnumbered address - no source")
311
312 attached_host = VppIpRoute(self, self.pg2.remote_hosts[3].ip4, 32,
313 [VppRoutePath("0.0.0.0",
314 self.pg2.sw_if_index)])
315 attached_host.add_vpp_config()
316
317 self.pg2.add_stream(p)
318 self.pg_enable_capture(self.pg_interfaces)
319 self.pg_start()
320
321 rx = self.pg2.get_capture(1)
322 self.verify_arp_resp(rx[0],
323 self.pg2.local_mac,
324 self.pg2.remote_mac,
325 self.pg1.local_ip4,
326 self.pg2.remote_hosts[3].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800327
Neale Ranns30d0fd42017-05-30 07:30:04 -0700328 self.pg2.add_stream(pt)
329 self.pg_enable_capture(self.pg_interfaces)
330 self.pg_start()
331
332 rx = self.pg2.get_capture(1)
333 self.verify_arp_resp(rx[0],
334 self.pg2.local_mac,
335 self.pg2.remote_mac,
336 self.pg1.local_ip4,
337 self.pg2.remote_hosts[3].ip4)
338
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800339 #
Neale Ranns3983ac22017-03-10 11:53:27 -0800340 # A neighbor entry that has no associated FIB-entry
341 #
342 arp_no_fib = VppNeighbor(self,
343 self.pg1.sw_if_index,
344 self.pg1.remote_hosts[4].mac,
345 self.pg1.remote_hosts[4].ip4,
346 is_no_fib_entry=1)
347 arp_no_fib.add_vpp_config()
348
349 #
350 # check we have the neighbor, but no route
351 #
352 self.assertTrue(find_nbr(self,
353 self.pg1.sw_if_index,
354 self.pg1._remote_hosts[4].ip4))
355 self.assertFalse(find_route(self,
356 self.pg1._remote_hosts[4].ip4,
357 32))
358 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800359 # pg2 is unnumbered to pg1, so we can form adjacencies out of pg2
360 # from within pg1's subnet
Neale Ranns3983ac22017-03-10 11:53:27 -0800361 #
362 arp_unnum = VppNeighbor(self,
363 self.pg2.sw_if_index,
364 self.pg1.remote_hosts[5].mac,
365 self.pg1.remote_hosts[5].ip4)
366 arp_unnum.add_vpp_config()
367
368 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
369 IP(src=self.pg0.remote_ip4,
370 dst=self.pg1._remote_hosts[5].ip4) /
371 UDP(sport=1234, dport=1234) /
372 Raw())
373
374 self.pg0.add_stream(p)
375 self.pg_enable_capture(self.pg_interfaces)
376 self.pg_start()
377
378 rx = self.pg2.get_capture(1)
379
380 self.verify_ip(rx[0],
381 self.pg2.local_mac,
382 self.pg1.remote_hosts[5].mac,
383 self.pg0.remote_ip4,
384 self.pg1._remote_hosts[5].ip4)
385
386 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800387 # ARP requests from hosts in pg1's subnet sent on pg2 are replied to
388 # with the unnumbered interface's address as the source
389 #
390 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
391 ARP(op="who-has",
392 hwsrc=self.pg2.remote_mac,
393 pdst=self.pg1.local_ip4,
394 psrc=self.pg1.remote_hosts[6].ip4))
395
396 self.pg2.add_stream(p)
397 self.pg_enable_capture(self.pg_interfaces)
398 self.pg_start()
399
400 rx = self.pg2.get_capture(1)
401 self.verify_arp_resp(rx[0],
402 self.pg2.local_mac,
403 self.pg2.remote_mac,
404 self.pg1.local_ip4,
405 self.pg1.remote_hosts[6].ip4)
406
407 #
408 # An attached host route out of pg2 for an undiscovered hosts generates
409 # an ARP request with the unnumbered address as the source
410 #
411 att_unnum = VppIpRoute(self, self.pg1.remote_hosts[7].ip4, 32,
412 [VppRoutePath("0.0.0.0",
413 self.pg2.sw_if_index)])
414 att_unnum.add_vpp_config()
415
416 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
417 IP(src=self.pg0.remote_ip4,
418 dst=self.pg1._remote_hosts[7].ip4) /
419 UDP(sport=1234, dport=1234) /
420 Raw())
421
422 self.pg0.add_stream(p)
423 self.pg_enable_capture(self.pg_interfaces)
424 self.pg_start()
425
426 rx = self.pg2.get_capture(1)
427
428 self.verify_arp_req(rx[0],
429 self.pg2.local_mac,
430 self.pg1.local_ip4,
431 self.pg1._remote_hosts[7].ip4)
432
433 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
434 ARP(op="who-has",
435 hwsrc=self.pg2.remote_mac,
436 pdst=self.pg1.local_ip4,
437 psrc=self.pg1.remote_hosts[7].ip4))
438
439 self.pg2.add_stream(p)
440 self.pg_enable_capture(self.pg_interfaces)
441 self.pg_start()
442
443 rx = self.pg2.get_capture(1)
444 self.verify_arp_resp(rx[0],
445 self.pg2.local_mac,
446 self.pg2.remote_mac,
447 self.pg1.local_ip4,
448 self.pg1.remote_hosts[7].ip4)
449
450 #
451 # An attached host route as yet unresolved out of pg2 for an
452 # undiscovered host, an ARP requests begets a response.
453 #
454 att_unnum1 = VppIpRoute(self, self.pg1.remote_hosts[8].ip4, 32,
455 [VppRoutePath("0.0.0.0",
456 self.pg2.sw_if_index)])
457 att_unnum1.add_vpp_config()
458
459 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
460 ARP(op="who-has",
461 hwsrc=self.pg2.remote_mac,
462 pdst=self.pg1.local_ip4,
463 psrc=self.pg1.remote_hosts[8].ip4))
464
465 self.pg2.add_stream(p)
466 self.pg_enable_capture(self.pg_interfaces)
467 self.pg_start()
468
469 rx = self.pg2.get_capture(1)
470 self.verify_arp_resp(rx[0],
471 self.pg2.local_mac,
472 self.pg2.remote_mac,
473 self.pg1.local_ip4,
474 self.pg1.remote_hosts[8].ip4)
475
476 #
Neale Ranns30d0fd42017-05-30 07:30:04 -0700477 # Send an ARP request from one of the so-far unlearned remote hosts
478 # with a VLAN0 tag
479 #
480 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
481 src=self.pg1._remote_hosts[9].mac) /
482 Dot1Q(vlan=0) /
483 ARP(op="who-has",
484 hwsrc=self.pg1._remote_hosts[9].mac,
485 pdst=self.pg1.local_ip4,
486 psrc=self.pg1._remote_hosts[9].ip4))
487
488 self.pg1.add_stream(p)
489 self.pg_enable_capture(self.pg_interfaces)
490 self.pg_start()
491
492 rx = self.pg1.get_capture(1)
493 self.verify_arp_resp(rx[0],
494 self.pg1.local_mac,
495 self.pg1._remote_hosts[9].mac,
496 self.pg1.local_ip4,
497 self.pg1._remote_hosts[9].ip4)
498
499 #
Neale Rannsca193612017-06-14 06:50:08 -0700500 # Add a hierachy of routes for a host in the sub-net.
501 # Should still get an ARP resp since the cover is attached
502 #
503 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_mac) /
504 ARP(op="who-has",
505 hwsrc=self.pg1.remote_mac,
506 pdst=self.pg1.local_ip4,
507 psrc=self.pg1.remote_hosts[10].ip4))
508
509 r1 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 30,
510 [VppRoutePath(self.pg1.remote_hosts[10].ip4,
511 self.pg1.sw_if_index)])
512 r1.add_vpp_config()
513
514 self.pg1.add_stream(p)
515 self.pg_enable_capture(self.pg_interfaces)
516 self.pg_start()
517 rx = self.pg1.get_capture(1)
518 self.verify_arp_resp(rx[0],
519 self.pg1.local_mac,
520 self.pg1.remote_mac,
521 self.pg1.local_ip4,
522 self.pg1.remote_hosts[10].ip4)
523
524 r2 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 32,
525 [VppRoutePath(self.pg1.remote_hosts[10].ip4,
526 self.pg1.sw_if_index)])
527 r2.add_vpp_config()
528
529 self.pg1.add_stream(p)
530 self.pg_enable_capture(self.pg_interfaces)
531 self.pg_start()
532 rx = self.pg1.get_capture(1)
533 self.verify_arp_resp(rx[0],
534 self.pg1.local_mac,
535 self.pg1.remote_mac,
536 self.pg1.local_ip4,
537 self.pg1.remote_hosts[10].ip4)
538
539 #
540 # add an ARP entry that's not on the sub-net and so whose
541 # adj-fib fails the refinement check. then send an ARP request
542 # from that source
543 #
544 a1 = VppNeighbor(self,
545 self.pg0.sw_if_index,
546 self.pg0.remote_mac,
547 "100.100.100.50")
548 a1.add_vpp_config()
549
550 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
551 ARP(op="who-has",
552 hwsrc=self.pg0.remote_mac,
553 psrc="100.100.100.50",
554 pdst=self.pg0.remote_ip4))
555 self.send_and_assert_no_replies(self.pg0, p,
556 "ARP req for from failed adj-fib")
557
558 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800559 # ERROR Cases
560 # 1 - don't respond to ARP request for address not within the
561 # interface's sub-net
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700562 # 1b - nor within the unnumbered subnet
563 # 1c - nor within the subnet of a different interface
564 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800565 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
566 ARP(op="who-has",
567 hwsrc=self.pg0.remote_mac,
568 pdst="10.10.10.3",
569 psrc=self.pg0.remote_ip4))
570 self.send_and_assert_no_replies(self.pg0, p,
571 "ARP req for non-local destination")
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700572 self.assertFalse(find_nbr(self,
573 self.pg0.sw_if_index,
574 "10.10.10.3"))
575
Neale Ranns4b919a52017-03-11 05:55:21 -0800576 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
577 ARP(op="who-has",
578 hwsrc=self.pg2.remote_mac,
579 pdst="10.10.10.3",
580 psrc=self.pg1.remote_hosts[7].ip4))
581 self.send_and_assert_no_replies(
582 self.pg0, p,
583 "ARP req for non-local destination - unnum")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800584
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700585 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
586 ARP(op="who-has",
587 hwsrc=self.pg0.remote_mac,
588 pdst=self.pg1.local_ip4,
589 psrc=self.pg1.remote_ip4))
590 self.send_and_assert_no_replies(self.pg0, p,
591 "ARP req diff sub-net")
592 self.assertFalse(find_nbr(self,
593 self.pg0.sw_if_index,
594 self.pg1.remote_ip4))
595
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800596 #
597 # 2 - don't respond to ARP request from an address not within the
598 # interface's sub-net
Neale Rannsca193612017-06-14 06:50:08 -0700599 # 2b - to a prxied address
600 # 2c - not within a differents interface's sub-net
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800601 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
602 ARP(op="who-has",
603 hwsrc=self.pg0.remote_mac,
604 psrc="10.10.10.3",
605 pdst=self.pg0.local_ip4))
606 self.send_and_assert_no_replies(self.pg0, p,
607 "ARP req for non-local source")
Neale Ranns4b919a52017-03-11 05:55:21 -0800608 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
609 ARP(op="who-has",
610 hwsrc=self.pg2.remote_mac,
611 psrc="10.10.10.3",
612 pdst=self.pg0.local_ip4))
613 self.send_and_assert_no_replies(
614 self.pg0, p,
615 "ARP req for non-local source - unnum")
Neale Rannsca193612017-06-14 06:50:08 -0700616 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
617 ARP(op="who-has",
618 hwsrc=self.pg0.remote_mac,
619 psrc=self.pg1.remote_ip4,
620 pdst=self.pg0.local_ip4))
621 self.send_and_assert_no_replies(self.pg0, p,
622 "ARP req for non-local source 2c")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800623
624 #
625 # 3 - don't respond to ARP request from an address that belongs to
626 # the router
627 #
628 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
629 ARP(op="who-has",
630 hwsrc=self.pg0.remote_mac,
631 psrc=self.pg0.local_ip4,
632 pdst=self.pg0.local_ip4))
633 self.send_and_assert_no_replies(self.pg0, p,
634 "ARP req for non-local source")
635
636 #
637 # 4 - don't respond to ARP requests that has mac source different
638 # from ARP request HW source
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800639 #
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 #
zhaoqinglingb4c42cd2017-12-23 15:20:59 +0800649 # 5 - don't respond to ARP requests for address within the
650 # interface's sub-net but not the interface's address
651 #
652 self.pg0.generate_remote_hosts(2)
653 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
654 ARP(op="who-has",
655 hwsrc=self.pg0.remote_mac,
656 psrc=self.pg0.remote_hosts[0].ip4,
657 pdst=self.pg0.remote_hosts[1].ip4))
658 self.send_and_assert_no_replies(self.pg0, p,
659 "ARP req for non-local destination")
660
661 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800662 # cleanup
663 #
664 dyn_arp.remove_vpp_config()
665 static_arp.remove_vpp_config()
Neale Ranns3983ac22017-03-10 11:53:27 -0800666 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800667
Neale Ranns4b919a52017-03-11 05:55:21 -0800668 # need this to flush the adj-fibs
669 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
670 self.pg2.admin_down()
Neale Rannsca193612017-06-14 06:50:08 -0700671 self.pg1.admin_down()
Neale Ranns4b919a52017-03-11 05:55:21 -0800672
Neale Ranns24b170a2017-08-15 05:33:11 -0700673 def test_proxy_mirror_arp(self):
674 """ Interface Mirror Proxy ARP """
675
676 #
677 # When VPP has an interface whose address is also applied to a TAP
678 # interface on the host, then VPP's TAP interface will be unnumbered
679 # to the 'real' interface and do proxy ARP from the host.
680 # the curious aspect of this setup is that ARP requests from the host
681 # will come from the VPP's own address.
682 #
683 self.pg0.generate_remote_hosts(2)
684
685 arp_req_from_me = (Ether(src=self.pg2.remote_mac,
686 dst="ff:ff:ff:ff:ff:ff") /
687 ARP(op="who-has",
688 hwsrc=self.pg2.remote_mac,
689 pdst=self.pg0.remote_hosts[1].ip4,
690 psrc=self.pg0.local_ip4))
691
692 #
693 # Configure Proxy ARP for the subnet on PG0addresses on pg0
694 #
695 self.vapi.proxy_arp_add_del(self.pg0._local_ip4n_subnet,
696 self.pg0._local_ip4n_bcast)
697
698 # Make pg2 un-numbered to pg0
699 #
700 self.pg2.set_unnumbered(self.pg0.sw_if_index)
701
702 #
703 # Enable pg2 for proxy ARP
704 #
705 self.pg2.set_proxy_arp()
706
707 #
708 # Send the ARP request with an originating address that
709 # is VPP's own address
710 #
711 self.pg2.add_stream(arp_req_from_me)
712 self.pg_enable_capture(self.pg_interfaces)
713 self.pg_start()
714
715 rx = self.pg2.get_capture(1)
716 self.verify_arp_resp(rx[0],
717 self.pg2.local_mac,
718 self.pg2.remote_mac,
719 self.pg0.remote_hosts[1].ip4,
720 self.pg0.local_ip4)
721
722 #
723 # validate we have not learned an ARP entry as a result of this
724 #
725 self.assertFalse(find_nbr(self,
726 self.pg2.sw_if_index,
727 self.pg0.local_ip4))
728
729 #
730 # cleanup
731 #
732 self.pg2.set_proxy_arp(0)
733 self.vapi.proxy_arp_add_del(self.pg0._local_ip4n_subnet,
734 self.pg0._local_ip4n_bcast,
735 is_add=0)
736
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800737 def test_proxy_arp(self):
738 """ Proxy ARP """
739
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700740 self.pg1.generate_remote_hosts(2)
741
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800742 #
743 # Proxy ARP rewquest packets for each interface
744 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800745 arp_req_pg0 = (Ether(src=self.pg0.remote_mac,
746 dst="ff:ff:ff:ff:ff:ff") /
747 ARP(op="who-has",
748 hwsrc=self.pg0.remote_mac,
749 pdst="10.10.10.3",
750 psrc=self.pg0.remote_ip4))
Neale Ranns30d0fd42017-05-30 07:30:04 -0700751 arp_req_pg0_tagged = (Ether(src=self.pg0.remote_mac,
752 dst="ff:ff:ff:ff:ff:ff") /
753 Dot1Q(vlan=0) /
754 ARP(op="who-has",
755 hwsrc=self.pg0.remote_mac,
756 pdst="10.10.10.3",
757 psrc=self.pg0.remote_ip4))
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800758 arp_req_pg1 = (Ether(src=self.pg1.remote_mac,
759 dst="ff:ff:ff:ff:ff:ff") /
760 ARP(op="who-has",
761 hwsrc=self.pg1.remote_mac,
762 pdst="10.10.10.3",
763 psrc=self.pg1.remote_ip4))
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700764 arp_req_pg2 = (Ether(src=self.pg2.remote_mac,
765 dst="ff:ff:ff:ff:ff:ff") /
766 ARP(op="who-has",
767 hwsrc=self.pg2.remote_mac,
768 pdst="10.10.10.3",
769 psrc=self.pg1.remote_hosts[1].ip4))
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800770 arp_req_pg3 = (Ether(src=self.pg3.remote_mac,
771 dst="ff:ff:ff:ff:ff:ff") /
772 ARP(op="who-has",
773 hwsrc=self.pg3.remote_mac,
774 pdst="10.10.10.3",
775 psrc=self.pg3.remote_ip4))
776
777 #
778 # Configure Proxy ARP for 10.10.10.0 -> 10.10.10.124
779 #
780 self.vapi.proxy_arp_add_del(inet_pton(AF_INET, "10.10.10.2"),
781 inet_pton(AF_INET, "10.10.10.124"))
782
783 #
784 # No responses are sent when the interfaces are not enabled for proxy
785 # ARP
786 #
787 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
788 "ARP req from unconfigured interface")
789 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
790 "ARP req from unconfigured interface")
791
792 #
793 # Make pg2 un-numbered to pg1
794 # still won't reply.
795 #
796 self.pg2.set_unnumbered(self.pg1.sw_if_index)
797
798 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
799 "ARP req from unnumbered interface")
800
801 #
802 # Enable each interface to reply to proxy ARPs
803 #
804 for i in self.pg_interfaces:
805 i.set_proxy_arp()
806
807 #
808 # Now each of the interfaces should reply to a request to a proxied
809 # address
810 #
811 self.pg0.add_stream(arp_req_pg0)
812 self.pg_enable_capture(self.pg_interfaces)
813 self.pg_start()
814
815 rx = self.pg0.get_capture(1)
816 self.verify_arp_resp(rx[0],
817 self.pg0.local_mac,
818 self.pg0.remote_mac,
819 "10.10.10.3",
820 self.pg0.remote_ip4)
821
Neale Ranns30d0fd42017-05-30 07:30:04 -0700822 self.pg0.add_stream(arp_req_pg0_tagged)
823 self.pg_enable_capture(self.pg_interfaces)
824 self.pg_start()
825
826 rx = self.pg0.get_capture(1)
827 self.verify_arp_resp(rx[0],
828 self.pg0.local_mac,
829 self.pg0.remote_mac,
830 "10.10.10.3",
831 self.pg0.remote_ip4)
832
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800833 self.pg1.add_stream(arp_req_pg1)
834 self.pg_enable_capture(self.pg_interfaces)
835 self.pg_start()
836
837 rx = self.pg1.get_capture(1)
838 self.verify_arp_resp(rx[0],
839 self.pg1.local_mac,
840 self.pg1.remote_mac,
841 "10.10.10.3",
842 self.pg1.remote_ip4)
843
844 self.pg2.add_stream(arp_req_pg2)
845 self.pg_enable_capture(self.pg_interfaces)
846 self.pg_start()
847
848 rx = self.pg2.get_capture(1)
849 self.verify_arp_resp(rx[0],
850 self.pg2.local_mac,
851 self.pg2.remote_mac,
852 "10.10.10.3",
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700853 self.pg1.remote_hosts[1].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800854
855 #
856 # A request for an address out of the configured range
857 #
858 arp_req_pg1_hi = (Ether(src=self.pg1.remote_mac,
859 dst="ff:ff:ff:ff:ff:ff") /
860 ARP(op="who-has",
861 hwsrc=self.pg1.remote_mac,
862 pdst="10.10.10.125",
863 psrc=self.pg1.remote_ip4))
864 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_hi,
865 "ARP req out of range HI")
866 arp_req_pg1_low = (Ether(src=self.pg1.remote_mac,
867 dst="ff:ff:ff:ff:ff:ff") /
868 ARP(op="who-has",
869 hwsrc=self.pg1.remote_mac,
870 pdst="10.10.10.1",
871 psrc=self.pg1.remote_ip4))
872 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_low,
873 "ARP req out of range Low")
874
875 #
876 # Request for an address in the proxy range but from an interface
877 # in a different VRF
878 #
879 self.send_and_assert_no_replies(self.pg3, arp_req_pg3,
880 "ARP req from different VRF")
881
882 #
883 # Disable Each interface for proxy ARP
884 # - expect none to respond
885 #
886 for i in self.pg_interfaces:
887 i.set_proxy_arp(0)
888
889 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
890 "ARP req from disable")
891 self.send_and_assert_no_replies(self.pg1, arp_req_pg1,
892 "ARP req from disable")
893 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
894 "ARP req from disable")
Neale Ranns37be7362017-02-21 17:30:26 -0800895
896 #
897 # clean up on interface 2
898 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800899 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns37be7362017-02-21 17:30:26 -0800900
901 def test_mpls(self):
902 """ MPLS """
903
904 #
905 # Interface 2 does not yet have ip4 config
906 #
907 self.pg2.config_ip4()
908 self.pg2.generate_remote_hosts(2)
909
910 #
911 # Add a reoute with out going label via an ARP unresolved next-hop
912 #
913 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
914 [VppRoutePath(self.pg2.remote_hosts[1].ip4,
915 self.pg2.sw_if_index,
916 labels=[55])])
917 ip_10_0_0_1.add_vpp_config()
918
919 #
920 # packets should generate an ARP request
921 #
922 p = (Ether(src=self.pg0.remote_mac,
923 dst=self.pg0.local_mac) /
924 IP(src=self.pg0.remote_ip4, dst="10.0.0.1") /
925 UDP(sport=1234, dport=1234) /
926 Raw('\xa5' * 100))
927
928 self.pg0.add_stream(p)
929 self.pg_enable_capture(self.pg_interfaces)
930 self.pg_start()
931
932 rx = self.pg2.get_capture(1)
933 self.verify_arp_req(rx[0],
934 self.pg2.local_mac,
935 self.pg2.local_ip4,
936 self.pg2._remote_hosts[1].ip4)
937
938 #
939 # now resolve the neighbours
940 #
941 self.pg2.configure_ipv4_neighbors()
942
943 #
944 # Now packet should be properly MPLS encapped.
945 # This verifies that MPLS link-type adjacencies are completed
946 # when the ARP entry resolves
947 #
948 self.pg0.add_stream(p)
949 self.pg_enable_capture(self.pg_interfaces)
950 self.pg_start()
951
952 rx = self.pg2.get_capture(1)
953 self.verify_ip_o_mpls(rx[0],
954 self.pg2.local_mac,
955 self.pg2.remote_hosts[1].mac,
956 55,
957 self.pg0.remote_ip4,
958 "10.0.0.1")
Neale Ranns4b919a52017-03-11 05:55:21 -0800959 self.pg2.unconfig_ip4()
Neale Ranns37be7362017-02-21 17:30:26 -0800960
Matthew Smithcb9ab472017-05-16 21:35:56 -0500961 def test_arp_vrrp(self):
962 """ ARP reply with VRRP virtual src hw addr """
963
964 #
965 # IP packet destined for pg1 remote host arrives on pg0 resulting
966 # in an ARP request for the address of the remote host on pg1
967 #
968 p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
969 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
970 UDP(sport=1234, dport=1234) /
971 Raw())
972
973 self.pg0.add_stream(p0)
974 self.pg_enable_capture(self.pg_interfaces)
975 self.pg_start()
976
977 rx1 = self.pg1.get_capture(1)
978
979 self.verify_arp_req(rx1[0],
980 self.pg1.local_mac,
981 self.pg1.local_ip4,
982 self.pg1.remote_ip4)
983
984 #
985 # ARP reply for address of pg1 remote host arrives on pg1 with
986 # the hw src addr set to a value in the VRRP IPv4 range of
987 # MAC addresses
988 #
989 p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
990 ARP(op="is-at", hwdst=self.pg1.local_mac,
991 hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
992 psrc=self.pg1.remote_ip4))
993
994 self.pg1.add_stream(p1)
995 self.pg_enable_capture(self.pg_interfaces)
996 self.pg_start()
997
998 #
999 # IP packet destined for pg1 remote host arrives on pg0 again.
1000 # VPP should have an ARP entry for that address now and the packet
1001 # should be sent out pg1.
1002 #
1003 self.pg0.add_stream(p0)
1004 self.pg_enable_capture(self.pg_interfaces)
1005 self.pg_start()
1006
1007 rx1 = self.pg1.get_capture(1)
1008
1009 self.verify_ip(rx1[0],
1010 self.pg1.local_mac,
1011 "00:00:5e:00:01:09",
1012 self.pg0.remote_ip4,
1013 self.pg1.remote_ip4)
1014
1015 self.pg1.admin_down()
1016 self.pg1.admin_up()
1017
Neale Rannsdcd6d622017-05-26 02:59:16 -07001018 def test_arp_duplicates(self):
1019 """ ARP Duplicates"""
1020
1021 #
1022 # Generate some hosts on the LAN
1023 #
1024 self.pg1.generate_remote_hosts(3)
1025
1026 #
1027 # Add host 1 on pg1 and pg2
1028 #
1029 arp_pg1 = VppNeighbor(self,
1030 self.pg1.sw_if_index,
1031 self.pg1.remote_hosts[1].mac,
1032 self.pg1.remote_hosts[1].ip4)
1033 arp_pg1.add_vpp_config()
1034 arp_pg2 = VppNeighbor(self,
1035 self.pg2.sw_if_index,
1036 self.pg2.remote_mac,
1037 self.pg1.remote_hosts[1].ip4)
1038 arp_pg2.add_vpp_config()
1039
1040 #
1041 # IP packet destined for pg1 remote host arrives on pg1 again.
1042 #
1043 p = (Ether(dst=self.pg0.local_mac,
1044 src=self.pg0.remote_mac) /
1045 IP(src=self.pg0.remote_ip4,
1046 dst=self.pg1.remote_hosts[1].ip4) /
1047 UDP(sport=1234, dport=1234) /
1048 Raw())
1049
1050 self.pg0.add_stream(p)
1051 self.pg_enable_capture(self.pg_interfaces)
1052 self.pg_start()
1053
1054 rx1 = self.pg1.get_capture(1)
1055
1056 self.verify_ip(rx1[0],
1057 self.pg1.local_mac,
1058 self.pg1.remote_hosts[1].mac,
1059 self.pg0.remote_ip4,
1060 self.pg1.remote_hosts[1].ip4)
1061
1062 #
1063 # remove the duplicate on pg1
1064 # packet stream shoud generate ARPs out of pg1
1065 #
1066 arp_pg1.remove_vpp_config()
1067
1068 self.pg0.add_stream(p)
1069 self.pg_enable_capture(self.pg_interfaces)
1070 self.pg_start()
1071
1072 rx1 = self.pg1.get_capture(1)
1073
1074 self.verify_arp_req(rx1[0],
1075 self.pg1.local_mac,
1076 self.pg1.local_ip4,
1077 self.pg1.remote_hosts[1].ip4)
1078
1079 #
1080 # Add it back
1081 #
1082 arp_pg1.add_vpp_config()
1083
1084 self.pg0.add_stream(p)
1085 self.pg_enable_capture(self.pg_interfaces)
1086 self.pg_start()
1087
1088 rx1 = self.pg1.get_capture(1)
1089
1090 self.verify_ip(rx1[0],
1091 self.pg1.local_mac,
1092 self.pg1.remote_hosts[1].mac,
1093 self.pg0.remote_ip4,
1094 self.pg1.remote_hosts[1].ip4)
1095
Neale Ranns15002542017-09-10 04:39:11 -07001096 def test_arp_static(self):
1097 """ ARP Static"""
1098 self.pg2.generate_remote_hosts(3)
1099
1100 #
1101 # Add a static ARP entry
1102 #
1103 static_arp = VppNeighbor(self,
1104 self.pg2.sw_if_index,
1105 self.pg2.remote_hosts[1].mac,
1106 self.pg2.remote_hosts[1].ip4,
1107 is_static=1)
1108 static_arp.add_vpp_config()
1109
1110 #
1111 # Add the connected prefix to the interface
1112 #
1113 self.pg2.config_ip4()
1114
1115 #
1116 # We should now find the adj-fib
1117 #
1118 self.assertTrue(find_nbr(self,
1119 self.pg2.sw_if_index,
1120 self.pg2.remote_hosts[1].ip4,
1121 is_static=1))
1122 self.assertTrue(find_route(self,
1123 self.pg2.remote_hosts[1].ip4,
1124 32))
1125
1126 #
1127 # remove the connected
1128 #
1129 self.pg2.unconfig_ip4()
1130
1131 #
1132 # put the interface into table 1
1133 #
1134 self.pg2.set_table_ip4(1)
1135
1136 #
1137 # configure the same connected and expect to find the
1138 # adj fib in the new table
1139 #
1140 self.pg2.config_ip4()
1141 self.assertTrue(find_route(self,
1142 self.pg2.remote_hosts[1].ip4,
1143 32,
1144 table_id=1))
1145
1146 #
1147 # clean-up
1148 #
1149 self.pg2.unconfig_ip4()
1150 self.pg2.set_table_ip4(0)
1151
Neale Rannsc819fc62018-02-16 02:44:05 -08001152 def test_arp_incomplete(self):
1153 """ ARP Incomplete"""
1154 self.pg1.generate_remote_hosts(3)
1155
1156 p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1157 IP(src=self.pg0.remote_ip4,
1158 dst=self.pg1.remote_hosts[1].ip4) /
1159 UDP(sport=1234, dport=1234) /
1160 Raw())
1161 p1 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1162 IP(src=self.pg0.remote_ip4,
1163 dst=self.pg1.remote_hosts[2].ip4) /
1164 UDP(sport=1234, dport=1234) /
1165 Raw())
1166
1167 #
1168 # a packet to an unresolved destination generates an ARP request
1169 #
1170 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1171 self.verify_arp_req(rx[0],
1172 self.pg1.local_mac,
1173 self.pg1.local_ip4,
1174 self.pg1._remote_hosts[1].ip4)
1175
1176 #
1177 # add a neighbour for remote host 1
1178 #
1179 static_arp = VppNeighbor(self,
1180 self.pg1.sw_if_index,
1181 self.pg1.remote_hosts[1].mac,
1182 self.pg1.remote_hosts[1].ip4,
1183 is_static=1)
1184 static_arp.add_vpp_config()
1185
1186 #
1187 # change the interface's MAC
1188 #
1189 mac = [chr(0x00), chr(0x00), chr(0x00),
1190 chr(0x33), chr(0x33), chr(0x33)]
1191 mac_string = ''.join(mac)
1192
1193 self.vapi.sw_interface_set_mac_address(self.pg1.sw_if_index,
1194 mac_string)
1195
1196 #
1197 # now ARP requests come from the new source mac
1198 #
1199 rx = self.send_and_expect(self.pg0, [p1], self.pg1)
1200 self.verify_arp_req(rx[0],
1201 "00:00:00:33:33:33",
1202 self.pg1.local_ip4,
1203 self.pg1._remote_hosts[2].ip4)
1204
1205 #
1206 # packets to the resolved host also have the new source mac
1207 #
1208 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1209 self.verify_ip(rx[0],
1210 "00:00:00:33:33:33",
1211 self.pg1.remote_hosts[1].mac,
1212 self.pg0.remote_ip4,
1213 self.pg1.remote_hosts[1].ip4)
1214
1215 #
1216 # set the mac address on the inteface that does not have a
1217 # configured subnet and thus no glean
1218 #
1219 self.vapi.sw_interface_set_mac_address(self.pg2.sw_if_index,
1220 mac_string)
1221
Neale Ranns59ae61e2018-06-07 18:09:49 -07001222 def test_garp(self):
1223 """ GARP """
1224
1225 #
1226 # Generate some hosts on the LAN
1227 #
1228 self.pg1.generate_remote_hosts(4)
1229
1230 #
1231 # And an ARP entry
1232 #
1233 arp = VppNeighbor(self,
1234 self.pg1.sw_if_index,
1235 self.pg1.remote_hosts[1].mac,
1236 self.pg1.remote_hosts[1].ip4)
1237 arp.add_vpp_config()
1238
1239 self.assertTrue(find_nbr(self,
1240 self.pg1.sw_if_index,
1241 self.pg1.remote_hosts[1].ip4,
1242 mac=self.pg1.remote_hosts[1].mac))
1243
1244 #
1245 # Send a GARP (request) to swap the host 1's address to that of host 2
1246 #
1247 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1248 src=self.pg1.remote_hosts[2].mac) /
1249 ARP(op="who-has",
1250 hwdst=self.pg1.local_mac,
1251 hwsrc=self.pg1.remote_hosts[2].mac,
1252 pdst=self.pg1.remote_hosts[1].ip4,
1253 psrc=self.pg1.remote_hosts[1].ip4))
1254
1255 self.pg1.add_stream(p1)
1256 self.pg_enable_capture(self.pg_interfaces)
1257 self.pg_start()
1258
1259 self.assertTrue(find_nbr(self,
1260 self.pg1.sw_if_index,
1261 self.pg1.remote_hosts[1].ip4,
1262 mac=self.pg1.remote_hosts[2].mac))
1263
1264 #
1265 # Send a GARP (reply) to swap the host 1's address to that of host 3
1266 #
1267 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1268 src=self.pg1.remote_hosts[3].mac) /
1269 ARP(op="is-at",
1270 hwdst=self.pg1.local_mac,
1271 hwsrc=self.pg1.remote_hosts[3].mac,
1272 pdst=self.pg1.remote_hosts[1].ip4,
1273 psrc=self.pg1.remote_hosts[1].ip4))
1274
1275 self.pg1.add_stream(p1)
1276 self.pg_enable_capture(self.pg_interfaces)
1277 self.pg_start()
1278
1279 self.assertTrue(find_nbr(self,
1280 self.pg1.sw_if_index,
1281 self.pg1.remote_hosts[1].ip4,
1282 mac=self.pg1.remote_hosts[3].mac))
1283
1284 #
1285 # GARPs (requets nor replies) for host we don't know yet
1286 # don't result in new neighbour entries
1287 #
1288 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1289 src=self.pg1.remote_hosts[3].mac) /
1290 ARP(op="who-has",
1291 hwdst=self.pg1.local_mac,
1292 hwsrc=self.pg1.remote_hosts[3].mac,
1293 pdst=self.pg1.remote_hosts[2].ip4,
1294 psrc=self.pg1.remote_hosts[2].ip4))
1295
1296 self.pg1.add_stream(p1)
1297 self.pg_enable_capture(self.pg_interfaces)
1298 self.pg_start()
1299
1300 self.assertFalse(find_nbr(self,
1301 self.pg1.sw_if_index,
1302 self.pg1.remote_hosts[2].ip4))
1303
1304 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1305 src=self.pg1.remote_hosts[3].mac) /
1306 ARP(op="is-at",
1307 hwdst=self.pg1.local_mac,
1308 hwsrc=self.pg1.remote_hosts[3].mac,
1309 pdst=self.pg1.remote_hosts[2].ip4,
1310 psrc=self.pg1.remote_hosts[2].ip4))
1311
1312 self.pg1.add_stream(p1)
1313 self.pg_enable_capture(self.pg_interfaces)
1314 self.pg_start()
1315
1316 self.assertFalse(find_nbr(self,
1317 self.pg1.sw_if_index,
1318 self.pg1.remote_hosts[2].ip4))
1319
Neale Rannsc8352bc2018-08-29 10:23:58 -07001320 def test_arp_incomplete(self):
Neale Ranns14260392018-09-28 05:00:57 -07001321 """ Incomplete Entries """
Neale Rannsc8352bc2018-08-29 10:23:58 -07001322
1323 #
1324 # ensure that we throttle the ARP requests
1325 #
1326 self.pg0.generate_remote_hosts(2)
1327
1328 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1329 [VppRoutePath(self.pg0.remote_hosts[1].ip4,
1330 self.pg0.sw_if_index,
1331 labels=[55])])
1332 ip_10_0_0_1.add_vpp_config()
1333
1334 p1 = (Ether(dst=self.pg1.local_mac,
1335 src=self.pg1.remote_mac) /
1336 IP(src=self.pg1.remote_ip4,
1337 dst="10.0.0.1") /
1338 UDP(sport=1234, dport=1234) /
1339 Raw())
1340
1341 self.pg1.add_stream(p1 * 257)
1342 self.pg_enable_capture(self.pg_interfaces)
1343 self.pg_start()
1344 rx = self.pg0._get_capture(1)
1345
1346 #
1347 # how many we get is going to be dependent on the time for packet
1348 # processing but it should be small
1349 #
1350 self.assertTrue(len(rx) < 64)
1351
Neale Rannsdcd6d622017-05-26 02:59:16 -07001352
Neale Ranns14260392018-09-28 05:00:57 -07001353class NeighborStatsTestCase(VppTestCase):
1354 """ ARP Test Case """
1355
1356 def setUp(self):
1357 super(NeighborStatsTestCase, self).setUp()
1358
1359 self.create_pg_interfaces(range(2))
1360
1361 # pg0 configured with ip4 and 6 addresses used for input
1362 # pg1 configured with ip4 and 6 addresses used for output
1363 # pg2 is unnumbered to pg0
1364 for i in self.pg_interfaces:
1365 i.admin_up()
1366 i.config_ip4()
1367 i.config_ip6()
1368 i.resolve_arp()
1369 i.resolve_ndp()
1370
1371 def tearDown(self):
1372 super(NeighborStatsTestCase, self).tearDown()
1373
1374 for i in self.pg_interfaces:
1375 i.unconfig_ip4()
1376 i.unconfig_ip6()
1377 i.admin_down()
1378
1379 def test_arp_stats(self):
1380 """ ARP Counters """
1381
1382 self.vapi.cli("adj counters enable")
1383 self.pg1.generate_remote_hosts(2)
1384
1385 arp1 = VppNeighbor(self,
1386 self.pg1.sw_if_index,
1387 self.pg1.remote_hosts[0].mac,
1388 self.pg1.remote_hosts[0].ip4)
1389 arp1.add_vpp_config()
1390 arp2 = VppNeighbor(self,
1391 self.pg1.sw_if_index,
1392 self.pg1.remote_hosts[1].mac,
1393 self.pg1.remote_hosts[1].ip4)
1394 arp2.add_vpp_config()
1395
1396 p1 = (Ether(dst=self.pg0.local_mac,
1397 src=self.pg0.remote_mac) /
1398 IP(src=self.pg0.remote_ip4,
1399 dst=self.pg1.remote_hosts[0].ip4) /
1400 UDP(sport=1234, dport=1234) /
1401 Raw())
1402 p2 = (Ether(dst=self.pg0.local_mac,
1403 src=self.pg0.remote_mac) /
1404 IP(src=self.pg0.remote_ip4,
1405 dst=self.pg1.remote_hosts[1].ip4) /
1406 UDP(sport=1234, dport=1234) /
1407 Raw())
1408
1409 rx = self.send_and_expect(self.pg0, p1 * 65, self.pg1)
1410 rx = self.send_and_expect(self.pg0, p2 * 65, self.pg1)
1411
1412 self.assertEqual(65, arp1.get_stats()['packets'])
1413 self.assertEqual(65, arp2.get_stats()['packets'])
1414
1415 rx = self.send_and_expect(self.pg0, p1 * 65, self.pg1)
1416 self.assertEqual(130, arp1.get_stats()['packets'])
1417
1418 def test_nd_stats(self):
1419 """ ND Counters """
1420
1421 self.vapi.cli("adj counters enable")
1422 self.pg0.generate_remote_hosts(3)
1423
1424 nd1 = VppNeighbor(self,
1425 self.pg0.sw_if_index,
1426 self.pg0.remote_hosts[1].mac,
1427 self.pg0.remote_hosts[1].ip6,
1428 af=AF_INET6)
1429 nd1.add_vpp_config()
1430 nd2 = VppNeighbor(self,
1431 self.pg0.sw_if_index,
1432 self.pg0.remote_hosts[2].mac,
1433 self.pg0.remote_hosts[2].ip6,
1434 af=AF_INET6)
1435 nd2.add_vpp_config()
1436
1437 p1 = (Ether(dst=self.pg1.local_mac,
1438 src=self.pg1.remote_mac) /
1439 IPv6(src=self.pg1.remote_ip6,
1440 dst=self.pg0.remote_hosts[1].ip6) /
1441 UDP(sport=1234, dport=1234) /
1442 Raw())
1443 p2 = (Ether(dst=self.pg1.local_mac,
1444 src=self.pg1.remote_mac) /
1445 IPv6(src=self.pg1.remote_ip6,
1446 dst=self.pg0.remote_hosts[2].ip6) /
1447 UDP(sport=1234, dport=1234) /
1448 Raw())
1449
1450 rx = self.send_and_expect(self.pg1, p1 * 16, self.pg0)
1451 rx = self.send_and_expect(self.pg1, p2 * 16, self.pg0)
1452
1453 self.assertEqual(16, nd1.get_stats()['packets'])
1454 self.assertEqual(16, nd2.get_stats()['packets'])
1455
1456 rx = self.send_and_expect(self.pg1, p1 * 65, self.pg0)
1457 self.assertEqual(81, nd1.get_stats()['packets'])
1458
1459
Neale Ranns37be7362017-02-21 17:30:26 -08001460if __name__ == '__main__':
1461 unittest.main(testRunner=VppTestRunner)