blob: 416241e8a6499187be1cd1993431c13b9909389a [file] [log] [blame]
Renato Botelho do Coutoead1e532019-10-31 13:31:07 -05001#!/usr/bin/env python3
Neale Ranns39f9d8b2017-02-16 21:57:05 -08002
3import unittest
Neale Rannscbe25aa2019-09-30 10:53:31 +00004import os
Neale Ranns39f9d8b2017-02-16 21:57:05 -08005from socket import AF_INET, AF_INET6, inet_pton
6
7from framework import VppTestCase, VppTestRunner
8from vpp_neighbor import VppNeighbor, find_nbr
Neale Ranns15002542017-09-10 04:39:11 -07009from vpp_ip_route import VppIpRoute, VppRoutePath, find_route, \
Neale Ranns097fa662018-05-01 05:17:55 -070010 VppIpTable, DpoProto, FibPathType
Neale Ranns37029302018-08-10 05:30:06 -070011from vpp_papi import VppEnum
Neale Ranns39f9d8b2017-02-16 21:57:05 -080012
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -070013import scapy.compat
Neale Ranns39f9d8b2017-02-16 21:57:05 -080014from scapy.packet import Raw
Neale Ranns30d0fd42017-05-30 07:30:04 -070015from scapy.layers.l2 import Ether, ARP, Dot1Q
Neale Ranns240dcb22020-04-23 09:04:59 +000016from scapy.layers.inet import IP, UDP, TCP
Neale Rannscd35e532018-08-31 02:51:45 -070017from scapy.layers.inet6 import IPv6
Neale Ranns37be7362017-02-21 17:30:26 -080018from scapy.contrib.mpls import MPLS
Neale Ranns14260392018-09-28 05:00:57 -070019from scapy.layers.inet6 import IPv6
Neale Ranns39f9d8b2017-02-16 21:57:05 -080020
Paul Vinciguerra4271c972019-05-14 13:25:49 -040021
22NUM_PKTS = 67
23
Neale Ranns39f9d8b2017-02-16 21:57:05 -080024# not exported by scapy, so redefined here
25arp_opts = {"who-has": 1, "is-at": 2}
26
27
28class ARPTestCase(VppTestCase):
29 """ ARP Test Case """
30
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070031 @classmethod
32 def setUpClass(cls):
33 super(ARPTestCase, cls).setUpClass()
34
35 @classmethod
36 def tearDownClass(cls):
37 super(ARPTestCase, cls).tearDownClass()
38
Neale Ranns39f9d8b2017-02-16 21:57:05 -080039 def setUp(self):
40 super(ARPTestCase, self).setUp()
41
42 # create 3 pg interfaces
43 self.create_pg_interfaces(range(4))
44
45 # pg0 configured with ip4 and 6 addresses used for input
46 # pg1 configured with ip4 and 6 addresses used for output
47 # pg2 is unnumbered to pg0
48 for i in self.pg_interfaces:
49 i.admin_up()
50
51 self.pg0.config_ip4()
52 self.pg0.config_ip6()
53 self.pg0.resolve_arp()
54
55 self.pg1.config_ip4()
56 self.pg1.config_ip6()
57
58 # pg3 in a different VRF
Neale Ranns15002542017-09-10 04:39:11 -070059 self.tbl = VppIpTable(self, 1)
60 self.tbl.add_vpp_config()
61
Neale Ranns39f9d8b2017-02-16 21:57:05 -080062 self.pg3.set_table_ip4(1)
63 self.pg3.config_ip4()
64
Neale Ranns4008ac92017-02-13 23:20:04 -080065 def tearDown(self):
Neale Ranns4b919a52017-03-11 05:55:21 -080066 self.pg0.unconfig_ip4()
67 self.pg0.unconfig_ip6()
68
69 self.pg1.unconfig_ip4()
70 self.pg1.unconfig_ip6()
71
72 self.pg3.unconfig_ip4()
Neale Ranns15002542017-09-10 04:39:11 -070073 self.pg3.set_table_ip4(0)
Neale Ranns4b919a52017-03-11 05:55:21 -080074
Neale Ranns4008ac92017-02-13 23:20:04 -080075 for i in self.pg_interfaces:
Neale Ranns4008ac92017-02-13 23:20:04 -080076 i.admin_down()
77
Neale Ranns15002542017-09-10 04:39:11 -070078 super(ARPTestCase, self).tearDown()
79
Neale Ranns39f9d8b2017-02-16 21:57:05 -080080 def verify_arp_req(self, rx, smac, sip, dip):
81 ether = rx[Ether]
82 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
83 self.assertEqual(ether.src, smac)
84
85 arp = rx[ARP]
86 self.assertEqual(arp.hwtype, 1)
87 self.assertEqual(arp.ptype, 0x800)
88 self.assertEqual(arp.hwlen, 6)
89 self.assertEqual(arp.plen, 4)
90 self.assertEqual(arp.op, arp_opts["who-has"])
91 self.assertEqual(arp.hwsrc, smac)
92 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
93 self.assertEqual(arp.psrc, sip)
94 self.assertEqual(arp.pdst, dip)
95
96 def verify_arp_resp(self, rx, smac, dmac, sip, dip):
97 ether = rx[Ether]
98 self.assertEqual(ether.dst, dmac)
99 self.assertEqual(ether.src, smac)
100
101 arp = rx[ARP]
102 self.assertEqual(arp.hwtype, 1)
103 self.assertEqual(arp.ptype, 0x800)
104 self.assertEqual(arp.hwlen, 6)
105 self.assertEqual(arp.plen, 4)
106 self.assertEqual(arp.op, arp_opts["is-at"])
107 self.assertEqual(arp.hwsrc, smac)
108 self.assertEqual(arp.hwdst, dmac)
109 self.assertEqual(arp.psrc, sip)
110 self.assertEqual(arp.pdst, dip)
111
Matthew Smithcb9ab472017-05-16 21:35:56 -0500112 def verify_arp_vrrp_resp(self, rx, smac, dmac, sip, dip):
113 ether = rx[Ether]
114 self.assertEqual(ether.dst, dmac)
115 self.assertEqual(ether.src, smac)
116
117 arp = rx[ARP]
118 self.assertEqual(arp.hwtype, 1)
119 self.assertEqual(arp.ptype, 0x800)
120 self.assertEqual(arp.hwlen, 6)
121 self.assertEqual(arp.plen, 4)
122 self.assertEqual(arp.op, arp_opts["is-at"])
123 self.assertNotEqual(arp.hwsrc, smac)
124 self.assertTrue("00:00:5e:00:01" in arp.hwsrc or
125 "00:00:5E:00:01" in arp.hwsrc)
126 self.assertEqual(arp.hwdst, dmac)
127 self.assertEqual(arp.psrc, sip)
128 self.assertEqual(arp.pdst, dip)
129
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800130 def verify_ip(self, rx, smac, dmac, sip, dip):
131 ether = rx[Ether]
132 self.assertEqual(ether.dst, dmac)
133 self.assertEqual(ether.src, smac)
134
135 ip = rx[IP]
136 self.assertEqual(ip.src, sip)
137 self.assertEqual(ip.dst, dip)
138
Neale Ranns37be7362017-02-21 17:30:26 -0800139 def verify_ip_o_mpls(self, rx, smac, dmac, label, sip, dip):
140 ether = rx[Ether]
141 self.assertEqual(ether.dst, dmac)
142 self.assertEqual(ether.src, smac)
143
144 mpls = rx[MPLS]
145 self.assertTrue(mpls.label, label)
146
147 ip = rx[IP]
148 self.assertEqual(ip.src, sip)
149 self.assertEqual(ip.dst, dip)
150
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800151 def test_arp(self):
152 """ ARP """
153
154 #
155 # Generate some hosts on the LAN
156 #
Neale Rannsca193612017-06-14 06:50:08 -0700157 self.pg1.generate_remote_hosts(11)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800158
159 #
Neale Rannscbe25aa2019-09-30 10:53:31 +0000160 # watch for:
161 # - all neighbour events
162 # - all neighbor events on pg1
163 # - neighbor events for host[1] on pg1
164 #
165 self.vapi.want_ip_neighbor_events(enable=1,
166 pid=os.getpid())
167 self.vapi.want_ip_neighbor_events(enable=1,
168 pid=os.getpid(),
169 sw_if_index=self.pg1.sw_if_index)
170 self.vapi.want_ip_neighbor_events(enable=1,
171 pid=os.getpid(),
172 sw_if_index=self.pg1.sw_if_index,
173 ip=self.pg1.remote_hosts[1].ip4)
174
175 self.logger.info(self.vapi.cli("sh ip neighbor-watcher"))
176
177 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800178 # Send IP traffic to one of these unresolved hosts.
179 # expect the generation of an ARP request
180 #
181 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
182 IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[1].ip4) /
183 UDP(sport=1234, dport=1234) /
184 Raw())
185
186 self.pg0.add_stream(p)
187 self.pg_enable_capture(self.pg_interfaces)
188 self.pg_start()
189
190 rx = self.pg1.get_capture(1)
191
192 self.verify_arp_req(rx[0],
193 self.pg1.local_mac,
194 self.pg1.local_ip4,
195 self.pg1._remote_hosts[1].ip4)
196
197 #
198 # And a dynamic ARP entry for host 1
199 #
200 dyn_arp = VppNeighbor(self,
201 self.pg1.sw_if_index,
202 self.pg1.remote_hosts[1].mac,
203 self.pg1.remote_hosts[1].ip4)
204 dyn_arp.add_vpp_config()
Neale Rannscbe25aa2019-09-30 10:53:31 +0000205 self.assertTrue(dyn_arp.query_vpp_config())
206
207 # this matches all of the listnerers
208 es = [self.vapi.wait_for_event(1, "ip_neighbor_event")
209 for i in range(3)]
210 for e in es:
211 self.assertEqual(str(e.neighbor.ip_address),
212 self.pg1.remote_hosts[1].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800213
214 #
215 # now we expect IP traffic forwarded
216 #
217 dyn_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
218 IP(src=self.pg0.remote_ip4,
219 dst=self.pg1._remote_hosts[1].ip4) /
220 UDP(sport=1234, dport=1234) /
221 Raw())
222
223 self.pg0.add_stream(dyn_p)
224 self.pg_enable_capture(self.pg_interfaces)
225 self.pg_start()
226
227 rx = self.pg1.get_capture(1)
228
229 self.verify_ip(rx[0],
230 self.pg1.local_mac,
231 self.pg1.remote_hosts[1].mac,
232 self.pg0.remote_ip4,
233 self.pg1._remote_hosts[1].ip4)
234
235 #
236 # And a Static ARP entry for host 2
237 #
238 static_arp = VppNeighbor(self,
239 self.pg1.sw_if_index,
240 self.pg1.remote_hosts[2].mac,
241 self.pg1.remote_hosts[2].ip4,
242 is_static=1)
243 static_arp.add_vpp_config()
Neale Rannscbe25aa2019-09-30 10:53:31 +0000244 es = [self.vapi.wait_for_event(1, "ip_neighbor_event")
245 for i in range(2)]
246 for e in es:
247 self.assertEqual(str(e.neighbor.ip_address),
248 self.pg1.remote_hosts[2].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800249
250 static_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
251 IP(src=self.pg0.remote_ip4,
252 dst=self.pg1._remote_hosts[2].ip4) /
253 UDP(sport=1234, dport=1234) /
254 Raw())
255
256 self.pg0.add_stream(static_p)
257 self.pg_enable_capture(self.pg_interfaces)
258 self.pg_start()
259
260 rx = self.pg1.get_capture(1)
261
262 self.verify_ip(rx[0],
263 self.pg1.local_mac,
264 self.pg1.remote_hosts[2].mac,
265 self.pg0.remote_ip4,
266 self.pg1._remote_hosts[2].ip4)
267
268 #
Neale Rannscbe25aa2019-09-30 10:53:31 +0000269 # remove all the listeners
270 #
271 self.vapi.want_ip_neighbor_events(enable=0,
272 pid=os.getpid())
273 self.vapi.want_ip_neighbor_events(enable=0,
274 pid=os.getpid(),
275 sw_if_index=self.pg1.sw_if_index)
276 self.vapi.want_ip_neighbor_events(enable=0,
277 pid=os.getpid(),
278 sw_if_index=self.pg1.sw_if_index,
279 ip=self.pg1.remote_hosts[1].ip4)
280
281 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800282 # flap the link. dynamic ARPs get flush, statics don't
283 #
284 self.pg1.admin_down()
285 self.pg1.admin_up()
286
287 self.pg0.add_stream(static_p)
288 self.pg_enable_capture(self.pg_interfaces)
289 self.pg_start()
290 rx = self.pg1.get_capture(1)
291
292 self.verify_ip(rx[0],
293 self.pg1.local_mac,
294 self.pg1.remote_hosts[2].mac,
295 self.pg0.remote_ip4,
296 self.pg1._remote_hosts[2].ip4)
297
298 self.pg0.add_stream(dyn_p)
299 self.pg_enable_capture(self.pg_interfaces)
300 self.pg_start()
301
302 rx = self.pg1.get_capture(1)
303 self.verify_arp_req(rx[0],
304 self.pg1.local_mac,
305 self.pg1.local_ip4,
306 self.pg1._remote_hosts[1].ip4)
307
Neale Rannscbe25aa2019-09-30 10:53:31 +0000308 self.assertFalse(dyn_arp.query_vpp_config())
309 self.assertTrue(static_arp.query_vpp_config())
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800310 #
311 # Send an ARP request from one of the so-far unlearned remote hosts
312 #
313 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
314 src=self.pg1._remote_hosts[3].mac) /
315 ARP(op="who-has",
316 hwsrc=self.pg1._remote_hosts[3].mac,
317 pdst=self.pg1.local_ip4,
318 psrc=self.pg1._remote_hosts[3].ip4))
319
320 self.pg1.add_stream(p)
321 self.pg_enable_capture(self.pg_interfaces)
322 self.pg_start()
323
324 rx = self.pg1.get_capture(1)
325 self.verify_arp_resp(rx[0],
326 self.pg1.local_mac,
327 self.pg1._remote_hosts[3].mac,
328 self.pg1.local_ip4,
329 self.pg1._remote_hosts[3].ip4)
330
331 #
332 # VPP should have learned the mapping for the remote host
333 #
334 self.assertTrue(find_nbr(self,
335 self.pg1.sw_if_index,
336 self.pg1._remote_hosts[3].ip4))
Neale Ranns4b919a52017-03-11 05:55:21 -0800337 #
338 # Fire in an ARP request before the interface becomes IP enabled
339 #
340 self.pg2.generate_remote_hosts(4)
341
342 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
343 ARP(op="who-has",
344 hwsrc=self.pg2.remote_mac,
345 pdst=self.pg1.local_ip4,
346 psrc=self.pg2.remote_hosts[3].ip4))
Neale Ranns30d0fd42017-05-30 07:30:04 -0700347 pt = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
348 Dot1Q(vlan=0) /
349 ARP(op="who-has",
350 hwsrc=self.pg2.remote_mac,
351 pdst=self.pg1.local_ip4,
352 psrc=self.pg2.remote_hosts[3].ip4))
Neale Ranns4b919a52017-03-11 05:55:21 -0800353 self.send_and_assert_no_replies(self.pg2, p,
354 "interface not IP enabled")
355
356 #
357 # Make pg2 un-numbered to pg1
358 #
359 self.pg2.set_unnumbered(self.pg1.sw_if_index)
360
Neale Rannsac3e72c2019-10-06 01:04:26 -0700361 #
362 # test the unnumbered dump both by all interfaces and just the enabled
363 # one
364 #
Neale Ranns404d88e2018-08-08 06:37:33 -0700365 unnum = self.vapi.ip_unnumbered_dump()
Neale Rannsac3e72c2019-10-06 01:04:26 -0700366 self.assertTrue(len(unnum))
367 self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
368 self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)
369 unnum = self.vapi.ip_unnumbered_dump(self.pg2.sw_if_index)
370 self.assertTrue(len(unnum))
Neale Ranns404d88e2018-08-08 06:37:33 -0700371 self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
372 self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)
373
Neale Ranns4b919a52017-03-11 05:55:21 -0800374 #
375 # We should respond to ARP requests for the unnumbered to address
376 # once an attached route to the source is known
377 #
378 self.send_and_assert_no_replies(
379 self.pg2, p,
380 "ARP req for unnumbered address - no source")
381
382 attached_host = VppIpRoute(self, self.pg2.remote_hosts[3].ip4, 32,
383 [VppRoutePath("0.0.0.0",
384 self.pg2.sw_if_index)])
385 attached_host.add_vpp_config()
386
387 self.pg2.add_stream(p)
388 self.pg_enable_capture(self.pg_interfaces)
389 self.pg_start()
390
391 rx = self.pg2.get_capture(1)
392 self.verify_arp_resp(rx[0],
393 self.pg2.local_mac,
394 self.pg2.remote_mac,
395 self.pg1.local_ip4,
396 self.pg2.remote_hosts[3].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800397
Neale Ranns30d0fd42017-05-30 07:30:04 -0700398 self.pg2.add_stream(pt)
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.pg2.remote_hosts[3].ip4)
408
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800409 #
Neale Ranns3983ac22017-03-10 11:53:27 -0800410 # A neighbor entry that has no associated FIB-entry
411 #
412 arp_no_fib = VppNeighbor(self,
413 self.pg1.sw_if_index,
414 self.pg1.remote_hosts[4].mac,
415 self.pg1.remote_hosts[4].ip4,
416 is_no_fib_entry=1)
417 arp_no_fib.add_vpp_config()
418
419 #
420 # check we have the neighbor, but no route
421 #
422 self.assertTrue(find_nbr(self,
423 self.pg1.sw_if_index,
424 self.pg1._remote_hosts[4].ip4))
425 self.assertFalse(find_route(self,
426 self.pg1._remote_hosts[4].ip4,
427 32))
428 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800429 # pg2 is unnumbered to pg1, so we can form adjacencies out of pg2
430 # from within pg1's subnet
Neale Ranns3983ac22017-03-10 11:53:27 -0800431 #
432 arp_unnum = VppNeighbor(self,
433 self.pg2.sw_if_index,
434 self.pg1.remote_hosts[5].mac,
435 self.pg1.remote_hosts[5].ip4)
436 arp_unnum.add_vpp_config()
437
438 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
439 IP(src=self.pg0.remote_ip4,
440 dst=self.pg1._remote_hosts[5].ip4) /
441 UDP(sport=1234, dport=1234) /
442 Raw())
443
444 self.pg0.add_stream(p)
445 self.pg_enable_capture(self.pg_interfaces)
446 self.pg_start()
447
448 rx = self.pg2.get_capture(1)
449
450 self.verify_ip(rx[0],
451 self.pg2.local_mac,
452 self.pg1.remote_hosts[5].mac,
453 self.pg0.remote_ip4,
454 self.pg1._remote_hosts[5].ip4)
455
456 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800457 # ARP requests from hosts in pg1's subnet sent on pg2 are replied to
458 # with the unnumbered interface's address as the source
459 #
460 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
461 ARP(op="who-has",
462 hwsrc=self.pg2.remote_mac,
463 pdst=self.pg1.local_ip4,
464 psrc=self.pg1.remote_hosts[6].ip4))
465
466 self.pg2.add_stream(p)
467 self.pg_enable_capture(self.pg_interfaces)
468 self.pg_start()
469
470 rx = self.pg2.get_capture(1)
471 self.verify_arp_resp(rx[0],
472 self.pg2.local_mac,
473 self.pg2.remote_mac,
474 self.pg1.local_ip4,
475 self.pg1.remote_hosts[6].ip4)
476
477 #
478 # An attached host route out of pg2 for an undiscovered hosts generates
479 # an ARP request with the unnumbered address as the source
480 #
481 att_unnum = VppIpRoute(self, self.pg1.remote_hosts[7].ip4, 32,
482 [VppRoutePath("0.0.0.0",
483 self.pg2.sw_if_index)])
484 att_unnum.add_vpp_config()
485
486 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
487 IP(src=self.pg0.remote_ip4,
488 dst=self.pg1._remote_hosts[7].ip4) /
489 UDP(sport=1234, dport=1234) /
490 Raw())
491
492 self.pg0.add_stream(p)
493 self.pg_enable_capture(self.pg_interfaces)
494 self.pg_start()
495
496 rx = self.pg2.get_capture(1)
497
498 self.verify_arp_req(rx[0],
499 self.pg2.local_mac,
500 self.pg1.local_ip4,
501 self.pg1._remote_hosts[7].ip4)
502
503 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
504 ARP(op="who-has",
505 hwsrc=self.pg2.remote_mac,
506 pdst=self.pg1.local_ip4,
507 psrc=self.pg1.remote_hosts[7].ip4))
508
509 self.pg2.add_stream(p)
510 self.pg_enable_capture(self.pg_interfaces)
511 self.pg_start()
512
513 rx = self.pg2.get_capture(1)
514 self.verify_arp_resp(rx[0],
515 self.pg2.local_mac,
516 self.pg2.remote_mac,
517 self.pg1.local_ip4,
518 self.pg1.remote_hosts[7].ip4)
519
520 #
521 # An attached host route as yet unresolved out of pg2 for an
522 # undiscovered host, an ARP requests begets a response.
523 #
524 att_unnum1 = VppIpRoute(self, self.pg1.remote_hosts[8].ip4, 32,
525 [VppRoutePath("0.0.0.0",
526 self.pg2.sw_if_index)])
527 att_unnum1.add_vpp_config()
528
529 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
530 ARP(op="who-has",
531 hwsrc=self.pg2.remote_mac,
532 pdst=self.pg1.local_ip4,
533 psrc=self.pg1.remote_hosts[8].ip4))
534
535 self.pg2.add_stream(p)
536 self.pg_enable_capture(self.pg_interfaces)
537 self.pg_start()
538
539 rx = self.pg2.get_capture(1)
540 self.verify_arp_resp(rx[0],
541 self.pg2.local_mac,
542 self.pg2.remote_mac,
543 self.pg1.local_ip4,
544 self.pg1.remote_hosts[8].ip4)
545
546 #
Neale Ranns30d0fd42017-05-30 07:30:04 -0700547 # Send an ARP request from one of the so-far unlearned remote hosts
548 # with a VLAN0 tag
549 #
550 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
551 src=self.pg1._remote_hosts[9].mac) /
552 Dot1Q(vlan=0) /
553 ARP(op="who-has",
554 hwsrc=self.pg1._remote_hosts[9].mac,
555 pdst=self.pg1.local_ip4,
556 psrc=self.pg1._remote_hosts[9].ip4))
557
558 self.pg1.add_stream(p)
559 self.pg_enable_capture(self.pg_interfaces)
560 self.pg_start()
561
562 rx = self.pg1.get_capture(1)
563 self.verify_arp_resp(rx[0],
564 self.pg1.local_mac,
565 self.pg1._remote_hosts[9].mac,
566 self.pg1.local_ip4,
567 self.pg1._remote_hosts[9].ip4)
568
569 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700570 # Add a hierarchy of routes for a host in the sub-net.
Neale Rannsca193612017-06-14 06:50:08 -0700571 # Should still get an ARP resp since the cover is attached
572 #
573 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_mac) /
574 ARP(op="who-has",
575 hwsrc=self.pg1.remote_mac,
576 pdst=self.pg1.local_ip4,
577 psrc=self.pg1.remote_hosts[10].ip4))
578
579 r1 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 30,
580 [VppRoutePath(self.pg1.remote_hosts[10].ip4,
581 self.pg1.sw_if_index)])
582 r1.add_vpp_config()
583
584 self.pg1.add_stream(p)
585 self.pg_enable_capture(self.pg_interfaces)
586 self.pg_start()
587 rx = self.pg1.get_capture(1)
588 self.verify_arp_resp(rx[0],
589 self.pg1.local_mac,
590 self.pg1.remote_mac,
591 self.pg1.local_ip4,
592 self.pg1.remote_hosts[10].ip4)
593
594 r2 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 32,
595 [VppRoutePath(self.pg1.remote_hosts[10].ip4,
596 self.pg1.sw_if_index)])
597 r2.add_vpp_config()
598
599 self.pg1.add_stream(p)
600 self.pg_enable_capture(self.pg_interfaces)
601 self.pg_start()
602 rx = self.pg1.get_capture(1)
603 self.verify_arp_resp(rx[0],
604 self.pg1.local_mac,
605 self.pg1.remote_mac,
606 self.pg1.local_ip4,
607 self.pg1.remote_hosts[10].ip4)
608
609 #
610 # add an ARP entry that's not on the sub-net and so whose
611 # adj-fib fails the refinement check. then send an ARP request
612 # from that source
613 #
614 a1 = VppNeighbor(self,
615 self.pg0.sw_if_index,
616 self.pg0.remote_mac,
617 "100.100.100.50")
618 a1.add_vpp_config()
619
620 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
621 ARP(op="who-has",
622 hwsrc=self.pg0.remote_mac,
623 psrc="100.100.100.50",
624 pdst=self.pg0.remote_ip4))
625 self.send_and_assert_no_replies(self.pg0, p,
626 "ARP req for from failed adj-fib")
627
628 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800629 # ERROR Cases
630 # 1 - don't respond to ARP request for address not within the
631 # interface's sub-net
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700632 # 1b - nor within the unnumbered subnet
633 # 1c - nor within the subnet of a different interface
634 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800635 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
636 ARP(op="who-has",
637 hwsrc=self.pg0.remote_mac,
638 pdst="10.10.10.3",
639 psrc=self.pg0.remote_ip4))
640 self.send_and_assert_no_replies(self.pg0, p,
641 "ARP req for non-local destination")
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700642 self.assertFalse(find_nbr(self,
643 self.pg0.sw_if_index,
644 "10.10.10.3"))
645
Neale Ranns4b919a52017-03-11 05:55:21 -0800646 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
647 ARP(op="who-has",
648 hwsrc=self.pg2.remote_mac,
649 pdst="10.10.10.3",
650 psrc=self.pg1.remote_hosts[7].ip4))
651 self.send_and_assert_no_replies(
652 self.pg0, p,
653 "ARP req for non-local destination - unnum")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800654
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700655 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 pdst=self.pg1.local_ip4,
659 psrc=self.pg1.remote_ip4))
660 self.send_and_assert_no_replies(self.pg0, p,
661 "ARP req diff sub-net")
662 self.assertFalse(find_nbr(self,
663 self.pg0.sw_if_index,
664 self.pg1.remote_ip4))
665
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800666 #
667 # 2 - don't respond to ARP request from an address not within the
668 # interface's sub-net
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700669 # 2b - to a proxied address
670 # 2c - not within a different interface's sub-net
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800671 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
672 ARP(op="who-has",
673 hwsrc=self.pg0.remote_mac,
674 psrc="10.10.10.3",
675 pdst=self.pg0.local_ip4))
676 self.send_and_assert_no_replies(self.pg0, p,
677 "ARP req for non-local source")
Neale Ranns4b919a52017-03-11 05:55:21 -0800678 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
679 ARP(op="who-has",
680 hwsrc=self.pg2.remote_mac,
681 psrc="10.10.10.3",
682 pdst=self.pg0.local_ip4))
683 self.send_and_assert_no_replies(
684 self.pg0, p,
685 "ARP req for non-local source - unnum")
Neale Rannsca193612017-06-14 06:50:08 -0700686 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
687 ARP(op="who-has",
688 hwsrc=self.pg0.remote_mac,
689 psrc=self.pg1.remote_ip4,
690 pdst=self.pg0.local_ip4))
691 self.send_and_assert_no_replies(self.pg0, p,
692 "ARP req for non-local source 2c")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800693
694 #
695 # 3 - don't respond to ARP request from an address that belongs to
696 # the router
697 #
698 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
699 ARP(op="who-has",
700 hwsrc=self.pg0.remote_mac,
701 psrc=self.pg0.local_ip4,
702 pdst=self.pg0.local_ip4))
703 self.send_and_assert_no_replies(self.pg0, p,
704 "ARP req for non-local source")
705
706 #
707 # 4 - don't respond to ARP requests that has mac source different
708 # from ARP request HW source
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800709 #
710 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
711 ARP(op="who-has",
712 hwsrc="00:00:00:DE:AD:BE",
713 psrc=self.pg0.remote_ip4,
714 pdst=self.pg0.local_ip4))
715 self.send_and_assert_no_replies(self.pg0, p,
716 "ARP req for non-local source")
717
718 #
zhaoqinglingb4c42cd2017-12-23 15:20:59 +0800719 # 5 - don't respond to ARP requests for address within the
720 # interface's sub-net but not the interface's address
721 #
722 self.pg0.generate_remote_hosts(2)
723 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
724 ARP(op="who-has",
725 hwsrc=self.pg0.remote_mac,
726 psrc=self.pg0.remote_hosts[0].ip4,
727 pdst=self.pg0.remote_hosts[1].ip4))
728 self.send_and_assert_no_replies(self.pg0, p,
729 "ARP req for non-local destination")
730
731 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800732 # cleanup
733 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800734 static_arp.remove_vpp_config()
Neale Ranns3983ac22017-03-10 11:53:27 -0800735 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800736
Neale Ranns4b919a52017-03-11 05:55:21 -0800737 # need this to flush the adj-fibs
738 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
739 self.pg2.admin_down()
Neale Rannsca193612017-06-14 06:50:08 -0700740 self.pg1.admin_down()
Neale Ranns4b919a52017-03-11 05:55:21 -0800741
Neale Ranns24b170a2017-08-15 05:33:11 -0700742 def test_proxy_mirror_arp(self):
743 """ Interface Mirror Proxy ARP """
744
745 #
746 # When VPP has an interface whose address is also applied to a TAP
747 # interface on the host, then VPP's TAP interface will be unnumbered
748 # to the 'real' interface and do proxy ARP from the host.
749 # the curious aspect of this setup is that ARP requests from the host
750 # will come from the VPP's own address.
751 #
752 self.pg0.generate_remote_hosts(2)
753
754 arp_req_from_me = (Ether(src=self.pg2.remote_mac,
755 dst="ff:ff:ff:ff:ff:ff") /
756 ARP(op="who-has",
757 hwsrc=self.pg2.remote_mac,
758 pdst=self.pg0.remote_hosts[1].ip4,
759 psrc=self.pg0.local_ip4))
760
761 #
762 # Configure Proxy ARP for the subnet on PG0addresses on pg0
763 #
Neale Ranns37029302018-08-10 05:30:06 -0700764 self.vapi.proxy_arp_add_del(self.pg0._local_ip4_subnet,
765 self.pg0._local_ip4_bcast)
Neale Ranns24b170a2017-08-15 05:33:11 -0700766
767 # Make pg2 un-numbered to pg0
768 #
769 self.pg2.set_unnumbered(self.pg0.sw_if_index)
770
771 #
772 # Enable pg2 for proxy ARP
773 #
774 self.pg2.set_proxy_arp()
775
776 #
777 # Send the ARP request with an originating address that
778 # is VPP's own address
779 #
Neale Ranns240dcb22020-04-23 09:04:59 +0000780 rx = self.send_and_expect(self.pg2, [arp_req_from_me], self.pg2)
Neale Ranns24b170a2017-08-15 05:33:11 -0700781 self.verify_arp_resp(rx[0],
782 self.pg2.local_mac,
783 self.pg2.remote_mac,
784 self.pg0.remote_hosts[1].ip4,
785 self.pg0.local_ip4)
786
787 #
788 # validate we have not learned an ARP entry as a result of this
789 #
790 self.assertFalse(find_nbr(self,
791 self.pg2.sw_if_index,
792 self.pg0.local_ip4))
793
794 #
Neale Ranns240dcb22020-04-23 09:04:59 +0000795 # setup a punt redirect so packets from the uplink go to the tap
796 #
797 self.vapi.ip_punt_redirect(self.pg0.sw_if_index,
798 self.pg2.sw_if_index,
799 self.pg0.local_ip4)
800
801 p_tcp = (Ether(src=self.pg0.remote_mac,
802 dst=self.pg0.local_mac,) /
803 IP(src=self.pg0.remote_ip4,
804 dst=self.pg0.local_ip4) /
805 TCP(sport=80, dport=80) /
806 Raw())
807 rx = self.send_and_expect(self.pg0, [p_tcp], self.pg2)
808
809 # there's no ARP entry so this is an ARP req
810 self.assertTrue(rx[0].haslayer(ARP))
811
812 # and ARP entry for VPP's pg0 address on the host interface
813 n1 = VppNeighbor(self,
814 self.pg2.sw_if_index,
815 self.pg2.remote_mac,
816 self.pg0.local_ip4,
817 is_no_fib_entry=True).add_vpp_config()
818 # now the packets shold forward
819 rx = self.send_and_expect(self.pg0, [p_tcp], self.pg2)
820 self.assertFalse(rx[0].haslayer(ARP))
821 self.assertEqual(rx[0][Ether].dst, self.pg2.remote_mac)
822
823 #
824 # flush the neighbor cache on the uplink
825 #
826 af = VppEnum.vl_api_address_family_t
827 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, self.pg0.sw_if_index)
828
829 # ensure we can still resolve the ARPs on the uplink
830 self.pg0.resolve_arp()
831
832 self.assertTrue(find_nbr(self,
833 self.pg0.sw_if_index,
834 self.pg0.remote_ip4))
835
836 #
Neale Ranns24b170a2017-08-15 05:33:11 -0700837 # cleanup
838 #
839 self.pg2.set_proxy_arp(0)
Neale Ranns37029302018-08-10 05:30:06 -0700840 self.vapi.proxy_arp_add_del(self.pg0._local_ip4_subnet,
841 self.pg0._local_ip4_bcast,
Neale Ranns24b170a2017-08-15 05:33:11 -0700842 is_add=0)
843
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800844 def test_proxy_arp(self):
845 """ Proxy ARP """
846
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700847 self.pg1.generate_remote_hosts(2)
848
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800849 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700850 # Proxy ARP request packets for each interface
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800851 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800852 arp_req_pg0 = (Ether(src=self.pg0.remote_mac,
853 dst="ff:ff:ff:ff:ff:ff") /
854 ARP(op="who-has",
855 hwsrc=self.pg0.remote_mac,
856 pdst="10.10.10.3",
857 psrc=self.pg0.remote_ip4))
Neale Ranns30d0fd42017-05-30 07:30:04 -0700858 arp_req_pg0_tagged = (Ether(src=self.pg0.remote_mac,
859 dst="ff:ff:ff:ff:ff:ff") /
860 Dot1Q(vlan=0) /
861 ARP(op="who-has",
862 hwsrc=self.pg0.remote_mac,
863 pdst="10.10.10.3",
864 psrc=self.pg0.remote_ip4))
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800865 arp_req_pg1 = (Ether(src=self.pg1.remote_mac,
866 dst="ff:ff:ff:ff:ff:ff") /
867 ARP(op="who-has",
868 hwsrc=self.pg1.remote_mac,
869 pdst="10.10.10.3",
870 psrc=self.pg1.remote_ip4))
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700871 arp_req_pg2 = (Ether(src=self.pg2.remote_mac,
872 dst="ff:ff:ff:ff:ff:ff") /
873 ARP(op="who-has",
874 hwsrc=self.pg2.remote_mac,
875 pdst="10.10.10.3",
876 psrc=self.pg1.remote_hosts[1].ip4))
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800877 arp_req_pg3 = (Ether(src=self.pg3.remote_mac,
878 dst="ff:ff:ff:ff:ff:ff") /
879 ARP(op="who-has",
880 hwsrc=self.pg3.remote_mac,
881 pdst="10.10.10.3",
882 psrc=self.pg3.remote_ip4))
883
884 #
885 # Configure Proxy ARP for 10.10.10.0 -> 10.10.10.124
886 #
887 self.vapi.proxy_arp_add_del(inet_pton(AF_INET, "10.10.10.2"),
888 inet_pton(AF_INET, "10.10.10.124"))
889
890 #
891 # No responses are sent when the interfaces are not enabled for proxy
892 # ARP
893 #
894 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
895 "ARP req from unconfigured interface")
896 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
897 "ARP req from unconfigured interface")
898
899 #
900 # Make pg2 un-numbered to pg1
901 # still won't reply.
902 #
903 self.pg2.set_unnumbered(self.pg1.sw_if_index)
904
905 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
906 "ARP req from unnumbered interface")
907
908 #
909 # Enable each interface to reply to proxy ARPs
910 #
911 for i in self.pg_interfaces:
912 i.set_proxy_arp()
913
914 #
915 # Now each of the interfaces should reply to a request to a proxied
916 # address
917 #
918 self.pg0.add_stream(arp_req_pg0)
919 self.pg_enable_capture(self.pg_interfaces)
920 self.pg_start()
921
922 rx = self.pg0.get_capture(1)
923 self.verify_arp_resp(rx[0],
924 self.pg0.local_mac,
925 self.pg0.remote_mac,
926 "10.10.10.3",
927 self.pg0.remote_ip4)
928
Neale Ranns30d0fd42017-05-30 07:30:04 -0700929 self.pg0.add_stream(arp_req_pg0_tagged)
930 self.pg_enable_capture(self.pg_interfaces)
931 self.pg_start()
932
933 rx = self.pg0.get_capture(1)
934 self.verify_arp_resp(rx[0],
935 self.pg0.local_mac,
936 self.pg0.remote_mac,
937 "10.10.10.3",
938 self.pg0.remote_ip4)
939
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800940 self.pg1.add_stream(arp_req_pg1)
941 self.pg_enable_capture(self.pg_interfaces)
942 self.pg_start()
943
944 rx = self.pg1.get_capture(1)
945 self.verify_arp_resp(rx[0],
946 self.pg1.local_mac,
947 self.pg1.remote_mac,
948 "10.10.10.3",
949 self.pg1.remote_ip4)
950
951 self.pg2.add_stream(arp_req_pg2)
952 self.pg_enable_capture(self.pg_interfaces)
953 self.pg_start()
954
955 rx = self.pg2.get_capture(1)
956 self.verify_arp_resp(rx[0],
957 self.pg2.local_mac,
958 self.pg2.remote_mac,
959 "10.10.10.3",
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700960 self.pg1.remote_hosts[1].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800961
962 #
963 # A request for an address out of the configured range
964 #
965 arp_req_pg1_hi = (Ether(src=self.pg1.remote_mac,
966 dst="ff:ff:ff:ff:ff:ff") /
967 ARP(op="who-has",
968 hwsrc=self.pg1.remote_mac,
969 pdst="10.10.10.125",
970 psrc=self.pg1.remote_ip4))
971 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_hi,
972 "ARP req out of range HI")
973 arp_req_pg1_low = (Ether(src=self.pg1.remote_mac,
974 dst="ff:ff:ff:ff:ff:ff") /
975 ARP(op="who-has",
976 hwsrc=self.pg1.remote_mac,
977 pdst="10.10.10.1",
978 psrc=self.pg1.remote_ip4))
979 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_low,
980 "ARP req out of range Low")
981
982 #
983 # Request for an address in the proxy range but from an interface
984 # in a different VRF
985 #
986 self.send_and_assert_no_replies(self.pg3, arp_req_pg3,
987 "ARP req from different VRF")
988
989 #
990 # Disable Each interface for proxy ARP
991 # - expect none to respond
992 #
993 for i in self.pg_interfaces:
994 i.set_proxy_arp(0)
995
996 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
997 "ARP req from disable")
998 self.send_and_assert_no_replies(self.pg1, arp_req_pg1,
999 "ARP req from disable")
1000 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
1001 "ARP req from disable")
Neale Ranns37be7362017-02-21 17:30:26 -08001002
1003 #
1004 # clean up on interface 2
1005 #
Neale Ranns4b919a52017-03-11 05:55:21 -08001006 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns37be7362017-02-21 17:30:26 -08001007
1008 def test_mpls(self):
1009 """ MPLS """
1010
1011 #
1012 # Interface 2 does not yet have ip4 config
1013 #
1014 self.pg2.config_ip4()
1015 self.pg2.generate_remote_hosts(2)
1016
1017 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001018 # Add a route with out going label via an ARP unresolved next-hop
Neale Ranns37be7362017-02-21 17:30:26 -08001019 #
1020 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1021 [VppRoutePath(self.pg2.remote_hosts[1].ip4,
1022 self.pg2.sw_if_index,
1023 labels=[55])])
1024 ip_10_0_0_1.add_vpp_config()
1025
1026 #
1027 # packets should generate an ARP request
1028 #
1029 p = (Ether(src=self.pg0.remote_mac,
1030 dst=self.pg0.local_mac) /
1031 IP(src=self.pg0.remote_ip4, dst="10.0.0.1") /
1032 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01001033 Raw(b'\xa5' * 100))
Neale Ranns37be7362017-02-21 17:30:26 -08001034
1035 self.pg0.add_stream(p)
1036 self.pg_enable_capture(self.pg_interfaces)
1037 self.pg_start()
1038
1039 rx = self.pg2.get_capture(1)
1040 self.verify_arp_req(rx[0],
1041 self.pg2.local_mac,
1042 self.pg2.local_ip4,
1043 self.pg2._remote_hosts[1].ip4)
1044
1045 #
1046 # now resolve the neighbours
1047 #
1048 self.pg2.configure_ipv4_neighbors()
1049
1050 #
1051 # Now packet should be properly MPLS encapped.
1052 # This verifies that MPLS link-type adjacencies are completed
1053 # when the ARP entry resolves
1054 #
1055 self.pg0.add_stream(p)
1056 self.pg_enable_capture(self.pg_interfaces)
1057 self.pg_start()
1058
1059 rx = self.pg2.get_capture(1)
1060 self.verify_ip_o_mpls(rx[0],
1061 self.pg2.local_mac,
1062 self.pg2.remote_hosts[1].mac,
1063 55,
1064 self.pg0.remote_ip4,
1065 "10.0.0.1")
Neale Ranns4b919a52017-03-11 05:55:21 -08001066 self.pg2.unconfig_ip4()
Neale Ranns37be7362017-02-21 17:30:26 -08001067
Matthew Smithcb9ab472017-05-16 21:35:56 -05001068 def test_arp_vrrp(self):
1069 """ ARP reply with VRRP virtual src hw addr """
1070
1071 #
1072 # IP packet destined for pg1 remote host arrives on pg0 resulting
1073 # in an ARP request for the address of the remote host on pg1
1074 #
1075 p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1076 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1077 UDP(sport=1234, dport=1234) /
1078 Raw())
1079
Neale Ranns37029302018-08-10 05:30:06 -07001080 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
Matthew Smithcb9ab472017-05-16 21:35:56 -05001081
1082 self.verify_arp_req(rx1[0],
1083 self.pg1.local_mac,
1084 self.pg1.local_ip4,
1085 self.pg1.remote_ip4)
1086
1087 #
1088 # ARP reply for address of pg1 remote host arrives on pg1 with
1089 # the hw src addr set to a value in the VRRP IPv4 range of
1090 # MAC addresses
1091 #
1092 p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1093 ARP(op="is-at", hwdst=self.pg1.local_mac,
1094 hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
1095 psrc=self.pg1.remote_ip4))
1096
Neale Ranns37029302018-08-10 05:30:06 -07001097 self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
Matthew Smithcb9ab472017-05-16 21:35:56 -05001098
1099 #
1100 # IP packet destined for pg1 remote host arrives on pg0 again.
1101 # VPP should have an ARP entry for that address now and the packet
1102 # should be sent out pg1.
1103 #
Neale Ranns37029302018-08-10 05:30:06 -07001104 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
Matthew Smithcb9ab472017-05-16 21:35:56 -05001105
1106 self.verify_ip(rx1[0],
1107 self.pg1.local_mac,
1108 "00:00:5e:00:01:09",
1109 self.pg0.remote_ip4,
1110 self.pg1.remote_ip4)
1111
1112 self.pg1.admin_down()
1113 self.pg1.admin_up()
1114
Neale Rannsdcd6d622017-05-26 02:59:16 -07001115 def test_arp_duplicates(self):
1116 """ ARP Duplicates"""
1117
1118 #
1119 # Generate some hosts on the LAN
1120 #
1121 self.pg1.generate_remote_hosts(3)
1122
1123 #
1124 # Add host 1 on pg1 and pg2
1125 #
1126 arp_pg1 = VppNeighbor(self,
1127 self.pg1.sw_if_index,
1128 self.pg1.remote_hosts[1].mac,
1129 self.pg1.remote_hosts[1].ip4)
1130 arp_pg1.add_vpp_config()
1131 arp_pg2 = VppNeighbor(self,
1132 self.pg2.sw_if_index,
1133 self.pg2.remote_mac,
1134 self.pg1.remote_hosts[1].ip4)
1135 arp_pg2.add_vpp_config()
1136
1137 #
1138 # IP packet destined for pg1 remote host arrives on pg1 again.
1139 #
1140 p = (Ether(dst=self.pg0.local_mac,
1141 src=self.pg0.remote_mac) /
1142 IP(src=self.pg0.remote_ip4,
1143 dst=self.pg1.remote_hosts[1].ip4) /
1144 UDP(sport=1234, dport=1234) /
1145 Raw())
1146
1147 self.pg0.add_stream(p)
1148 self.pg_enable_capture(self.pg_interfaces)
1149 self.pg_start()
1150
1151 rx1 = self.pg1.get_capture(1)
1152
1153 self.verify_ip(rx1[0],
1154 self.pg1.local_mac,
1155 self.pg1.remote_hosts[1].mac,
1156 self.pg0.remote_ip4,
1157 self.pg1.remote_hosts[1].ip4)
1158
1159 #
1160 # remove the duplicate on pg1
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001161 # packet stream should generate ARPs out of pg1
Neale Rannsdcd6d622017-05-26 02:59:16 -07001162 #
1163 arp_pg1.remove_vpp_config()
1164
1165 self.pg0.add_stream(p)
1166 self.pg_enable_capture(self.pg_interfaces)
1167 self.pg_start()
1168
1169 rx1 = self.pg1.get_capture(1)
1170
1171 self.verify_arp_req(rx1[0],
1172 self.pg1.local_mac,
1173 self.pg1.local_ip4,
1174 self.pg1.remote_hosts[1].ip4)
1175
1176 #
1177 # Add it back
1178 #
1179 arp_pg1.add_vpp_config()
1180
1181 self.pg0.add_stream(p)
1182 self.pg_enable_capture(self.pg_interfaces)
1183 self.pg_start()
1184
1185 rx1 = self.pg1.get_capture(1)
1186
1187 self.verify_ip(rx1[0],
1188 self.pg1.local_mac,
1189 self.pg1.remote_hosts[1].mac,
1190 self.pg0.remote_ip4,
1191 self.pg1.remote_hosts[1].ip4)
1192
Neale Ranns15002542017-09-10 04:39:11 -07001193 def test_arp_static(self):
1194 """ ARP Static"""
1195 self.pg2.generate_remote_hosts(3)
1196
1197 #
1198 # Add a static ARP entry
1199 #
1200 static_arp = VppNeighbor(self,
1201 self.pg2.sw_if_index,
1202 self.pg2.remote_hosts[1].mac,
1203 self.pg2.remote_hosts[1].ip4,
1204 is_static=1)
1205 static_arp.add_vpp_config()
1206
1207 #
1208 # Add the connected prefix to the interface
1209 #
1210 self.pg2.config_ip4()
1211
1212 #
1213 # We should now find the adj-fib
1214 #
1215 self.assertTrue(find_nbr(self,
1216 self.pg2.sw_if_index,
1217 self.pg2.remote_hosts[1].ip4,
1218 is_static=1))
1219 self.assertTrue(find_route(self,
1220 self.pg2.remote_hosts[1].ip4,
1221 32))
1222
1223 #
1224 # remove the connected
1225 #
1226 self.pg2.unconfig_ip4()
1227
1228 #
1229 # put the interface into table 1
1230 #
1231 self.pg2.set_table_ip4(1)
1232
1233 #
1234 # configure the same connected and expect to find the
1235 # adj fib in the new table
1236 #
1237 self.pg2.config_ip4()
1238 self.assertTrue(find_route(self,
1239 self.pg2.remote_hosts[1].ip4,
1240 32,
1241 table_id=1))
1242
1243 #
1244 # clean-up
1245 #
1246 self.pg2.unconfig_ip4()
Neale Rannscbe25aa2019-09-30 10:53:31 +00001247 static_arp.remove_vpp_config()
Neale Ranns15002542017-09-10 04:39:11 -07001248 self.pg2.set_table_ip4(0)
1249
Neale Rannsc819fc62018-02-16 02:44:05 -08001250 def test_arp_incomplete(self):
1251 """ ARP Incomplete"""
1252 self.pg1.generate_remote_hosts(3)
1253
1254 p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1255 IP(src=self.pg0.remote_ip4,
1256 dst=self.pg1.remote_hosts[1].ip4) /
1257 UDP(sport=1234, dport=1234) /
1258 Raw())
1259 p1 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1260 IP(src=self.pg0.remote_ip4,
1261 dst=self.pg1.remote_hosts[2].ip4) /
1262 UDP(sport=1234, dport=1234) /
1263 Raw())
1264
1265 #
1266 # a packet to an unresolved destination generates an ARP request
1267 #
1268 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1269 self.verify_arp_req(rx[0],
1270 self.pg1.local_mac,
1271 self.pg1.local_ip4,
1272 self.pg1._remote_hosts[1].ip4)
1273
1274 #
1275 # add a neighbour for remote host 1
1276 #
1277 static_arp = VppNeighbor(self,
1278 self.pg1.sw_if_index,
1279 self.pg1.remote_hosts[1].mac,
1280 self.pg1.remote_hosts[1].ip4,
1281 is_static=1)
1282 static_arp.add_vpp_config()
1283
1284 #
1285 # change the interface's MAC
1286 #
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001287 mac = [scapy.compat.chb(0x00), scapy.compat.chb(0x00),
1288 scapy.compat.chb(0x00), scapy.compat.chb(0x33),
1289 scapy.compat.chb(0x33), scapy.compat.chb(0x33)]
Neale Rannsc819fc62018-02-16 02:44:05 -08001290 mac_string = ''.join(mac)
1291
1292 self.vapi.sw_interface_set_mac_address(self.pg1.sw_if_index,
1293 mac_string)
1294
1295 #
1296 # now ARP requests come from the new source mac
1297 #
1298 rx = self.send_and_expect(self.pg0, [p1], self.pg1)
1299 self.verify_arp_req(rx[0],
1300 "00:00:00:33:33:33",
1301 self.pg1.local_ip4,
1302 self.pg1._remote_hosts[2].ip4)
1303
1304 #
1305 # packets to the resolved host also have the new source mac
1306 #
1307 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1308 self.verify_ip(rx[0],
1309 "00:00:00:33:33:33",
1310 self.pg1.remote_hosts[1].mac,
1311 self.pg0.remote_ip4,
1312 self.pg1.remote_hosts[1].ip4)
1313
1314 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001315 # set the mac address on the interface that does not have a
Neale Rannsc819fc62018-02-16 02:44:05 -08001316 # configured subnet and thus no glean
1317 #
1318 self.vapi.sw_interface_set_mac_address(self.pg2.sw_if_index,
1319 mac_string)
1320
Neale Ranns59ae61e2018-06-07 18:09:49 -07001321 def test_garp(self):
1322 """ GARP """
1323
1324 #
1325 # Generate some hosts on the LAN
1326 #
1327 self.pg1.generate_remote_hosts(4)
1328
1329 #
1330 # And an ARP entry
1331 #
1332 arp = VppNeighbor(self,
1333 self.pg1.sw_if_index,
1334 self.pg1.remote_hosts[1].mac,
1335 self.pg1.remote_hosts[1].ip4)
1336 arp.add_vpp_config()
1337
1338 self.assertTrue(find_nbr(self,
1339 self.pg1.sw_if_index,
1340 self.pg1.remote_hosts[1].ip4,
1341 mac=self.pg1.remote_hosts[1].mac))
1342
1343 #
1344 # Send a GARP (request) to swap the host 1's address to that of host 2
1345 #
1346 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1347 src=self.pg1.remote_hosts[2].mac) /
1348 ARP(op="who-has",
1349 hwdst=self.pg1.local_mac,
1350 hwsrc=self.pg1.remote_hosts[2].mac,
1351 pdst=self.pg1.remote_hosts[1].ip4,
1352 psrc=self.pg1.remote_hosts[1].ip4))
1353
1354 self.pg1.add_stream(p1)
1355 self.pg_enable_capture(self.pg_interfaces)
1356 self.pg_start()
1357
1358 self.assertTrue(find_nbr(self,
1359 self.pg1.sw_if_index,
1360 self.pg1.remote_hosts[1].ip4,
1361 mac=self.pg1.remote_hosts[2].mac))
1362
1363 #
1364 # Send a GARP (reply) to swap the host 1's address to that of host 3
1365 #
1366 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1367 src=self.pg1.remote_hosts[3].mac) /
1368 ARP(op="is-at",
1369 hwdst=self.pg1.local_mac,
1370 hwsrc=self.pg1.remote_hosts[3].mac,
1371 pdst=self.pg1.remote_hosts[1].ip4,
1372 psrc=self.pg1.remote_hosts[1].ip4))
1373
1374 self.pg1.add_stream(p1)
1375 self.pg_enable_capture(self.pg_interfaces)
1376 self.pg_start()
1377
1378 self.assertTrue(find_nbr(self,
1379 self.pg1.sw_if_index,
1380 self.pg1.remote_hosts[1].ip4,
1381 mac=self.pg1.remote_hosts[3].mac))
1382
1383 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001384 # GARPs (request nor replies) for host we don't know yet
Neale Ranns59ae61e2018-06-07 18:09:49 -07001385 # don't result in new neighbour entries
1386 #
1387 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1388 src=self.pg1.remote_hosts[3].mac) /
1389 ARP(op="who-has",
1390 hwdst=self.pg1.local_mac,
1391 hwsrc=self.pg1.remote_hosts[3].mac,
1392 pdst=self.pg1.remote_hosts[2].ip4,
1393 psrc=self.pg1.remote_hosts[2].ip4))
1394
1395 self.pg1.add_stream(p1)
1396 self.pg_enable_capture(self.pg_interfaces)
1397 self.pg_start()
1398
1399 self.assertFalse(find_nbr(self,
1400 self.pg1.sw_if_index,
1401 self.pg1.remote_hosts[2].ip4))
1402
1403 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1404 src=self.pg1.remote_hosts[3].mac) /
1405 ARP(op="is-at",
1406 hwdst=self.pg1.local_mac,
1407 hwsrc=self.pg1.remote_hosts[3].mac,
1408 pdst=self.pg1.remote_hosts[2].ip4,
1409 psrc=self.pg1.remote_hosts[2].ip4))
1410
1411 self.pg1.add_stream(p1)
1412 self.pg_enable_capture(self.pg_interfaces)
1413 self.pg_start()
1414
1415 self.assertFalse(find_nbr(self,
1416 self.pg1.sw_if_index,
1417 self.pg1.remote_hosts[2].ip4))
1418
Neale Rannsc8352bc2018-08-29 10:23:58 -07001419 def test_arp_incomplete(self):
Neale Ranns14260392018-09-28 05:00:57 -07001420 """ Incomplete Entries """
Neale Rannsc8352bc2018-08-29 10:23:58 -07001421
1422 #
Neale Rannscd35e532018-08-31 02:51:45 -07001423 # ensure that we throttle the ARP and ND requests
Neale Rannsc8352bc2018-08-29 10:23:58 -07001424 #
1425 self.pg0.generate_remote_hosts(2)
1426
Neale Rannscd35e532018-08-31 02:51:45 -07001427 #
1428 # IPv4/ARP
1429 #
Neale Rannsc8352bc2018-08-29 10:23:58 -07001430 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1431 [VppRoutePath(self.pg0.remote_hosts[1].ip4,
Neale Rannscd35e532018-08-31 02:51:45 -07001432 self.pg0.sw_if_index)])
Neale Rannsc8352bc2018-08-29 10:23:58 -07001433 ip_10_0_0_1.add_vpp_config()
1434
1435 p1 = (Ether(dst=self.pg1.local_mac,
1436 src=self.pg1.remote_mac) /
1437 IP(src=self.pg1.remote_ip4,
1438 dst="10.0.0.1") /
1439 UDP(sport=1234, dport=1234) /
1440 Raw())
1441
1442 self.pg1.add_stream(p1 * 257)
1443 self.pg_enable_capture(self.pg_interfaces)
1444 self.pg_start()
1445 rx = self.pg0._get_capture(1)
1446
1447 #
1448 # how many we get is going to be dependent on the time for packet
1449 # processing but it should be small
1450 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001451 self.assertLess(len(rx), 64)
Neale Rannsc8352bc2018-08-29 10:23:58 -07001452
Neale Rannscd35e532018-08-31 02:51:45 -07001453 #
1454 # IPv6/ND
1455 #
1456 ip_10_1 = VppIpRoute(self, "10::1", 128,
1457 [VppRoutePath(self.pg0.remote_hosts[1].ip6,
1458 self.pg0.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07001459 proto=DpoProto.DPO_PROTO_IP6)])
Neale Rannscd35e532018-08-31 02:51:45 -07001460 ip_10_1.add_vpp_config()
1461
1462 p1 = (Ether(dst=self.pg1.local_mac,
1463 src=self.pg1.remote_mac) /
1464 IPv6(src=self.pg1.remote_ip6,
1465 dst="10::1") /
1466 UDP(sport=1234, dport=1234) /
1467 Raw())
1468
1469 self.pg1.add_stream(p1 * 257)
1470 self.pg_enable_capture(self.pg_interfaces)
1471 self.pg_start()
1472 rx = self.pg0._get_capture(1)
1473
1474 #
1475 # how many we get is going to be dependent on the time for packet
1476 # processing but it should be small
1477 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001478 self.assertLess(len(rx), 64)
Neale Rannscd35e532018-08-31 02:51:45 -07001479
Neale Ranns7425f922019-01-23 00:36:16 -08001480 def test_arp_forus(self):
1481 """ ARP for for-us """
1482
1483 #
1484 # Test that VPP responds with ARP requests to addresses that
1485 # are connected and local routes.
1486 # Use one of the 'remote' addresses in the subnet as a local address
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001487 # The intention of this route is that it then acts like a secondary
Neale Ranns7425f922019-01-23 00:36:16 -08001488 # address added to an interface
1489 #
1490 self.pg0.generate_remote_hosts(2)
1491
Neale Ranns097fa662018-05-01 05:17:55 -07001492 forus = VppIpRoute(
1493 self, self.pg0.remote_hosts[1].ip4, 32,
1494 [VppRoutePath("0.0.0.0",
1495 self.pg0.sw_if_index,
1496 type=FibPathType.FIB_PATH_TYPE_LOCAL)])
Neale Ranns7425f922019-01-23 00:36:16 -08001497 forus.add_vpp_config()
1498
1499 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
1500 src=self.pg0.remote_mac) /
1501 ARP(op="who-has",
1502 hwdst=self.pg0.local_mac,
1503 hwsrc=self.pg0.remote_mac,
1504 pdst=self.pg0.remote_hosts[1].ip4,
1505 psrc=self.pg0.remote_ip4))
1506
1507 rx = self.send_and_expect(self.pg0, [p], self.pg0)
1508
1509 self.verify_arp_resp(rx[0],
1510 self.pg0.local_mac,
1511 self.pg0.remote_mac,
1512 self.pg0.remote_hosts[1].ip4,
1513 self.pg0.remote_ip4)
1514
Neale Rannsfca3c6a2019-12-31 03:49:34 +00001515 def test_arp_table_swap(self):
1516 #
1517 # Generate some hosts on the LAN
1518 #
1519 N_NBRS = 4
1520 self.pg1.generate_remote_hosts(N_NBRS)
1521
1522 for n in range(N_NBRS):
1523 # a route thru each neighbour
1524 VppIpRoute(self, "10.0.0.%d" % n, 32,
1525 [VppRoutePath(self.pg1.remote_hosts[n].ip4,
1526 self.pg1.sw_if_index)]).add_vpp_config()
1527
1528 # resolve each neighbour
1529 p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1530 ARP(op="is-at", hwdst=self.pg1.local_mac,
1531 hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
1532 psrc=self.pg1.remote_hosts[n].ip4))
1533
1534 self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
1535
1536 self.logger.info(self.vapi.cli("sh ip neighbors"))
1537
1538 #
1539 # swap the table pg1 is in
1540 #
1541 table = VppIpTable(self, 100).add_vpp_config()
1542
1543 self.pg1.unconfig_ip4()
1544 self.pg1.set_table_ip4(100)
1545 self.pg1.config_ip4()
1546
1547 #
1548 # all neighbours are cleared
1549 #
1550 for n in range(N_NBRS):
1551 self.assertFalse(find_nbr(self,
1552 self.pg1.sw_if_index,
1553 self.pg1.remote_hosts[n].ip4))
1554
1555 #
1556 # packets to all neighbours generate ARP requests
1557 #
1558 for n in range(N_NBRS):
1559 # a route thru each neighbour
1560 VppIpRoute(self, "10.0.0.%d" % n, 32,
1561 [VppRoutePath(self.pg1.remote_hosts[n].ip4,
1562 self.pg1.sw_if_index)],
1563 table_id=100).add_vpp_config()
1564
1565 p = (Ether(src=self.pg1.remote_hosts[n].mac,
1566 dst=self.pg1.local_mac) /
1567 IP(src=self.pg1.remote_hosts[n].ip4,
1568 dst="10.0.0.%d" % n) /
1569 Raw(b'0x5' * 100))
1570 rxs = self.send_and_expect(self.pg1, [p], self.pg1)
1571 for rx in rxs:
1572 self.verify_arp_req(rx,
1573 self.pg1.local_mac,
1574 self.pg1.local_ip4,
1575 self.pg1.remote_hosts[n].ip4)
1576
1577 self.pg1.unconfig_ip4()
1578 self.pg1.set_table_ip4(0)
1579
Neale Rannsdcd6d622017-05-26 02:59:16 -07001580
Neale Ranns14260392018-09-28 05:00:57 -07001581class NeighborStatsTestCase(VppTestCase):
Neale Ranns37029302018-08-10 05:30:06 -07001582 """ ARP/ND Counters """
Neale Ranns14260392018-09-28 05:00:57 -07001583
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001584 @classmethod
1585 def setUpClass(cls):
1586 super(NeighborStatsTestCase, cls).setUpClass()
1587
1588 @classmethod
1589 def tearDownClass(cls):
1590 super(NeighborStatsTestCase, cls).tearDownClass()
1591
Neale Ranns14260392018-09-28 05:00:57 -07001592 def setUp(self):
1593 super(NeighborStatsTestCase, self).setUp()
1594
1595 self.create_pg_interfaces(range(2))
1596
1597 # pg0 configured with ip4 and 6 addresses used for input
1598 # pg1 configured with ip4 and 6 addresses used for output
1599 # pg2 is unnumbered to pg0
1600 for i in self.pg_interfaces:
1601 i.admin_up()
1602 i.config_ip4()
1603 i.config_ip6()
1604 i.resolve_arp()
1605 i.resolve_ndp()
1606
1607 def tearDown(self):
1608 super(NeighborStatsTestCase, self).tearDown()
1609
1610 for i in self.pg_interfaces:
1611 i.unconfig_ip4()
1612 i.unconfig_ip6()
1613 i.admin_down()
1614
1615 def test_arp_stats(self):
1616 """ ARP Counters """
1617
1618 self.vapi.cli("adj counters enable")
1619 self.pg1.generate_remote_hosts(2)
1620
1621 arp1 = VppNeighbor(self,
1622 self.pg1.sw_if_index,
1623 self.pg1.remote_hosts[0].mac,
1624 self.pg1.remote_hosts[0].ip4)
1625 arp1.add_vpp_config()
1626 arp2 = VppNeighbor(self,
1627 self.pg1.sw_if_index,
1628 self.pg1.remote_hosts[1].mac,
1629 self.pg1.remote_hosts[1].ip4)
1630 arp2.add_vpp_config()
1631
1632 p1 = (Ether(dst=self.pg0.local_mac,
1633 src=self.pg0.remote_mac) /
1634 IP(src=self.pg0.remote_ip4,
1635 dst=self.pg1.remote_hosts[0].ip4) /
1636 UDP(sport=1234, dport=1234) /
1637 Raw())
1638 p2 = (Ether(dst=self.pg0.local_mac,
1639 src=self.pg0.remote_mac) /
1640 IP(src=self.pg0.remote_ip4,
1641 dst=self.pg1.remote_hosts[1].ip4) /
1642 UDP(sport=1234, dport=1234) /
1643 Raw())
1644
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001645 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
1646 rx = self.send_and_expect(self.pg0, p2 * NUM_PKTS, self.pg1)
Neale Ranns14260392018-09-28 05:00:57 -07001647
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001648 self.assertEqual(NUM_PKTS, arp1.get_stats()['packets'])
1649 self.assertEqual(NUM_PKTS, arp2.get_stats()['packets'])
Neale Ranns14260392018-09-28 05:00:57 -07001650
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001651 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
1652 self.assertEqual(NUM_PKTS*2, arp1.get_stats()['packets'])
Neale Ranns14260392018-09-28 05:00:57 -07001653
1654 def test_nd_stats(self):
1655 """ ND Counters """
1656
1657 self.vapi.cli("adj counters enable")
1658 self.pg0.generate_remote_hosts(3)
1659
1660 nd1 = VppNeighbor(self,
1661 self.pg0.sw_if_index,
1662 self.pg0.remote_hosts[1].mac,
Neale Ranns37029302018-08-10 05:30:06 -07001663 self.pg0.remote_hosts[1].ip6)
Neale Ranns14260392018-09-28 05:00:57 -07001664 nd1.add_vpp_config()
1665 nd2 = VppNeighbor(self,
1666 self.pg0.sw_if_index,
1667 self.pg0.remote_hosts[2].mac,
Neale Ranns37029302018-08-10 05:30:06 -07001668 self.pg0.remote_hosts[2].ip6)
Neale Ranns14260392018-09-28 05:00:57 -07001669 nd2.add_vpp_config()
1670
1671 p1 = (Ether(dst=self.pg1.local_mac,
1672 src=self.pg1.remote_mac) /
1673 IPv6(src=self.pg1.remote_ip6,
1674 dst=self.pg0.remote_hosts[1].ip6) /
1675 UDP(sport=1234, dport=1234) /
1676 Raw())
1677 p2 = (Ether(dst=self.pg1.local_mac,
1678 src=self.pg1.remote_mac) /
1679 IPv6(src=self.pg1.remote_ip6,
1680 dst=self.pg0.remote_hosts[2].ip6) /
1681 UDP(sport=1234, dport=1234) /
1682 Raw())
1683
1684 rx = self.send_and_expect(self.pg1, p1 * 16, self.pg0)
1685 rx = self.send_and_expect(self.pg1, p2 * 16, self.pg0)
1686
1687 self.assertEqual(16, nd1.get_stats()['packets'])
1688 self.assertEqual(16, nd2.get_stats()['packets'])
1689
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001690 rx = self.send_and_expect(self.pg1, p1 * NUM_PKTS, self.pg0)
1691 self.assertEqual(NUM_PKTS+16, nd1.get_stats()['packets'])
Neale Ranns14260392018-09-28 05:00:57 -07001692
1693
Neale Rannscbe25aa2019-09-30 10:53:31 +00001694class NeighborAgeTestCase(VppTestCase):
1695 """ ARP/ND Aging """
1696
1697 @classmethod
1698 def setUpClass(cls):
1699 super(NeighborAgeTestCase, cls).setUpClass()
1700
1701 @classmethod
1702 def tearDownClass(cls):
1703 super(NeighborAgeTestCase, cls).tearDownClass()
1704
1705 def setUp(self):
1706 super(NeighborAgeTestCase, self).setUp()
1707
1708 self.create_pg_interfaces(range(1))
1709
1710 # pg0 configured with ip4 and 6 addresses used for input
1711 # pg1 configured with ip4 and 6 addresses used for output
1712 # pg2 is unnumbered to pg0
1713 for i in self.pg_interfaces:
1714 i.admin_up()
1715 i.config_ip4()
1716 i.config_ip6()
1717 i.resolve_arp()
1718 i.resolve_ndp()
1719
1720 def tearDown(self):
1721 super(NeighborAgeTestCase, self).tearDown()
1722
1723 for i in self.pg_interfaces:
1724 i.unconfig_ip4()
1725 i.unconfig_ip6()
1726 i.admin_down()
1727
1728 def wait_for_no_nbr(self, intf, address,
1729 n_tries=50, s_time=1):
1730 while (n_tries):
1731 if not find_nbr(self, intf, address):
1732 return True
1733 n_tries = n_tries - 1
1734 self.sleep(s_time)
1735
1736 return False
1737
1738 def verify_arp_req(self, rx, smac, sip, dip):
1739 ether = rx[Ether]
1740 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
1741 self.assertEqual(ether.src, smac)
1742
1743 arp = rx[ARP]
1744 self.assertEqual(arp.hwtype, 1)
1745 self.assertEqual(arp.ptype, 0x800)
1746 self.assertEqual(arp.hwlen, 6)
1747 self.assertEqual(arp.plen, 4)
1748 self.assertEqual(arp.op, arp_opts["who-has"])
1749 self.assertEqual(arp.hwsrc, smac)
1750 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
1751 self.assertEqual(arp.psrc, sip)
1752 self.assertEqual(arp.pdst, dip)
1753
1754 def test_age(self):
1755 """ Aging/Recycle """
1756
1757 self.vapi.cli("set logging unthrottle 0")
1758 self.vapi.cli("set logging size %d" % 0xffff)
1759
1760 self.pg0.generate_remote_hosts(201)
1761
1762 vaf = VppEnum.vl_api_address_family_t
1763
1764 #
1765 # start listening on all interfaces
1766 #
1767 self.pg_enable_capture(self.pg_interfaces)
1768
1769 #
1770 # Set the neighbor configuration:
1771 # limi = 200
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03001772 # age = 0 seconds
Neale Rannscbe25aa2019-09-30 10:53:31 +00001773 # recycle = false
1774 #
1775 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
1776 max_number=200,
1777 max_age=0,
1778 recycle=False)
1779
1780 self.vapi.cli("sh ip neighbor-config")
1781
1782 # add the 198 neighbours that should pass (-1 for one created in setup)
1783 for ii in range(200):
1784 VppNeighbor(self,
1785 self.pg0.sw_if_index,
1786 self.pg0.remote_hosts[ii].mac,
1787 self.pg0.remote_hosts[ii].ip4).add_vpp_config()
1788
1789 # one more neighbor over the limit should fail
1790 with self.vapi.assert_negative_api_retval():
1791 VppNeighbor(self,
1792 self.pg0.sw_if_index,
1793 self.pg0.remote_hosts[200].mac,
1794 self.pg0.remote_hosts[200].ip4).add_vpp_config()
1795
1796 #
1797 # change the config to allow recycling the old neighbors
1798 #
1799 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
1800 max_number=200,
1801 max_age=0,
1802 recycle=True)
1803
1804 # now new additions are allowed
1805 VppNeighbor(self,
1806 self.pg0.sw_if_index,
1807 self.pg0.remote_hosts[200].mac,
1808 self.pg0.remote_hosts[200].ip4).add_vpp_config()
1809
1810 # add the first neighbor we configured has been re-used
1811 self.assertFalse(find_nbr(self,
1812 self.pg0.sw_if_index,
1813 self.pg0.remote_hosts[0].ip4))
1814 self.assertTrue(find_nbr(self,
1815 self.pg0.sw_if_index,
1816 self.pg0.remote_hosts[200].ip4))
1817
1818 #
1819 # change the config to age old neighbors
1820 #
1821 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
1822 max_number=200,
1823 max_age=2,
1824 recycle=True)
1825
1826 self.vapi.cli("sh ip4 neighbor-sorted")
1827
1828 #
1829 # expect probes from all these ARP entries as they age
1830 # 3 probes for each neighbor 3*200 = 600
1831 rxs = self.pg0.get_capture(600, timeout=8)
1832
1833 for ii in range(3):
1834 for jj in range(200):
1835 rx = rxs[ii*200 + jj]
1836 # rx.show()
1837
1838 #
1839 # 3 probes sent then 1 more second to see if a reply comes, before
1840 # they age out
1841 #
1842 for jj in range(1, 201):
1843 self.wait_for_no_nbr(self.pg0.sw_if_index,
1844 self.pg0.remote_hosts[jj].ip4)
1845
1846 self.assertFalse(self.vapi.ip_neighbor_dump(sw_if_index=0xffffffff,
1847 af=vaf.ADDRESS_IP4))
1848
1849 #
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03001850 # load up some neighbours again with 2s aging enabled
1851 # they should be removed after 10s (2s age + 4s for probes + gap)
1852 #
1853 for ii in range(10):
1854 VppNeighbor(self,
1855 self.pg0.sw_if_index,
1856 self.pg0.remote_hosts[ii].mac,
1857 self.pg0.remote_hosts[ii].ip4).add_vpp_config()
1858 self.sleep(10)
1859 self.assertFalse(self.vapi.ip_neighbor_dump(sw_if_index=0xffffffff,
1860 af=vaf.ADDRESS_IP4))
1861
1862 #
1863 # check if we can set age and recycle with empty neighbor list
1864 #
1865 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
1866 max_number=200,
1867 max_age=1000,
1868 recycle=True)
1869
1870 #
Neale Rannscbe25aa2019-09-30 10:53:31 +00001871 # load up some neighbours again, then disable the aging
1872 # they should still be there in 10 seconds time
1873 #
1874 for ii in range(10):
1875 VppNeighbor(self,
1876 self.pg0.sw_if_index,
1877 self.pg0.remote_hosts[ii].mac,
1878 self.pg0.remote_hosts[ii].ip4).add_vpp_config()
1879 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
1880 max_number=200,
1881 max_age=0,
1882 recycle=False)
1883
1884 self.sleep(10)
1885 self.assertTrue(find_nbr(self,
1886 self.pg0.sw_if_index,
1887 self.pg0.remote_hosts[0].ip4))
1888
1889
Neale Rannsc87fbb42020-04-02 17:08:28 +00001890class NeighborReplaceTestCase(VppTestCase):
1891 """ ARP/ND Replacement """
1892
1893 @classmethod
1894 def setUpClass(cls):
1895 super(NeighborReplaceTestCase, cls).setUpClass()
1896
1897 @classmethod
1898 def tearDownClass(cls):
1899 super(NeighborReplaceTestCase, cls).tearDownClass()
1900
1901 def setUp(self):
1902 super(NeighborReplaceTestCase, self).setUp()
1903
1904 self.create_pg_interfaces(range(4))
1905
1906 # pg0 configured with ip4 and 6 addresses used for input
1907 # pg1 configured with ip4 and 6 addresses used for output
1908 # pg2 is unnumbered to pg0
1909 for i in self.pg_interfaces:
1910 i.admin_up()
1911 i.config_ip4()
1912 i.config_ip6()
1913 i.resolve_arp()
1914 i.resolve_ndp()
1915
1916 def tearDown(self):
1917 super(NeighborReplaceTestCase, self).tearDown()
1918
1919 for i in self.pg_interfaces:
1920 i.unconfig_ip4()
1921 i.unconfig_ip6()
1922 i.admin_down()
1923
1924 def test_replace(self):
1925 """ replace """
1926
1927 N_HOSTS = 16
1928
1929 for i in self.pg_interfaces:
1930 i.generate_remote_hosts(N_HOSTS)
1931 i.configure_ipv4_neighbors()
1932 i.configure_ipv6_neighbors()
1933
1934 # replace them all
1935 self.vapi.ip_neighbor_replace_begin()
1936 self.vapi.ip_neighbor_replace_end()
1937
1938 for i in self.pg_interfaces:
1939 for h in range(N_HOSTS):
1940 self.assertFalse(find_nbr(self,
1941 self.pg0.sw_if_index,
1942 self.pg0.remote_hosts[h].ip4))
1943 self.assertFalse(find_nbr(self,
1944 self.pg0.sw_if_index,
1945 self.pg0.remote_hosts[h].ip6))
1946
1947 #
1948 # and them all back via the API
1949 #
1950 for i in self.pg_interfaces:
1951 for h in range(N_HOSTS):
1952 VppNeighbor(self,
1953 i.sw_if_index,
1954 i.remote_hosts[h].mac,
1955 i.remote_hosts[h].ip4).add_vpp_config()
1956 VppNeighbor(self,
1957 i.sw_if_index,
1958 i.remote_hosts[h].mac,
1959 i.remote_hosts[h].ip6).add_vpp_config()
1960
1961 #
1962 # begin the replacement again, this time touch some
1963 # the neighbours on pg1 so they are not deleted
1964 #
1965 self.vapi.ip_neighbor_replace_begin()
1966
1967 # update from the API all neighbours on pg1
1968 for h in range(N_HOSTS):
1969 VppNeighbor(self,
1970 self.pg1.sw_if_index,
1971 self.pg1.remote_hosts[h].mac,
1972 self.pg1.remote_hosts[h].ip4).add_vpp_config()
1973 VppNeighbor(self,
1974 self.pg1.sw_if_index,
1975 self.pg1.remote_hosts[h].mac,
1976 self.pg1.remote_hosts[h].ip6).add_vpp_config()
1977
1978 # update from the data-plane all neighbours on pg3
1979 self.pg3.configure_ipv4_neighbors()
1980 self.pg3.configure_ipv6_neighbors()
1981
1982 # complete the replacement
1983 self.logger.info(self.vapi.cli("sh ip neighbors"))
1984 self.vapi.ip_neighbor_replace_end()
1985
1986 for i in self.pg_interfaces:
1987 if i == self.pg1 or i == self.pg3:
1988 # neighbours on pg1 and pg3 are still present
1989 for h in range(N_HOSTS):
1990 self.assertTrue(find_nbr(self,
1991 i.sw_if_index,
1992 i.remote_hosts[h].ip4))
1993 self.assertTrue(find_nbr(self,
1994 i.sw_if_index,
1995 i.remote_hosts[h].ip6))
1996 else:
1997 # all other neighbours are toast
1998 for h in range(N_HOSTS):
1999 self.assertFalse(find_nbr(self,
2000 i.sw_if_index,
2001 i.remote_hosts[h].ip4))
2002 self.assertFalse(find_nbr(self,
2003 i.sw_if_index,
2004 i.remote_hosts[h].ip6))
2005
2006
Neale Ranns240dcb22020-04-23 09:04:59 +00002007class NeighborFlush(VppTestCase):
2008 """ Neighbor Flush """
2009
2010 @classmethod
2011 def setUpClass(cls):
2012 super(NeighborFlush, cls).setUpClass()
2013
2014 @classmethod
2015 def tearDownClass(cls):
2016 super(NeighborFlush, cls).tearDownClass()
2017
2018 def setUp(self):
2019 super(NeighborFlush, self).setUp()
2020
2021 self.create_pg_interfaces(range(2))
2022
2023 for i in self.pg_interfaces:
2024 i.admin_up()
2025 i.config_ip4()
2026 i.config_ip6()
2027 i.resolve_arp()
2028 i.resolve_ndp()
2029
2030 def tearDown(self):
2031 super(NeighborFlush, self).tearDown()
2032
2033 for i in self.pg_interfaces:
2034 i.unconfig_ip4()
2035 i.unconfig_ip6()
2036 i.admin_down()
2037
2038 def test_flush(self):
2039 """ Neighbour Flush """
2040
2041 e = VppEnum
2042 nf = e.vl_api_ip_neighbor_flags_t
2043 af = e.vl_api_address_family_t
2044 N_HOSTS = 16
2045 static = [False, True]
2046 self.pg0.generate_remote_hosts(N_HOSTS)
2047 self.pg1.generate_remote_hosts(N_HOSTS)
2048
2049 for s in static:
2050 # a few v4 and v6 dynamic neoghbors
2051 for n in range(N_HOSTS):
2052 VppNeighbor(self,
2053 self.pg0.sw_if_index,
2054 self.pg0.remote_hosts[n].mac,
2055 self.pg0.remote_hosts[n].ip4,
2056 is_static=s).add_vpp_config()
2057 VppNeighbor(self,
2058 self.pg1.sw_if_index,
2059 self.pg1.remote_hosts[n].mac,
2060 self.pg1.remote_hosts[n].ip6,
2061 is_static=s).add_vpp_config()
2062
2063 # flush the interfaces individually
2064 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, self.pg0.sw_if_index)
2065
2066 # check we haven't flushed that which we shouldn't
2067 for n in range(N_HOSTS):
2068 self.assertTrue(find_nbr(self,
2069 self.pg1.sw_if_index,
2070 self.pg1.remote_hosts[n].ip6,
2071 is_static=s))
2072
2073 self.vapi.ip_neighbor_flush(af.ADDRESS_IP6, self.pg1.sw_if_index)
2074
2075 for n in range(N_HOSTS):
2076 self.assertFalse(find_nbr(self,
2077 self.pg0.sw_if_index,
2078 self.pg0.remote_hosts[n].ip4))
2079 self.assertFalse(find_nbr(self,
2080 self.pg1.sw_if_index,
2081 self.pg1.remote_hosts[n].ip6))
2082
2083 # add the nieghbours back
2084 for n in range(N_HOSTS):
2085 VppNeighbor(self,
2086 self.pg0.sw_if_index,
2087 self.pg0.remote_hosts[n].mac,
2088 self.pg0.remote_hosts[n].ip4,
2089 is_static=s).add_vpp_config()
2090 VppNeighbor(self,
2091 self.pg1.sw_if_index,
2092 self.pg1.remote_hosts[n].mac,
2093 self.pg1.remote_hosts[n].ip6,
2094 is_static=s).add_vpp_config()
2095
2096 self.logger.info(self.vapi.cli("sh ip neighbor"))
2097
2098 # flush both interfaces at the same time
2099 self.vapi.ip_neighbor_flush(af.ADDRESS_IP6, 0xffffffff)
2100
2101 # check we haven't flushed that which we shouldn't
2102 for n in range(N_HOSTS):
2103 self.assertTrue(find_nbr(self,
2104 self.pg0.sw_if_index,
2105 self.pg0.remote_hosts[n].ip4,
2106 is_static=s))
2107
2108 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, 0xffffffff)
2109
2110 for n in range(N_HOSTS):
2111 self.assertFalse(find_nbr(self,
2112 self.pg0.sw_if_index,
2113 self.pg0.remote_hosts[n].ip4))
2114 self.assertFalse(find_nbr(self,
2115 self.pg1.sw_if_index,
2116 self.pg1.remote_hosts[n].ip6))
2117
2118
Neale Ranns37be7362017-02-21 17:30:26 -08002119if __name__ == '__main__':
2120 unittest.main(testRunner=VppTestRunner)