VPP-1110 BVI reply ARP that doesn't request BVI loacl IP.
[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     VppIpTable
10
11 from scapy.packet import Raw
12 from scapy.layers.l2 import Ether, ARP, Dot1Q
13 from scapy.layers.inet import IP, UDP
14 from scapy.contrib.mpls import MPLS
15
16 # not exported by scapy, so redefined here
17 arp_opts = {"who-has": 1, "is-at": 2}
18
19
20 class ARPTestCase(VppTestCase):
21     """ ARP Test Case """
22
23     def setUp(self):
24         super(ARPTestCase, self).setUp()
25
26         # create 3 pg interfaces
27         self.create_pg_interfaces(range(4))
28
29         # pg0 configured with ip4 and 6 addresses used for input
30         # pg1 configured with ip4 and 6 addresses used for output
31         # pg2 is unnumbered to pg0
32         for i in self.pg_interfaces:
33             i.admin_up()
34
35         self.pg0.config_ip4()
36         self.pg0.config_ip6()
37         self.pg0.resolve_arp()
38
39         self.pg1.config_ip4()
40         self.pg1.config_ip6()
41
42         # pg3 in a different VRF
43         self.tbl = VppIpTable(self, 1)
44         self.tbl.add_vpp_config()
45
46         self.pg3.set_table_ip4(1)
47         self.pg3.config_ip4()
48
49     def tearDown(self):
50         self.pg0.unconfig_ip4()
51         self.pg0.unconfig_ip6()
52
53         self.pg1.unconfig_ip4()
54         self.pg1.unconfig_ip6()
55
56         self.pg3.unconfig_ip4()
57         self.pg3.set_table_ip4(0)
58
59         for i in self.pg_interfaces:
60             i.admin_down()
61
62         super(ARPTestCase, self).tearDown()
63
64     def verify_arp_req(self, rx, smac, sip, dip):
65         ether = rx[Ether]
66         self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
67         self.assertEqual(ether.src, smac)
68
69         arp = rx[ARP]
70         self.assertEqual(arp.hwtype, 1)
71         self.assertEqual(arp.ptype, 0x800)
72         self.assertEqual(arp.hwlen, 6)
73         self.assertEqual(arp.plen, 4)
74         self.assertEqual(arp.op, arp_opts["who-has"])
75         self.assertEqual(arp.hwsrc, smac)
76         self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
77         self.assertEqual(arp.psrc, sip)
78         self.assertEqual(arp.pdst, dip)
79
80     def verify_arp_resp(self, rx, smac, dmac, sip, dip):
81         ether = rx[Ether]
82         self.assertEqual(ether.dst, dmac)
83         self.assertEqual(ether.src, smac)
84
85         arp = rx[ARP]
86         self.assertEqual(arp.hwtype, 1)
87         self.assertEqual(arp.ptype, 0x800)
88         self.assertEqual(arp.hwlen, 6)
89         self.assertEqual(arp.plen, 4)
90         self.assertEqual(arp.op, arp_opts["is-at"])
91         self.assertEqual(arp.hwsrc, smac)
92         self.assertEqual(arp.hwdst, dmac)
93         self.assertEqual(arp.psrc, sip)
94         self.assertEqual(arp.pdst, dip)
95
96     def verify_arp_vrrp_resp(self, rx, smac, dmac, sip, dip):
97         ether = rx[Ether]
98         self.assertEqual(ether.dst, dmac)
99         self.assertEqual(ether.src, smac)
100
101         arp = rx[ARP]
102         self.assertEqual(arp.hwtype, 1)
103         self.assertEqual(arp.ptype, 0x800)
104         self.assertEqual(arp.hwlen, 6)
105         self.assertEqual(arp.plen, 4)
106         self.assertEqual(arp.op, arp_opts["is-at"])
107         self.assertNotEqual(arp.hwsrc, smac)
108         self.assertTrue("00:00:5e:00:01" in arp.hwsrc or
109                         "00:00:5E:00:01" in arp.hwsrc)
110         self.assertEqual(arp.hwdst, dmac)
111         self.assertEqual(arp.psrc, sip)
112         self.assertEqual(arp.pdst, dip)
113
114     def verify_ip(self, rx, smac, dmac, sip, dip):
115         ether = rx[Ether]
116         self.assertEqual(ether.dst, dmac)
117         self.assertEqual(ether.src, smac)
118
119         ip = rx[IP]
120         self.assertEqual(ip.src, sip)
121         self.assertEqual(ip.dst, dip)
122
123     def verify_ip_o_mpls(self, rx, smac, dmac, label, sip, dip):
124         ether = rx[Ether]
125         self.assertEqual(ether.dst, dmac)
126         self.assertEqual(ether.src, smac)
127
128         mpls = rx[MPLS]
129         self.assertTrue(mpls.label, label)
130
131         ip = rx[IP]
132         self.assertEqual(ip.src, sip)
133         self.assertEqual(ip.dst, dip)
134
135     def send_and_assert_no_replies(self, intf, pkts, remark):
136         intf.add_stream(pkts)
137         self.pg_enable_capture(self.pg_interfaces)
138         self.pg_start()
139         timeout = 1
140         for i in self.pg_interfaces:
141             i.get_capture(0, timeout=timeout)
142             i.assert_nothing_captured(remark=remark)
143             timeout = 0.1
144
145     def test_arp(self):
146         """ ARP """
147
148         #
149         # Generate some hosts on the LAN
150         #
151         self.pg1.generate_remote_hosts(11)
152
153         #
154         # Send IP traffic to one of these unresolved hosts.
155         #  expect the generation of an ARP request
156         #
157         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
158              IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[1].ip4) /
159              UDP(sport=1234, dport=1234) /
160              Raw())
161
162         self.pg0.add_stream(p)
163         self.pg_enable_capture(self.pg_interfaces)
164         self.pg_start()
165
166         rx = self.pg1.get_capture(1)
167
168         self.verify_arp_req(rx[0],
169                             self.pg1.local_mac,
170                             self.pg1.local_ip4,
171                             self.pg1._remote_hosts[1].ip4)
172
173         #
174         # And a dynamic ARP entry for host 1
175         #
176         dyn_arp = VppNeighbor(self,
177                               self.pg1.sw_if_index,
178                               self.pg1.remote_hosts[1].mac,
179                               self.pg1.remote_hosts[1].ip4)
180         dyn_arp.add_vpp_config()
181
182         #
183         # now we expect IP traffic forwarded
184         #
185         dyn_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
186                  IP(src=self.pg0.remote_ip4,
187                     dst=self.pg1._remote_hosts[1].ip4) /
188                  UDP(sport=1234, dport=1234) /
189                  Raw())
190
191         self.pg0.add_stream(dyn_p)
192         self.pg_enable_capture(self.pg_interfaces)
193         self.pg_start()
194
195         rx = self.pg1.get_capture(1)
196
197         self.verify_ip(rx[0],
198                        self.pg1.local_mac,
199                        self.pg1.remote_hosts[1].mac,
200                        self.pg0.remote_ip4,
201                        self.pg1._remote_hosts[1].ip4)
202
203         #
204         # And a Static ARP entry for host 2
205         #
206         static_arp = VppNeighbor(self,
207                                  self.pg1.sw_if_index,
208                                  self.pg1.remote_hosts[2].mac,
209                                  self.pg1.remote_hosts[2].ip4,
210                                  is_static=1)
211         static_arp.add_vpp_config()
212
213         static_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
214                     IP(src=self.pg0.remote_ip4,
215                        dst=self.pg1._remote_hosts[2].ip4) /
216                     UDP(sport=1234, dport=1234) /
217                     Raw())
218
219         self.pg0.add_stream(static_p)
220         self.pg_enable_capture(self.pg_interfaces)
221         self.pg_start()
222
223         rx = self.pg1.get_capture(1)
224
225         self.verify_ip(rx[0],
226                        self.pg1.local_mac,
227                        self.pg1.remote_hosts[2].mac,
228                        self.pg0.remote_ip4,
229                        self.pg1._remote_hosts[2].ip4)
230
231         #
232         # flap the link. dynamic ARPs get flush, statics don't
233         #
234         self.pg1.admin_down()
235         self.pg1.admin_up()
236
237         self.pg0.add_stream(static_p)
238         self.pg_enable_capture(self.pg_interfaces)
239         self.pg_start()
240         rx = self.pg1.get_capture(1)
241
242         self.verify_ip(rx[0],
243                        self.pg1.local_mac,
244                        self.pg1.remote_hosts[2].mac,
245                        self.pg0.remote_ip4,
246                        self.pg1._remote_hosts[2].ip4)
247
248         self.pg0.add_stream(dyn_p)
249         self.pg_enable_capture(self.pg_interfaces)
250         self.pg_start()
251
252         rx = self.pg1.get_capture(1)
253         self.verify_arp_req(rx[0],
254                             self.pg1.local_mac,
255                             self.pg1.local_ip4,
256                             self.pg1._remote_hosts[1].ip4)
257
258         #
259         # Send an ARP request from one of the so-far unlearned remote hosts
260         #
261         p = (Ether(dst="ff:ff:ff:ff:ff:ff",
262                    src=self.pg1._remote_hosts[3].mac) /
263              ARP(op="who-has",
264                  hwsrc=self.pg1._remote_hosts[3].mac,
265                  pdst=self.pg1.local_ip4,
266                  psrc=self.pg1._remote_hosts[3].ip4))
267
268         self.pg1.add_stream(p)
269         self.pg_enable_capture(self.pg_interfaces)
270         self.pg_start()
271
272         rx = self.pg1.get_capture(1)
273         self.verify_arp_resp(rx[0],
274                              self.pg1.local_mac,
275                              self.pg1._remote_hosts[3].mac,
276                              self.pg1.local_ip4,
277                              self.pg1._remote_hosts[3].ip4)
278
279         #
280         # VPP should have learned the mapping for the remote host
281         #
282         self.assertTrue(find_nbr(self,
283                                  self.pg1.sw_if_index,
284                                  self.pg1._remote_hosts[3].ip4))
285         #
286         # Fire in an ARP request before the interface becomes IP enabled
287         #
288         self.pg2.generate_remote_hosts(4)
289
290         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
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         pt = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
296               Dot1Q(vlan=0) /
297               ARP(op="who-has",
298                   hwsrc=self.pg2.remote_mac,
299                   pdst=self.pg1.local_ip4,
300                   psrc=self.pg2.remote_hosts[3].ip4))
301         self.send_and_assert_no_replies(self.pg2, p,
302                                         "interface not IP enabled")
303
304         #
305         # Make pg2 un-numbered to pg1
306         #
307         self.pg2.set_unnumbered(self.pg1.sw_if_index)
308
309         #
310         # We should respond to ARP requests for the unnumbered to address
311         # once an attached route to the source is known
312         #
313         self.send_and_assert_no_replies(
314             self.pg2, p,
315             "ARP req for unnumbered address - no source")
316
317         attached_host = VppIpRoute(self, self.pg2.remote_hosts[3].ip4, 32,
318                                    [VppRoutePath("0.0.0.0",
319                                                  self.pg2.sw_if_index)])
320         attached_host.add_vpp_config()
321
322         self.pg2.add_stream(p)
323         self.pg_enable_capture(self.pg_interfaces)
324         self.pg_start()
325
326         rx = self.pg2.get_capture(1)
327         self.verify_arp_resp(rx[0],
328                              self.pg2.local_mac,
329                              self.pg2.remote_mac,
330                              self.pg1.local_ip4,
331                              self.pg2.remote_hosts[3].ip4)
332
333         self.pg2.add_stream(pt)
334         self.pg_enable_capture(self.pg_interfaces)
335         self.pg_start()
336
337         rx = self.pg2.get_capture(1)
338         self.verify_arp_resp(rx[0],
339                              self.pg2.local_mac,
340                              self.pg2.remote_mac,
341                              self.pg1.local_ip4,
342                              self.pg2.remote_hosts[3].ip4)
343
344         #
345         # A neighbor entry that has no associated FIB-entry
346         #
347         arp_no_fib = VppNeighbor(self,
348                                  self.pg1.sw_if_index,
349                                  self.pg1.remote_hosts[4].mac,
350                                  self.pg1.remote_hosts[4].ip4,
351                                  is_no_fib_entry=1)
352         arp_no_fib.add_vpp_config()
353
354         #
355         # check we have the neighbor, but no route
356         #
357         self.assertTrue(find_nbr(self,
358                                  self.pg1.sw_if_index,
359                                  self.pg1._remote_hosts[4].ip4))
360         self.assertFalse(find_route(self,
361                                     self.pg1._remote_hosts[4].ip4,
362                                     32))
363         #
364         # pg2 is unnumbered to pg1, so we can form adjacencies out of pg2
365         # from within pg1's subnet
366         #
367         arp_unnum = VppNeighbor(self,
368                                 self.pg2.sw_if_index,
369                                 self.pg1.remote_hosts[5].mac,
370                                 self.pg1.remote_hosts[5].ip4)
371         arp_unnum.add_vpp_config()
372
373         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
374              IP(src=self.pg0.remote_ip4,
375                 dst=self.pg1._remote_hosts[5].ip4) /
376              UDP(sport=1234, dport=1234) /
377              Raw())
378
379         self.pg0.add_stream(p)
380         self.pg_enable_capture(self.pg_interfaces)
381         self.pg_start()
382
383         rx = self.pg2.get_capture(1)
384
385         self.verify_ip(rx[0],
386                        self.pg2.local_mac,
387                        self.pg1.remote_hosts[5].mac,
388                        self.pg0.remote_ip4,
389                        self.pg1._remote_hosts[5].ip4)
390
391         #
392         # ARP requests from hosts in pg1's subnet sent on pg2 are replied to
393         # with the unnumbered interface's address as the source
394         #
395         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
396              ARP(op="who-has",
397                  hwsrc=self.pg2.remote_mac,
398                  pdst=self.pg1.local_ip4,
399                  psrc=self.pg1.remote_hosts[6].ip4))
400
401         self.pg2.add_stream(p)
402         self.pg_enable_capture(self.pg_interfaces)
403         self.pg_start()
404
405         rx = self.pg2.get_capture(1)
406         self.verify_arp_resp(rx[0],
407                              self.pg2.local_mac,
408                              self.pg2.remote_mac,
409                              self.pg1.local_ip4,
410                              self.pg1.remote_hosts[6].ip4)
411
412         #
413         # An attached host route out of pg2 for an undiscovered hosts generates
414         # an ARP request with the unnumbered address as the source
415         #
416         att_unnum = VppIpRoute(self, self.pg1.remote_hosts[7].ip4, 32,
417                                [VppRoutePath("0.0.0.0",
418                                              self.pg2.sw_if_index)])
419         att_unnum.add_vpp_config()
420
421         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
422              IP(src=self.pg0.remote_ip4,
423                 dst=self.pg1._remote_hosts[7].ip4) /
424              UDP(sport=1234, dport=1234) /
425              Raw())
426
427         self.pg0.add_stream(p)
428         self.pg_enable_capture(self.pg_interfaces)
429         self.pg_start()
430
431         rx = self.pg2.get_capture(1)
432
433         self.verify_arp_req(rx[0],
434                             self.pg2.local_mac,
435                             self.pg1.local_ip4,
436                             self.pg1._remote_hosts[7].ip4)
437
438         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
439              ARP(op="who-has",
440                  hwsrc=self.pg2.remote_mac,
441                  pdst=self.pg1.local_ip4,
442                  psrc=self.pg1.remote_hosts[7].ip4))
443
444         self.pg2.add_stream(p)
445         self.pg_enable_capture(self.pg_interfaces)
446         self.pg_start()
447
448         rx = self.pg2.get_capture(1)
449         self.verify_arp_resp(rx[0],
450                              self.pg2.local_mac,
451                              self.pg2.remote_mac,
452                              self.pg1.local_ip4,
453                              self.pg1.remote_hosts[7].ip4)
454
455         #
456         # An attached host route as yet unresolved out of pg2 for an
457         # undiscovered host, an ARP requests begets a response.
458         #
459         att_unnum1 = VppIpRoute(self, self.pg1.remote_hosts[8].ip4, 32,
460                                 [VppRoutePath("0.0.0.0",
461                                               self.pg2.sw_if_index)])
462         att_unnum1.add_vpp_config()
463
464         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
465              ARP(op="who-has",
466                  hwsrc=self.pg2.remote_mac,
467                  pdst=self.pg1.local_ip4,
468                  psrc=self.pg1.remote_hosts[8].ip4))
469
470         self.pg2.add_stream(p)
471         self.pg_enable_capture(self.pg_interfaces)
472         self.pg_start()
473
474         rx = self.pg2.get_capture(1)
475         self.verify_arp_resp(rx[0],
476                              self.pg2.local_mac,
477                              self.pg2.remote_mac,
478                              self.pg1.local_ip4,
479                              self.pg1.remote_hosts[8].ip4)
480
481         #
482         # Send an ARP request from one of the so-far unlearned remote hosts
483         # with a VLAN0 tag
484         #
485         p = (Ether(dst="ff:ff:ff:ff:ff:ff",
486                    src=self.pg1._remote_hosts[9].mac) /
487              Dot1Q(vlan=0) /
488              ARP(op="who-has",
489                  hwsrc=self.pg1._remote_hosts[9].mac,
490                  pdst=self.pg1.local_ip4,
491                  psrc=self.pg1._remote_hosts[9].ip4))
492
493         self.pg1.add_stream(p)
494         self.pg_enable_capture(self.pg_interfaces)
495         self.pg_start()
496
497         rx = self.pg1.get_capture(1)
498         self.verify_arp_resp(rx[0],
499                              self.pg1.local_mac,
500                              self.pg1._remote_hosts[9].mac,
501                              self.pg1.local_ip4,
502                              self.pg1._remote_hosts[9].ip4)
503
504         #
505         # Add a hierachy of routes for a host in the sub-net.
506         # Should still get an ARP resp since the cover is attached
507         #
508         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_mac) /
509              ARP(op="who-has",
510                  hwsrc=self.pg1.remote_mac,
511                  pdst=self.pg1.local_ip4,
512                  psrc=self.pg1.remote_hosts[10].ip4))
513
514         r1 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 30,
515                         [VppRoutePath(self.pg1.remote_hosts[10].ip4,
516                                       self.pg1.sw_if_index)])
517         r1.add_vpp_config()
518
519         self.pg1.add_stream(p)
520         self.pg_enable_capture(self.pg_interfaces)
521         self.pg_start()
522         rx = self.pg1.get_capture(1)
523         self.verify_arp_resp(rx[0],
524                              self.pg1.local_mac,
525                              self.pg1.remote_mac,
526                              self.pg1.local_ip4,
527                              self.pg1.remote_hosts[10].ip4)
528
529         r2 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 32,
530                         [VppRoutePath(self.pg1.remote_hosts[10].ip4,
531                                       self.pg1.sw_if_index)])
532         r2.add_vpp_config()
533
534         self.pg1.add_stream(p)
535         self.pg_enable_capture(self.pg_interfaces)
536         self.pg_start()
537         rx = self.pg1.get_capture(1)
538         self.verify_arp_resp(rx[0],
539                              self.pg1.local_mac,
540                              self.pg1.remote_mac,
541                              self.pg1.local_ip4,
542                              self.pg1.remote_hosts[10].ip4)
543
544         #
545         # add an ARP entry that's not on the sub-net and so whose
546         # adj-fib fails the refinement check. then send an ARP request
547         # from that source
548         #
549         a1 = VppNeighbor(self,
550                          self.pg0.sw_if_index,
551                          self.pg0.remote_mac,
552                          "100.100.100.50")
553         a1.add_vpp_config()
554
555         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
556              ARP(op="who-has",
557                  hwsrc=self.pg0.remote_mac,
558                  psrc="100.100.100.50",
559                  pdst=self.pg0.remote_ip4))
560         self.send_and_assert_no_replies(self.pg0, p,
561                                         "ARP req for from failed adj-fib")
562
563         #
564         # ERROR Cases
565         #  1 - don't respond to ARP request for address not within the
566         #      interface's sub-net
567         #  1b - nor within the unnumbered subnet
568         #  1c - nor within the subnet of a different interface
569         #
570         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
571              ARP(op="who-has",
572                  hwsrc=self.pg0.remote_mac,
573                  pdst="10.10.10.3",
574                  psrc=self.pg0.remote_ip4))
575         self.send_and_assert_no_replies(self.pg0, p,
576                                         "ARP req for non-local destination")
577         self.assertFalse(find_nbr(self,
578                                   self.pg0.sw_if_index,
579                                   "10.10.10.3"))
580
581         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
582              ARP(op="who-has",
583                  hwsrc=self.pg2.remote_mac,
584                  pdst="10.10.10.3",
585                  psrc=self.pg1.remote_hosts[7].ip4))
586         self.send_and_assert_no_replies(
587             self.pg0, p,
588             "ARP req for non-local destination - unnum")
589
590         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
591              ARP(op="who-has",
592                  hwsrc=self.pg0.remote_mac,
593                  pdst=self.pg1.local_ip4,
594                  psrc=self.pg1.remote_ip4))
595         self.send_and_assert_no_replies(self.pg0, p,
596                                         "ARP req diff sub-net")
597         self.assertFalse(find_nbr(self,
598                                   self.pg0.sw_if_index,
599                                   self.pg1.remote_ip4))
600
601         #
602         #  2 - don't respond to ARP request from an address not within the
603         #      interface's sub-net
604         #   2b - to a prxied address
605         #   2c - not within a differents interface's sub-net
606         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
607              ARP(op="who-has",
608                  hwsrc=self.pg0.remote_mac,
609                  psrc="10.10.10.3",
610                  pdst=self.pg0.local_ip4))
611         self.send_and_assert_no_replies(self.pg0, p,
612                                         "ARP req for non-local source")
613         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
614              ARP(op="who-has",
615                  hwsrc=self.pg2.remote_mac,
616                  psrc="10.10.10.3",
617                  pdst=self.pg0.local_ip4))
618         self.send_and_assert_no_replies(
619             self.pg0, p,
620             "ARP req for non-local source - unnum")
621         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
622              ARP(op="who-has",
623                  hwsrc=self.pg0.remote_mac,
624                  psrc=self.pg1.remote_ip4,
625                  pdst=self.pg0.local_ip4))
626         self.send_and_assert_no_replies(self.pg0, p,
627                                         "ARP req for non-local source 2c")
628
629         #
630         #  3 - don't respond to ARP request from an address that belongs to
631         #      the router
632         #
633         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
634              ARP(op="who-has",
635                  hwsrc=self.pg0.remote_mac,
636                  psrc=self.pg0.local_ip4,
637                  pdst=self.pg0.local_ip4))
638         self.send_and_assert_no_replies(self.pg0, p,
639                                         "ARP req for non-local source")
640
641         #
642         #  4 - don't respond to ARP requests that has mac source different
643         #      from ARP request HW source
644         #
645         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
646              ARP(op="who-has",
647                  hwsrc="00:00:00:DE:AD:BE",
648                  psrc=self.pg0.remote_ip4,
649                  pdst=self.pg0.local_ip4))
650         self.send_and_assert_no_replies(self.pg0, p,
651                                         "ARP req for non-local source")
652
653         #
654         #  5 - don't respond to ARP requests for address within the
655         #      interface's sub-net but not the interface's address
656         #
657         self.pg0.generate_remote_hosts(2)
658         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
659              ARP(op="who-has",
660                  hwsrc=self.pg0.remote_mac,
661                  psrc=self.pg0.remote_hosts[0].ip4,
662                  pdst=self.pg0.remote_hosts[1].ip4))
663         self.send_and_assert_no_replies(self.pg0, p,
664                                         "ARP req for non-local destination")
665
666         #
667         # cleanup
668         #
669         dyn_arp.remove_vpp_config()
670         static_arp.remove_vpp_config()
671         self.pg2.unset_unnumbered(self.pg1.sw_if_index)
672
673         # need this to flush the adj-fibs
674         self.pg2.unset_unnumbered(self.pg1.sw_if_index)
675         self.pg2.admin_down()
676         self.pg1.admin_down()
677
678     def test_proxy_mirror_arp(self):
679         """ Interface Mirror Proxy ARP """
680
681         #
682         # When VPP has an interface whose address is also applied to a TAP
683         # interface on the host, then VPP's TAP interface will be unnumbered
684         # to the 'real' interface and do proxy ARP from the host.
685         # the curious aspect of this setup is that ARP requests from the host
686         # will come from the VPP's own address.
687         #
688         self.pg0.generate_remote_hosts(2)
689
690         arp_req_from_me = (Ether(src=self.pg2.remote_mac,
691                                  dst="ff:ff:ff:ff:ff:ff") /
692                            ARP(op="who-has",
693                                hwsrc=self.pg2.remote_mac,
694                                pdst=self.pg0.remote_hosts[1].ip4,
695                                psrc=self.pg0.local_ip4))
696
697         #
698         # Configure Proxy ARP for the subnet on PG0addresses on pg0
699         #
700         self.vapi.proxy_arp_add_del(self.pg0._local_ip4n_subnet,
701                                     self.pg0._local_ip4n_bcast)
702
703         # Make pg2 un-numbered to pg0
704         #
705         self.pg2.set_unnumbered(self.pg0.sw_if_index)
706
707         #
708         # Enable pg2 for proxy ARP
709         #
710         self.pg2.set_proxy_arp()
711
712         #
713         # Send the ARP request with an originating address that
714         # is VPP's own address
715         #
716         self.pg2.add_stream(arp_req_from_me)
717         self.pg_enable_capture(self.pg_interfaces)
718         self.pg_start()
719
720         rx = self.pg2.get_capture(1)
721         self.verify_arp_resp(rx[0],
722                              self.pg2.local_mac,
723                              self.pg2.remote_mac,
724                              self.pg0.remote_hosts[1].ip4,
725                              self.pg0.local_ip4)
726
727         #
728         # validate we have not learned an ARP entry as a result of this
729         #
730         self.assertFalse(find_nbr(self,
731                                   self.pg2.sw_if_index,
732                                   self.pg0.local_ip4))
733
734         #
735         # cleanup
736         #
737         self.pg2.set_proxy_arp(0)
738         self.vapi.proxy_arp_add_del(self.pg0._local_ip4n_subnet,
739                                     self.pg0._local_ip4n_bcast,
740                                     is_add=0)
741
742     def test_proxy_arp(self):
743         """ Proxy ARP """
744
745         self.pg1.generate_remote_hosts(2)
746
747         #
748         # Proxy ARP rewquest packets for each interface
749         #
750         arp_req_pg0 = (Ether(src=self.pg0.remote_mac,
751                              dst="ff:ff:ff:ff:ff:ff") /
752                        ARP(op="who-has",
753                            hwsrc=self.pg0.remote_mac,
754                            pdst="10.10.10.3",
755                            psrc=self.pg0.remote_ip4))
756         arp_req_pg0_tagged = (Ether(src=self.pg0.remote_mac,
757                                     dst="ff:ff:ff:ff:ff:ff") /
758                               Dot1Q(vlan=0) /
759                               ARP(op="who-has",
760                                   hwsrc=self.pg0.remote_mac,
761                                   pdst="10.10.10.3",
762                                   psrc=self.pg0.remote_ip4))
763         arp_req_pg1 = (Ether(src=self.pg1.remote_mac,
764                              dst="ff:ff:ff:ff:ff:ff") /
765                        ARP(op="who-has",
766                            hwsrc=self.pg1.remote_mac,
767                            pdst="10.10.10.3",
768                            psrc=self.pg1.remote_ip4))
769         arp_req_pg2 = (Ether(src=self.pg2.remote_mac,
770                              dst="ff:ff:ff:ff:ff:ff") /
771                        ARP(op="who-has",
772                            hwsrc=self.pg2.remote_mac,
773                            pdst="10.10.10.3",
774                            psrc=self.pg1.remote_hosts[1].ip4))
775         arp_req_pg3 = (Ether(src=self.pg3.remote_mac,
776                              dst="ff:ff:ff:ff:ff:ff") /
777                        ARP(op="who-has",
778                            hwsrc=self.pg3.remote_mac,
779                            pdst="10.10.10.3",
780                            psrc=self.pg3.remote_ip4))
781
782         #
783         # Configure Proxy ARP for 10.10.10.0 -> 10.10.10.124
784         #
785         self.vapi.proxy_arp_add_del(inet_pton(AF_INET, "10.10.10.2"),
786                                     inet_pton(AF_INET, "10.10.10.124"))
787
788         #
789         # No responses are sent when the interfaces are not enabled for proxy
790         # ARP
791         #
792         self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
793                                         "ARP req from unconfigured interface")
794         self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
795                                         "ARP req from unconfigured interface")
796
797         #
798         # Make pg2 un-numbered to pg1
799         #  still won't reply.
800         #
801         self.pg2.set_unnumbered(self.pg1.sw_if_index)
802
803         self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
804                                         "ARP req from unnumbered interface")
805
806         #
807         # Enable each interface to reply to proxy ARPs
808         #
809         for i in self.pg_interfaces:
810             i.set_proxy_arp()
811
812         #
813         # Now each of the interfaces should reply to a request to a proxied
814         # address
815         #
816         self.pg0.add_stream(arp_req_pg0)
817         self.pg_enable_capture(self.pg_interfaces)
818         self.pg_start()
819
820         rx = self.pg0.get_capture(1)
821         self.verify_arp_resp(rx[0],
822                              self.pg0.local_mac,
823                              self.pg0.remote_mac,
824                              "10.10.10.3",
825                              self.pg0.remote_ip4)
826
827         self.pg0.add_stream(arp_req_pg0_tagged)
828         self.pg_enable_capture(self.pg_interfaces)
829         self.pg_start()
830
831         rx = self.pg0.get_capture(1)
832         self.verify_arp_resp(rx[0],
833                              self.pg0.local_mac,
834                              self.pg0.remote_mac,
835                              "10.10.10.3",
836                              self.pg0.remote_ip4)
837
838         self.pg1.add_stream(arp_req_pg1)
839         self.pg_enable_capture(self.pg_interfaces)
840         self.pg_start()
841
842         rx = self.pg1.get_capture(1)
843         self.verify_arp_resp(rx[0],
844                              self.pg1.local_mac,
845                              self.pg1.remote_mac,
846                              "10.10.10.3",
847                              self.pg1.remote_ip4)
848
849         self.pg2.add_stream(arp_req_pg2)
850         self.pg_enable_capture(self.pg_interfaces)
851         self.pg_start()
852
853         rx = self.pg2.get_capture(1)
854         self.verify_arp_resp(rx[0],
855                              self.pg2.local_mac,
856                              self.pg2.remote_mac,
857                              "10.10.10.3",
858                              self.pg1.remote_hosts[1].ip4)
859
860         #
861         # A request for an address out of the configured range
862         #
863         arp_req_pg1_hi = (Ether(src=self.pg1.remote_mac,
864                                 dst="ff:ff:ff:ff:ff:ff") /
865                           ARP(op="who-has",
866                               hwsrc=self.pg1.remote_mac,
867                               pdst="10.10.10.125",
868                               psrc=self.pg1.remote_ip4))
869         self.send_and_assert_no_replies(self.pg1, arp_req_pg1_hi,
870                                         "ARP req out of range HI")
871         arp_req_pg1_low = (Ether(src=self.pg1.remote_mac,
872                                  dst="ff:ff:ff:ff:ff:ff") /
873                            ARP(op="who-has",
874                                hwsrc=self.pg1.remote_mac,
875                                pdst="10.10.10.1",
876                                psrc=self.pg1.remote_ip4))
877         self.send_and_assert_no_replies(self.pg1, arp_req_pg1_low,
878                                         "ARP req out of range Low")
879
880         #
881         # Request for an address in the proxy range but from an interface
882         # in a different VRF
883         #
884         self.send_and_assert_no_replies(self.pg3, arp_req_pg3,
885                                         "ARP req from different VRF")
886
887         #
888         # Disable Each interface for proxy ARP
889         #  - expect none to respond
890         #
891         for i in self.pg_interfaces:
892             i.set_proxy_arp(0)
893
894         self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
895                                         "ARP req from disable")
896         self.send_and_assert_no_replies(self.pg1, arp_req_pg1,
897                                         "ARP req from disable")
898         self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
899                                         "ARP req from disable")
900
901         #
902         # clean up on interface 2
903         #
904         self.pg2.unset_unnumbered(self.pg1.sw_if_index)
905
906     def test_mpls(self):
907         """ MPLS """
908
909         #
910         # Interface 2 does not yet have ip4 config
911         #
912         self.pg2.config_ip4()
913         self.pg2.generate_remote_hosts(2)
914
915         #
916         # Add a reoute with out going label via an ARP unresolved next-hop
917         #
918         ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
919                                  [VppRoutePath(self.pg2.remote_hosts[1].ip4,
920                                                self.pg2.sw_if_index,
921                                                labels=[55])])
922         ip_10_0_0_1.add_vpp_config()
923
924         #
925         # packets should generate an ARP request
926         #
927         p = (Ether(src=self.pg0.remote_mac,
928                    dst=self.pg0.local_mac) /
929              IP(src=self.pg0.remote_ip4, dst="10.0.0.1") /
930              UDP(sport=1234, dport=1234) /
931              Raw('\xa5' * 100))
932
933         self.pg0.add_stream(p)
934         self.pg_enable_capture(self.pg_interfaces)
935         self.pg_start()
936
937         rx = self.pg2.get_capture(1)
938         self.verify_arp_req(rx[0],
939                             self.pg2.local_mac,
940                             self.pg2.local_ip4,
941                             self.pg2._remote_hosts[1].ip4)
942
943         #
944         # now resolve the neighbours
945         #
946         self.pg2.configure_ipv4_neighbors()
947
948         #
949         # Now packet should be properly MPLS encapped.
950         #  This verifies that MPLS link-type adjacencies are completed
951         #  when the ARP entry resolves
952         #
953         self.pg0.add_stream(p)
954         self.pg_enable_capture(self.pg_interfaces)
955         self.pg_start()
956
957         rx = self.pg2.get_capture(1)
958         self.verify_ip_o_mpls(rx[0],
959                               self.pg2.local_mac,
960                               self.pg2.remote_hosts[1].mac,
961                               55,
962                               self.pg0.remote_ip4,
963                               "10.0.0.1")
964         self.pg2.unconfig_ip4()
965
966     def test_arp_vrrp(self):
967         """ ARP reply with VRRP virtual src hw addr """
968
969         #
970         # IP packet destined for pg1 remote host arrives on pg0 resulting
971         # in an ARP request for the address of the remote host on pg1
972         #
973         p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
974               IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
975               UDP(sport=1234, dport=1234) /
976               Raw())
977
978         self.pg0.add_stream(p0)
979         self.pg_enable_capture(self.pg_interfaces)
980         self.pg_start()
981
982         rx1 = self.pg1.get_capture(1)
983
984         self.verify_arp_req(rx1[0],
985                             self.pg1.local_mac,
986                             self.pg1.local_ip4,
987                             self.pg1.remote_ip4)
988
989         #
990         # ARP reply for address of pg1 remote host arrives on pg1 with
991         # the hw src addr set to a value in the VRRP IPv4 range of
992         # MAC addresses
993         #
994         p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
995               ARP(op="is-at", hwdst=self.pg1.local_mac,
996                   hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
997                   psrc=self.pg1.remote_ip4))
998
999         self.pg1.add_stream(p1)
1000         self.pg_enable_capture(self.pg_interfaces)
1001         self.pg_start()
1002
1003         #
1004         # IP packet destined for pg1 remote host arrives on pg0 again.
1005         # VPP should have an ARP entry for that address now and the packet
1006         # should be sent out pg1.
1007         #
1008         self.pg0.add_stream(p0)
1009         self.pg_enable_capture(self.pg_interfaces)
1010         self.pg_start()
1011
1012         rx1 = self.pg1.get_capture(1)
1013
1014         self.verify_ip(rx1[0],
1015                        self.pg1.local_mac,
1016                        "00:00:5e:00:01:09",
1017                        self.pg0.remote_ip4,
1018                        self.pg1.remote_ip4)
1019
1020         self.pg1.admin_down()
1021         self.pg1.admin_up()
1022
1023     def test_arp_duplicates(self):
1024         """ ARP Duplicates"""
1025
1026         #
1027         # Generate some hosts on the LAN
1028         #
1029         self.pg1.generate_remote_hosts(3)
1030
1031         #
1032         # Add host 1 on pg1 and pg2
1033         #
1034         arp_pg1 = VppNeighbor(self,
1035                               self.pg1.sw_if_index,
1036                               self.pg1.remote_hosts[1].mac,
1037                               self.pg1.remote_hosts[1].ip4)
1038         arp_pg1.add_vpp_config()
1039         arp_pg2 = VppNeighbor(self,
1040                               self.pg2.sw_if_index,
1041                               self.pg2.remote_mac,
1042                               self.pg1.remote_hosts[1].ip4)
1043         arp_pg2.add_vpp_config()
1044
1045         #
1046         # IP packet destined for pg1 remote host arrives on pg1 again.
1047         #
1048         p = (Ether(dst=self.pg0.local_mac,
1049                    src=self.pg0.remote_mac) /
1050              IP(src=self.pg0.remote_ip4,
1051                 dst=self.pg1.remote_hosts[1].ip4) /
1052              UDP(sport=1234, dport=1234) /
1053              Raw())
1054
1055         self.pg0.add_stream(p)
1056         self.pg_enable_capture(self.pg_interfaces)
1057         self.pg_start()
1058
1059         rx1 = self.pg1.get_capture(1)
1060
1061         self.verify_ip(rx1[0],
1062                        self.pg1.local_mac,
1063                        self.pg1.remote_hosts[1].mac,
1064                        self.pg0.remote_ip4,
1065                        self.pg1.remote_hosts[1].ip4)
1066
1067         #
1068         # remove the duplicate on pg1
1069         # packet stream shoud generate ARPs out of pg1
1070         #
1071         arp_pg1.remove_vpp_config()
1072
1073         self.pg0.add_stream(p)
1074         self.pg_enable_capture(self.pg_interfaces)
1075         self.pg_start()
1076
1077         rx1 = self.pg1.get_capture(1)
1078
1079         self.verify_arp_req(rx1[0],
1080                             self.pg1.local_mac,
1081                             self.pg1.local_ip4,
1082                             self.pg1.remote_hosts[1].ip4)
1083
1084         #
1085         # Add it back
1086         #
1087         arp_pg1.add_vpp_config()
1088
1089         self.pg0.add_stream(p)
1090         self.pg_enable_capture(self.pg_interfaces)
1091         self.pg_start()
1092
1093         rx1 = self.pg1.get_capture(1)
1094
1095         self.verify_ip(rx1[0],
1096                        self.pg1.local_mac,
1097                        self.pg1.remote_hosts[1].mac,
1098                        self.pg0.remote_ip4,
1099                        self.pg1.remote_hosts[1].ip4)
1100
1101     def test_arp_static(self):
1102         """ ARP Static"""
1103         self.pg2.generate_remote_hosts(3)
1104
1105         #
1106         # Add a static ARP entry
1107         #
1108         static_arp = VppNeighbor(self,
1109                                  self.pg2.sw_if_index,
1110                                  self.pg2.remote_hosts[1].mac,
1111                                  self.pg2.remote_hosts[1].ip4,
1112                                  is_static=1)
1113         static_arp.add_vpp_config()
1114
1115         #
1116         # Add the connected prefix to the interface
1117         #
1118         self.pg2.config_ip4()
1119
1120         #
1121         # We should now find the adj-fib
1122         #
1123         self.assertTrue(find_nbr(self,
1124                                  self.pg2.sw_if_index,
1125                                  self.pg2.remote_hosts[1].ip4,
1126                                  is_static=1))
1127         self.assertTrue(find_route(self,
1128                                    self.pg2.remote_hosts[1].ip4,
1129                                    32))
1130
1131         #
1132         # remove the connected
1133         #
1134         self.pg2.unconfig_ip4()
1135
1136         #
1137         # put the interface into table 1
1138         #
1139         self.pg2.set_table_ip4(1)
1140
1141         #
1142         # configure the same connected and expect to find the
1143         # adj fib in the new table
1144         #
1145         self.pg2.config_ip4()
1146         self.assertTrue(find_route(self,
1147                                    self.pg2.remote_hosts[1].ip4,
1148                                    32,
1149                                    table_id=1))
1150
1151         #
1152         # clean-up
1153         #
1154         self.pg2.unconfig_ip4()
1155         self.pg2.set_table_ip4(0)
1156
1157
1158 if __name__ == '__main__':
1159     unittest.main(testRunner=VppTestRunner)