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