blob: 6565d23a8b693981b43534d00a6c7c89e13a523c [file] [log] [blame]
Renato Botelho do Coutoead1e532019-10-31 13:31:07 -05001#!/usr/bin/env python3
Matej Klotton8d8a1da2016-12-22 11:06:56 +01002"""CRUD tests of APIs (Create, Read, Update, Delete) HLD:
3
4- interface up/down/add/delete - interface type:
5 - pg (TBD)
6 - loopback
7 - vhostuser (TBD)
8 - af_packet (TBD)
9 - netmap (TBD)
10 - tuntap (root privileges needed)
11 - vxlan (TBD)
12"""
13
14import unittest
15
16from scapy.layers.inet import IP, ICMP
17from scapy.layers.l2 import Ether
18
Dave Wallace8800f732023-08-31 00:47:44 -040019from framework import VppTestCase
20from asfframework import VppTestRunner
Dmitry Valter34fa0ce2024-03-11 10:38:46 +000021from config import config
Matej Klotton8d8a1da2016-12-22 11:06:56 +010022
23
24class TestLoopbackInterfaceCRUD(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020025 """CRUD Loopback"""
Matej Klotton8d8a1da2016-12-22 11:06:56 +010026
27 @classmethod
28 def setUpClass(cls):
29 super(TestLoopbackInterfaceCRUD, cls).setUpClass()
30 try:
31 cls.create_pg_interfaces(range(1))
32 for i in cls.pg_interfaces:
Paul Vinciguerra207083f2019-12-02 22:38:00 -050033 i.config_ip4().resolve_arp()
Matej Klotton8d8a1da2016-12-22 11:06:56 +010034 except:
35 cls.tearDownClass()
36 raise
37
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070038 @classmethod
39 def tearDownClass(cls):
40 super(TestLoopbackInterfaceCRUD, cls).tearDownClass()
41
Matej Klotton8d8a1da2016-12-22 11:06:56 +010042 @staticmethod
43 def create_icmp_stream(src_if, dst_ifs):
44 """
45
46 :param VppInterface src_if: Packets are send to this interface,
47 using this interfaces remote host.
48 :param list dst_ifs: IPv4 ICMP requests are send to interfaces
49 addresses.
50 :return: List of generated packets.
51 """
52 pkts = []
53 for i in dst_ifs:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020054 p = (
55 Ether(dst=src_if.local_mac, src=src_if.remote_mac)
56 / IP(src=src_if.remote_ip4, dst=i.local_ip4)
57 / ICMP(id=i.sw_if_index, type="echo-request")
58 )
Matej Klotton8d8a1da2016-12-22 11:06:56 +010059 pkts.append(p)
60 return pkts
61
62 def verify_icmp(self, capture, request_src_if, dst_ifs):
63 """
64
65 :param capture: Capture to verify.
66 :param VppInterface request_src_if: Interface where was send packets.
67 :param list dst_ifs: Interfaces where was generated IPv4 ICMP requests.
68 """
69 rcvd_icmp_pkts = []
70 for pkt in capture:
71 try:
72 ip = pkt[IP]
73 icmp = pkt[ICMP]
74 except IndexError:
75 pass
76 else:
77 info = (ip.src, ip.dst, icmp.type, icmp.id)
78 rcvd_icmp_pkts.append(info)
79
80 for i in dst_ifs:
81 # 0 - icmp echo response
82 info = (i.local_ip4, request_src_if.remote_ip4, 0, i.sw_if_index)
83 self.assertIn(info, rcvd_icmp_pkts)
84
Dmitry Valter34fa0ce2024-03-11 10:38:46 +000085 @unittest.skipIf(
86 "ping" in config.excluded_plugins, "Exclude tests requiring Ping plugin"
87 )
Matej Klotton8d8a1da2016-12-22 11:06:56 +010088 def test_crud(self):
89 # create
Klement Sekerab9ef2732018-06-24 22:49:33 +020090 loopbacks = self.create_loopback_interfaces(20)
Matej Klotton8d8a1da2016-12-22 11:06:56 +010091 for i in loopbacks:
Neale Rannsefd7bc22019-11-11 08:32:34 +000092 i.local_ip4_prefix_len = 32
Paul Vinciguerra207083f2019-12-02 22:38:00 -050093 i.config_ip4().admin_up()
Matej Klotton8d8a1da2016-12-22 11:06:56 +010094
95 # read (check sw if dump, ip4 fib, ip6 fib)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020096 if_dump = self.vapi.sw_interface_dump(
97 name_filter_valid=True, name_filter="loop"
98 )
Neale Ranns097fa662018-05-01 05:17:55 -070099 fib4_dump = self.vapi.ip_route_dump(0)
Matej Klotton8d8a1da2016-12-22 11:06:56 +0100100 for i in loopbacks:
101 self.assertTrue(i.is_interface_config_in_dump(if_dump))
102 self.assertTrue(i.is_ip4_entry_in_fib_dump(fib4_dump))
103
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200104 if_dump = self.vapi.sw_interface_dump(
105 name_filter_valid=True, name_filter="loopXYZ"
106 )
Aleksander Djuricc12eae72019-10-31 14:35:21 +0300107 self.assertEqual(len(if_dump), 0)
108
Matej Klotton8d8a1da2016-12-22 11:06:56 +0100109 # check ping
110 stream = self.create_icmp_stream(self.pg0, loopbacks)
111 self.pg0.add_stream(stream)
112 self.pg_enable_capture(self.pg_interfaces)
113 self.pg_start()
114 capture = self.pg0.get_capture(expected_count=len(stream))
115
116 self.verify_icmp(capture, self.pg0, loopbacks)
117
118 # delete
119 for i in loopbacks:
120 i.remove_vpp_config()
121
122 # read (check not in sw if dump, ip4 fib, ip6 fib)
123 if_dump = self.vapi.sw_interface_dump()
Neale Ranns097fa662018-05-01 05:17:55 -0700124 fib4_dump = self.vapi.ip_route_dump(0)
Matej Klotton8d8a1da2016-12-22 11:06:56 +0100125 for i in loopbacks:
126 self.assertFalse(i.is_interface_config_in_dump(if_dump))
127 self.assertFalse(i.is_ip4_entry_in_fib_dump(fib4_dump))
128
129 # check not ping
130 stream = self.create_icmp_stream(self.pg0, loopbacks)
131 self.pg0.add_stream(stream)
132 self.pg_enable_capture(self.pg_interfaces)
133 self.pg_start()
134 self.pg0.assert_nothing_captured()
135
136 def test_down(self):
137 # create
Klement Sekerab9ef2732018-06-24 22:49:33 +0200138 loopbacks = self.create_loopback_interfaces(20)
Matej Klotton8d8a1da2016-12-22 11:06:56 +0100139 for i in loopbacks:
Neale Rannsefd7bc22019-11-11 08:32:34 +0000140 i.local_ip4_prefix_len = 32
Paul Vinciguerra207083f2019-12-02 22:38:00 -0500141 i.config_ip4().admin_up()
Matej Klotton8d8a1da2016-12-22 11:06:56 +0100142
143 # disable
144 for i in loopbacks:
Paul Vinciguerra207083f2019-12-02 22:38:00 -0500145 i.admin_down().unconfig_ip4()
Matej Klotton8d8a1da2016-12-22 11:06:56 +0100146
147 # read (check not in sw if dump, ip4 fib, ip6 fib)
148 if_dump = self.vapi.sw_interface_dump()
Neale Ranns097fa662018-05-01 05:17:55 -0700149 fib4_dump = self.vapi.ip_route_dump(0)
Matej Klotton8d8a1da2016-12-22 11:06:56 +0100150 for i in loopbacks:
151 self.assertTrue(i.is_interface_config_in_dump(if_dump))
152 self.assertFalse(i.is_ip4_entry_in_fib_dump(fib4_dump))
153
154 # check not ping
155 stream = self.create_icmp_stream(self.pg0, loopbacks)
156 self.pg0.add_stream(stream)
157 self.pg_enable_capture(self.pg_interfaces)
158 self.pg_start()
159 self.pg0.assert_nothing_captured()
160
161
Paul Vinciguerra6407ba52019-04-04 13:22:20 -0700162class TestInterfaceDumpApiLocalOnly(VppTestCase):
163 """test_interface_crud.TestInterfaceDumpApiLocalOnly"""
164
165 def test_sw_if_index_0(self):
166 rv = self.vapi.sw_interface_dump(sw_if_index=0)
167 self.assertEqual(rv[0].sw_if_index, 0)
168
169 def test_sw_if_index_twiddle0(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200170 rv = self.vapi.sw_interface_dump(sw_if_index=0xFFFFFFFF)
Paul Vinciguerra6407ba52019-04-04 13:22:20 -0700171 self.assertEqual(rv[0].sw_if_index, 0)
172
173 def test_sw_if_index_1_not_existing(self):
174 rv = self.vapi.sw_interface_dump(sw_if_index=1)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200175 self.assertEqual(len(rv), 0, "expected no records.")
Paul Vinciguerra6407ba52019-04-04 13:22:20 -0700176
177
178class TestInterfaceDumpApi(VppTestCase):
179 """test_interface_crud.TestInterfaceDumpApi"""
180
181 def test_sw_if_index_1(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200182 self.vapi.create_loopback_instance(is_specified=1, user_instance=10)
183 self.vapi.create_loopback_instance(is_specified=1, user_instance=5)
Paul Vinciguerra6407ba52019-04-04 13:22:20 -0700184
185 # Can I get back the specified record?
186 rv = self.vapi.sw_interface_dump(sw_if_index=1)
187 self.assertEqual(rv[0].sw_if_index, 1, rv)
188
189 # verify 3 interfaces
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200190 rv = self.vapi.sw_interface_dump(sw_if_index=0xFFFFFFFF)
191 self.assertEqual(len(rv), 3, "Expected 3 interfaces.")
Paul Vinciguerra6407ba52019-04-04 13:22:20 -0700192
Paul Vinciguerra207083f2019-12-02 22:38:00 -0500193
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200194if __name__ == "__main__":
Matej Klotton8d8a1da2016-12-22 11:06:56 +0100195 unittest.main(testRunner=VppTestRunner)