[SDFAB-189] UpfProgrammable implementation for fabric v1model
Change-Id: I4ea7980830d761a0da8a78943c08229c2da9410d
(cherry picked from commit 8d630f1091c63ff6e7b4ea31669344c5274773cc)
diff --git a/pipelines/fabric/impl/src/test/java/org/onosproject/pipelines/fabric/impl/behaviour/upf/FabricUpfProgrammableTest.java b/pipelines/fabric/impl/src/test/java/org/onosproject/pipelines/fabric/impl/behaviour/upf/FabricUpfProgrammableTest.java
new file mode 100644
index 0000000..50fd8bc
--- /dev/null
+++ b/pipelines/fabric/impl/src/test/java/org/onosproject/pipelines/fabric/impl/behaviour/upf/FabricUpfProgrammableTest.java
@@ -0,0 +1,281 @@
+/*
+ * Copyright 2021-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.pipelines.fabric.impl.behaviour.upf;
+
+import com.google.common.collect.ImmutableList;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.junit.TestUtils;
+import org.onlab.util.HexString;
+import org.onosproject.TestApplicationId;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.behaviour.upf.ForwardingActionRule;
+import org.onosproject.net.behaviour.upf.PacketDetectionRule;
+import org.onosproject.net.behaviour.upf.PdrStats;
+import org.onosproject.net.behaviour.upf.UpfInterface;
+import org.onosproject.net.config.NetworkConfigService;
+import org.onosproject.net.config.basics.BasicDeviceConfig;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.driver.DriverData;
+import org.onosproject.net.driver.DriverHandler;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.FlowRuleService;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.packet.PacketService;
+import org.onosproject.net.pi.model.PiCounterModel;
+import org.onosproject.net.pi.model.PiTableModel;
+import org.onosproject.net.pi.service.PiPipeconfService;
+import org.onosproject.net.pi.service.PiTranslationService;
+import org.onosproject.p4runtime.api.P4RuntimeController;
+import org.onosproject.pipelines.fabric.impl.FabricPipeconfLoader;
+import org.onosproject.pipelines.fabric.impl.behaviour.FabricCapabilities;
+
+import java.net.URI;
+import java.nio.ByteBuffer;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.ConcurrentMap;
+
+import static junit.framework.TestCase.assertNotNull;
+import static junit.framework.TestCase.assertTrue;
+import static org.easymock.EasyMock.anyString;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.equalTo;
+import static org.onosproject.pipelines.fabric.FabricConstants.FABRIC_EGRESS_SPGW_PDR_COUNTER;
+import static org.onosproject.pipelines.fabric.FabricConstants.FABRIC_INGRESS_SPGW_DOWNLINK_PDRS;
+import static org.onosproject.pipelines.fabric.FabricConstants.FABRIC_INGRESS_SPGW_FARS;
+import static org.onosproject.pipelines.fabric.FabricConstants.FABRIC_INGRESS_SPGW_PDR_COUNTER;
+import static org.onosproject.pipelines.fabric.FabricConstants.FABRIC_INGRESS_SPGW_UPLINK_PDRS;
+
+public class FabricUpfProgrammableTest {
+
+ private static final ApplicationId APP_ID =
+ TestApplicationId.create(FabricPipeconfLoader.PIPELINE_APP_NAME);
+
+ private final DistributedFabricUpfStore upfStore = TestDistributedFabricUpfStore.build();
+ private MockPacketService packetService;
+ private FabricUpfProgrammable upfProgrammable;
+
+ // Bytes of a random but valid Ethernet frame.
+ private static final byte[] ETH_FRAME_BYTES = HexString.fromHexString(
+ "00060708090a0001020304058100000a08004500006a000100004011f92ec0a80001c0a8000204d2005" +
+ "00056a8d5000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20" +
+ "2122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f4041424344454" +
+ "64748494a4b4c4d", "");
+ private static final TrafficTreatment TABLE_OUTPUT_TREATMENT = DefaultTrafficTreatment.builder()
+ .setOutput(PortNumber.TABLE)
+ .build();
+
+ private static final List<PiTableModel> TABLE_MODELS = ImmutableList.of(
+ new MockTableModel(FABRIC_INGRESS_SPGW_UPLINK_PDRS,
+ TestUpfConstants.PHYSICAL_MAX_PDRS / 2),
+ new MockTableModel(FABRIC_INGRESS_SPGW_DOWNLINK_PDRS,
+ TestUpfConstants.PHYSICAL_MAX_PDRS / 2),
+ new MockTableModel(FABRIC_INGRESS_SPGW_FARS,
+ TestUpfConstants.PHYSICAL_MAX_FARS)
+ );
+ private static final List<PiCounterModel> COUNTER_MODELS = ImmutableList.of(
+ new MockCounterModel(FABRIC_INGRESS_SPGW_PDR_COUNTER,
+ TestUpfConstants.PHYSICAL_COUNTER_SIZE),
+ new MockCounterModel(FABRIC_EGRESS_SPGW_PDR_COUNTER,
+ TestUpfConstants.PHYSICAL_COUNTER_SIZE)
+ );
+
+ @Before
+ public void setUp() throws Exception {
+ FabricCapabilities capabilities = createMock(FabricCapabilities.class);
+ expect(capabilities.supportUpf()).andReturn(true).anyTimes();
+ replay(capabilities);
+
+ // Services mock
+ packetService = new MockPacketService();
+ CoreService coreService = createMock(CoreService.class);
+ NetworkConfigService netcfgService = createMock(NetworkConfigService.class);
+ DeviceService deviceService = createMock(DeviceService.class);
+ PiTranslationService piTranslationService = createMock(PiTranslationService.class);
+ expect(coreService.getAppId(anyString())).andReturn(APP_ID).anyTimes();
+ expect(netcfgService.getConfig(TestUpfConstants.DEVICE_ID, BasicDeviceConfig.class))
+ .andReturn(TestUpfUtils.getBasicConfig(TestUpfConstants.DEVICE_ID, "/basic.json"))
+ .anyTimes();
+ replay(coreService, netcfgService);
+
+ // Mock driverData to get the right device ID
+ DriverData driverData = createMock(DriverData.class);
+ expect(driverData.deviceId()).andReturn(TestUpfConstants.DEVICE_ID).anyTimes();
+ replay(driverData);
+
+ // Mock DriverHandler to get all the required mocked services
+ DriverHandler driverHandler = createMock(DriverHandler.class);
+ expect(driverHandler.get(FlowRuleService.class)).andReturn(new MockFlowRuleService()).anyTimes();
+ expect(driverHandler.get(PacketService.class)).andReturn(packetService).anyTimes();
+ expect(driverHandler.get(FabricUpfStore.class)).andReturn(upfStore).anyTimes();
+ expect(driverHandler.get(NetworkConfigService.class)).andReturn(netcfgService).anyTimes();
+ expect(driverHandler.get(CoreService.class)).andReturn(coreService).anyTimes();
+ expect(driverHandler.get(DeviceService.class)).andReturn(deviceService).anyTimes();
+ expect(driverHandler.get(PiTranslationService.class)).andReturn(piTranslationService).anyTimes();
+ expect(driverHandler.get(PiPipeconfService.class))
+ .andReturn(new MockPiPipeconfService(TABLE_MODELS, COUNTER_MODELS))
+ .anyTimes();
+ expect(driverHandler.get(P4RuntimeController.class))
+ .andReturn(new MockP4RuntimeController(TestUpfConstants.DEVICE_ID,
+ TestUpfConstants.COUNTER_PKTS,
+ TestUpfConstants.COUNTER_BYTES,
+ TestUpfConstants.PHYSICAL_COUNTER_SIZE))
+ .anyTimes();
+ expect(driverHandler.data()).andReturn(driverData).anyTimes();
+ replay(driverHandler);
+
+ upfProgrammable = new FabricUpfProgrammable();
+ TestUtils.setField(upfProgrammable, "handler", driverHandler);
+ TestUtils.setField(upfProgrammable, "data", driverData);
+ ConcurrentMap<DeviceId, URI> channelUris = TestUtils.getField(upfProgrammable, "CHANNEL_URIS");
+ channelUris.put(TestUpfConstants.DEVICE_ID, new URI("grpc://localhost:1234?device_id=1"));
+ }
+
+ @Test
+ public void testUplinkPdr() throws Exception {
+ assertTrue(upfProgrammable.getPdrs().isEmpty());
+ PacketDetectionRule expectedPdr = TestUpfConstants.UPLINK_PDR;
+ upfProgrammable.addPdr(expectedPdr);
+ Collection<PacketDetectionRule> installedPdrs = upfProgrammable.getPdrs();
+ assertThat(installedPdrs.size(), equalTo(1));
+ for (var readPdr : installedPdrs) {
+ assertThat(readPdr, equalTo(expectedPdr));
+ }
+ upfProgrammable.removePdr(expectedPdr.withoutActionParams());
+ assertTrue(upfProgrammable.getPdrs().isEmpty());
+ }
+
+ @Test
+ public void testDownlinkPdr() throws Exception {
+ assertTrue(upfProgrammable.getPdrs().isEmpty());
+ PacketDetectionRule expectedPdr = TestUpfConstants.DOWNLINK_PDR;
+ upfProgrammable.addPdr(expectedPdr);
+ Collection<PacketDetectionRule> installedPdrs = upfProgrammable.getPdrs();
+ assertThat(installedPdrs.size(), equalTo(1));
+ for (var readPdr : installedPdrs) {
+ assertThat(readPdr, equalTo(expectedPdr));
+ }
+ upfProgrammable.removePdr(expectedPdr.withoutActionParams());
+ assertTrue(upfProgrammable.getPdrs().isEmpty());
+ }
+
+ @Test
+ public void testUplinkFar() throws Exception {
+ assertTrue(upfProgrammable.getFars().isEmpty());
+ ForwardingActionRule expectedFar = TestUpfConstants.UPLINK_FAR;
+ upfProgrammable.addFar(expectedFar);
+ Collection<ForwardingActionRule> installedFars = upfProgrammable.getFars();
+ assertThat(installedFars.size(), equalTo(1));
+ for (var readFar : installedFars) {
+ assertThat(readFar, equalTo(expectedFar));
+ }
+ upfProgrammable.removeFar(expectedFar.withoutActionParams());
+ assertTrue(upfProgrammable.getFars().isEmpty());
+ }
+
+ @Test
+ public void testDownlinkFar() throws Exception {
+ assertTrue(upfProgrammable.getFars().isEmpty());
+ ForwardingActionRule expectedFar = TestUpfConstants.DOWNLINK_FAR;
+ upfProgrammable.addFar(expectedFar);
+ Collection<ForwardingActionRule> installedFars = upfProgrammable.getFars();
+ assertThat(installedFars.size(), equalTo(1));
+ for (var readFar : installedFars) {
+ assertThat(readFar, equalTo(expectedFar));
+ }
+ upfProgrammable.removeFar(expectedFar.withoutActionParams());
+ assertTrue(upfProgrammable.getFars().isEmpty());
+ }
+
+ @Test
+ public void testUplinkInterface() throws Exception {
+ assertTrue(upfProgrammable.getInterfaces().isEmpty());
+ UpfInterface expectedInterface = TestUpfConstants.UPLINK_INTERFACE;
+ upfProgrammable.addInterface(expectedInterface);
+ Collection<UpfInterface> installedInterfaces = upfProgrammable.getInterfaces();
+ assertThat(installedInterfaces.size(), equalTo(1));
+ for (var readInterface : installedInterfaces) {
+ assertThat(readInterface, equalTo(expectedInterface));
+ }
+ upfProgrammable.removeInterface(expectedInterface);
+ assertTrue(upfProgrammable.getInterfaces().isEmpty());
+ }
+
+ @Test
+ public void testDownlinkInterface() throws Exception {
+ assertTrue(upfProgrammable.getInterfaces().isEmpty());
+ UpfInterface expectedInterface = TestUpfConstants.DOWNLINK_INTERFACE;
+ upfProgrammable.addInterface(expectedInterface);
+ Collection<UpfInterface> installedInterfaces = upfProgrammable.getInterfaces();
+ assertThat(installedInterfaces.size(), equalTo(1));
+ for (var readInterface : installedInterfaces) {
+ assertThat(readInterface, equalTo(expectedInterface));
+ }
+ upfProgrammable.removeInterface(expectedInterface);
+ assertTrue(upfProgrammable.getInterfaces().isEmpty());
+ }
+
+ @Test
+ public void testClearInterfaces() throws Exception {
+ assertTrue(upfProgrammable.getInterfaces().isEmpty());
+ upfProgrammable.addInterface(TestUpfConstants.UPLINK_INTERFACE);
+ upfProgrammable.addInterface(TestUpfConstants.DOWNLINK_INTERFACE);
+ assertThat(upfProgrammable.getInterfaces().size(), equalTo(2));
+ upfProgrammable.clearInterfaces();
+ assertTrue(upfProgrammable.getInterfaces().isEmpty());
+ }
+
+ @Test
+ public void testReadAllCounters() {
+ Collection<PdrStats> allStats = upfProgrammable.readAllCounters(-1);
+ assertThat(allStats.size(), equalTo(TestUpfConstants.PHYSICAL_COUNTER_SIZE));
+ for (PdrStats stat : allStats) {
+ assertThat(stat.getIngressBytes(), equalTo(TestUpfConstants.COUNTER_BYTES));
+ assertThat(stat.getEgressBytes(), equalTo(TestUpfConstants.COUNTER_BYTES));
+ assertThat(stat.getIngressPkts(), equalTo(TestUpfConstants.COUNTER_PKTS));
+ assertThat(stat.getEgressPkts(), equalTo(TestUpfConstants.COUNTER_PKTS));
+ }
+ }
+
+ @Test
+ public void testReadAllCountersLimitedCounters() {
+ Collection<PdrStats> allStats = upfProgrammable.readAllCounters(10);
+ assertThat(allStats.size(), equalTo(10));
+ }
+
+ @Test
+ public void testReadAllCountersPhysicalLimit() {
+ Collection<PdrStats> allStats = upfProgrammable.readAllCounters(1024);
+ assertThat(allStats.size(), equalTo(TestUpfConstants.PHYSICAL_COUNTER_SIZE));
+ }
+
+ @Test
+ public void testSendPacketOut() {
+ upfProgrammable.sendPacketOut(ByteBuffer.wrap(ETH_FRAME_BYTES));
+ var emittedPkt = packetService.emittedPackets.poll();
+ assertNotNull(emittedPkt);
+ assertThat(emittedPkt.data().array(), equalTo(ETH_FRAME_BYTES));
+ assertThat(emittedPkt.treatment(), equalTo(TABLE_OUTPUT_TREATMENT));
+ }
+}