blob: 6e3edca3c500cd44c41cf32cfefd64dcab9e48cf [file] [log] [blame]
Renato Botelho do Coutoead1e532019-10-31 13:31:07 -05001#!/usr/bin/env python3
Neale Ranns17ff3c12018-07-04 10:24:24 -07002from socket import AF_INET, AF_INET6, inet_pton
Paul Vinciguerra38404db2019-05-14 13:35:19 -04003import unittest
Neale Ranns17ff3c12018-07-04 10:24:24 -07004
5from scapy.packet import Raw
6from scapy.layers.l2 import Ether
7from scapy.layers.inet import IP, UDP
8
Paul Vinciguerra38404db2019-05-14 13:35:19 -04009from framework import VppTestCase, VppTestRunner
10from vpp_interface import VppInterface
11from vpp_ip_route import VppIpTable, VppIpRoute, VppRoutePath
12
Paul Vinciguerra4271c972019-05-14 13:25:49 -040013NUM_PKTS = 67
14
Neale Ranns17ff3c12018-07-04 10:24:24 -070015
16class 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)
Neale Ranns208c29a2018-04-11 08:08:30 -070038 self.set_sw_if_index(self.result.sw_if_index)
Neale Ranns17ff3c12018-07-04 10:24:24 -070039
40 def remove_vpp_config(self):
41 self._test.vapi.pipe_delete(
Neale Ranns208c29a2018-04-11 08:08:30 -070042 self.result.sw_if_index)
Neale Ranns17ff3c12018-07-04 10:24:24 -070043
Neale Ranns17ff3c12018-07-04 10:24:24 -070044 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:
Neale Ranns208c29a2018-04-11 08:08:30 -070050 if p.sw_if_index == self.result.sw_if_index:
Neale Ranns17ff3c12018-07-04 10:24:24 -070051 return True
52 return False
53
54 def set_unnumbered(self, ip_sw_if_index, is_add=True):
Ole Troan9a475372019-03-05 16:58:24 +010055 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)
Neale Ranns17ff3c12018-07-04 10:24:24 -070059
60
61class TestPipe(VppTestCase):
62 """ Pipes """
63
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070064 @classmethod
65 def setUpClass(cls):
66 super(TestPipe, cls).setUpClass()
67
68 @classmethod
69 def tearDownClass(cls):
70 super(TestPipe, cls).tearDownClass()
71
Neale Ranns17ff3c12018-07-04 10:24:24 -070072 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
Neale Ranns208c29a2018-04-11 08:08:30 -070089 pipes = [VppPipe(self), VppPipe(self, 10)]
Neale Ranns17ff3c12018-07-04 10:24:24 -070090
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
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700111 # test bi-directional L2 flow pg0<->pg1
Neale Ranns17ff3c12018-07-04 10:24:24 -0700112 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) /
Ole Troan770a0de2019-11-07 13:52:21 +0100117 Raw(b'\xa5' * 100))
Neale Ranns17ff3c12018-07-04 10:24:24 -0700118
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400119 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1)
120 self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0)
Neale Ranns17ff3c12018-07-04 10:24:24 -0700121
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])
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400143 self.send_and_assert_no_replies(self.pg0, p * NUM_PKTS)
144 self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0)
Neale Ranns17ff3c12018-07-04 10:24:24 -0700145
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])
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400153 self.send_and_assert_no_replies(self.pg0, p * NUM_PKTS)
154 self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0)
Neale Ranns17ff3c12018-07-04 10:24:24 -0700155 self.vapi.acl_interface_set_acl_list(pipes[0].west,
156 0,
157 [])
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400158 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1)
159 self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0)
Neale Ranns17ff3c12018-07-04 10:24:24 -0700160
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) /
Ole Troan770a0de2019-11-07 13:52:21 +0100203 Raw(b'\xa5' * 100))
Neale Ranns17ff3c12018-07-04 10:24:24 -0700204
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
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400210 self.send_and_assert_no_replies(self.pg2, p_east * NUM_PKTS)
Neale Ranns17ff3c12018-07-04 10:24:24 -0700211
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
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400216 self.send_and_expect(self.pg2, p_east * NUM_PKTS, self.pg3)
Neale Ranns17ff3c12018-07-04 10:24:24 -0700217
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) /
Ole Troan770a0de2019-11-07 13:52:21 +0100224 Raw(b'\xa5' * 100))
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400225 self.send_and_expect(self.pg3, p_west * NUM_PKTS, self.pg2)
Neale Ranns17ff3c12018-07-04 10:24:24 -0700226
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])
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400233 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)
Neale Ranns17ff3c12018-07-04 10:24:24 -0700235
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])
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400243 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)
Neale Ranns17ff3c12018-07-04 10:24:24 -0700245 self.vapi.acl_interface_set_acl_list(pipes[1].west,
246 0,
247 [])
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400248 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)
Neale Ranns17ff3c12018-07-04 10:24:24 -0700250
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
260if __name__ == '__main__':
261 unittest.main(testRunner=VppTestRunner)