ARP learning fixes (VPP-843)
[vpp.git] / test / test_neighbor.py
1 #!/usr/bin/env python
2
3 import unittest
4 from socket import AF_INET, AF_INET6, inet_pton
5
6 from framework import VppTestCase, VppTestRunner
7 from vpp_neighbor import VppNeighbor, find_nbr
8 from vpp_ip_route import VppIpRoute, VppRoutePath, find_route
9
10 from scapy.packet import Raw
11 from scapy.layers.l2 import Ether, ARP
12 from scapy.layers.inet import IP, UDP
13 from scapy.contrib.mpls import MPLS
14
15 # not exported by scapy, so redefined here
16 arp_opts = {"who-has": 1, "is-at": 2}
17
18
19 class ARPTestCase(VppTestCase):
20     """ ARP Test Case """
21
22     def setUp(self):
23         super(ARPTestCase, self).setUp()
24
25         # create 3 pg interfaces
26         self.create_pg_interfaces(range(4))
27
28         # pg0 configured with ip4 and 6 addresses used for input
29         # pg1 configured with ip4 and 6 addresses used for output
30         # pg2 is unnumbered to pg0
31         for i in self.pg_interfaces:
32             i.admin_up()
33
34         self.pg0.config_ip4()
35         self.pg0.config_ip6()
36         self.pg0.resolve_arp()
37
38         self.pg1.config_ip4()
39         self.pg1.config_ip6()
40
41         # pg3 in a different VRF
42         self.pg3.set_table_ip4(1)
43         self.pg3.config_ip4()
44
45     def tearDown(self):
46         super(ARPTestCase, self).tearDown()
47         self.pg0.unconfig_ip4()
48         self.pg0.unconfig_ip6()
49
50         self.pg1.unconfig_ip4()
51         self.pg1.unconfig_ip6()
52
53         self.pg3.unconfig_ip4()
54
55         for i in self.pg_interfaces:
56             i.admin_down()
57
58     def verify_arp_req(self, rx, smac, sip, dip):
59         ether = rx[Ether]
60         self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
61         self.assertEqual(ether.src, smac)
62
63         arp = rx[ARP]
64         self.assertEqual(arp.hwtype, 1)
65         self.assertEqual(arp.ptype, 0x800)
66         self.assertEqual(arp.hwlen, 6)
67         self.assertEqual(arp.plen, 4)
68         self.assertEqual(arp.op, arp_opts["who-has"])
69         self.assertEqual(arp.hwsrc, smac)
70         self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
71         self.assertEqual(arp.psrc, sip)
72         self.assertEqual(arp.pdst, dip)
73
74     def verify_arp_resp(self, rx, smac, dmac, sip, dip):
75         ether = rx[Ether]
76         self.assertEqual(ether.dst, dmac)
77         self.assertEqual(ether.src, smac)
78
79         arp = rx[ARP]
80         self.assertEqual(arp.hwtype, 1)
81         self.assertEqual(arp.ptype, 0x800)
82         self.assertEqual(arp.hwlen, 6)
83         self.assertEqual(arp.plen, 4)
84         self.assertEqual(arp.op, arp_opts["is-at"])
85         self.assertEqual(arp.hwsrc, smac)
86         self.assertEqual(arp.hwdst, dmac)
87         self.assertEqual(arp.psrc, sip)
88         self.assertEqual(arp.pdst, dip)
89
90     def verify_ip(self, rx, smac, dmac, sip, dip):
91         ether = rx[Ether]
92         self.assertEqual(ether.dst, dmac)
93         self.assertEqual(ether.src, smac)
94
95         ip = rx[IP]
96         self.assertEqual(ip.src, sip)
97         self.assertEqual(ip.dst, dip)
98
99     def verify_ip_o_mpls(self, rx, smac, dmac, label, sip, dip):
100         ether = rx[Ether]
101         self.assertEqual(ether.dst, dmac)
102         self.assertEqual(ether.src, smac)
103
104         mpls = rx[MPLS]
105         self.assertTrue(mpls.label, label)
106
107         ip = rx[IP]
108         self.assertEqual(ip.src, sip)
109         self.assertEqual(ip.dst, dip)
110
111     def send_and_assert_no_replies(self, intf, pkts, remark):
112         intf.add_stream(pkts)
113         self.pg_enable_capture(self.pg_interfaces)
114         self.pg_start()
115         timeout = 1
116         for i in self.pg_interfaces:
117             i.get_capture(0, timeout=timeout)
118             i.assert_nothing_captured(remark=remark)
119             timeout = 0.1
120
121     def test_arp(self):
122         """ ARP """
123
124         #
125         # Generate some hosts on the LAN
126         #
127         self.pg1.generate_remote_hosts(9)
128
129         #
130         # Send IP traffic to one of these unresolved hosts.
131         #  expect the generation of an ARP request
132         #
133         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
134              IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[1].ip4) /
135              UDP(sport=1234, dport=1234) /
136              Raw())
137
138         self.pg0.add_stream(p)
139         self.pg_enable_capture(self.pg_interfaces)
140         self.pg_start()
141
142         rx = self.pg1.get_capture(1)
143
144         self.verify_arp_req(rx[0],
145                             self.pg1.local_mac,
146                             self.pg1.local_ip4,
147                             self.pg1._remote_hosts[1].ip4)
148
149         #
150         # And a dynamic ARP entry for host 1
151         #
152         dyn_arp = VppNeighbor(self,
153                               self.pg1.sw_if_index,
154                               self.pg1.remote_hosts[1].mac,
155                               self.pg1.remote_hosts[1].ip4)
156         dyn_arp.add_vpp_config()
157
158         #
159         # now we expect IP traffic forwarded
160         #
161         dyn_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
162                  IP(src=self.pg0.remote_ip4,
163                     dst=self.pg1._remote_hosts[1].ip4) /
164                  UDP(sport=1234, dport=1234) /
165                  Raw())
166
167         self.pg0.add_stream(dyn_p)
168         self.pg_enable_capture(self.pg_interfaces)
169         self.pg_start()
170
171         rx = self.pg1.get_capture(1)
172
173         self.verify_ip(rx[0],
174                        self.pg1.local_mac,
175                        self.pg1.remote_hosts[1].mac,
176                        self.pg0.remote_ip4,
177                        self.pg1._remote_hosts[1].ip4)
178
179         #
180         # And a Static ARP entry for host 2
181         #
182         static_arp = VppNeighbor(self,
183                                  self.pg1.sw_if_index,
184                                  self.pg1.remote_hosts[2].mac,
185                                  self.pg1.remote_hosts[2].ip4,
186                                  is_static=1)
187         static_arp.add_vpp_config()
188
189         static_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
190                     IP(src=self.pg0.remote_ip4,
191                        dst=self.pg1._remote_hosts[2].ip4) /
192                     UDP(sport=1234, dport=1234) /
193                     Raw())
194
195         self.pg0.add_stream(static_p)
196         self.pg_enable_capture(self.pg_interfaces)
197         self.pg_start()
198
199         rx = self.pg1.get_capture(1)
200
201         self.verify_ip(rx[0],
202                        self.pg1.local_mac,
203                        self.pg1.remote_hosts[2].mac,
204                        self.pg0.remote_ip4,
205                        self.pg1._remote_hosts[2].ip4)
206
207         #
208         # flap the link. dynamic ARPs get flush, statics don't
209         #
210         self.pg1.admin_down()
211         self.pg1.admin_up()
212
213         self.pg0.add_stream(static_p)
214         self.pg_enable_capture(self.pg_interfaces)
215         self.pg_start()
216         rx = self.pg1.get_capture(1)
217
218         self.verify_ip(rx[0],
219                        self.pg1.local_mac,
220                        self.pg1.remote_hosts[2].mac,
221                        self.pg0.remote_ip4,
222                        self.pg1._remote_hosts[2].ip4)
223
224         self.pg0.add_stream(dyn_p)
225         self.pg_enable_capture(self.pg_interfaces)
226         self.pg_start()
227
228         rx = self.pg1.get_capture(1)
229         self.verify_arp_req(rx[0],
230                             self.pg1.local_mac,
231                             self.pg1.local_ip4,
232                             self.pg1._remote_hosts[1].ip4)
233
234         #
235         # Send an ARP request from one of the so-far unlearned remote hosts
236         #
237         p = (Ether(dst="ff:ff:ff:ff:ff:ff",
238                    src=self.pg1._remote_hosts[3].mac) /
239              ARP(op="who-has",
240                  hwsrc=self.pg1._remote_hosts[3].mac,
241                  pdst=self.pg1.local_ip4,
242                  psrc=self.pg1._remote_hosts[3].ip4))
243
244         self.pg1.add_stream(p)
245         self.pg_enable_capture(self.pg_interfaces)
246         self.pg_start()
247
248         rx = self.pg1.get_capture(1)
249         self.verify_arp_resp(rx[0],
250                              self.pg1.local_mac,
251                              self.pg1._remote_hosts[3].mac,
252                              self.pg1.local_ip4,
253                              self.pg1._remote_hosts[3].ip4)
254
255         #
256         # VPP should have learned the mapping for the remote host
257         #
258         self.assertTrue(find_nbr(self,
259                                  self.pg1.sw_if_index,
260                                  self.pg1._remote_hosts[3].ip4))
261         #
262         # Fire in an ARP request before the interface becomes IP enabled
263         #
264         self.pg2.generate_remote_hosts(4)
265
266         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
267              ARP(op="who-has",
268                  hwsrc=self.pg2.remote_mac,
269                  pdst=self.pg1.local_ip4,
270                  psrc=self.pg2.remote_hosts[3].ip4))
271         self.send_and_assert_no_replies(self.pg2, p,
272                                         "interface not IP enabled")
273
274         #
275         # Make pg2 un-numbered to pg1
276         #
277         self.pg2.set_unnumbered(self.pg1.sw_if_index)
278
279         #
280         # We should respond to ARP requests for the unnumbered to address
281         # once an attached route to the source is known
282         #
283         self.send_and_assert_no_replies(
284             self.pg2, p,
285             "ARP req for unnumbered address - no source")
286
287         attached_host = VppIpRoute(self, self.pg2.remote_hosts[3].ip4, 32,
288                                    [VppRoutePath("0.0.0.0",
289                                                  self.pg2.sw_if_index)])
290         attached_host.add_vpp_config()
291
292         self.pg2.add_stream(p)
293         self.pg_enable_capture(self.pg_interfaces)
294         self.pg_start()
295
296         rx = self.pg2.get_capture(1)
297         self.verify_arp_resp(rx[0],
298                              self.pg2.local_mac,
299                              self.pg2.remote_mac,
300                              self.pg1.local_ip4,
301                              self.pg2.remote_hosts[3].ip4)
302
303         #
304         # A neighbor entry that has no associated FIB-entry
305         #
306         arp_no_fib = VppNeighbor(self,
307                                  self.pg1.sw_if_index,
308                                  self.pg1.remote_hosts[4].mac,
309                                  self.pg1.remote_hosts[4].ip4,
310                                  is_no_fib_entry=1)
311         arp_no_fib.add_vpp_config()
312
313         #
314         # check we have the neighbor, but no route
315         #
316         self.assertTrue(find_nbr(self,
317                                  self.pg1.sw_if_index,
318                                  self.pg1._remote_hosts[4].ip4))
319         self.assertFalse(find_route(self,
320                                     self.pg1._remote_hosts[4].ip4,
321                                     32))
322         #
323         # pg2 is unnumbered to pg1, so we can form adjacencies out of pg2
324         # from within pg1's subnet
325         #
326         arp_unnum = VppNeighbor(self,
327                                 self.pg2.sw_if_index,
328                                 self.pg1.remote_hosts[5].mac,
329                                 self.pg1.remote_hosts[5].ip4)
330         arp_unnum.add_vpp_config()
331
332         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
333              IP(src=self.pg0.remote_ip4,
334                 dst=self.pg1._remote_hosts[5].ip4) /
335              UDP(sport=1234, dport=1234) /
336              Raw())
337
338         self.pg0.add_stream(p)
339         self.pg_enable_capture(self.pg_interfaces)
340         self.pg_start()
341
342         rx = self.pg2.get_capture(1)
343
344         self.verify_ip(rx[0],
345                        self.pg2.local_mac,
346                        self.pg1.remote_hosts[5].mac,
347                        self.pg0.remote_ip4,
348                        self.pg1._remote_hosts[5].ip4)
349
350         #
351         # ARP requests from hosts in pg1's subnet sent on pg2 are replied to
352         # with the unnumbered interface's address as the source
353         #
354         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
355              ARP(op="who-has",
356                  hwsrc=self.pg2.remote_mac,
357                  pdst=self.pg1.local_ip4,
358                  psrc=self.pg1.remote_hosts[6].ip4))
359
360         self.pg2.add_stream(p)
361         self.pg_enable_capture(self.pg_interfaces)
362         self.pg_start()
363
364         rx = self.pg2.get_capture(1)
365         self.verify_arp_resp(rx[0],
366                              self.pg2.local_mac,
367                              self.pg2.remote_mac,
368                              self.pg1.local_ip4,
369                              self.pg1.remote_hosts[6].ip4)
370
371         #
372         # An attached host route out of pg2 for an undiscovered hosts generates
373         # an ARP request with the unnumbered address as the source
374         #
375         att_unnum = VppIpRoute(self, self.pg1.remote_hosts[7].ip4, 32,
376                                [VppRoutePath("0.0.0.0",
377                                              self.pg2.sw_if_index)])
378         att_unnum.add_vpp_config()
379
380         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
381              IP(src=self.pg0.remote_ip4,
382                 dst=self.pg1._remote_hosts[7].ip4) /
383              UDP(sport=1234, dport=1234) /
384              Raw())
385
386         self.pg0.add_stream(p)
387         self.pg_enable_capture(self.pg_interfaces)
388         self.pg_start()
389
390         rx = self.pg2.get_capture(1)
391
392         self.verify_arp_req(rx[0],
393                             self.pg2.local_mac,
394                             self.pg1.local_ip4,
395                             self.pg1._remote_hosts[7].ip4)
396
397         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
398              ARP(op="who-has",
399                  hwsrc=self.pg2.remote_mac,
400                  pdst=self.pg1.local_ip4,
401                  psrc=self.pg1.remote_hosts[7].ip4))
402
403         self.pg2.add_stream(p)
404         self.pg_enable_capture(self.pg_interfaces)
405         self.pg_start()
406
407         rx = self.pg2.get_capture(1)
408         self.verify_arp_resp(rx[0],
409                              self.pg2.local_mac,
410                              self.pg2.remote_mac,
411                              self.pg1.local_ip4,
412                              self.pg1.remote_hosts[7].ip4)
413
414         #
415         # An attached host route as yet unresolved out of pg2 for an
416         # undiscovered host, an ARP requests begets a response.
417         #
418         att_unnum1 = VppIpRoute(self, self.pg1.remote_hosts[8].ip4, 32,
419                                 [VppRoutePath("0.0.0.0",
420                                               self.pg2.sw_if_index)])
421         att_unnum1.add_vpp_config()
422
423         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
424              ARP(op="who-has",
425                  hwsrc=self.pg2.remote_mac,
426                  pdst=self.pg1.local_ip4,
427                  psrc=self.pg1.remote_hosts[8].ip4))
428
429         self.pg2.add_stream(p)
430         self.pg_enable_capture(self.pg_interfaces)
431         self.pg_start()
432
433         rx = self.pg2.get_capture(1)
434         self.verify_arp_resp(rx[0],
435                              self.pg2.local_mac,
436                              self.pg2.remote_mac,
437                              self.pg1.local_ip4,
438                              self.pg1.remote_hosts[8].ip4)
439
440         #
441         # ERROR Cases
442         #  1 - don't respond to ARP request for address not within the
443         #      interface's sub-net
444         #  1b - nor within the unnumbered subnet
445         #  1c - nor within the subnet of a different interface
446         #
447         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
448              ARP(op="who-has",
449                  hwsrc=self.pg0.remote_mac,
450                  pdst="10.10.10.3",
451                  psrc=self.pg0.remote_ip4))
452         self.send_and_assert_no_replies(self.pg0, p,
453                                         "ARP req for non-local destination")
454         self.assertFalse(find_nbr(self,
455                                   self.pg0.sw_if_index,
456                                   "10.10.10.3"))
457
458         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
459              ARP(op="who-has",
460                  hwsrc=self.pg2.remote_mac,
461                  pdst="10.10.10.3",
462                  psrc=self.pg1.remote_hosts[7].ip4))
463         self.send_and_assert_no_replies(
464             self.pg0, p,
465             "ARP req for non-local destination - unnum")
466
467         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
468              ARP(op="who-has",
469                  hwsrc=self.pg0.remote_mac,
470                  pdst=self.pg1.local_ip4,
471                  psrc=self.pg1.remote_ip4))
472         self.send_and_assert_no_replies(self.pg0, p,
473                                         "ARP req diff sub-net")
474         self.assertFalse(find_nbr(self,
475                                   self.pg0.sw_if_index,
476                                   self.pg1.remote_ip4))
477
478         #
479         #  2 - don't respond to ARP request from an address not within the
480         #      interface's sub-net
481         #
482         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
483              ARP(op="who-has",
484                  hwsrc=self.pg0.remote_mac,
485                  psrc="10.10.10.3",
486                  pdst=self.pg0.local_ip4))
487         self.send_and_assert_no_replies(self.pg0, p,
488                                         "ARP req for non-local source")
489         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
490              ARP(op="who-has",
491                  hwsrc=self.pg2.remote_mac,
492                  psrc="10.10.10.3",
493                  pdst=self.pg0.local_ip4))
494         self.send_and_assert_no_replies(
495             self.pg0, p,
496             "ARP req for non-local source - unnum")
497
498         #
499         #  3 - don't respond to ARP request from an address that belongs to
500         #      the router
501         #
502         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
503              ARP(op="who-has",
504                  hwsrc=self.pg0.remote_mac,
505                  psrc=self.pg0.local_ip4,
506                  pdst=self.pg0.local_ip4))
507         self.send_and_assert_no_replies(self.pg0, p,
508                                         "ARP req for non-local source")
509
510         #
511         #  4 - don't respond to ARP requests that has mac source different
512         #      from ARP request HW source
513         #      the router
514         #
515         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
516              ARP(op="who-has",
517                  hwsrc="00:00:00:DE:AD:BE",
518                  psrc=self.pg0.remote_ip4,
519                  pdst=self.pg0.local_ip4))
520         self.send_and_assert_no_replies(self.pg0, p,
521                                         "ARP req for non-local source")
522
523         #
524         # cleanup
525         #
526         dyn_arp.remove_vpp_config()
527         static_arp.remove_vpp_config()
528         self.pg2.unset_unnumbered(self.pg1.sw_if_index)
529
530         # need this to flush the adj-fibs
531         self.pg2.unset_unnumbered(self.pg1.sw_if_index)
532         self.pg2.admin_down()
533
534     def test_proxy_arp(self):
535         """ Proxy ARP """
536
537         self.pg1.generate_remote_hosts(2)
538
539         #
540         # Proxy ARP rewquest packets for each interface
541         #
542         arp_req_pg0 = (Ether(src=self.pg0.remote_mac,
543                              dst="ff:ff:ff:ff:ff:ff") /
544                        ARP(op="who-has",
545                            hwsrc=self.pg0.remote_mac,
546                            pdst="10.10.10.3",
547                            psrc=self.pg0.remote_ip4))
548         arp_req_pg1 = (Ether(src=self.pg1.remote_mac,
549                              dst="ff:ff:ff:ff:ff:ff") /
550                        ARP(op="who-has",
551                            hwsrc=self.pg1.remote_mac,
552                            pdst="10.10.10.3",
553                            psrc=self.pg1.remote_ip4))
554         arp_req_pg2 = (Ether(src=self.pg2.remote_mac,
555                              dst="ff:ff:ff:ff:ff:ff") /
556                        ARP(op="who-has",
557                            hwsrc=self.pg2.remote_mac,
558                            pdst="10.10.10.3",
559                            psrc=self.pg1.remote_hosts[1].ip4))
560         arp_req_pg3 = (Ether(src=self.pg3.remote_mac,
561                              dst="ff:ff:ff:ff:ff:ff") /
562                        ARP(op="who-has",
563                            hwsrc=self.pg3.remote_mac,
564                            pdst="10.10.10.3",
565                            psrc=self.pg3.remote_ip4))
566
567         #
568         # Configure Proxy ARP for 10.10.10.0 -> 10.10.10.124
569         #
570         self.vapi.proxy_arp_add_del(inet_pton(AF_INET, "10.10.10.2"),
571                                     inet_pton(AF_INET, "10.10.10.124"))
572
573         #
574         # No responses are sent when the interfaces are not enabled for proxy
575         # ARP
576         #
577         self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
578                                         "ARP req from unconfigured interface")
579         self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
580                                         "ARP req from unconfigured interface")
581
582         #
583         # Make pg2 un-numbered to pg1
584         #  still won't reply.
585         #
586         self.pg2.set_unnumbered(self.pg1.sw_if_index)
587
588         self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
589                                         "ARP req from unnumbered interface")
590
591         #
592         # Enable each interface to reply to proxy ARPs
593         #
594         for i in self.pg_interfaces:
595             i.set_proxy_arp()
596
597         #
598         # Now each of the interfaces should reply to a request to a proxied
599         # address
600         #
601         self.pg0.add_stream(arp_req_pg0)
602         self.pg_enable_capture(self.pg_interfaces)
603         self.pg_start()
604
605         rx = self.pg0.get_capture(1)
606         self.verify_arp_resp(rx[0],
607                              self.pg0.local_mac,
608                              self.pg0.remote_mac,
609                              "10.10.10.3",
610                              self.pg0.remote_ip4)
611
612         self.pg1.add_stream(arp_req_pg1)
613         self.pg_enable_capture(self.pg_interfaces)
614         self.pg_start()
615
616         rx = self.pg1.get_capture(1)
617         self.verify_arp_resp(rx[0],
618                              self.pg1.local_mac,
619                              self.pg1.remote_mac,
620                              "10.10.10.3",
621                              self.pg1.remote_ip4)
622
623         self.pg2.add_stream(arp_req_pg2)
624         self.pg_enable_capture(self.pg_interfaces)
625         self.pg_start()
626
627         rx = self.pg2.get_capture(1)
628         self.verify_arp_resp(rx[0],
629                              self.pg2.local_mac,
630                              self.pg2.remote_mac,
631                              "10.10.10.3",
632                              self.pg1.remote_hosts[1].ip4)
633
634         #
635         # A request for an address out of the configured range
636         #
637         arp_req_pg1_hi = (Ether(src=self.pg1.remote_mac,
638                                 dst="ff:ff:ff:ff:ff:ff") /
639                           ARP(op="who-has",
640                               hwsrc=self.pg1.remote_mac,
641                               pdst="10.10.10.125",
642                               psrc=self.pg1.remote_ip4))
643         self.send_and_assert_no_replies(self.pg1, arp_req_pg1_hi,
644                                         "ARP req out of range HI")
645         arp_req_pg1_low = (Ether(src=self.pg1.remote_mac,
646                                  dst="ff:ff:ff:ff:ff:ff") /
647                            ARP(op="who-has",
648                                hwsrc=self.pg1.remote_mac,
649                                pdst="10.10.10.1",
650                                psrc=self.pg1.remote_ip4))
651         self.send_and_assert_no_replies(self.pg1, arp_req_pg1_low,
652                                         "ARP req out of range Low")
653
654         #
655         # Request for an address in the proxy range but from an interface
656         # in a different VRF
657         #
658         self.send_and_assert_no_replies(self.pg3, arp_req_pg3,
659                                         "ARP req from different VRF")
660
661         #
662         # Disable Each interface for proxy ARP
663         #  - expect none to respond
664         #
665         for i in self.pg_interfaces:
666             i.set_proxy_arp(0)
667
668         self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
669                                         "ARP req from disable")
670         self.send_and_assert_no_replies(self.pg1, arp_req_pg1,
671                                         "ARP req from disable")
672         self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
673                                         "ARP req from disable")
674
675         #
676         # clean up on interface 2
677         #
678         self.pg2.unset_unnumbered(self.pg1.sw_if_index)
679
680     def test_mpls(self):
681         """ MPLS """
682
683         #
684         # Interface 2 does not yet have ip4 config
685         #
686         self.pg2.config_ip4()
687         self.pg2.generate_remote_hosts(2)
688
689         #
690         # Add a reoute with out going label via an ARP unresolved next-hop
691         #
692         ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
693                                  [VppRoutePath(self.pg2.remote_hosts[1].ip4,
694                                                self.pg2.sw_if_index,
695                                                labels=[55])])
696         ip_10_0_0_1.add_vpp_config()
697
698         #
699         # packets should generate an ARP request
700         #
701         p = (Ether(src=self.pg0.remote_mac,
702                    dst=self.pg0.local_mac) /
703              IP(src=self.pg0.remote_ip4, dst="10.0.0.1") /
704              UDP(sport=1234, dport=1234) /
705              Raw('\xa5' * 100))
706
707         self.pg0.add_stream(p)
708         self.pg_enable_capture(self.pg_interfaces)
709         self.pg_start()
710
711         rx = self.pg2.get_capture(1)
712         self.verify_arp_req(rx[0],
713                             self.pg2.local_mac,
714                             self.pg2.local_ip4,
715                             self.pg2._remote_hosts[1].ip4)
716
717         #
718         # now resolve the neighbours
719         #
720         self.pg2.configure_ipv4_neighbors()
721
722         #
723         # Now packet should be properly MPLS encapped.
724         #  This verifies that MPLS link-type adjacencies are completed
725         #  when the ARP entry resolves
726         #
727         self.pg0.add_stream(p)
728         self.pg_enable_capture(self.pg_interfaces)
729         self.pg_start()
730
731         rx = self.pg2.get_capture(1)
732         self.verify_ip_o_mpls(rx[0],
733                               self.pg2.local_mac,
734                               self.pg2.remote_hosts[1].mac,
735                               55,
736                               self.pg0.remote_ip4,
737                               "10.0.0.1")
738         self.pg2.unconfig_ip4()
739
740 if __name__ == '__main__':
741     unittest.main(testRunner=VppTestRunner)