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