blob: c34ac1aea4e0eaae96666e6ef62826ba295a90fe [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
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00007from framework import tag_fixme_vpp_workers
Neale Ranns39f9d8b2017-02-16 21:57:05 -08008from framework import VppTestCase, VppTestRunner
9from vpp_neighbor import VppNeighbor, find_nbr
Neale Ranns15002542017-09-10 04:39:11 -070010from vpp_ip_route import VppIpRoute, VppRoutePath, find_route, \
Neale Rannse2fe0972020-11-26 08:37:27 +000011 VppIpTable, DpoProto, FibPathType, VppIpInterfaceAddress
Neale Ranns37029302018-08-10 05:30:06 -070012from vpp_papi import VppEnum
Jakub Grajciar2df2f752020-12-01 11:23:44 +010013from vpp_ip import VppIpPuntRedirect
Neale Ranns39f9d8b2017-02-16 21:57:05 -080014
Paul Vinciguerraa7427ec2019-03-10 10:04:23 -070015import scapy.compat
Neale Ranns39f9d8b2017-02-16 21:57:05 -080016from scapy.packet import Raw
Neale Ranns30d0fd42017-05-30 07:30:04 -070017from scapy.layers.l2 import Ether, ARP, Dot1Q
Neale Ranns240dcb22020-04-23 09:04:59 +000018from scapy.layers.inet import IP, UDP, TCP
Neale Rannscd35e532018-08-31 02:51:45 -070019from scapy.layers.inet6 import IPv6
Neale Ranns37be7362017-02-21 17:30:26 -080020from scapy.contrib.mpls import MPLS
Neale Ranns14260392018-09-28 05:00:57 -070021from scapy.layers.inet6 import IPv6
Neale Ranns39f9d8b2017-02-16 21:57:05 -080022
Paul Vinciguerra4271c972019-05-14 13:25:49 -040023
24NUM_PKTS = 67
25
Neale Ranns39f9d8b2017-02-16 21:57:05 -080026# not exported by scapy, so redefined here
27arp_opts = {"who-has": 1, "is-at": 2}
28
29
30class ARPTestCase(VppTestCase):
31 """ ARP Test Case """
32
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070033 @classmethod
34 def setUpClass(cls):
35 super(ARPTestCase, cls).setUpClass()
36
37 @classmethod
38 def tearDownClass(cls):
39 super(ARPTestCase, cls).tearDownClass()
40
Neale Ranns39f9d8b2017-02-16 21:57:05 -080041 def setUp(self):
42 super(ARPTestCase, self).setUp()
43
44 # create 3 pg interfaces
45 self.create_pg_interfaces(range(4))
46
47 # pg0 configured with ip4 and 6 addresses used for input
48 # pg1 configured with ip4 and 6 addresses used for output
49 # pg2 is unnumbered to pg0
50 for i in self.pg_interfaces:
51 i.admin_up()
52
53 self.pg0.config_ip4()
54 self.pg0.config_ip6()
55 self.pg0.resolve_arp()
56
57 self.pg1.config_ip4()
58 self.pg1.config_ip6()
59
60 # pg3 in a different VRF
Neale Ranns15002542017-09-10 04:39:11 -070061 self.tbl = VppIpTable(self, 1)
62 self.tbl.add_vpp_config()
63
Neale Ranns39f9d8b2017-02-16 21:57:05 -080064 self.pg3.set_table_ip4(1)
65 self.pg3.config_ip4()
66
Neale Ranns4008ac92017-02-13 23:20:04 -080067 def tearDown(self):
Neale Ranns4b919a52017-03-11 05:55:21 -080068 self.pg0.unconfig_ip4()
69 self.pg0.unconfig_ip6()
70
71 self.pg1.unconfig_ip4()
72 self.pg1.unconfig_ip6()
73
74 self.pg3.unconfig_ip4()
Neale Ranns15002542017-09-10 04:39:11 -070075 self.pg3.set_table_ip4(0)
Neale Ranns4b919a52017-03-11 05:55:21 -080076
Neale Ranns4008ac92017-02-13 23:20:04 -080077 for i in self.pg_interfaces:
Neale Ranns4008ac92017-02-13 23:20:04 -080078 i.admin_down()
79
Neale Ranns15002542017-09-10 04:39:11 -070080 super(ARPTestCase, self).tearDown()
81
Neale Ranns39f9d8b2017-02-16 21:57:05 -080082 def verify_arp_req(self, rx, smac, sip, dip):
83 ether = rx[Ether]
84 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
85 self.assertEqual(ether.src, smac)
Elias Rudberg71845712020-12-10 14:20:43 +010086 self.assertEqual(ether.type, 0x0806)
Neale Ranns39f9d8b2017-02-16 21:57:05 -080087
88 arp = rx[ARP]
89 self.assertEqual(arp.hwtype, 1)
90 self.assertEqual(arp.ptype, 0x800)
91 self.assertEqual(arp.hwlen, 6)
92 self.assertEqual(arp.plen, 4)
93 self.assertEqual(arp.op, arp_opts["who-has"])
94 self.assertEqual(arp.hwsrc, smac)
95 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
96 self.assertEqual(arp.psrc, sip)
97 self.assertEqual(arp.pdst, dip)
98
99 def verify_arp_resp(self, rx, smac, dmac, sip, dip):
100 ether = rx[Ether]
101 self.assertEqual(ether.dst, dmac)
102 self.assertEqual(ether.src, smac)
Elias Rudberg71845712020-12-10 14:20:43 +0100103 self.assertEqual(ether.type, 0x0806)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800104
105 arp = rx[ARP]
106 self.assertEqual(arp.hwtype, 1)
107 self.assertEqual(arp.ptype, 0x800)
108 self.assertEqual(arp.hwlen, 6)
109 self.assertEqual(arp.plen, 4)
110 self.assertEqual(arp.op, arp_opts["is-at"])
111 self.assertEqual(arp.hwsrc, smac)
112 self.assertEqual(arp.hwdst, dmac)
113 self.assertEqual(arp.psrc, sip)
114 self.assertEqual(arp.pdst, dip)
115
Matthew Smithcb9ab472017-05-16 21:35:56 -0500116 def verify_arp_vrrp_resp(self, rx, smac, dmac, sip, dip):
117 ether = rx[Ether]
118 self.assertEqual(ether.dst, dmac)
119 self.assertEqual(ether.src, smac)
120
121 arp = rx[ARP]
122 self.assertEqual(arp.hwtype, 1)
123 self.assertEqual(arp.ptype, 0x800)
124 self.assertEqual(arp.hwlen, 6)
125 self.assertEqual(arp.plen, 4)
126 self.assertEqual(arp.op, arp_opts["is-at"])
127 self.assertNotEqual(arp.hwsrc, smac)
128 self.assertTrue("00:00:5e:00:01" in arp.hwsrc or
129 "00:00:5E:00:01" in arp.hwsrc)
130 self.assertEqual(arp.hwdst, dmac)
131 self.assertEqual(arp.psrc, sip)
132 self.assertEqual(arp.pdst, dip)
133
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800134 def verify_ip(self, rx, smac, dmac, sip, dip):
135 ether = rx[Ether]
136 self.assertEqual(ether.dst, dmac)
137 self.assertEqual(ether.src, smac)
Elias Rudberg71845712020-12-10 14:20:43 +0100138 self.assertEqual(ether.type, 0x0800)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800139
140 ip = rx[IP]
141 self.assertEqual(ip.src, sip)
142 self.assertEqual(ip.dst, dip)
143
Neale Ranns37be7362017-02-21 17:30:26 -0800144 def verify_ip_o_mpls(self, rx, smac, dmac, label, sip, dip):
145 ether = rx[Ether]
146 self.assertEqual(ether.dst, dmac)
147 self.assertEqual(ether.src, smac)
Elias Rudberg71845712020-12-10 14:20:43 +0100148 self.assertEqual(ether.type, 0x8847)
Neale Ranns37be7362017-02-21 17:30:26 -0800149
150 mpls = rx[MPLS]
151 self.assertTrue(mpls.label, label)
152
153 ip = rx[IP]
154 self.assertEqual(ip.src, sip)
155 self.assertEqual(ip.dst, dip)
156
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800157 def test_arp(self):
158 """ ARP """
159
160 #
161 # Generate some hosts on the LAN
162 #
Neale Rannsca193612017-06-14 06:50:08 -0700163 self.pg1.generate_remote_hosts(11)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800164
165 #
Neale Rannscbe25aa2019-09-30 10:53:31 +0000166 # watch for:
167 # - all neighbour events
168 # - all neighbor events on pg1
169 # - neighbor events for host[1] on pg1
170 #
171 self.vapi.want_ip_neighbor_events(enable=1,
172 pid=os.getpid())
173 self.vapi.want_ip_neighbor_events(enable=1,
174 pid=os.getpid(),
175 sw_if_index=self.pg1.sw_if_index)
176 self.vapi.want_ip_neighbor_events(enable=1,
177 pid=os.getpid(),
178 sw_if_index=self.pg1.sw_if_index,
179 ip=self.pg1.remote_hosts[1].ip4)
180
181 self.logger.info(self.vapi.cli("sh ip neighbor-watcher"))
182
183 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800184 # Send IP traffic to one of these unresolved hosts.
185 # expect the generation of an ARP request
186 #
187 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
188 IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[1].ip4) /
189 UDP(sport=1234, dport=1234) /
190 Raw())
191
192 self.pg0.add_stream(p)
193 self.pg_enable_capture(self.pg_interfaces)
194 self.pg_start()
195
196 rx = self.pg1.get_capture(1)
197
198 self.verify_arp_req(rx[0],
199 self.pg1.local_mac,
200 self.pg1.local_ip4,
201 self.pg1._remote_hosts[1].ip4)
202
203 #
204 # And a dynamic ARP entry for host 1
205 #
206 dyn_arp = VppNeighbor(self,
207 self.pg1.sw_if_index,
208 self.pg1.remote_hosts[1].mac,
209 self.pg1.remote_hosts[1].ip4)
210 dyn_arp.add_vpp_config()
Neale Rannscbe25aa2019-09-30 10:53:31 +0000211 self.assertTrue(dyn_arp.query_vpp_config())
212
Neale Rannsdc617b82020-08-20 08:22:56 +0000213 self.logger.info(self.vapi.cli("show ip neighbor-watcher"))
214
Neale Rannscbe25aa2019-09-30 10:53:31 +0000215 # this matches all of the listnerers
216 es = [self.vapi.wait_for_event(1, "ip_neighbor_event")
217 for i in range(3)]
218 for e in es:
219 self.assertEqual(str(e.neighbor.ip_address),
220 self.pg1.remote_hosts[1].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800221
222 #
223 # now we expect IP traffic forwarded
224 #
225 dyn_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
226 IP(src=self.pg0.remote_ip4,
227 dst=self.pg1._remote_hosts[1].ip4) /
228 UDP(sport=1234, dport=1234) /
229 Raw())
230
231 self.pg0.add_stream(dyn_p)
232 self.pg_enable_capture(self.pg_interfaces)
233 self.pg_start()
234
235 rx = self.pg1.get_capture(1)
236
237 self.verify_ip(rx[0],
238 self.pg1.local_mac,
239 self.pg1.remote_hosts[1].mac,
240 self.pg0.remote_ip4,
241 self.pg1._remote_hosts[1].ip4)
242
243 #
244 # And a Static ARP entry for host 2
245 #
246 static_arp = VppNeighbor(self,
247 self.pg1.sw_if_index,
248 self.pg1.remote_hosts[2].mac,
249 self.pg1.remote_hosts[2].ip4,
250 is_static=1)
251 static_arp.add_vpp_config()
Neale Rannscbe25aa2019-09-30 10:53:31 +0000252 es = [self.vapi.wait_for_event(1, "ip_neighbor_event")
253 for i in range(2)]
254 for e in es:
255 self.assertEqual(str(e.neighbor.ip_address),
256 self.pg1.remote_hosts[2].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800257
258 static_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
259 IP(src=self.pg0.remote_ip4,
260 dst=self.pg1._remote_hosts[2].ip4) /
261 UDP(sport=1234, dport=1234) /
262 Raw())
263
264 self.pg0.add_stream(static_p)
265 self.pg_enable_capture(self.pg_interfaces)
266 self.pg_start()
267
268 rx = self.pg1.get_capture(1)
269
270 self.verify_ip(rx[0],
271 self.pg1.local_mac,
272 self.pg1.remote_hosts[2].mac,
273 self.pg0.remote_ip4,
274 self.pg1._remote_hosts[2].ip4)
275
276 #
Neale Rannscbe25aa2019-09-30 10:53:31 +0000277 # remove all the listeners
278 #
279 self.vapi.want_ip_neighbor_events(enable=0,
280 pid=os.getpid())
281 self.vapi.want_ip_neighbor_events(enable=0,
282 pid=os.getpid(),
283 sw_if_index=self.pg1.sw_if_index)
284 self.vapi.want_ip_neighbor_events(enable=0,
285 pid=os.getpid(),
286 sw_if_index=self.pg1.sw_if_index,
287 ip=self.pg1.remote_hosts[1].ip4)
288
289 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800290 # flap the link. dynamic ARPs get flush, statics don't
291 #
292 self.pg1.admin_down()
293 self.pg1.admin_up()
294
295 self.pg0.add_stream(static_p)
296 self.pg_enable_capture(self.pg_interfaces)
297 self.pg_start()
298 rx = self.pg1.get_capture(1)
299
300 self.verify_ip(rx[0],
301 self.pg1.local_mac,
302 self.pg1.remote_hosts[2].mac,
303 self.pg0.remote_ip4,
304 self.pg1._remote_hosts[2].ip4)
305
306 self.pg0.add_stream(dyn_p)
307 self.pg_enable_capture(self.pg_interfaces)
308 self.pg_start()
309
310 rx = self.pg1.get_capture(1)
311 self.verify_arp_req(rx[0],
312 self.pg1.local_mac,
313 self.pg1.local_ip4,
314 self.pg1._remote_hosts[1].ip4)
315
Neale Rannscbe25aa2019-09-30 10:53:31 +0000316 self.assertFalse(dyn_arp.query_vpp_config())
317 self.assertTrue(static_arp.query_vpp_config())
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800318 #
319 # Send an ARP request from one of the so-far unlearned remote hosts
320 #
321 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
322 src=self.pg1._remote_hosts[3].mac) /
323 ARP(op="who-has",
324 hwsrc=self.pg1._remote_hosts[3].mac,
325 pdst=self.pg1.local_ip4,
326 psrc=self.pg1._remote_hosts[3].ip4))
327
328 self.pg1.add_stream(p)
329 self.pg_enable_capture(self.pg_interfaces)
330 self.pg_start()
331
332 rx = self.pg1.get_capture(1)
333 self.verify_arp_resp(rx[0],
334 self.pg1.local_mac,
335 self.pg1._remote_hosts[3].mac,
336 self.pg1.local_ip4,
337 self.pg1._remote_hosts[3].ip4)
338
339 #
340 # VPP should have learned the mapping for the remote host
341 #
342 self.assertTrue(find_nbr(self,
343 self.pg1.sw_if_index,
344 self.pg1._remote_hosts[3].ip4))
Neale Ranns4b919a52017-03-11 05:55:21 -0800345 #
346 # Fire in an ARP request before the interface becomes IP enabled
347 #
348 self.pg2.generate_remote_hosts(4)
349
350 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
351 ARP(op="who-has",
352 hwsrc=self.pg2.remote_mac,
353 pdst=self.pg1.local_ip4,
354 psrc=self.pg2.remote_hosts[3].ip4))
Neale Ranns30d0fd42017-05-30 07:30:04 -0700355 pt = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
356 Dot1Q(vlan=0) /
357 ARP(op="who-has",
358 hwsrc=self.pg2.remote_mac,
359 pdst=self.pg1.local_ip4,
360 psrc=self.pg2.remote_hosts[3].ip4))
Neale Ranns4b919a52017-03-11 05:55:21 -0800361 self.send_and_assert_no_replies(self.pg2, p,
362 "interface not IP enabled")
363
364 #
365 # Make pg2 un-numbered to pg1
366 #
367 self.pg2.set_unnumbered(self.pg1.sw_if_index)
368
Neale Rannsac3e72c2019-10-06 01:04:26 -0700369 #
370 # test the unnumbered dump both by all interfaces and just the enabled
371 # one
372 #
Neale Ranns404d88e2018-08-08 06:37:33 -0700373 unnum = self.vapi.ip_unnumbered_dump()
Neale Rannsac3e72c2019-10-06 01:04:26 -0700374 self.assertTrue(len(unnum))
375 self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
376 self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)
377 unnum = self.vapi.ip_unnumbered_dump(self.pg2.sw_if_index)
378 self.assertTrue(len(unnum))
Neale Ranns404d88e2018-08-08 06:37:33 -0700379 self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
380 self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)
381
Neale Ranns4b919a52017-03-11 05:55:21 -0800382 #
383 # We should respond to ARP requests for the unnumbered to address
384 # once an attached route to the source is known
385 #
386 self.send_and_assert_no_replies(
387 self.pg2, p,
388 "ARP req for unnumbered address - no source")
389
390 attached_host = VppIpRoute(self, self.pg2.remote_hosts[3].ip4, 32,
391 [VppRoutePath("0.0.0.0",
392 self.pg2.sw_if_index)])
393 attached_host.add_vpp_config()
394
395 self.pg2.add_stream(p)
396 self.pg_enable_capture(self.pg_interfaces)
397 self.pg_start()
398
399 rx = self.pg2.get_capture(1)
400 self.verify_arp_resp(rx[0],
401 self.pg2.local_mac,
402 self.pg2.remote_mac,
403 self.pg1.local_ip4,
404 self.pg2.remote_hosts[3].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800405
Neale Ranns30d0fd42017-05-30 07:30:04 -0700406 self.pg2.add_stream(pt)
407 self.pg_enable_capture(self.pg_interfaces)
408 self.pg_start()
409
410 rx = self.pg2.get_capture(1)
411 self.verify_arp_resp(rx[0],
412 self.pg2.local_mac,
413 self.pg2.remote_mac,
414 self.pg1.local_ip4,
415 self.pg2.remote_hosts[3].ip4)
416
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800417 #
Neale Ranns3983ac22017-03-10 11:53:27 -0800418 # A neighbor entry that has no associated FIB-entry
419 #
420 arp_no_fib = VppNeighbor(self,
421 self.pg1.sw_if_index,
422 self.pg1.remote_hosts[4].mac,
423 self.pg1.remote_hosts[4].ip4,
424 is_no_fib_entry=1)
425 arp_no_fib.add_vpp_config()
426
427 #
428 # check we have the neighbor, but no route
429 #
430 self.assertTrue(find_nbr(self,
431 self.pg1.sw_if_index,
432 self.pg1._remote_hosts[4].ip4))
433 self.assertFalse(find_route(self,
434 self.pg1._remote_hosts[4].ip4,
435 32))
436 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800437 # pg2 is unnumbered to pg1, so we can form adjacencies out of pg2
438 # from within pg1's subnet
Neale Ranns3983ac22017-03-10 11:53:27 -0800439 #
440 arp_unnum = VppNeighbor(self,
441 self.pg2.sw_if_index,
442 self.pg1.remote_hosts[5].mac,
443 self.pg1.remote_hosts[5].ip4)
444 arp_unnum.add_vpp_config()
445
446 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
447 IP(src=self.pg0.remote_ip4,
448 dst=self.pg1._remote_hosts[5].ip4) /
449 UDP(sport=1234, dport=1234) /
450 Raw())
451
452 self.pg0.add_stream(p)
453 self.pg_enable_capture(self.pg_interfaces)
454 self.pg_start()
455
456 rx = self.pg2.get_capture(1)
457
458 self.verify_ip(rx[0],
459 self.pg2.local_mac,
460 self.pg1.remote_hosts[5].mac,
461 self.pg0.remote_ip4,
462 self.pg1._remote_hosts[5].ip4)
463
464 #
Neale Ranns4b919a52017-03-11 05:55:21 -0800465 # ARP requests from hosts in pg1's subnet sent on pg2 are replied to
466 # with the unnumbered interface's address as the source
467 #
468 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
469 ARP(op="who-has",
470 hwsrc=self.pg2.remote_mac,
471 pdst=self.pg1.local_ip4,
472 psrc=self.pg1.remote_hosts[6].ip4))
473
474 self.pg2.add_stream(p)
475 self.pg_enable_capture(self.pg_interfaces)
476 self.pg_start()
477
478 rx = self.pg2.get_capture(1)
479 self.verify_arp_resp(rx[0],
480 self.pg2.local_mac,
481 self.pg2.remote_mac,
482 self.pg1.local_ip4,
483 self.pg1.remote_hosts[6].ip4)
484
485 #
486 # An attached host route out of pg2 for an undiscovered hosts generates
487 # an ARP request with the unnumbered address as the source
488 #
489 att_unnum = VppIpRoute(self, self.pg1.remote_hosts[7].ip4, 32,
490 [VppRoutePath("0.0.0.0",
491 self.pg2.sw_if_index)])
492 att_unnum.add_vpp_config()
493
494 p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
495 IP(src=self.pg0.remote_ip4,
496 dst=self.pg1._remote_hosts[7].ip4) /
497 UDP(sport=1234, dport=1234) /
498 Raw())
499
500 self.pg0.add_stream(p)
501 self.pg_enable_capture(self.pg_interfaces)
502 self.pg_start()
503
504 rx = self.pg2.get_capture(1)
505
506 self.verify_arp_req(rx[0],
507 self.pg2.local_mac,
508 self.pg1.local_ip4,
509 self.pg1._remote_hosts[7].ip4)
510
511 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
512 ARP(op="who-has",
513 hwsrc=self.pg2.remote_mac,
514 pdst=self.pg1.local_ip4,
515 psrc=self.pg1.remote_hosts[7].ip4))
516
517 self.pg2.add_stream(p)
518 self.pg_enable_capture(self.pg_interfaces)
519 self.pg_start()
520
521 rx = self.pg2.get_capture(1)
522 self.verify_arp_resp(rx[0],
523 self.pg2.local_mac,
524 self.pg2.remote_mac,
525 self.pg1.local_ip4,
526 self.pg1.remote_hosts[7].ip4)
527
528 #
529 # An attached host route as yet unresolved out of pg2 for an
530 # undiscovered host, an ARP requests begets a response.
531 #
532 att_unnum1 = VppIpRoute(self, self.pg1.remote_hosts[8].ip4, 32,
533 [VppRoutePath("0.0.0.0",
534 self.pg2.sw_if_index)])
535 att_unnum1.add_vpp_config()
536
537 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
538 ARP(op="who-has",
539 hwsrc=self.pg2.remote_mac,
540 pdst=self.pg1.local_ip4,
541 psrc=self.pg1.remote_hosts[8].ip4))
542
543 self.pg2.add_stream(p)
544 self.pg_enable_capture(self.pg_interfaces)
545 self.pg_start()
546
547 rx = self.pg2.get_capture(1)
548 self.verify_arp_resp(rx[0],
549 self.pg2.local_mac,
550 self.pg2.remote_mac,
551 self.pg1.local_ip4,
552 self.pg1.remote_hosts[8].ip4)
553
554 #
Neale Ranns30d0fd42017-05-30 07:30:04 -0700555 # Send an ARP request from one of the so-far unlearned remote hosts
556 # with a VLAN0 tag
557 #
558 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
559 src=self.pg1._remote_hosts[9].mac) /
560 Dot1Q(vlan=0) /
561 ARP(op="who-has",
562 hwsrc=self.pg1._remote_hosts[9].mac,
563 pdst=self.pg1.local_ip4,
564 psrc=self.pg1._remote_hosts[9].ip4))
565
566 self.pg1.add_stream(p)
567 self.pg_enable_capture(self.pg_interfaces)
568 self.pg_start()
569
570 rx = self.pg1.get_capture(1)
571 self.verify_arp_resp(rx[0],
572 self.pg1.local_mac,
573 self.pg1._remote_hosts[9].mac,
574 self.pg1.local_ip4,
575 self.pg1._remote_hosts[9].ip4)
576
577 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700578 # Add a hierarchy of routes for a host in the sub-net.
Neale Rannsca193612017-06-14 06:50:08 -0700579 # Should still get an ARP resp since the cover is attached
580 #
581 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_mac) /
582 ARP(op="who-has",
583 hwsrc=self.pg1.remote_mac,
584 pdst=self.pg1.local_ip4,
585 psrc=self.pg1.remote_hosts[10].ip4))
586
587 r1 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 30,
588 [VppRoutePath(self.pg1.remote_hosts[10].ip4,
589 self.pg1.sw_if_index)])
590 r1.add_vpp_config()
591
592 self.pg1.add_stream(p)
593 self.pg_enable_capture(self.pg_interfaces)
594 self.pg_start()
595 rx = self.pg1.get_capture(1)
596 self.verify_arp_resp(rx[0],
597 self.pg1.local_mac,
598 self.pg1.remote_mac,
599 self.pg1.local_ip4,
600 self.pg1.remote_hosts[10].ip4)
601
602 r2 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 32,
603 [VppRoutePath(self.pg1.remote_hosts[10].ip4,
604 self.pg1.sw_if_index)])
605 r2.add_vpp_config()
606
607 self.pg1.add_stream(p)
608 self.pg_enable_capture(self.pg_interfaces)
609 self.pg_start()
610 rx = self.pg1.get_capture(1)
611 self.verify_arp_resp(rx[0],
612 self.pg1.local_mac,
613 self.pg1.remote_mac,
614 self.pg1.local_ip4,
615 self.pg1.remote_hosts[10].ip4)
616
617 #
618 # add an ARP entry that's not on the sub-net and so whose
619 # adj-fib fails the refinement check. then send an ARP request
620 # from that source
621 #
622 a1 = VppNeighbor(self,
623 self.pg0.sw_if_index,
624 self.pg0.remote_mac,
625 "100.100.100.50")
626 a1.add_vpp_config()
627
628 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
629 ARP(op="who-has",
630 hwsrc=self.pg0.remote_mac,
631 psrc="100.100.100.50",
632 pdst=self.pg0.remote_ip4))
633 self.send_and_assert_no_replies(self.pg0, p,
634 "ARP req for from failed adj-fib")
635
636 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800637 # ERROR Cases
638 # 1 - don't respond to ARP request for address not within the
639 # interface's sub-net
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700640 # 1b - nor within the unnumbered subnet
641 # 1c - nor within the subnet of a different interface
642 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800643 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
644 ARP(op="who-has",
645 hwsrc=self.pg0.remote_mac,
646 pdst="10.10.10.3",
647 psrc=self.pg0.remote_ip4))
648 self.send_and_assert_no_replies(self.pg0, p,
649 "ARP req for non-local destination")
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700650 self.assertFalse(find_nbr(self,
651 self.pg0.sw_if_index,
652 "10.10.10.3"))
653
Neale Ranns4b919a52017-03-11 05:55:21 -0800654 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
655 ARP(op="who-has",
656 hwsrc=self.pg2.remote_mac,
657 pdst="10.10.10.3",
658 psrc=self.pg1.remote_hosts[7].ip4))
659 self.send_and_assert_no_replies(
660 self.pg0, p,
661 "ARP req for non-local destination - unnum")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800662
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700663 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
664 ARP(op="who-has",
665 hwsrc=self.pg0.remote_mac,
666 pdst=self.pg1.local_ip4,
667 psrc=self.pg1.remote_ip4))
668 self.send_and_assert_no_replies(self.pg0, p,
669 "ARP req diff sub-net")
670 self.assertFalse(find_nbr(self,
671 self.pg0.sw_if_index,
672 self.pg1.remote_ip4))
673
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800674 #
675 # 2 - don't respond to ARP request from an address not within the
676 # interface's sub-net
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700677 # 2b - to a proxied address
678 # 2c - not within a different interface's sub-net
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800679 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
680 ARP(op="who-has",
681 hwsrc=self.pg0.remote_mac,
682 psrc="10.10.10.3",
683 pdst=self.pg0.local_ip4))
684 self.send_and_assert_no_replies(self.pg0, p,
685 "ARP req for non-local source")
Neale Ranns4b919a52017-03-11 05:55:21 -0800686 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
687 ARP(op="who-has",
688 hwsrc=self.pg2.remote_mac,
689 psrc="10.10.10.3",
690 pdst=self.pg0.local_ip4))
691 self.send_and_assert_no_replies(
692 self.pg0, p,
693 "ARP req for non-local source - unnum")
Neale Rannsca193612017-06-14 06:50:08 -0700694 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
695 ARP(op="who-has",
696 hwsrc=self.pg0.remote_mac,
697 psrc=self.pg1.remote_ip4,
698 pdst=self.pg0.local_ip4))
699 self.send_and_assert_no_replies(self.pg0, p,
700 "ARP req for non-local source 2c")
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800701
702 #
703 # 3 - don't respond to ARP request from an address that belongs to
704 # the router
705 #
706 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
707 ARP(op="who-has",
708 hwsrc=self.pg0.remote_mac,
709 psrc=self.pg0.local_ip4,
710 pdst=self.pg0.local_ip4))
711 self.send_and_assert_no_replies(self.pg0, p,
712 "ARP req for non-local source")
713
714 #
715 # 4 - don't respond to ARP requests that has mac source different
716 # from ARP request HW source
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800717 #
718 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
719 ARP(op="who-has",
720 hwsrc="00:00:00:DE:AD:BE",
721 psrc=self.pg0.remote_ip4,
722 pdst=self.pg0.local_ip4))
723 self.send_and_assert_no_replies(self.pg0, p,
724 "ARP req for non-local source")
725
726 #
zhaoqinglingb4c42cd2017-12-23 15:20:59 +0800727 # 5 - don't respond to ARP requests for address within the
728 # interface's sub-net but not the interface's address
729 #
730 self.pg0.generate_remote_hosts(2)
731 p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
732 ARP(op="who-has",
733 hwsrc=self.pg0.remote_mac,
734 psrc=self.pg0.remote_hosts[0].ip4,
735 pdst=self.pg0.remote_hosts[1].ip4))
736 self.send_and_assert_no_replies(self.pg0, p,
737 "ARP req for non-local destination")
738
739 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800740 # cleanup
741 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800742 static_arp.remove_vpp_config()
Neale Ranns3983ac22017-03-10 11:53:27 -0800743 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800744
Neale Ranns4b919a52017-03-11 05:55:21 -0800745 # need this to flush the adj-fibs
746 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
747 self.pg2.admin_down()
Neale Rannsca193612017-06-14 06:50:08 -0700748 self.pg1.admin_down()
Neale Ranns4b919a52017-03-11 05:55:21 -0800749
Neale Ranns24b170a2017-08-15 05:33:11 -0700750 def test_proxy_mirror_arp(self):
751 """ Interface Mirror Proxy ARP """
752
753 #
754 # When VPP has an interface whose address is also applied to a TAP
755 # interface on the host, then VPP's TAP interface will be unnumbered
756 # to the 'real' interface and do proxy ARP from the host.
757 # the curious aspect of this setup is that ARP requests from the host
758 # will come from the VPP's own address.
759 #
760 self.pg0.generate_remote_hosts(2)
761
762 arp_req_from_me = (Ether(src=self.pg2.remote_mac,
763 dst="ff:ff:ff:ff:ff:ff") /
764 ARP(op="who-has",
765 hwsrc=self.pg2.remote_mac,
766 pdst=self.pg0.remote_hosts[1].ip4,
767 psrc=self.pg0.local_ip4))
768
769 #
770 # Configure Proxy ARP for the subnet on PG0addresses on pg0
771 #
Ole Troan5c2a2372020-11-19 16:01:23 +0100772 self.vapi.proxy_arp_add_del(proxy={'table_id': 0,
773 'low': self.pg0._local_ip4_subnet,
774 'hi': self.pg0._local_ip4_bcast},
775 is_add=1)
Neale Ranns24b170a2017-08-15 05:33:11 -0700776
777 # Make pg2 un-numbered to pg0
778 #
779 self.pg2.set_unnumbered(self.pg0.sw_if_index)
780
781 #
782 # Enable pg2 for proxy ARP
783 #
784 self.pg2.set_proxy_arp()
785
786 #
787 # Send the ARP request with an originating address that
788 # is VPP's own address
789 #
Neale Ranns240dcb22020-04-23 09:04:59 +0000790 rx = self.send_and_expect(self.pg2, [arp_req_from_me], self.pg2)
Neale Ranns24b170a2017-08-15 05:33:11 -0700791 self.verify_arp_resp(rx[0],
792 self.pg2.local_mac,
793 self.pg2.remote_mac,
794 self.pg0.remote_hosts[1].ip4,
795 self.pg0.local_ip4)
796
797 #
798 # validate we have not learned an ARP entry as a result of this
799 #
800 self.assertFalse(find_nbr(self,
801 self.pg2.sw_if_index,
802 self.pg0.local_ip4))
803
804 #
Neale Ranns240dcb22020-04-23 09:04:59 +0000805 # setup a punt redirect so packets from the uplink go to the tap
806 #
Jakub Grajciar2df2f752020-12-01 11:23:44 +0100807 redirect = VppIpPuntRedirect(self, self.pg0.sw_if_index,
808 self.pg2.sw_if_index, self.pg0.local_ip4)
809 redirect.add_vpp_config()
Neale Ranns240dcb22020-04-23 09:04:59 +0000810
811 p_tcp = (Ether(src=self.pg0.remote_mac,
812 dst=self.pg0.local_mac,) /
813 IP(src=self.pg0.remote_ip4,
814 dst=self.pg0.local_ip4) /
815 TCP(sport=80, dport=80) /
816 Raw())
817 rx = self.send_and_expect(self.pg0, [p_tcp], self.pg2)
818
819 # there's no ARP entry so this is an ARP req
820 self.assertTrue(rx[0].haslayer(ARP))
821
822 # and ARP entry for VPP's pg0 address on the host interface
823 n1 = VppNeighbor(self,
824 self.pg2.sw_if_index,
825 self.pg2.remote_mac,
826 self.pg0.local_ip4,
827 is_no_fib_entry=True).add_vpp_config()
828 # now the packets shold forward
829 rx = self.send_and_expect(self.pg0, [p_tcp], self.pg2)
830 self.assertFalse(rx[0].haslayer(ARP))
831 self.assertEqual(rx[0][Ether].dst, self.pg2.remote_mac)
832
833 #
834 # flush the neighbor cache on the uplink
835 #
836 af = VppEnum.vl_api_address_family_t
837 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, self.pg0.sw_if_index)
838
839 # ensure we can still resolve the ARPs on the uplink
840 self.pg0.resolve_arp()
841
842 self.assertTrue(find_nbr(self,
843 self.pg0.sw_if_index,
844 self.pg0.remote_ip4))
845
846 #
Neale Ranns24b170a2017-08-15 05:33:11 -0700847 # cleanup
848 #
Ole Troan5c2a2372020-11-19 16:01:23 +0100849 self.vapi.proxy_arp_add_del(proxy={'table_id': 0,
850 'low': self.pg0._local_ip4_subnet,
851 'hi': self.pg0._local_ip4_bcast},
Neale Ranns24b170a2017-08-15 05:33:11 -0700852 is_add=0)
Jakub Grajciar2df2f752020-12-01 11:23:44 +0100853 redirect.remove_vpp_config()
Neale Ranns24b170a2017-08-15 05:33:11 -0700854
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800855 def test_proxy_arp(self):
856 """ Proxy ARP """
857
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700858 self.pg1.generate_remote_hosts(2)
859
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800860 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700861 # Proxy ARP request packets for each interface
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800862 #
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800863 arp_req_pg0 = (Ether(src=self.pg0.remote_mac,
864 dst="ff:ff:ff:ff:ff:ff") /
865 ARP(op="who-has",
866 hwsrc=self.pg0.remote_mac,
867 pdst="10.10.10.3",
868 psrc=self.pg0.remote_ip4))
Neale Ranns30d0fd42017-05-30 07:30:04 -0700869 arp_req_pg0_tagged = (Ether(src=self.pg0.remote_mac,
870 dst="ff:ff:ff:ff:ff:ff") /
871 Dot1Q(vlan=0) /
872 ARP(op="who-has",
873 hwsrc=self.pg0.remote_mac,
874 pdst="10.10.10.3",
875 psrc=self.pg0.remote_ip4))
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800876 arp_req_pg1 = (Ether(src=self.pg1.remote_mac,
877 dst="ff:ff:ff:ff:ff:ff") /
878 ARP(op="who-has",
879 hwsrc=self.pg1.remote_mac,
880 pdst="10.10.10.3",
881 psrc=self.pg1.remote_ip4))
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700882 arp_req_pg2 = (Ether(src=self.pg2.remote_mac,
883 dst="ff:ff:ff:ff:ff:ff") /
884 ARP(op="who-has",
885 hwsrc=self.pg2.remote_mac,
886 pdst="10.10.10.3",
887 psrc=self.pg1.remote_hosts[1].ip4))
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800888 arp_req_pg3 = (Ether(src=self.pg3.remote_mac,
889 dst="ff:ff:ff:ff:ff:ff") /
890 ARP(op="who-has",
891 hwsrc=self.pg3.remote_mac,
892 pdst="10.10.10.3",
893 psrc=self.pg3.remote_ip4))
894
895 #
896 # Configure Proxy ARP for 10.10.10.0 -> 10.10.10.124
897 #
Ole Troan5c2a2372020-11-19 16:01:23 +0100898 self.vapi.proxy_arp_add_del(proxy={'table_id': 0,
899 'low': "10.10.10.2",
900 'hi': "10.10.10.124"},
901 is_add=1)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800902
903 #
904 # No responses are sent when the interfaces are not enabled for proxy
905 # ARP
906 #
907 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
908 "ARP req from unconfigured interface")
909 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
910 "ARP req from unconfigured interface")
911
912 #
913 # Make pg2 un-numbered to pg1
914 # still won't reply.
915 #
916 self.pg2.set_unnumbered(self.pg1.sw_if_index)
917
918 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
919 "ARP req from unnumbered interface")
920
921 #
922 # Enable each interface to reply to proxy ARPs
923 #
924 for i in self.pg_interfaces:
925 i.set_proxy_arp()
926
927 #
928 # Now each of the interfaces should reply to a request to a proxied
929 # address
930 #
931 self.pg0.add_stream(arp_req_pg0)
932 self.pg_enable_capture(self.pg_interfaces)
933 self.pg_start()
934
935 rx = self.pg0.get_capture(1)
936 self.verify_arp_resp(rx[0],
937 self.pg0.local_mac,
938 self.pg0.remote_mac,
939 "10.10.10.3",
940 self.pg0.remote_ip4)
941
Neale Ranns30d0fd42017-05-30 07:30:04 -0700942 self.pg0.add_stream(arp_req_pg0_tagged)
943 self.pg_enable_capture(self.pg_interfaces)
944 self.pg_start()
945
946 rx = self.pg0.get_capture(1)
947 self.verify_arp_resp(rx[0],
948 self.pg0.local_mac,
949 self.pg0.remote_mac,
950 "10.10.10.3",
951 self.pg0.remote_ip4)
952
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800953 self.pg1.add_stream(arp_req_pg1)
954 self.pg_enable_capture(self.pg_interfaces)
955 self.pg_start()
956
957 rx = self.pg1.get_capture(1)
958 self.verify_arp_resp(rx[0],
959 self.pg1.local_mac,
960 self.pg1.remote_mac,
961 "10.10.10.3",
962 self.pg1.remote_ip4)
963
964 self.pg2.add_stream(arp_req_pg2)
965 self.pg_enable_capture(self.pg_interfaces)
966 self.pg_start()
967
968 rx = self.pg2.get_capture(1)
969 self.verify_arp_resp(rx[0],
970 self.pg2.local_mac,
971 self.pg2.remote_mac,
972 "10.10.10.3",
Neale Rannsd5b6aa12017-05-16 08:46:45 -0700973 self.pg1.remote_hosts[1].ip4)
Neale Ranns39f9d8b2017-02-16 21:57:05 -0800974
975 #
976 # A request for an address out of the configured range
977 #
978 arp_req_pg1_hi = (Ether(src=self.pg1.remote_mac,
979 dst="ff:ff:ff:ff:ff:ff") /
980 ARP(op="who-has",
981 hwsrc=self.pg1.remote_mac,
982 pdst="10.10.10.125",
983 psrc=self.pg1.remote_ip4))
984 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_hi,
985 "ARP req out of range HI")
986 arp_req_pg1_low = (Ether(src=self.pg1.remote_mac,
987 dst="ff:ff:ff:ff:ff:ff") /
988 ARP(op="who-has",
989 hwsrc=self.pg1.remote_mac,
990 pdst="10.10.10.1",
991 psrc=self.pg1.remote_ip4))
992 self.send_and_assert_no_replies(self.pg1, arp_req_pg1_low,
993 "ARP req out of range Low")
994
995 #
996 # Request for an address in the proxy range but from an interface
997 # in a different VRF
998 #
999 self.send_and_assert_no_replies(self.pg3, arp_req_pg3,
1000 "ARP req from different VRF")
1001
1002 #
1003 # Disable Each interface for proxy ARP
1004 # - expect none to respond
1005 #
1006 for i in self.pg_interfaces:
1007 i.set_proxy_arp(0)
1008
1009 self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
1010 "ARP req from disable")
1011 self.send_and_assert_no_replies(self.pg1, arp_req_pg1,
1012 "ARP req from disable")
1013 self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
1014 "ARP req from disable")
Neale Ranns37be7362017-02-21 17:30:26 -08001015
1016 #
1017 # clean up on interface 2
1018 #
Neale Ranns4b919a52017-03-11 05:55:21 -08001019 self.pg2.unset_unnumbered(self.pg1.sw_if_index)
Neale Ranns37be7362017-02-21 17:30:26 -08001020
1021 def test_mpls(self):
1022 """ MPLS """
1023
1024 #
1025 # Interface 2 does not yet have ip4 config
1026 #
1027 self.pg2.config_ip4()
1028 self.pg2.generate_remote_hosts(2)
1029
1030 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001031 # Add a route with out going label via an ARP unresolved next-hop
Neale Ranns37be7362017-02-21 17:30:26 -08001032 #
1033 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1034 [VppRoutePath(self.pg2.remote_hosts[1].ip4,
1035 self.pg2.sw_if_index,
1036 labels=[55])])
1037 ip_10_0_0_1.add_vpp_config()
1038
1039 #
1040 # packets should generate an ARP request
1041 #
1042 p = (Ether(src=self.pg0.remote_mac,
1043 dst=self.pg0.local_mac) /
1044 IP(src=self.pg0.remote_ip4, dst="10.0.0.1") /
1045 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +01001046 Raw(b'\xa5' * 100))
Neale Ranns37be7362017-02-21 17:30:26 -08001047
1048 self.pg0.add_stream(p)
1049 self.pg_enable_capture(self.pg_interfaces)
1050 self.pg_start()
1051
1052 rx = self.pg2.get_capture(1)
1053 self.verify_arp_req(rx[0],
1054 self.pg2.local_mac,
1055 self.pg2.local_ip4,
1056 self.pg2._remote_hosts[1].ip4)
1057
1058 #
1059 # now resolve the neighbours
1060 #
1061 self.pg2.configure_ipv4_neighbors()
1062
1063 #
1064 # Now packet should be properly MPLS encapped.
1065 # This verifies that MPLS link-type adjacencies are completed
1066 # when the ARP entry resolves
1067 #
1068 self.pg0.add_stream(p)
1069 self.pg_enable_capture(self.pg_interfaces)
1070 self.pg_start()
1071
1072 rx = self.pg2.get_capture(1)
1073 self.verify_ip_o_mpls(rx[0],
1074 self.pg2.local_mac,
1075 self.pg2.remote_hosts[1].mac,
1076 55,
1077 self.pg0.remote_ip4,
1078 "10.0.0.1")
Neale Ranns4b919a52017-03-11 05:55:21 -08001079 self.pg2.unconfig_ip4()
Neale Ranns37be7362017-02-21 17:30:26 -08001080
Matthew Smithcb9ab472017-05-16 21:35:56 -05001081 def test_arp_vrrp(self):
1082 """ ARP reply with VRRP virtual src hw addr """
1083
1084 #
1085 # IP packet destined for pg1 remote host arrives on pg0 resulting
1086 # in an ARP request for the address of the remote host on pg1
1087 #
1088 p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1089 IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
1090 UDP(sport=1234, dport=1234) /
1091 Raw())
1092
Neale Ranns37029302018-08-10 05:30:06 -07001093 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
Matthew Smithcb9ab472017-05-16 21:35:56 -05001094
1095 self.verify_arp_req(rx1[0],
1096 self.pg1.local_mac,
1097 self.pg1.local_ip4,
1098 self.pg1.remote_ip4)
1099
1100 #
1101 # ARP reply for address of pg1 remote host arrives on pg1 with
1102 # the hw src addr set to a value in the VRRP IPv4 range of
1103 # MAC addresses
1104 #
1105 p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1106 ARP(op="is-at", hwdst=self.pg1.local_mac,
1107 hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
1108 psrc=self.pg1.remote_ip4))
1109
Neale Ranns37029302018-08-10 05:30:06 -07001110 self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
Matthew Smithcb9ab472017-05-16 21:35:56 -05001111
1112 #
1113 # IP packet destined for pg1 remote host arrives on pg0 again.
1114 # VPP should have an ARP entry for that address now and the packet
1115 # should be sent out pg1.
1116 #
Neale Ranns37029302018-08-10 05:30:06 -07001117 rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
Matthew Smithcb9ab472017-05-16 21:35:56 -05001118
1119 self.verify_ip(rx1[0],
1120 self.pg1.local_mac,
1121 "00:00:5e:00:01:09",
1122 self.pg0.remote_ip4,
1123 self.pg1.remote_ip4)
1124
1125 self.pg1.admin_down()
1126 self.pg1.admin_up()
1127
Neale Rannsdcd6d622017-05-26 02:59:16 -07001128 def test_arp_duplicates(self):
1129 """ ARP Duplicates"""
1130
1131 #
1132 # Generate some hosts on the LAN
1133 #
1134 self.pg1.generate_remote_hosts(3)
1135
1136 #
1137 # Add host 1 on pg1 and pg2
1138 #
1139 arp_pg1 = VppNeighbor(self,
1140 self.pg1.sw_if_index,
1141 self.pg1.remote_hosts[1].mac,
1142 self.pg1.remote_hosts[1].ip4)
1143 arp_pg1.add_vpp_config()
1144 arp_pg2 = VppNeighbor(self,
1145 self.pg2.sw_if_index,
1146 self.pg2.remote_mac,
1147 self.pg1.remote_hosts[1].ip4)
1148 arp_pg2.add_vpp_config()
1149
1150 #
1151 # IP packet destined for pg1 remote host arrives on pg1 again.
1152 #
1153 p = (Ether(dst=self.pg0.local_mac,
1154 src=self.pg0.remote_mac) /
1155 IP(src=self.pg0.remote_ip4,
1156 dst=self.pg1.remote_hosts[1].ip4) /
1157 UDP(sport=1234, dport=1234) /
1158 Raw())
1159
1160 self.pg0.add_stream(p)
1161 self.pg_enable_capture(self.pg_interfaces)
1162 self.pg_start()
1163
1164 rx1 = self.pg1.get_capture(1)
1165
1166 self.verify_ip(rx1[0],
1167 self.pg1.local_mac,
1168 self.pg1.remote_hosts[1].mac,
1169 self.pg0.remote_ip4,
1170 self.pg1.remote_hosts[1].ip4)
1171
1172 #
1173 # remove the duplicate on pg1
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001174 # packet stream should generate ARPs out of pg1
Neale Rannsdcd6d622017-05-26 02:59:16 -07001175 #
1176 arp_pg1.remove_vpp_config()
1177
1178 self.pg0.add_stream(p)
1179 self.pg_enable_capture(self.pg_interfaces)
1180 self.pg_start()
1181
1182 rx1 = self.pg1.get_capture(1)
1183
1184 self.verify_arp_req(rx1[0],
1185 self.pg1.local_mac,
1186 self.pg1.local_ip4,
1187 self.pg1.remote_hosts[1].ip4)
1188
1189 #
1190 # Add it back
1191 #
1192 arp_pg1.add_vpp_config()
1193
1194 self.pg0.add_stream(p)
1195 self.pg_enable_capture(self.pg_interfaces)
1196 self.pg_start()
1197
1198 rx1 = self.pg1.get_capture(1)
1199
1200 self.verify_ip(rx1[0],
1201 self.pg1.local_mac,
1202 self.pg1.remote_hosts[1].mac,
1203 self.pg0.remote_ip4,
1204 self.pg1.remote_hosts[1].ip4)
1205
Neale Ranns15002542017-09-10 04:39:11 -07001206 def test_arp_static(self):
1207 """ ARP Static"""
1208 self.pg2.generate_remote_hosts(3)
1209
1210 #
1211 # Add a static ARP entry
1212 #
1213 static_arp = VppNeighbor(self,
1214 self.pg2.sw_if_index,
1215 self.pg2.remote_hosts[1].mac,
1216 self.pg2.remote_hosts[1].ip4,
1217 is_static=1)
1218 static_arp.add_vpp_config()
1219
1220 #
1221 # Add the connected prefix to the interface
1222 #
1223 self.pg2.config_ip4()
1224
1225 #
1226 # We should now find the adj-fib
1227 #
1228 self.assertTrue(find_nbr(self,
1229 self.pg2.sw_if_index,
1230 self.pg2.remote_hosts[1].ip4,
1231 is_static=1))
1232 self.assertTrue(find_route(self,
1233 self.pg2.remote_hosts[1].ip4,
1234 32))
1235
1236 #
1237 # remove the connected
1238 #
1239 self.pg2.unconfig_ip4()
1240
1241 #
1242 # put the interface into table 1
1243 #
1244 self.pg2.set_table_ip4(1)
1245
1246 #
1247 # configure the same connected and expect to find the
1248 # adj fib in the new table
1249 #
1250 self.pg2.config_ip4()
1251 self.assertTrue(find_route(self,
1252 self.pg2.remote_hosts[1].ip4,
1253 32,
1254 table_id=1))
1255
1256 #
1257 # clean-up
1258 #
1259 self.pg2.unconfig_ip4()
Neale Rannscbe25aa2019-09-30 10:53:31 +00001260 static_arp.remove_vpp_config()
Neale Ranns15002542017-09-10 04:39:11 -07001261 self.pg2.set_table_ip4(0)
1262
Vladimir Isaevb2f44bd2020-07-16 17:05:18 +03001263 def test_arp_static_replace_dynamic_same_mac(self):
1264 """ ARP Static can replace Dynamic (same mac) """
1265 self.pg2.generate_remote_hosts(1)
1266
1267 dyn_arp = VppNeighbor(self,
1268 self.pg2.sw_if_index,
1269 self.pg2.remote_hosts[0].mac,
1270 self.pg2.remote_hosts[0].ip4)
1271 static_arp = VppNeighbor(self,
1272 self.pg2.sw_if_index,
1273 self.pg2.remote_hosts[0].mac,
1274 self.pg2.remote_hosts[0].ip4,
1275 is_static=1)
1276
1277 #
1278 # Add a dynamic ARP entry
1279 #
1280 dyn_arp.add_vpp_config()
1281
1282 #
1283 # We should find the dynamic nbr
1284 #
1285 self.assertFalse(find_nbr(self,
1286 self.pg2.sw_if_index,
1287 self.pg2.remote_hosts[0].ip4,
1288 is_static=1))
1289 self.assertTrue(find_nbr(self,
1290 self.pg2.sw_if_index,
1291 self.pg2.remote_hosts[0].ip4,
1292 is_static=0,
1293 mac=self.pg2.remote_hosts[0].mac))
1294
1295 #
1296 # Add a static ARP entry with the same mac
1297 #
1298 static_arp.add_vpp_config()
1299
1300 #
1301 # We should now find the static nbr with the same mac
1302 #
1303 self.assertFalse(find_nbr(self,
1304 self.pg2.sw_if_index,
1305 self.pg2.remote_hosts[0].ip4,
1306 is_static=0))
1307 self.assertTrue(find_nbr(self,
1308 self.pg2.sw_if_index,
1309 self.pg2.remote_hosts[0].ip4,
1310 is_static=1,
1311 mac=self.pg2.remote_hosts[0].mac))
1312
1313 #
1314 # clean-up
1315 #
1316 static_arp.remove_vpp_config()
1317
1318 def test_arp_static_replace_dynamic_diff_mac(self):
1319 """ ARP Static can replace Dynamic (diff mac) """
1320 self.pg2.generate_remote_hosts(2)
1321
1322 dyn_arp = VppNeighbor(self,
1323 self.pg2.sw_if_index,
1324 self.pg2.remote_hosts[0].mac,
1325 self.pg2.remote_hosts[0].ip4)
1326 static_arp = VppNeighbor(self,
1327 self.pg2.sw_if_index,
1328 self.pg2.remote_hosts[1].mac,
1329 self.pg2.remote_hosts[0].ip4,
1330 is_static=1)
1331
1332 #
1333 # Add a dynamic ARP entry
1334 #
1335 dyn_arp.add_vpp_config()
1336
1337 #
1338 # We should find the dynamic nbr
1339 #
1340 self.assertFalse(find_nbr(self,
1341 self.pg2.sw_if_index,
1342 self.pg2.remote_hosts[0].ip4,
1343 is_static=1))
1344 self.assertTrue(find_nbr(self,
1345 self.pg2.sw_if_index,
1346 self.pg2.remote_hosts[0].ip4,
1347 is_static=0,
1348 mac=self.pg2.remote_hosts[0].mac))
1349
1350 #
1351 # Add a static ARP entry with a changed mac
1352 #
1353 static_arp.add_vpp_config()
1354
1355 #
1356 # We should now find the static nbr with a changed mac
1357 #
1358 self.assertFalse(find_nbr(self,
1359 self.pg2.sw_if_index,
1360 self.pg2.remote_hosts[0].ip4,
1361 is_static=0))
1362 self.assertTrue(find_nbr(self,
1363 self.pg2.sw_if_index,
1364 self.pg2.remote_hosts[0].ip4,
1365 is_static=1,
1366 mac=self.pg2.remote_hosts[1].mac))
1367
1368 #
1369 # clean-up
1370 #
1371 static_arp.remove_vpp_config()
1372
Neale Rannsc819fc62018-02-16 02:44:05 -08001373 def test_arp_incomplete(self):
1374 """ ARP Incomplete"""
1375 self.pg1.generate_remote_hosts(3)
1376
1377 p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1378 IP(src=self.pg0.remote_ip4,
1379 dst=self.pg1.remote_hosts[1].ip4) /
1380 UDP(sport=1234, dport=1234) /
1381 Raw())
1382 p1 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1383 IP(src=self.pg0.remote_ip4,
1384 dst=self.pg1.remote_hosts[2].ip4) /
1385 UDP(sport=1234, dport=1234) /
1386 Raw())
1387
1388 #
1389 # a packet to an unresolved destination generates an ARP request
1390 #
1391 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1392 self.verify_arp_req(rx[0],
1393 self.pg1.local_mac,
1394 self.pg1.local_ip4,
1395 self.pg1._remote_hosts[1].ip4)
1396
1397 #
1398 # add a neighbour for remote host 1
1399 #
1400 static_arp = VppNeighbor(self,
1401 self.pg1.sw_if_index,
1402 self.pg1.remote_hosts[1].mac,
1403 self.pg1.remote_hosts[1].ip4,
1404 is_static=1)
1405 static_arp.add_vpp_config()
1406
1407 #
1408 # change the interface's MAC
1409 #
Neale Rannsc819fc62018-02-16 02:44:05 -08001410 self.vapi.sw_interface_set_mac_address(self.pg1.sw_if_index,
Neale Ranns77f91622020-11-23 16:25:27 +00001411 "00:00:00:33:33:33")
Neale Rannsc819fc62018-02-16 02:44:05 -08001412
1413 #
1414 # now ARP requests come from the new source mac
1415 #
1416 rx = self.send_and_expect(self.pg0, [p1], self.pg1)
1417 self.verify_arp_req(rx[0],
1418 "00:00:00:33:33:33",
1419 self.pg1.local_ip4,
1420 self.pg1._remote_hosts[2].ip4)
1421
1422 #
1423 # packets to the resolved host also have the new source mac
1424 #
1425 rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1426 self.verify_ip(rx[0],
1427 "00:00:00:33:33:33",
1428 self.pg1.remote_hosts[1].mac,
1429 self.pg0.remote_ip4,
1430 self.pg1.remote_hosts[1].ip4)
1431
1432 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001433 # set the mac address on the interface that does not have a
Neale Rannsc819fc62018-02-16 02:44:05 -08001434 # configured subnet and thus no glean
1435 #
1436 self.vapi.sw_interface_set_mac_address(self.pg2.sw_if_index,
Neale Ranns77f91622020-11-23 16:25:27 +00001437 "00:00:00:33:33:33")
Neale Rannsc819fc62018-02-16 02:44:05 -08001438
Neale Ranns59ae61e2018-06-07 18:09:49 -07001439 def test_garp(self):
1440 """ GARP """
1441
1442 #
1443 # Generate some hosts on the LAN
1444 #
1445 self.pg1.generate_remote_hosts(4)
Neale Ranns22eefd72020-09-23 11:25:21 +00001446 self.pg2.generate_remote_hosts(4)
Neale Ranns59ae61e2018-06-07 18:09:49 -07001447
1448 #
1449 # And an ARP entry
1450 #
1451 arp = VppNeighbor(self,
1452 self.pg1.sw_if_index,
1453 self.pg1.remote_hosts[1].mac,
1454 self.pg1.remote_hosts[1].ip4)
1455 arp.add_vpp_config()
1456
1457 self.assertTrue(find_nbr(self,
1458 self.pg1.sw_if_index,
1459 self.pg1.remote_hosts[1].ip4,
1460 mac=self.pg1.remote_hosts[1].mac))
1461
1462 #
1463 # Send a GARP (request) to swap the host 1's address to that of host 2
1464 #
1465 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1466 src=self.pg1.remote_hosts[2].mac) /
1467 ARP(op="who-has",
1468 hwdst=self.pg1.local_mac,
1469 hwsrc=self.pg1.remote_hosts[2].mac,
1470 pdst=self.pg1.remote_hosts[1].ip4,
1471 psrc=self.pg1.remote_hosts[1].ip4))
1472
1473 self.pg1.add_stream(p1)
1474 self.pg_enable_capture(self.pg_interfaces)
1475 self.pg_start()
1476
1477 self.assertTrue(find_nbr(self,
1478 self.pg1.sw_if_index,
1479 self.pg1.remote_hosts[1].ip4,
1480 mac=self.pg1.remote_hosts[2].mac))
1481
1482 #
1483 # Send a GARP (reply) to swap the host 1's address to that of host 3
1484 #
1485 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1486 src=self.pg1.remote_hosts[3].mac) /
1487 ARP(op="is-at",
1488 hwdst=self.pg1.local_mac,
1489 hwsrc=self.pg1.remote_hosts[3].mac,
1490 pdst=self.pg1.remote_hosts[1].ip4,
1491 psrc=self.pg1.remote_hosts[1].ip4))
1492
1493 self.pg1.add_stream(p1)
1494 self.pg_enable_capture(self.pg_interfaces)
1495 self.pg_start()
1496
1497 self.assertTrue(find_nbr(self,
1498 self.pg1.sw_if_index,
1499 self.pg1.remote_hosts[1].ip4,
1500 mac=self.pg1.remote_hosts[3].mac))
1501
1502 #
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001503 # GARPs (request nor replies) for host we don't know yet
Neale Ranns59ae61e2018-06-07 18:09:49 -07001504 # don't result in new neighbour entries
1505 #
1506 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1507 src=self.pg1.remote_hosts[3].mac) /
1508 ARP(op="who-has",
1509 hwdst=self.pg1.local_mac,
1510 hwsrc=self.pg1.remote_hosts[3].mac,
1511 pdst=self.pg1.remote_hosts[2].ip4,
1512 psrc=self.pg1.remote_hosts[2].ip4))
1513
1514 self.pg1.add_stream(p1)
1515 self.pg_enable_capture(self.pg_interfaces)
1516 self.pg_start()
1517
1518 self.assertFalse(find_nbr(self,
1519 self.pg1.sw_if_index,
1520 self.pg1.remote_hosts[2].ip4))
1521
1522 p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1523 src=self.pg1.remote_hosts[3].mac) /
1524 ARP(op="is-at",
1525 hwdst=self.pg1.local_mac,
1526 hwsrc=self.pg1.remote_hosts[3].mac,
1527 pdst=self.pg1.remote_hosts[2].ip4,
1528 psrc=self.pg1.remote_hosts[2].ip4))
1529
1530 self.pg1.add_stream(p1)
1531 self.pg_enable_capture(self.pg_interfaces)
1532 self.pg_start()
1533
1534 self.assertFalse(find_nbr(self,
1535 self.pg1.sw_if_index,
1536 self.pg1.remote_hosts[2].ip4))
1537
Neale Ranns22eefd72020-09-23 11:25:21 +00001538 #
1539 # IP address in different subnets are not learnt
1540 #
1541 self.pg2.configure_ipv4_neighbors()
1542
1543 for op in ["is-at", "who-has"]:
1544 p1 = [(Ether(dst="ff:ff:ff:ff:ff:ff",
1545 src=self.pg2.remote_hosts[1].mac) /
1546 ARP(op=op,
1547 hwdst=self.pg2.local_mac,
1548 hwsrc=self.pg2.remote_hosts[1].mac,
1549 pdst=self.pg2.remote_hosts[1].ip4,
1550 psrc=self.pg2.remote_hosts[1].ip4)),
1551 (Ether(dst="ff:ff:ff:ff:ff:ff",
1552 src=self.pg2.remote_hosts[1].mac) /
1553 ARP(op=op,
1554 hwdst="ff:ff:ff:ff:ff:ff",
1555 hwsrc=self.pg2.remote_hosts[1].mac,
1556 pdst=self.pg2.remote_hosts[1].ip4,
1557 psrc=self.pg2.remote_hosts[1].ip4))]
1558
1559 self.send_and_assert_no_replies(self.pg1, p1)
1560 self.assertFalse(find_nbr(self,
1561 self.pg1.sw_if_index,
1562 self.pg2.remote_hosts[1].ip4))
1563
1564 # they are all dropped because the subnet's don't match
1565 self.assertEqual(4, self.statistics.get_err_counter(
1566 "/err/arp-reply/IP4 destination address not local to subnet"))
1567
Neale Ranns77f91622020-11-23 16:25:27 +00001568 def test_arp_incomplete2(self):
Neale Ranns14260392018-09-28 05:00:57 -07001569 """ Incomplete Entries """
Neale Rannsc8352bc2018-08-29 10:23:58 -07001570
1571 #
Neale Rannscd35e532018-08-31 02:51:45 -07001572 # ensure that we throttle the ARP and ND requests
Neale Rannsc8352bc2018-08-29 10:23:58 -07001573 #
1574 self.pg0.generate_remote_hosts(2)
1575
Neale Rannscd35e532018-08-31 02:51:45 -07001576 #
1577 # IPv4/ARP
1578 #
Neale Rannsc8352bc2018-08-29 10:23:58 -07001579 ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1580 [VppRoutePath(self.pg0.remote_hosts[1].ip4,
Neale Rannscd35e532018-08-31 02:51:45 -07001581 self.pg0.sw_if_index)])
Neale Rannsc8352bc2018-08-29 10:23:58 -07001582 ip_10_0_0_1.add_vpp_config()
1583
1584 p1 = (Ether(dst=self.pg1.local_mac,
1585 src=self.pg1.remote_mac) /
1586 IP(src=self.pg1.remote_ip4,
1587 dst="10.0.0.1") /
1588 UDP(sport=1234, dport=1234) /
1589 Raw())
1590
1591 self.pg1.add_stream(p1 * 257)
1592 self.pg_enable_capture(self.pg_interfaces)
1593 self.pg_start()
1594 rx = self.pg0._get_capture(1)
1595
1596 #
1597 # how many we get is going to be dependent on the time for packet
1598 # processing but it should be small
1599 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001600 self.assertLess(len(rx), 64)
Neale Rannsc8352bc2018-08-29 10:23:58 -07001601
Neale Rannscd35e532018-08-31 02:51:45 -07001602 #
1603 # IPv6/ND
1604 #
1605 ip_10_1 = VppIpRoute(self, "10::1", 128,
1606 [VppRoutePath(self.pg0.remote_hosts[1].ip6,
1607 self.pg0.sw_if_index,
Neale Ranns097fa662018-05-01 05:17:55 -07001608 proto=DpoProto.DPO_PROTO_IP6)])
Neale Rannscd35e532018-08-31 02:51:45 -07001609 ip_10_1.add_vpp_config()
1610
1611 p1 = (Ether(dst=self.pg1.local_mac,
1612 src=self.pg1.remote_mac) /
1613 IPv6(src=self.pg1.remote_ip6,
1614 dst="10::1") /
1615 UDP(sport=1234, dport=1234) /
1616 Raw())
1617
1618 self.pg1.add_stream(p1 * 257)
1619 self.pg_enable_capture(self.pg_interfaces)
1620 self.pg_start()
1621 rx = self.pg0._get_capture(1)
1622
1623 #
1624 # how many we get is going to be dependent on the time for packet
1625 # processing but it should be small
1626 #
Paul Vinciguerra3d2df212018-11-24 23:19:53 -08001627 self.assertLess(len(rx), 64)
Neale Rannscd35e532018-08-31 02:51:45 -07001628
Neale Ranns7425f922019-01-23 00:36:16 -08001629 def test_arp_forus(self):
1630 """ ARP for for-us """
1631
1632 #
1633 # Test that VPP responds with ARP requests to addresses that
1634 # are connected and local routes.
1635 # Use one of the 'remote' addresses in the subnet as a local address
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -07001636 # The intention of this route is that it then acts like a secondary
Neale Ranns7425f922019-01-23 00:36:16 -08001637 # address added to an interface
1638 #
1639 self.pg0.generate_remote_hosts(2)
1640
Neale Ranns097fa662018-05-01 05:17:55 -07001641 forus = VppIpRoute(
1642 self, self.pg0.remote_hosts[1].ip4, 32,
1643 [VppRoutePath("0.0.0.0",
1644 self.pg0.sw_if_index,
1645 type=FibPathType.FIB_PATH_TYPE_LOCAL)])
Neale Ranns7425f922019-01-23 00:36:16 -08001646 forus.add_vpp_config()
1647
1648 p = (Ether(dst="ff:ff:ff:ff:ff:ff",
1649 src=self.pg0.remote_mac) /
1650 ARP(op="who-has",
1651 hwdst=self.pg0.local_mac,
1652 hwsrc=self.pg0.remote_mac,
1653 pdst=self.pg0.remote_hosts[1].ip4,
1654 psrc=self.pg0.remote_ip4))
1655
1656 rx = self.send_and_expect(self.pg0, [p], self.pg0)
1657
1658 self.verify_arp_resp(rx[0],
1659 self.pg0.local_mac,
1660 self.pg0.remote_mac,
1661 self.pg0.remote_hosts[1].ip4,
1662 self.pg0.remote_ip4)
1663
Neale Rannsfca3c6a2019-12-31 03:49:34 +00001664 def test_arp_table_swap(self):
1665 #
1666 # Generate some hosts on the LAN
1667 #
1668 N_NBRS = 4
1669 self.pg1.generate_remote_hosts(N_NBRS)
1670
1671 for n in range(N_NBRS):
1672 # a route thru each neighbour
1673 VppIpRoute(self, "10.0.0.%d" % n, 32,
1674 [VppRoutePath(self.pg1.remote_hosts[n].ip4,
1675 self.pg1.sw_if_index)]).add_vpp_config()
1676
1677 # resolve each neighbour
1678 p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
1679 ARP(op="is-at", hwdst=self.pg1.local_mac,
1680 hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
1681 psrc=self.pg1.remote_hosts[n].ip4))
1682
1683 self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
1684
1685 self.logger.info(self.vapi.cli("sh ip neighbors"))
1686
1687 #
1688 # swap the table pg1 is in
1689 #
1690 table = VppIpTable(self, 100).add_vpp_config()
1691
1692 self.pg1.unconfig_ip4()
1693 self.pg1.set_table_ip4(100)
1694 self.pg1.config_ip4()
1695
1696 #
1697 # all neighbours are cleared
1698 #
1699 for n in range(N_NBRS):
1700 self.assertFalse(find_nbr(self,
1701 self.pg1.sw_if_index,
1702 self.pg1.remote_hosts[n].ip4))
1703
1704 #
1705 # packets to all neighbours generate ARP requests
1706 #
1707 for n in range(N_NBRS):
1708 # a route thru each neighbour
1709 VppIpRoute(self, "10.0.0.%d" % n, 32,
1710 [VppRoutePath(self.pg1.remote_hosts[n].ip4,
1711 self.pg1.sw_if_index)],
1712 table_id=100).add_vpp_config()
1713
1714 p = (Ether(src=self.pg1.remote_hosts[n].mac,
1715 dst=self.pg1.local_mac) /
1716 IP(src=self.pg1.remote_hosts[n].ip4,
1717 dst="10.0.0.%d" % n) /
1718 Raw(b'0x5' * 100))
1719 rxs = self.send_and_expect(self.pg1, [p], self.pg1)
1720 for rx in rxs:
1721 self.verify_arp_req(rx,
1722 self.pg1.local_mac,
1723 self.pg1.local_ip4,
1724 self.pg1.remote_hosts[n].ip4)
1725
1726 self.pg1.unconfig_ip4()
1727 self.pg1.set_table_ip4(0)
1728
Neale Rannse2fe0972020-11-26 08:37:27 +00001729 def test_glean_src_select(self):
1730 """ Multi Connecteds """
1731
1732 #
1733 # configure multiple connected subnets on an interface
1734 # and ensure that ARP requests for hosts on those subnets
1735 # pick up the correct source address
1736 #
1737 conn1 = VppIpInterfaceAddress(self, self.pg1,
1738 "10.0.0.1", 24).add_vpp_config()
1739 conn2 = VppIpInterfaceAddress(self, self.pg1,
1740 "10.0.1.1", 24).add_vpp_config()
1741
1742 p1 = (Ether(src=self.pg0.remote_mac,
1743 dst=self.pg0.local_mac) /
1744 IP(src=self.pg1.remote_ip4,
1745 dst="10.0.0.128") /
1746 Raw(b'0x5' * 100))
1747
1748 rxs = self.send_and_expect(self.pg0, [p1], self.pg1)
1749 for rx in rxs:
1750 self.verify_arp_req(rx,
1751 self.pg1.local_mac,
1752 "10.0.0.1",
1753 "10.0.0.128")
1754
1755 p2 = (Ether(src=self.pg0.remote_mac,
1756 dst=self.pg0.local_mac) /
1757 IP(src=self.pg1.remote_ip4,
1758 dst="10.0.1.128") /
1759 Raw(b'0x5' * 100))
1760
1761 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
1762 for rx in rxs:
1763 self.verify_arp_req(rx,
1764 self.pg1.local_mac,
1765 "10.0.1.1",
1766 "10.0.1.128")
1767
1768 #
1769 # add a local address in the same subnet
1770 # the source addresses are equivalent. VPP happens to
1771 # choose the last one that was added
1772 conn3 = VppIpInterfaceAddress(self, self.pg1,
1773 "10.0.1.2", 24).add_vpp_config()
1774
1775 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
1776 for rx in rxs:
1777 self.verify_arp_req(rx,
1778 self.pg1.local_mac,
1779 "10.0.1.2",
1780 "10.0.1.128")
1781
1782 #
1783 # remove
1784 #
1785 conn3.remove_vpp_config()
1786 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
1787 for rx in rxs:
1788 self.verify_arp_req(rx,
1789 self.pg1.local_mac,
1790 "10.0.1.1",
1791 "10.0.1.128")
1792
1793 #
1794 # add back, this time remove the first one
1795 #
1796 conn3 = VppIpInterfaceAddress(self, self.pg1,
1797 "10.0.1.2", 24).add_vpp_config()
1798
1799 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
1800 for rx in rxs:
1801 self.verify_arp_req(rx,
1802 self.pg1.local_mac,
1803 "10.0.1.2",
1804 "10.0.1.128")
1805
1806 conn1.remove_vpp_config()
1807 rxs = self.send_and_expect(self.pg0, [p2], self.pg1)
1808 for rx in rxs:
1809 self.verify_arp_req(rx,
1810 self.pg1.local_mac,
1811 "10.0.1.2",
1812 "10.0.1.128")
1813
1814 # cleanup
1815 conn3.remove_vpp_config()
1816 conn2.remove_vpp_config()
1817
Neale Rannsdcd6d622017-05-26 02:59:16 -07001818
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00001819@tag_fixme_vpp_workers
Neale Ranns14260392018-09-28 05:00:57 -07001820class NeighborStatsTestCase(VppTestCase):
Neale Ranns37029302018-08-10 05:30:06 -07001821 """ ARP/ND Counters """
Neale Ranns14260392018-09-28 05:00:57 -07001822
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -07001823 @classmethod
1824 def setUpClass(cls):
1825 super(NeighborStatsTestCase, cls).setUpClass()
1826
1827 @classmethod
1828 def tearDownClass(cls):
1829 super(NeighborStatsTestCase, cls).tearDownClass()
1830
Neale Ranns14260392018-09-28 05:00:57 -07001831 def setUp(self):
1832 super(NeighborStatsTestCase, self).setUp()
1833
1834 self.create_pg_interfaces(range(2))
1835
1836 # pg0 configured with ip4 and 6 addresses used for input
1837 # pg1 configured with ip4 and 6 addresses used for output
1838 # pg2 is unnumbered to pg0
1839 for i in self.pg_interfaces:
1840 i.admin_up()
1841 i.config_ip4()
1842 i.config_ip6()
1843 i.resolve_arp()
1844 i.resolve_ndp()
1845
1846 def tearDown(self):
1847 super(NeighborStatsTestCase, self).tearDown()
1848
1849 for i in self.pg_interfaces:
1850 i.unconfig_ip4()
1851 i.unconfig_ip6()
1852 i.admin_down()
1853
1854 def test_arp_stats(self):
1855 """ ARP Counters """
1856
1857 self.vapi.cli("adj counters enable")
1858 self.pg1.generate_remote_hosts(2)
1859
1860 arp1 = VppNeighbor(self,
1861 self.pg1.sw_if_index,
1862 self.pg1.remote_hosts[0].mac,
1863 self.pg1.remote_hosts[0].ip4)
1864 arp1.add_vpp_config()
1865 arp2 = VppNeighbor(self,
1866 self.pg1.sw_if_index,
1867 self.pg1.remote_hosts[1].mac,
1868 self.pg1.remote_hosts[1].ip4)
1869 arp2.add_vpp_config()
1870
1871 p1 = (Ether(dst=self.pg0.local_mac,
1872 src=self.pg0.remote_mac) /
1873 IP(src=self.pg0.remote_ip4,
1874 dst=self.pg1.remote_hosts[0].ip4) /
1875 UDP(sport=1234, dport=1234) /
1876 Raw())
1877 p2 = (Ether(dst=self.pg0.local_mac,
1878 src=self.pg0.remote_mac) /
1879 IP(src=self.pg0.remote_ip4,
1880 dst=self.pg1.remote_hosts[1].ip4) /
1881 UDP(sport=1234, dport=1234) /
1882 Raw())
1883
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001884 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
1885 rx = self.send_and_expect(self.pg0, p2 * NUM_PKTS, self.pg1)
Neale Ranns14260392018-09-28 05:00:57 -07001886
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001887 self.assertEqual(NUM_PKTS, arp1.get_stats()['packets'])
1888 self.assertEqual(NUM_PKTS, arp2.get_stats()['packets'])
Neale Ranns14260392018-09-28 05:00:57 -07001889
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001890 rx = self.send_and_expect(self.pg0, p1 * NUM_PKTS, self.pg1)
1891 self.assertEqual(NUM_PKTS*2, arp1.get_stats()['packets'])
Neale Ranns14260392018-09-28 05:00:57 -07001892
1893 def test_nd_stats(self):
1894 """ ND Counters """
1895
1896 self.vapi.cli("adj counters enable")
1897 self.pg0.generate_remote_hosts(3)
1898
1899 nd1 = VppNeighbor(self,
1900 self.pg0.sw_if_index,
1901 self.pg0.remote_hosts[1].mac,
Neale Ranns37029302018-08-10 05:30:06 -07001902 self.pg0.remote_hosts[1].ip6)
Neale Ranns14260392018-09-28 05:00:57 -07001903 nd1.add_vpp_config()
1904 nd2 = VppNeighbor(self,
1905 self.pg0.sw_if_index,
1906 self.pg0.remote_hosts[2].mac,
Neale Ranns37029302018-08-10 05:30:06 -07001907 self.pg0.remote_hosts[2].ip6)
Neale Ranns14260392018-09-28 05:00:57 -07001908 nd2.add_vpp_config()
1909
1910 p1 = (Ether(dst=self.pg1.local_mac,
1911 src=self.pg1.remote_mac) /
1912 IPv6(src=self.pg1.remote_ip6,
1913 dst=self.pg0.remote_hosts[1].ip6) /
1914 UDP(sport=1234, dport=1234) /
1915 Raw())
1916 p2 = (Ether(dst=self.pg1.local_mac,
1917 src=self.pg1.remote_mac) /
1918 IPv6(src=self.pg1.remote_ip6,
1919 dst=self.pg0.remote_hosts[2].ip6) /
1920 UDP(sport=1234, dport=1234) /
1921 Raw())
1922
1923 rx = self.send_and_expect(self.pg1, p1 * 16, self.pg0)
1924 rx = self.send_and_expect(self.pg1, p2 * 16, self.pg0)
1925
1926 self.assertEqual(16, nd1.get_stats()['packets'])
1927 self.assertEqual(16, nd2.get_stats()['packets'])
1928
Paul Vinciguerra4271c972019-05-14 13:25:49 -04001929 rx = self.send_and_expect(self.pg1, p1 * NUM_PKTS, self.pg0)
1930 self.assertEqual(NUM_PKTS+16, nd1.get_stats()['packets'])
Neale Ranns14260392018-09-28 05:00:57 -07001931
1932
Neale Rannscbe25aa2019-09-30 10:53:31 +00001933class NeighborAgeTestCase(VppTestCase):
1934 """ ARP/ND Aging """
1935
1936 @classmethod
1937 def setUpClass(cls):
1938 super(NeighborAgeTestCase, cls).setUpClass()
1939
1940 @classmethod
1941 def tearDownClass(cls):
1942 super(NeighborAgeTestCase, cls).tearDownClass()
1943
1944 def setUp(self):
1945 super(NeighborAgeTestCase, self).setUp()
1946
1947 self.create_pg_interfaces(range(1))
1948
1949 # pg0 configured with ip4 and 6 addresses used for input
1950 # pg1 configured with ip4 and 6 addresses used for output
1951 # pg2 is unnumbered to pg0
1952 for i in self.pg_interfaces:
1953 i.admin_up()
1954 i.config_ip4()
1955 i.config_ip6()
1956 i.resolve_arp()
1957 i.resolve_ndp()
1958
1959 def tearDown(self):
1960 super(NeighborAgeTestCase, self).tearDown()
1961
1962 for i in self.pg_interfaces:
1963 i.unconfig_ip4()
1964 i.unconfig_ip6()
1965 i.admin_down()
1966
1967 def wait_for_no_nbr(self, intf, address,
1968 n_tries=50, s_time=1):
1969 while (n_tries):
1970 if not find_nbr(self, intf, address):
1971 return True
1972 n_tries = n_tries - 1
1973 self.sleep(s_time)
1974
1975 return False
1976
1977 def verify_arp_req(self, rx, smac, sip, dip):
1978 ether = rx[Ether]
1979 self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
1980 self.assertEqual(ether.src, smac)
1981
1982 arp = rx[ARP]
1983 self.assertEqual(arp.hwtype, 1)
1984 self.assertEqual(arp.ptype, 0x800)
1985 self.assertEqual(arp.hwlen, 6)
1986 self.assertEqual(arp.plen, 4)
1987 self.assertEqual(arp.op, arp_opts["who-has"])
1988 self.assertEqual(arp.hwsrc, smac)
1989 self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
1990 self.assertEqual(arp.psrc, sip)
1991 self.assertEqual(arp.pdst, dip)
1992
1993 def test_age(self):
1994 """ Aging/Recycle """
1995
1996 self.vapi.cli("set logging unthrottle 0")
1997 self.vapi.cli("set logging size %d" % 0xffff)
1998
1999 self.pg0.generate_remote_hosts(201)
2000
2001 vaf = VppEnum.vl_api_address_family_t
2002
2003 #
2004 # start listening on all interfaces
2005 #
2006 self.pg_enable_capture(self.pg_interfaces)
2007
2008 #
2009 # Set the neighbor configuration:
2010 # limi = 200
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002011 # age = 0 seconds
Neale Rannscbe25aa2019-09-30 10:53:31 +00002012 # recycle = false
2013 #
2014 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
2015 max_number=200,
2016 max_age=0,
2017 recycle=False)
2018
2019 self.vapi.cli("sh ip neighbor-config")
2020
2021 # add the 198 neighbours that should pass (-1 for one created in setup)
2022 for ii in range(200):
2023 VppNeighbor(self,
2024 self.pg0.sw_if_index,
2025 self.pg0.remote_hosts[ii].mac,
2026 self.pg0.remote_hosts[ii].ip4).add_vpp_config()
2027
2028 # one more neighbor over the limit should fail
2029 with self.vapi.assert_negative_api_retval():
2030 VppNeighbor(self,
2031 self.pg0.sw_if_index,
2032 self.pg0.remote_hosts[200].mac,
2033 self.pg0.remote_hosts[200].ip4).add_vpp_config()
2034
2035 #
2036 # change the config to allow recycling the old neighbors
2037 #
2038 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
2039 max_number=200,
2040 max_age=0,
2041 recycle=True)
2042
2043 # now new additions are allowed
2044 VppNeighbor(self,
2045 self.pg0.sw_if_index,
2046 self.pg0.remote_hosts[200].mac,
2047 self.pg0.remote_hosts[200].ip4).add_vpp_config()
2048
2049 # add the first neighbor we configured has been re-used
2050 self.assertFalse(find_nbr(self,
2051 self.pg0.sw_if_index,
2052 self.pg0.remote_hosts[0].ip4))
2053 self.assertTrue(find_nbr(self,
2054 self.pg0.sw_if_index,
2055 self.pg0.remote_hosts[200].ip4))
2056
2057 #
2058 # change the config to age old neighbors
2059 #
2060 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
2061 max_number=200,
2062 max_age=2,
2063 recycle=True)
2064
2065 self.vapi.cli("sh ip4 neighbor-sorted")
2066
2067 #
2068 # expect probes from all these ARP entries as they age
2069 # 3 probes for each neighbor 3*200 = 600
2070 rxs = self.pg0.get_capture(600, timeout=8)
2071
2072 for ii in range(3):
2073 for jj in range(200):
2074 rx = rxs[ii*200 + jj]
2075 # rx.show()
2076
2077 #
2078 # 3 probes sent then 1 more second to see if a reply comes, before
2079 # they age out
2080 #
2081 for jj in range(1, 201):
2082 self.wait_for_no_nbr(self.pg0.sw_if_index,
2083 self.pg0.remote_hosts[jj].ip4)
2084
2085 self.assertFalse(self.vapi.ip_neighbor_dump(sw_if_index=0xffffffff,
2086 af=vaf.ADDRESS_IP4))
2087
2088 #
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002089 # load up some neighbours again with 2s aging enabled
2090 # they should be removed after 10s (2s age + 4s for probes + gap)
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002091 # check for the add and remove events
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002092 #
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002093 enum = VppEnum.vl_api_ip_neighbor_event_flags_t
2094
2095 self.vapi.want_ip_neighbor_events_v2(enable=1)
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002096 for ii in range(10):
2097 VppNeighbor(self,
2098 self.pg0.sw_if_index,
2099 self.pg0.remote_hosts[ii].mac,
2100 self.pg0.remote_hosts[ii].ip4).add_vpp_config()
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002101
2102 e = self.vapi.wait_for_event(1, "ip_neighbor_event_v2")
2103 self.assertEqual(e.flags,
2104 enum.IP_NEIGHBOR_API_EVENT_FLAG_ADDED)
2105 self.assertEqual(str(e.neighbor.ip_address),
2106 self.pg0.remote_hosts[ii].ip4)
2107 self.assertEqual(e.neighbor.mac_address,
2108 self.pg0.remote_hosts[ii].mac)
2109
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002110 self.sleep(10)
2111 self.assertFalse(self.vapi.ip_neighbor_dump(sw_if_index=0xffffffff,
2112 af=vaf.ADDRESS_IP4))
2113
Neale Ranns4ac36bc2020-11-20 13:05:59 +00002114 evs = []
2115 for ii in range(10):
2116 e = self.vapi.wait_for_event(1, "ip_neighbor_event_v2")
2117 self.assertEqual(e.flags,
2118 enum.IP_NEIGHBOR_API_EVENT_FLAG_REMOVED)
2119 evs.append(e)
2120
2121 # check we got the correct mac/ip pairs - done separately
2122 # because we don't care about the order the remove notifications
2123 # arrive
2124 for ii in range(10):
2125 found = False
2126 mac = self.pg0.remote_hosts[ii].mac
2127 ip = self.pg0.remote_hosts[ii].ip4
2128
2129 for e in evs:
2130 if (e.neighbor.mac_address == mac and
2131 str(e.neighbor.ip_address) == ip):
2132 found = True
2133 break
2134 self.assertTrue(found)
2135
Vladimir Isaev1284f8c2020-02-18 15:26:12 +03002136 #
2137 # check if we can set age and recycle with empty neighbor list
2138 #
2139 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
2140 max_number=200,
2141 max_age=1000,
2142 recycle=True)
2143
2144 #
Neale Rannscbe25aa2019-09-30 10:53:31 +00002145 # load up some neighbours again, then disable the aging
2146 # they should still be there in 10 seconds time
2147 #
2148 for ii in range(10):
2149 VppNeighbor(self,
2150 self.pg0.sw_if_index,
2151 self.pg0.remote_hosts[ii].mac,
2152 self.pg0.remote_hosts[ii].ip4).add_vpp_config()
2153 self.vapi.ip_neighbor_config(af=vaf.ADDRESS_IP4,
2154 max_number=200,
2155 max_age=0,
2156 recycle=False)
2157
2158 self.sleep(10)
2159 self.assertTrue(find_nbr(self,
2160 self.pg0.sw_if_index,
2161 self.pg0.remote_hosts[0].ip4))
2162
2163
Neale Rannsc87fbb42020-04-02 17:08:28 +00002164class NeighborReplaceTestCase(VppTestCase):
2165 """ ARP/ND Replacement """
2166
2167 @classmethod
2168 def setUpClass(cls):
2169 super(NeighborReplaceTestCase, cls).setUpClass()
2170
2171 @classmethod
2172 def tearDownClass(cls):
2173 super(NeighborReplaceTestCase, cls).tearDownClass()
2174
2175 def setUp(self):
2176 super(NeighborReplaceTestCase, self).setUp()
2177
2178 self.create_pg_interfaces(range(4))
2179
2180 # pg0 configured with ip4 and 6 addresses used for input
2181 # pg1 configured with ip4 and 6 addresses used for output
2182 # pg2 is unnumbered to pg0
2183 for i in self.pg_interfaces:
2184 i.admin_up()
2185 i.config_ip4()
2186 i.config_ip6()
2187 i.resolve_arp()
2188 i.resolve_ndp()
2189
2190 def tearDown(self):
2191 super(NeighborReplaceTestCase, self).tearDown()
2192
2193 for i in self.pg_interfaces:
2194 i.unconfig_ip4()
2195 i.unconfig_ip6()
2196 i.admin_down()
2197
2198 def test_replace(self):
2199 """ replace """
2200
2201 N_HOSTS = 16
2202
2203 for i in self.pg_interfaces:
2204 i.generate_remote_hosts(N_HOSTS)
2205 i.configure_ipv4_neighbors()
2206 i.configure_ipv6_neighbors()
2207
2208 # replace them all
2209 self.vapi.ip_neighbor_replace_begin()
2210 self.vapi.ip_neighbor_replace_end()
2211
2212 for i in self.pg_interfaces:
2213 for h in range(N_HOSTS):
2214 self.assertFalse(find_nbr(self,
2215 self.pg0.sw_if_index,
2216 self.pg0.remote_hosts[h].ip4))
2217 self.assertFalse(find_nbr(self,
2218 self.pg0.sw_if_index,
2219 self.pg0.remote_hosts[h].ip6))
2220
2221 #
2222 # and them all back via the API
2223 #
2224 for i in self.pg_interfaces:
2225 for h in range(N_HOSTS):
2226 VppNeighbor(self,
2227 i.sw_if_index,
2228 i.remote_hosts[h].mac,
2229 i.remote_hosts[h].ip4).add_vpp_config()
2230 VppNeighbor(self,
2231 i.sw_if_index,
2232 i.remote_hosts[h].mac,
2233 i.remote_hosts[h].ip6).add_vpp_config()
2234
2235 #
2236 # begin the replacement again, this time touch some
2237 # the neighbours on pg1 so they are not deleted
2238 #
2239 self.vapi.ip_neighbor_replace_begin()
2240
2241 # update from the API all neighbours on pg1
2242 for h in range(N_HOSTS):
2243 VppNeighbor(self,
2244 self.pg1.sw_if_index,
2245 self.pg1.remote_hosts[h].mac,
2246 self.pg1.remote_hosts[h].ip4).add_vpp_config()
2247 VppNeighbor(self,
2248 self.pg1.sw_if_index,
2249 self.pg1.remote_hosts[h].mac,
2250 self.pg1.remote_hosts[h].ip6).add_vpp_config()
2251
2252 # update from the data-plane all neighbours on pg3
2253 self.pg3.configure_ipv4_neighbors()
2254 self.pg3.configure_ipv6_neighbors()
2255
2256 # complete the replacement
2257 self.logger.info(self.vapi.cli("sh ip neighbors"))
2258 self.vapi.ip_neighbor_replace_end()
2259
2260 for i in self.pg_interfaces:
2261 if i == self.pg1 or i == self.pg3:
2262 # neighbours on pg1 and pg3 are still present
2263 for h in range(N_HOSTS):
2264 self.assertTrue(find_nbr(self,
2265 i.sw_if_index,
2266 i.remote_hosts[h].ip4))
2267 self.assertTrue(find_nbr(self,
2268 i.sw_if_index,
2269 i.remote_hosts[h].ip6))
2270 else:
2271 # all other neighbours are toast
2272 for h in range(N_HOSTS):
2273 self.assertFalse(find_nbr(self,
2274 i.sw_if_index,
2275 i.remote_hosts[h].ip4))
2276 self.assertFalse(find_nbr(self,
2277 i.sw_if_index,
2278 i.remote_hosts[h].ip6))
2279
2280
Neale Ranns240dcb22020-04-23 09:04:59 +00002281class NeighborFlush(VppTestCase):
2282 """ Neighbor Flush """
2283
2284 @classmethod
2285 def setUpClass(cls):
2286 super(NeighborFlush, cls).setUpClass()
2287
2288 @classmethod
2289 def tearDownClass(cls):
2290 super(NeighborFlush, cls).tearDownClass()
2291
2292 def setUp(self):
2293 super(NeighborFlush, self).setUp()
2294
2295 self.create_pg_interfaces(range(2))
2296
2297 for i in self.pg_interfaces:
2298 i.admin_up()
2299 i.config_ip4()
2300 i.config_ip6()
2301 i.resolve_arp()
2302 i.resolve_ndp()
2303
2304 def tearDown(self):
2305 super(NeighborFlush, self).tearDown()
2306
2307 for i in self.pg_interfaces:
2308 i.unconfig_ip4()
2309 i.unconfig_ip6()
2310 i.admin_down()
2311
2312 def test_flush(self):
2313 """ Neighbour Flush """
2314
2315 e = VppEnum
2316 nf = e.vl_api_ip_neighbor_flags_t
2317 af = e.vl_api_address_family_t
2318 N_HOSTS = 16
2319 static = [False, True]
2320 self.pg0.generate_remote_hosts(N_HOSTS)
2321 self.pg1.generate_remote_hosts(N_HOSTS)
2322
2323 for s in static:
2324 # a few v4 and v6 dynamic neoghbors
2325 for n in range(N_HOSTS):
2326 VppNeighbor(self,
2327 self.pg0.sw_if_index,
2328 self.pg0.remote_hosts[n].mac,
2329 self.pg0.remote_hosts[n].ip4,
2330 is_static=s).add_vpp_config()
2331 VppNeighbor(self,
2332 self.pg1.sw_if_index,
2333 self.pg1.remote_hosts[n].mac,
2334 self.pg1.remote_hosts[n].ip6,
2335 is_static=s).add_vpp_config()
2336
2337 # flush the interfaces individually
2338 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, self.pg0.sw_if_index)
2339
2340 # check we haven't flushed that which we shouldn't
2341 for n in range(N_HOSTS):
2342 self.assertTrue(find_nbr(self,
2343 self.pg1.sw_if_index,
2344 self.pg1.remote_hosts[n].ip6,
2345 is_static=s))
2346
2347 self.vapi.ip_neighbor_flush(af.ADDRESS_IP6, self.pg1.sw_if_index)
2348
2349 for n in range(N_HOSTS):
2350 self.assertFalse(find_nbr(self,
2351 self.pg0.sw_if_index,
2352 self.pg0.remote_hosts[n].ip4))
2353 self.assertFalse(find_nbr(self,
2354 self.pg1.sw_if_index,
2355 self.pg1.remote_hosts[n].ip6))
2356
2357 # add the nieghbours back
2358 for n in range(N_HOSTS):
2359 VppNeighbor(self,
2360 self.pg0.sw_if_index,
2361 self.pg0.remote_hosts[n].mac,
2362 self.pg0.remote_hosts[n].ip4,
2363 is_static=s).add_vpp_config()
2364 VppNeighbor(self,
2365 self.pg1.sw_if_index,
2366 self.pg1.remote_hosts[n].mac,
2367 self.pg1.remote_hosts[n].ip6,
2368 is_static=s).add_vpp_config()
2369
2370 self.logger.info(self.vapi.cli("sh ip neighbor"))
2371
2372 # flush both interfaces at the same time
2373 self.vapi.ip_neighbor_flush(af.ADDRESS_IP6, 0xffffffff)
2374
2375 # check we haven't flushed that which we shouldn't
2376 for n in range(N_HOSTS):
2377 self.assertTrue(find_nbr(self,
2378 self.pg0.sw_if_index,
2379 self.pg0.remote_hosts[n].ip4,
2380 is_static=s))
2381
2382 self.vapi.ip_neighbor_flush(af.ADDRESS_IP4, 0xffffffff)
2383
2384 for n in range(N_HOSTS):
2385 self.assertFalse(find_nbr(self,
2386 self.pg0.sw_if_index,
2387 self.pg0.remote_hosts[n].ip4))
2388 self.assertFalse(find_nbr(self,
2389 self.pg1.sw_if_index,
2390 self.pg1.remote_hosts[n].ip6))
2391
2392
Neale Ranns37be7362017-02-21 17:30:26 -08002393if __name__ == '__main__':
2394 unittest.main(testRunner=VppTestRunner)