Add VAT handlers for LISP-GPE API
[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, Dot1Q
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_arp_vrrp_resp(self, rx, smac, dmac, sip, dip):
91         ether = rx[Ether]
92         self.assertEqual(ether.dst, dmac)
93         self.assertEqual(ether.src, smac)
94
95         arp = rx[ARP]
96         self.assertEqual(arp.hwtype, 1)
97         self.assertEqual(arp.ptype, 0x800)
98         self.assertEqual(arp.hwlen, 6)
99         self.assertEqual(arp.plen, 4)
100         self.assertEqual(arp.op, arp_opts["is-at"])
101         self.assertNotEqual(arp.hwsrc, smac)
102         self.assertTrue("00:00:5e:00:01" in arp.hwsrc or
103                         "00:00:5E:00:01" in arp.hwsrc)
104         self.assertEqual(arp.hwdst, dmac)
105         self.assertEqual(arp.psrc, sip)
106         self.assertEqual(arp.pdst, dip)
107
108     def verify_ip(self, rx, smac, dmac, sip, dip):
109         ether = rx[Ether]
110         self.assertEqual(ether.dst, dmac)
111         self.assertEqual(ether.src, smac)
112
113         ip = rx[IP]
114         self.assertEqual(ip.src, sip)
115         self.assertEqual(ip.dst, dip)
116
117     def verify_ip_o_mpls(self, rx, smac, dmac, label, sip, dip):
118         ether = rx[Ether]
119         self.assertEqual(ether.dst, dmac)
120         self.assertEqual(ether.src, smac)
121
122         mpls = rx[MPLS]
123         self.assertTrue(mpls.label, label)
124
125         ip = rx[IP]
126         self.assertEqual(ip.src, sip)
127         self.assertEqual(ip.dst, dip)
128
129     def send_and_assert_no_replies(self, intf, pkts, remark):
130         intf.add_stream(pkts)
131         self.pg_enable_capture(self.pg_interfaces)
132         self.pg_start()
133         timeout = 1
134         for i in self.pg_interfaces:
135             i.get_capture(0, timeout=timeout)
136             i.assert_nothing_captured(remark=remark)
137             timeout = 0.1
138
139     def test_arp(self):
140         """ ARP """
141
142         #
143         # Generate some hosts on the LAN
144         #
145         self.pg1.generate_remote_hosts(10)
146
147         #
148         # Send IP traffic to one of these unresolved hosts.
149         #  expect the generation of an ARP request
150         #
151         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
152              IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[1].ip4) /
153              UDP(sport=1234, dport=1234) /
154              Raw())
155
156         self.pg0.add_stream(p)
157         self.pg_enable_capture(self.pg_interfaces)
158         self.pg_start()
159
160         rx = self.pg1.get_capture(1)
161
162         self.verify_arp_req(rx[0],
163                             self.pg1.local_mac,
164                             self.pg1.local_ip4,
165                             self.pg1._remote_hosts[1].ip4)
166
167         #
168         # And a dynamic ARP entry for host 1
169         #
170         dyn_arp = VppNeighbor(self,
171                               self.pg1.sw_if_index,
172                               self.pg1.remote_hosts[1].mac,
173                               self.pg1.remote_hosts[1].ip4)
174         dyn_arp.add_vpp_config()
175
176         #
177         # now we expect IP traffic forwarded
178         #
179         dyn_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
180                  IP(src=self.pg0.remote_ip4,
181                     dst=self.pg1._remote_hosts[1].ip4) /
182                  UDP(sport=1234, dport=1234) /
183                  Raw())
184
185         self.pg0.add_stream(dyn_p)
186         self.pg_enable_capture(self.pg_interfaces)
187         self.pg_start()
188
189         rx = self.pg1.get_capture(1)
190
191         self.verify_ip(rx[0],
192                        self.pg1.local_mac,
193                        self.pg1.remote_hosts[1].mac,
194                        self.pg0.remote_ip4,
195                        self.pg1._remote_hosts[1].ip4)
196
197         #
198         # And a Static ARP entry for host 2
199         #
200         static_arp = VppNeighbor(self,
201                                  self.pg1.sw_if_index,
202                                  self.pg1.remote_hosts[2].mac,
203                                  self.pg1.remote_hosts[2].ip4,
204                                  is_static=1)
205         static_arp.add_vpp_config()
206
207         static_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
208                     IP(src=self.pg0.remote_ip4,
209                        dst=self.pg1._remote_hosts[2].ip4) /
210                     UDP(sport=1234, dport=1234) /
211                     Raw())
212
213         self.pg0.add_stream(static_p)
214         self.pg_enable_capture(self.pg_interfaces)
215         self.pg_start()
216
217         rx = self.pg1.get_capture(1)
218
219         self.verify_ip(rx[0],
220                        self.pg1.local_mac,
221                        self.pg1.remote_hosts[2].mac,
222                        self.pg0.remote_ip4,
223                        self.pg1._remote_hosts[2].ip4)
224
225         #
226         # flap the link. dynamic ARPs get flush, statics don't
227         #
228         self.pg1.admin_down()
229         self.pg1.admin_up()
230
231         self.pg0.add_stream(static_p)
232         self.pg_enable_capture(self.pg_interfaces)
233         self.pg_start()
234         rx = self.pg1.get_capture(1)
235
236         self.verify_ip(rx[0],
237                        self.pg1.local_mac,
238                        self.pg1.remote_hosts[2].mac,
239                        self.pg0.remote_ip4,
240                        self.pg1._remote_hosts[2].ip4)
241
242         self.pg0.add_stream(dyn_p)
243         self.pg_enable_capture(self.pg_interfaces)
244         self.pg_start()
245
246         rx = self.pg1.get_capture(1)
247         self.verify_arp_req(rx[0],
248                             self.pg1.local_mac,
249                             self.pg1.local_ip4,
250                             self.pg1._remote_hosts[1].ip4)
251
252         #
253         # Send an ARP request from one of the so-far unlearned remote hosts
254         #
255         p = (Ether(dst="ff:ff:ff:ff:ff:ff",
256                    src=self.pg1._remote_hosts[3].mac) /
257              ARP(op="who-has",
258                  hwsrc=self.pg1._remote_hosts[3].mac,
259                  pdst=self.pg1.local_ip4,
260                  psrc=self.pg1._remote_hosts[3].ip4))
261
262         self.pg1.add_stream(p)
263         self.pg_enable_capture(self.pg_interfaces)
264         self.pg_start()
265
266         rx = self.pg1.get_capture(1)
267         self.verify_arp_resp(rx[0],
268                              self.pg1.local_mac,
269                              self.pg1._remote_hosts[3].mac,
270                              self.pg1.local_ip4,
271                              self.pg1._remote_hosts[3].ip4)
272
273         #
274         # VPP should have learned the mapping for the remote host
275         #
276         self.assertTrue(find_nbr(self,
277                                  self.pg1.sw_if_index,
278                                  self.pg1._remote_hosts[3].ip4))
279         #
280         # Fire in an ARP request before the interface becomes IP enabled
281         #
282         self.pg2.generate_remote_hosts(4)
283
284         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
285              ARP(op="who-has",
286                  hwsrc=self.pg2.remote_mac,
287                  pdst=self.pg1.local_ip4,
288                  psrc=self.pg2.remote_hosts[3].ip4))
289         pt = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
290               Dot1Q(vlan=0) /
291               ARP(op="who-has",
292                   hwsrc=self.pg2.remote_mac,
293                   pdst=self.pg1.local_ip4,
294                   psrc=self.pg2.remote_hosts[3].ip4))
295         self.send_and_assert_no_replies(self.pg2, p,
296                                         "interface not IP enabled")
297
298         #
299         # Make pg2 un-numbered to pg1
300         #
301         self.pg2.set_unnumbered(self.pg1.sw_if_index)
302
303         #
304         # We should respond to ARP requests for the unnumbered to address
305         # once an attached route to the source is known
306         #
307         self.send_and_assert_no_replies(
308             self.pg2, p,
309             "ARP req for unnumbered address - no source")
310
311         attached_host = VppIpRoute(self, self.pg2.remote_hosts[3].ip4, 32,
312                                    [VppRoutePath("0.0.0.0",
313                                                  self.pg2.sw_if_index)])
314         attached_host.add_vpp_config()
315
316         self.pg2.add_stream(p)
317         self.pg_enable_capture(self.pg_interfaces)
318         self.pg_start()
319
320         rx = self.pg2.get_capture(1)
321         self.verify_arp_resp(rx[0],
322                              self.pg2.local_mac,
323                              self.pg2.remote_mac,
324                              self.pg1.local_ip4,
325                              self.pg2.remote_hosts[3].ip4)
326
327         self.pg2.add_stream(pt)
328         self.pg_enable_capture(self.pg_interfaces)
329         self.pg_start()
330
331         rx = self.pg2.get_capture(1)
332         self.verify_arp_resp(rx[0],
333                              self.pg2.local_mac,
334                              self.pg2.remote_mac,
335                              self.pg1.local_ip4,
336                              self.pg2.remote_hosts[3].ip4)
337
338         #
339         # A neighbor entry that has no associated FIB-entry
340         #
341         arp_no_fib = VppNeighbor(self,
342                                  self.pg1.sw_if_index,
343                                  self.pg1.remote_hosts[4].mac,
344                                  self.pg1.remote_hosts[4].ip4,
345                                  is_no_fib_entry=1)
346         arp_no_fib.add_vpp_config()
347
348         #
349         # check we have the neighbor, but no route
350         #
351         self.assertTrue(find_nbr(self,
352                                  self.pg1.sw_if_index,
353                                  self.pg1._remote_hosts[4].ip4))
354         self.assertFalse(find_route(self,
355                                     self.pg1._remote_hosts[4].ip4,
356                                     32))
357         #
358         # pg2 is unnumbered to pg1, so we can form adjacencies out of pg2
359         # from within pg1's subnet
360         #
361         arp_unnum = VppNeighbor(self,
362                                 self.pg2.sw_if_index,
363                                 self.pg1.remote_hosts[5].mac,
364                                 self.pg1.remote_hosts[5].ip4)
365         arp_unnum.add_vpp_config()
366
367         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
368              IP(src=self.pg0.remote_ip4,
369                 dst=self.pg1._remote_hosts[5].ip4) /
370              UDP(sport=1234, dport=1234) /
371              Raw())
372
373         self.pg0.add_stream(p)
374         self.pg_enable_capture(self.pg_interfaces)
375         self.pg_start()
376
377         rx = self.pg2.get_capture(1)
378
379         self.verify_ip(rx[0],
380                        self.pg2.local_mac,
381                        self.pg1.remote_hosts[5].mac,
382                        self.pg0.remote_ip4,
383                        self.pg1._remote_hosts[5].ip4)
384
385         #
386         # ARP requests from hosts in pg1's subnet sent on pg2 are replied to
387         # with the unnumbered interface's address as the source
388         #
389         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
390              ARP(op="who-has",
391                  hwsrc=self.pg2.remote_mac,
392                  pdst=self.pg1.local_ip4,
393                  psrc=self.pg1.remote_hosts[6].ip4))
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.pg1.remote_hosts[6].ip4)
405
406         #
407         # An attached host route out of pg2 for an undiscovered hosts generates
408         # an ARP request with the unnumbered address as the source
409         #
410         att_unnum = VppIpRoute(self, self.pg1.remote_hosts[7].ip4, 32,
411                                [VppRoutePath("0.0.0.0",
412                                              self.pg2.sw_if_index)])
413         att_unnum.add_vpp_config()
414
415         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
416              IP(src=self.pg0.remote_ip4,
417                 dst=self.pg1._remote_hosts[7].ip4) /
418              UDP(sport=1234, dport=1234) /
419              Raw())
420
421         self.pg0.add_stream(p)
422         self.pg_enable_capture(self.pg_interfaces)
423         self.pg_start()
424
425         rx = self.pg2.get_capture(1)
426
427         self.verify_arp_req(rx[0],
428                             self.pg2.local_mac,
429                             self.pg1.local_ip4,
430                             self.pg1._remote_hosts[7].ip4)
431
432         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
433              ARP(op="who-has",
434                  hwsrc=self.pg2.remote_mac,
435                  pdst=self.pg1.local_ip4,
436                  psrc=self.pg1.remote_hosts[7].ip4))
437
438         self.pg2.add_stream(p)
439         self.pg_enable_capture(self.pg_interfaces)
440         self.pg_start()
441
442         rx = self.pg2.get_capture(1)
443         self.verify_arp_resp(rx[0],
444                              self.pg2.local_mac,
445                              self.pg2.remote_mac,
446                              self.pg1.local_ip4,
447                              self.pg1.remote_hosts[7].ip4)
448
449         #
450         # An attached host route as yet unresolved out of pg2 for an
451         # undiscovered host, an ARP requests begets a response.
452         #
453         att_unnum1 = VppIpRoute(self, self.pg1.remote_hosts[8].ip4, 32,
454                                 [VppRoutePath("0.0.0.0",
455                                               self.pg2.sw_if_index)])
456         att_unnum1.add_vpp_config()
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=self.pg1.local_ip4,
462                  psrc=self.pg1.remote_hosts[8].ip4))
463
464         self.pg2.add_stream(p)
465         self.pg_enable_capture(self.pg_interfaces)
466         self.pg_start()
467
468         rx = self.pg2.get_capture(1)
469         self.verify_arp_resp(rx[0],
470                              self.pg2.local_mac,
471                              self.pg2.remote_mac,
472                              self.pg1.local_ip4,
473                              self.pg1.remote_hosts[8].ip4)
474
475         #
476         # Send an ARP request from one of the so-far unlearned remote hosts
477         # with a VLAN0 tag
478         #
479         p = (Ether(dst="ff:ff:ff:ff:ff:ff",
480                    src=self.pg1._remote_hosts[9].mac) /
481              Dot1Q(vlan=0) /
482              ARP(op="who-has",
483                  hwsrc=self.pg1._remote_hosts[9].mac,
484                  pdst=self.pg1.local_ip4,
485                  psrc=self.pg1._remote_hosts[9].ip4))
486
487         self.pg1.add_stream(p)
488         self.pg_enable_capture(self.pg_interfaces)
489         self.pg_start()
490
491         rx = self.pg1.get_capture(1)
492         self.verify_arp_resp(rx[0],
493                              self.pg1.local_mac,
494                              self.pg1._remote_hosts[9].mac,
495                              self.pg1.local_ip4,
496                              self.pg1._remote_hosts[9].ip4)
497
498         #
499         # ERROR Cases
500         #  1 - don't respond to ARP request for address not within the
501         #      interface's sub-net
502         #  1b - nor within the unnumbered subnet
503         #  1c - nor within the subnet of a different interface
504         #
505         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
506              ARP(op="who-has",
507                  hwsrc=self.pg0.remote_mac,
508                  pdst="10.10.10.3",
509                  psrc=self.pg0.remote_ip4))
510         self.send_and_assert_no_replies(self.pg0, p,
511                                         "ARP req for non-local destination")
512         self.assertFalse(find_nbr(self,
513                                   self.pg0.sw_if_index,
514                                   "10.10.10.3"))
515
516         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
517              ARP(op="who-has",
518                  hwsrc=self.pg2.remote_mac,
519                  pdst="10.10.10.3",
520                  psrc=self.pg1.remote_hosts[7].ip4))
521         self.send_and_assert_no_replies(
522             self.pg0, p,
523             "ARP req for non-local destination - unnum")
524
525         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
526              ARP(op="who-has",
527                  hwsrc=self.pg0.remote_mac,
528                  pdst=self.pg1.local_ip4,
529                  psrc=self.pg1.remote_ip4))
530         self.send_and_assert_no_replies(self.pg0, p,
531                                         "ARP req diff sub-net")
532         self.assertFalse(find_nbr(self,
533                                   self.pg0.sw_if_index,
534                                   self.pg1.remote_ip4))
535
536         #
537         #  2 - don't respond to ARP request from an address not within the
538         #      interface's sub-net
539         #
540         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
541              ARP(op="who-has",
542                  hwsrc=self.pg0.remote_mac,
543                  psrc="10.10.10.3",
544                  pdst=self.pg0.local_ip4))
545         self.send_and_assert_no_replies(self.pg0, p,
546                                         "ARP req for non-local source")
547         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
548              ARP(op="who-has",
549                  hwsrc=self.pg2.remote_mac,
550                  psrc="10.10.10.3",
551                  pdst=self.pg0.local_ip4))
552         self.send_and_assert_no_replies(
553             self.pg0, p,
554             "ARP req for non-local source - unnum")
555
556         #
557         #  3 - don't respond to ARP request from an address that belongs to
558         #      the router
559         #
560         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
561              ARP(op="who-has",
562                  hwsrc=self.pg0.remote_mac,
563                  psrc=self.pg0.local_ip4,
564                  pdst=self.pg0.local_ip4))
565         self.send_and_assert_no_replies(self.pg0, p,
566                                         "ARP req for non-local source")
567
568         #
569         #  4 - don't respond to ARP requests that has mac source different
570         #      from ARP request HW source
571         #      the router
572         #
573         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
574              ARP(op="who-has",
575                  hwsrc="00:00:00:DE:AD:BE",
576                  psrc=self.pg0.remote_ip4,
577                  pdst=self.pg0.local_ip4))
578         self.send_and_assert_no_replies(self.pg0, p,
579                                         "ARP req for non-local source")
580
581         #
582         # cleanup
583         #
584         dyn_arp.remove_vpp_config()
585         static_arp.remove_vpp_config()
586         self.pg2.unset_unnumbered(self.pg1.sw_if_index)
587
588         # need this to flush the adj-fibs
589         self.pg2.unset_unnumbered(self.pg1.sw_if_index)
590         self.pg2.admin_down()
591
592     def test_proxy_arp(self):
593         """ Proxy ARP """
594
595         self.pg1.generate_remote_hosts(2)
596
597         #
598         # Proxy ARP rewquest packets for each interface
599         #
600         arp_req_pg0 = (Ether(src=self.pg0.remote_mac,
601                              dst="ff:ff:ff:ff:ff:ff") /
602                        ARP(op="who-has",
603                            hwsrc=self.pg0.remote_mac,
604                            pdst="10.10.10.3",
605                            psrc=self.pg0.remote_ip4))
606         arp_req_pg0_tagged = (Ether(src=self.pg0.remote_mac,
607                                     dst="ff:ff:ff:ff:ff:ff") /
608                               Dot1Q(vlan=0) /
609                               ARP(op="who-has",
610                                   hwsrc=self.pg0.remote_mac,
611                                   pdst="10.10.10.3",
612                                   psrc=self.pg0.remote_ip4))
613         arp_req_pg1 = (Ether(src=self.pg1.remote_mac,
614                              dst="ff:ff:ff:ff:ff:ff") /
615                        ARP(op="who-has",
616                            hwsrc=self.pg1.remote_mac,
617                            pdst="10.10.10.3",
618                            psrc=self.pg1.remote_ip4))
619         arp_req_pg2 = (Ether(src=self.pg2.remote_mac,
620                              dst="ff:ff:ff:ff:ff:ff") /
621                        ARP(op="who-has",
622                            hwsrc=self.pg2.remote_mac,
623                            pdst="10.10.10.3",
624                            psrc=self.pg1.remote_hosts[1].ip4))
625         arp_req_pg3 = (Ether(src=self.pg3.remote_mac,
626                              dst="ff:ff:ff:ff:ff:ff") /
627                        ARP(op="who-has",
628                            hwsrc=self.pg3.remote_mac,
629                            pdst="10.10.10.3",
630                            psrc=self.pg3.remote_ip4))
631
632         #
633         # Configure Proxy ARP for 10.10.10.0 -> 10.10.10.124
634         #
635         self.vapi.proxy_arp_add_del(inet_pton(AF_INET, "10.10.10.2"),
636                                     inet_pton(AF_INET, "10.10.10.124"))
637
638         #
639         # No responses are sent when the interfaces are not enabled for proxy
640         # ARP
641         #
642         self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
643                                         "ARP req from unconfigured interface")
644         self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
645                                         "ARP req from unconfigured interface")
646
647         #
648         # Make pg2 un-numbered to pg1
649         #  still won't reply.
650         #
651         self.pg2.set_unnumbered(self.pg1.sw_if_index)
652
653         self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
654                                         "ARP req from unnumbered interface")
655
656         #
657         # Enable each interface to reply to proxy ARPs
658         #
659         for i in self.pg_interfaces:
660             i.set_proxy_arp()
661
662         #
663         # Now each of the interfaces should reply to a request to a proxied
664         # address
665         #
666         self.pg0.add_stream(arp_req_pg0)
667         self.pg_enable_capture(self.pg_interfaces)
668         self.pg_start()
669
670         rx = self.pg0.get_capture(1)
671         self.verify_arp_resp(rx[0],
672                              self.pg0.local_mac,
673                              self.pg0.remote_mac,
674                              "10.10.10.3",
675                              self.pg0.remote_ip4)
676
677         self.pg0.add_stream(arp_req_pg0_tagged)
678         self.pg_enable_capture(self.pg_interfaces)
679         self.pg_start()
680
681         rx = self.pg0.get_capture(1)
682         self.verify_arp_resp(rx[0],
683                              self.pg0.local_mac,
684                              self.pg0.remote_mac,
685                              "10.10.10.3",
686                              self.pg0.remote_ip4)
687
688         self.pg1.add_stream(arp_req_pg1)
689         self.pg_enable_capture(self.pg_interfaces)
690         self.pg_start()
691
692         rx = self.pg1.get_capture(1)
693         self.verify_arp_resp(rx[0],
694                              self.pg1.local_mac,
695                              self.pg1.remote_mac,
696                              "10.10.10.3",
697                              self.pg1.remote_ip4)
698
699         self.pg2.add_stream(arp_req_pg2)
700         self.pg_enable_capture(self.pg_interfaces)
701         self.pg_start()
702
703         rx = self.pg2.get_capture(1)
704         self.verify_arp_resp(rx[0],
705                              self.pg2.local_mac,
706                              self.pg2.remote_mac,
707                              "10.10.10.3",
708                              self.pg1.remote_hosts[1].ip4)
709
710         #
711         # A request for an address out of the configured range
712         #
713         arp_req_pg1_hi = (Ether(src=self.pg1.remote_mac,
714                                 dst="ff:ff:ff:ff:ff:ff") /
715                           ARP(op="who-has",
716                               hwsrc=self.pg1.remote_mac,
717                               pdst="10.10.10.125",
718                               psrc=self.pg1.remote_ip4))
719         self.send_and_assert_no_replies(self.pg1, arp_req_pg1_hi,
720                                         "ARP req out of range HI")
721         arp_req_pg1_low = (Ether(src=self.pg1.remote_mac,
722                                  dst="ff:ff:ff:ff:ff:ff") /
723                            ARP(op="who-has",
724                                hwsrc=self.pg1.remote_mac,
725                                pdst="10.10.10.1",
726                                psrc=self.pg1.remote_ip4))
727         self.send_and_assert_no_replies(self.pg1, arp_req_pg1_low,
728                                         "ARP req out of range Low")
729
730         #
731         # Request for an address in the proxy range but from an interface
732         # in a different VRF
733         #
734         self.send_and_assert_no_replies(self.pg3, arp_req_pg3,
735                                         "ARP req from different VRF")
736
737         #
738         # Disable Each interface for proxy ARP
739         #  - expect none to respond
740         #
741         for i in self.pg_interfaces:
742             i.set_proxy_arp(0)
743
744         self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
745                                         "ARP req from disable")
746         self.send_and_assert_no_replies(self.pg1, arp_req_pg1,
747                                         "ARP req from disable")
748         self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
749                                         "ARP req from disable")
750
751         #
752         # clean up on interface 2
753         #
754         self.pg2.unset_unnumbered(self.pg1.sw_if_index)
755
756     def test_mpls(self):
757         """ MPLS """
758
759         #
760         # Interface 2 does not yet have ip4 config
761         #
762         self.pg2.config_ip4()
763         self.pg2.generate_remote_hosts(2)
764
765         #
766         # Add a reoute with out going label via an ARP unresolved next-hop
767         #
768         ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
769                                  [VppRoutePath(self.pg2.remote_hosts[1].ip4,
770                                                self.pg2.sw_if_index,
771                                                labels=[55])])
772         ip_10_0_0_1.add_vpp_config()
773
774         #
775         # packets should generate an ARP request
776         #
777         p = (Ether(src=self.pg0.remote_mac,
778                    dst=self.pg0.local_mac) /
779              IP(src=self.pg0.remote_ip4, dst="10.0.0.1") /
780              UDP(sport=1234, dport=1234) /
781              Raw('\xa5' * 100))
782
783         self.pg0.add_stream(p)
784         self.pg_enable_capture(self.pg_interfaces)
785         self.pg_start()
786
787         rx = self.pg2.get_capture(1)
788         self.verify_arp_req(rx[0],
789                             self.pg2.local_mac,
790                             self.pg2.local_ip4,
791                             self.pg2._remote_hosts[1].ip4)
792
793         #
794         # now resolve the neighbours
795         #
796         self.pg2.configure_ipv4_neighbors()
797
798         #
799         # Now packet should be properly MPLS encapped.
800         #  This verifies that MPLS link-type adjacencies are completed
801         #  when the ARP entry resolves
802         #
803         self.pg0.add_stream(p)
804         self.pg_enable_capture(self.pg_interfaces)
805         self.pg_start()
806
807         rx = self.pg2.get_capture(1)
808         self.verify_ip_o_mpls(rx[0],
809                               self.pg2.local_mac,
810                               self.pg2.remote_hosts[1].mac,
811                               55,
812                               self.pg0.remote_ip4,
813                               "10.0.0.1")
814         self.pg2.unconfig_ip4()
815
816     def test_arp_vrrp(self):
817         """ ARP reply with VRRP virtual src hw addr """
818
819         #
820         # IP packet destined for pg1 remote host arrives on pg0 resulting
821         # in an ARP request for the address of the remote host on pg1
822         #
823         p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
824               IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
825               UDP(sport=1234, dport=1234) /
826               Raw())
827
828         self.pg0.add_stream(p0)
829         self.pg_enable_capture(self.pg_interfaces)
830         self.pg_start()
831
832         rx1 = self.pg1.get_capture(1)
833
834         self.verify_arp_req(rx1[0],
835                             self.pg1.local_mac,
836                             self.pg1.local_ip4,
837                             self.pg1.remote_ip4)
838
839         #
840         # ARP reply for address of pg1 remote host arrives on pg1 with
841         # the hw src addr set to a value in the VRRP IPv4 range of
842         # MAC addresses
843         #
844         p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
845               ARP(op="is-at", hwdst=self.pg1.local_mac,
846                   hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
847                   psrc=self.pg1.remote_ip4))
848
849         self.pg1.add_stream(p1)
850         self.pg_enable_capture(self.pg_interfaces)
851         self.pg_start()
852
853         #
854         # IP packet destined for pg1 remote host arrives on pg0 again.
855         # VPP should have an ARP entry for that address now and the packet
856         # should be sent out pg1.
857         #
858         self.pg0.add_stream(p0)
859         self.pg_enable_capture(self.pg_interfaces)
860         self.pg_start()
861
862         rx1 = self.pg1.get_capture(1)
863
864         self.verify_ip(rx1[0],
865                        self.pg1.local_mac,
866                        "00:00:5e:00:01:09",
867                        self.pg0.remote_ip4,
868                        self.pg1.remote_ip4)
869
870         self.pg1.admin_down()
871         self.pg1.admin_up()
872
873     def test_arp_duplicates(self):
874         """ ARP Duplicates"""
875
876         #
877         # Generate some hosts on the LAN
878         #
879         self.pg1.generate_remote_hosts(3)
880
881         #
882         # Add host 1 on pg1 and pg2
883         #
884         arp_pg1 = VppNeighbor(self,
885                               self.pg1.sw_if_index,
886                               self.pg1.remote_hosts[1].mac,
887                               self.pg1.remote_hosts[1].ip4)
888         arp_pg1.add_vpp_config()
889         arp_pg2 = VppNeighbor(self,
890                               self.pg2.sw_if_index,
891                               self.pg2.remote_mac,
892                               self.pg1.remote_hosts[1].ip4)
893         arp_pg2.add_vpp_config()
894
895         #
896         # IP packet destined for pg1 remote host arrives on pg1 again.
897         #
898         p = (Ether(dst=self.pg0.local_mac,
899                    src=self.pg0.remote_mac) /
900              IP(src=self.pg0.remote_ip4,
901                 dst=self.pg1.remote_hosts[1].ip4) /
902              UDP(sport=1234, dport=1234) /
903              Raw())
904
905         self.pg0.add_stream(p)
906         self.pg_enable_capture(self.pg_interfaces)
907         self.pg_start()
908
909         rx1 = self.pg1.get_capture(1)
910
911         self.verify_ip(rx1[0],
912                        self.pg1.local_mac,
913                        self.pg1.remote_hosts[1].mac,
914                        self.pg0.remote_ip4,
915                        self.pg1.remote_hosts[1].ip4)
916
917         #
918         # remove the duplicate on pg1
919         # packet stream shoud generate ARPs out of pg1
920         #
921         arp_pg1.remove_vpp_config()
922
923         self.pg0.add_stream(p)
924         self.pg_enable_capture(self.pg_interfaces)
925         self.pg_start()
926
927         rx1 = self.pg1.get_capture(1)
928
929         self.verify_arp_req(rx1[0],
930                             self.pg1.local_mac,
931                             self.pg1.local_ip4,
932                             self.pg1.remote_hosts[1].ip4)
933
934         #
935         # Add it back
936         #
937         arp_pg1.add_vpp_config()
938
939         self.pg0.add_stream(p)
940         self.pg_enable_capture(self.pg_interfaces)
941         self.pg_start()
942
943         rx1 = self.pg1.get_capture(1)
944
945         self.verify_ip(rx1[0],
946                        self.pg1.local_mac,
947                        self.pg1.remote_hosts[1].mac,
948                        self.pg0.remote_ip4,
949                        self.pg1.remote_hosts[1].ip4)
950
951
952 if __name__ == '__main__':
953     unittest.main(testRunner=VppTestRunner)