blob: 937a28ef826ccc19967934f372d2f66b5c2b78d0 [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
Jakub Grajciar2f8cd912020-03-27 06:55:06 +01004from ipaddress import IPv4Network
Neale Ranns17ff3c12018-07-04 10:24:24 -07005
6from scapy.packet import Raw
7from scapy.layers.l2 import Ether
8from scapy.layers.inet import IP, UDP
9
Paul Vinciguerra38404db2019-05-14 13:35:19 -040010from framework import VppTestCase, VppTestRunner
11from vpp_interface import VppInterface
12from vpp_ip_route import VppIpTable, VppIpRoute, VppRoutePath
Jakub Grajciar2f8cd912020-03-27 06:55:06 +010013from vpp_acl import AclRule, VppAcl, VppAclInterface
Paul Vinciguerra38404db2019-05-14 13:35:19 -040014
Paul Vinciguerra4271c972019-05-14 13:25:49 -040015NUM_PKTS = 67
16
Neale Ranns17ff3c12018-07-04 10:24:24 -070017
18class VppPipe(VppInterface):
19 """
20 VPP Pipe
21 """
22
23 @property
24 def east(self):
25 return self.result.pipe_sw_if_index[1]
26
27 @property
28 def west(self):
29 return self.result.pipe_sw_if_index[0]
30
31 def __init__(self, test, instance=0xffffffff):
32 super(VppPipe, self).__init__(test)
33 self._test = test
34 self.instance = instance
35
36 def add_vpp_config(self):
37 self.result = self._test.vapi.pipe_create(
38 0 if self.instance == 0xffffffff else 1,
39 self.instance)
Neale Ranns208c29a2018-04-11 08:08:30 -070040 self.set_sw_if_index(self.result.sw_if_index)
Neale Ranns17ff3c12018-07-04 10:24:24 -070041
42 def remove_vpp_config(self):
43 self._test.vapi.pipe_delete(
Neale Ranns208c29a2018-04-11 08:08:30 -070044 self.result.sw_if_index)
Neale Ranns17ff3c12018-07-04 10:24:24 -070045
Neale Ranns17ff3c12018-07-04 10:24:24 -070046 def object_id(self):
47 return "pipe-%d" % (self._sw_if_index)
48
49 def query_vpp_config(self):
50 pipes = self._test.vapi.pipe_dump()
51 for p in pipes:
Neale Ranns208c29a2018-04-11 08:08:30 -070052 if p.sw_if_index == self.result.sw_if_index:
Neale Ranns17ff3c12018-07-04 10:24:24 -070053 return True
54 return False
55
Stanislav Zaikin328b5da2021-07-15 16:27:29 +020056 def set_unnumbered(self, ip_sw_if_index, is_east, is_add=True):
57 if is_east:
58 res = self._test.vapi.sw_interface_set_unnumbered(
59 ip_sw_if_index, self.east, is_add)
60 else:
61 res = self._test.vapi.sw_interface_set_unnumbered(
62 ip_sw_if_index, self.west, is_add)
Neale Ranns17ff3c12018-07-04 10:24:24 -070063
64
65class TestPipe(VppTestCase):
66 """ Pipes """
67
Paul Vinciguerra7f9b7f92019-03-12 19:23:27 -070068 @classmethod
69 def setUpClass(cls):
70 super(TestPipe, cls).setUpClass()
71
72 @classmethod
73 def tearDownClass(cls):
74 super(TestPipe, cls).tearDownClass()
75
Neale Ranns17ff3c12018-07-04 10:24:24 -070076 def setUp(self):
77 super(TestPipe, self).setUp()
78
79 self.create_pg_interfaces(range(4))
80
81 for i in self.pg_interfaces:
82 i.admin_up()
83
84 def tearDown(self):
85 for i in self.pg_interfaces:
86 i.admin_down()
87
88 super(TestPipe, self).tearDown()
89
90 def test_pipe(self):
91 """ Pipes """
92
Neale Ranns208c29a2018-04-11 08:08:30 -070093 pipes = [VppPipe(self), VppPipe(self, 10)]
Neale Ranns17ff3c12018-07-04 10:24:24 -070094
95 for p in pipes:
96 p.add_vpp_config()
97 p.admin_up()
98
99 #
100 # L2 cross-connect pipe0 east with pg0 and west with pg1
101 #
102 self.vapi.sw_interface_set_l2_xconnect(self.pg0.sw_if_index,
103 pipes[0].east,
104 enable=1)
105 self.vapi.sw_interface_set_l2_xconnect(pipes[0].east,
106 self.pg0.sw_if_index,
107 enable=1)
108 self.vapi.sw_interface_set_l2_xconnect(self.pg1.sw_if_index,
109 pipes[0].west,
110 enable=1)
111 self.vapi.sw_interface_set_l2_xconnect(pipes[0].west,
112 self.pg1.sw_if_index,
113 enable=1)
114
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700115 # test bi-directional L2 flow pg0<->pg1
Neale Ranns17ff3c12018-07-04 10:24:24 -0700116 p = (Ether(src=self.pg0.remote_mac,
117 dst=self.pg1.remote_mac) /
118 IP(src="1.1.1.1",
119 dst="1.1.1.2") /
120 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +0100121 Raw(b'\xa5' * 100))
Neale Ranns17ff3c12018-07-04 10:24:24 -0700122
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400123 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1)
124 self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0)
Neale Ranns17ff3c12018-07-04 10:24:24 -0700125
126 #
127 # Attach ACL to ensure features are run on the pipe
128 #
Jakub Grajciar2f8cd912020-03-27 06:55:06 +0100129 rule_1 = AclRule(is_permit=0, proto=17,
130 src_prefix=IPv4Network("1.1.1.1/32"),
131 dst_prefix=IPv4Network("1.1.1.2/32"), ports=1234)
132 acl = VppAcl(self, rules=[rule_1])
133 acl.add_vpp_config()
Neale Ranns17ff3c12018-07-04 10:24:24 -0700134
135 # Apply the ACL on the pipe on output
Jakub Grajciar2f8cd912020-03-27 06:55:06 +0100136 acl_if_e = VppAclInterface(self, sw_if_index=pipes[0].east, n_input=0,
137 acls=[acl])
138 acl_if_e.add_vpp_config()
139
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400140 self.send_and_assert_no_replies(self.pg0, p * NUM_PKTS)
141 self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0)
Neale Ranns17ff3c12018-07-04 10:24:24 -0700142
143 # remove from output and apply on input
Jakub Grajciar2f8cd912020-03-27 06:55:06 +0100144 acl_if_e.remove_vpp_config()
145 acl_if_w = VppAclInterface(self, sw_if_index=pipes[0].west, n_input=1,
146 acls=[acl])
147 acl_if_w.add_vpp_config()
148
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400149 self.send_and_assert_no_replies(self.pg0, p * NUM_PKTS)
150 self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0)
Jakub Grajciar2f8cd912020-03-27 06:55:06 +0100151
152 acl_if_w.remove_vpp_config()
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400153 self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1)
154 self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0)
Neale Ranns17ff3c12018-07-04 10:24:24 -0700155
156 #
157 # L3 routes in two separate tables so a pipe can be used to L3
158 # x-connect
159 #
160 tables = []
161 tables.append(VppIpTable(self, 1))
162 tables.append(VppIpTable(self, 2))
163
164 for t in tables:
165 t.add_vpp_config()
166
167 self.pg2.set_table_ip4(1)
168 self.pg2.config_ip4()
169 self.pg2.resolve_arp()
170 self.pg3.set_table_ip4(2)
171 self.pg3.config_ip4()
172 self.pg3.resolve_arp()
173
174 routes = []
175 routes.append(VppIpRoute(self, "1.1.1.1", 32,
176 [VppRoutePath(self.pg3.remote_ip4,
177 self.pg3.sw_if_index)],
178 table_id=2))
179 routes.append(VppIpRoute(self, "1.1.1.1", 32,
180 [VppRoutePath("0.0.0.0", pipes[1].east)],
181 table_id=1))
182 routes.append(VppIpRoute(self, "1.1.1.2", 32,
183 [VppRoutePath("0.0.0.0", pipes[1].west)],
184 table_id=2))
185 routes.append(VppIpRoute(self, "1.1.1.2", 32,
186 [VppRoutePath(self.pg2.remote_ip4,
187 self.pg2.sw_if_index)],
188 table_id=1))
189
190 for r in routes:
191 r.add_vpp_config()
192
193 p_east = (Ether(src=self.pg2.remote_mac,
194 dst=self.pg2.local_mac) /
195 IP(src="1.1.1.2",
196 dst="1.1.1.1") /
197 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +0100198 Raw(b'\xa5' * 100))
Neale Ranns17ff3c12018-07-04 10:24:24 -0700199
200 # bind the pipe ends to the correct tables
201 self.vapi.sw_interface_set_table(pipes[1].west, 0, 2)
202 self.vapi.sw_interface_set_table(pipes[1].east, 0, 1)
203
204 # IP is not enabled on the pipes at this point
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400205 self.send_and_assert_no_replies(self.pg2, p_east * NUM_PKTS)
Neale Ranns17ff3c12018-07-04 10:24:24 -0700206
207 # IP enable the Pipes by making them unnumbered
Stanislav Zaikin328b5da2021-07-15 16:27:29 +0200208 pipes[1].set_unnumbered(self.pg2.sw_if_index, True)
209 pipes[1].set_unnumbered(self.pg3.sw_if_index, False)
Neale Ranns17ff3c12018-07-04 10:24:24 -0700210
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400211 self.send_and_expect(self.pg2, p_east * NUM_PKTS, self.pg3)
Neale Ranns17ff3c12018-07-04 10:24:24 -0700212
213 # and the return path
214 p_west = (Ether(src=self.pg3.remote_mac,
215 dst=self.pg3.local_mac) /
216 IP(src="1.1.1.1",
217 dst="1.1.1.2") /
218 UDP(sport=1234, dport=1234) /
Ole Troan770a0de2019-11-07 13:52:21 +0100219 Raw(b'\xa5' * 100))
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400220 self.send_and_expect(self.pg3, p_west * NUM_PKTS, self.pg2)
Neale Ranns17ff3c12018-07-04 10:24:24 -0700221
222 #
223 # Use ACLs to test features run on the Pipes
224 #
Jakub Grajciar2f8cd912020-03-27 06:55:06 +0100225 acl_if_e1 = VppAclInterface(self, sw_if_index=pipes[1].east, n_input=0,
226 acls=[acl])
227 acl_if_e1.add_vpp_config()
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400228 self.send_and_assert_no_replies(self.pg2, p_east * NUM_PKTS)
229 self.send_and_expect(self.pg3, p_west * NUM_PKTS, self.pg2)
Neale Ranns17ff3c12018-07-04 10:24:24 -0700230
231 # remove from output and apply on input
Jakub Grajciar2f8cd912020-03-27 06:55:06 +0100232 acl_if_e1.remove_vpp_config()
233 acl_if_w1 = VppAclInterface(self, sw_if_index=pipes[1].west, n_input=1,
234 acls=[acl])
235 acl_if_w1.add_vpp_config()
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400236 self.send_and_assert_no_replies(self.pg2, p_east * NUM_PKTS)
237 self.send_and_expect(self.pg3, p_west * NUM_PKTS, self.pg2)
Jakub Grajciar2f8cd912020-03-27 06:55:06 +0100238 acl_if_w1.remove_vpp_config()
239
Paul Vinciguerra4271c972019-05-14 13:25:49 -0400240 self.send_and_expect(self.pg2, p_east * NUM_PKTS, self.pg3)
241 self.send_and_expect(self.pg3, p_west * NUM_PKTS, self.pg2)
Neale Ranns17ff3c12018-07-04 10:24:24 -0700242
243 # cleanup (so the tables delete)
244 self.pg2.unconfig_ip4()
245 self.pg2.set_table_ip4(0)
246 self.pg3.unconfig_ip4()
247 self.pg3.set_table_ip4(0)
248 self.vapi.sw_interface_set_table(pipes[1].west, 0, 0)
249 self.vapi.sw_interface_set_table(pipes[1].east, 0, 0)
250
251
252if __name__ == '__main__':
253 unittest.main(testRunner=VppTestRunner)