blob: 1045f4ba1e9bb66cc03e74e5a44b6ccc1f073956 [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)
1438
1439 #
1440 # And an ARP entry
1441 #
1442 arp = VppNeighbor(self,
1443 self.pg1.sw_if_index,
1444 self.pg1.remote_hosts[1].mac,
1445 self.pg1.remote_hosts[1].ip4)
1446 arp.add_vpp_config()
1447
1448 self.assertTrue(find_nbr(self,
1449 self.pg1.sw_if_index,
1450 self.pg1.remote_hosts[1].ip4,
1451 mac=self.pg1.remote_hosts[1].mac))
1452
1453 #
1454 # Send a GARP (request) to swap the host 1's address to that of host 2
1455 #
1456 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1457 src=self.pg1.remote_hosts[2].mac) /
1458 ARP(op="who-has",
1459 hwdst=self.pg1.local_mac,
1460 hwsrc=self.pg1.remote_hosts[2].mac,
1461 pdst=self.pg1.remote_hosts[1].ip4,
1462 psrc=self.pg1.remote_hosts[1].ip4))
1463
1464 self.pg1.add_stream(p1)
1465 self.pg_enable_capture(self.pg_interfaces)
1466 self.pg_start()
1467
1468 self.assertTrue(find_nbr(self,
1469 self.pg1.sw_if_index,
1470 self.pg1.remote_hosts[1].ip4,
1471 mac=self.pg1.remote_hosts[2].mac))
1472
1473 #
1474 # Send a GARP (reply) to swap the host 1's address to that of host 3
1475 #
1476 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1477 src=self.pg1.remote_hosts[3].mac) /
1478 ARP(op="is-at",
1479 hwdst=self.pg1.local_mac,
1480 hwsrc=self.pg1.remote_hosts[3].mac,
1481 pdst=self.pg1.remote_hosts[1].ip4,
1482 psrc=self.pg1.remote_hosts[1].ip4))
1483
1484 self.pg1.add_stream(p1)
1485 self.pg_enable_capture(self.pg_interfaces)
1486 self.pg_start()
1487
1488 self.assertTrue(find_nbr(self,
1489 self.pg1.sw_if_index,
1490 self.pg1.remote_hosts[1].ip4,
1491 mac=self.pg1.remote_hosts[3].mac))
1492
1493 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001494 # GARPs (request nor replies) for host we don't know yet
Neale Ranns59ae61e2018-06-07 18:09:49 -07001495 # don't result in new neighbour entries
1496 #
1497 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1498 src=self.pg1.remote_hosts[3].mac) /
1499 ARP(op="who-has",
1500 hwdst=self.pg1.local_mac,
1501 hwsrc=self.pg1.remote_hosts[3].mac,
1502 pdst=self.pg1.remote_hosts[2].ip4,
1503 psrc=self.pg1.remote_hosts[2].ip4))
1504
1505 self.pg1.add_stream(p1)
1506 self.pg_enable_capture(self.pg_interfaces)
1507 self.pg_start()
1508
1509 self.assertFalse(find_nbr(self,
1510 self.pg1.sw_if_index,
1511 self.pg1.remote_hosts[2].ip4))
1512
1513 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1514 src=self.pg1.remote_hosts[3].mac) /
1515 ARP(op="is-at",
1516 hwdst=self.pg1.local_mac,
1517 hwsrc=self.pg1.remote_hosts[3].mac,
1518 pdst=self.pg1.remote_hosts[2].ip4,
1519 psrc=self.pg1.remote_hosts[2].ip4))
1520
1521 self.pg1.add_stream(p1)
1522 self.pg_enable_capture(self.pg_interfaces)
1523 self.pg_start()
1524
1525 self.assertFalse(find_nbr(self,
1526 self.pg1.sw_if_index,
1527 self.pg1.remote_hosts[2].ip4))
1528
Neale Rannsc8352bc2018-08-29 10:23:58 -07001529 def test_arp_incomplete(self):
Neale Ranns14260392018-09-28 05:00:57 -07001530 """ Incomplete Entries """
Neale Rannsc8352bc2018-08-29 10:23:58 -07001531
1532 #
Neale Rannscd35e532018-08-31 02:51:45 -07001533 # ensure that we throttle the ARP and ND requests
Neale Rannsc8352bc2018-08-29 10:23:58 -07001534 #
1535 self.pg0.generate_remote_hosts(2)
1536
Neale Rannscd35e532018-08-31 02:51:45 -07001537 #
1538 # IPv4/ARP
1539 #
Neale Rannsc8352bc2018-08-29 10:23:58 -07001540 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1541 [VppRoutePath(self.pg0.remote_hosts[1].ip4,
Neale Rannscd35e532018-08-31 02:51:45 -07001542 self.pg0.sw_if_index)])
Neale Rannsc8352bc2018-08-29 10:23:58 -07001543 ip_10_0_0_1.add_vpp_config()
1544
1545 p1 = (Ether(dst=self.pg1.local_mac,
1546 src=self.pg1.remote_mac) /
1547 IP(src=self.pg1.remote_ip4,
1548 dst="10.0.0.1") /
1549 UDP(sport=1234, dport=1234) /
1550 Raw())
1551
1552 self.pg1.add_stream(p1 * 257)
1553 self.pg_enable_capture(self.pg_interfaces)
1554 self.pg_start()
1555 rx = self.pg0._get_capture(1)
1556
1557 #
1558 # how many we get is going to be dependent on the time for packet
1559 # processing but it should be small
1560 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001561 self.assertLess(len(rx), 64)
Neale Rannsc8352bc2018-08-29 10:23:58 -07001562
Neale Rannscd35e532018-08-31 02:51:45 -07001563 #
1564 # IPv6/ND
1565 #
1566 ip_10_1 = VppIpRoute(self, "10::1", 128,
1567 [VppRoutePath(self.pg0.remote_hosts[1].ip6,
1568 self.pg0.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07001569 proto=DpoProto.DPO_PROTO_IP6)])
Neale Rannscd35e532018-08-31 02:51:45 -07001570 ip_10_1.add_vpp_config()
1571
1572 p1 = (Ether(dst=self.pg1.local_mac,
1573 src=self.pg1.remote_mac) /
1574 IPv6(src=self.pg1.remote_ip6,
1575 dst="10::1") /
1576 UDP(sport=1234, dport=1234) /
1577 Raw())
1578
1579 self.pg1.add_stream(p1 * 257)
1580 self.pg_enable_capture(self.pg_interfaces)
1581 self.pg_start()
1582 rx = self.pg0._get_capture(1)
1583
1584 #
1585 # how many we get is going to be dependent on the time for packet
1586 # processing but it should be small
1587 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001588 self.assertLess(len(rx), 64)
Neale Rannscd35e532018-08-31 02:51:45 -07001589
Neale Ranns7425f922019-01-23 00:36:16 -08001590 def test_arp_forus(self):
1591 """ ARP for for-us """
1592
1593 #
1594 # Test that VPP responds with ARP requests to addresses that
1595 # are connected and local routes.
1596 # Use one of the 'remote' addresses in the subnet as a local address
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001597 # The intention of this route is that it then acts like a secondary
Neale Ranns7425f922019-01-23 00:36:16 -08001598 # address added to an interface
1599 #
1600 self.pg0.generate_remote_hosts(2)
1601
Neale Ranns097fa662018-05-01 05:17:55 -07001602 forus = VppIpRoute(
1603 self, self.pg0.remote_hosts[1].ip4, 32,
1604 [VppRoutePath("0.0.0.0",
1605 self.pg0.sw_if_index,
1606 type=FibPathType.FIB_PATH_TYPE_LOCAL)])
Neale Ranns7425f922019-01-23 00:36:16 -08001607 forus.add_vpp_config()
1608
1609 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
1610 src=self.pg0.remote_mac) /
1611 ARP(op="who-has",
1612 hwdst=self.pg0.local_mac,
1613 hwsrc=self.pg0.remote_mac,
1614 pdst=self.pg0.remote_hosts[1].ip4,
1615 psrc=self.pg0.remote_ip4))
1616
1617 rx = self.send_and_expect(self.pg0, [p], self.pg0)
1618
1619 self.verify_arp_resp(rx[0],
1620 self.pg0.local_mac,
1621 self.pg0.remote_mac,
1622 self.pg0.remote_hosts[1].ip4,
1623 self.pg0.remote_ip4)
1624
Neale Rannsfca3c6a2019-12-31 03:49:34 +00001625 def test_arp_table_swap(self):
1626 #
1627 # Generate some hosts on the LAN
1628 #
1629 N_NBRS = 4
1630 self.pg1.generate_remote_hosts(N_NBRS)
1631
1632 for n in range(N_NBRS):
1633 # a route thru each neighbour
1634 VppIpRoute(self, "10.0.0.%d" % n, 32,
1635 [VppRoutePath(self.pg1.remote_hosts[n].ip4,
1636 self.pg1.sw_if_index)]).add_vpp_config()
1637
1638 # resolve each neighbour
1639 p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1640 ARP(op="is-at", hwdst=self.pg1.local_mac,
1641 hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
1642 psrc=self.pg1.remote_hosts[n].ip4))
1643
1644 self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
1645
1646 self.logger.info(self.vapi.cli("sh ip neighbors"))
1647
1648 #
1649 # swap the table pg1 is in
1650 #
1651 table = VppIpTable(self, 100).add_vpp_config()
1652
1653 self.pg1.unconfig_ip4()
1654 self.pg1.set_table_ip4(100)
1655 self.pg1.config_ip4()
1656
1657 #
1658 # all neighbours are cleared
1659 #
1660 for n in range(N_NBRS):
1661 self.assertFalse(find_nbr(self,
1662 self.pg1.sw_if_index,
1663 self.pg1.remote_hosts[n].ip4))
1664
1665 #
1666 # packets to all neighbours generate ARP requests
1667 #
1668 for n in range(N_NBRS):
1669 # a route thru each neighbour
1670 VppIpRoute(self, "10.0.0.%d" % n, 32,
1671 [VppRoutePath(self.pg1.remote_hosts[n].ip4,
1672 self.pg1.sw_if_index)],
1673 table_id=100).add_vpp_config()
1674
1675 p = (Ether(src=self.pg1.remote_hosts[n].mac,
1676 dst=self.pg1.local_mac) /
1677 IP(src=self.pg1.remote_hosts[n].ip4,
1678 dst="10.0.0.%d" % n) /
1679 Raw(b'0x5' * 100))
1680 rxs = self.send_and_expect(self.pg1, [p], self.pg1)
1681 for rx in rxs:
1682 self.verify_arp_req(rx,
1683 self.pg1.local_mac,
1684 self.pg1.local_ip4,
1685 self.pg1.remote_hosts[n].ip4)
1686
1687 self.pg1.unconfig_ip4()
1688 self.pg1.set_table_ip4(0)
1689
Neale Rannsdcd6d622017-05-26 02:59:16 -07001690
Neale Ranns14260392018-09-28 05:00:57 -07001691class NeighborStatsTestCase(VppTestCase):
Neale Ranns37029302018-08-10 05:30:06 -07001692 """ ARP/ND Counters """
Neale Ranns14260392018-09-28 05:00:57 -07001693
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001694 @classmethod
1695 def setUpClass(cls):
1696 super(NeighborStatsTestCase, cls).setUpClass()
1697
1698 @classmethod
1699 def tearDownClass(cls):
1700 super(NeighborStatsTestCase, cls).tearDownClass()
1701
Neale Ranns14260392018-09-28 05:00:57 -07001702 def setUp(self):
1703 super(NeighborStatsTestCase, self).setUp()
1704
1705 self.create_pg_interfaces(range(2))
1706
1707 # pg0 configured with ip4 and 6 addresses used for input
1708 # pg1 configured with ip4 and 6 addresses used for output
1709 # pg2 is unnumbered to pg0
1710 for i in self.pg_interfaces:
1711 i.admin_up()
1712 i.config_ip4()
1713 i.config_ip6()
1714 i.resolve_arp()
1715 i.resolve_ndp()
1716
1717 def tearDown(self):
1718 super(NeighborStatsTestCase, self).tearDown()
1719
1720 for i in self.pg_interfaces:
1721 i.unconfig_ip4()
1722 i.unconfig_ip6()
1723 i.admin_down()
1724
1725 def test_arp_stats(self):
1726 """ ARP Counters """
1727
1728 self.vapi.cli("adj counters enable")
1729 self.pg1.generate_remote_hosts(2)
1730
1731 arp1 = VppNeighbor(self,
1732 self.pg1.sw_if_index,
1733 self.pg1.remote_hosts[0].mac,
1734 self.pg1.remote_hosts[0].ip4)
1735 arp1.add_vpp_config()
1736 arp2 = VppNeighbor(self,
1737 self.pg1.sw_if_index,
1738 self.pg1.remote_hosts[1].mac,
1739 self.pg1.remote_hosts[1].ip4)
1740 arp2.add_vpp_config()
1741
1742 p1 = (Ether(dst=self.pg0.local_mac,
1743 src=self.pg0.remote_mac) /
1744 IP(src=self.pg0.remote_ip4,
1745 dst=self.pg1.remote_hosts[0].ip4) /
1746 UDP(sport=1234, dport=1234) /
1747 Raw())
1748 p2 = (Ether(dst=self.pg0.local_mac,
1749 src=self.pg0.remote_mac) /
1750 IP(src=self.pg0.remote_ip4,
1751 dst=self.pg1.remote_hosts[1].ip4) /
1752 UDP(sport=1234, dport=1234) /
1753 Raw())
1754
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001755 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
1756 rx = self.send_and_expect(self.pg0, p2 * NUM_PKTS, self.pg1)
Neale Ranns14260392018-09-28 05:00:57 -07001757
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001758 self.assertEqual(NUM_PKTS, arp1.get_stats()['packets'])
1759 self.assertEqual(NUM_PKTS, arp2.get_stats()['packets'])
Neale Ranns14260392018-09-28 05:00:57 -07001760
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001761 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
1762 self.assertEqual(NUM_PKTS*2, arp1.get_stats()['packets'])
Neale Ranns14260392018-09-28 05:00:57 -07001763
1764 def test_nd_stats(self):
1765 """ ND Counters """
1766
1767 self.vapi.cli("adj counters enable")
1768 self.pg0.generate_remote_hosts(3)
1769
1770 nd1 = VppNeighbor(self,
1771 self.pg0.sw_if_index,
1772 self.pg0.remote_hosts[1].mac,
Neale Ranns37029302018-08-10 05:30:06 -07001773 self.pg0.remote_hosts[1].ip6)
Neale Ranns14260392018-09-28 05:00:57 -07001774 nd1.add_vpp_config()
1775 nd2 = VppNeighbor(self,
1776 self.pg0.sw_if_index,
1777 self.pg0.remote_hosts[2].mac,
Neale Ranns37029302018-08-10 05:30:06 -07001778 self.pg0.remote_hosts[2].ip6)
Neale Ranns14260392018-09-28 05:00:57 -07001779 nd2.add_vpp_config()
1780
1781 p1 = (Ether(dst=self.pg1.local_mac,
1782 src=self.pg1.remote_mac) /
1783 IPv6(src=self.pg1.remote_ip6,
1784 dst=self.pg0.remote_hosts[1].ip6) /
1785 UDP(sport=1234, dport=1234) /
1786 Raw())
1787 p2 = (Ether(dst=self.pg1.local_mac,
1788 src=self.pg1.remote_mac) /
1789 IPv6(src=self.pg1.remote_ip6,
1790 dst=self.pg0.remote_hosts[2].ip6) /
1791 UDP(sport=1234, dport=1234) /
1792 Raw())
1793
1794 rx = self.send_and_expect(self.pg1, p1 * 16, self.pg0)
1795 rx = self.send_and_expect(self.pg1, p2 * 16, self.pg0)
1796
1797 self.assertEqual(16, nd1.get_stats()['packets'])
1798 self.assertEqual(16, nd2.get_stats()['packets'])
1799
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001800 rx = self.send_and_expect(self.pg1, p1 * NUM_PKTS, self.pg0)
1801 self.assertEqual(NUM_PKTS+16, nd1.get_stats()['packets'])
Neale Ranns14260392018-09-28 05:00:57 -07001802
1803
Neale Rannscbe25aa2019-09-30 10:53:31 +00001804class NeighborAgeTestCase(VppTestCase):
1805 """ ARP/ND Aging """
1806
1807 @classmethod
1808 def setUpClass(cls):
1809 super(NeighborAgeTestCase, cls).setUpClass()
1810
1811 @classmethod
1812 def tearDownClass(cls):
1813 super(NeighborAgeTestCase, cls).tearDownClass()
1814
1815 def setUp(self):
1816 super(NeighborAgeTestCase, self).setUp()
1817
1818 self.create_pg_interfaces(range(1))
1819
1820 # pg0 configured with ip4 and 6 addresses used for input
1821 # pg1 configured with ip4 and 6 addresses used for output
1822 # pg2 is unnumbered to pg0
1823 for i in self.pg_interfaces:
1824 i.admin_up()
1825 i.config_ip4()
1826 i.config_ip6()
1827 i.resolve_arp()
1828 i.resolve_ndp()
1829
1830 def tearDown(self):
1831 super(NeighborAgeTestCase, self).tearDown()
1832
1833 for i in self.pg_interfaces:
1834 i.unconfig_ip4()
1835 i.unconfig_ip6()
1836 i.admin_down()
1837
1838 def wait_for_no_nbr(self, intf, address,
1839 n_tries=50, s_time=1):
1840 while (n_tries):
1841 if not find_nbr(self, intf, address):
1842 return True
1843 n_tries = n_tries - 1
1844 self.sleep(s_time)
1845
1846 return False
1847
1848 def verify_arp_req(self, rx, smac, sip, dip):
1849 ether = rx[Ether]
1850 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
1851 self.assertEqual(ether.src, smac)
1852
1853 arp = rx[ARP]
1854 self.assertEqual(arp.hwtype, 1)
1855 self.assertEqual(arp.ptype, 0x800)
1856 self.assertEqual(arp.hwlen, 6)
1857 self.assertEqual(arp.plen, 4)
1858 self.assertEqual(arp.op, arp_opts["who-has"])
1859 self.assertEqual(arp.hwsrc, smac)
1860 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
1861 self.assertEqual(arp.psrc, sip)
1862 self.assertEqual(arp.pdst, dip)
1863
1864 def test_age(self):
1865 """ Aging/Recycle """
1866
1867 self.vapi.cli("set logging unthrottle 0")
1868 self.vapi.cli("set logging size %d" % 0xffff)
1869
1870 self.pg0.generate_remote_hosts(201)
1871
1872 vaf = VppEnum.vl_api_address_family_t
1873
1874 #
1875 # start listening on all interfaces
1876 #
1877 self.pg_enable_capture(self.pg_interfaces)
1878
1879 #
1880 # Set the neighbor configuration:
1881 # limi = 200
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03001882 # age = 0 seconds
Neale Rannscbe25aa2019-09-30 10:53:31 +00001883 # recycle = false
1884 #
1885 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
1886 max_number=200,
1887 max_age=0,
1888 recycle=False)
1889
1890 self.vapi.cli("sh ip neighbor-config")
1891
1892 # add the 198 neighbours that should pass (-1 for one created in setup)
1893 for ii in range(200):
1894 VppNeighbor(self,
1895 self.pg0.sw_if_index,
1896 self.pg0.remote_hosts[ii].mac,
1897 self.pg0.remote_hosts[ii].ip4).add_vpp_config()
1898
1899 # one more neighbor over the limit should fail
1900 with self.vapi.assert_negative_api_retval():
1901 VppNeighbor(self,
1902 self.pg0.sw_if_index,
1903 self.pg0.remote_hosts[200].mac,
1904 self.pg0.remote_hosts[200].ip4).add_vpp_config()
1905
1906 #
1907 # change the config to allow recycling the old neighbors
1908 #
1909 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
1910 max_number=200,
1911 max_age=0,
1912 recycle=True)
1913
1914 # now new additions are allowed
1915 VppNeighbor(self,
1916 self.pg0.sw_if_index,
1917 self.pg0.remote_hosts[200].mac,
1918 self.pg0.remote_hosts[200].ip4).add_vpp_config()
1919
1920 # add the first neighbor we configured has been re-used
1921 self.assertFalse(find_nbr(self,
1922 self.pg0.sw_if_index,
1923 self.pg0.remote_hosts[0].ip4))
1924 self.assertTrue(find_nbr(self,
1925 self.pg0.sw_if_index,
1926 self.pg0.remote_hosts[200].ip4))
1927
1928 #
1929 # change the config to age old neighbors
1930 #
1931 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
1932 max_number=200,
1933 max_age=2,
1934 recycle=True)
1935
1936 self.vapi.cli("sh ip4 neighbor-sorted")
1937
1938 #
1939 # expect probes from all these ARP entries as they age
1940 # 3 probes for each neighbor 3*200 = 600
1941 rxs = self.pg0.get_capture(600, timeout=8)
1942
1943 for ii in range(3):
1944 for jj in range(200):
1945 rx = rxs[ii*200 + jj]
1946 # rx.show()
1947
1948 #
1949 # 3 probes sent then 1 more second to see if a reply comes, before
1950 # they age out
1951 #
1952 for jj in range(1, 201):
1953 self.wait_for_no_nbr(self.pg0.sw_if_index,
1954 self.pg0.remote_hosts[jj].ip4)
1955
1956 self.assertFalse(self.vapi.ip_neighbor_dump(sw_if_index=0xffffffff,
1957 af=vaf.ADDRESS_IP4))
1958
1959 #
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03001960 # load up some neighbours again with 2s aging enabled
1961 # they should be removed after 10s (2s age + 4s for probes + gap)
1962 #
1963 for ii in range(10):
1964 VppNeighbor(self,
1965 self.pg0.sw_if_index,
1966 self.pg0.remote_hosts[ii].mac,
1967 self.pg0.remote_hosts[ii].ip4).add_vpp_config()
1968 self.sleep(10)
1969 self.assertFalse(self.vapi.ip_neighbor_dump(sw_if_index=0xffffffff,
1970 af=vaf.ADDRESS_IP4))
1971
1972 #
1973 # check if we can set age and recycle with empty neighbor list
1974 #
1975 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
1976 max_number=200,
1977 max_age=1000,
1978 recycle=True)
1979
1980 #
Neale Rannscbe25aa2019-09-30 10:53:31 +00001981 # load up some neighbours again, then disable the aging
1982 # they should still be there in 10 seconds time
1983 #
1984 for ii in range(10):
1985 VppNeighbor(self,
1986 self.pg0.sw_if_index,
1987 self.pg0.remote_hosts[ii].mac,
1988 self.pg0.remote_hosts[ii].ip4).add_vpp_config()
1989 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
1990 max_number=200,
1991 max_age=0,
1992 recycle=False)
1993
1994 self.sleep(10)
1995 self.assertTrue(find_nbr(self,
1996 self.pg0.sw_if_index,
1997 self.pg0.remote_hosts[0].ip4))
1998
1999
Neale Rannsc87fbb42020-04-02 17:08:28 +00002000class NeighborReplaceTestCase(VppTestCase):
2001 """ ARP/ND Replacement """
2002
2003 @classmethod
2004 def setUpClass(cls):
2005 super(NeighborReplaceTestCase, cls).setUpClass()
2006
2007 @classmethod
2008 def tearDownClass(cls):
2009 super(NeighborReplaceTestCase, cls).tearDownClass()
2010
2011 def setUp(self):
2012 super(NeighborReplaceTestCase, self).setUp()
2013
2014 self.create_pg_interfaces(range(4))
2015
2016 # pg0 configured with ip4 and 6 addresses used for input
2017 # pg1 configured with ip4 and 6 addresses used for output
2018 # pg2 is unnumbered to pg0
2019 for i in self.pg_interfaces:
2020 i.admin_up()
2021 i.config_ip4()
2022 i.config_ip6()
2023 i.resolve_arp()
2024 i.resolve_ndp()
2025
2026 def tearDown(self):
2027 super(NeighborReplaceTestCase, self).tearDown()
2028
2029 for i in self.pg_interfaces:
2030 i.unconfig_ip4()
2031 i.unconfig_ip6()
2032 i.admin_down()
2033
2034 def test_replace(self):
2035 """ replace """
2036
2037 N_HOSTS = 16
2038
2039 for i in self.pg_interfaces:
2040 i.generate_remote_hosts(N_HOSTS)
2041 i.configure_ipv4_neighbors()
2042 i.configure_ipv6_neighbors()
2043
2044 # replace them all
2045 self.vapi.ip_neighbor_replace_begin()
2046 self.vapi.ip_neighbor_replace_end()
2047
2048 for i in self.pg_interfaces:
2049 for h in range(N_HOSTS):
2050 self.assertFalse(find_nbr(self,
2051 self.pg0.sw_if_index,
2052 self.pg0.remote_hosts[h].ip4))
2053 self.assertFalse(find_nbr(self,
2054 self.pg0.sw_if_index,
2055 self.pg0.remote_hosts[h].ip6))
2056
2057 #
2058 # and them all back via the API
2059 #
2060 for i in self.pg_interfaces:
2061 for h in range(N_HOSTS):
2062 VppNeighbor(self,
2063 i.sw_if_index,
2064 i.remote_hosts[h].mac,
2065 i.remote_hosts[h].ip4).add_vpp_config()
2066 VppNeighbor(self,
2067 i.sw_if_index,
2068 i.remote_hosts[h].mac,
2069 i.remote_hosts[h].ip6).add_vpp_config()
2070
2071 #
2072 # begin the replacement again, this time touch some
2073 # the neighbours on pg1 so they are not deleted
2074 #
2075 self.vapi.ip_neighbor_replace_begin()
2076
2077 # update from the API all neighbours on pg1
2078 for h in range(N_HOSTS):
2079 VppNeighbor(self,
2080 self.pg1.sw_if_index,
2081 self.pg1.remote_hosts[h].mac,
2082 self.pg1.remote_hosts[h].ip4).add_vpp_config()
2083 VppNeighbor(self,
2084 self.pg1.sw_if_index,
2085 self.pg1.remote_hosts[h].mac,
2086 self.pg1.remote_hosts[h].ip6).add_vpp_config()
2087
2088 # update from the data-plane all neighbours on pg3
2089 self.pg3.configure_ipv4_neighbors()
2090 self.pg3.configure_ipv6_neighbors()
2091
2092 # complete the replacement
2093 self.logger.info(self.vapi.cli("sh ip neighbors"))
2094 self.vapi.ip_neighbor_replace_end()
2095
2096 for i in self.pg_interfaces:
2097 if i == self.pg1 or i == self.pg3:
2098 # neighbours on pg1 and pg3 are still present
2099 for h in range(N_HOSTS):
2100 self.assertTrue(find_nbr(self,
2101 i.sw_if_index,
2102 i.remote_hosts[h].ip4))
2103 self.assertTrue(find_nbr(self,
2104 i.sw_if_index,
2105 i.remote_hosts[h].ip6))
2106 else:
2107 # all other neighbours are toast
2108 for h in range(N_HOSTS):
2109 self.assertFalse(find_nbr(self,
2110 i.sw_if_index,
2111 i.remote_hosts[h].ip4))
2112 self.assertFalse(find_nbr(self,
2113 i.sw_if_index,
2114 i.remote_hosts[h].ip6))
2115
2116
Neale Ranns240dcb22020-04-23 09:04:59 +00002117class NeighborFlush(VppTestCase):
2118 """ Neighbor Flush """
2119
2120 @classmethod
2121 def setUpClass(cls):
2122 super(NeighborFlush, cls).setUpClass()
2123
2124 @classmethod
2125 def tearDownClass(cls):
2126 super(NeighborFlush, cls).tearDownClass()
2127
2128 def setUp(self):
2129 super(NeighborFlush, self).setUp()
2130
2131 self.create_pg_interfaces(range(2))
2132
2133 for i in self.pg_interfaces:
2134 i.admin_up()
2135 i.config_ip4()
2136 i.config_ip6()
2137 i.resolve_arp()
2138 i.resolve_ndp()
2139
2140 def tearDown(self):
2141 super(NeighborFlush, self).tearDown()
2142
2143 for i in self.pg_interfaces:
2144 i.unconfig_ip4()
2145 i.unconfig_ip6()
2146 i.admin_down()
2147
2148 def test_flush(self):
2149 """ Neighbour Flush """
2150
2151 e = VppEnum
2152 nf = e.vl_api_ip_neighbor_flags_t
2153 af = e.vl_api_address_family_t
2154 N_HOSTS = 16
2155 static = [False, True]
2156 self.pg0.generate_remote_hosts(N_HOSTS)
2157 self.pg1.generate_remote_hosts(N_HOSTS)
2158
2159 for s in static:
2160 # a few v4 and v6 dynamic neoghbors
2161 for n in range(N_HOSTS):
2162 VppNeighbor(self,
2163 self.pg0.sw_if_index,
2164 self.pg0.remote_hosts[n].mac,
2165 self.pg0.remote_hosts[n].ip4,
2166 is_static=s).add_vpp_config()
2167 VppNeighbor(self,
2168 self.pg1.sw_if_index,
2169 self.pg1.remote_hosts[n].mac,
2170 self.pg1.remote_hosts[n].ip6,
2171 is_static=s).add_vpp_config()
2172
2173 # flush the interfaces individually
2174 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, self.pg0.sw_if_index)
2175
2176 # check we haven't flushed that which we shouldn't
2177 for n in range(N_HOSTS):
2178 self.assertTrue(find_nbr(self,
2179 self.pg1.sw_if_index,
2180 self.pg1.remote_hosts[n].ip6,
2181 is_static=s))
2182
2183 self.vapi.ip_neighbor_flush(af.ADDRESS_IP6, self.pg1.sw_if_index)
2184
2185 for n in range(N_HOSTS):
2186 self.assertFalse(find_nbr(self,
2187 self.pg0.sw_if_index,
2188 self.pg0.remote_hosts[n].ip4))
2189 self.assertFalse(find_nbr(self,
2190 self.pg1.sw_if_index,
2191 self.pg1.remote_hosts[n].ip6))
2192
2193 # add the nieghbours back
2194 for n in range(N_HOSTS):
2195 VppNeighbor(self,
2196 self.pg0.sw_if_index,
2197 self.pg0.remote_hosts[n].mac,
2198 self.pg0.remote_hosts[n].ip4,
2199 is_static=s).add_vpp_config()
2200 VppNeighbor(self,
2201 self.pg1.sw_if_index,
2202 self.pg1.remote_hosts[n].mac,
2203 self.pg1.remote_hosts[n].ip6,
2204 is_static=s).add_vpp_config()
2205
2206 self.logger.info(self.vapi.cli("sh ip neighbor"))
2207
2208 # flush both interfaces at the same time
2209 self.vapi.ip_neighbor_flush(af.ADDRESS_IP6, 0xffffffff)
2210
2211 # check we haven't flushed that which we shouldn't
2212 for n in range(N_HOSTS):
2213 self.assertTrue(find_nbr(self,
2214 self.pg0.sw_if_index,
2215 self.pg0.remote_hosts[n].ip4,
2216 is_static=s))
2217
2218 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, 0xffffffff)
2219
2220 for n in range(N_HOSTS):
2221 self.assertFalse(find_nbr(self,
2222 self.pg0.sw_if_index,
2223 self.pg0.remote_hosts[n].ip4))
2224 self.assertFalse(find_nbr(self,
2225 self.pg1.sw_if_index,
2226 self.pg1.remote_hosts[n].ip6))
2227
2228
Neale Ranns37be7362017-02-21 17:30:26 -08002229if __name__ == '__main__':
2230 unittest.main(testRunner=VppTestRunner)