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