acl: revert acl: api cleanup
[vpp.git] / test / test_pipe.py
1 #!/usr/bin/env python3
2 from socket import AF_INET, AF_INET6, inet_pton
3 import unittest
4
5 from scapy.packet import Raw
6 from scapy.layers.l2 import Ether
7 from scapy.layers.inet import IP, UDP
8
9 from framework import VppTestCase, VppTestRunner
10 from vpp_interface import VppInterface
11 from vpp_ip_route import VppIpTable, VppIpRoute, VppRoutePath
12
13 NUM_PKTS = 67
14
15
16 class VppPipe(VppInterface):
17     """
18     VPP Pipe
19     """
20
21     @property
22     def east(self):
23         return self.result.pipe_sw_if_index[1]
24
25     @property
26     def west(self):
27         return self.result.pipe_sw_if_index[0]
28
29     def __init__(self, test, instance=0xffffffff):
30         super(VppPipe, self).__init__(test)
31         self._test = test
32         self.instance = instance
33
34     def add_vpp_config(self):
35         self.result = self._test.vapi.pipe_create(
36             0 if self.instance == 0xffffffff else 1,
37             self.instance)
38         self.set_sw_if_index(self.result.sw_if_index)
39
40     def remove_vpp_config(self):
41         self._test.vapi.pipe_delete(
42             self.result.sw_if_index)
43
44     def object_id(self):
45         return "pipe-%d" % (self._sw_if_index)
46
47     def query_vpp_config(self):
48         pipes = self._test.vapi.pipe_dump()
49         for p in pipes:
50             if p.sw_if_index == self.result.sw_if_index:
51                 return True
52         return False
53
54     def set_unnumbered(self, ip_sw_if_index, is_add=True):
55         res = self._test.vapi.sw_interface_set_unnumbered(ip_sw_if_index,
56                                                           self.east, is_add)
57         res = self._test.vapi.sw_interface_set_unnumbered(ip_sw_if_index,
58                                                           self.west, is_add)
59
60
61 class TestPipe(VppTestCase):
62     """ Pipes """
63
64     @classmethod
65     def setUpClass(cls):
66         super(TestPipe, cls).setUpClass()
67
68     @classmethod
69     def tearDownClass(cls):
70         super(TestPipe, cls).tearDownClass()
71
72     def setUp(self):
73         super(TestPipe, self).setUp()
74
75         self.create_pg_interfaces(range(4))
76
77         for i in self.pg_interfaces:
78             i.admin_up()
79
80     def tearDown(self):
81         for i in self.pg_interfaces:
82             i.admin_down()
83
84         super(TestPipe, self).tearDown()
85
86     def test_pipe(self):
87         """ Pipes """
88
89         pipes = [VppPipe(self), VppPipe(self, 10)]
90
91         for p in pipes:
92             p.add_vpp_config()
93             p.admin_up()
94
95         #
96         # L2 cross-connect pipe0 east with pg0 and west with pg1
97         #
98         self.vapi.sw_interface_set_l2_xconnect(self.pg0.sw_if_index,
99                                                pipes[0].east,
100                                                enable=1)
101         self.vapi.sw_interface_set_l2_xconnect(pipes[0].east,
102                                                self.pg0.sw_if_index,
103                                                enable=1)
104         self.vapi.sw_interface_set_l2_xconnect(self.pg1.sw_if_index,
105                                                pipes[0].west,
106                                                enable=1)
107         self.vapi.sw_interface_set_l2_xconnect(pipes[0].west,
108                                                self.pg1.sw_if_index,
109                                                enable=1)
110
111         # test bi-directional L2 flow pg0<->pg1
112         p = (Ether(src=self.pg0.remote_mac,
113                    dst=self.pg1.remote_mac) /
114              IP(src="1.1.1.1",
115                 dst="1.1.1.2") /
116              UDP(sport=1234, dport=1234) /
117              Raw(b'\xa5' * 100))
118
119         self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1)
120         self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0)
121
122         #
123         # Attach ACL to ensure features are run on the pipe
124         #
125         rule_1 = ({'is_permit': 0,
126                    'is_ipv6': 0,
127                    'proto': 17,
128                    'srcport_or_icmptype_first': 1234,
129                    'srcport_or_icmptype_last': 1234,
130                    'src_ip_prefix_len': 32,
131                    'src_ip_addr': inet_pton(AF_INET, "1.1.1.1"),
132                    'dstport_or_icmpcode_first': 1234,
133                    'dstport_or_icmpcode_last': 1234,
134                    'dst_ip_prefix_len': 32,
135                    'dst_ip_addr': inet_pton(AF_INET, "1.1.1.2")})
136         acl = self.vapi.acl_add_replace(acl_index=4294967295,
137                                         r=[rule_1])
138
139         # Apply the ACL on the pipe on output
140         self.vapi.acl_interface_set_acl_list(pipes[0].east,
141                                              0,
142                                              [acl.acl_index])
143         self.send_and_assert_no_replies(self.pg0, p * NUM_PKTS)
144         self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0)
145
146         # remove from output and apply on input
147         self.vapi.acl_interface_set_acl_list(pipes[0].east,
148                                              0,
149                                              [])
150         self.vapi.acl_interface_set_acl_list(pipes[0].west,
151                                              1,
152                                              [acl.acl_index])
153         self.send_and_assert_no_replies(self.pg0, p * NUM_PKTS)
154         self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0)
155         self.vapi.acl_interface_set_acl_list(pipes[0].west,
156                                              0,
157                                              [])
158         self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1)
159         self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0)
160
161         #
162         # L3 routes in two separate tables so a pipe can be used to L3
163         # x-connect
164         #
165         tables = []
166         tables.append(VppIpTable(self, 1))
167         tables.append(VppIpTable(self, 2))
168
169         for t in tables:
170             t.add_vpp_config()
171
172         self.pg2.set_table_ip4(1)
173         self.pg2.config_ip4()
174         self.pg2.resolve_arp()
175         self.pg3.set_table_ip4(2)
176         self.pg3.config_ip4()
177         self.pg3.resolve_arp()
178
179         routes = []
180         routes.append(VppIpRoute(self, "1.1.1.1", 32,
181                                  [VppRoutePath(self.pg3.remote_ip4,
182                                                self.pg3.sw_if_index)],
183                                  table_id=2))
184         routes.append(VppIpRoute(self, "1.1.1.1", 32,
185                                  [VppRoutePath("0.0.0.0", pipes[1].east)],
186                                  table_id=1))
187         routes.append(VppIpRoute(self, "1.1.1.2", 32,
188                                  [VppRoutePath("0.0.0.0", pipes[1].west)],
189                                  table_id=2))
190         routes.append(VppIpRoute(self, "1.1.1.2", 32,
191                                  [VppRoutePath(self.pg2.remote_ip4,
192                                                self.pg2.sw_if_index)],
193                                  table_id=1))
194
195         for r in routes:
196             r.add_vpp_config()
197
198         p_east = (Ether(src=self.pg2.remote_mac,
199                         dst=self.pg2.local_mac) /
200                   IP(src="1.1.1.2",
201                      dst="1.1.1.1") /
202                   UDP(sport=1234, dport=1234) /
203                   Raw(b'\xa5' * 100))
204
205         # bind the pipe ends to the correct tables
206         self.vapi.sw_interface_set_table(pipes[1].west, 0, 2)
207         self.vapi.sw_interface_set_table(pipes[1].east, 0, 1)
208
209         # IP is not enabled on the pipes at this point
210         self.send_and_assert_no_replies(self.pg2, p_east * NUM_PKTS)
211
212         # IP enable the Pipes by making them unnumbered
213         pipes[0].set_unnumbered(self.pg2.sw_if_index)
214         pipes[1].set_unnumbered(self.pg3.sw_if_index)
215
216         self.send_and_expect(self.pg2, p_east * NUM_PKTS, self.pg3)
217
218         # and the return path
219         p_west = (Ether(src=self.pg3.remote_mac,
220                         dst=self.pg3.local_mac) /
221                   IP(src="1.1.1.1",
222                      dst="1.1.1.2") /
223                   UDP(sport=1234, dport=1234) /
224                   Raw(b'\xa5' * 100))
225         self.send_and_expect(self.pg3, p_west * NUM_PKTS, self.pg2)
226
227         #
228         # Use ACLs to test features run on the Pipes
229         #
230         self.vapi.acl_interface_set_acl_list(pipes[1].east,
231                                              0,
232                                              [acl.acl_index])
233         self.send_and_assert_no_replies(self.pg2, p_east * NUM_PKTS)
234         self.send_and_expect(self.pg3, p_west * NUM_PKTS, self.pg2)
235
236         # remove from output and apply on input
237         self.vapi.acl_interface_set_acl_list(pipes[1].east,
238                                              0,
239                                              [])
240         self.vapi.acl_interface_set_acl_list(pipes[1].west,
241                                              1,
242                                              [acl.acl_index])
243         self.send_and_assert_no_replies(self.pg2, p_east * NUM_PKTS)
244         self.send_and_expect(self.pg3, p_west * NUM_PKTS, self.pg2)
245         self.vapi.acl_interface_set_acl_list(pipes[1].west,
246                                              0,
247                                              [])
248         self.send_and_expect(self.pg2, p_east * NUM_PKTS, self.pg3)
249         self.send_and_expect(self.pg3, p_west * NUM_PKTS, self.pg2)
250
251         # cleanup (so the tables delete)
252         self.pg2.unconfig_ip4()
253         self.pg2.set_table_ip4(0)
254         self.pg3.unconfig_ip4()
255         self.pg3.set_table_ip4(0)
256         self.vapi.sw_interface_set_table(pipes[1].west, 0, 0)
257         self.vapi.sw_interface_set_table(pipes[1].east, 0, 0)
258
259
260 if __name__ == '__main__':
261     unittest.main(testRunner=VppTestRunner)