Use IP and MAC API types for neighbors
[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, DpoProto
10 from vpp_papi import VppEnum
11
12 from scapy.packet import Raw
13 from scapy.layers.l2 import Ether, ARP, Dot1Q
14 from scapy.layers.inet import IP, UDP
15 from scapy.layers.inet6 import IPv6
16 from scapy.contrib.mpls import MPLS
17 from scapy.layers.inet6 import IPv6
18
19 # not exported by scapy, so redefined here
20 arp_opts = {"who-has": 1, "is-at": 2}
21
22
23 class ARPTestCase(VppTestCase):
24     """ ARP Test Case """
25
26     def setUp(self):
27         super(ARPTestCase, self).setUp()
28
29         # create 3 pg interfaces
30         self.create_pg_interfaces(range(4))
31
32         # pg0 configured with ip4 and 6 addresses used for input
33         # pg1 configured with ip4 and 6 addresses used for output
34         # pg2 is unnumbered to pg0
35         for i in self.pg_interfaces:
36             i.admin_up()
37
38         self.pg0.config_ip4()
39         self.pg0.config_ip6()
40         self.pg0.resolve_arp()
41
42         self.pg1.config_ip4()
43         self.pg1.config_ip6()
44
45         # pg3 in a different VRF
46         self.tbl = VppIpTable(self, 1)
47         self.tbl.add_vpp_config()
48
49         self.pg3.set_table_ip4(1)
50         self.pg3.config_ip4()
51
52     def tearDown(self):
53         self.pg0.unconfig_ip4()
54         self.pg0.unconfig_ip6()
55
56         self.pg1.unconfig_ip4()
57         self.pg1.unconfig_ip6()
58
59         self.pg3.unconfig_ip4()
60         self.pg3.set_table_ip4(0)
61
62         for i in self.pg_interfaces:
63             i.admin_down()
64
65         super(ARPTestCase, self).tearDown()
66
67     def verify_arp_req(self, rx, smac, sip, dip):
68         ether = rx[Ether]
69         self.assertEqual(ether.dst, "ff:ff:ff:ff:ff:ff")
70         self.assertEqual(ether.src, smac)
71
72         arp = rx[ARP]
73         self.assertEqual(arp.hwtype, 1)
74         self.assertEqual(arp.ptype, 0x800)
75         self.assertEqual(arp.hwlen, 6)
76         self.assertEqual(arp.plen, 4)
77         self.assertEqual(arp.op, arp_opts["who-has"])
78         self.assertEqual(arp.hwsrc, smac)
79         self.assertEqual(arp.hwdst, "00:00:00:00:00:00")
80         self.assertEqual(arp.psrc, sip)
81         self.assertEqual(arp.pdst, dip)
82
83     def verify_arp_resp(self, rx, smac, dmac, sip, dip):
84         ether = rx[Ether]
85         self.assertEqual(ether.dst, dmac)
86         self.assertEqual(ether.src, smac)
87
88         arp = rx[ARP]
89         self.assertEqual(arp.hwtype, 1)
90         self.assertEqual(arp.ptype, 0x800)
91         self.assertEqual(arp.hwlen, 6)
92         self.assertEqual(arp.plen, 4)
93         self.assertEqual(arp.op, arp_opts["is-at"])
94         self.assertEqual(arp.hwsrc, smac)
95         self.assertEqual(arp.hwdst, dmac)
96         self.assertEqual(arp.psrc, sip)
97         self.assertEqual(arp.pdst, dip)
98
99     def verify_arp_vrrp_resp(self, rx, smac, dmac, sip, dip):
100         ether = rx[Ether]
101         self.assertEqual(ether.dst, dmac)
102         self.assertEqual(ether.src, smac)
103
104         arp = rx[ARP]
105         self.assertEqual(arp.hwtype, 1)
106         self.assertEqual(arp.ptype, 0x800)
107         self.assertEqual(arp.hwlen, 6)
108         self.assertEqual(arp.plen, 4)
109         self.assertEqual(arp.op, arp_opts["is-at"])
110         self.assertNotEqual(arp.hwsrc, smac)
111         self.assertTrue("00:00:5e:00:01" in arp.hwsrc or
112                         "00:00:5E:00:01" in arp.hwsrc)
113         self.assertEqual(arp.hwdst, dmac)
114         self.assertEqual(arp.psrc, sip)
115         self.assertEqual(arp.pdst, dip)
116
117     def verify_ip(self, rx, smac, dmac, sip, dip):
118         ether = rx[Ether]
119         self.assertEqual(ether.dst, dmac)
120         self.assertEqual(ether.src, smac)
121
122         ip = rx[IP]
123         self.assertEqual(ip.src, sip)
124         self.assertEqual(ip.dst, dip)
125
126     def verify_ip_o_mpls(self, rx, smac, dmac, label, sip, dip):
127         ether = rx[Ether]
128         self.assertEqual(ether.dst, dmac)
129         self.assertEqual(ether.src, smac)
130
131         mpls = rx[MPLS]
132         self.assertTrue(mpls.label, label)
133
134         ip = rx[IP]
135         self.assertEqual(ip.src, sip)
136         self.assertEqual(ip.dst, dip)
137
138     def test_arp(self):
139         """ ARP """
140
141         #
142         # Generate some hosts on the LAN
143         #
144         self.pg1.generate_remote_hosts(11)
145
146         #
147         # Send IP traffic to one of these unresolved hosts.
148         #  expect the generation of an ARP request
149         #
150         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
151              IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[1].ip4) /
152              UDP(sport=1234, dport=1234) /
153              Raw())
154
155         self.pg0.add_stream(p)
156         self.pg_enable_capture(self.pg_interfaces)
157         self.pg_start()
158
159         rx = self.pg1.get_capture(1)
160
161         self.verify_arp_req(rx[0],
162                             self.pg1.local_mac,
163                             self.pg1.local_ip4,
164                             self.pg1._remote_hosts[1].ip4)
165
166         #
167         # And a dynamic ARP entry for host 1
168         #
169         dyn_arp = VppNeighbor(self,
170                               self.pg1.sw_if_index,
171                               self.pg1.remote_hosts[1].mac,
172                               self.pg1.remote_hosts[1].ip4)
173         dyn_arp.add_vpp_config()
174
175         #
176         # now we expect IP traffic forwarded
177         #
178         dyn_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
179                  IP(src=self.pg0.remote_ip4,
180                     dst=self.pg1._remote_hosts[1].ip4) /
181                  UDP(sport=1234, dport=1234) /
182                  Raw())
183
184         self.pg0.add_stream(dyn_p)
185         self.pg_enable_capture(self.pg_interfaces)
186         self.pg_start()
187
188         rx = self.pg1.get_capture(1)
189
190         self.verify_ip(rx[0],
191                        self.pg1.local_mac,
192                        self.pg1.remote_hosts[1].mac,
193                        self.pg0.remote_ip4,
194                        self.pg1._remote_hosts[1].ip4)
195
196         #
197         # And a Static ARP entry for host 2
198         #
199         static_arp = VppNeighbor(self,
200                                  self.pg1.sw_if_index,
201                                  self.pg1.remote_hosts[2].mac,
202                                  self.pg1.remote_hosts[2].ip4,
203                                  is_static=1)
204         static_arp.add_vpp_config()
205
206         static_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
207                     IP(src=self.pg0.remote_ip4,
208                        dst=self.pg1._remote_hosts[2].ip4) /
209                     UDP(sport=1234, dport=1234) /
210                     Raw())
211
212         self.pg0.add_stream(static_p)
213         self.pg_enable_capture(self.pg_interfaces)
214         self.pg_start()
215
216         rx = self.pg1.get_capture(1)
217
218         self.verify_ip(rx[0],
219                        self.pg1.local_mac,
220                        self.pg1.remote_hosts[2].mac,
221                        self.pg0.remote_ip4,
222                        self.pg1._remote_hosts[2].ip4)
223
224         #
225         # flap the link. dynamic ARPs get flush, statics don't
226         #
227         self.pg1.admin_down()
228         self.pg1.admin_up()
229
230         self.pg0.add_stream(static_p)
231         self.pg_enable_capture(self.pg_interfaces)
232         self.pg_start()
233         rx = self.pg1.get_capture(1)
234
235         self.verify_ip(rx[0],
236                        self.pg1.local_mac,
237                        self.pg1.remote_hosts[2].mac,
238                        self.pg0.remote_ip4,
239                        self.pg1._remote_hosts[2].ip4)
240
241         self.pg0.add_stream(dyn_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_req(rx[0],
247                             self.pg1.local_mac,
248                             self.pg1.local_ip4,
249                             self.pg1._remote_hosts[1].ip4)
250
251         #
252         # Send an ARP request from one of the so-far unlearned remote hosts
253         #
254         p = (Ether(dst="ff:ff:ff:ff:ff:ff",
255                    src=self.pg1._remote_hosts[3].mac) /
256              ARP(op="who-has",
257                  hwsrc=self.pg1._remote_hosts[3].mac,
258                  pdst=self.pg1.local_ip4,
259                  psrc=self.pg1._remote_hosts[3].ip4))
260
261         self.pg1.add_stream(p)
262         self.pg_enable_capture(self.pg_interfaces)
263         self.pg_start()
264
265         rx = self.pg1.get_capture(1)
266         self.verify_arp_resp(rx[0],
267                              self.pg1.local_mac,
268                              self.pg1._remote_hosts[3].mac,
269                              self.pg1.local_ip4,
270                              self.pg1._remote_hosts[3].ip4)
271
272         #
273         # VPP should have learned the mapping for the remote host
274         #
275         self.assertTrue(find_nbr(self,
276                                  self.pg1.sw_if_index,
277                                  self.pg1._remote_hosts[3].ip4))
278         #
279         # Fire in an ARP request before the interface becomes IP enabled
280         #
281         self.pg2.generate_remote_hosts(4)
282
283         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
284              ARP(op="who-has",
285                  hwsrc=self.pg2.remote_mac,
286                  pdst=self.pg1.local_ip4,
287                  psrc=self.pg2.remote_hosts[3].ip4))
288         pt = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
289               Dot1Q(vlan=0) /
290               ARP(op="who-has",
291                   hwsrc=self.pg2.remote_mac,
292                   pdst=self.pg1.local_ip4,
293                   psrc=self.pg2.remote_hosts[3].ip4))
294         self.send_and_assert_no_replies(self.pg2, p,
295                                         "interface not IP enabled")
296
297         #
298         # Make pg2 un-numbered to pg1
299         #
300         self.pg2.set_unnumbered(self.pg1.sw_if_index)
301
302         unnum = self.vapi.ip_unnumbered_dump()
303         self.assertEqual(unnum[0].ip_sw_if_index, self.pg1.sw_if_index)
304         self.assertEqual(unnum[0].sw_if_index, self.pg2.sw_if_index)
305
306         #
307         # We should respond to ARP requests for the unnumbered to address
308         # once an attached route to the source is known
309         #
310         self.send_and_assert_no_replies(
311             self.pg2, p,
312             "ARP req for unnumbered address - no source")
313
314         attached_host = VppIpRoute(self, self.pg2.remote_hosts[3].ip4, 32,
315                                    [VppRoutePath("0.0.0.0",
316                                                  self.pg2.sw_if_index)])
317         attached_host.add_vpp_config()
318
319         self.pg2.add_stream(p)
320         self.pg_enable_capture(self.pg_interfaces)
321         self.pg_start()
322
323         rx = self.pg2.get_capture(1)
324         self.verify_arp_resp(rx[0],
325                              self.pg2.local_mac,
326                              self.pg2.remote_mac,
327                              self.pg1.local_ip4,
328                              self.pg2.remote_hosts[3].ip4)
329
330         self.pg2.add_stream(pt)
331         self.pg_enable_capture(self.pg_interfaces)
332         self.pg_start()
333
334         rx = self.pg2.get_capture(1)
335         self.verify_arp_resp(rx[0],
336                              self.pg2.local_mac,
337                              self.pg2.remote_mac,
338                              self.pg1.local_ip4,
339                              self.pg2.remote_hosts[3].ip4)
340
341         #
342         # A neighbor entry that has no associated FIB-entry
343         #
344         arp_no_fib = VppNeighbor(self,
345                                  self.pg1.sw_if_index,
346                                  self.pg1.remote_hosts[4].mac,
347                                  self.pg1.remote_hosts[4].ip4,
348                                  is_no_fib_entry=1)
349         arp_no_fib.add_vpp_config()
350
351         #
352         # check we have the neighbor, but no route
353         #
354         self.assertTrue(find_nbr(self,
355                                  self.pg1.sw_if_index,
356                                  self.pg1._remote_hosts[4].ip4))
357         self.assertFalse(find_route(self,
358                                     self.pg1._remote_hosts[4].ip4,
359                                     32))
360         #
361         # pg2 is unnumbered to pg1, so we can form adjacencies out of pg2
362         # from within pg1's subnet
363         #
364         arp_unnum = VppNeighbor(self,
365                                 self.pg2.sw_if_index,
366                                 self.pg1.remote_hosts[5].mac,
367                                 self.pg1.remote_hosts[5].ip4)
368         arp_unnum.add_vpp_config()
369
370         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
371              IP(src=self.pg0.remote_ip4,
372                 dst=self.pg1._remote_hosts[5].ip4) /
373              UDP(sport=1234, dport=1234) /
374              Raw())
375
376         self.pg0.add_stream(p)
377         self.pg_enable_capture(self.pg_interfaces)
378         self.pg_start()
379
380         rx = self.pg2.get_capture(1)
381
382         self.verify_ip(rx[0],
383                        self.pg2.local_mac,
384                        self.pg1.remote_hosts[5].mac,
385                        self.pg0.remote_ip4,
386                        self.pg1._remote_hosts[5].ip4)
387
388         #
389         # ARP requests from hosts in pg1's subnet sent on pg2 are replied to
390         # with the unnumbered interface's address as the source
391         #
392         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
393              ARP(op="who-has",
394                  hwsrc=self.pg2.remote_mac,
395                  pdst=self.pg1.local_ip4,
396                  psrc=self.pg1.remote_hosts[6].ip4))
397
398         self.pg2.add_stream(p)
399         self.pg_enable_capture(self.pg_interfaces)
400         self.pg_start()
401
402         rx = self.pg2.get_capture(1)
403         self.verify_arp_resp(rx[0],
404                              self.pg2.local_mac,
405                              self.pg2.remote_mac,
406                              self.pg1.local_ip4,
407                              self.pg1.remote_hosts[6].ip4)
408
409         #
410         # An attached host route out of pg2 for an undiscovered hosts generates
411         # an ARP request with the unnumbered address as the source
412         #
413         att_unnum = VppIpRoute(self, self.pg1.remote_hosts[7].ip4, 32,
414                                [VppRoutePath("0.0.0.0",
415                                              self.pg2.sw_if_index)])
416         att_unnum.add_vpp_config()
417
418         p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
419              IP(src=self.pg0.remote_ip4,
420                 dst=self.pg1._remote_hosts[7].ip4) /
421              UDP(sport=1234, dport=1234) /
422              Raw())
423
424         self.pg0.add_stream(p)
425         self.pg_enable_capture(self.pg_interfaces)
426         self.pg_start()
427
428         rx = self.pg2.get_capture(1)
429
430         self.verify_arp_req(rx[0],
431                             self.pg2.local_mac,
432                             self.pg1.local_ip4,
433                             self.pg1._remote_hosts[7].ip4)
434
435         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
436              ARP(op="who-has",
437                  hwsrc=self.pg2.remote_mac,
438                  pdst=self.pg1.local_ip4,
439                  psrc=self.pg1.remote_hosts[7].ip4))
440
441         self.pg2.add_stream(p)
442         self.pg_enable_capture(self.pg_interfaces)
443         self.pg_start()
444
445         rx = self.pg2.get_capture(1)
446         self.verify_arp_resp(rx[0],
447                              self.pg2.local_mac,
448                              self.pg2.remote_mac,
449                              self.pg1.local_ip4,
450                              self.pg1.remote_hosts[7].ip4)
451
452         #
453         # An attached host route as yet unresolved out of pg2 for an
454         # undiscovered host, an ARP requests begets a response.
455         #
456         att_unnum1 = VppIpRoute(self, self.pg1.remote_hosts[8].ip4, 32,
457                                 [VppRoutePath("0.0.0.0",
458                                               self.pg2.sw_if_index)])
459         att_unnum1.add_vpp_config()
460
461         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
462              ARP(op="who-has",
463                  hwsrc=self.pg2.remote_mac,
464                  pdst=self.pg1.local_ip4,
465                  psrc=self.pg1.remote_hosts[8].ip4))
466
467         self.pg2.add_stream(p)
468         self.pg_enable_capture(self.pg_interfaces)
469         self.pg_start()
470
471         rx = self.pg2.get_capture(1)
472         self.verify_arp_resp(rx[0],
473                              self.pg2.local_mac,
474                              self.pg2.remote_mac,
475                              self.pg1.local_ip4,
476                              self.pg1.remote_hosts[8].ip4)
477
478         #
479         # Send an ARP request from one of the so-far unlearned remote hosts
480         # with a VLAN0 tag
481         #
482         p = (Ether(dst="ff:ff:ff:ff:ff:ff",
483                    src=self.pg1._remote_hosts[9].mac) /
484              Dot1Q(vlan=0) /
485              ARP(op="who-has",
486                  hwsrc=self.pg1._remote_hosts[9].mac,
487                  pdst=self.pg1.local_ip4,
488                  psrc=self.pg1._remote_hosts[9].ip4))
489
490         self.pg1.add_stream(p)
491         self.pg_enable_capture(self.pg_interfaces)
492         self.pg_start()
493
494         rx = self.pg1.get_capture(1)
495         self.verify_arp_resp(rx[0],
496                              self.pg1.local_mac,
497                              self.pg1._remote_hosts[9].mac,
498                              self.pg1.local_ip4,
499                              self.pg1._remote_hosts[9].ip4)
500
501         #
502         # Add a hierachy of routes for a host in the sub-net.
503         # Should still get an ARP resp since the cover is attached
504         #
505         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_mac) /
506              ARP(op="who-has",
507                  hwsrc=self.pg1.remote_mac,
508                  pdst=self.pg1.local_ip4,
509                  psrc=self.pg1.remote_hosts[10].ip4))
510
511         r1 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 30,
512                         [VppRoutePath(self.pg1.remote_hosts[10].ip4,
513                                       self.pg1.sw_if_index)])
514         r1.add_vpp_config()
515
516         self.pg1.add_stream(p)
517         self.pg_enable_capture(self.pg_interfaces)
518         self.pg_start()
519         rx = self.pg1.get_capture(1)
520         self.verify_arp_resp(rx[0],
521                              self.pg1.local_mac,
522                              self.pg1.remote_mac,
523                              self.pg1.local_ip4,
524                              self.pg1.remote_hosts[10].ip4)
525
526         r2 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 32,
527                         [VppRoutePath(self.pg1.remote_hosts[10].ip4,
528                                       self.pg1.sw_if_index)])
529         r2.add_vpp_config()
530
531         self.pg1.add_stream(p)
532         self.pg_enable_capture(self.pg_interfaces)
533         self.pg_start()
534         rx = self.pg1.get_capture(1)
535         self.verify_arp_resp(rx[0],
536                              self.pg1.local_mac,
537                              self.pg1.remote_mac,
538                              self.pg1.local_ip4,
539                              self.pg1.remote_hosts[10].ip4)
540
541         #
542         # add an ARP entry that's not on the sub-net and so whose
543         # adj-fib fails the refinement check. then send an ARP request
544         # from that source
545         #
546         a1 = VppNeighbor(self,
547                          self.pg0.sw_if_index,
548                          self.pg0.remote_mac,
549                          "100.100.100.50")
550         a1.add_vpp_config()
551
552         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
553              ARP(op="who-has",
554                  hwsrc=self.pg0.remote_mac,
555                  psrc="100.100.100.50",
556                  pdst=self.pg0.remote_ip4))
557         self.send_and_assert_no_replies(self.pg0, p,
558                                         "ARP req for from failed adj-fib")
559
560         #
561         # ERROR Cases
562         #  1 - don't respond to ARP request for address not within the
563         #      interface's sub-net
564         #  1b - nor within the unnumbered subnet
565         #  1c - nor within the subnet of a different interface
566         #
567         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
568              ARP(op="who-has",
569                  hwsrc=self.pg0.remote_mac,
570                  pdst="10.10.10.3",
571                  psrc=self.pg0.remote_ip4))
572         self.send_and_assert_no_replies(self.pg0, p,
573                                         "ARP req for non-local destination")
574         self.assertFalse(find_nbr(self,
575                                   self.pg0.sw_if_index,
576                                   "10.10.10.3"))
577
578         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
579              ARP(op="who-has",
580                  hwsrc=self.pg2.remote_mac,
581                  pdst="10.10.10.3",
582                  psrc=self.pg1.remote_hosts[7].ip4))
583         self.send_and_assert_no_replies(
584             self.pg0, p,
585             "ARP req for non-local destination - unnum")
586
587         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
588              ARP(op="who-has",
589                  hwsrc=self.pg0.remote_mac,
590                  pdst=self.pg1.local_ip4,
591                  psrc=self.pg1.remote_ip4))
592         self.send_and_assert_no_replies(self.pg0, p,
593                                         "ARP req diff sub-net")
594         self.assertFalse(find_nbr(self,
595                                   self.pg0.sw_if_index,
596                                   self.pg1.remote_ip4))
597
598         #
599         #  2 - don't respond to ARP request from an address not within the
600         #      interface's sub-net
601         #   2b - to a prxied address
602         #   2c - not within a differents interface's sub-net
603         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
604              ARP(op="who-has",
605                  hwsrc=self.pg0.remote_mac,
606                  psrc="10.10.10.3",
607                  pdst=self.pg0.local_ip4))
608         self.send_and_assert_no_replies(self.pg0, p,
609                                         "ARP req for non-local source")
610         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) /
611              ARP(op="who-has",
612                  hwsrc=self.pg2.remote_mac,
613                  psrc="10.10.10.3",
614                  pdst=self.pg0.local_ip4))
615         self.send_and_assert_no_replies(
616             self.pg0, p,
617             "ARP req for non-local source - unnum")
618         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
619              ARP(op="who-has",
620                  hwsrc=self.pg0.remote_mac,
621                  psrc=self.pg1.remote_ip4,
622                  pdst=self.pg0.local_ip4))
623         self.send_and_assert_no_replies(self.pg0, p,
624                                         "ARP req for non-local source 2c")
625
626         #
627         #  3 - don't respond to ARP request from an address that belongs to
628         #      the router
629         #
630         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
631              ARP(op="who-has",
632                  hwsrc=self.pg0.remote_mac,
633                  psrc=self.pg0.local_ip4,
634                  pdst=self.pg0.local_ip4))
635         self.send_and_assert_no_replies(self.pg0, p,
636                                         "ARP req for non-local source")
637
638         #
639         #  4 - don't respond to ARP requests that has mac source different
640         #      from ARP request HW source
641         #
642         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
643              ARP(op="who-has",
644                  hwsrc="00:00:00:DE:AD:BE",
645                  psrc=self.pg0.remote_ip4,
646                  pdst=self.pg0.local_ip4))
647         self.send_and_assert_no_replies(self.pg0, p,
648                                         "ARP req for non-local source")
649
650         #
651         #  5 - don't respond to ARP requests for address within the
652         #      interface's sub-net but not the interface's address
653         #
654         self.pg0.generate_remote_hosts(2)
655         p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) /
656              ARP(op="who-has",
657                  hwsrc=self.pg0.remote_mac,
658                  psrc=self.pg0.remote_hosts[0].ip4,
659                  pdst=self.pg0.remote_hosts[1].ip4))
660         self.send_and_assert_no_replies(self.pg0, p,
661                                         "ARP req for non-local destination")
662
663         #
664         # cleanup
665         #
666         dyn_arp.remove_vpp_config()
667         static_arp.remove_vpp_config()
668         self.pg2.unset_unnumbered(self.pg1.sw_if_index)
669
670         # need this to flush the adj-fibs
671         self.pg2.unset_unnumbered(self.pg1.sw_if_index)
672         self.pg2.admin_down()
673         self.pg1.admin_down()
674
675     def test_proxy_mirror_arp(self):
676         """ Interface Mirror Proxy ARP """
677
678         #
679         # When VPP has an interface whose address is also applied to a TAP
680         # interface on the host, then VPP's TAP interface will be unnumbered
681         # to the 'real' interface and do proxy ARP from the host.
682         # the curious aspect of this setup is that ARP requests from the host
683         # will come from the VPP's own address.
684         #
685         self.pg0.generate_remote_hosts(2)
686
687         arp_req_from_me = (Ether(src=self.pg2.remote_mac,
688                                  dst="ff:ff:ff:ff:ff:ff") /
689                            ARP(op="who-has",
690                                hwsrc=self.pg2.remote_mac,
691                                pdst=self.pg0.remote_hosts[1].ip4,
692                                psrc=self.pg0.local_ip4))
693
694         #
695         # Configure Proxy ARP for the subnet on PG0addresses on pg0
696         #
697         self.vapi.proxy_arp_add_del(self.pg0._local_ip4_subnet,
698                                     self.pg0._local_ip4_bcast)
699
700         # Make pg2 un-numbered to pg0
701         #
702         self.pg2.set_unnumbered(self.pg0.sw_if_index)
703
704         #
705         # Enable pg2 for proxy ARP
706         #
707         self.pg2.set_proxy_arp()
708
709         #
710         # Send the ARP request with an originating address that
711         # is VPP's own address
712         #
713         self.pg2.add_stream(arp_req_from_me)
714         self.pg_enable_capture(self.pg_interfaces)
715         self.pg_start()
716
717         rx = self.pg2.get_capture(1)
718         self.verify_arp_resp(rx[0],
719                              self.pg2.local_mac,
720                              self.pg2.remote_mac,
721                              self.pg0.remote_hosts[1].ip4,
722                              self.pg0.local_ip4)
723
724         #
725         # validate we have not learned an ARP entry as a result of this
726         #
727         self.assertFalse(find_nbr(self,
728                                   self.pg2.sw_if_index,
729                                   self.pg0.local_ip4))
730
731         #
732         # cleanup
733         #
734         self.pg2.set_proxy_arp(0)
735         self.vapi.proxy_arp_add_del(self.pg0._local_ip4_subnet,
736                                     self.pg0._local_ip4_bcast,
737                                     is_add=0)
738
739     def test_proxy_arp(self):
740         """ Proxy ARP """
741
742         self.pg1.generate_remote_hosts(2)
743
744         #
745         # Proxy ARP rewquest packets for each interface
746         #
747         arp_req_pg0 = (Ether(src=self.pg0.remote_mac,
748                              dst="ff:ff:ff:ff:ff:ff") /
749                        ARP(op="who-has",
750                            hwsrc=self.pg0.remote_mac,
751                            pdst="10.10.10.3",
752                            psrc=self.pg0.remote_ip4))
753         arp_req_pg0_tagged = (Ether(src=self.pg0.remote_mac,
754                                     dst="ff:ff:ff:ff:ff:ff") /
755                               Dot1Q(vlan=0) /
756                               ARP(op="who-has",
757                                   hwsrc=self.pg0.remote_mac,
758                                   pdst="10.10.10.3",
759                                   psrc=self.pg0.remote_ip4))
760         arp_req_pg1 = (Ether(src=self.pg1.remote_mac,
761                              dst="ff:ff:ff:ff:ff:ff") /
762                        ARP(op="who-has",
763                            hwsrc=self.pg1.remote_mac,
764                            pdst="10.10.10.3",
765                            psrc=self.pg1.remote_ip4))
766         arp_req_pg2 = (Ether(src=self.pg2.remote_mac,
767                              dst="ff:ff:ff:ff:ff:ff") /
768                        ARP(op="who-has",
769                            hwsrc=self.pg2.remote_mac,
770                            pdst="10.10.10.3",
771                            psrc=self.pg1.remote_hosts[1].ip4))
772         arp_req_pg3 = (Ether(src=self.pg3.remote_mac,
773                              dst="ff:ff:ff:ff:ff:ff") /
774                        ARP(op="who-has",
775                            hwsrc=self.pg3.remote_mac,
776                            pdst="10.10.10.3",
777                            psrc=self.pg3.remote_ip4))
778
779         #
780         # Configure Proxy ARP for 10.10.10.0 -> 10.10.10.124
781         #
782         self.vapi.proxy_arp_add_del(inet_pton(AF_INET, "10.10.10.2"),
783                                     inet_pton(AF_INET, "10.10.10.124"))
784
785         #
786         # No responses are sent when the interfaces are not enabled for proxy
787         # ARP
788         #
789         self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
790                                         "ARP req from unconfigured interface")
791         self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
792                                         "ARP req from unconfigured interface")
793
794         #
795         # Make pg2 un-numbered to pg1
796         #  still won't reply.
797         #
798         self.pg2.set_unnumbered(self.pg1.sw_if_index)
799
800         self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
801                                         "ARP req from unnumbered interface")
802
803         #
804         # Enable each interface to reply to proxy ARPs
805         #
806         for i in self.pg_interfaces:
807             i.set_proxy_arp()
808
809         #
810         # Now each of the interfaces should reply to a request to a proxied
811         # address
812         #
813         self.pg0.add_stream(arp_req_pg0)
814         self.pg_enable_capture(self.pg_interfaces)
815         self.pg_start()
816
817         rx = self.pg0.get_capture(1)
818         self.verify_arp_resp(rx[0],
819                              self.pg0.local_mac,
820                              self.pg0.remote_mac,
821                              "10.10.10.3",
822                              self.pg0.remote_ip4)
823
824         self.pg0.add_stream(arp_req_pg0_tagged)
825         self.pg_enable_capture(self.pg_interfaces)
826         self.pg_start()
827
828         rx = self.pg0.get_capture(1)
829         self.verify_arp_resp(rx[0],
830                              self.pg0.local_mac,
831                              self.pg0.remote_mac,
832                              "10.10.10.3",
833                              self.pg0.remote_ip4)
834
835         self.pg1.add_stream(arp_req_pg1)
836         self.pg_enable_capture(self.pg_interfaces)
837         self.pg_start()
838
839         rx = self.pg1.get_capture(1)
840         self.verify_arp_resp(rx[0],
841                              self.pg1.local_mac,
842                              self.pg1.remote_mac,
843                              "10.10.10.3",
844                              self.pg1.remote_ip4)
845
846         self.pg2.add_stream(arp_req_pg2)
847         self.pg_enable_capture(self.pg_interfaces)
848         self.pg_start()
849
850         rx = self.pg2.get_capture(1)
851         self.verify_arp_resp(rx[0],
852                              self.pg2.local_mac,
853                              self.pg2.remote_mac,
854                              "10.10.10.3",
855                              self.pg1.remote_hosts[1].ip4)
856
857         #
858         # A request for an address out of the configured range
859         #
860         arp_req_pg1_hi = (Ether(src=self.pg1.remote_mac,
861                                 dst="ff:ff:ff:ff:ff:ff") /
862                           ARP(op="who-has",
863                               hwsrc=self.pg1.remote_mac,
864                               pdst="10.10.10.125",
865                               psrc=self.pg1.remote_ip4))
866         self.send_and_assert_no_replies(self.pg1, arp_req_pg1_hi,
867                                         "ARP req out of range HI")
868         arp_req_pg1_low = (Ether(src=self.pg1.remote_mac,
869                                  dst="ff:ff:ff:ff:ff:ff") /
870                            ARP(op="who-has",
871                                hwsrc=self.pg1.remote_mac,
872                                pdst="10.10.10.1",
873                                psrc=self.pg1.remote_ip4))
874         self.send_and_assert_no_replies(self.pg1, arp_req_pg1_low,
875                                         "ARP req out of range Low")
876
877         #
878         # Request for an address in the proxy range but from an interface
879         # in a different VRF
880         #
881         self.send_and_assert_no_replies(self.pg3, arp_req_pg3,
882                                         "ARP req from different VRF")
883
884         #
885         # Disable Each interface for proxy ARP
886         #  - expect none to respond
887         #
888         for i in self.pg_interfaces:
889             i.set_proxy_arp(0)
890
891         self.send_and_assert_no_replies(self.pg0, arp_req_pg0,
892                                         "ARP req from disable")
893         self.send_and_assert_no_replies(self.pg1, arp_req_pg1,
894                                         "ARP req from disable")
895         self.send_and_assert_no_replies(self.pg2, arp_req_pg2,
896                                         "ARP req from disable")
897
898         #
899         # clean up on interface 2
900         #
901         self.pg2.unset_unnumbered(self.pg1.sw_if_index)
902
903     def test_mpls(self):
904         """ MPLS """
905
906         #
907         # Interface 2 does not yet have ip4 config
908         #
909         self.pg2.config_ip4()
910         self.pg2.generate_remote_hosts(2)
911
912         #
913         # Add a reoute with out going label via an ARP unresolved next-hop
914         #
915         ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
916                                  [VppRoutePath(self.pg2.remote_hosts[1].ip4,
917                                                self.pg2.sw_if_index,
918                                                labels=[55])])
919         ip_10_0_0_1.add_vpp_config()
920
921         #
922         # packets should generate an ARP request
923         #
924         p = (Ether(src=self.pg0.remote_mac,
925                    dst=self.pg0.local_mac) /
926              IP(src=self.pg0.remote_ip4, dst="10.0.0.1") /
927              UDP(sport=1234, dport=1234) /
928              Raw('\xa5' * 100))
929
930         self.pg0.add_stream(p)
931         self.pg_enable_capture(self.pg_interfaces)
932         self.pg_start()
933
934         rx = self.pg2.get_capture(1)
935         self.verify_arp_req(rx[0],
936                             self.pg2.local_mac,
937                             self.pg2.local_ip4,
938                             self.pg2._remote_hosts[1].ip4)
939
940         #
941         # now resolve the neighbours
942         #
943         self.pg2.configure_ipv4_neighbors()
944
945         #
946         # Now packet should be properly MPLS encapped.
947         #  This verifies that MPLS link-type adjacencies are completed
948         #  when the ARP entry resolves
949         #
950         self.pg0.add_stream(p)
951         self.pg_enable_capture(self.pg_interfaces)
952         self.pg_start()
953
954         rx = self.pg2.get_capture(1)
955         self.verify_ip_o_mpls(rx[0],
956                               self.pg2.local_mac,
957                               self.pg2.remote_hosts[1].mac,
958                               55,
959                               self.pg0.remote_ip4,
960                               "10.0.0.1")
961         self.pg2.unconfig_ip4()
962
963     def test_arp_vrrp(self):
964         """ ARP reply with VRRP virtual src hw addr """
965
966         #
967         # IP packet destined for pg1 remote host arrives on pg0 resulting
968         # in an ARP request for the address of the remote host on pg1
969         #
970         p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
971               IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4) /
972               UDP(sport=1234, dport=1234) /
973               Raw())
974
975         rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
976
977         self.verify_arp_req(rx1[0],
978                             self.pg1.local_mac,
979                             self.pg1.local_ip4,
980                             self.pg1.remote_ip4)
981
982         #
983         # ARP reply for address of pg1 remote host arrives on pg1 with
984         # the hw src addr set to a value in the VRRP IPv4 range of
985         # MAC addresses
986         #
987         p1 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) /
988               ARP(op="is-at", hwdst=self.pg1.local_mac,
989                   hwsrc="00:00:5e:00:01:09", pdst=self.pg1.local_ip4,
990                   psrc=self.pg1.remote_ip4))
991
992         self.send_and_assert_no_replies(self.pg1, p1, "ARP reply")
993
994         #
995         # IP packet destined for pg1 remote host arrives on pg0 again.
996         # VPP should have an ARP entry for that address now and the packet
997         # should be sent out pg1.
998         #
999         rx1 = self.send_and_expect(self.pg0, [p0], self.pg1)
1000
1001         self.verify_ip(rx1[0],
1002                        self.pg1.local_mac,
1003                        "00:00:5e:00:01:09",
1004                        self.pg0.remote_ip4,
1005                        self.pg1.remote_ip4)
1006
1007         self.pg1.admin_down()
1008         self.pg1.admin_up()
1009
1010     def test_arp_duplicates(self):
1011         """ ARP Duplicates"""
1012
1013         #
1014         # Generate some hosts on the LAN
1015         #
1016         self.pg1.generate_remote_hosts(3)
1017
1018         #
1019         # Add host 1 on pg1 and pg2
1020         #
1021         arp_pg1 = VppNeighbor(self,
1022                               self.pg1.sw_if_index,
1023                               self.pg1.remote_hosts[1].mac,
1024                               self.pg1.remote_hosts[1].ip4)
1025         arp_pg1.add_vpp_config()
1026         arp_pg2 = VppNeighbor(self,
1027                               self.pg2.sw_if_index,
1028                               self.pg2.remote_mac,
1029                               self.pg1.remote_hosts[1].ip4)
1030         arp_pg2.add_vpp_config()
1031
1032         #
1033         # IP packet destined for pg1 remote host arrives on pg1 again.
1034         #
1035         p = (Ether(dst=self.pg0.local_mac,
1036                    src=self.pg0.remote_mac) /
1037              IP(src=self.pg0.remote_ip4,
1038                 dst=self.pg1.remote_hosts[1].ip4) /
1039              UDP(sport=1234, dport=1234) /
1040              Raw())
1041
1042         self.pg0.add_stream(p)
1043         self.pg_enable_capture(self.pg_interfaces)
1044         self.pg_start()
1045
1046         rx1 = self.pg1.get_capture(1)
1047
1048         self.verify_ip(rx1[0],
1049                        self.pg1.local_mac,
1050                        self.pg1.remote_hosts[1].mac,
1051                        self.pg0.remote_ip4,
1052                        self.pg1.remote_hosts[1].ip4)
1053
1054         #
1055         # remove the duplicate on pg1
1056         # packet stream shoud generate ARPs out of pg1
1057         #
1058         arp_pg1.remove_vpp_config()
1059
1060         self.pg0.add_stream(p)
1061         self.pg_enable_capture(self.pg_interfaces)
1062         self.pg_start()
1063
1064         rx1 = self.pg1.get_capture(1)
1065
1066         self.verify_arp_req(rx1[0],
1067                             self.pg1.local_mac,
1068                             self.pg1.local_ip4,
1069                             self.pg1.remote_hosts[1].ip4)
1070
1071         #
1072         # Add it back
1073         #
1074         arp_pg1.add_vpp_config()
1075
1076         self.pg0.add_stream(p)
1077         self.pg_enable_capture(self.pg_interfaces)
1078         self.pg_start()
1079
1080         rx1 = self.pg1.get_capture(1)
1081
1082         self.verify_ip(rx1[0],
1083                        self.pg1.local_mac,
1084                        self.pg1.remote_hosts[1].mac,
1085                        self.pg0.remote_ip4,
1086                        self.pg1.remote_hosts[1].ip4)
1087
1088     def test_arp_static(self):
1089         """ ARP Static"""
1090         self.pg2.generate_remote_hosts(3)
1091
1092         #
1093         # Add a static ARP entry
1094         #
1095         static_arp = VppNeighbor(self,
1096                                  self.pg2.sw_if_index,
1097                                  self.pg2.remote_hosts[1].mac,
1098                                  self.pg2.remote_hosts[1].ip4,
1099                                  is_static=1)
1100         static_arp.add_vpp_config()
1101
1102         #
1103         # Add the connected prefix to the interface
1104         #
1105         self.pg2.config_ip4()
1106
1107         #
1108         # We should now find the adj-fib
1109         #
1110         self.assertTrue(find_nbr(self,
1111                                  self.pg2.sw_if_index,
1112                                  self.pg2.remote_hosts[1].ip4,
1113                                  is_static=1))
1114         self.assertTrue(find_route(self,
1115                                    self.pg2.remote_hosts[1].ip4,
1116                                    32))
1117
1118         #
1119         # remove the connected
1120         #
1121         self.pg2.unconfig_ip4()
1122
1123         #
1124         # put the interface into table 1
1125         #
1126         self.pg2.set_table_ip4(1)
1127
1128         #
1129         # configure the same connected and expect to find the
1130         # adj fib in the new table
1131         #
1132         self.pg2.config_ip4()
1133         self.assertTrue(find_route(self,
1134                                    self.pg2.remote_hosts[1].ip4,
1135                                    32,
1136                                    table_id=1))
1137
1138         #
1139         # clean-up
1140         #
1141         self.pg2.unconfig_ip4()
1142         self.pg2.set_table_ip4(0)
1143
1144     def test_arp_incomplete(self):
1145         """ ARP Incomplete"""
1146         self.pg1.generate_remote_hosts(3)
1147
1148         p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1149               IP(src=self.pg0.remote_ip4,
1150                  dst=self.pg1.remote_hosts[1].ip4) /
1151               UDP(sport=1234, dport=1234) /
1152               Raw())
1153         p1 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
1154               IP(src=self.pg0.remote_ip4,
1155                  dst=self.pg1.remote_hosts[2].ip4) /
1156               UDP(sport=1234, dport=1234) /
1157               Raw())
1158
1159         #
1160         # a packet to an unresolved destination generates an ARP request
1161         #
1162         rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1163         self.verify_arp_req(rx[0],
1164                             self.pg1.local_mac,
1165                             self.pg1.local_ip4,
1166                             self.pg1._remote_hosts[1].ip4)
1167
1168         #
1169         # add a neighbour for remote host 1
1170         #
1171         static_arp = VppNeighbor(self,
1172                                  self.pg1.sw_if_index,
1173                                  self.pg1.remote_hosts[1].mac,
1174                                  self.pg1.remote_hosts[1].ip4,
1175                                  is_static=1)
1176         static_arp.add_vpp_config()
1177
1178         #
1179         # change the interface's MAC
1180         #
1181         mac = [chr(0x00), chr(0x00), chr(0x00),
1182                chr(0x33), chr(0x33), chr(0x33)]
1183         mac_string = ''.join(mac)
1184
1185         self.vapi.sw_interface_set_mac_address(self.pg1.sw_if_index,
1186                                                mac_string)
1187
1188         #
1189         # now ARP requests come from the new source mac
1190         #
1191         rx = self.send_and_expect(self.pg0, [p1], self.pg1)
1192         self.verify_arp_req(rx[0],
1193                             "00:00:00:33:33:33",
1194                             self.pg1.local_ip4,
1195                             self.pg1._remote_hosts[2].ip4)
1196
1197         #
1198         # packets to the resolved host also have the new source mac
1199         #
1200         rx = self.send_and_expect(self.pg0, [p0], self.pg1)
1201         self.verify_ip(rx[0],
1202                        "00:00:00:33:33:33",
1203                        self.pg1.remote_hosts[1].mac,
1204                        self.pg0.remote_ip4,
1205                        self.pg1.remote_hosts[1].ip4)
1206
1207         #
1208         # set the mac address on the inteface that does not have a
1209         # configured subnet and thus no glean
1210         #
1211         self.vapi.sw_interface_set_mac_address(self.pg2.sw_if_index,
1212                                                mac_string)
1213
1214     def test_garp(self):
1215         """ GARP """
1216
1217         #
1218         # Generate some hosts on the LAN
1219         #
1220         self.pg1.generate_remote_hosts(4)
1221
1222         #
1223         # And an ARP entry
1224         #
1225         arp = VppNeighbor(self,
1226                           self.pg1.sw_if_index,
1227                           self.pg1.remote_hosts[1].mac,
1228                           self.pg1.remote_hosts[1].ip4)
1229         arp.add_vpp_config()
1230
1231         self.assertTrue(find_nbr(self,
1232                                  self.pg1.sw_if_index,
1233                                  self.pg1.remote_hosts[1].ip4,
1234                                  mac=self.pg1.remote_hosts[1].mac))
1235
1236         #
1237         # Send a GARP (request) to swap the host 1's address to that of host 2
1238         #
1239         p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1240                     src=self.pg1.remote_hosts[2].mac) /
1241               ARP(op="who-has",
1242                   hwdst=self.pg1.local_mac,
1243                   hwsrc=self.pg1.remote_hosts[2].mac,
1244                   pdst=self.pg1.remote_hosts[1].ip4,
1245                   psrc=self.pg1.remote_hosts[1].ip4))
1246
1247         self.pg1.add_stream(p1)
1248         self.pg_enable_capture(self.pg_interfaces)
1249         self.pg_start()
1250
1251         self.assertTrue(find_nbr(self,
1252                                  self.pg1.sw_if_index,
1253                                  self.pg1.remote_hosts[1].ip4,
1254                                  mac=self.pg1.remote_hosts[2].mac))
1255
1256         #
1257         # Send a GARP (reply) to swap the host 1's address to that of host 3
1258         #
1259         p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1260                     src=self.pg1.remote_hosts[3].mac) /
1261               ARP(op="is-at",
1262                   hwdst=self.pg1.local_mac,
1263                   hwsrc=self.pg1.remote_hosts[3].mac,
1264                   pdst=self.pg1.remote_hosts[1].ip4,
1265                   psrc=self.pg1.remote_hosts[1].ip4))
1266
1267         self.pg1.add_stream(p1)
1268         self.pg_enable_capture(self.pg_interfaces)
1269         self.pg_start()
1270
1271         self.assertTrue(find_nbr(self,
1272                                  self.pg1.sw_if_index,
1273                                  self.pg1.remote_hosts[1].ip4,
1274                                  mac=self.pg1.remote_hosts[3].mac))
1275
1276         #
1277         # GARPs (requets nor replies) for host we don't know yet
1278         # don't result in new neighbour entries
1279         #
1280         p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1281                     src=self.pg1.remote_hosts[3].mac) /
1282               ARP(op="who-has",
1283                   hwdst=self.pg1.local_mac,
1284                   hwsrc=self.pg1.remote_hosts[3].mac,
1285                   pdst=self.pg1.remote_hosts[2].ip4,
1286                   psrc=self.pg1.remote_hosts[2].ip4))
1287
1288         self.pg1.add_stream(p1)
1289         self.pg_enable_capture(self.pg_interfaces)
1290         self.pg_start()
1291
1292         self.assertFalse(find_nbr(self,
1293                                   self.pg1.sw_if_index,
1294                                   self.pg1.remote_hosts[2].ip4))
1295
1296         p1 = (Ether(dst="ff:ff:ff:ff:ff:ff",
1297                     src=self.pg1.remote_hosts[3].mac) /
1298               ARP(op="is-at",
1299                   hwdst=self.pg1.local_mac,
1300                   hwsrc=self.pg1.remote_hosts[3].mac,
1301                   pdst=self.pg1.remote_hosts[2].ip4,
1302                   psrc=self.pg1.remote_hosts[2].ip4))
1303
1304         self.pg1.add_stream(p1)
1305         self.pg_enable_capture(self.pg_interfaces)
1306         self.pg_start()
1307
1308         self.assertFalse(find_nbr(self,
1309                                   self.pg1.sw_if_index,
1310                                   self.pg1.remote_hosts[2].ip4))
1311
1312     def test_arp_incomplete(self):
1313         """ Incomplete Entries """
1314
1315         #
1316         # ensure that we throttle the ARP and ND requests
1317         #
1318         self.pg0.generate_remote_hosts(2)
1319
1320         #
1321         # IPv4/ARP
1322         #
1323         ip_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32,
1324                                  [VppRoutePath(self.pg0.remote_hosts[1].ip4,
1325                                                self.pg0.sw_if_index)])
1326         ip_10_0_0_1.add_vpp_config()
1327
1328         p1 = (Ether(dst=self.pg1.local_mac,
1329                     src=self.pg1.remote_mac) /
1330               IP(src=self.pg1.remote_ip4,
1331                  dst="10.0.0.1") /
1332               UDP(sport=1234, dport=1234) /
1333               Raw())
1334
1335         self.pg1.add_stream(p1 * 257)
1336         self.pg_enable_capture(self.pg_interfaces)
1337         self.pg_start()
1338         rx = self.pg0._get_capture(1)
1339
1340         #
1341         # how many we get is going to be dependent on the time for packet
1342         # processing but it should be small
1343         #
1344         self.assertLess(len(rx), 64)
1345
1346         #
1347         # IPv6/ND
1348         #
1349         ip_10_1 = VppIpRoute(self, "10::1", 128,
1350                              [VppRoutePath(self.pg0.remote_hosts[1].ip6,
1351                                            self.pg0.sw_if_index,
1352                                            proto=DpoProto.DPO_PROTO_IP6)],
1353                              is_ip6=1)
1354         ip_10_1.add_vpp_config()
1355
1356         p1 = (Ether(dst=self.pg1.local_mac,
1357                     src=self.pg1.remote_mac) /
1358               IPv6(src=self.pg1.remote_ip6,
1359                    dst="10::1") /
1360               UDP(sport=1234, dport=1234) /
1361               Raw())
1362
1363         self.pg1.add_stream(p1 * 257)
1364         self.pg_enable_capture(self.pg_interfaces)
1365         self.pg_start()
1366         rx = self.pg0._get_capture(1)
1367
1368         #
1369         # how many we get is going to be dependent on the time for packet
1370         # processing but it should be small
1371         #
1372         self.assertLess(len(rx), 64)
1373
1374     def test_arp_forus(self):
1375         """ ARP for for-us """
1376
1377         #
1378         # Test that VPP responds with ARP requests to addresses that
1379         # are connected and local routes.
1380         # Use one of the 'remote' addresses in the subnet as a local address
1381         # The intention of this route is that it then acts like a secondardy
1382         # address added to an interface
1383         #
1384         self.pg0.generate_remote_hosts(2)
1385
1386         forus = VppIpRoute(self, self.pg0.remote_hosts[1].ip4, 32,
1387                            [VppRoutePath(self.pg0.remote_hosts[1].ip4,
1388                                          self.pg0.sw_if_index)],
1389                            is_local=1)
1390         forus.add_vpp_config()
1391
1392         p = (Ether(dst="ff:ff:ff:ff:ff:ff",
1393                    src=self.pg0.remote_mac) /
1394              ARP(op="who-has",
1395                  hwdst=self.pg0.local_mac,
1396                  hwsrc=self.pg0.remote_mac,
1397                  pdst=self.pg0.remote_hosts[1].ip4,
1398                  psrc=self.pg0.remote_ip4))
1399
1400         rx = self.send_and_expect(self.pg0, [p], self.pg0)
1401
1402         self.verify_arp_resp(rx[0],
1403                              self.pg0.local_mac,
1404                              self.pg0.remote_mac,
1405                              self.pg0.remote_hosts[1].ip4,
1406                              self.pg0.remote_ip4)
1407
1408
1409 class NeighborStatsTestCase(VppTestCase):
1410     """ ARP/ND Counters """
1411
1412     def setUp(self):
1413         super(NeighborStatsTestCase, self).setUp()
1414
1415         self.create_pg_interfaces(range(2))
1416
1417         # pg0 configured with ip4 and 6 addresses used for input
1418         # pg1 configured with ip4 and 6 addresses used for output
1419         # pg2 is unnumbered to pg0
1420         for i in self.pg_interfaces:
1421             i.admin_up()
1422             i.config_ip4()
1423             i.config_ip6()
1424             i.resolve_arp()
1425             i.resolve_ndp()
1426
1427     def tearDown(self):
1428         super(NeighborStatsTestCase, self).tearDown()
1429
1430         for i in self.pg_interfaces:
1431             i.unconfig_ip4()
1432             i.unconfig_ip6()
1433             i.admin_down()
1434
1435     def test_arp_stats(self):
1436         """ ARP Counters """
1437
1438         self.vapi.cli("adj counters enable")
1439         self.pg1.generate_remote_hosts(2)
1440
1441         arp1 = VppNeighbor(self,
1442                            self.pg1.sw_if_index,
1443                            self.pg1.remote_hosts[0].mac,
1444                            self.pg1.remote_hosts[0].ip4)
1445         arp1.add_vpp_config()
1446         arp2 = VppNeighbor(self,
1447                            self.pg1.sw_if_index,
1448                            self.pg1.remote_hosts[1].mac,
1449                            self.pg1.remote_hosts[1].ip4)
1450         arp2.add_vpp_config()
1451
1452         p1 = (Ether(dst=self.pg0.local_mac,
1453                     src=self.pg0.remote_mac) /
1454               IP(src=self.pg0.remote_ip4,
1455                  dst=self.pg1.remote_hosts[0].ip4) /
1456               UDP(sport=1234, dport=1234) /
1457               Raw())
1458         p2 = (Ether(dst=self.pg0.local_mac,
1459                     src=self.pg0.remote_mac) /
1460               IP(src=self.pg0.remote_ip4,
1461                  dst=self.pg1.remote_hosts[1].ip4) /
1462               UDP(sport=1234, dport=1234) /
1463               Raw())
1464
1465         rx = self.send_and_expect(self.pg0, p1 * 65, self.pg1)
1466         rx = self.send_and_expect(self.pg0, p2 * 65, self.pg1)
1467
1468         self.assertEqual(65, arp1.get_stats()['packets'])
1469         self.assertEqual(65, arp2.get_stats()['packets'])
1470
1471         rx = self.send_and_expect(self.pg0, p1 * 65, self.pg1)
1472         self.assertEqual(130, arp1.get_stats()['packets'])
1473
1474     def test_nd_stats(self):
1475         """ ND Counters """
1476
1477         self.vapi.cli("adj counters enable")
1478         self.pg0.generate_remote_hosts(3)
1479
1480         nd1 = VppNeighbor(self,
1481                           self.pg0.sw_if_index,
1482                           self.pg0.remote_hosts[1].mac,
1483                           self.pg0.remote_hosts[1].ip6)
1484         nd1.add_vpp_config()
1485         nd2 = VppNeighbor(self,
1486                           self.pg0.sw_if_index,
1487                           self.pg0.remote_hosts[2].mac,
1488                           self.pg0.remote_hosts[2].ip6)
1489         nd2.add_vpp_config()
1490
1491         p1 = (Ether(dst=self.pg1.local_mac,
1492                     src=self.pg1.remote_mac) /
1493               IPv6(src=self.pg1.remote_ip6,
1494                    dst=self.pg0.remote_hosts[1].ip6) /
1495               UDP(sport=1234, dport=1234) /
1496               Raw())
1497         p2 = (Ether(dst=self.pg1.local_mac,
1498                     src=self.pg1.remote_mac) /
1499               IPv6(src=self.pg1.remote_ip6,
1500                    dst=self.pg0.remote_hosts[2].ip6) /
1501               UDP(sport=1234, dport=1234) /
1502               Raw())
1503
1504         rx = self.send_and_expect(self.pg1, p1 * 16, self.pg0)
1505         rx = self.send_and_expect(self.pg1, p2 * 16, self.pg0)
1506
1507         self.assertEqual(16, nd1.get_stats()['packets'])
1508         self.assertEqual(16, nd2.get_stats()['packets'])
1509
1510         rx = self.send_and_expect(self.pg1, p1 * 65, self.pg0)
1511         self.assertEqual(81, nd1.get_stats()['packets'])
1512
1513
1514 if __name__ == '__main__':
1515     unittest.main(testRunner=VppTestRunner)