blob: 50fd8bcb00a9be150bfd4f2eac9003cc6a306f02 [file] [log] [blame]
Daniele Moro7c31a3b2021-06-15 20:53:22 +02001/*
2 * Copyright 2021-present Open Networking Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.onosproject.pipelines.fabric.impl.behaviour.upf;
18
19import com.google.common.collect.ImmutableList;
20import org.junit.Before;
21import org.junit.Test;
22import org.onlab.junit.TestUtils;
23import org.onlab.util.HexString;
24import org.onosproject.TestApplicationId;
25import org.onosproject.core.ApplicationId;
26import org.onosproject.core.CoreService;
27import org.onosproject.net.DeviceId;
28import org.onosproject.net.PortNumber;
29import org.onosproject.net.behaviour.upf.ForwardingActionRule;
30import org.onosproject.net.behaviour.upf.PacketDetectionRule;
31import org.onosproject.net.behaviour.upf.PdrStats;
32import org.onosproject.net.behaviour.upf.UpfInterface;
33import org.onosproject.net.config.NetworkConfigService;
34import org.onosproject.net.config.basics.BasicDeviceConfig;
35import org.onosproject.net.device.DeviceService;
36import org.onosproject.net.driver.DriverData;
37import org.onosproject.net.driver.DriverHandler;
38import org.onosproject.net.flow.DefaultTrafficTreatment;
39import org.onosproject.net.flow.FlowRuleService;
40import org.onosproject.net.flow.TrafficTreatment;
41import org.onosproject.net.packet.PacketService;
42import org.onosproject.net.pi.model.PiCounterModel;
43import org.onosproject.net.pi.model.PiTableModel;
44import org.onosproject.net.pi.service.PiPipeconfService;
45import org.onosproject.net.pi.service.PiTranslationService;
46import org.onosproject.p4runtime.api.P4RuntimeController;
47import org.onosproject.pipelines.fabric.impl.FabricPipeconfLoader;
48import org.onosproject.pipelines.fabric.impl.behaviour.FabricCapabilities;
49
50import java.net.URI;
51import java.nio.ByteBuffer;
52import java.util.Collection;
53import java.util.List;
54import java.util.concurrent.ConcurrentMap;
55
56import static junit.framework.TestCase.assertNotNull;
57import static junit.framework.TestCase.assertTrue;
58import static org.easymock.EasyMock.anyString;
59import static org.easymock.EasyMock.createMock;
60import static org.easymock.EasyMock.expect;
61import static org.easymock.EasyMock.replay;
62import static org.hamcrest.MatcherAssert.assertThat;
63import static org.hamcrest.Matchers.equalTo;
64import static org.onosproject.pipelines.fabric.FabricConstants.FABRIC_EGRESS_SPGW_PDR_COUNTER;
65import static org.onosproject.pipelines.fabric.FabricConstants.FABRIC_INGRESS_SPGW_DOWNLINK_PDRS;
66import static org.onosproject.pipelines.fabric.FabricConstants.FABRIC_INGRESS_SPGW_FARS;
67import static org.onosproject.pipelines.fabric.FabricConstants.FABRIC_INGRESS_SPGW_PDR_COUNTER;
68import static org.onosproject.pipelines.fabric.FabricConstants.FABRIC_INGRESS_SPGW_UPLINK_PDRS;
69
70public class FabricUpfProgrammableTest {
71
72 private static final ApplicationId APP_ID =
73 TestApplicationId.create(FabricPipeconfLoader.PIPELINE_APP_NAME);
74
75 private final DistributedFabricUpfStore upfStore = TestDistributedFabricUpfStore.build();
76 private MockPacketService packetService;
77 private FabricUpfProgrammable upfProgrammable;
78
79 // Bytes of a random but valid Ethernet frame.
80 private static final byte[] ETH_FRAME_BYTES = HexString.fromHexString(
81 "00060708090a0001020304058100000a08004500006a000100004011f92ec0a80001c0a8000204d2005" +
82 "00056a8d5000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20" +
83 "2122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f4041424344454" +
84 "64748494a4b4c4d", "");
85 private static final TrafficTreatment TABLE_OUTPUT_TREATMENT = DefaultTrafficTreatment.builder()
86 .setOutput(PortNumber.TABLE)
87 .build();
88
89 private static final List<PiTableModel> TABLE_MODELS = ImmutableList.of(
90 new MockTableModel(FABRIC_INGRESS_SPGW_UPLINK_PDRS,
91 TestUpfConstants.PHYSICAL_MAX_PDRS / 2),
92 new MockTableModel(FABRIC_INGRESS_SPGW_DOWNLINK_PDRS,
93 TestUpfConstants.PHYSICAL_MAX_PDRS / 2),
94 new MockTableModel(FABRIC_INGRESS_SPGW_FARS,
95 TestUpfConstants.PHYSICAL_MAX_FARS)
96 );
97 private static final List<PiCounterModel> COUNTER_MODELS = ImmutableList.of(
98 new MockCounterModel(FABRIC_INGRESS_SPGW_PDR_COUNTER,
99 TestUpfConstants.PHYSICAL_COUNTER_SIZE),
100 new MockCounterModel(FABRIC_EGRESS_SPGW_PDR_COUNTER,
101 TestUpfConstants.PHYSICAL_COUNTER_SIZE)
102 );
103
104 @Before
105 public void setUp() throws Exception {
106 FabricCapabilities capabilities = createMock(FabricCapabilities.class);
107 expect(capabilities.supportUpf()).andReturn(true).anyTimes();
108 replay(capabilities);
109
110 // Services mock
111 packetService = new MockPacketService();
112 CoreService coreService = createMock(CoreService.class);
113 NetworkConfigService netcfgService = createMock(NetworkConfigService.class);
114 DeviceService deviceService = createMock(DeviceService.class);
115 PiTranslationService piTranslationService = createMock(PiTranslationService.class);
116 expect(coreService.getAppId(anyString())).andReturn(APP_ID).anyTimes();
117 expect(netcfgService.getConfig(TestUpfConstants.DEVICE_ID, BasicDeviceConfig.class))
118 .andReturn(TestUpfUtils.getBasicConfig(TestUpfConstants.DEVICE_ID, "/basic.json"))
119 .anyTimes();
120 replay(coreService, netcfgService);
121
122 // Mock driverData to get the right device ID
123 DriverData driverData = createMock(DriverData.class);
124 expect(driverData.deviceId()).andReturn(TestUpfConstants.DEVICE_ID).anyTimes();
125 replay(driverData);
126
127 // Mock DriverHandler to get all the required mocked services
128 DriverHandler driverHandler = createMock(DriverHandler.class);
129 expect(driverHandler.get(FlowRuleService.class)).andReturn(new MockFlowRuleService()).anyTimes();
130 expect(driverHandler.get(PacketService.class)).andReturn(packetService).anyTimes();
131 expect(driverHandler.get(FabricUpfStore.class)).andReturn(upfStore).anyTimes();
132 expect(driverHandler.get(NetworkConfigService.class)).andReturn(netcfgService).anyTimes();
133 expect(driverHandler.get(CoreService.class)).andReturn(coreService).anyTimes();
134 expect(driverHandler.get(DeviceService.class)).andReturn(deviceService).anyTimes();
135 expect(driverHandler.get(PiTranslationService.class)).andReturn(piTranslationService).anyTimes();
136 expect(driverHandler.get(PiPipeconfService.class))
137 .andReturn(new MockPiPipeconfService(TABLE_MODELS, COUNTER_MODELS))
138 .anyTimes();
139 expect(driverHandler.get(P4RuntimeController.class))
140 .andReturn(new MockP4RuntimeController(TestUpfConstants.DEVICE_ID,
141 TestUpfConstants.COUNTER_PKTS,
142 TestUpfConstants.COUNTER_BYTES,
143 TestUpfConstants.PHYSICAL_COUNTER_SIZE))
144 .anyTimes();
145 expect(driverHandler.data()).andReturn(driverData).anyTimes();
146 replay(driverHandler);
147
148 upfProgrammable = new FabricUpfProgrammable();
149 TestUtils.setField(upfProgrammable, "handler", driverHandler);
150 TestUtils.setField(upfProgrammable, "data", driverData);
151 ConcurrentMap<DeviceId, URI> channelUris = TestUtils.getField(upfProgrammable, "CHANNEL_URIS");
152 channelUris.put(TestUpfConstants.DEVICE_ID, new URI("grpc://localhost:1234?device_id=1"));
153 }
154
155 @Test
156 public void testUplinkPdr() throws Exception {
157 assertTrue(upfProgrammable.getPdrs().isEmpty());
158 PacketDetectionRule expectedPdr = TestUpfConstants.UPLINK_PDR;
159 upfProgrammable.addPdr(expectedPdr);
160 Collection<PacketDetectionRule> installedPdrs = upfProgrammable.getPdrs();
161 assertThat(installedPdrs.size(), equalTo(1));
162 for (var readPdr : installedPdrs) {
163 assertThat(readPdr, equalTo(expectedPdr));
164 }
165 upfProgrammable.removePdr(expectedPdr.withoutActionParams());
166 assertTrue(upfProgrammable.getPdrs().isEmpty());
167 }
168
169 @Test
170 public void testDownlinkPdr() throws Exception {
171 assertTrue(upfProgrammable.getPdrs().isEmpty());
172 PacketDetectionRule expectedPdr = TestUpfConstants.DOWNLINK_PDR;
173 upfProgrammable.addPdr(expectedPdr);
174 Collection<PacketDetectionRule> installedPdrs = upfProgrammable.getPdrs();
175 assertThat(installedPdrs.size(), equalTo(1));
176 for (var readPdr : installedPdrs) {
177 assertThat(readPdr, equalTo(expectedPdr));
178 }
179 upfProgrammable.removePdr(expectedPdr.withoutActionParams());
180 assertTrue(upfProgrammable.getPdrs().isEmpty());
181 }
182
183 @Test
184 public void testUplinkFar() throws Exception {
185 assertTrue(upfProgrammable.getFars().isEmpty());
186 ForwardingActionRule expectedFar = TestUpfConstants.UPLINK_FAR;
187 upfProgrammable.addFar(expectedFar);
188 Collection<ForwardingActionRule> installedFars = upfProgrammable.getFars();
189 assertThat(installedFars.size(), equalTo(1));
190 for (var readFar : installedFars) {
191 assertThat(readFar, equalTo(expectedFar));
192 }
193 upfProgrammable.removeFar(expectedFar.withoutActionParams());
194 assertTrue(upfProgrammable.getFars().isEmpty());
195 }
196
197 @Test
198 public void testDownlinkFar() throws Exception {
199 assertTrue(upfProgrammable.getFars().isEmpty());
200 ForwardingActionRule expectedFar = TestUpfConstants.DOWNLINK_FAR;
201 upfProgrammable.addFar(expectedFar);
202 Collection<ForwardingActionRule> installedFars = upfProgrammable.getFars();
203 assertThat(installedFars.size(), equalTo(1));
204 for (var readFar : installedFars) {
205 assertThat(readFar, equalTo(expectedFar));
206 }
207 upfProgrammable.removeFar(expectedFar.withoutActionParams());
208 assertTrue(upfProgrammable.getFars().isEmpty());
209 }
210
211 @Test
212 public void testUplinkInterface() throws Exception {
213 assertTrue(upfProgrammable.getInterfaces().isEmpty());
214 UpfInterface expectedInterface = TestUpfConstants.UPLINK_INTERFACE;
215 upfProgrammable.addInterface(expectedInterface);
216 Collection<UpfInterface> installedInterfaces = upfProgrammable.getInterfaces();
217 assertThat(installedInterfaces.size(), equalTo(1));
218 for (var readInterface : installedInterfaces) {
219 assertThat(readInterface, equalTo(expectedInterface));
220 }
221 upfProgrammable.removeInterface(expectedInterface);
222 assertTrue(upfProgrammable.getInterfaces().isEmpty());
223 }
224
225 @Test
226 public void testDownlinkInterface() throws Exception {
227 assertTrue(upfProgrammable.getInterfaces().isEmpty());
228 UpfInterface expectedInterface = TestUpfConstants.DOWNLINK_INTERFACE;
229 upfProgrammable.addInterface(expectedInterface);
230 Collection<UpfInterface> installedInterfaces = upfProgrammable.getInterfaces();
231 assertThat(installedInterfaces.size(), equalTo(1));
232 for (var readInterface : installedInterfaces) {
233 assertThat(readInterface, equalTo(expectedInterface));
234 }
235 upfProgrammable.removeInterface(expectedInterface);
236 assertTrue(upfProgrammable.getInterfaces().isEmpty());
237 }
238
239 @Test
240 public void testClearInterfaces() throws Exception {
241 assertTrue(upfProgrammable.getInterfaces().isEmpty());
242 upfProgrammable.addInterface(TestUpfConstants.UPLINK_INTERFACE);
243 upfProgrammable.addInterface(TestUpfConstants.DOWNLINK_INTERFACE);
244 assertThat(upfProgrammable.getInterfaces().size(), equalTo(2));
245 upfProgrammable.clearInterfaces();
246 assertTrue(upfProgrammable.getInterfaces().isEmpty());
247 }
248
249 @Test
250 public void testReadAllCounters() {
251 Collection<PdrStats> allStats = upfProgrammable.readAllCounters(-1);
252 assertThat(allStats.size(), equalTo(TestUpfConstants.PHYSICAL_COUNTER_SIZE));
253 for (PdrStats stat : allStats) {
254 assertThat(stat.getIngressBytes(), equalTo(TestUpfConstants.COUNTER_BYTES));
255 assertThat(stat.getEgressBytes(), equalTo(TestUpfConstants.COUNTER_BYTES));
256 assertThat(stat.getIngressPkts(), equalTo(TestUpfConstants.COUNTER_PKTS));
257 assertThat(stat.getEgressPkts(), equalTo(TestUpfConstants.COUNTER_PKTS));
258 }
259 }
260
261 @Test
262 public void testReadAllCountersLimitedCounters() {
263 Collection<PdrStats> allStats = upfProgrammable.readAllCounters(10);
264 assertThat(allStats.size(), equalTo(10));
265 }
266
267 @Test
268 public void testReadAllCountersPhysicalLimit() {
269 Collection<PdrStats> allStats = upfProgrammable.readAllCounters(1024);
270 assertThat(allStats.size(), equalTo(TestUpfConstants.PHYSICAL_COUNTER_SIZE));
271 }
272
273 @Test
274 public void testSendPacketOut() {
275 upfProgrammable.sendPacketOut(ByteBuffer.wrap(ETH_FRAME_BYTES));
276 var emittedPkt = packetService.emittedPackets.poll();
277 assertNotNull(emittedPkt);
278 assertThat(emittedPkt.data().array(), equalTo(ETH_FRAME_BYTES));
279 assertThat(emittedPkt.treatment(), equalTo(TABLE_OUTPUT_TREATMENT));
280 }
281}