blob: cc1357ce0d8484a127f1d6b060eb97ae510cf350 [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 Ranns39f9d8b2017-02-16 21:57:05 -080016from scapy.layers.inet import IP, UDP
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 #
780 self.pg2.add_stream(arp_req_from_me)
781 self.pg_enable_capture(self.pg_interfaces)
782 self.pg_start()
783
784 rx = self.pg2.get_capture(1)
785 self.verify_arp_resp(rx[0],
786 self.pg2.local_mac,
787 self.pg2.remote_mac,
788 self.pg0.remote_hosts[1].ip4,
789 self.pg0.local_ip4)
790
791 #
792 # validate we have not learned an ARP entry as a result of this
793 #
794 self.assertFalse(find_nbr(self,
795 self.pg2.sw_if_index,
796 self.pg0.local_ip4))
797
798 #
799 # cleanup
800 #
801 self.pg2.set_proxy_arp(0)
Neale Ranns37029302018-08-10 05:30:06 -0700802 self.vapi.proxy_arp_add_del(self.pg0._local_ip4_subnet,
803 self.pg0._local_ip4_bcast,
Neale Ranns24b170a2017-08-15 05:33:11 -0700804 is_add=0)
805
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800806 def test_proxy_arp(self):
807 """ Proxy ARP """
808
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700809 self.pg1.generate_remote_hosts(2)
810
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800811 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700812 # Proxy ARP request packets for each interface
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800813 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800814 arp_req_pg0 = (Ether(src=self.pg0.remote_mac,
815 dst="ff:ff:ff:ff:ff:ff") /
816 ARP(op="who-has",
817 hwsrc=self.pg0.remote_mac,
818 pdst="10.10.10.3",
819 psrc=self.pg0.remote_ip4))
Neale Ranns30d0fd42017-05-30 07:30:04 -0700820 arp_req_pg0_tagged = (Ether(src=self.pg0.remote_mac,
821 dst="ff:ff:ff:ff:ff:ff") /
822 Dot1Q(vlan=0) /
823 ARP(op="who-has",
824 hwsrc=self.pg0.remote_mac,
825 pdst="10.10.10.3",
826 psrc=self.pg0.remote_ip4))
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800827 arp_req_pg1 = (Ether(src=self.pg1.remote_mac,
828 dst="ff:ff:ff:ff:ff:ff") /
829 ARP(op="who-has",
830 hwsrc=self.pg1.remote_mac,
831 pdst="10.10.10.3",
832 psrc=self.pg1.remote_ip4))
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700833 arp_req_pg2 = (Ether(src=self.pg2.remote_mac,
834 dst="ff:ff:ff:ff:ff:ff") /
835 ARP(op="who-has",
836 hwsrc=self.pg2.remote_mac,
837 pdst="10.10.10.3",
838 psrc=self.pg1.remote_hosts[1].ip4))
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800839 arp_req_pg3 = (Ether(src=self.pg3.remote_mac,
840 dst="ff:ff:ff:ff:ff:ff") /
841 ARP(op="who-has",
842 hwsrc=self.pg3.remote_mac,
843 pdst="10.10.10.3",
844 psrc=self.pg3.remote_ip4))
845
846 #
847 # Configure Proxy ARP for 10.10.10.0 -> 10.10.10.124
848 #
849 self.vapi.proxy_arp_add_del(inet_pton(AF_INET, "10.10.10.2"),
850 inet_pton(AF_INET, "10.10.10.124"))
851
852 #
853 # No responses are sent when the interfaces are not enabled for proxy
854 # ARP
855 #
856 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
857 "ARP req from unconfigured interface")
858 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
859 "ARP req from unconfigured interface")
860
861 #
862 # Make pg2 un-numbered to pg1
863 # still won't reply.
864 #
865 self.pg2.set_unnumbered(self.pg1.sw_if_index)
866
867 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
868 "ARP req from unnumbered interface")
869
870 #
871 # Enable each interface to reply to proxy ARPs
872 #
873 for i in self.pg_interfaces:
874 i.set_proxy_arp()
875
876 #
877 # Now each of the interfaces should reply to a request to a proxied
878 # address
879 #
880 self.pg0.add_stream(arp_req_pg0)
881 self.pg_enable_capture(self.pg_interfaces)
882 self.pg_start()
883
884 rx = self.pg0.get_capture(1)
885 self.verify_arp_resp(rx[0],
886 self.pg0.local_mac,
887 self.pg0.remote_mac,
888 "10.10.10.3",
889 self.pg0.remote_ip4)
890
Neale Ranns30d0fd42017-05-30 07:30:04 -0700891 self.pg0.add_stream(arp_req_pg0_tagged)
892 self.pg_enable_capture(self.pg_interfaces)
893 self.pg_start()
894
895 rx = self.pg0.get_capture(1)
896 self.verify_arp_resp(rx[0],
897 self.pg0.local_mac,
898 self.pg0.remote_mac,
899 "10.10.10.3",
900 self.pg0.remote_ip4)
901
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800902 self.pg1.add_stream(arp_req_pg1)
903 self.pg_enable_capture(self.pg_interfaces)
904 self.pg_start()
905
906 rx = self.pg1.get_capture(1)
907 self.verify_arp_resp(rx[0],
908 self.pg1.local_mac,
909 self.pg1.remote_mac,
910 "10.10.10.3",
911 self.pg1.remote_ip4)
912
913 self.pg2.add_stream(arp_req_pg2)
914 self.pg_enable_capture(self.pg_interfaces)
915 self.pg_start()
916
917 rx = self.pg2.get_capture(1)
918 self.verify_arp_resp(rx[0],
919 self.pg2.local_mac,
920 self.pg2.remote_mac,
921 "10.10.10.3",
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700922 self.pg1.remote_hosts[1].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800923
924 #
925 # A request for an address out of the configured range
926 #
927 arp_req_pg1_hi = (Ether(src=self.pg1.remote_mac,
928 dst="ff:ff:ff:ff:ff:ff") /
929 ARP(op="who-has",
930 hwsrc=self.pg1.remote_mac,
931 pdst="10.10.10.125",
932 psrc=self.pg1.remote_ip4))
933 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_hi,
934 "ARP req out of range HI")
935 arp_req_pg1_low = (Ether(src=self.pg1.remote_mac,
936 dst="ff:ff:ff:ff:ff:ff") /
937 ARP(op="who-has",
938 hwsrc=self.pg1.remote_mac,
939 pdst="10.10.10.1",
940 psrc=self.pg1.remote_ip4))
941 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_low,
942 "ARP req out of range Low")
943
944 #
945 # Request for an address in the proxy range but from an interface
946 # in a different VRF
947 #
948 self.send_and_assert_no_replies(self.pg3, arp_req_pg3,
949 "ARP req from different VRF")
950
951 #
952 # Disable Each interface for proxy ARP
953 # - expect none to respond
954 #
955 for i in self.pg_interfaces:
956 i.set_proxy_arp(0)
957
958 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
959 "ARP req from disable")
960 self.send_and_assert_no_replies(self.pg1, arp_req_pg1,
961 "ARP req from disable")
962 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
963 "ARP req from disable")
Neale Ranns37be7362017-02-21 17:30:26 -0800964
965 #
966 # clean up on interface 2
967 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800968 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns37be7362017-02-21 17:30:26 -0800969
970 def test_mpls(self):
971 """ MPLS """
972
973 #
974 # Interface 2 does not yet have ip4 config
975 #
976 self.pg2.config_ip4()
977 self.pg2.generate_remote_hosts(2)
978
979 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700980 # Add a route with out going label via an ARP unresolved next-hop
Neale Ranns37be7362017-02-21 17:30:26 -0800981 #
982 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
983 [VppRoutePath(self.pg2.remote_hosts[1].ip4,
984 self.pg2.sw_if_index,
985 labels=[55])])
986 ip_10_0_0_1.add_vpp_config()
987
988 #
989 # packets should generate an ARP request
990 #
991 p = (Ether(src=self.pg0.remote_mac,
992 dst=self.pg0.local_mac) /
993 IP(src=self.pg0.remote_ip4, dst="10.0.0.1") /
994 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +0100995 Raw(b'\xa5' * 100))
Neale Ranns37be7362017-02-21 17:30:26 -0800996
997 self.pg0.add_stream(p)
998 self.pg_enable_capture(self.pg_interfaces)
999 self.pg_start()
1000
1001 rx = self.pg2.get_capture(1)
1002 self.verify_arp_req(rx[0],
1003 self.pg2.local_mac,
1004 self.pg2.local_ip4,
1005 self.pg2._remote_hosts[1].ip4)
1006
1007 #
1008 # now resolve the neighbours
1009 #
1010 self.pg2.configure_ipv4_neighbors()
1011
1012 #
1013 # Now packet should be properly MPLS encapped.
1014 # This verifies that MPLS link-type adjacencies are completed
1015 # when the ARP entry resolves
1016 #
1017 self.pg0.add_stream(p)
1018 self.pg_enable_capture(self.pg_interfaces)
1019 self.pg_start()
1020
1021 rx = self.pg2.get_capture(1)
1022 self.verify_ip_o_mpls(rx[0],
1023 self.pg2.local_mac,
1024 self.pg2.remote_hosts[1].mac,
1025 55,
1026 self.pg0.remote_ip4,
1027 "10.0.0.1")
Neale Ranns4b919a52017-03-11 05:55:21 -08001028 self.pg2.unconfig_ip4()
Neale Ranns37be7362017-02-21 17:30:26 -08001029
Matthew Smithcb9ab472017-05-16 21:35:56 -05001030 def test_arp_vrrp(self):
1031 """ ARP reply with VRRP virtual src hw addr """
1032
1033 #
1034 # IP packet destined for pg1 remote host arrives on pg0 resulting
1035 # in an ARP request for the address of the remote host on pg1
1036 #
1037 p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1038 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1039 UDP(sport=1234, dport=1234) /
1040 Raw())
1041
Neale Ranns37029302018-08-10 05:30:06 -07001042 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
Matthew Smithcb9ab472017-05-16 21:35:56 -05001043
1044 self.verify_arp_req(rx1[0],
1045 self.pg1.local_mac,
1046 self.pg1.local_ip4,
1047 self.pg1.remote_ip4)
1048
1049 #
1050 # ARP reply for address of pg1 remote host arrives on pg1 with
1051 # the hw src addr set to a value in the VRRP IPv4 range of
1052 # MAC addresses
1053 #
1054 p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1055 ARP(op="is-at", hwdst=self.pg1.local_mac,
1056 hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
1057 psrc=self.pg1.remote_ip4))
1058
Neale Ranns37029302018-08-10 05:30:06 -07001059 self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
Matthew Smithcb9ab472017-05-16 21:35:56 -05001060
1061 #
1062 # IP packet destined for pg1 remote host arrives on pg0 again.
1063 # VPP should have an ARP entry for that address now and the packet
1064 # should be sent out pg1.
1065 #
Neale Ranns37029302018-08-10 05:30:06 -07001066 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
Matthew Smithcb9ab472017-05-16 21:35:56 -05001067
1068 self.verify_ip(rx1[0],
1069 self.pg1.local_mac,
1070 "00:00:5e:00:01:09",
1071 self.pg0.remote_ip4,
1072 self.pg1.remote_ip4)
1073
1074 self.pg1.admin_down()
1075 self.pg1.admin_up()
1076
Neale Rannsdcd6d622017-05-26 02:59:16 -07001077 def test_arp_duplicates(self):
1078 """ ARP Duplicates"""
1079
1080 #
1081 # Generate some hosts on the LAN
1082 #
1083 self.pg1.generate_remote_hosts(3)
1084
1085 #
1086 # Add host 1 on pg1 and pg2
1087 #
1088 arp_pg1 = VppNeighbor(self,
1089 self.pg1.sw_if_index,
1090 self.pg1.remote_hosts[1].mac,
1091 self.pg1.remote_hosts[1].ip4)
1092 arp_pg1.add_vpp_config()
1093 arp_pg2 = VppNeighbor(self,
1094 self.pg2.sw_if_index,
1095 self.pg2.remote_mac,
1096 self.pg1.remote_hosts[1].ip4)
1097 arp_pg2.add_vpp_config()
1098
1099 #
1100 # IP packet destined for pg1 remote host arrives on pg1 again.
1101 #
1102 p = (Ether(dst=self.pg0.local_mac,
1103 src=self.pg0.remote_mac) /
1104 IP(src=self.pg0.remote_ip4,
1105 dst=self.pg1.remote_hosts[1].ip4) /
1106 UDP(sport=1234, dport=1234) /
1107 Raw())
1108
1109 self.pg0.add_stream(p)
1110 self.pg_enable_capture(self.pg_interfaces)
1111 self.pg_start()
1112
1113 rx1 = self.pg1.get_capture(1)
1114
1115 self.verify_ip(rx1[0],
1116 self.pg1.local_mac,
1117 self.pg1.remote_hosts[1].mac,
1118 self.pg0.remote_ip4,
1119 self.pg1.remote_hosts[1].ip4)
1120
1121 #
1122 # remove the duplicate on pg1
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001123 # packet stream should generate ARPs out of pg1
Neale Rannsdcd6d622017-05-26 02:59:16 -07001124 #
1125 arp_pg1.remove_vpp_config()
1126
1127 self.pg0.add_stream(p)
1128 self.pg_enable_capture(self.pg_interfaces)
1129 self.pg_start()
1130
1131 rx1 = self.pg1.get_capture(1)
1132
1133 self.verify_arp_req(rx1[0],
1134 self.pg1.local_mac,
1135 self.pg1.local_ip4,
1136 self.pg1.remote_hosts[1].ip4)
1137
1138 #
1139 # Add it back
1140 #
1141 arp_pg1.add_vpp_config()
1142
1143 self.pg0.add_stream(p)
1144 self.pg_enable_capture(self.pg_interfaces)
1145 self.pg_start()
1146
1147 rx1 = self.pg1.get_capture(1)
1148
1149 self.verify_ip(rx1[0],
1150 self.pg1.local_mac,
1151 self.pg1.remote_hosts[1].mac,
1152 self.pg0.remote_ip4,
1153 self.pg1.remote_hosts[1].ip4)
1154
Neale Ranns15002542017-09-10 04:39:11 -07001155 def test_arp_static(self):
1156 """ ARP Static"""
1157 self.pg2.generate_remote_hosts(3)
1158
1159 #
1160 # Add a static ARP entry
1161 #
1162 static_arp = VppNeighbor(self,
1163 self.pg2.sw_if_index,
1164 self.pg2.remote_hosts[1].mac,
1165 self.pg2.remote_hosts[1].ip4,
1166 is_static=1)
1167 static_arp.add_vpp_config()
1168
1169 #
1170 # Add the connected prefix to the interface
1171 #
1172 self.pg2.config_ip4()
1173
1174 #
1175 # We should now find the adj-fib
1176 #
1177 self.assertTrue(find_nbr(self,
1178 self.pg2.sw_if_index,
1179 self.pg2.remote_hosts[1].ip4,
1180 is_static=1))
1181 self.assertTrue(find_route(self,
1182 self.pg2.remote_hosts[1].ip4,
1183 32))
1184
1185 #
1186 # remove the connected
1187 #
1188 self.pg2.unconfig_ip4()
1189
1190 #
1191 # put the interface into table 1
1192 #
1193 self.pg2.set_table_ip4(1)
1194
1195 #
1196 # configure the same connected and expect to find the
1197 # adj fib in the new table
1198 #
1199 self.pg2.config_ip4()
1200 self.assertTrue(find_route(self,
1201 self.pg2.remote_hosts[1].ip4,
1202 32,
1203 table_id=1))
1204
1205 #
1206 # clean-up
1207 #
1208 self.pg2.unconfig_ip4()
Neale Rannscbe25aa2019-09-30 10:53:31 +00001209 static_arp.remove_vpp_config()
Neale Ranns15002542017-09-10 04:39:11 -07001210 self.pg2.set_table_ip4(0)
1211
Neale Rannsc819fc62018-02-16 02:44:05 -08001212 def test_arp_incomplete(self):
1213 """ ARP Incomplete"""
1214 self.pg1.generate_remote_hosts(3)
1215
1216 p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1217 IP(src=self.pg0.remote_ip4,
1218 dst=self.pg1.remote_hosts[1].ip4) /
1219 UDP(sport=1234, dport=1234) /
1220 Raw())
1221 p1 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1222 IP(src=self.pg0.remote_ip4,
1223 dst=self.pg1.remote_hosts[2].ip4) /
1224 UDP(sport=1234, dport=1234) /
1225 Raw())
1226
1227 #
1228 # a packet to an unresolved destination generates an ARP request
1229 #
1230 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1231 self.verify_arp_req(rx[0],
1232 self.pg1.local_mac,
1233 self.pg1.local_ip4,
1234 self.pg1._remote_hosts[1].ip4)
1235
1236 #
1237 # add a neighbour for remote host 1
1238 #
1239 static_arp = VppNeighbor(self,
1240 self.pg1.sw_if_index,
1241 self.pg1.remote_hosts[1].mac,
1242 self.pg1.remote_hosts[1].ip4,
1243 is_static=1)
1244 static_arp.add_vpp_config()
1245
1246 #
1247 # change the interface's MAC
1248 #
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -07001249 mac = [scapy.compat.chb(0x00), scapy.compat.chb(0x00),
1250 scapy.compat.chb(0x00), scapy.compat.chb(0x33),
1251 scapy.compat.chb(0x33), scapy.compat.chb(0x33)]
Neale Rannsc819fc62018-02-16 02:44:05 -08001252 mac_string = ''.join(mac)
1253
1254 self.vapi.sw_interface_set_mac_address(self.pg1.sw_if_index,
1255 mac_string)
1256
1257 #
1258 # now ARP requests come from the new source mac
1259 #
1260 rx = self.send_and_expect(self.pg0, [p1], self.pg1)
1261 self.verify_arp_req(rx[0],
1262 "00:00:00:33:33:33",
1263 self.pg1.local_ip4,
1264 self.pg1._remote_hosts[2].ip4)
1265
1266 #
1267 # packets to the resolved host also have the new source mac
1268 #
1269 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1270 self.verify_ip(rx[0],
1271 "00:00:00:33:33:33",
1272 self.pg1.remote_hosts[1].mac,
1273 self.pg0.remote_ip4,
1274 self.pg1.remote_hosts[1].ip4)
1275
1276 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001277 # set the mac address on the interface that does not have a
Neale Rannsc819fc62018-02-16 02:44:05 -08001278 # configured subnet and thus no glean
1279 #
1280 self.vapi.sw_interface_set_mac_address(self.pg2.sw_if_index,
1281 mac_string)
1282
Neale Ranns59ae61e2018-06-07 18:09:49 -07001283 def test_garp(self):
1284 """ GARP """
1285
1286 #
1287 # Generate some hosts on the LAN
1288 #
1289 self.pg1.generate_remote_hosts(4)
1290
1291 #
1292 # And an ARP entry
1293 #
1294 arp = VppNeighbor(self,
1295 self.pg1.sw_if_index,
1296 self.pg1.remote_hosts[1].mac,
1297 self.pg1.remote_hosts[1].ip4)
1298 arp.add_vpp_config()
1299
1300 self.assertTrue(find_nbr(self,
1301 self.pg1.sw_if_index,
1302 self.pg1.remote_hosts[1].ip4,
1303 mac=self.pg1.remote_hosts[1].mac))
1304
1305 #
1306 # Send a GARP (request) to swap the host 1's address to that of host 2
1307 #
1308 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1309 src=self.pg1.remote_hosts[2].mac) /
1310 ARP(op="who-has",
1311 hwdst=self.pg1.local_mac,
1312 hwsrc=self.pg1.remote_hosts[2].mac,
1313 pdst=self.pg1.remote_hosts[1].ip4,
1314 psrc=self.pg1.remote_hosts[1].ip4))
1315
1316 self.pg1.add_stream(p1)
1317 self.pg_enable_capture(self.pg_interfaces)
1318 self.pg_start()
1319
1320 self.assertTrue(find_nbr(self,
1321 self.pg1.sw_if_index,
1322 self.pg1.remote_hosts[1].ip4,
1323 mac=self.pg1.remote_hosts[2].mac))
1324
1325 #
1326 # Send a GARP (reply) to swap the host 1's address to that of host 3
1327 #
1328 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1329 src=self.pg1.remote_hosts[3].mac) /
1330 ARP(op="is-at",
1331 hwdst=self.pg1.local_mac,
1332 hwsrc=self.pg1.remote_hosts[3].mac,
1333 pdst=self.pg1.remote_hosts[1].ip4,
1334 psrc=self.pg1.remote_hosts[1].ip4))
1335
1336 self.pg1.add_stream(p1)
1337 self.pg_enable_capture(self.pg_interfaces)
1338 self.pg_start()
1339
1340 self.assertTrue(find_nbr(self,
1341 self.pg1.sw_if_index,
1342 self.pg1.remote_hosts[1].ip4,
1343 mac=self.pg1.remote_hosts[3].mac))
1344
1345 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001346 # GARPs (request nor replies) for host we don't know yet
Neale Ranns59ae61e2018-06-07 18:09:49 -07001347 # don't result in new neighbour entries
1348 #
1349 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1350 src=self.pg1.remote_hosts[3].mac) /
1351 ARP(op="who-has",
1352 hwdst=self.pg1.local_mac,
1353 hwsrc=self.pg1.remote_hosts[3].mac,
1354 pdst=self.pg1.remote_hosts[2].ip4,
1355 psrc=self.pg1.remote_hosts[2].ip4))
1356
1357 self.pg1.add_stream(p1)
1358 self.pg_enable_capture(self.pg_interfaces)
1359 self.pg_start()
1360
1361 self.assertFalse(find_nbr(self,
1362 self.pg1.sw_if_index,
1363 self.pg1.remote_hosts[2].ip4))
1364
1365 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1366 src=self.pg1.remote_hosts[3].mac) /
1367 ARP(op="is-at",
1368 hwdst=self.pg1.local_mac,
1369 hwsrc=self.pg1.remote_hosts[3].mac,
1370 pdst=self.pg1.remote_hosts[2].ip4,
1371 psrc=self.pg1.remote_hosts[2].ip4))
1372
1373 self.pg1.add_stream(p1)
1374 self.pg_enable_capture(self.pg_interfaces)
1375 self.pg_start()
1376
1377 self.assertFalse(find_nbr(self,
1378 self.pg1.sw_if_index,
1379 self.pg1.remote_hosts[2].ip4))
1380
Neale Rannsc8352bc2018-08-29 10:23:58 -07001381 def test_arp_incomplete(self):
Neale Ranns14260392018-09-28 05:00:57 -07001382 """ Incomplete Entries """
Neale Rannsc8352bc2018-08-29 10:23:58 -07001383
1384 #
Neale Rannscd35e532018-08-31 02:51:45 -07001385 # ensure that we throttle the ARP and ND requests
Neale Rannsc8352bc2018-08-29 10:23:58 -07001386 #
1387 self.pg0.generate_remote_hosts(2)
1388
Neale Rannscd35e532018-08-31 02:51:45 -07001389 #
1390 # IPv4/ARP
1391 #
Neale Rannsc8352bc2018-08-29 10:23:58 -07001392 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1393 [VppRoutePath(self.pg0.remote_hosts[1].ip4,
Neale Rannscd35e532018-08-31 02:51:45 -07001394 self.pg0.sw_if_index)])
Neale Rannsc8352bc2018-08-29 10:23:58 -07001395 ip_10_0_0_1.add_vpp_config()
1396
1397 p1 = (Ether(dst=self.pg1.local_mac,
1398 src=self.pg1.remote_mac) /
1399 IP(src=self.pg1.remote_ip4,
1400 dst="10.0.0.1") /
1401 UDP(sport=1234, dport=1234) /
1402 Raw())
1403
1404 self.pg1.add_stream(p1 * 257)
1405 self.pg_enable_capture(self.pg_interfaces)
1406 self.pg_start()
1407 rx = self.pg0._get_capture(1)
1408
1409 #
1410 # how many we get is going to be dependent on the time for packet
1411 # processing but it should be small
1412 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001413 self.assertLess(len(rx), 64)
Neale Rannsc8352bc2018-08-29 10:23:58 -07001414
Neale Rannscd35e532018-08-31 02:51:45 -07001415 #
1416 # IPv6/ND
1417 #
1418 ip_10_1 = VppIpRoute(self, "10::1", 128,
1419 [VppRoutePath(self.pg0.remote_hosts[1].ip6,
1420 self.pg0.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07001421 proto=DpoProto.DPO_PROTO_IP6)])
Neale Rannscd35e532018-08-31 02:51:45 -07001422 ip_10_1.add_vpp_config()
1423
1424 p1 = (Ether(dst=self.pg1.local_mac,
1425 src=self.pg1.remote_mac) /
1426 IPv6(src=self.pg1.remote_ip6,
1427 dst="10::1") /
1428 UDP(sport=1234, dport=1234) /
1429 Raw())
1430
1431 self.pg1.add_stream(p1 * 257)
1432 self.pg_enable_capture(self.pg_interfaces)
1433 self.pg_start()
1434 rx = self.pg0._get_capture(1)
1435
1436 #
1437 # how many we get is going to be dependent on the time for packet
1438 # processing but it should be small
1439 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001440 self.assertLess(len(rx), 64)
Neale Rannscd35e532018-08-31 02:51:45 -07001441
Neale Ranns7425f922019-01-23 00:36:16 -08001442 def test_arp_forus(self):
1443 """ ARP for for-us """
1444
1445 #
1446 # Test that VPP responds with ARP requests to addresses that
1447 # are connected and local routes.
1448 # Use one of the 'remote' addresses in the subnet as a local address
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001449 # The intention of this route is that it then acts like a secondary
Neale Ranns7425f922019-01-23 00:36:16 -08001450 # address added to an interface
1451 #
1452 self.pg0.generate_remote_hosts(2)
1453
Neale Ranns097fa662018-05-01 05:17:55 -07001454 forus = VppIpRoute(
1455 self, self.pg0.remote_hosts[1].ip4, 32,
1456 [VppRoutePath("0.0.0.0",
1457 self.pg0.sw_if_index,
1458 type=FibPathType.FIB_PATH_TYPE_LOCAL)])
Neale Ranns7425f922019-01-23 00:36:16 -08001459 forus.add_vpp_config()
1460
1461 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
1462 src=self.pg0.remote_mac) /
1463 ARP(op="who-has",
1464 hwdst=self.pg0.local_mac,
1465 hwsrc=self.pg0.remote_mac,
1466 pdst=self.pg0.remote_hosts[1].ip4,
1467 psrc=self.pg0.remote_ip4))
1468
1469 rx = self.send_and_expect(self.pg0, [p], self.pg0)
1470
1471 self.verify_arp_resp(rx[0],
1472 self.pg0.local_mac,
1473 self.pg0.remote_mac,
1474 self.pg0.remote_hosts[1].ip4,
1475 self.pg0.remote_ip4)
1476
Neale Rannsfca3c6a2019-12-31 03:49:34 +00001477 def test_arp_table_swap(self):
1478 #
1479 # Generate some hosts on the LAN
1480 #
1481 N_NBRS = 4
1482 self.pg1.generate_remote_hosts(N_NBRS)
1483
1484 for n in range(N_NBRS):
1485 # a route thru each neighbour
1486 VppIpRoute(self, "10.0.0.%d" % n, 32,
1487 [VppRoutePath(self.pg1.remote_hosts[n].ip4,
1488 self.pg1.sw_if_index)]).add_vpp_config()
1489
1490 # resolve each neighbour
1491 p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1492 ARP(op="is-at", hwdst=self.pg1.local_mac,
1493 hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
1494 psrc=self.pg1.remote_hosts[n].ip4))
1495
1496 self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
1497
1498 self.logger.info(self.vapi.cli("sh ip neighbors"))
1499
1500 #
1501 # swap the table pg1 is in
1502 #
1503 table = VppIpTable(self, 100).add_vpp_config()
1504
1505 self.pg1.unconfig_ip4()
1506 self.pg1.set_table_ip4(100)
1507 self.pg1.config_ip4()
1508
1509 #
1510 # all neighbours are cleared
1511 #
1512 for n in range(N_NBRS):
1513 self.assertFalse(find_nbr(self,
1514 self.pg1.sw_if_index,
1515 self.pg1.remote_hosts[n].ip4))
1516
1517 #
1518 # packets to all neighbours generate ARP requests
1519 #
1520 for n in range(N_NBRS):
1521 # a route thru each neighbour
1522 VppIpRoute(self, "10.0.0.%d" % n, 32,
1523 [VppRoutePath(self.pg1.remote_hosts[n].ip4,
1524 self.pg1.sw_if_index)],
1525 table_id=100).add_vpp_config()
1526
1527 p = (Ether(src=self.pg1.remote_hosts[n].mac,
1528 dst=self.pg1.local_mac) /
1529 IP(src=self.pg1.remote_hosts[n].ip4,
1530 dst="10.0.0.%d" % n) /
1531 Raw(b'0x5' * 100))
1532 rxs = self.send_and_expect(self.pg1, [p], self.pg1)
1533 for rx in rxs:
1534 self.verify_arp_req(rx,
1535 self.pg1.local_mac,
1536 self.pg1.local_ip4,
1537 self.pg1.remote_hosts[n].ip4)
1538
1539 self.pg1.unconfig_ip4()
1540 self.pg1.set_table_ip4(0)
1541
Neale Rannsdcd6d622017-05-26 02:59:16 -07001542
Neale Ranns14260392018-09-28 05:00:57 -07001543class NeighborStatsTestCase(VppTestCase):
Neale Ranns37029302018-08-10 05:30:06 -07001544 """ ARP/ND Counters """
Neale Ranns14260392018-09-28 05:00:57 -07001545
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001546 @classmethod
1547 def setUpClass(cls):
1548 super(NeighborStatsTestCase, cls).setUpClass()
1549
1550 @classmethod
1551 def tearDownClass(cls):
1552 super(NeighborStatsTestCase, cls).tearDownClass()
1553
Neale Ranns14260392018-09-28 05:00:57 -07001554 def setUp(self):
1555 super(NeighborStatsTestCase, self).setUp()
1556
1557 self.create_pg_interfaces(range(2))
1558
1559 # pg0 configured with ip4 and 6 addresses used for input
1560 # pg1 configured with ip4 and 6 addresses used for output
1561 # pg2 is unnumbered to pg0
1562 for i in self.pg_interfaces:
1563 i.admin_up()
1564 i.config_ip4()
1565 i.config_ip6()
1566 i.resolve_arp()
1567 i.resolve_ndp()
1568
1569 def tearDown(self):
1570 super(NeighborStatsTestCase, self).tearDown()
1571
1572 for i in self.pg_interfaces:
1573 i.unconfig_ip4()
1574 i.unconfig_ip6()
1575 i.admin_down()
1576
1577 def test_arp_stats(self):
1578 """ ARP Counters """
1579
1580 self.vapi.cli("adj counters enable")
1581 self.pg1.generate_remote_hosts(2)
1582
1583 arp1 = VppNeighbor(self,
1584 self.pg1.sw_if_index,
1585 self.pg1.remote_hosts[0].mac,
1586 self.pg1.remote_hosts[0].ip4)
1587 arp1.add_vpp_config()
1588 arp2 = VppNeighbor(self,
1589 self.pg1.sw_if_index,
1590 self.pg1.remote_hosts[1].mac,
1591 self.pg1.remote_hosts[1].ip4)
1592 arp2.add_vpp_config()
1593
1594 p1 = (Ether(dst=self.pg0.local_mac,
1595 src=self.pg0.remote_mac) /
1596 IP(src=self.pg0.remote_ip4,
1597 dst=self.pg1.remote_hosts[0].ip4) /
1598 UDP(sport=1234, dport=1234) /
1599 Raw())
1600 p2 = (Ether(dst=self.pg0.local_mac,
1601 src=self.pg0.remote_mac) /
1602 IP(src=self.pg0.remote_ip4,
1603 dst=self.pg1.remote_hosts[1].ip4) /
1604 UDP(sport=1234, dport=1234) /
1605 Raw())
1606
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001607 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
1608 rx = self.send_and_expect(self.pg0, p2 * NUM_PKTS, self.pg1)
Neale Ranns14260392018-09-28 05:00:57 -07001609
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001610 self.assertEqual(NUM_PKTS, arp1.get_stats()['packets'])
1611 self.assertEqual(NUM_PKTS, arp2.get_stats()['packets'])
Neale Ranns14260392018-09-28 05:00:57 -07001612
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001613 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
1614 self.assertEqual(NUM_PKTS*2, arp1.get_stats()['packets'])
Neale Ranns14260392018-09-28 05:00:57 -07001615
1616 def test_nd_stats(self):
1617 """ ND Counters """
1618
1619 self.vapi.cli("adj counters enable")
1620 self.pg0.generate_remote_hosts(3)
1621
1622 nd1 = VppNeighbor(self,
1623 self.pg0.sw_if_index,
1624 self.pg0.remote_hosts[1].mac,
Neale Ranns37029302018-08-10 05:30:06 -07001625 self.pg0.remote_hosts[1].ip6)
Neale Ranns14260392018-09-28 05:00:57 -07001626 nd1.add_vpp_config()
1627 nd2 = VppNeighbor(self,
1628 self.pg0.sw_if_index,
1629 self.pg0.remote_hosts[2].mac,
Neale Ranns37029302018-08-10 05:30:06 -07001630 self.pg0.remote_hosts[2].ip6)
Neale Ranns14260392018-09-28 05:00:57 -07001631 nd2.add_vpp_config()
1632
1633 p1 = (Ether(dst=self.pg1.local_mac,
1634 src=self.pg1.remote_mac) /
1635 IPv6(src=self.pg1.remote_ip6,
1636 dst=self.pg0.remote_hosts[1].ip6) /
1637 UDP(sport=1234, dport=1234) /
1638 Raw())
1639 p2 = (Ether(dst=self.pg1.local_mac,
1640 src=self.pg1.remote_mac) /
1641 IPv6(src=self.pg1.remote_ip6,
1642 dst=self.pg0.remote_hosts[2].ip6) /
1643 UDP(sport=1234, dport=1234) /
1644 Raw())
1645
1646 rx = self.send_and_expect(self.pg1, p1 * 16, self.pg0)
1647 rx = self.send_and_expect(self.pg1, p2 * 16, self.pg0)
1648
1649 self.assertEqual(16, nd1.get_stats()['packets'])
1650 self.assertEqual(16, nd2.get_stats()['packets'])
1651
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001652 rx = self.send_and_expect(self.pg1, p1 * NUM_PKTS, self.pg0)
1653 self.assertEqual(NUM_PKTS+16, nd1.get_stats()['packets'])
Neale Ranns14260392018-09-28 05:00:57 -07001654
1655
Neale Rannscbe25aa2019-09-30 10:53:31 +00001656class NeighborAgeTestCase(VppTestCase):
1657 """ ARP/ND Aging """
1658
1659 @classmethod
1660 def setUpClass(cls):
1661 super(NeighborAgeTestCase, cls).setUpClass()
1662
1663 @classmethod
1664 def tearDownClass(cls):
1665 super(NeighborAgeTestCase, cls).tearDownClass()
1666
1667 def setUp(self):
1668 super(NeighborAgeTestCase, self).setUp()
1669
1670 self.create_pg_interfaces(range(1))
1671
1672 # pg0 configured with ip4 and 6 addresses used for input
1673 # pg1 configured with ip4 and 6 addresses used for output
1674 # pg2 is unnumbered to pg0
1675 for i in self.pg_interfaces:
1676 i.admin_up()
1677 i.config_ip4()
1678 i.config_ip6()
1679 i.resolve_arp()
1680 i.resolve_ndp()
1681
1682 def tearDown(self):
1683 super(NeighborAgeTestCase, self).tearDown()
1684
1685 for i in self.pg_interfaces:
1686 i.unconfig_ip4()
1687 i.unconfig_ip6()
1688 i.admin_down()
1689
1690 def wait_for_no_nbr(self, intf, address,
1691 n_tries=50, s_time=1):
1692 while (n_tries):
1693 if not find_nbr(self, intf, address):
1694 return True
1695 n_tries = n_tries - 1
1696 self.sleep(s_time)
1697
1698 return False
1699
1700 def verify_arp_req(self, rx, smac, sip, dip):
1701 ether = rx[Ether]
1702 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
1703 self.assertEqual(ether.src, smac)
1704
1705 arp = rx[ARP]
1706 self.assertEqual(arp.hwtype, 1)
1707 self.assertEqual(arp.ptype, 0x800)
1708 self.assertEqual(arp.hwlen, 6)
1709 self.assertEqual(arp.plen, 4)
1710 self.assertEqual(arp.op, arp_opts["who-has"])
1711 self.assertEqual(arp.hwsrc, smac)
1712 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
1713 self.assertEqual(arp.psrc, sip)
1714 self.assertEqual(arp.pdst, dip)
1715
1716 def test_age(self):
1717 """ Aging/Recycle """
1718
1719 self.vapi.cli("set logging unthrottle 0")
1720 self.vapi.cli("set logging size %d" % 0xffff)
1721
1722 self.pg0.generate_remote_hosts(201)
1723
1724 vaf = VppEnum.vl_api_address_family_t
1725
1726 #
1727 # start listening on all interfaces
1728 #
1729 self.pg_enable_capture(self.pg_interfaces)
1730
1731 #
1732 # Set the neighbor configuration:
1733 # limi = 200
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03001734 # age = 0 seconds
Neale Rannscbe25aa2019-09-30 10:53:31 +00001735 # recycle = false
1736 #
1737 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
1738 max_number=200,
1739 max_age=0,
1740 recycle=False)
1741
1742 self.vapi.cli("sh ip neighbor-config")
1743
1744 # add the 198 neighbours that should pass (-1 for one created in setup)
1745 for ii in range(200):
1746 VppNeighbor(self,
1747 self.pg0.sw_if_index,
1748 self.pg0.remote_hosts[ii].mac,
1749 self.pg0.remote_hosts[ii].ip4).add_vpp_config()
1750
1751 # one more neighbor over the limit should fail
1752 with self.vapi.assert_negative_api_retval():
1753 VppNeighbor(self,
1754 self.pg0.sw_if_index,
1755 self.pg0.remote_hosts[200].mac,
1756 self.pg0.remote_hosts[200].ip4).add_vpp_config()
1757
1758 #
1759 # change the config to allow recycling the old neighbors
1760 #
1761 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
1762 max_number=200,
1763 max_age=0,
1764 recycle=True)
1765
1766 # now new additions are allowed
1767 VppNeighbor(self,
1768 self.pg0.sw_if_index,
1769 self.pg0.remote_hosts[200].mac,
1770 self.pg0.remote_hosts[200].ip4).add_vpp_config()
1771
1772 # add the first neighbor we configured has been re-used
1773 self.assertFalse(find_nbr(self,
1774 self.pg0.sw_if_index,
1775 self.pg0.remote_hosts[0].ip4))
1776 self.assertTrue(find_nbr(self,
1777 self.pg0.sw_if_index,
1778 self.pg0.remote_hosts[200].ip4))
1779
1780 #
1781 # change the config to age old neighbors
1782 #
1783 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
1784 max_number=200,
1785 max_age=2,
1786 recycle=True)
1787
1788 self.vapi.cli("sh ip4 neighbor-sorted")
1789
1790 #
1791 # expect probes from all these ARP entries as they age
1792 # 3 probes for each neighbor 3*200 = 600
1793 rxs = self.pg0.get_capture(600, timeout=8)
1794
1795 for ii in range(3):
1796 for jj in range(200):
1797 rx = rxs[ii*200 + jj]
1798 # rx.show()
1799
1800 #
1801 # 3 probes sent then 1 more second to see if a reply comes, before
1802 # they age out
1803 #
1804 for jj in range(1, 201):
1805 self.wait_for_no_nbr(self.pg0.sw_if_index,
1806 self.pg0.remote_hosts[jj].ip4)
1807
1808 self.assertFalse(self.vapi.ip_neighbor_dump(sw_if_index=0xffffffff,
1809 af=vaf.ADDRESS_IP4))
1810
1811 #
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03001812 # load up some neighbours again with 2s aging enabled
1813 # they should be removed after 10s (2s age + 4s for probes + gap)
1814 #
1815 for ii in range(10):
1816 VppNeighbor(self,
1817 self.pg0.sw_if_index,
1818 self.pg0.remote_hosts[ii].mac,
1819 self.pg0.remote_hosts[ii].ip4).add_vpp_config()
1820 self.sleep(10)
1821 self.assertFalse(self.vapi.ip_neighbor_dump(sw_if_index=0xffffffff,
1822 af=vaf.ADDRESS_IP4))
1823
1824 #
1825 # check if we can set age and recycle with empty neighbor list
1826 #
1827 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
1828 max_number=200,
1829 max_age=1000,
1830 recycle=True)
1831
1832 #
Neale Rannscbe25aa2019-09-30 10:53:31 +00001833 # load up some neighbours again, then disable the aging
1834 # they should still be there in 10 seconds time
1835 #
1836 for ii in range(10):
1837 VppNeighbor(self,
1838 self.pg0.sw_if_index,
1839 self.pg0.remote_hosts[ii].mac,
1840 self.pg0.remote_hosts[ii].ip4).add_vpp_config()
1841 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
1842 max_number=200,
1843 max_age=0,
1844 recycle=False)
1845
1846 self.sleep(10)
1847 self.assertTrue(find_nbr(self,
1848 self.pg0.sw_if_index,
1849 self.pg0.remote_hosts[0].ip4))
1850
1851
Neale Rannsc87fbb42020-04-02 17:08:28 +00001852class NeighborReplaceTestCase(VppTestCase):
1853 """ ARP/ND Replacement """
1854
1855 @classmethod
1856 def setUpClass(cls):
1857 super(NeighborReplaceTestCase, cls).setUpClass()
1858
1859 @classmethod
1860 def tearDownClass(cls):
1861 super(NeighborReplaceTestCase, cls).tearDownClass()
1862
1863 def setUp(self):
1864 super(NeighborReplaceTestCase, self).setUp()
1865
1866 self.create_pg_interfaces(range(4))
1867
1868 # pg0 configured with ip4 and 6 addresses used for input
1869 # pg1 configured with ip4 and 6 addresses used for output
1870 # pg2 is unnumbered to pg0
1871 for i in self.pg_interfaces:
1872 i.admin_up()
1873 i.config_ip4()
1874 i.config_ip6()
1875 i.resolve_arp()
1876 i.resolve_ndp()
1877
1878 def tearDown(self):
1879 super(NeighborReplaceTestCase, self).tearDown()
1880
1881 for i in self.pg_interfaces:
1882 i.unconfig_ip4()
1883 i.unconfig_ip6()
1884 i.admin_down()
1885
1886 def test_replace(self):
1887 """ replace """
1888
1889 N_HOSTS = 16
1890
1891 for i in self.pg_interfaces:
1892 i.generate_remote_hosts(N_HOSTS)
1893 i.configure_ipv4_neighbors()
1894 i.configure_ipv6_neighbors()
1895
1896 # replace them all
1897 self.vapi.ip_neighbor_replace_begin()
1898 self.vapi.ip_neighbor_replace_end()
1899
1900 for i in self.pg_interfaces:
1901 for h in range(N_HOSTS):
1902 self.assertFalse(find_nbr(self,
1903 self.pg0.sw_if_index,
1904 self.pg0.remote_hosts[h].ip4))
1905 self.assertFalse(find_nbr(self,
1906 self.pg0.sw_if_index,
1907 self.pg0.remote_hosts[h].ip6))
1908
1909 #
1910 # and them all back via the API
1911 #
1912 for i in self.pg_interfaces:
1913 for h in range(N_HOSTS):
1914 VppNeighbor(self,
1915 i.sw_if_index,
1916 i.remote_hosts[h].mac,
1917 i.remote_hosts[h].ip4).add_vpp_config()
1918 VppNeighbor(self,
1919 i.sw_if_index,
1920 i.remote_hosts[h].mac,
1921 i.remote_hosts[h].ip6).add_vpp_config()
1922
1923 #
1924 # begin the replacement again, this time touch some
1925 # the neighbours on pg1 so they are not deleted
1926 #
1927 self.vapi.ip_neighbor_replace_begin()
1928
1929 # update from the API all neighbours on pg1
1930 for h in range(N_HOSTS):
1931 VppNeighbor(self,
1932 self.pg1.sw_if_index,
1933 self.pg1.remote_hosts[h].mac,
1934 self.pg1.remote_hosts[h].ip4).add_vpp_config()
1935 VppNeighbor(self,
1936 self.pg1.sw_if_index,
1937 self.pg1.remote_hosts[h].mac,
1938 self.pg1.remote_hosts[h].ip6).add_vpp_config()
1939
1940 # update from the data-plane all neighbours on pg3
1941 self.pg3.configure_ipv4_neighbors()
1942 self.pg3.configure_ipv6_neighbors()
1943
1944 # complete the replacement
1945 self.logger.info(self.vapi.cli("sh ip neighbors"))
1946 self.vapi.ip_neighbor_replace_end()
1947
1948 for i in self.pg_interfaces:
1949 if i == self.pg1 or i == self.pg3:
1950 # neighbours on pg1 and pg3 are still present
1951 for h in range(N_HOSTS):
1952 self.assertTrue(find_nbr(self,
1953 i.sw_if_index,
1954 i.remote_hosts[h].ip4))
1955 self.assertTrue(find_nbr(self,
1956 i.sw_if_index,
1957 i.remote_hosts[h].ip6))
1958 else:
1959 # all other neighbours are toast
1960 for h in range(N_HOSTS):
1961 self.assertFalse(find_nbr(self,
1962 i.sw_if_index,
1963 i.remote_hosts[h].ip4))
1964 self.assertFalse(find_nbr(self,
1965 i.sw_if_index,
1966 i.remote_hosts[h].ip6))
1967
1968
Neale Ranns37be7362017-02-21 17:30:26 -08001969if __name__ == '__main__':
1970 unittest.main(testRunner=VppTestRunner)