blob: dfefb151091426b49797c83c2efe5ab2b52b5881 [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
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001250 def test_arp_static_replace_dynamic_same_mac(self):
1251 """ ARP Static can replace Dynamic (same mac) """
1252 self.pg2.generate_remote_hosts(1)
1253
1254 dyn_arp = VppNeighbor(self,
1255 self.pg2.sw_if_index,
1256 self.pg2.remote_hosts[0].mac,
1257 self.pg2.remote_hosts[0].ip4)
1258 static_arp = VppNeighbor(self,
1259 self.pg2.sw_if_index,
1260 self.pg2.remote_hosts[0].mac,
1261 self.pg2.remote_hosts[0].ip4,
1262 is_static=1)
1263
1264 #
1265 # Add a dynamic ARP entry
1266 #
1267 dyn_arp.add_vpp_config()
1268
1269 #
1270 # We should find the dynamic nbr
1271 #
1272 self.assertFalse(find_nbr(self,
1273 self.pg2.sw_if_index,
1274 self.pg2.remote_hosts[0].ip4,
1275 is_static=1))
1276 self.assertTrue(find_nbr(self,
1277 self.pg2.sw_if_index,
1278 self.pg2.remote_hosts[0].ip4,
1279 is_static=0,
1280 mac=self.pg2.remote_hosts[0].mac))
1281
1282 #
1283 # Add a static ARP entry with the same mac
1284 #
1285 static_arp.add_vpp_config()
1286
1287 #
1288 # We should now find the static nbr with the same mac
1289 #
1290 self.assertFalse(find_nbr(self,
1291 self.pg2.sw_if_index,
1292 self.pg2.remote_hosts[0].ip4,
1293 is_static=0))
1294 self.assertTrue(find_nbr(self,
1295 self.pg2.sw_if_index,
1296 self.pg2.remote_hosts[0].ip4,
1297 is_static=1,
1298 mac=self.pg2.remote_hosts[0].mac))
1299
1300 #
1301 # clean-up
1302 #
1303 static_arp.remove_vpp_config()
1304
1305 def test_arp_static_replace_dynamic_diff_mac(self):
1306 """ ARP Static can replace Dynamic (diff mac) """
1307 self.pg2.generate_remote_hosts(2)
1308
1309 dyn_arp = VppNeighbor(self,
1310 self.pg2.sw_if_index,
1311 self.pg2.remote_hosts[0].mac,
1312 self.pg2.remote_hosts[0].ip4)
1313 static_arp = VppNeighbor(self,
1314 self.pg2.sw_if_index,
1315 self.pg2.remote_hosts[1].mac,
1316 self.pg2.remote_hosts[0].ip4,
1317 is_static=1)
1318
1319 #
1320 # Add a dynamic ARP entry
1321 #
1322 dyn_arp.add_vpp_config()
1323
1324 #
1325 # We should find the dynamic nbr
1326 #
1327 self.assertFalse(find_nbr(self,
1328 self.pg2.sw_if_index,
1329 self.pg2.remote_hosts[0].ip4,
1330 is_static=1))
1331 self.assertTrue(find_nbr(self,
1332 self.pg2.sw_if_index,
1333 self.pg2.remote_hosts[0].ip4,
1334 is_static=0,
1335 mac=self.pg2.remote_hosts[0].mac))
1336
1337 #
1338 # Add a static ARP entry with a changed mac
1339 #
1340 static_arp.add_vpp_config()
1341
1342 #
1343 # We should now find the static nbr with a changed mac
1344 #
1345 self.assertFalse(find_nbr(self,
1346 self.pg2.sw_if_index,
1347 self.pg2.remote_hosts[0].ip4,
1348 is_static=0))
1349 self.assertTrue(find_nbr(self,
1350 self.pg2.sw_if_index,
1351 self.pg2.remote_hosts[0].ip4,
1352 is_static=1,
1353 mac=self.pg2.remote_hosts[1].mac))
1354
1355 #
1356 # clean-up
1357 #
1358 static_arp.remove_vpp_config()
1359
Neale Rannsc819fc62018-02-16 02:44:05 -08001360 def test_arp_incomplete(self):
1361 """ ARP Incomplete"""
1362 self.pg1.generate_remote_hosts(3)
1363
1364 p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1365 IP(src=self.pg0.remote_ip4,
1366 dst=self.pg1.remote_hosts[1].ip4) /
1367 UDP(sport=1234, dport=1234) /
1368 Raw())
1369 p1 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1370 IP(src=self.pg0.remote_ip4,
1371 dst=self.pg1.remote_hosts[2].ip4) /
1372 UDP(sport=1234, dport=1234) /
1373 Raw())
1374
1375 #
1376 # a packet to an unresolved destination generates an ARP request
1377 #
1378 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1379 self.verify_arp_req(rx[0],
1380 self.pg1.local_mac,
1381 self.pg1.local_ip4,
1382 self.pg1._remote_hosts[1].ip4)
1383
1384 #
1385 # add a neighbour for remote host 1
1386 #
1387 static_arp = VppNeighbor(self,
1388 self.pg1.sw_if_index,
1389 self.pg1.remote_hosts[1].mac,
1390 self.pg1.remote_hosts[1].ip4,
1391 is_static=1)
1392 static_arp.add_vpp_config()
1393
1394 #
1395 # change the interface's MAC
1396 #
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001397 mac = [scapy.compat.chb(0x00), scapy.compat.chb(0x00),
1398 scapy.compat.chb(0x00), scapy.compat.chb(0x33),
1399 scapy.compat.chb(0x33), scapy.compat.chb(0x33)]
Neale Rannsc819fc62018-02-16 02:44:05 -08001400 mac_string = ''.join(mac)
1401
1402 self.vapi.sw_interface_set_mac_address(self.pg1.sw_if_index,
1403 mac_string)
1404
1405 #
1406 # now ARP requests come from the new source mac
1407 #
1408 rx = self.send_and_expect(self.pg0, [p1], self.pg1)
1409 self.verify_arp_req(rx[0],
1410 "00:00:00:33:33:33",
1411 self.pg1.local_ip4,
1412 self.pg1._remote_hosts[2].ip4)
1413
1414 #
1415 # packets to the resolved host also have the new source mac
1416 #
1417 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1418 self.verify_ip(rx[0],
1419 "00:00:00:33:33:33",
1420 self.pg1.remote_hosts[1].mac,
1421 self.pg0.remote_ip4,
1422 self.pg1.remote_hosts[1].ip4)
1423
1424 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001425 # set the mac address on the interface that does not have a
Neale Rannsc819fc62018-02-16 02:44:05 -08001426 # configured subnet and thus no glean
1427 #
1428 self.vapi.sw_interface_set_mac_address(self.pg2.sw_if_index,
1429 mac_string)
1430
Neale Ranns59ae61e2018-06-07 18:09:49 -07001431 def test_garp(self):
1432 """ GARP """
1433
1434 #
1435 # Generate some hosts on the LAN
1436 #
1437 self.pg1.generate_remote_hosts(4)
Neale Ranns22eefd72020-09-23 11:25:21 +00001438 self.pg2.generate_remote_hosts(4)
Neale Ranns59ae61e2018-06-07 18:09:49 -07001439
1440 #
1441 # And an ARP entry
1442 #
1443 arp = VppNeighbor(self,
1444 self.pg1.sw_if_index,
1445 self.pg1.remote_hosts[1].mac,
1446 self.pg1.remote_hosts[1].ip4)
1447 arp.add_vpp_config()
1448
1449 self.assertTrue(find_nbr(self,
1450 self.pg1.sw_if_index,
1451 self.pg1.remote_hosts[1].ip4,
1452 mac=self.pg1.remote_hosts[1].mac))
1453
1454 #
1455 # Send a GARP (request) to swap the host 1's address to that of host 2
1456 #
1457 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1458 src=self.pg1.remote_hosts[2].mac) /
1459 ARP(op="who-has",
1460 hwdst=self.pg1.local_mac,
1461 hwsrc=self.pg1.remote_hosts[2].mac,
1462 pdst=self.pg1.remote_hosts[1].ip4,
1463 psrc=self.pg1.remote_hosts[1].ip4))
1464
1465 self.pg1.add_stream(p1)
1466 self.pg_enable_capture(self.pg_interfaces)
1467 self.pg_start()
1468
1469 self.assertTrue(find_nbr(self,
1470 self.pg1.sw_if_index,
1471 self.pg1.remote_hosts[1].ip4,
1472 mac=self.pg1.remote_hosts[2].mac))
1473
1474 #
1475 # Send a GARP (reply) to swap the host 1's address to that of host 3
1476 #
1477 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1478 src=self.pg1.remote_hosts[3].mac) /
1479 ARP(op="is-at",
1480 hwdst=self.pg1.local_mac,
1481 hwsrc=self.pg1.remote_hosts[3].mac,
1482 pdst=self.pg1.remote_hosts[1].ip4,
1483 psrc=self.pg1.remote_hosts[1].ip4))
1484
1485 self.pg1.add_stream(p1)
1486 self.pg_enable_capture(self.pg_interfaces)
1487 self.pg_start()
1488
1489 self.assertTrue(find_nbr(self,
1490 self.pg1.sw_if_index,
1491 self.pg1.remote_hosts[1].ip4,
1492 mac=self.pg1.remote_hosts[3].mac))
1493
1494 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001495 # GARPs (request nor replies) for host we don't know yet
Neale Ranns59ae61e2018-06-07 18:09:49 -07001496 # don't result in new neighbour entries
1497 #
1498 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1499 src=self.pg1.remote_hosts[3].mac) /
1500 ARP(op="who-has",
1501 hwdst=self.pg1.local_mac,
1502 hwsrc=self.pg1.remote_hosts[3].mac,
1503 pdst=self.pg1.remote_hosts[2].ip4,
1504 psrc=self.pg1.remote_hosts[2].ip4))
1505
1506 self.pg1.add_stream(p1)
1507 self.pg_enable_capture(self.pg_interfaces)
1508 self.pg_start()
1509
1510 self.assertFalse(find_nbr(self,
1511 self.pg1.sw_if_index,
1512 self.pg1.remote_hosts[2].ip4))
1513
1514 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1515 src=self.pg1.remote_hosts[3].mac) /
1516 ARP(op="is-at",
1517 hwdst=self.pg1.local_mac,
1518 hwsrc=self.pg1.remote_hosts[3].mac,
1519 pdst=self.pg1.remote_hosts[2].ip4,
1520 psrc=self.pg1.remote_hosts[2].ip4))
1521
1522 self.pg1.add_stream(p1)
1523 self.pg_enable_capture(self.pg_interfaces)
1524 self.pg_start()
1525
1526 self.assertFalse(find_nbr(self,
1527 self.pg1.sw_if_index,
1528 self.pg1.remote_hosts[2].ip4))
1529
Neale Ranns22eefd72020-09-23 11:25:21 +00001530 #
1531 # IP address in different subnets are not learnt
1532 #
1533 self.pg2.configure_ipv4_neighbors()
1534
1535 for op in ["is-at", "who-has"]:
1536 p1 = [(Ether(dst="ff:ff:ff:ff:ff:ff",
1537 src=self.pg2.remote_hosts[1].mac) /
1538 ARP(op=op,
1539 hwdst=self.pg2.local_mac,
1540 hwsrc=self.pg2.remote_hosts[1].mac,
1541 pdst=self.pg2.remote_hosts[1].ip4,
1542 psrc=self.pg2.remote_hosts[1].ip4)),
1543 (Ether(dst="ff:ff:ff:ff:ff:ff",
1544 src=self.pg2.remote_hosts[1].mac) /
1545 ARP(op=op,
1546 hwdst="ff:ff:ff:ff:ff:ff",
1547 hwsrc=self.pg2.remote_hosts[1].mac,
1548 pdst=self.pg2.remote_hosts[1].ip4,
1549 psrc=self.pg2.remote_hosts[1].ip4))]
1550
1551 self.send_and_assert_no_replies(self.pg1, p1)
1552 self.assertFalse(find_nbr(self,
1553 self.pg1.sw_if_index,
1554 self.pg2.remote_hosts[1].ip4))
1555
1556 # they are all dropped because the subnet's don't match
1557 self.assertEqual(4, self.statistics.get_err_counter(
1558 "/err/arp-reply/IP4 destination address not local to subnet"))
1559
Neale Rannsc8352bc2018-08-29 10:23:58 -07001560 def test_arp_incomplete(self):
Neale Ranns14260392018-09-28 05:00:57 -07001561 """ Incomplete Entries """
Neale Rannsc8352bc2018-08-29 10:23:58 -07001562
1563 #
Neale Rannscd35e532018-08-31 02:51:45 -07001564 # ensure that we throttle the ARP and ND requests
Neale Rannsc8352bc2018-08-29 10:23:58 -07001565 #
1566 self.pg0.generate_remote_hosts(2)
1567
Neale Rannscd35e532018-08-31 02:51:45 -07001568 #
1569 # IPv4/ARP
1570 #
Neale Rannsc8352bc2018-08-29 10:23:58 -07001571 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1572 [VppRoutePath(self.pg0.remote_hosts[1].ip4,
Neale Rannscd35e532018-08-31 02:51:45 -07001573 self.pg0.sw_if_index)])
Neale Rannsc8352bc2018-08-29 10:23:58 -07001574 ip_10_0_0_1.add_vpp_config()
1575
1576 p1 = (Ether(dst=self.pg1.local_mac,
1577 src=self.pg1.remote_mac) /
1578 IP(src=self.pg1.remote_ip4,
1579 dst="10.0.0.1") /
1580 UDP(sport=1234, dport=1234) /
1581 Raw())
1582
1583 self.pg1.add_stream(p1 * 257)
1584 self.pg_enable_capture(self.pg_interfaces)
1585 self.pg_start()
1586 rx = self.pg0._get_capture(1)
1587
1588 #
1589 # how many we get is going to be dependent on the time for packet
1590 # processing but it should be small
1591 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001592 self.assertLess(len(rx), 64)
Neale Rannsc8352bc2018-08-29 10:23:58 -07001593
Neale Rannscd35e532018-08-31 02:51:45 -07001594 #
1595 # IPv6/ND
1596 #
1597 ip_10_1 = VppIpRoute(self, "10::1", 128,
1598 [VppRoutePath(self.pg0.remote_hosts[1].ip6,
1599 self.pg0.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07001600 proto=DpoProto.DPO_PROTO_IP6)])
Neale Rannscd35e532018-08-31 02:51:45 -07001601 ip_10_1.add_vpp_config()
1602
1603 p1 = (Ether(dst=self.pg1.local_mac,
1604 src=self.pg1.remote_mac) /
1605 IPv6(src=self.pg1.remote_ip6,
1606 dst="10::1") /
1607 UDP(sport=1234, dport=1234) /
1608 Raw())
1609
1610 self.pg1.add_stream(p1 * 257)
1611 self.pg_enable_capture(self.pg_interfaces)
1612 self.pg_start()
1613 rx = self.pg0._get_capture(1)
1614
1615 #
1616 # how many we get is going to be dependent on the time for packet
1617 # processing but it should be small
1618 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001619 self.assertLess(len(rx), 64)
Neale Rannscd35e532018-08-31 02:51:45 -07001620
Neale Ranns7425f922019-01-23 00:36:16 -08001621 def test_arp_forus(self):
1622 """ ARP for for-us """
1623
1624 #
1625 # Test that VPP responds with ARP requests to addresses that
1626 # are connected and local routes.
1627 # Use one of the 'remote' addresses in the subnet as a local address
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001628 # The intention of this route is that it then acts like a secondary
Neale Ranns7425f922019-01-23 00:36:16 -08001629 # address added to an interface
1630 #
1631 self.pg0.generate_remote_hosts(2)
1632
Neale Ranns097fa662018-05-01 05:17:55 -07001633 forus = VppIpRoute(
1634 self, self.pg0.remote_hosts[1].ip4, 32,
1635 [VppRoutePath("0.0.0.0",
1636 self.pg0.sw_if_index,
1637 type=FibPathType.FIB_PATH_TYPE_LOCAL)])
Neale Ranns7425f922019-01-23 00:36:16 -08001638 forus.add_vpp_config()
1639
1640 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
1641 src=self.pg0.remote_mac) /
1642 ARP(op="who-has",
1643 hwdst=self.pg0.local_mac,
1644 hwsrc=self.pg0.remote_mac,
1645 pdst=self.pg0.remote_hosts[1].ip4,
1646 psrc=self.pg0.remote_ip4))
1647
1648 rx = self.send_and_expect(self.pg0, [p], self.pg0)
1649
1650 self.verify_arp_resp(rx[0],
1651 self.pg0.local_mac,
1652 self.pg0.remote_mac,
1653 self.pg0.remote_hosts[1].ip4,
1654 self.pg0.remote_ip4)
1655
Neale Rannsfca3c6a2019-12-31 03:49:34 +00001656 def test_arp_table_swap(self):
1657 #
1658 # Generate some hosts on the LAN
1659 #
1660 N_NBRS = 4
1661 self.pg1.generate_remote_hosts(N_NBRS)
1662
1663 for n in range(N_NBRS):
1664 # a route thru each neighbour
1665 VppIpRoute(self, "10.0.0.%d" % n, 32,
1666 [VppRoutePath(self.pg1.remote_hosts[n].ip4,
1667 self.pg1.sw_if_index)]).add_vpp_config()
1668
1669 # resolve each neighbour
1670 p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1671 ARP(op="is-at", hwdst=self.pg1.local_mac,
1672 hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
1673 psrc=self.pg1.remote_hosts[n].ip4))
1674
1675 self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
1676
1677 self.logger.info(self.vapi.cli("sh ip neighbors"))
1678
1679 #
1680 # swap the table pg1 is in
1681 #
1682 table = VppIpTable(self, 100).add_vpp_config()
1683
1684 self.pg1.unconfig_ip4()
1685 self.pg1.set_table_ip4(100)
1686 self.pg1.config_ip4()
1687
1688 #
1689 # all neighbours are cleared
1690 #
1691 for n in range(N_NBRS):
1692 self.assertFalse(find_nbr(self,
1693 self.pg1.sw_if_index,
1694 self.pg1.remote_hosts[n].ip4))
1695
1696 #
1697 # packets to all neighbours generate ARP requests
1698 #
1699 for n in range(N_NBRS):
1700 # a route thru each neighbour
1701 VppIpRoute(self, "10.0.0.%d" % n, 32,
1702 [VppRoutePath(self.pg1.remote_hosts[n].ip4,
1703 self.pg1.sw_if_index)],
1704 table_id=100).add_vpp_config()
1705
1706 p = (Ether(src=self.pg1.remote_hosts[n].mac,
1707 dst=self.pg1.local_mac) /
1708 IP(src=self.pg1.remote_hosts[n].ip4,
1709 dst="10.0.0.%d" % n) /
1710 Raw(b'0x5' * 100))
1711 rxs = self.send_and_expect(self.pg1, [p], self.pg1)
1712 for rx in rxs:
1713 self.verify_arp_req(rx,
1714 self.pg1.local_mac,
1715 self.pg1.local_ip4,
1716 self.pg1.remote_hosts[n].ip4)
1717
1718 self.pg1.unconfig_ip4()
1719 self.pg1.set_table_ip4(0)
1720
Neale Rannsdcd6d622017-05-26 02:59:16 -07001721
Neale Ranns14260392018-09-28 05:00:57 -07001722class NeighborStatsTestCase(VppTestCase):
Neale Ranns37029302018-08-10 05:30:06 -07001723 """ ARP/ND Counters """
Neale Ranns14260392018-09-28 05:00:57 -07001724
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001725 @classmethod
1726 def setUpClass(cls):
1727 super(NeighborStatsTestCase, cls).setUpClass()
1728
1729 @classmethod
1730 def tearDownClass(cls):
1731 super(NeighborStatsTestCase, cls).tearDownClass()
1732
Neale Ranns14260392018-09-28 05:00:57 -07001733 def setUp(self):
1734 super(NeighborStatsTestCase, self).setUp()
1735
1736 self.create_pg_interfaces(range(2))
1737
1738 # pg0 configured with ip4 and 6 addresses used for input
1739 # pg1 configured with ip4 and 6 addresses used for output
1740 # pg2 is unnumbered to pg0
1741 for i in self.pg_interfaces:
1742 i.admin_up()
1743 i.config_ip4()
1744 i.config_ip6()
1745 i.resolve_arp()
1746 i.resolve_ndp()
1747
1748 def tearDown(self):
1749 super(NeighborStatsTestCase, self).tearDown()
1750
1751 for i in self.pg_interfaces:
1752 i.unconfig_ip4()
1753 i.unconfig_ip6()
1754 i.admin_down()
1755
1756 def test_arp_stats(self):
1757 """ ARP Counters """
1758
1759 self.vapi.cli("adj counters enable")
1760 self.pg1.generate_remote_hosts(2)
1761
1762 arp1 = VppNeighbor(self,
1763 self.pg1.sw_if_index,
1764 self.pg1.remote_hosts[0].mac,
1765 self.pg1.remote_hosts[0].ip4)
1766 arp1.add_vpp_config()
1767 arp2 = VppNeighbor(self,
1768 self.pg1.sw_if_index,
1769 self.pg1.remote_hosts[1].mac,
1770 self.pg1.remote_hosts[1].ip4)
1771 arp2.add_vpp_config()
1772
1773 p1 = (Ether(dst=self.pg0.local_mac,
1774 src=self.pg0.remote_mac) /
1775 IP(src=self.pg0.remote_ip4,
1776 dst=self.pg1.remote_hosts[0].ip4) /
1777 UDP(sport=1234, dport=1234) /
1778 Raw())
1779 p2 = (Ether(dst=self.pg0.local_mac,
1780 src=self.pg0.remote_mac) /
1781 IP(src=self.pg0.remote_ip4,
1782 dst=self.pg1.remote_hosts[1].ip4) /
1783 UDP(sport=1234, dport=1234) /
1784 Raw())
1785
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001786 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
1787 rx = self.send_and_expect(self.pg0, p2 * NUM_PKTS, self.pg1)
Neale Ranns14260392018-09-28 05:00:57 -07001788
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001789 self.assertEqual(NUM_PKTS, arp1.get_stats()['packets'])
1790 self.assertEqual(NUM_PKTS, arp2.get_stats()['packets'])
Neale Ranns14260392018-09-28 05:00:57 -07001791
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001792 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
1793 self.assertEqual(NUM_PKTS*2, arp1.get_stats()['packets'])
Neale Ranns14260392018-09-28 05:00:57 -07001794
1795 def test_nd_stats(self):
1796 """ ND Counters """
1797
1798 self.vapi.cli("adj counters enable")
1799 self.pg0.generate_remote_hosts(3)
1800
1801 nd1 = VppNeighbor(self,
1802 self.pg0.sw_if_index,
1803 self.pg0.remote_hosts[1].mac,
Neale Ranns37029302018-08-10 05:30:06 -07001804 self.pg0.remote_hosts[1].ip6)
Neale Ranns14260392018-09-28 05:00:57 -07001805 nd1.add_vpp_config()
1806 nd2 = VppNeighbor(self,
1807 self.pg0.sw_if_index,
1808 self.pg0.remote_hosts[2].mac,
Neale Ranns37029302018-08-10 05:30:06 -07001809 self.pg0.remote_hosts[2].ip6)
Neale Ranns14260392018-09-28 05:00:57 -07001810 nd2.add_vpp_config()
1811
1812 p1 = (Ether(dst=self.pg1.local_mac,
1813 src=self.pg1.remote_mac) /
1814 IPv6(src=self.pg1.remote_ip6,
1815 dst=self.pg0.remote_hosts[1].ip6) /
1816 UDP(sport=1234, dport=1234) /
1817 Raw())
1818 p2 = (Ether(dst=self.pg1.local_mac,
1819 src=self.pg1.remote_mac) /
1820 IPv6(src=self.pg1.remote_ip6,
1821 dst=self.pg0.remote_hosts[2].ip6) /
1822 UDP(sport=1234, dport=1234) /
1823 Raw())
1824
1825 rx = self.send_and_expect(self.pg1, p1 * 16, self.pg0)
1826 rx = self.send_and_expect(self.pg1, p2 * 16, self.pg0)
1827
1828 self.assertEqual(16, nd1.get_stats()['packets'])
1829 self.assertEqual(16, nd2.get_stats()['packets'])
1830
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001831 rx = self.send_and_expect(self.pg1, p1 * NUM_PKTS, self.pg0)
1832 self.assertEqual(NUM_PKTS+16, nd1.get_stats()['packets'])
Neale Ranns14260392018-09-28 05:00:57 -07001833
1834
Neale Rannscbe25aa2019-09-30 10:53:31 +00001835class NeighborAgeTestCase(VppTestCase):
1836 """ ARP/ND Aging """
1837
1838 @classmethod
1839 def setUpClass(cls):
1840 super(NeighborAgeTestCase, cls).setUpClass()
1841
1842 @classmethod
1843 def tearDownClass(cls):
1844 super(NeighborAgeTestCase, cls).tearDownClass()
1845
1846 def setUp(self):
1847 super(NeighborAgeTestCase, self).setUp()
1848
1849 self.create_pg_interfaces(range(1))
1850
1851 # pg0 configured with ip4 and 6 addresses used for input
1852 # pg1 configured with ip4 and 6 addresses used for output
1853 # pg2 is unnumbered to pg0
1854 for i in self.pg_interfaces:
1855 i.admin_up()
1856 i.config_ip4()
1857 i.config_ip6()
1858 i.resolve_arp()
1859 i.resolve_ndp()
1860
1861 def tearDown(self):
1862 super(NeighborAgeTestCase, self).tearDown()
1863
1864 for i in self.pg_interfaces:
1865 i.unconfig_ip4()
1866 i.unconfig_ip6()
1867 i.admin_down()
1868
1869 def wait_for_no_nbr(self, intf, address,
1870 n_tries=50, s_time=1):
1871 while (n_tries):
1872 if not find_nbr(self, intf, address):
1873 return True
1874 n_tries = n_tries - 1
1875 self.sleep(s_time)
1876
1877 return False
1878
1879 def verify_arp_req(self, rx, smac, sip, dip):
1880 ether = rx[Ether]
1881 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
1882 self.assertEqual(ether.src, smac)
1883
1884 arp = rx[ARP]
1885 self.assertEqual(arp.hwtype, 1)
1886 self.assertEqual(arp.ptype, 0x800)
1887 self.assertEqual(arp.hwlen, 6)
1888 self.assertEqual(arp.plen, 4)
1889 self.assertEqual(arp.op, arp_opts["who-has"])
1890 self.assertEqual(arp.hwsrc, smac)
1891 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
1892 self.assertEqual(arp.psrc, sip)
1893 self.assertEqual(arp.pdst, dip)
1894
1895 def test_age(self):
1896 """ Aging/Recycle """
1897
1898 self.vapi.cli("set logging unthrottle 0")
1899 self.vapi.cli("set logging size %d" % 0xffff)
1900
1901 self.pg0.generate_remote_hosts(201)
1902
1903 vaf = VppEnum.vl_api_address_family_t
1904
1905 #
1906 # start listening on all interfaces
1907 #
1908 self.pg_enable_capture(self.pg_interfaces)
1909
1910 #
1911 # Set the neighbor configuration:
1912 # limi = 200
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03001913 # age = 0 seconds
Neale Rannscbe25aa2019-09-30 10:53:31 +00001914 # recycle = false
1915 #
1916 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
1917 max_number=200,
1918 max_age=0,
1919 recycle=False)
1920
1921 self.vapi.cli("sh ip neighbor-config")
1922
1923 # add the 198 neighbours that should pass (-1 for one created in setup)
1924 for ii in range(200):
1925 VppNeighbor(self,
1926 self.pg0.sw_if_index,
1927 self.pg0.remote_hosts[ii].mac,
1928 self.pg0.remote_hosts[ii].ip4).add_vpp_config()
1929
1930 # one more neighbor over the limit should fail
1931 with self.vapi.assert_negative_api_retval():
1932 VppNeighbor(self,
1933 self.pg0.sw_if_index,
1934 self.pg0.remote_hosts[200].mac,
1935 self.pg0.remote_hosts[200].ip4).add_vpp_config()
1936
1937 #
1938 # change the config to allow recycling the old neighbors
1939 #
1940 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
1941 max_number=200,
1942 max_age=0,
1943 recycle=True)
1944
1945 # now new additions are allowed
1946 VppNeighbor(self,
1947 self.pg0.sw_if_index,
1948 self.pg0.remote_hosts[200].mac,
1949 self.pg0.remote_hosts[200].ip4).add_vpp_config()
1950
1951 # add the first neighbor we configured has been re-used
1952 self.assertFalse(find_nbr(self,
1953 self.pg0.sw_if_index,
1954 self.pg0.remote_hosts[0].ip4))
1955 self.assertTrue(find_nbr(self,
1956 self.pg0.sw_if_index,
1957 self.pg0.remote_hosts[200].ip4))
1958
1959 #
1960 # change the config to age old neighbors
1961 #
1962 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
1963 max_number=200,
1964 max_age=2,
1965 recycle=True)
1966
1967 self.vapi.cli("sh ip4 neighbor-sorted")
1968
1969 #
1970 # expect probes from all these ARP entries as they age
1971 # 3 probes for each neighbor 3*200 = 600
1972 rxs = self.pg0.get_capture(600, timeout=8)
1973
1974 for ii in range(3):
1975 for jj in range(200):
1976 rx = rxs[ii*200 + jj]
1977 # rx.show()
1978
1979 #
1980 # 3 probes sent then 1 more second to see if a reply comes, before
1981 # they age out
1982 #
1983 for jj in range(1, 201):
1984 self.wait_for_no_nbr(self.pg0.sw_if_index,
1985 self.pg0.remote_hosts[jj].ip4)
1986
1987 self.assertFalse(self.vapi.ip_neighbor_dump(sw_if_index=0xffffffff,
1988 af=vaf.ADDRESS_IP4))
1989
1990 #
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03001991 # load up some neighbours again with 2s aging enabled
1992 # they should be removed after 10s (2s age + 4s for probes + gap)
1993 #
1994 for ii in range(10):
1995 VppNeighbor(self,
1996 self.pg0.sw_if_index,
1997 self.pg0.remote_hosts[ii].mac,
1998 self.pg0.remote_hosts[ii].ip4).add_vpp_config()
1999 self.sleep(10)
2000 self.assertFalse(self.vapi.ip_neighbor_dump(sw_if_index=0xffffffff,
2001 af=vaf.ADDRESS_IP4))
2002
2003 #
2004 # check if we can set age and recycle with empty neighbor list
2005 #
2006 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
2007 max_number=200,
2008 max_age=1000,
2009 recycle=True)
2010
2011 #
Neale Rannscbe25aa2019-09-30 10:53:31 +00002012 # load up some neighbours again, then disable the aging
2013 # they should still be there in 10 seconds time
2014 #
2015 for ii in range(10):
2016 VppNeighbor(self,
2017 self.pg0.sw_if_index,
2018 self.pg0.remote_hosts[ii].mac,
2019 self.pg0.remote_hosts[ii].ip4).add_vpp_config()
2020 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
2021 max_number=200,
2022 max_age=0,
2023 recycle=False)
2024
2025 self.sleep(10)
2026 self.assertTrue(find_nbr(self,
2027 self.pg0.sw_if_index,
2028 self.pg0.remote_hosts[0].ip4))
2029
2030
Neale Rannsc87fbb42020-04-02 17:08:28 +00002031class NeighborReplaceTestCase(VppTestCase):
2032 """ ARP/ND Replacement """
2033
2034 @classmethod
2035 def setUpClass(cls):
2036 super(NeighborReplaceTestCase, cls).setUpClass()
2037
2038 @classmethod
2039 def tearDownClass(cls):
2040 super(NeighborReplaceTestCase, cls).tearDownClass()
2041
2042 def setUp(self):
2043 super(NeighborReplaceTestCase, self).setUp()
2044
2045 self.create_pg_interfaces(range(4))
2046
2047 # pg0 configured with ip4 and 6 addresses used for input
2048 # pg1 configured with ip4 and 6 addresses used for output
2049 # pg2 is unnumbered to pg0
2050 for i in self.pg_interfaces:
2051 i.admin_up()
2052 i.config_ip4()
2053 i.config_ip6()
2054 i.resolve_arp()
2055 i.resolve_ndp()
2056
2057 def tearDown(self):
2058 super(NeighborReplaceTestCase, self).tearDown()
2059
2060 for i in self.pg_interfaces:
2061 i.unconfig_ip4()
2062 i.unconfig_ip6()
2063 i.admin_down()
2064
2065 def test_replace(self):
2066 """ replace """
2067
2068 N_HOSTS = 16
2069
2070 for i in self.pg_interfaces:
2071 i.generate_remote_hosts(N_HOSTS)
2072 i.configure_ipv4_neighbors()
2073 i.configure_ipv6_neighbors()
2074
2075 # replace them all
2076 self.vapi.ip_neighbor_replace_begin()
2077 self.vapi.ip_neighbor_replace_end()
2078
2079 for i in self.pg_interfaces:
2080 for h in range(N_HOSTS):
2081 self.assertFalse(find_nbr(self,
2082 self.pg0.sw_if_index,
2083 self.pg0.remote_hosts[h].ip4))
2084 self.assertFalse(find_nbr(self,
2085 self.pg0.sw_if_index,
2086 self.pg0.remote_hosts[h].ip6))
2087
2088 #
2089 # and them all back via the API
2090 #
2091 for i in self.pg_interfaces:
2092 for h in range(N_HOSTS):
2093 VppNeighbor(self,
2094 i.sw_if_index,
2095 i.remote_hosts[h].mac,
2096 i.remote_hosts[h].ip4).add_vpp_config()
2097 VppNeighbor(self,
2098 i.sw_if_index,
2099 i.remote_hosts[h].mac,
2100 i.remote_hosts[h].ip6).add_vpp_config()
2101
2102 #
2103 # begin the replacement again, this time touch some
2104 # the neighbours on pg1 so they are not deleted
2105 #
2106 self.vapi.ip_neighbor_replace_begin()
2107
2108 # update from the API all neighbours on pg1
2109 for h in range(N_HOSTS):
2110 VppNeighbor(self,
2111 self.pg1.sw_if_index,
2112 self.pg1.remote_hosts[h].mac,
2113 self.pg1.remote_hosts[h].ip4).add_vpp_config()
2114 VppNeighbor(self,
2115 self.pg1.sw_if_index,
2116 self.pg1.remote_hosts[h].mac,
2117 self.pg1.remote_hosts[h].ip6).add_vpp_config()
2118
2119 # update from the data-plane all neighbours on pg3
2120 self.pg3.configure_ipv4_neighbors()
2121 self.pg3.configure_ipv6_neighbors()
2122
2123 # complete the replacement
2124 self.logger.info(self.vapi.cli("sh ip neighbors"))
2125 self.vapi.ip_neighbor_replace_end()
2126
2127 for i in self.pg_interfaces:
2128 if i == self.pg1 or i == self.pg3:
2129 # neighbours on pg1 and pg3 are still present
2130 for h in range(N_HOSTS):
2131 self.assertTrue(find_nbr(self,
2132 i.sw_if_index,
2133 i.remote_hosts[h].ip4))
2134 self.assertTrue(find_nbr(self,
2135 i.sw_if_index,
2136 i.remote_hosts[h].ip6))
2137 else:
2138 # all other neighbours are toast
2139 for h in range(N_HOSTS):
2140 self.assertFalse(find_nbr(self,
2141 i.sw_if_index,
2142 i.remote_hosts[h].ip4))
2143 self.assertFalse(find_nbr(self,
2144 i.sw_if_index,
2145 i.remote_hosts[h].ip6))
2146
2147
Neale Ranns240dcb22020-04-23 09:04:59 +00002148class NeighborFlush(VppTestCase):
2149 """ Neighbor Flush """
2150
2151 @classmethod
2152 def setUpClass(cls):
2153 super(NeighborFlush, cls).setUpClass()
2154
2155 @classmethod
2156 def tearDownClass(cls):
2157 super(NeighborFlush, cls).tearDownClass()
2158
2159 def setUp(self):
2160 super(NeighborFlush, self).setUp()
2161
2162 self.create_pg_interfaces(range(2))
2163
2164 for i in self.pg_interfaces:
2165 i.admin_up()
2166 i.config_ip4()
2167 i.config_ip6()
2168 i.resolve_arp()
2169 i.resolve_ndp()
2170
2171 def tearDown(self):
2172 super(NeighborFlush, self).tearDown()
2173
2174 for i in self.pg_interfaces:
2175 i.unconfig_ip4()
2176 i.unconfig_ip6()
2177 i.admin_down()
2178
2179 def test_flush(self):
2180 """ Neighbour Flush """
2181
2182 e = VppEnum
2183 nf = e.vl_api_ip_neighbor_flags_t
2184 af = e.vl_api_address_family_t
2185 N_HOSTS = 16
2186 static = [False, True]
2187 self.pg0.generate_remote_hosts(N_HOSTS)
2188 self.pg1.generate_remote_hosts(N_HOSTS)
2189
2190 for s in static:
2191 # a few v4 and v6 dynamic neoghbors
2192 for n in range(N_HOSTS):
2193 VppNeighbor(self,
2194 self.pg0.sw_if_index,
2195 self.pg0.remote_hosts[n].mac,
2196 self.pg0.remote_hosts[n].ip4,
2197 is_static=s).add_vpp_config()
2198 VppNeighbor(self,
2199 self.pg1.sw_if_index,
2200 self.pg1.remote_hosts[n].mac,
2201 self.pg1.remote_hosts[n].ip6,
2202 is_static=s).add_vpp_config()
2203
2204 # flush the interfaces individually
2205 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, self.pg0.sw_if_index)
2206
2207 # check we haven't flushed that which we shouldn't
2208 for n in range(N_HOSTS):
2209 self.assertTrue(find_nbr(self,
2210 self.pg1.sw_if_index,
2211 self.pg1.remote_hosts[n].ip6,
2212 is_static=s))
2213
2214 self.vapi.ip_neighbor_flush(af.ADDRESS_IP6, self.pg1.sw_if_index)
2215
2216 for n in range(N_HOSTS):
2217 self.assertFalse(find_nbr(self,
2218 self.pg0.sw_if_index,
2219 self.pg0.remote_hosts[n].ip4))
2220 self.assertFalse(find_nbr(self,
2221 self.pg1.sw_if_index,
2222 self.pg1.remote_hosts[n].ip6))
2223
2224 # add the nieghbours back
2225 for n in range(N_HOSTS):
2226 VppNeighbor(self,
2227 self.pg0.sw_if_index,
2228 self.pg0.remote_hosts[n].mac,
2229 self.pg0.remote_hosts[n].ip4,
2230 is_static=s).add_vpp_config()
2231 VppNeighbor(self,
2232 self.pg1.sw_if_index,
2233 self.pg1.remote_hosts[n].mac,
2234 self.pg1.remote_hosts[n].ip6,
2235 is_static=s).add_vpp_config()
2236
2237 self.logger.info(self.vapi.cli("sh ip neighbor"))
2238
2239 # flush both interfaces at the same time
2240 self.vapi.ip_neighbor_flush(af.ADDRESS_IP6, 0xffffffff)
2241
2242 # check we haven't flushed that which we shouldn't
2243 for n in range(N_HOSTS):
2244 self.assertTrue(find_nbr(self,
2245 self.pg0.sw_if_index,
2246 self.pg0.remote_hosts[n].ip4,
2247 is_static=s))
2248
2249 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, 0xffffffff)
2250
2251 for n in range(N_HOSTS):
2252 self.assertFalse(find_nbr(self,
2253 self.pg0.sw_if_index,
2254 self.pg0.remote_hosts[n].ip4))
2255 self.assertFalse(find_nbr(self,
2256 self.pg1.sw_if_index,
2257 self.pg1.remote_hosts[n].ip6))
2258
2259
Neale Ranns37be7362017-02-21 17:30:26 -08002260if __name__ == '__main__':
2261 unittest.main(testRunner=VppTestRunner)