blob: 2d3c1ecd24cec88bb955b4abe8e0468c6f58e5da [file] [log] [blame]
Neale Ranns17ff3c12018-07-04 10:24:24 -07001#!/usr/bin/env python
2from socket import AF_INET, AF_INET6, inet_pton
3
4from framework import VppTestCase, VppTestRunner
5from vpp_interface import VppInterface
6from vpp_ip_route import VppIpTable, VppIpRoute, VppRoutePath
7
8from scapy.packet import Raw
9from scapy.layers.l2 import Ether
10from scapy.layers.inet import IP, UDP
11
12
13class 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)
Neale Ranns208c29a2018-04-11 08:08:30 -070035 self.set_sw_if_index(self.result.sw_if_index)
Neale Ranns17ff3c12018-07-04 10:24:24 -070036
37 def remove_vpp_config(self):
38 self._test.vapi.pipe_delete(
Neale Ranns208c29a2018-04-11 08:08:30 -070039 self.result.sw_if_index)
Neale Ranns17ff3c12018-07-04 10:24:24 -070040
Neale Ranns17ff3c12018-07-04 10:24:24 -070041 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:
Neale Ranns208c29a2018-04-11 08:08:30 -070047 if p.sw_if_index == self.result.sw_if_index:
Neale Ranns17ff3c12018-07-04 10:24:24 -070048 return True
49 return False
50
51 def set_unnumbered(self, ip_sw_if_index, is_add=True):
Ole Troan9a475372019-03-05 16:58:24 +010052 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)
Neale Ranns17ff3c12018-07-04 10:24:24 -070056
57
58class TestPipe(VppTestCase):
59 """ Pipes """
60
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070061 @classmethod
62 def setUpClass(cls):
63 super(TestPipe, cls).setUpClass()
64
65 @classmethod
66 def tearDownClass(cls):
67 super(TestPipe, cls).tearDownClass()
68
Neale Ranns17ff3c12018-07-04 10:24:24 -070069 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
Neale Ranns208c29a2018-04-11 08:08:30 -070086 pipes = [VppPipe(self), VppPipe(self, 10)]
Neale Ranns17ff3c12018-07-04 10:24:24 -070087
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
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700108 # test bi-directional L2 flow pg0<->pg1
Neale Ranns17ff3c12018-07-04 10:24:24 -0700109 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
257if __name__ == '__main__':
258 unittest.main(testRunner=VppTestRunner)