Merge remote-tracking branch 'origin/master' into dev/murrelet
diff --git a/apps/ofagent/BUCK b/apps/ofagent/BUCK
index 8e0826b..0d28fca 100644
--- a/apps/ofagent/BUCK
+++ b/apps/ofagent/BUCK
@@ -15,6 +15,12 @@
'//lib:openflowj',
'//lib:javax.ws.rs-api',
'//utils/rest:onlab-rest',
+ '//providers/openflow/flow:onos-providers-openflow-flow',
+]
+
+BUNDLES = [
+ '//apps/ofagent:onos-apps-ofagent',
+ '//providers/openflow/flow:onos-providers-openflow-flow',
]
TEST_DEPS = [
@@ -30,12 +36,17 @@
osgi_jar_with_tests (
deps = COMPILE_DEPS,
test_deps = TEST_DEPS,
- web_context = '/onos/v1/ofagent',
+ web_context = '/onos/ofagent',
+ api_title = 'OFAgent API',
+ api_version = '1.0',
+ api_description = 'REST API for OFAgent',
+ api_package = 'org.onosproject.ofagent.rest',
)
onos_app (
title = 'OpenFlow Agent',
category = 'Traffic Steering',
url = 'http://onosproject.org',
+ included_bundles = BUNDLES,
description = 'OpenFlow agent application for virtualization subsystem.',
)
diff --git a/apps/ofagent/pom.xml b/apps/ofagent/pom.xml
index a3590e9..76fb852 100644
--- a/apps/ofagent/pom.xml
+++ b/apps/ofagent/pom.xml
@@ -172,6 +172,13 @@
<scope>test</scope>
</dependency>
+ <!-- Flow Entry building dependencies -->
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-providers-openflow-flow</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
</dependencies>
<build>
@@ -191,6 +198,9 @@
*,org.glassfish.jersey.servlet
</Import-Package>
<Web-ContextPath>${web.context}</Web-ContextPath>
+ <Private-Package>
+ org.onosproject.provider.of.flow.util
+ </Private-Package>
</instructions>
</configuration>
</plugin>
diff --git a/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/DefaultOFSwitch.java b/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/DefaultOFSwitch.java
index 3f4f878..f06446a 100644
--- a/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/DefaultOFSwitch.java
+++ b/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/DefaultOFSwitch.java
@@ -20,13 +20,16 @@
import io.netty.channel.Channel;
import org.onlab.osgi.ServiceDirectory;
import org.onosproject.incubator.net.virtual.NetworkId;
+import org.onosproject.incubator.net.virtual.VirtualNetworkService;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.device.PortStatistics;
+import org.onosproject.net.driver.DriverService;
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.FlowRuleService;
import org.onosproject.net.flow.TableStatisticsEntry;
import org.onosproject.net.group.Group;
import org.onosproject.net.packet.InboundPacket;
@@ -34,6 +37,7 @@
import org.onosproject.ofagent.api.OFSwitchCapabilities;
import org.onosproject.ofagent.api.OFSwitchService;
import org.projectfloodlight.openflow.protocol.OFActionType;
+import org.projectfloodlight.openflow.protocol.OFBadRequestCode;
import org.projectfloodlight.openflow.protocol.OFBarrierReply;
import org.projectfloodlight.openflow.protocol.OFBucket;
import org.projectfloodlight.openflow.protocol.OFBucketCounter;
@@ -43,6 +47,7 @@
import org.projectfloodlight.openflow.protocol.OFFactories;
import org.projectfloodlight.openflow.protocol.OFFactory;
import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
+import org.projectfloodlight.openflow.protocol.OFFlowMod;
import org.projectfloodlight.openflow.protocol.OFFlowStatsEntry;
import org.projectfloodlight.openflow.protocol.OFGetConfigReply;
import org.projectfloodlight.openflow.protocol.OFGroupDescStatsEntry;
@@ -55,6 +60,7 @@
import org.projectfloodlight.openflow.protocol.OFPacketInReason;
import org.projectfloodlight.openflow.protocol.OFPacketOut;
import org.projectfloodlight.openflow.protocol.OFPortDesc;
+import org.projectfloodlight.openflow.protocol.OFPortMod;
import org.projectfloodlight.openflow.protocol.OFPortReason;
import org.projectfloodlight.openflow.protocol.OFPortStatsEntry;
import org.projectfloodlight.openflow.protocol.OFPortStatsRequest;
@@ -69,6 +75,7 @@
import org.projectfloodlight.openflow.protocol.OFVersion;
import org.projectfloodlight.openflow.protocol.action.OFAction;
import org.projectfloodlight.openflow.protocol.action.OFActionOutput;
+import org.projectfloodlight.openflow.protocol.errormsg.OFBadRequestErrorMsg;
import org.projectfloodlight.openflow.protocol.instruction.OFInstruction;
import org.projectfloodlight.openflow.protocol.match.Match;
import org.projectfloodlight.openflow.protocol.match.MatchField;
@@ -103,6 +110,8 @@
private final Logger log;
private final OFSwitchService ofSwitchService;
+ private final FlowRuleService flowRuleService;
+ private final DriverService driverService;
private final DatapathId dpId;
private final OFSwitchCapabilities capabilities;
@@ -121,12 +130,15 @@
private DefaultOFSwitch(DatapathId dpid, OFSwitchCapabilities capabilities,
NetworkId networkId, DeviceId deviceId,
- OFSwitchService ofSwitchService) {
+ ServiceDirectory serviceDirectory) {
this.dpId = dpid;
this.capabilities = capabilities;
this.networkId = networkId;
this.deviceId = deviceId;
- this.ofSwitchService = ofSwitchService;
+ this.ofSwitchService = serviceDirectory.get(OFSwitchService.class);
+ this.driverService = serviceDirectory.get(DriverService.class);
+ VirtualNetworkService virtualNetworkService = serviceDirectory.get(VirtualNetworkService.class);
+ this.flowRuleService = virtualNetworkService.get(networkId, FlowRuleService.class);
log = LoggerFactory.getLogger(getClass().getName() + " : " + dpid);
}
@@ -135,8 +147,7 @@
ServiceDirectory serviceDirectory) {
checkNotNull(dpid, "DPID cannot be null");
checkNotNull(capabilities, "OF capabilities cannot be null");
- return new DefaultOFSwitch(dpid, capabilities, networkId, deviceId,
- serviceDirectory.get(OFSwitchService.class));
+ return new DefaultOFSwitch(dpid, capabilities, networkId, deviceId, serviceDirectory);
}
@Override
@@ -224,10 +235,53 @@
log.debug("processPacketIn: Functionality not yet supported for {}", packet);
}
+ private void processPortMod(OFPortMod portMod) {
+// PortNumber portNumber = PortNumber.portNumber(portMod.getPortNo().getPortNumber());
+ log.debug("processPortMod: {} not yet supported for {}",
+ portMod.getType(), portMod);
+ }
+
+ private void processFlowMod(OFFlowMod flowMod) {
+ // convert OFFlowMod to FLowRule object
+ OFAgentVirtualFlowEntryBuilder flowEntryBuilder =
+ new OFAgentVirtualFlowEntryBuilder(deviceId, flowMod, driverService);
+ FlowEntry flowEntry = flowEntryBuilder.build();
+ flowRuleService.applyFlowRules(flowEntry);
+ }
+
@Override
public void processControllerCommand(Channel channel, OFMessage msg) {
- // TODO process controller command
- log.debug("processControllerCommand: Functionality not yet supported for {}", msg);
+
+ OFControllerRole myRole = role(channel);
+ if (OFControllerRole.ROLE_SLAVE.equals(myRole)) {
+ OFBadRequestErrorMsg errorMsg = FACTORY.errorMsgs()
+ .buildBadRequestErrorMsg()
+ .setXid(msg.getXid())
+ .setCode(OFBadRequestCode.IS_SLAVE)
+ .build();
+ channel.writeAndFlush(Collections.singletonList(errorMsg));
+ return;
+ }
+
+ switch (msg.getType()) {
+ case PORT_MOD:
+ OFPortMod portMod = (OFPortMod) msg;
+ processPortMod(portMod);
+ break;
+ case FLOW_MOD:
+ OFFlowMod flowMod = (OFFlowMod) msg;
+ processFlowMod(flowMod);
+ break;
+ case GROUP_MOD:
+ case METER_MOD:
+ case TABLE_MOD:
+ log.debug("processControllerCommand: {} not yet supported for {}",
+ msg.getType(), msg);
+ break;
+ default:
+ log.warn("Unexpected message {} received for switch {}",
+ msg.getType(), this);
+ }
}
private void sendPortStatus(Port port, OFPortReason ofPortReason) {
diff --git a/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/OFAgentVirtualFlowEntryBuilder.java b/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/OFAgentVirtualFlowEntryBuilder.java
new file mode 100644
index 0000000..e3cb9e3
--- /dev/null
+++ b/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/OFAgentVirtualFlowEntryBuilder.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2017-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.ofagent.impl;
+
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.driver.DefaultDriverData;
+import org.onosproject.net.driver.DefaultDriverHandler;
+import org.onosproject.net.driver.Driver;
+import org.onosproject.net.driver.DriverHandler;
+import org.onosproject.net.driver.DriverService;
+import org.onosproject.provider.of.flow.util.FlowEntryBuilder;
+import org.projectfloodlight.openflow.protocol.OFFlowMod;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+// FlowEntryBuilder customized for OFAgent. This builder will be used to build FlowEntry objects for
+// virtual devices encountered by OFAgent. The driver has been hardcoded to "ovs".
+public class OFAgentVirtualFlowEntryBuilder extends FlowEntryBuilder {
+ private static final Logger log = LoggerFactory.getLogger(OFAgentVirtualFlowEntryBuilder.class);
+ private static final String DRIVER_NAME = "ovs";
+
+ private final DriverService driverService;
+
+ public OFAgentVirtualFlowEntryBuilder(DeviceId deviceId, OFFlowMod fm, DriverService driverService) {
+ super(deviceId, fm, driverService);
+ this.driverService = driverService;
+ }
+
+ protected DriverHandler getDriver(DeviceId devId) {
+ log.debug("calling getDriver for {}", devId);
+ Driver driver = driverService.getDriver(DRIVER_NAME);
+ DriverHandler handler = new DefaultDriverHandler(new DefaultDriverData(driver, devId));
+ return handler;
+ }
+}
diff --git a/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/OFChannelHandler.java b/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/OFChannelHandler.java
index aea97d1..ddfadc2 100644
--- a/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/OFChannelHandler.java
+++ b/apps/ofagent/src/main/java/org/onosproject/ofagent/impl/OFChannelHandler.java
@@ -128,6 +128,13 @@
// TODO: check if this is lldp - ignore if it is not lldp
handler.ofSwitch.processLldp(handler.channel, msg);
break;
+ case FLOW_MOD:
+ case PORT_MOD:
+ case GROUP_MOD:
+ case METER_MOD:
+ case TABLE_MOD:
+ handler.ofSwitch.processControllerCommand(handler.channel, msg);
+ break;
case ERROR:
handler.logErrorClose((OFErrorMsg) msg);
break;
diff --git a/apps/p4runtime-test/src/test/java/org/onosproject/p4runtime/test/P4RuntimeTest.java b/apps/p4runtime-test/src/test/java/org/onosproject/p4runtime/test/P4RuntimeTest.java
index dcad695..514ece7 100644
--- a/apps/p4runtime-test/src/test/java/org/onosproject/p4runtime/test/P4RuntimeTest.java
+++ b/apps/p4runtime-test/src/test/java/org/onosproject/p4runtime/test/P4RuntimeTest.java
@@ -29,9 +29,14 @@
import org.onosproject.net.pi.model.PiPipeconf;
import org.onosproject.net.pi.model.PiPipelineInterpreter;
import org.onosproject.net.pi.runtime.PiAction;
+import org.onosproject.net.pi.runtime.PiActionGroup;
+import org.onosproject.net.pi.runtime.PiActionGroupId;
+import org.onosproject.net.pi.runtime.PiActionGroupMember;
+import org.onosproject.net.pi.runtime.PiActionGroupMemberId;
import org.onosproject.net.pi.runtime.PiActionId;
import org.onosproject.net.pi.runtime.PiActionParam;
import org.onosproject.net.pi.runtime.PiActionParamId;
+import org.onosproject.net.pi.runtime.PiActionProfileId;
import org.onosproject.net.pi.runtime.PiHeaderFieldId;
import org.onosproject.net.pi.runtime.PiMatchKey;
import org.onosproject.net.pi.runtime.PiPacketMetadata;
@@ -43,10 +48,13 @@
import org.onosproject.p4runtime.api.P4RuntimeClient;
import org.onosproject.p4runtime.ctl.P4RuntimeClientImpl;
import org.onosproject.p4runtime.ctl.P4RuntimeControllerImpl;
+import org.slf4j.Logger;
import p4.P4RuntimeGrpc;
import p4.P4RuntimeOuterClass;
import java.net.URL;
+import java.util.Collection;
+import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import static org.onlab.util.ImmutableByteSequence.copyFrom;
@@ -54,6 +62,7 @@
import static org.onlab.util.ImmutableByteSequence.ofZeros;
import static org.onosproject.net.pi.model.PiPipeconf.ExtensionType.BMV2_JSON;
import static org.onosproject.net.pi.runtime.PiPacketOperation.Type.PACKET_OUT;
+import static org.slf4j.LoggerFactory.getLogger;
import static p4.P4RuntimeOuterClass.ActionProfileGroup.Type.SELECT;
import static p4.P4RuntimeOuterClass.Update.Type.INSERT;
@@ -61,6 +70,7 @@
* Class used for quick testing of P4Runtime with real devices. To be removed before release.
*/
public class P4RuntimeTest {
+ private static final Logger log = getLogger(P4RuntimeTest.class);
private static final String GRPC_SERVER_ADDR = "192.168.56.102";
private static final int GRPC_SERVER_PORT = 55044;
@@ -233,6 +243,56 @@
@Test
@Ignore
+ public void testBmv2ActionProfile() throws Exception {
+ createClient();
+ setPipelineConfig(bmv2DefaultPipeconf, BMV2_JSON);
+ PiActionProfileId actionProfileId = PiActionProfileId.of("ecmp_selector");
+ PiActionGroupId groupId = PiActionGroupId.of(1);
+
+ Collection<PiActionGroupMember> members = Lists.newArrayList();
+
+ for (int port = 1; port <= 4; port++) {
+ PiAction memberAction = PiAction.builder()
+ .withId(PiActionId.of(SET_EGRESS_PORT))
+ .withParameter(new PiActionParam(PiActionParamId.of(PORT),
+ ImmutableByteSequence.copyFrom((short) port)))
+ .build();
+ PiActionGroupMemberId memberId = PiActionGroupMemberId.of(port);
+ PiActionGroupMember member = PiActionGroupMember.builder()
+ .withId(memberId)
+ .withAction(memberAction)
+ .withWeight(port)
+ .build();
+ members.add(member);
+ }
+ PiActionGroup actionGroup = PiActionGroup.builder()
+ .withType(PiActionGroup.Type.SELECT)
+ .withActionProfileId(actionProfileId)
+ .withId(groupId)
+ .addMembers(members)
+ .build();
+ CompletableFuture<Boolean> success = client.writeActionGroupMembers(actionGroup, members,
+ P4RuntimeClient.WriteOperationType.INSERT,
+ bmv2DefaultPipeconf);
+ assert (success.get());
+
+ success = client.writeActionGroup(actionGroup, P4RuntimeClient.WriteOperationType.INSERT, bmv2DefaultPipeconf);
+ assert (success.get());
+
+ CompletableFuture<Collection<PiActionGroup>> piGroups = client.dumpGroups(actionProfileId, bmv2DefaultPipeconf);
+
+ log.info("Number of groups: {}", piGroups.get().size());
+ piGroups.get().forEach(piGroup -> {
+ log.info("Group {}", piGroup);
+ log.info("------");
+ piGroup.members().forEach(piMem -> {
+ log.info(" {}", piMem);
+ });
+ });
+ }
+
+ @Test
+ @Ignore
public void testTofino() throws Exception {
createClient();
setPipelineConfig(bmv2DefaultPipeconf, null);
diff --git a/core/api/src/main/java/org/onosproject/app/DefaultApplicationDescription.java b/core/api/src/main/java/org/onosproject/app/DefaultApplicationDescription.java
index 2e0988b..3862718 100644
--- a/core/api/src/main/java/org/onosproject/app/DefaultApplicationDescription.java
+++ b/core/api/src/main/java/org/onosproject/app/DefaultApplicationDescription.java
@@ -15,15 +15,17 @@
*/
package org.onosproject.app;
-import org.onosproject.core.ApplicationRole;
-import org.onosproject.core.Version;
-import org.onosproject.security.Permission;
-
import java.net.URI;
import java.util.List;
import java.util.Optional;
import java.util.Set;
+import org.onosproject.core.ApplicationRole;
+import org.onosproject.core.Version;
+import org.onosproject.security.Permission;
+
+import com.google.common.collect.ImmutableList;
+
import static com.google.common.base.MoreObjects.toStringHelper;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
@@ -31,7 +33,7 @@
/**
* Default implementation of network control/management application descriptor.
*/
-public class DefaultApplicationDescription implements ApplicationDescription {
+public final class DefaultApplicationDescription implements ApplicationDescription {
private final String name;
private final Version version;
@@ -49,6 +51,14 @@
private final List<String> requiredApps;
/**
+ * Default constructor is hidden to prevent calls to new.
+ */
+ private DefaultApplicationDescription() {
+ // Should not happen
+ throw new UnsupportedOperationException();
+ }
+
+ /**
* Creates a new application descriptor using the supplied data.
*
* @param name application name
@@ -66,27 +76,26 @@
* @param features application features
* @param requiredApps list of required application names
*/
- public DefaultApplicationDescription(String name, Version version, String title,
- String description, String origin, String category,
- String url, String readme, byte[] icon,
- ApplicationRole role, Set<Permission> permissions,
- URI featuresRepo, List<String> features,
- List<String> requiredApps) {
- this.name = checkNotNull(name, "Name cannot be null");
- this.version = checkNotNull(version, "Version cannot be null");
- this.title = checkNotNull(title, "Title cannot be null");
- this.description = checkNotNull(description, "Description cannot be null");
- this.origin = checkNotNull(origin, "Origin cannot be null");
- this.category = checkNotNull(category, "Category cannot be null");
+ private DefaultApplicationDescription(String name, Version version, String title,
+ String description, String origin, String category,
+ String url, String readme, byte[] icon,
+ ApplicationRole role, Set<Permission> permissions,
+ URI featuresRepo, List<String> features,
+ List<String> requiredApps) {
+ this.name = name;
+ this.version = version;
+ this.title = title;
+ this.description = description;
+ this.origin = origin;
+ this.category = category;
this.url = url;
- this.readme = checkNotNull(readme, "Readme cannot be null");
+ this.readme = readme;
this.icon = icon;
- this.role = checkNotNull(role, "Role cannot be null");
- this.permissions = checkNotNull(permissions, "Permissions cannot be null");
+ this.role = role;
+ this.permissions = permissions;
this.featuresRepo = Optional.ofNullable(featuresRepo);
- this.features = checkNotNull(features, "Features cannot be null");
- this.requiredApps = checkNotNull(requiredApps, "Required apps cannot be null");
- checkArgument(!features.isEmpty(), "There must be at least one feature");
+ this.features = ImmutableList.copyOf(features);
+ this.requiredApps = ImmutableList.copyOf(requiredApps);
}
@Override
@@ -177,4 +186,220 @@
.add("requiredApps", requiredApps)
.toString();
}
+
+ /**
+ * Returns a default application description builder.
+ *
+ * @return builder
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Default application description builder.
+ */
+ public static final class Builder {
+
+ private String name;
+ private Version version;
+ private String title;
+ private String description;
+ private String category;
+ private String url;
+ private String readme;
+ private byte[] icon;
+ private String origin;
+ private ApplicationRole role;
+ private Set<Permission> permissions;
+ private URI featuresRepo;
+ private List<String> features;
+ private List<String> requiredApps;
+
+ /**
+ * Default constructor for the builder.
+ */
+ public Builder() {}
+
+ /**
+ * Adds an application id.
+ *
+ * @param name application name
+ * @return builder
+ */
+ public Builder withName(String name) {
+ this.name = name;
+ return this;
+ }
+
+ /**
+ * Adds a version string.
+ *
+ * @param version version string
+ * @return builder
+ */
+ public Builder withVersion(Version version) {
+ this.version = version;
+ return this;
+ }
+
+ /**
+ * Adds a title string.
+ *
+ * @param title title string
+ * @return builder
+ */
+ public Builder withTitle(String title) {
+ this.title = title;
+ return this;
+ }
+
+ /**
+ * Adds a description string.
+ *
+ * @param description description string
+ * @return builder
+ */
+ public Builder withDescription(String description) {
+ this.description = description;
+ return this;
+ }
+
+ /**
+ * Adds a category string.
+ *
+ * @param category category string
+ * @return builder
+ */
+ public Builder withCategory(String category) {
+ this.category = category;
+ return this;
+ }
+
+ /**
+ * Adds a URL string.
+ *
+ * @param url url string
+ * @return builder
+ */
+ public Builder withUrl(String url) {
+ this.url = url;
+ return this;
+ }
+
+ /**
+ * Adds a readme string.
+ *
+ * @param readme readme string
+ * @return builder
+ */
+ public Builder withReadme(String readme) {
+ this.readme = readme;
+ return this;
+ }
+
+ /**
+ * Adds an icon.
+ *
+ * @param icon icon data
+ * @return builder
+ */
+ public Builder withIcon(byte[] icon) {
+ this.icon = icon;
+ return this;
+ }
+
+ /**
+ * Adds an origin string.
+ *
+ * @param origin origin string
+ * @return builder
+ */
+ public Builder withOrigin(String origin) {
+ this.origin = origin;
+ return this;
+ }
+
+ /**
+ * Adds an application role.
+ *
+ * @param role application role
+ * @return builder
+ */
+ public Builder withRole(ApplicationRole role) {
+ this.role = role;
+ return this;
+ }
+
+ /**
+ * Adds a permissions set.
+ *
+ * @param permissions permissions set
+ * @return builder
+ */
+ public Builder withPermissions(Set<Permission> permissions) {
+ this.permissions = permissions;
+ return this;
+ }
+
+ /**
+ * Adds a URI for a features repository.
+ *
+ * @param featuresRepo Optional URI for a features repository
+ * @return builder
+ */
+ public Builder withFeaturesRepo(URI featuresRepo) {
+ this.featuresRepo = featuresRepo;
+ return this;
+ }
+
+ /**
+ * Adds a features list.
+ *
+ * @param features features list
+ * @return builder
+ */
+ public Builder withFeatures(List<String> features) {
+ this.features = features;
+ return this;
+ }
+
+ /**
+ * Adds a list of required applications.
+ *
+ * @param requiredApps List of name strings of required applications
+ * @return builder
+ */
+ public Builder withRequiredApps(List<String> requiredApps) {
+ this.requiredApps = requiredApps;
+ return this;
+ }
+
+ /**
+ * Builds a default application object from the gathered parameters.
+ *
+ * @return new default application
+ */
+ public DefaultApplicationDescription build() {
+ checkNotNull(name, "Name cannot be null");
+ checkNotNull(version, "Version cannot be null");
+ checkNotNull(title, "Title cannot be null");
+ checkNotNull(description, "Description cannot be null");
+ checkNotNull(origin, "Origin cannot be null");
+ checkNotNull(category, "Category cannot be null");
+ checkNotNull(readme, "Readme cannot be null");
+ checkNotNull(role, "Role cannot be null");
+ checkNotNull(permissions, "Permissions cannot be null");
+ checkNotNull(features, "Features cannot be null");
+ checkNotNull(requiredApps, "Required apps cannot be null");
+ checkArgument(!features.isEmpty(), "There must be at least one feature");
+
+ return new DefaultApplicationDescription(name, version, title,
+ description, origin, category,
+ url, readme, icon,
+ role, permissions,
+ featuresRepo, features,
+ requiredApps);
+ }
+ }
}
diff --git a/core/api/src/main/java/org/onosproject/core/DefaultApplication.java b/core/api/src/main/java/org/onosproject/core/DefaultApplication.java
index f780623..2df2f8f 100644
--- a/core/api/src/main/java/org/onosproject/core/DefaultApplication.java
+++ b/core/api/src/main/java/org/onosproject/core/DefaultApplication.java
@@ -17,6 +17,8 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
+
+import org.onosproject.app.ApplicationDescription;
import org.onosproject.security.Permission;
import java.net.URI;
@@ -32,7 +34,7 @@
/**
* Default implementation of network control/management application descriptor.
*/
-public class DefaultApplication implements Application {
+public final class DefaultApplication implements Application {
private final ApplicationId appId;
private final Version version;
@@ -50,6 +52,26 @@
private final List<String> requiredApps;
/**
+ * Default constructor is hidden to prevent calls to new.
+ */
+ private DefaultApplication() {
+ appId = null;
+ version = null;
+ title = null;
+ description = null;
+ category = null;
+ url = null;
+ readme = null;
+ icon = null;
+ origin = null;
+ role = null;
+ permissions = null;
+ featuresRepo = Optional.empty();
+ features = ImmutableList.of();
+ requiredApps = ImmutableList.of();
+ }
+
+ /**
* Creates a new application descriptor using the supplied data.
*
* @param appId application identifier
@@ -67,33 +89,26 @@
* @param features application features
* @param requiredApps list of required application names
*/
- public DefaultApplication(ApplicationId appId, Version version, String title,
+ private DefaultApplication(ApplicationId appId, Version version, String title,
String description, String origin, String category,
String url, String readme, byte[] icon,
ApplicationRole role, Set<Permission> permissions,
Optional<URI> featuresRepo, List<String> features,
List<String> requiredApps) {
- this.appId = checkNotNull(appId, "ID cannot be null");
- this.version = checkNotNull(version, "Version cannot be null");
- this.title = checkNotNull(title, "Title cannot be null");
- this.description = checkNotNull(description, "Description cannot be null");
- this.origin = checkNotNull(origin, "Origin cannot be null");
- this.category = checkNotNull(category, "Category cannot be null");
+ this.appId = appId;
+ this.version = version;
+ this.title = title;
+ this.description = description;
+ this.origin = origin;
+ this.category = category;
this.url = url;
- this.readme = checkNotNull(readme, "Readme cannot be null");
+ this.readme = readme;
this.icon = icon == null ? new byte[0] : icon.clone();
- this.role = checkNotNull(role, "Role cannot be null");
- this.permissions = ImmutableSet.copyOf(
- checkNotNull(permissions, "Permissions cannot be null")
- );
- this.featuresRepo = checkNotNull(featuresRepo, "Features repo cannot be null");
- this.features = ImmutableList.copyOf(
- checkNotNull(features, "Features cannot be null")
- );
- this.requiredApps = ImmutableList.copyOf(
- checkNotNull(requiredApps, "Required apps cannot be null")
- );
- checkArgument(!features.isEmpty(), "There must be at least one feature");
+ this.role = role;
+ this.permissions = ImmutableSet.copyOf(permissions);
+ this.featuresRepo = featuresRepo;
+ this.features = ImmutableList.copyOf(features);
+ this.requiredApps = ImmutableList.copyOf(requiredApps);
}
@Override
@@ -217,4 +232,317 @@
.add("requiredApps", requiredApps)
.toString();
}
+
+ /**
+ * Returns a default application builder.
+ *
+ * @return builder
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Creates a new builder as a copy of an existing builder.
+ *
+ * @param builder existing builder to copy
+ * @return new builder
+ */
+ public static Builder builder(Builder builder) {
+ return new Builder(builder);
+ }
+
+ /**
+ * Creates a new builder as a copy of an existing application.
+ *
+ * @param application existing application to copy
+ * @return new builder
+ */
+ public static Builder builder(Application application) {
+ return new Builder(application);
+ }
+
+ /**
+ * Creates a new builder as a copy of an existing application description.
+ *
+ * @param appDesc existing application description
+ * @return new builder
+ */
+ public static Builder builder(ApplicationDescription appDesc) {
+ return new Builder(appDesc);
+ }
+
+
+ /**
+ * Default application builder.
+ */
+ public static final class Builder {
+
+ private ApplicationId appId;
+ private Version version;
+ private String title;
+ private String description;
+ private String category;
+ private String url;
+ private String readme;
+ private byte[] icon;
+ private String origin;
+ private ApplicationRole role;
+ private Set<Permission> permissions;
+ private Optional<URI> featuresRepo;
+ private List<String> features;
+ private List<String> requiredApps;
+
+ /**
+ * Default constructor for the builder.
+ */
+ public Builder() {}
+
+ /**
+ * Updates the builder to be a copy of an existing builder.
+ *
+ * @param builder existing builder to copy
+ */
+ public Builder(Builder builder) {
+ this.appId = builder.appId;
+ this.version = builder.version;
+ this.title = builder.title;
+ this.description = builder.description;
+ this.category = builder.category;
+ this.url = builder.url;
+ this.readme = builder.readme;
+ this.icon = builder.icon;
+ this.origin = builder.origin;
+ this.role = builder.role;
+ this.permissions = builder.permissions;
+ this.featuresRepo = builder.featuresRepo;
+ this.features = builder.features;
+ this.requiredApps = builder.requiredApps;
+ }
+
+ /**
+ * Updates the builder to be a copy of an existing application.
+ *
+ * @param application existing application to copy
+ */
+ public Builder(Application application) {
+ this.appId = application.id();
+ this.version = application.version();
+ this.title = application.title();
+ this.description = application.description();
+ this.category = application.category();
+ this.url = application.url();
+ this.readme = application.readme();
+ this.icon = application.icon();
+ this.origin = application.origin();
+ this.role = application.role();
+ this.permissions = application.permissions();
+ this.featuresRepo = application.featuresRepo();
+ this.features = application.features();
+ this.requiredApps = application.requiredApps();
+ }
+
+ /**
+ * Updates the builder to be a copy of an existing application description.
+ *
+ * @param appDesc existing application description
+ */
+ public Builder(ApplicationDescription appDesc) {
+ this.version = appDesc.version();
+ this.title = appDesc.title();
+ this.description = appDesc.description();
+ this.category = appDesc.category();
+ this.url = appDesc.url();
+ this.readme = appDesc.readme();
+ this.icon = appDesc.icon();
+ this.origin = appDesc.origin();
+ this.role = appDesc.role();
+ this.permissions = appDesc.permissions();
+ this.featuresRepo = appDesc.featuresRepo();
+ this.features = appDesc.features();
+ this.requiredApps = appDesc.requiredApps();
+ }
+
+ /**
+ * Adds an application id.
+ *
+ * @param appId application id
+ * @return builder
+ */
+ public Builder withAppId(ApplicationId appId) {
+ this.appId = appId;
+ return this;
+ }
+
+ /**
+ * Adds a version string.
+ *
+ * @param version version string
+ * @return builder
+ */
+ public Builder withVersion(Version version) {
+ this.version = version;
+ return this;
+ }
+
+ /**
+ * Adds a title string.
+ *
+ * @param title title string
+ * @return builder
+ */
+ public Builder withTitle(String title) {
+ this.title = title;
+ return this;
+ }
+
+ /**
+ * Adds a description string.
+ *
+ * @param description description string
+ * @return builder
+ */
+ public Builder withDescription(String description) {
+ this.description = description;
+ return this;
+ }
+
+ /**
+ * Adds a category string.
+ *
+ * @param category category string
+ * @return builder
+ */
+ public Builder withCategory(String category) {
+ this.category = category;
+ return this;
+ }
+
+ /**
+ * Adds a URL string.
+ *
+ * @param url url string
+ * @return builder
+ */
+ public Builder withUrl(String url) {
+ this.url = url;
+ return this;
+ }
+
+ /**
+ * Adds a readme string.
+ *
+ * @param readme readme string
+ * @return builder
+ */
+ public Builder withReadme(String readme) {
+ this.readme = readme;
+ return this;
+ }
+
+ /**
+ * Adds an icon.
+ *
+ * @param icon icon data
+ * @return builder
+ */
+ public Builder withIcon(byte[] icon) {
+ this.icon = icon;
+ return this;
+ }
+
+ /**
+ * Adds an origin string.
+ *
+ * @param origin origin string
+ * @return builder
+ */
+ public Builder withOrigin(String origin) {
+ this.origin = origin;
+ return this;
+ }
+
+ /**
+ * Adds an application role.
+ *
+ * @param role application role
+ * @return builder
+ */
+ public Builder withRole(ApplicationRole role) {
+ this.role = role;
+ return this;
+ }
+
+ /**
+ * Adds a permissions set.
+ *
+ * @param permissions permissions set
+ * @return builder
+ */
+ public Builder withPermissions(Set<Permission> permissions) {
+ this.permissions = permissions;
+ return this;
+ }
+
+ /**
+ * Adds a URI for a features repository.
+ *
+ * @param featuresRepo Optional URI for a features repository
+ * @return builder
+ */
+ public Builder withFeaturesRepo(Optional<URI> featuresRepo) {
+ this.featuresRepo = featuresRepo;
+ return this;
+ }
+
+ /**
+ * Adds a features list.
+ *
+ * @param features features list
+ * @return builder
+ */
+ public Builder withFeatures(List<String> features) {
+ this.features = features;
+ return this;
+ }
+
+ /**
+ * Adds a list of required applications.
+ *
+ * @param requiredApps List of name strings of required applications
+ * @return builder
+ */
+ public Builder withRequiredApps(List<String> requiredApps) {
+ this.requiredApps = requiredApps;
+ return this;
+ }
+
+ /**
+ * Builds a default application object from the gathered parameters.
+ *
+ * @return new default application
+ */
+ public DefaultApplication build() {
+ checkNotNull(appId, "ID cannot be null");
+ checkNotNull(version, "Version cannot be null");
+ checkNotNull(title, "Title cannot be null");
+ checkNotNull(description, "Description cannot be null");
+ checkNotNull(origin, "Origin cannot be null");
+ checkNotNull(category, "Category cannot be null");
+ checkNotNull(readme, "Readme cannot be null");
+ checkNotNull(role, "Role cannot be null");
+ checkNotNull(permissions, "Permissions cannot be null");
+ checkNotNull(featuresRepo, "Features repo cannot be null");
+ checkNotNull(features, "Features cannot be null");
+ checkNotNull(requiredApps, "Required apps cannot be null");
+ checkArgument(!features.isEmpty(), "There must be at least one feature");
+
+ return new DefaultApplication(appId, version, title,
+ description, origin, category,
+ url, readme, icon,
+ role, permissions,
+ featuresRepo, features,
+ requiredApps);
+ }
+ }
}
diff --git a/core/api/src/main/java/org/onosproject/net/AnnotationKeys.java b/core/api/src/main/java/org/onosproject/net/AnnotationKeys.java
index d3157e1..da93417 100644
--- a/core/api/src/main/java/org/onosproject/net/AnnotationKeys.java
+++ b/core/api/src/main/java/org/onosproject/net/AnnotationKeys.java
@@ -122,6 +122,16 @@
public static final String PORT_NAME = "portName";
/**
+ * Annotation key for the optical channel receiving/in port (RX).
+ */
+ public static final String PORT_IN = "portIn";
+
+ /**
+ * Annotation key for the optical channel port transmitting/out port (TX).
+ */
+
+ public static final String PORT_OUT = "portOut";
+ /**
* Annotation key for the port mac.
*/
public static final String PORT_MAC = "portMac";
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/DefaultMirroringDescription.java b/core/api/src/main/java/org/onosproject/net/behaviour/DefaultMirroringDescription.java
index 47a19a3..0c82e48 100644
--- a/core/api/src/main/java/org/onosproject/net/behaviour/DefaultMirroringDescription.java
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/DefaultMirroringDescription.java
@@ -29,7 +29,7 @@
* Default implementation of mirroring description entity.
*/
@Beta
-public class DefaultMirroringDescription extends AbstractDescription
+public final class DefaultMirroringDescription extends AbstractDescription
implements MirroringDescription {
private final MirroringName mirroringName;
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/DefaultPatchDescription.java b/core/api/src/main/java/org/onosproject/net/behaviour/DefaultPatchDescription.java
index 8d13c68..9450f39 100644
--- a/core/api/src/main/java/org/onosproject/net/behaviour/DefaultPatchDescription.java
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/DefaultPatchDescription.java
@@ -20,6 +20,7 @@
import org.onosproject.net.AbstractDescription;
import org.onosproject.net.SparseAnnotations;
+import java.util.Objects;
import java.util.Optional;
import static com.google.common.base.Preconditions.checkArgument;
@@ -61,6 +62,26 @@
}
@Override
+ public int hashCode() {
+ return Objects.hash(deviceId, ifaceName, peerName);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DefaultPatchDescription) {
+ final DefaultPatchDescription that = (DefaultPatchDescription) obj;
+ return this.getClass() == that.getClass() &&
+ Objects.equals(this.deviceId, that.deviceId) &&
+ Objects.equals(this.ifaceName, that.ifaceName) &&
+ Objects.equals(this.peerName, that.peerName);
+ }
+ return false;
+ }
+
+ @Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("deviceId", deviceId)
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/MirroringStatistics.java b/core/api/src/main/java/org/onosproject/net/behaviour/MirroringStatistics.java
index 6713633..b9aae84 100644
--- a/core/api/src/main/java/org/onosproject/net/behaviour/MirroringStatistics.java
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/MirroringStatistics.java
@@ -16,19 +16,28 @@
package org.onosproject.net.behaviour;
-import com.google.common.base.MoreObjects;
-
import java.util.Map;
import java.util.Objects;
+import com.google.common.base.MoreObjects;
+
/**
* Represents statistics associated to a mirroring.
*/
public final class MirroringStatistics {
- private MirroringName mirroringName;
- private int txBytes;
- private int txPackets;
+ private final MirroringName mirroringName;
+ private final long txBytes;
+ private final long txPackets;
+
+ /**
+ * Hide private constructor to prevent calls to new().
+ */
+ private MirroringStatistics() {
+ mirroringName = null;
+ txBytes = 0;
+ txPackets = 0;
+ }
/**
* Statistics associated to a named mirroring.
@@ -37,7 +46,7 @@
* @param bytes transmitted bytes
* @param packets transmitted packets
*/
- private MirroringStatistics(String name, int bytes, int packets) {
+ private MirroringStatistics(String name, long bytes, long packets) {
this.mirroringName = MirroringName.mirroringName(name);
this.txBytes = bytes;
this.txPackets = packets;
@@ -78,7 +87,7 @@
*
* @return the packets
*/
- public long packtes() {
+ public long packets() {
return txPackets;
}
@@ -107,7 +116,7 @@
return MoreObjects.toStringHelper(getClass())
.add("name", name())
.add("tx_bytes", bytes())
- .add("tx_packets", packtes())
+ .add("tx_packets", packets())
.toString();
}
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/TunnelEndPoint.java b/core/api/src/main/java/org/onosproject/net/behaviour/TunnelEndPoint.java
index 2b96452..ab9eee5 100644
--- a/core/api/src/main/java/org/onosproject/net/behaviour/TunnelEndPoint.java
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/TunnelEndPoint.java
@@ -22,9 +22,9 @@
* Represents for source end point or destination end point of a tunnel. Maybe a tunnel
* based on ConnectPoint, IpAddress, MacAddress and so on is built.
*/
-public class TunnelEndPoint<T> {
+public final class TunnelEndPoint<T> {
- protected final T value;
+ private final T value;
/**
* Default constructor.
diff --git a/core/api/src/main/java/org/onosproject/net/flow/FlowRuleProvider.java b/core/api/src/main/java/org/onosproject/net/flow/FlowRuleProvider.java
index cbf1da5..d20f9aa 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/FlowRuleProvider.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/FlowRuleProvider.java
@@ -16,6 +16,7 @@
package org.onosproject.net.flow;
import org.onosproject.core.ApplicationId;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchOperation;
import org.onosproject.net.provider.Provider;
/**
diff --git a/core/api/src/main/java/org/onosproject/net/flow/FlowRuleStore.java b/core/api/src/main/java/org/onosproject/net/flow/FlowRuleStore.java
index 13a91a7..ff0bbe1 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/FlowRuleStore.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/FlowRuleStore.java
@@ -18,6 +18,8 @@
import java.util.List;
import org.onosproject.net.DeviceId;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchEvent;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchOperation;
import org.onosproject.store.Store;
/**
diff --git a/core/api/src/main/java/org/onosproject/net/flow/FlowRuleStoreDelegate.java b/core/api/src/main/java/org/onosproject/net/flow/FlowRuleStoreDelegate.java
index 7b31f48..3e712f2 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/FlowRuleStoreDelegate.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/FlowRuleStoreDelegate.java
@@ -15,6 +15,7 @@
*/
package org.onosproject.net.flow;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchEvent;
import org.onosproject.store.StoreDelegate;
/**
diff --git a/core/api/src/main/java/org/onosproject/net/flow/FlowRuleBatchEntry.java b/core/api/src/main/java/org/onosproject/net/flow/oldbatch/FlowRuleBatchEntry.java
similarity index 85%
rename from core/api/src/main/java/org/onosproject/net/flow/FlowRuleBatchEntry.java
rename to core/api/src/main/java/org/onosproject/net/flow/oldbatch/FlowRuleBatchEntry.java
index 964647b..905af60 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/FlowRuleBatchEntry.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/oldbatch/FlowRuleBatchEntry.java
@@ -13,9 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.onosproject.net.flow;
+package org.onosproject.net.flow.oldbatch;
-import org.onosproject.net.flow.FlowRuleBatchEntry.FlowRuleOperation;
+import org.onosproject.net.flow.BatchOperationEntry;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchEntry.FlowRuleOperation;
@Deprecated
/**
diff --git a/core/api/src/main/java/org/onosproject/net/flow/FlowRuleBatchEvent.java b/core/api/src/main/java/org/onosproject/net/flow/oldbatch/FlowRuleBatchEvent.java
similarity index 97%
rename from core/api/src/main/java/org/onosproject/net/flow/FlowRuleBatchEvent.java
rename to core/api/src/main/java/org/onosproject/net/flow/oldbatch/FlowRuleBatchEvent.java
index f70067f..ab41753 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/FlowRuleBatchEvent.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/oldbatch/FlowRuleBatchEvent.java
@@ -13,10 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.onosproject.net.flow;
+package org.onosproject.net.flow.oldbatch;
import org.onosproject.event.AbstractEvent;
import org.onosproject.net.DeviceId;
+import org.onosproject.net.flow.CompletedBatchOperation;
@Deprecated
/**
diff --git a/core/api/src/main/java/org/onosproject/net/flow/FlowRuleBatchOperation.java b/core/api/src/main/java/org/onosproject/net/flow/oldbatch/FlowRuleBatchOperation.java
similarity index 94%
rename from core/api/src/main/java/org/onosproject/net/flow/FlowRuleBatchOperation.java
rename to core/api/src/main/java/org/onosproject/net/flow/oldbatch/FlowRuleBatchOperation.java
index a721cc8..d252e6a 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/FlowRuleBatchOperation.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/oldbatch/FlowRuleBatchOperation.java
@@ -13,9 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.onosproject.net.flow;
+package org.onosproject.net.flow.oldbatch;
import org.onosproject.net.DeviceId;
+import org.onosproject.net.flow.BatchOperation;
import java.util.Collection;
diff --git a/core/api/src/main/java/org/onosproject/net/flow/FlowRuleBatchRequest.java b/core/api/src/main/java/org/onosproject/net/flow/oldbatch/FlowRuleBatchRequest.java
similarity index 97%
rename from core/api/src/main/java/org/onosproject/net/flow/FlowRuleBatchRequest.java
rename to core/api/src/main/java/org/onosproject/net/flow/oldbatch/FlowRuleBatchRequest.java
index d1e74cd..33539e4 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/FlowRuleBatchRequest.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/oldbatch/FlowRuleBatchRequest.java
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.onosproject.net.flow;
+package org.onosproject.net.flow.oldbatch;
import java.util.List;
import java.util.Set;
diff --git a/core/api/src/main/java/org/onosproject/net/flow/oldbatch/package-info.java b/core/api/src/main/java/org/onosproject/net/flow/oldbatch/package-info.java
new file mode 100644
index 0000000..20cb7a3
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/flow/oldbatch/package-info.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2014-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.
+ */
+
+/**
+ * Flow rule model & related services API definitions.
+ *
+ * <p>
+ * The figure below depicts the general interactions between different
+ * components of the intent subsystem.<br>
+ * <img src="doc-files/flow-design.png" alt="ONOS flow rule subsystem design">
+ * </p>
+ */
+package org.onosproject.net.flow.oldbatch;
diff --git a/core/api/src/main/java/org/onosproject/net/pi/runtime/PiActionGroup.java b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiActionGroup.java
index f023e05..1de4d61 100644
--- a/core/api/src/main/java/org/onosproject/net/pi/runtime/PiActionGroup.java
+++ b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiActionGroup.java
@@ -47,11 +47,15 @@
private final PiActionGroupId id;
private final Type type;
private final ImmutableSet<PiActionGroupMember> members;
+ private final PiActionProfileId piActionProfileId;
- private PiActionGroup(PiActionGroupId id, Type type, ImmutableSet<PiActionGroupMember> members) {
+ private PiActionGroup(PiActionGroupId id, Type type,
+ ImmutableSet<PiActionGroupMember> members,
+ PiActionProfileId piActionProfileId) {
this.id = id;
this.type = type;
this.members = members;
+ this.piActionProfileId = piActionProfileId;
}
/**
@@ -81,18 +85,28 @@
return members;
}
+ /**
+ * Gets identifier of the action profile.
+ *
+ * @return action profile id
+ */
+ public PiActionProfileId actionProfileId() {
+ return piActionProfileId;
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
- if (o == null || getClass() != o.getClass()) {
+ if (o == null || !(o instanceof PiActionGroup)) {
return false;
}
PiActionGroup that = (PiActionGroup) o;
- return id == that.id &&
+ return Objects.equal(id, that.id) &&
Objects.equal(type, that.type) &&
- Objects.equal(members, that.members);
+ Objects.equal(members, that.members) &&
+ Objects.equal(piActionProfileId, that.piActionProfileId);
}
@Override
@@ -106,6 +120,7 @@
.add("groupId", id)
.add("type", type)
.add("members", members)
+ .add("piActionProfileId", piActionProfileId)
.toString();
}
@@ -126,6 +141,7 @@
private PiActionGroupId id;
private Type type;
private Map<PiActionGroupMemberId, PiActionGroupMember> members = Maps.newHashMap();
+ private PiActionProfileId piActionProfileId;
private Builder() {
// hides constructor.
@@ -176,6 +192,17 @@
}
/**
+ * Sets the identifier of the action profile.
+ *
+ * @param piActionProfileId the identifier of the action profile
+ * @return this
+ */
+ public Builder withActionProfileId(PiActionProfileId piActionProfileId) {
+ this.piActionProfileId = piActionProfileId;
+ return this;
+ }
+
+ /**
* Creates a new action group.
*
* @return action group
@@ -183,8 +210,11 @@
public PiActionGroup build() {
checkNotNull(id);
checkNotNull(type);
- checkArgument(members.size() > 0, "Members cannot be empty");
- return new PiActionGroup(id, type, ImmutableSet.copyOf(members.values()));
+ checkArgument(!members.isEmpty(), "Members cannot be empty");
+ checkNotNull(piActionProfileId);
+ return new PiActionGroup(id, type,
+ ImmutableSet.copyOf(members.values()),
+ piActionProfileId);
}
}
}
diff --git a/core/api/src/main/java/org/onosproject/net/pi/runtime/PiActionProfileId.java b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiActionProfileId.java
new file mode 100644
index 0000000..e0158c9
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/pi/runtime/PiActionProfileId.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2017-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.net.pi.runtime;
+
+import com.google.common.annotations.Beta;
+import org.onlab.util.Identifier;
+
+/**
+ * Identifier of an action profile of a protocol-independent pipeline.
+ */
+@Beta
+public final class PiActionProfileId extends Identifier<String> {
+
+ private PiActionProfileId(String actionProfileName) {
+ super(actionProfileName);
+ }
+
+ /**
+ * Returns action profile id with given action profile name.
+ *
+ * @param actionProfileName action profile name
+ * @return action profile id
+ */
+ public static PiActionProfileId of(String actionProfileName) {
+ return new PiActionProfileId(actionProfileName);
+ }
+}
diff --git a/core/api/src/test/java/org/onosproject/app/ApplicationEventTest.java b/core/api/src/test/java/org/onosproject/app/ApplicationEventTest.java
index 3cdedd2..61538f0 100644
--- a/core/api/src/test/java/org/onosproject/app/ApplicationEventTest.java
+++ b/core/api/src/test/java/org/onosproject/app/ApplicationEventTest.java
@@ -32,9 +32,22 @@
public class ApplicationEventTest extends AbstractEventTest {
private Application createApp() {
- return new DefaultApplication(APP_ID, VER, TITLE, DESC, ORIGIN, CATEGORY,
- URL, README, ICON, ROLE, PERMS,
- Optional.of(FURL), FEATURES, APPS);
+ return DefaultApplication.builder()
+ .withAppId(APP_ID)
+ .withVersion(VER)
+ .withTitle(TITLE)
+ .withDescription(DESC)
+ .withOrigin(ORIGIN)
+ .withCategory(CATEGORY)
+ .withUrl(URL)
+ .withReadme(README)
+ .withIcon(ICON)
+ .withRole(ROLE)
+ .withPermissions(PERMS)
+ .withFeaturesRepo(Optional.of(FURL))
+ .withFeatures(FEATURES)
+ .withRequiredApps(APPS)
+ .build();
}
@Test
@@ -53,4 +66,4 @@
validateEvent(event, APP_ACTIVATED, app, before, after);
}
-}
\ No newline at end of file
+}
diff --git a/core/api/src/test/java/org/onosproject/app/DefaultApplicationDescriptionTest.java b/core/api/src/test/java/org/onosproject/app/DefaultApplicationDescriptionTest.java
index ac8d971..a935c1b 100644
--- a/core/api/src/test/java/org/onosproject/app/DefaultApplicationDescriptionTest.java
+++ b/core/api/src/test/java/org/onosproject/app/DefaultApplicationDescriptionTest.java
@@ -29,6 +29,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
/**
@@ -53,12 +54,34 @@
public static final List<String> FEATURES = ImmutableList.of("foo", "bar");
public static final List<String> APPS = ImmutableList.of("fifi");
+ /**
+ * Checks that the DefaultApplicationDescription class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(DefaultApplicationDescription.class);
+ }
+
@Test
public void basics() {
ApplicationDescription app =
- new DefaultApplicationDescription(APP_NAME, VER, TITLE, DESC, ORIGIN,
- CATEGORY, URL, README, ICON,
- ROLE, PERMS, FURL, FEATURES, APPS);
+ DefaultApplicationDescription.builder()
+ .withName(APP_NAME)
+ .withVersion(VER)
+ .withTitle(TITLE)
+ .withDescription(DESC)
+ .withOrigin(ORIGIN)
+ .withCategory(CATEGORY)
+ .withUrl(URL)
+ .withReadme(README)
+ .withIcon(ICON)
+ .withRole(ROLE)
+ .withPermissions(PERMS)
+ .withFeaturesRepo(FURL)
+ .withFeatures(FEATURES)
+ .withRequiredApps(APPS)
+ .build();
+
assertEquals("incorrect id", APP_NAME, app.name());
assertEquals("incorrect version", VER, app.version());
assertEquals("incorrect title", TITLE, app.title());
@@ -74,4 +97,4 @@
assertEquals("incorrect apps", APPS, app.requiredApps());
assertTrue("incorrect toString", app.toString().contains(APP_NAME));
}
-}
\ No newline at end of file
+}
diff --git a/core/api/src/test/java/org/onosproject/core/DefaultApplicationTest.java b/core/api/src/test/java/org/onosproject/core/DefaultApplicationTest.java
index 38113bf..b523126 100644
--- a/core/api/src/test/java/org/onosproject/core/DefaultApplicationTest.java
+++ b/core/api/src/test/java/org/onosproject/core/DefaultApplicationTest.java
@@ -28,6 +28,9 @@
import java.util.Optional;
import java.util.Set;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+import static org.onosproject.core.DefaultApplication.Builder;
+
import static org.junit.Assert.*;
import static org.onosproject.app.DefaultApplicationDescriptionTest.*;
@@ -36,13 +39,35 @@
*/
public class DefaultApplicationTest {
+ /**
+ * Checks that the DefaultApplication class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(DefaultApplication.class);
+ }
+
public static final ApplicationId APP_ID = new DefaultApplicationId(2, APP_NAME);
+ private Builder baseBuilder = DefaultApplication.builder()
+ .withAppId(APP_ID)
+ .withVersion(VER)
+ .withTitle(TITLE)
+ .withDescription(DESC)
+ .withOrigin(ORIGIN)
+ .withCategory(CATEGORY)
+ .withUrl(URL)
+ .withReadme(README)
+ .withIcon(ICON)
+ .withRole(ROLE)
+ .withPermissions(PERMS)
+ .withFeaturesRepo(Optional.of(FURL))
+ .withFeatures(FEATURES)
+ .withRequiredApps(APPS);
@Test
public void basics() {
- Application app = new DefaultApplication(APP_ID, VER, TITLE, DESC, ORIGIN,
- CATEGORY, URL, README, ICON, ROLE,
- PERMS, Optional.of(FURL), FEATURES, APPS);
+ Application app = baseBuilder.build();
+
assertEquals("incorrect id", APP_ID, app.id());
assertEquals("incorrect version", VER, app.version());
assertEquals("incorrect title", TITLE, app.title());
@@ -62,20 +87,20 @@
@Test
public void testEquality() {
- Application a1 = new DefaultApplication(APP_ID, VER, TITLE, DESC, ORIGIN,
- CATEGORY, URL, README, ICON, ROLE,
- PERMS, Optional.of(FURL), FEATURES, APPS);
- Application a2 = new DefaultApplication(APP_ID, VER, TITLE, DESC, ORIGIN,
- CATEGORY, URL, README, ICON, ROLE,
- PERMS, Optional.of(FURL), FEATURES, APPS);
- Application a3 = new DefaultApplication(APP_ID, VER, TITLE, DESC, ORIGIN,
- CATEGORY, URL, README, ICON, ROLE,
- PERMS, Optional.empty(), FEATURES, APPS);
- Application a4 = new DefaultApplication(APP_ID, VER, TITLE, DESC, ORIGIN + "asd",
- CATEGORY, URL, README, ICON, ROLE,
- PERMS, Optional.of(FURL), FEATURES, APPS);
- new EqualsTester().addEqualityGroup(a1, a2)
- .addEqualityGroup(a3).addEqualityGroup(a4).testEquals();
+ Application a1 = baseBuilder.build();
+ Application a2 = DefaultApplication.builder(a1)
+ .build();
+ Application a3 = DefaultApplication.builder(baseBuilder)
+ .withFeaturesRepo(Optional.empty())
+ .build();
+ Application a4 = DefaultApplication.builder(baseBuilder)
+ .withOrigin(ORIGIN + "asd")
+ .build();
+ new EqualsTester()
+ .addEqualityGroup(a1, a2)
+ .addEqualityGroup(a3)
+ .addEqualityGroup(a4)
+ .testEquals();
}
@@ -85,9 +110,8 @@
public void immutableIcon() {
byte[] iconSourceData = ICON_ORIG.clone();
- Application app = new DefaultApplication(APP_ID, VER, TITLE, DESC, ORIGIN,
- CATEGORY, URL, README, iconSourceData, ROLE,
- PERMS, Optional.of(FURL), FEATURES, APPS);
+ Application app = DefaultApplication.builder(baseBuilder)
+ .withIcon(iconSourceData).build();
// can we modify the icon after getting a reference to the app?
byte[] icon = app.icon();
@@ -126,9 +150,7 @@
// Set<Permission> p = PERMS_ORIG;
Set<Permission> p = PERMS_UNSAFE;
- Application app = new DefaultApplication(APP_ID, VER, TITLE, DESC, ORIGIN,
- CATEGORY, URL, README, ICON, ROLE,
- p, Optional.of(FURL), FEATURES, APPS);
+ Application app = baseBuilder.build();
Set<Permission> perms = app.permissions();
try {
@@ -168,9 +190,7 @@
// List<String> f = FEATURES_ORIG;
List<String> f = FEATURES_UNSAFE;
- Application app = new DefaultApplication(APP_ID, VER, TITLE, DESC, ORIGIN,
- CATEGORY, URL, README, ICON, ROLE,
- PERMS, Optional.of(FURL), f, APPS);
+ Application app = DefaultApplication.builder(baseBuilder).withFeatures(f).build();
List<String> features = app.features();
try {
@@ -188,9 +208,7 @@
// List<String> ra = REQ_APPS_ORIG;
List<String> ra = REQ_APPS_UNSAFE;
- Application app = new DefaultApplication(APP_ID, VER, TITLE, DESC, ORIGIN,
- CATEGORY, URL, README, ICON, ROLE,
- PERMS, Optional.of(FURL), FEATURES, ra);
+ Application app = DefaultApplication.builder(baseBuilder).withRequiredApps(ra).build();
List<String> reqApps = app.requiredApps();
try {
@@ -204,11 +222,9 @@
@Test
public void nullIcon() {
- Application app = new DefaultApplication(APP_ID, VER, TITLE, DESC, ORIGIN,
- CATEGORY, URL, README, null, ROLE,
- PERMS, Optional.of(FURL), FEATURES, APPS);
+ Application app = DefaultApplication.builder(baseBuilder).withIcon(null).build();
byte[] icon = app.icon();
assertNotNull("null icon", icon);
assertEquals("unexpected size", 0, icon.length);
}
-}
\ No newline at end of file
+}
diff --git a/core/api/src/test/java/org/onosproject/net/behaviour/BridgeNameTest.java b/core/api/src/test/java/org/onosproject/net/behaviour/BridgeNameTest.java
new file mode 100644
index 0000000..ad23c9a
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/net/behaviour/BridgeNameTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2017-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.net.behaviour;
+
+import org.junit.Test;
+
+import com.google.common.testing.EqualsTester;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+public class BridgeNameTest {
+
+ private static final String NAME1 = "bridge-1";
+ private static final String NAME2 = "bridge-2";
+ private BridgeName bridgeName1 = BridgeName.bridgeName(NAME1);
+ private BridgeName sameAsBridgeName1 = BridgeName.bridgeName(NAME1);
+ private BridgeName bridgeName2 = BridgeName.bridgeName(NAME2);
+
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(BridgeName.class);
+ }
+
+ @Test
+ public void testConstruction() {
+ assertThat(bridgeName1.name(), is(NAME1));
+ }
+
+ @Test
+ public void testEquals() {
+ new EqualsTester()
+ .addEqualityGroup(bridgeName1, sameAsBridgeName1)
+ .addEqualityGroup(bridgeName2)
+ .testEquals();
+ }
+
+}
diff --git a/core/api/src/test/java/org/onosproject/net/behaviour/DefaultMirroringDescriptionTest.java b/core/api/src/test/java/org/onosproject/net/behaviour/DefaultMirroringDescriptionTest.java
new file mode 100644
index 0000000..2596f7b
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/net/behaviour/DefaultMirroringDescriptionTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2017-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.net.behaviour;
+
+import java.util.List;
+import java.util.Optional;
+
+import org.junit.Test;
+import org.onlab.packet.VlanId;
+
+import com.google.common.collect.ImmutableList;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+public class DefaultMirroringDescriptionTest {
+
+ private static final MirroringName NAME_1 = MirroringName.mirroringName("mirror1");
+ private static final List<String> MONITOR_SRC_PORTS_1 =
+ ImmutableList.of("s1", "s2", "s3");
+ private static final List<String> MONITOR_DST_PORTS_1 =
+ ImmutableList.of("d1", "d2");
+ private static final List<VlanId> MONITOR_VLANS_1 = ImmutableList.of(VlanId.ANY);
+ private static final Optional<String> MIRROR_PORT_1 = Optional.of("port1");
+ private static final Optional<VlanId> MIRROR_VLAN_1 = Optional.of(VlanId.ANY);
+ private MirroringDescription md1 =
+ new DefaultMirroringDescription(NAME_1, MONITOR_SRC_PORTS_1,
+ MONITOR_DST_PORTS_1, MONITOR_VLANS_1,
+ MIRROR_PORT_1, MIRROR_VLAN_1);
+
+
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(DefaultMirroringDescription.class);
+ }
+
+ @Test
+ public void testConstruction() {
+ assertThat(md1.name(), is(NAME_1));
+ assertThat(md1.monitorSrcPorts(), is(MONITOR_SRC_PORTS_1));
+ assertThat(md1.monitorDstPorts(), is(MONITOR_DST_PORTS_1));
+ assertThat(md1.monitorVlans(), is(MONITOR_VLANS_1));
+ assertThat(md1.mirrorPort(), is(MIRROR_PORT_1));
+ assertThat(md1.mirrorVlan(), is(MIRROR_VLAN_1));
+ }
+
+ @Test
+ public void testToString() {
+ String result = md1.toString();
+ assertThat(result, notNullValue());
+ assertThat(result, containsString("name=" + NAME_1.toString()));
+ assertThat(result, containsString("monitorsrcports=" + MONITOR_SRC_PORTS_1.toString()));
+ assertThat(result, containsString("monitordstports=" + MONITOR_DST_PORTS_1.toString()));
+ assertThat(result, containsString("monitorvlans=" + MONITOR_VLANS_1.toString()));
+ assertThat(result, containsString("mirrorport=" + MIRROR_PORT_1.toString()));
+ assertThat(result, containsString("mirrorvlan=" + MIRROR_VLAN_1.toString()));
+ }
+}
diff --git a/core/api/src/test/java/org/onosproject/net/behaviour/DefaultPatchDescriptionTest.java b/core/api/src/test/java/org/onosproject/net/behaviour/DefaultPatchDescriptionTest.java
new file mode 100644
index 0000000..34c4521
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/net/behaviour/DefaultPatchDescriptionTest.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2017-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.net.behaviour;
+
+import org.junit.Test;
+
+import com.google.common.testing.EqualsTester;
+
+import static com.spotify.hamcrest.optional.OptionalMatchers.optionalWithValue;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+
+public class DefaultPatchDescriptionTest {
+
+ private String deviceId1 = "d1";
+ private String ifaceName1 = "i1";
+ private String peerName1 = "p1";
+
+ private PatchDescription defaultPatchDescription1 =
+ DefaultPatchDescription.builder()
+ .deviceId(deviceId1)
+ .ifaceName(ifaceName1)
+ .peer(peerName1)
+ .build();
+ private PatchDescription sameAsDefaultPatchDescription1 =
+ DefaultPatchDescription.builder()
+ .deviceId(deviceId1)
+ .ifaceName(ifaceName1)
+ .peer(peerName1)
+ .build();
+ private PatchDescription defaultPatchDescription2 =
+ DefaultPatchDescription.builder()
+ .deviceId(deviceId1 + "2")
+ .ifaceName(ifaceName1)
+ .peer(peerName1)
+ .build();
+ private PatchDescription defaultPatchDescription3 =
+ DefaultPatchDescription.builder()
+ .deviceId(deviceId1)
+ .ifaceName(ifaceName1 + "2")
+ .peer(peerName1)
+ .build();
+ private PatchDescription defaultPatchDescription4 =
+ DefaultPatchDescription.builder()
+ .deviceId(deviceId1)
+ .ifaceName(ifaceName1)
+ .peer(peerName1 + "2")
+ .build();
+ private PatchDescription defaultPatchDescriptionNoDeviceId =
+ DefaultPatchDescription.builder()
+ .ifaceName(ifaceName1)
+ .peer(peerName1 + "2")
+ .build();
+
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(DefaultPatchDescription.class);
+ }
+
+ @Test
+ public void testConstruction() {
+ assertThat(defaultPatchDescription1.deviceId(), optionalWithValue(is(deviceId1)));
+ assertThat(defaultPatchDescription1.ifaceName(), is(ifaceName1));
+ assertThat(defaultPatchDescription1.peer(), is(peerName1));
+ }
+
+ @Test
+ public void testEquals() {
+ new EqualsTester()
+ .addEqualityGroup(defaultPatchDescription1, sameAsDefaultPatchDescription1)
+ .addEqualityGroup(defaultPatchDescription2)
+ .addEqualityGroup(defaultPatchDescription3)
+ .addEqualityGroup(defaultPatchDescription4)
+ .addEqualityGroup(defaultPatchDescriptionNoDeviceId)
+ .testEquals();
+ }
+}
diff --git a/core/api/src/test/java/org/onosproject/net/behaviour/DefaultQosDescriptionTest.java b/core/api/src/test/java/org/onosproject/net/behaviour/DefaultQosDescriptionTest.java
new file mode 100644
index 0000000..8196d74
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/net/behaviour/DefaultQosDescriptionTest.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2017-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.net.behaviour;
+
+import java.util.Map;
+
+import org.junit.Test;
+import org.onlab.util.Bandwidth;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.testing.EqualsTester;
+
+import static com.spotify.hamcrest.optional.OptionalMatchers.optionalWithValue;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+public class DefaultQosDescriptionTest {
+
+ private QosId qosId1 = QosId.qosId("1");
+ private Bandwidth bandwidth1 = Bandwidth.bps(1);
+ private Map<Long, QueueDescription> queues1 = ImmutableMap.of();
+
+ private QosDescription defaultQosDescription1 =
+ DefaultQosDescription.builder()
+ .qosId(qosId1)
+ .cbs(1L)
+ .cir(11L)
+ .maxRate(bandwidth1)
+ .queues(queues1)
+ .type(QosDescription.Type.NOOP)
+ .build();
+ private QosDescription sameAsDefaultQosDescription1 =
+ DefaultQosDescription.builder()
+ .qosId(qosId1)
+ .cbs(1L)
+ .cir(11L)
+ .maxRate(bandwidth1)
+ .queues(queues1)
+ .type(QosDescription.Type.NOOP)
+ .build();
+ private QosDescription defaultQosDescription2 =
+ DefaultQosDescription.builder()
+ .qosId(qosId1)
+ .cbs(2L)
+ .cir(11L)
+ .maxRate(bandwidth1)
+ .queues(queues1)
+ .type(QosDescription.Type.NOOP)
+ .build();
+ private QosDescription defaultQosDescription3 =
+ DefaultQosDescription.builder()
+ .qosId(qosId1)
+ .cbs(1L)
+ .cir(33L)
+ .maxRate(bandwidth1)
+ .queues(queues1)
+ .type(QosDescription.Type.NOOP)
+ .build();
+ private QosDescription defaultQosDescription4 =
+ DefaultQosDescription.builder()
+ .qosId(qosId1)
+ .cbs(1L)
+ .cir(11L)
+ .queues(queues1)
+ .type(QosDescription.Type.NOOP)
+ .build();
+ private QosDescription defaultQosDescription5 =
+ DefaultQosDescription.builder()
+ .qosId(qosId1)
+ .cbs(1L)
+ .cir(11L)
+ .maxRate(bandwidth1)
+ .type(QosDescription.Type.NOOP)
+ .build();
+ private QosDescription defaultQosDescription6 =
+ DefaultQosDescription.builder()
+ .qosId(qosId1)
+ .cbs(1L)
+ .cir(11L)
+ .maxRate(bandwidth1)
+ .queues(queues1)
+ .type(QosDescription.Type.CODEL)
+ .build();
+
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(DefaultQosDescription.class);
+ }
+
+ @Test
+ public void testConstruction() {
+ assertThat(defaultQosDescription1.qosId(), is(qosId1));
+ assertThat(defaultQosDescription1.cbs(), optionalWithValue(is(1L)));
+ assertThat(defaultQosDescription1.cir(), optionalWithValue(is(11L)));
+ assertThat(defaultQosDescription1.maxRate(), optionalWithValue(is(bandwidth1)));
+ assertThat(defaultQosDescription1.queues(), optionalWithValue(is(queues1)));
+ assertThat(defaultQosDescription1.type(), is(QosDescription.Type.NOOP));
+ }
+
+ @Test
+ public void testEquals() {
+ new EqualsTester()
+ .addEqualityGroup(defaultQosDescription1, sameAsDefaultQosDescription1)
+ .addEqualityGroup(defaultQosDescription2)
+ .addEqualityGroup(defaultQosDescription3)
+ .addEqualityGroup(defaultQosDescription4)
+ .addEqualityGroup(defaultQosDescription5)
+ .addEqualityGroup(defaultQosDescription6)
+ .testEquals();
+ }
+}
diff --git a/core/api/src/test/java/org/onosproject/net/behaviour/DefaultQueueDescriptionTest.java b/core/api/src/test/java/org/onosproject/net/behaviour/DefaultQueueDescriptionTest.java
index 6c495fb..99647cc 100644
--- a/core/api/src/test/java/org/onosproject/net/behaviour/DefaultQueueDescriptionTest.java
+++ b/core/api/src/test/java/org/onosproject/net/behaviour/DefaultQueueDescriptionTest.java
@@ -16,17 +16,15 @@
package org.onosproject.net.behaviour;
-import java.util.EnumSet;
-
+import com.google.common.testing.EqualsTester;
import org.junit.Test;
import org.onlab.util.Bandwidth;
-import com.google.common.testing.EqualsTester;
+import java.util.EnumSet;
-import static org.hamcrest.Matchers.contains;
+import static com.spotify.hamcrest.optional.OptionalMatchers.optionalWithValue;
+import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
public class DefaultQueueDescriptionTest {
@@ -71,17 +69,11 @@
@Test
public void testConstruction() {
- assertTrue(queueDescription1.burst().isPresent());
- assertThat(queueDescription1.burst().get(), is(1L));
- assertTrue(queueDescription1.dscp().isPresent());
- assertThat(queueDescription1.dscp().get(), is(11));
- assertTrue(queueDescription1.maxRate().isPresent());
- assertThat(queueDescription1.maxRate().get(), is(MAX_BANDWIDTH_1));
- assertTrue(queueDescription1.minRate().isPresent());
- assertThat(queueDescription1.minRate().get(), is(MIN_BANDWIDTH_1));
- assertThat(queueDescription1.type(), contains(QueueDescription.Type.MAX));
- assertTrue(queueDescription1.priority().isPresent());
- assertThat(queueDescription1.priority().get(), is(1L));
+ assertThat(queueDescription1.burst(), optionalWithValue(is(1L)));
+ assertThat(queueDescription1.dscp(), optionalWithValue(is(11)));
+ assertThat(queueDescription1.maxRate(), optionalWithValue(is(MAX_BANDWIDTH_1)));
+ assertThat(queueDescription1.minRate(), optionalWithValue(is(MIN_BANDWIDTH_1)));
+ assertThat(queueDescription1.priority(), optionalWithValue(is(1L)));
assertThat(queueDescription1.queueId(), is(QUEUE_ID1));
}
diff --git a/core/api/src/test/java/org/onosproject/net/behaviour/DefaultTunnelDescriptionTest.java b/core/api/src/test/java/org/onosproject/net/behaviour/DefaultTunnelDescriptionTest.java
index 5cd339f..4d9e2b9 100644
--- a/core/api/src/test/java/org/onosproject/net/behaviour/DefaultTunnelDescriptionTest.java
+++ b/core/api/src/test/java/org/onosproject/net/behaviour/DefaultTunnelDescriptionTest.java
@@ -16,15 +16,14 @@
package org.onosproject.net.behaviour;
+import com.google.common.testing.EqualsTester;
import org.junit.Test;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.SparseAnnotations;
-import com.google.common.testing.EqualsTester;
-
+import static com.spotify.hamcrest.optional.OptionalMatchers.optionalWithValue;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
public class DefaultTunnelDescriptionTest {
@@ -64,16 +63,12 @@
@Test
public void testConstruction() {
- assertTrue(tunnelDescription1.deviceId().isPresent());
- assertThat(tunnelDescription1.deviceId().get(), is(DID_1));
+ assertThat(tunnelDescription1.deviceId(), optionalWithValue(is(DID_1)));
assertThat(tunnelDescription1.ifaceName(), is(IFACE_NAME_1));
- assertTrue(tunnelDescription1.key().isPresent());
- assertThat(tunnelDescription1.key().get(), is(KEY_1));
+ assertThat(tunnelDescription1.key(), optionalWithValue(is(KEY_1)));
assertThat(tunnelDescription1.type(), is(TunnelDescription.Type.GRE));
- assertTrue(tunnelDescription1.local().isPresent());
- assertThat(tunnelDescription1.local().get(), is(LOCAL_1));
- assertTrue(tunnelDescription1.remote().isPresent());
- assertThat(tunnelDescription1.remote().get(), is(REMOTE_1));
+ assertThat(tunnelDescription1.local(), optionalWithValue(is(LOCAL_1)));
+ assertThat(tunnelDescription1.remote(), optionalWithValue(is(REMOTE_1)));
}
@Test
diff --git a/core/api/src/test/java/org/onosproject/net/behaviour/MirroringNameTest.java b/core/api/src/test/java/org/onosproject/net/behaviour/MirroringNameTest.java
new file mode 100644
index 0000000..bce584f
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/net/behaviour/MirroringNameTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2017-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.net.behaviour;
+
+import org.junit.Test;
+
+import com.google.common.testing.EqualsTester;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+public class MirroringNameTest {
+
+ private static final String NAME1 = "name1";
+ private MirroringName name1 = MirroringName.mirroringName(NAME1);
+ private MirroringName sameAsName1 = MirroringName.mirroringName(NAME1);
+ private static final String NAME2 = "name2";
+ private MirroringName name2 = MirroringName.mirroringName(NAME2);
+
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(MirroringName.class);
+ }
+
+ @Test
+ public void testConstruction() {
+ assertThat(name1.name(), is(NAME1));
+ }
+
+ @Test
+ public void testEquals() {
+ new EqualsTester()
+ .addEqualityGroup(name1, sameAsName1)
+ .addEqualityGroup(name2)
+ .testEquals();
+ }
+}
diff --git a/core/api/src/test/java/org/onosproject/net/behaviour/MirroringStatisticsTest.java b/core/api/src/test/java/org/onosproject/net/behaviour/MirroringStatisticsTest.java
new file mode 100644
index 0000000..b79da88
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/net/behaviour/MirroringStatisticsTest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2017-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.net.behaviour;
+
+import java.util.Map;
+
+import org.junit.Test;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.testing.EqualsTester;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+public class MirroringStatisticsTest {
+
+ private static final long BYTES_1 = 100L;
+ private static final long PACKETS_1 = 2L;
+ private static final String NAME_1 = "mirror1";
+ private Map<String, Integer> statistics1 =
+ ImmutableMap.of("tx_bytes", (int) BYTES_1, "tx_packets", (int) PACKETS_1);
+ private MirroringStatistics mirrorStatisticStats1 = MirroringStatistics.mirroringStatistics(NAME_1, statistics1);
+
+ private Map<String, Integer> sameAsStatistics1 =
+ ImmutableMap.of("tx_bytes", (int) BYTES_1, "tx_packets", (int) PACKETS_1);
+ private MirroringStatistics sameAsMirrorStatisticStats1 =
+ MirroringStatistics.mirroringStatistics(NAME_1, sameAsStatistics1);
+
+ private static final long BYTES_2 = 100L;
+ private static final long PACKETS_2 = 2L;
+ private static final String NAME_2 = "mirror2";
+ private Map<String, Integer> statistics2 =
+ ImmutableMap.of("tx_bytes", (int) BYTES_2, "tx_packets", (int) PACKETS_2);
+ private MirroringStatistics mirrorStatisticStats2 = MirroringStatistics.mirroringStatistics(NAME_2, statistics2);
+
+ private static final long BYTES_3 = 100L;
+ private static final long PACKETS_3 = 2L;
+ private static final String NAME_3 = "mirror3";
+ private Map<String, Integer> statistics3 =
+ ImmutableMap.of("tx_bytes", (int) BYTES_3, "tx_packets", (int) PACKETS_3);
+ private MirroringStatistics mirrorStatisticStats3 = MirroringStatistics.mirroringStatistics(NAME_3, statistics3);
+
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(MirroringStatistics.class);
+ }
+
+ @Test
+ public void testConstruction() {
+ assertThat(mirrorStatisticStats1.bytes(), is(BYTES_1));
+ assertThat(mirrorStatisticStats1.name().name(), is(NAME_1));
+ assertThat(mirrorStatisticStats1.packets(), is(PACKETS_1));
+ }
+
+ @Test
+ public void testEquals() {
+ new EqualsTester()
+ .addEqualityGroup(mirrorStatisticStats1, sameAsMirrorStatisticStats1)
+ .addEqualityGroup(mirrorStatisticStats2)
+ .addEqualityGroup(mirrorStatisticStats3)
+ .testEquals();
+ }
+}
diff --git a/core/api/src/test/java/org/onosproject/net/behaviour/QosIdTest.java b/core/api/src/test/java/org/onosproject/net/behaviour/QosIdTest.java
new file mode 100644
index 0000000..11f5c40
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/net/behaviour/QosIdTest.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2017-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.net.behaviour;
+
+public class QosIdTest {
+
+}
diff --git a/core/api/src/test/java/org/onosproject/net/behaviour/TunnelEndPointTest.java b/core/api/src/test/java/org/onosproject/net/behaviour/TunnelEndPointTest.java
new file mode 100644
index 0000000..af76773
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/net/behaviour/TunnelEndPointTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2017-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.net.behaviour;
+
+import org.junit.Test;
+import org.onlab.packet.MacAddress;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.NetTestTools;
+
+import com.google.common.testing.EqualsTester;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+public class TunnelEndPointTest {
+
+ private ConnectPoint cp1 = NetTestTools.connectPoint("cp1", 1);
+ private TunnelEndPoint<ConnectPoint> endPoint1 =
+ new TunnelEndPoint<>(cp1);
+ private TunnelEndPoint<ConnectPoint> sameAsEndPoint1 =
+ new TunnelEndPoint<>(cp1);
+
+ private ConnectPoint cp2 = NetTestTools.connectPoint("cp2", 2);
+ private TunnelEndPoint<ConnectPoint> endPoint2 =
+ new TunnelEndPoint<>(cp2);
+
+ private TunnelEndPoint<MacAddress> endPoint3 =
+ new TunnelEndPoint<>(MacAddress.BROADCAST);
+
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(TunnelEndPoint.class);
+ }
+
+ @Test
+ public void testConstruction() {
+ assertThat(endPoint1.value(), is(cp1));
+ assertThat(endPoint1.strValue(), is(cp1.toString()));
+ }
+
+ @Test
+ public void testEquals() {
+ new EqualsTester()
+ .addEqualityGroup(endPoint1, sameAsEndPoint1)
+ .addEqualityGroup(endPoint2)
+ .addEqualityGroup(endPoint3)
+ .testEquals();
+ }
+}
diff --git a/core/api/src/test/java/org/onosproject/net/flow/FlowRuleBatchOperationTest.java b/core/api/src/test/java/org/onosproject/net/flow/FlowRuleBatchOperationTest.java
index 2ff894c..0fa563f 100644
--- a/core/api/src/test/java/org/onosproject/net/flow/FlowRuleBatchOperationTest.java
+++ b/core/api/src/test/java/org/onosproject/net/flow/FlowRuleBatchOperationTest.java
@@ -18,6 +18,8 @@
import java.util.LinkedList;
import org.junit.Test;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchEntry;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchOperation;
import org.onosproject.net.intent.IntentTestsMocks;
import com.google.common.testing.EqualsTester;
diff --git a/core/api/src/test/java/org/onosproject/net/flow/FlowRuleBatchRequestTest.java b/core/api/src/test/java/org/onosproject/net/flow/FlowRuleBatchRequestTest.java
index a06e84a..ca263ee 100644
--- a/core/api/src/test/java/org/onosproject/net/flow/FlowRuleBatchRequestTest.java
+++ b/core/api/src/test/java/org/onosproject/net/flow/FlowRuleBatchRequestTest.java
@@ -16,6 +16,9 @@
package org.onosproject.net.flow;
import org.junit.Test;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchEntry;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchOperation;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchRequest;
import org.onosproject.net.intent.IntentTestsMocks;
import java.util.HashSet;
@@ -25,8 +28,8 @@
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
-import static org.onosproject.net.flow.FlowRuleBatchEntry.FlowRuleOperation.ADD;
-import static org.onosproject.net.flow.FlowRuleBatchEntry.FlowRuleOperation.REMOVE;
+import static org.onosproject.net.flow.oldbatch.FlowRuleBatchEntry.FlowRuleOperation.ADD;
+import static org.onosproject.net.flow.oldbatch.FlowRuleBatchEntry.FlowRuleOperation.REMOVE;
/**
* Unit tests for the FlowRuleBatchRequest class.
diff --git a/core/api/src/test/java/org/onosproject/net/pi/runtime/PiActionGroupTest.java b/core/api/src/test/java/org/onosproject/net/pi/runtime/PiActionGroupTest.java
index e9b736b..0da15e4 100644
--- a/core/api/src/test/java/org/onosproject/net/pi/runtime/PiActionGroupTest.java
+++ b/core/api/src/test/java/org/onosproject/net/pi/runtime/PiActionGroupTest.java
@@ -28,6 +28,7 @@
import static org.hamcrest.Matchers.notNullValue;
import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
import static org.onlab.util.ImmutableByteSequence.copyFrom;
+import static org.onosproject.net.pi.runtime.PiConstantsTest.ACTION_PROF_ID;
import static org.onosproject.net.pi.runtime.PiConstantsTest.DST_ADDR;
import static org.onosproject.net.pi.runtime.PiConstantsTest.MOD_NW_DST;
@@ -51,12 +52,14 @@
.addMember(piActionGroupMember)
.withId(piActionGroupId)
.withType(PiActionGroup.Type.SELECT)
+ .withActionProfileId(ACTION_PROF_ID)
.build();
PiActionGroup sameAsPiActionGroup1 = PiActionGroup.builder()
.addMember(piActionGroupMember)
.withId(piActionGroupId)
.withType(PiActionGroup.Type.SELECT)
+ .withActionProfileId(ACTION_PROF_ID)
.build();
PiActionGroupId piActionGroupId2 = PiActionGroupId.of(20);
@@ -64,6 +67,7 @@
.addMember(piActionGroupMember)
.withId(piActionGroupId2)
.withType(PiActionGroup.Type.SELECT)
+ .withActionProfileId(ACTION_PROF_ID)
.build();
/**
diff --git a/core/api/src/test/java/org/onosproject/net/pi/runtime/PiConstantsTest.java b/core/api/src/test/java/org/onosproject/net/pi/runtime/PiConstantsTest.java
index b2bda37..86f713d 100644
--- a/core/api/src/test/java/org/onosproject/net/pi/runtime/PiConstantsTest.java
+++ b/core/api/src/test/java/org/onosproject/net/pi/runtime/PiConstantsTest.java
@@ -38,4 +38,7 @@
public static final String EGRESS_PORT = "egress_port";
public static final String INGRESS_PORT = "ingress_port";
+
+ public static final PiActionProfileId ACTION_PROF_ID =
+ PiActionProfileId.of("Test action profile");
}
diff --git a/core/api/src/test/java/org/onosproject/net/topology/AbstractPathServiceTest.java b/core/api/src/test/java/org/onosproject/net/topology/AbstractPathServiceTest.java
new file mode 100644
index 0000000..d8d14e9
--- /dev/null
+++ b/core/api/src/test/java/org/onosproject/net/topology/AbstractPathServiceTest.java
@@ -0,0 +1,269 @@
+/*
+ * Copyright 2017-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.net.topology;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.graph.ScalarWeight;
+import org.onlab.graph.Weight;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DefaultDisjointPath;
+import org.onosproject.net.DefaultLink;
+import org.onosproject.net.DefaultPath;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.DisjointPath;
+import org.onosproject.net.ElementId;
+import org.onosproject.net.HostId;
+import org.onosproject.net.Link;
+import org.onosproject.net.NetTestTools;
+import org.onosproject.net.Path;
+import org.onosproject.net.host.HostServiceAdapter;
+import org.onosproject.net.provider.ProviderId;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.empty;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.hamcrest.Matchers.nullValue;
+import static org.onosproject.net.NetTestTools.did;
+import static org.onosproject.net.NetTestTools.hid;
+
+public class AbstractPathServiceTest {
+
+ private TestPathService service;
+ private FakeTopoMgr topoMgr;
+
+ private ConnectPoint cpA = NetTestTools.connectPoint("A", 1);
+ private ConnectPoint cpB = NetTestTools.connectPoint("B", 2);
+ private ConnectPoint cpC = NetTestTools.connectPoint("C", 3);
+ private ProviderId pid = ProviderId.NONE;
+ private Link link1 = DefaultLink.builder()
+ .providerId(pid)
+ .src(cpA)
+ .dst(cpB)
+ .type(Link.Type.DIRECT)
+ .state(Link.State.ACTIVE)
+ .build();
+ private Link link2 = DefaultLink.builder()
+ .providerId(pid)
+ .src(cpB)
+ .dst(cpC)
+ .type(Link.Type.DIRECT)
+ .state(Link.State.ACTIVE)
+ .build();
+ private List<Link> links1 = ImmutableList.of(link1, link2);
+ private Path path1 = new DefaultPath(pid, links1, new ScalarWeight(1.0));
+
+
+
+ private class TestPathService extends AbstractPathService {
+ Set<Path> paths = null;
+ Set<DisjointPath> disjointPaths = null;
+
+ @Override
+ public Set<Path> getPaths(ElementId src, ElementId dst) {
+ return paths;
+ }
+
+ @Override
+ public Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst) {
+ return disjointPaths;
+ }
+
+ @Override
+ public Set<DisjointPath> getDisjointPaths(ElementId src, ElementId dst, Map<Link, Object> riskProfile) {
+ return disjointPaths;
+ }
+ }
+
+ class TestWeigher implements LinkWeigher {
+ @Override
+ public Weight weight(TopologyEdge edge) {
+ return new ScalarWeight(1.0);
+ }
+
+ @Override
+ public Weight getInitialWeight() {
+ return new ScalarWeight(1.0);
+ }
+
+ @Override
+ public Weight getNonViableWeight() {
+ return new ScalarWeight(0.0);
+ }
+ }
+
+ // Fake entity to give out paths.
+ private class FakeTopoMgr extends TopologyServiceAdapter {
+
+ Set<Path> paths = new HashSet<>();
+ Set<DisjointPath> disjointPaths = new HashSet<>();
+
+ void definePaths(Set<Path> paths) {
+ this.paths = paths;
+ this.disjointPaths = paths.stream()
+ .map(path ->
+ new DefaultDisjointPath(path.providerId(),
+ (DefaultPath) path))
+ .collect(Collectors.toSet());
+ }
+
+ @Override
+ public Set<Path> getPaths(Topology topology, DeviceId src,
+ DeviceId dst) {
+ return paths;
+ }
+
+ @Override
+ public Set<Path> getPaths(Topology topology, DeviceId src,
+ DeviceId dst, LinkWeigher weight) {
+ return paths;
+ }
+
+ @Override
+ public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src,
+ DeviceId dst,
+ LinkWeigher weigher) {
+ return disjointPaths;
+ }
+
+ @Override
+ public Set<DisjointPath> getDisjointPaths(Topology topology, DeviceId src,
+ DeviceId dst,
+ LinkWeigher weigher,
+ Map<Link, Object> riskProfile) {
+ return disjointPaths;
+ }
+ }
+
+ @Before
+ public void setUp() {
+ service = new TestPathService();
+ topoMgr = new FakeTopoMgr();
+ service.topologyService = topoMgr;
+ service.hostService = new HostServiceAdapter();
+ }
+
+ private void checkPathValues(Path path) {
+ assertThat(path, notNullValue());
+ assertThat(path.links(), hasSize(2));
+ assertThat(path.links().get(0).src(), is(cpA));
+ assertThat(path.links().get(0).dst(), is(cpB));
+ assertThat(path.links().get(1).src(), is(cpB));
+ assertThat(path.links().get(1).dst(), is(cpC));
+ }
+
+ private void checkDisjointPaths(Set<DisjointPath> paths) {
+ assertThat(paths, notNullValue());
+ assertThat(paths, hasSize(1));
+ Path path = paths.iterator().next();
+ checkPathValues(path);
+ }
+
+ private void checkPaths(Collection<Path> paths) {
+ assertThat(paths, notNullValue());
+ assertThat(paths, hasSize(1));
+ Path path = paths.iterator().next();
+ checkPathValues(path);
+ }
+
+ /**
+ * Tests no paths being set up.
+ */
+ @Test
+ public void testNoPaths() {
+ Set<Path> noPaths = service.getPaths(did("A"), did("B"), new TestWeigher());
+ assertThat(noPaths, empty());
+ }
+
+ /**
+ * Tests paths from a host.
+ */
+ @Test
+ public void testSelfPaths() {
+ HostId host = hid("12:34:56:78:90:ab/1");
+ Set<Path> paths = service.getPaths(host, host, new TestWeigher());
+ assertThat(paths, hasSize(1));
+ Path path = paths.iterator().next();
+ assertThat(path, not(nullValue()));
+ assertThat(path.links(), hasSize(2));
+ Link link1 = path.links().get(0);
+ Link link2 = path.links().get(1);
+ assertThat(link1.src(), is(link2.dst()));
+ assertThat(link2.src(), is(link1.dst()));
+ assertThat(link1.src().hostId(), is(host));
+ assertThat(link2.dst().hostId(), is(host));
+ }
+
+ /**
+ * Tests paths from a device to a device.
+ */
+ @Test
+ public void testDevicePaths() {
+ topoMgr.definePaths(ImmutableSet.of(path1));
+ Set<Path> pathsAC = service.getPaths(did("A"), did("C"), new TestWeigher());
+ checkPaths(pathsAC);
+ }
+
+ /**
+ * Tests K Shortest Path computation.
+ */
+ @Test
+ public void testKShortestPath() {
+ topoMgr.definePaths(ImmutableSet.of(path1));
+ List<Path> paths = service.getKShortestPaths(did("A"), did("C"), new TestWeigher())
+ .collect(Collectors.toList());
+ checkPaths(paths);
+ }
+
+ /**
+ * Tests disjoint paths.
+ */
+ @Test
+ public void testDisjointPaths() {
+ topoMgr.definePaths(ImmutableSet.of(path1));
+ Set<DisjointPath> paths = service.getDisjointPaths(did("A"), did("C"), new TestWeigher());
+ checkDisjointPaths(paths);
+ }
+
+ /**
+ * Tests disjoint paths with a risk profile.
+ */
+ @Test
+ public void testDisjointPathsWithRiskProfile() {
+ topoMgr.definePaths(ImmutableSet.of(path1));
+ Map<Link, Object> riskProfile = ImmutableMap.of();
+
+ Set<DisjointPath> paths =
+ service.getDisjointPaths(did("A"), did("C"), new TestWeigher(),
+ riskProfile);
+
+ checkDisjointPaths(paths);
+ }
+}
diff --git a/core/common/src/main/java/org/onosproject/common/app/ApplicationArchive.java b/core/common/src/main/java/org/onosproject/common/app/ApplicationArchive.java
index 92709cb..55c198e 100644
--- a/core/common/src/main/java/org/onosproject/common/app/ApplicationArchive.java
+++ b/core/common/src/main/java/org/onosproject/common/app/ApplicationArchive.java
@@ -328,10 +328,22 @@
// put short description to description field
String desc = compactDescription(readme);
- return new DefaultApplicationDescription(name, version, title, desc, origin,
- category, url, readme, icon,
- role, perms, featuresRepo,
- features, requiredApps);
+ return DefaultApplicationDescription.builder()
+ .withName(name)
+ .withVersion(version)
+ .withTitle(title)
+ .withDescription(desc)
+ .withOrigin(origin)
+ .withCategory(category)
+ .withUrl(url)
+ .withReadme(readme)
+ .withIcon(icon)
+ .withRole(role)
+ .withPermissions(perms)
+ .withFeaturesRepo(featuresRepo)
+ .withFeatures(features)
+ .withRequiredApps(requiredApps)
+ .build();
}
// Expands the specified ZIP stream into app-specific directory.
diff --git a/core/common/src/test/java/org/onosproject/store/trivial/SimpleApplicationStore.java b/core/common/src/test/java/org/onosproject/store/trivial/SimpleApplicationStore.java
index ec05afb..c904455 100644
--- a/core/common/src/test/java/org/onosproject/store/trivial/SimpleApplicationStore.java
+++ b/core/common/src/test/java/org/onosproject/store/trivial/SimpleApplicationStore.java
@@ -76,20 +76,11 @@
ApplicationId appId = idStore.registerApplication(name);
ApplicationDescription appDesc = getApplicationDescription(name);
DefaultApplication app =
- new DefaultApplication(appId,
- appDesc.version(),
- appDesc.title(),
- appDesc.description(),
- appDesc.origin(),
- appDesc.category(),
- appDesc.url(),
- appDesc.readme(),
- appDesc.icon(),
- appDesc.role(),
- appDesc.permissions(),
- appDesc.featuresRepo(),
- appDesc.features(),
- appDesc.requiredApps());
+ DefaultApplication
+ .builder(appDesc)
+ .withAppId(appId)
+ .build();
+
apps.put(appId, app);
states.put(appId, isActive(name) ? INSTALLED : ACTIVE);
// load app permissions
@@ -129,20 +120,11 @@
ApplicationDescription appDesc = saveApplication(appDescStream);
ApplicationId appId = idStore.registerApplication(appDesc.name());
DefaultApplication app =
- new DefaultApplication(appId,
- appDesc.version(),
- appDesc.title(),
- appDesc.description(),
- appDesc.origin(),
- appDesc.category(),
- appDesc.url(),
- appDesc.readme(),
- appDesc.icon(),
- appDesc.role(),
- appDesc.permissions(),
- appDesc.featuresRepo(),
- appDesc.features(),
- appDesc.requiredApps());
+ DefaultApplication
+ .builder(appDesc)
+ .withAppId(appId)
+ .build();
+
apps.put(appId, app);
states.put(appId, INSTALLED);
delegate.notify(new ApplicationEvent(APP_INSTALLED, app));
diff --git a/core/common/src/test/java/org/onosproject/store/trivial/SimpleFlowRuleStore.java b/core/common/src/test/java/org/onosproject/store/trivial/SimpleFlowRuleStore.java
index 29e9a65..02cd8ec 100644
--- a/core/common/src/test/java/org/onosproject/store/trivial/SimpleFlowRuleStore.java
+++ b/core/common/src/test/java/org/onosproject/store/trivial/SimpleFlowRuleStore.java
@@ -39,11 +39,11 @@
import org.onosproject.net.flow.FlowEntry.FlowEntryState;
import org.onosproject.net.flow.FlowId;
import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.FlowRuleBatchEntry;
-import org.onosproject.net.flow.FlowRuleBatchEntry.FlowRuleOperation;
-import org.onosproject.net.flow.FlowRuleBatchEvent;
-import org.onosproject.net.flow.FlowRuleBatchOperation;
-import org.onosproject.net.flow.FlowRuleBatchRequest;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchEntry;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchEntry.FlowRuleOperation;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchEvent;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchOperation;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchRequest;
import org.onosproject.net.flow.FlowRuleEvent;
import org.onosproject.net.flow.FlowRuleEvent.Type;
import org.onosproject.net.flow.FlowRuleStore;
diff --git a/core/common/src/test/java/org/onosproject/utils/ComparatorsTest.java b/core/common/src/test/java/org/onosproject/utils/ComparatorsTest.java
index 8562d7e..6047719 100644
--- a/core/common/src/test/java/org/onosproject/utils/ComparatorsTest.java
+++ b/core/common/src/test/java/org/onosproject/utils/ComparatorsTest.java
@@ -161,9 +161,22 @@
}
private Application app(int id, String name) {
- return new DefaultApplication(new DefaultApplicationId(id, name), VER, TITLE, DESC, ORIGIN,
- CATEGORY, URL, README, ICON, ROLE,
- PERMS, Optional.of(FURL), FEATURES, APPS);
+ return DefaultApplication.builder()
+ .withAppId(new DefaultApplicationId(id, name))
+ .withVersion(VER)
+ .withTitle(TITLE)
+ .withDescription(DESC)
+ .withOrigin(ORIGIN)
+ .withCategory(CATEGORY)
+ .withUrl(URL)
+ .withReadme(README)
+ .withIcon(ICON)
+ .withRole(ROLE)
+ .withPermissions(PERMS)
+ .withFeaturesRepo(Optional.of(FURL))
+ .withFeatures(FEATURES)
+ .withRequiredApps(APPS)
+ .build();
}
@Test
diff --git a/core/net/src/main/java/org/onosproject/net/flow/impl/FlowRuleDriverProvider.java b/core/net/src/main/java/org/onosproject/net/flow/impl/FlowRuleDriverProvider.java
index c4dc883..c058ab6 100644
--- a/core/net/src/main/java/org/onosproject/net/flow/impl/FlowRuleDriverProvider.java
+++ b/core/net/src/main/java/org/onosproject/net/flow/impl/FlowRuleDriverProvider.java
@@ -30,8 +30,8 @@
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.flow.CompletedBatchOperation;
import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.FlowRuleBatchEntry;
-import org.onosproject.net.flow.FlowRuleBatchOperation;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchEntry;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchOperation;
import org.onosproject.net.flow.FlowRuleProgrammable;
import org.onosproject.net.flow.FlowRuleProvider;
import org.onosproject.net.flow.FlowRuleProviderService;
@@ -50,7 +50,7 @@
import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
import static org.onlab.util.Tools.groupedThreads;
import static org.onosproject.net.device.DeviceEvent.Type.*;
-import static org.onosproject.net.flow.FlowRuleBatchEntry.FlowRuleOperation.*;
+import static org.onosproject.net.flow.oldbatch.FlowRuleBatchEntry.FlowRuleOperation.*;
/**
* Driver-based flow rule provider.
diff --git a/core/net/src/main/java/org/onosproject/net/flow/impl/FlowRuleManager.java b/core/net/src/main/java/org/onosproject/net/flow/impl/FlowRuleManager.java
index 04b73d0..47623a7 100644
--- a/core/net/src/main/java/org/onosproject/net/flow/impl/FlowRuleManager.java
+++ b/core/net/src/main/java/org/onosproject/net/flow/impl/FlowRuleManager.java
@@ -45,10 +45,10 @@
import org.onosproject.net.flow.DefaultFlowEntry;
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.FlowRuleBatchEntry;
-import org.onosproject.net.flow.FlowRuleBatchEvent;
-import org.onosproject.net.flow.FlowRuleBatchOperation;
-import org.onosproject.net.flow.FlowRuleBatchRequest;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchEntry;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchEvent;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchOperation;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchRequest;
import org.onosproject.net.flow.FlowRuleEvent;
import org.onosproject.net.flow.FlowRuleListener;
import org.onosproject.net.flow.FlowRuleOperation;
diff --git a/core/net/src/main/java/org/onosproject/net/pi/impl/PiFlowRuleTranslator.java b/core/net/src/main/java/org/onosproject/net/pi/impl/PiFlowRuleTranslator.java
index 25465e9..f8775c8 100644
--- a/core/net/src/main/java/org/onosproject/net/pi/impl/PiFlowRuleTranslator.java
+++ b/core/net/src/main/java/org/onosproject/net/pi/impl/PiFlowRuleTranslator.java
@@ -131,8 +131,8 @@
Collection<PiFieldMatch> fieldMatches = buildFieldMatches(interpreter, rule.selector(), table);
/* Translate treatment */
- PiAction piAction = buildAction(rule.treatment(), interpreter, piTableId);
- piAction = typeCheckAction(piAction, table);
+ PiTableAction piTableAction = buildAction(rule.treatment(), interpreter, piTableId);
+ piTableAction = typeCheckAction(piTableAction, table);
PiTableEntry.Builder tableEntryBuilder = PiTableEntry.builder();
@@ -154,7 +154,7 @@
.withMatchKey(PiMatchKey.builder()
.addFieldMatches(fieldMatches)
.build())
- .withAction(piAction);
+ .withAction(piTableAction);
if (!rule.isPermanent()) {
if (table.supportsAging()) {
@@ -172,7 +172,7 @@
/**
* Builds a PI action out of the given treatment, optionally using the given interpreter.
*/
- private static PiAction buildAction(TrafficTreatment treatment, PiPipelineInterpreter interpreter,
+ private static PiTableAction buildAction(TrafficTreatment treatment, PiPipelineInterpreter interpreter,
PiTableId tableId)
throws PiFlowRuleTranslationException {
@@ -208,22 +208,28 @@
+ "protocol-independent instruction were provided.");
}
- if (piTableAction.type() != PiTableAction.Type.ACTION) {
- // TODO: implement handling of other table action types, e.g. action profiles.
- throw new PiFlowRuleTranslationException(format(
- "PiTableAction type %s is not supported yet.", piTableAction.type()));
- }
-
- return (PiAction) piTableAction;
+ return piTableAction;
}
/**
- * Checks that the given PI action is suitable for the given table model and returns a new action instance with
- * parameters well-sized, according to the table model. If not suitable, throws an exception explaining why.
+ * Checks that the given PI table action is suitable for the given table
+ * model and returns a new action instance with parameters well-sized,
+ * according to the table model. If not suitable, throws an exception explaining why.
*/
- private static PiAction typeCheckAction(PiAction piAction, PiTableModel table)
+ private static PiTableAction typeCheckAction(PiTableAction piTableAction, PiTableModel table)
throws PiFlowRuleTranslationException {
+ switch (piTableAction.type()) {
+ case ACTION:
+ return checkPiAction((PiAction) piTableAction, table);
+ default:
+ // FIXME: should we check? how?
+ return piTableAction;
+ }
+ }
+
+ private static PiTableAction checkPiAction(PiAction piAction, PiTableModel table)
+ throws PiFlowRuleTranslationException {
// Table supports this action?
PiActionModel actionModel = table.action(piAction.id().name()).orElseThrow(
() -> new PiFlowRuleTranslationException(format("Not such action '%s' for table '%s'",
diff --git a/core/net/src/test/java/org/onosproject/app/impl/ApplicationManagerTest.java b/core/net/src/test/java/org/onosproject/app/impl/ApplicationManagerTest.java
index 5fd7701..5528f26 100644
--- a/core/net/src/test/java/org/onosproject/app/impl/ApplicationManagerTest.java
+++ b/core/net/src/test/java/org/onosproject/app/impl/ApplicationManagerTest.java
@@ -15,7 +15,6 @@
*/
package org.onosproject.app.impl;
-import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import org.junit.After;
import org.junit.Before;
@@ -138,9 +137,22 @@
@Override
public Application create(InputStream appDescStream) {
- app = new DefaultApplication(APP_ID, VER, TITLE, DESC, ORIGIN, CATEGORY,
- URL, README, ICON, ROLE, PERMS,
- Optional.of(FURL), FEATURES, ImmutableList.of());
+ app = DefaultApplication.builder()
+ .withAppId(APP_ID)
+ .withVersion(VER)
+ .withTitle(TITLE)
+ .withDescription(DESC)
+ .withOrigin(ORIGIN)
+ .withCategory(CATEGORY)
+ .withUrl(URL)
+ .withReadme(README)
+ .withIcon(ICON)
+ .withRole(ROLE)
+ .withPermissions(PERMS)
+ .withFeaturesRepo(Optional.of(FURL))
+ .withFeatures(FEATURES)
+ .withRequiredApps(APPS)
+ .build();
state = INSTALLED;
delegate.notify(new ApplicationEvent(APP_INSTALLED, app));
return app;
@@ -211,4 +223,4 @@
}
}
-}
\ No newline at end of file
+}
diff --git a/core/net/src/test/java/org/onosproject/net/flow/impl/FlowRuleManagerTest.java b/core/net/src/test/java/org/onosproject/net/flow/impl/FlowRuleManagerTest.java
index 08f3373..825ef1a 100644
--- a/core/net/src/test/java/org/onosproject/net/flow/impl/FlowRuleManagerTest.java
+++ b/core/net/src/test/java/org/onosproject/net/flow/impl/FlowRuleManagerTest.java
@@ -51,7 +51,7 @@
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowEntry.FlowEntryState;
import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.FlowRuleBatchOperation;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchOperation;
import org.onosproject.net.flow.FlowRuleEvent;
import org.onosproject.net.flow.FlowRuleListener;
import org.onosproject.net.flow.FlowRuleProgrammable;
diff --git a/core/security/src/test/java/org/onosproject/security/impl/SecurityModeManagerTest.java b/core/security/src/test/java/org/onosproject/security/impl/SecurityModeManagerTest.java
index 15155ff..328d903 100644
--- a/core/security/src/test/java/org/onosproject/security/impl/SecurityModeManagerTest.java
+++ b/core/security/src/test/java/org/onosproject/security/impl/SecurityModeManagerTest.java
@@ -69,11 +69,22 @@
testFeatures.add("testFeature");
testRequiredApps = new ArrayList<String>();
testRequiredApps.add("testRequiredApp");
- app = new DefaultApplication(appId, Version.version(1, 1, "patch", "build"), "testTitle",
- "testDes", "testOri", "testCT",
- "testurl", "test", null,
- ApplicationRole.ADMIN, testPermissions,
- Optional.ofNullable(null), testFeatures, testRequiredApps);
+ app = DefaultApplication.builder()
+ .withAppId(appId)
+ .withVersion(Version.version(1, 1, "patch", "build"))
+ .withTitle("testTitle")
+ .withDescription("testDes")
+ .withOrigin("testOri")
+ .withCategory("testCT")
+ .withUrl("testurl")
+ .withReadme("test")
+ .withIcon(null)
+ .withRole(ApplicationRole.ADMIN)
+ .withPermissions(testPermissions)
+ .withFeaturesRepo(Optional.ofNullable(null))
+ .withFeatures(testFeatures)
+ .withRequiredApps(testRequiredApps)
+ .build();
store.registerApplication(appId);
}
diff --git a/core/security/src/test/java/org/onosproject/security/store/DistributedSecurityModeStoreTest.java b/core/security/src/test/java/org/onosproject/security/store/DistributedSecurityModeStoreTest.java
index f3e38bf..220b44e 100644
--- a/core/security/src/test/java/org/onosproject/security/store/DistributedSecurityModeStoreTest.java
+++ b/core/security/src/test/java/org/onosproject/security/store/DistributedSecurityModeStoreTest.java
@@ -79,11 +79,22 @@
testFeatures.add("testFeature");
testRequiredApps = new ArrayList<String>();
testRequiredApps.add("testRequiredApp");
- app = new DefaultApplication(appId, Version.version(1, 1, "patch", "build"), "testTitle",
- "testDes", "testOri", "testCT",
- "testurl", "test", null,
- ApplicationRole.ADMIN, testPermissions,
- Optional.ofNullable(null), testFeatures, testRequiredApps);
+ app = DefaultApplication.builder()
+ .withAppId(appId)
+ .withVersion(Version.version(1, 1, "patch", "build"))
+ .withTitle("testTitle")
+ .withDescription("testDes")
+ .withOrigin("testOri")
+ .withCategory("testCT")
+ .withUrl("testurl")
+ .withReadme("test")
+ .withIcon(null)
+ .withRole(ApplicationRole.ADMIN)
+ .withPermissions(testPermissions)
+ .withFeaturesRepo(Optional.ofNullable(null))
+ .withFeatures(testFeatures)
+ .withRequiredApps(testRequiredApps)
+ .build();
testLocations = new HashSet<String>();
testLocations.add("locationA");
diff --git a/core/store/dist/src/main/java/org/onosproject/store/app/DistributedApplicationStore.java b/core/store/dist/src/main/java/org/onosproject/store/app/DistributedApplicationStore.java
index 532b279..c65d1aa 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/app/DistributedApplicationStore.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/app/DistributedApplicationStore.java
@@ -571,20 +571,10 @@
*/
private Application registerApp(ApplicationDescription appDesc) {
ApplicationId appId = idStore.registerApplication(appDesc.name());
- return new DefaultApplication(appId,
- appDesc.version(),
- appDesc.title(),
- appDesc.description(),
- appDesc.origin(),
- appDesc.category(),
- appDesc.url(),
- appDesc.readme(),
- appDesc.icon(),
- appDesc.role(),
- appDesc.permissions(),
- appDesc.featuresRepo(),
- appDesc.features(),
- appDesc.requiredApps());
+ return DefaultApplication
+ .builder(appDesc)
+ .withAppId(appId)
+ .build();
}
/**
diff --git a/core/store/dist/src/main/java/org/onosproject/store/flow/impl/DistributedFlowRuleStore.java b/core/store/dist/src/main/java/org/onosproject/store/flow/impl/DistributedFlowRuleStore.java
index e2d485f..c4c7485 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/flow/impl/DistributedFlowRuleStore.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/flow/impl/DistributedFlowRuleStore.java
@@ -55,11 +55,11 @@
import org.onosproject.net.flow.FlowEntry.FlowEntryState;
import org.onosproject.net.flow.FlowId;
import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.FlowRuleBatchEntry;
-import org.onosproject.net.flow.FlowRuleBatchEntry.FlowRuleOperation;
-import org.onosproject.net.flow.FlowRuleBatchEvent;
-import org.onosproject.net.flow.FlowRuleBatchOperation;
-import org.onosproject.net.flow.FlowRuleBatchRequest;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchEntry;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchEntry.FlowRuleOperation;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchEvent;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchOperation;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchRequest;
import org.onosproject.net.flow.FlowRuleEvent;
import org.onosproject.net.flow.FlowRuleEvent.Type;
import org.onosproject.net.flow.FlowRuleService;
diff --git a/core/store/dist/src/test/java/org/onosproject/store/flow/impl/DistributedFlowRuleStoreTest.java b/core/store/dist/src/test/java/org/onosproject/store/flow/impl/DistributedFlowRuleStoreTest.java
index 8144d22..449190d 100644
--- a/core/store/dist/src/test/java/org/onosproject/store/flow/impl/DistributedFlowRuleStoreTest.java
+++ b/core/store/dist/src/test/java/org/onosproject/store/flow/impl/DistributedFlowRuleStoreTest.java
@@ -36,8 +36,8 @@
import org.onosproject.net.flow.DefaultFlowRule;
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.FlowRuleBatchEntry;
-import org.onosproject.net.flow.FlowRuleBatchOperation;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchEntry;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchOperation;
import org.onosproject.net.flow.FlowRuleOperation;
import org.onosproject.net.intent.IntentTestsMocks;
import org.onosproject.store.cluster.messaging.ClusterCommunicationServiceAdapter;
diff --git a/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java b/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java
index 6413037..54dd14c 100644
--- a/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java
+++ b/core/store/serializers/src/main/java/org/onosproject/store/serializers/KryoNamespaces.java
@@ -100,10 +100,10 @@
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowId;
import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.FlowRuleBatchEntry;
-import org.onosproject.net.flow.FlowRuleBatchEvent;
-import org.onosproject.net.flow.FlowRuleBatchOperation;
-import org.onosproject.net.flow.FlowRuleBatchRequest;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchEntry;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchEvent;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchOperation;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchRequest;
import org.onosproject.net.flow.FlowRuleEvent;
import org.onosproject.net.flow.FlowRuleExtPayLoad;
import org.onosproject.net.flow.IndexTableId;
@@ -212,6 +212,7 @@
import org.onosproject.net.pi.runtime.PiActionParamId;
import org.onosproject.net.pi.runtime.PiExactFieldMatch;
import org.onosproject.net.pi.runtime.PiFieldMatch;
+import org.onosproject.net.pi.runtime.PiActionProfileId;
import org.onosproject.net.pi.runtime.PiHeaderFieldId;
import org.onosproject.net.pi.runtime.PiLpmFieldMatch;
import org.onosproject.net.pi.runtime.PiMatchKey;
@@ -388,7 +389,6 @@
DefaultFlowRule.class,
TableId.class,
IndexTableId.class,
- PiTableId.class,
FlowRule.FlowRemoveReason.class,
DefaultPacketRequest.class,
PacketPriority.class,
@@ -620,6 +620,7 @@
PiTableId.class,
PiTernaryFieldMatch.class,
PiValidFieldMatch.class,
+ PiActionProfileId.class,
// Other
PiCriterion.class,
PiInstruction.class
diff --git a/core/store/serializers/src/test/java/org/onosproject/store/serializers/KryoSerializerTest.java b/core/store/serializers/src/test/java/org/onosproject/store/serializers/KryoSerializerTest.java
index a2e4670..ac6072b 100644
--- a/core/store/serializers/src/test/java/org/onosproject/store/serializers/KryoSerializerTest.java
+++ b/core/store/serializers/src/test/java/org/onosproject/store/serializers/KryoSerializerTest.java
@@ -54,7 +54,7 @@
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.FlowId;
import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.FlowRuleBatchEntry;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchEntry;
import org.onosproject.net.intent.IntentId;
import org.onosproject.net.resource.ResourceAllocation;
import org.onosproject.net.resource.ResourceConsumerId;
diff --git a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2DefaultPipeconfFactory.java b/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2DefaultPipeconfFactory.java
index cd89bba..b0b55a8 100644
--- a/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2DefaultPipeconfFactory.java
+++ b/drivers/bmv2/src/main/java/org/onosproject/drivers/bmv2/Bmv2DefaultPipeconfFactory.java
@@ -57,7 +57,6 @@
final URL jsonUrl = Bmv2DefaultPipeconfFactory.class.getResource(JSON_PATH);
final URL p4InfoUrl = Bmv2DefaultPipeconfFactory.class.getResource(P4INFO_PATH);
-
return DefaultPiPipeconf.builder()
.withId(new PiPipeconfId(PIPECONF_ID))
.withPipelineModel(Bmv2PipelineModelParser.parse(jsonUrl))
diff --git a/drivers/ciena/BUCK b/drivers/ciena/BUCK
index f6b7fa7..be8746e 100644
--- a/drivers/ciena/BUCK
+++ b/drivers/ciena/BUCK
@@ -6,6 +6,7 @@
'//protocols/rest/api:onos-protocols-rest-api',
'//apps/optical-model:onos-apps-optical-model',
'//lib:javax.ws.rs-api',
+ '//drivers/optical:onos-drivers-optical',
]
TEST_DEPS = [
diff --git a/drivers/ciena/pom.xml b/drivers/ciena/pom.xml
index 671148a..9c6df7d 100644
--- a/drivers/ciena/pom.xml
+++ b/drivers/ciena/pom.xml
@@ -59,6 +59,11 @@
<artifactId>onos-restsb-api</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-drivers-optical</artifactId>
+ <version>${project.version}</version>
+ </dependency>
</dependencies>
</project>
diff --git a/drivers/ciena/src/main/java/org/onosproject/drivers/ciena/CienaFlowRuleProgrammable.java b/drivers/ciena/src/main/java/org/onosproject/drivers/ciena/CienaFlowRuleProgrammable.java
new file mode 100644
index 0000000..e514188
--- /dev/null
+++ b/drivers/ciena/src/main/java/org/onosproject/drivers/ciena/CienaFlowRuleProgrammable.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2016-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.drivers.ciena;
+
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.OchSignal;
+import org.onosproject.net.PortNumber;
+import org.onosproject.driver.optical.flowrule.CrossConnectFlowRule;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.net.flow.FlowEntry;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.FlowRuleProgrammable;
+
+import org.slf4j.Logger;
+
+
+import java.util.List;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.stream.Collectors;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+public class CienaFlowRuleProgrammable extends AbstractHandlerBehaviour implements FlowRuleProgrammable {
+ private CienaRestDevice restCiena;
+ private final Logger log = getLogger(getClass());
+
+ @Override
+ public Collection<FlowEntry> getFlowEntries() {
+ DeviceId deviceId = handler().data().deviceId();
+ log.debug("getting flow entries for device {}", deviceId);
+ log.debug("getFlowEntries not supported for device {}", deviceId);
+ return Collections.EMPTY_LIST;
+ }
+
+ @Override
+ public Collection<FlowRule> applyFlowRules(Collection<FlowRule> rules) {
+ log.debug("installing flow rules: {}", rules);
+ // Apply the valid rules on the device
+ Collection<FlowRule> added = rules.stream()
+ .map(r -> createCrossConnectFlowRule(r))
+ .filter(xc -> installCrossConnect(xc))
+ .collect(Collectors.toList());
+ return added;
+ }
+
+ @Override
+ public Collection<FlowRule> removeFlowRules(Collection<FlowRule> rules) {
+ log.debug("removing flow rules: {}", rules);
+ Collection<FlowRule> removed = rules.stream()
+ .map(r -> createCrossConnectFlowRule(r))
+ .filter(xc -> removeCrossConnect(xc))
+ .collect(Collectors.toList());
+ return removed;
+ }
+
+ private CrossConnectFlowRule createCrossConnectFlowRule(FlowRule r) {
+ List<PortNumber> linePorts = CienaWaveserverDeviceDescription.getLinesidePortId().stream()
+ .map(p -> PortNumber.portNumber(p))
+ .collect(Collectors.toList());
+ try {
+ return new CrossConnectFlowRule(r, linePorts);
+ } catch (IllegalArgumentException e) {
+ log.debug("unable to create cross connect for rule:\n{}", r);
+ }
+ return null;
+ }
+
+ private boolean installCrossConnect(CrossConnectFlowRule xc) {
+ if (xc == null) {
+ return false;
+ }
+ // only handling lineside rule
+ if (xc.isAddRule()) {
+ PortNumber outPort = xc.addDrop();
+ OchSignal signal = xc.ochSignal();
+ return install(outPort, signal);
+ }
+ return false;
+ }
+
+ private boolean removeCrossConnect(CrossConnectFlowRule xc) {
+ //for now setting channel to 0 for remove rule
+ if (xc == null) {
+ return false;
+ }
+ // only handling lineside rule
+ if (xc.isAddRule()) {
+ PortNumber outPort = xc.addDrop();
+ OchSignal signal = OchSignal.newDwdmSlot(xc.ochSignal().channelSpacing(),
+ -CienaRestDevice.getMultiplierOffset());
+ return install(outPort, signal);
+ }
+ return false;
+ }
+
+ private boolean install(PortNumber outPort, OchSignal signal) {
+ /*
+ * rule is installed in three steps
+ * 1- disable port
+ * 2- change channel
+ * 3- enable port
+ */
+ try {
+ restCiena = new CienaRestDevice(handler());
+ } catch (NullPointerException e) {
+ log.error("unable to create CienaRestDevice, {}", e);
+ return false;
+ }
+ //1- disable port
+ //blindly disabling port
+ if (!restCiena.disablePort(outPort)) {
+ log.error("unable to disable port {}", outPort);
+ return false;
+ }
+ //2- change channel
+ if (!restCiena.changeChannel(signal, outPort)) {
+ log.error("unable to change the channel for port {}", outPort);
+ return false;
+ }
+ //3- enable port
+ if (!restCiena.enablePort(outPort)) {
+ log.error("unable to enable port {}", outPort);
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/drivers/ciena/src/main/java/org/onosproject/drivers/ciena/CienaRestDevice.java b/drivers/ciena/src/main/java/org/onosproject/drivers/ciena/CienaRestDevice.java
new file mode 100644
index 0000000..7627959
--- /dev/null
+++ b/drivers/ciena/src/main/java/org/onosproject/drivers/ciena/CienaRestDevice.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2016-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.drivers.ciena;
+
+import org.onlab.util.Frequency;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.OchSignal;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.driver.DriverHandler;
+import org.onosproject.protocol.rest.RestSBController;
+import org.slf4j.Logger;
+
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.slf4j.LoggerFactory.getLogger;
+
+public class CienaRestDevice {
+ private DeviceId deviceId;
+ private RestSBController controller;
+
+ private final Logger log = getLogger(getClass());
+ private static final String ENABLED = "enabled";
+ private static final String DISABLED = "disabled";
+ private static final Frequency BASE_FREQUENCY = Frequency.ofGHz(193_950);
+ private static final int MULTIPLIER_OFFSET = 80;
+
+ //URIs
+ private static final String PORT_URI = "ws-ptps/ptps/%s";
+ private static final String TRANSMITTER_URI = PORT_URI + "/properties/transmitter";
+ private static final String PORT_STATE_URI = PORT_URI + "/state";
+ private static final String WAVELENGTH_URI = TRANSMITTER_URI + "/wavelength";
+ private static final String FREQUENCY_URI = TRANSMITTER_URI + "/ciena-ws-ptp-modem:frequency";
+ private static final String CHANNEL_URI = TRANSMITTER_URI + "/ciena-ws-ptp-modem:line-system-channel-number";
+
+ public CienaRestDevice(DriverHandler handler) throws NullPointerException {
+ deviceId = handler.data().deviceId();
+ controller = checkNotNull(handler.get(RestSBController.class));
+ }
+
+ private final String genPortStateRequest(String state) {
+ String request = "{\n" +
+ "\"state\": {\n" +
+ "\"admin-state\": \"" + state + "\"\n}\n}";
+ log.debug("generated request: \n{}", request);
+ return request;
+ }
+
+ private String genWavelengthChangeRequest(String wavelength) {
+ String request = "{\n" +
+ "\"wavelength\": {\n" +
+ "\"value\": " + wavelength + "\n" +
+ "}\n" +
+ "}";
+ log.debug("request:\n{}", request);
+ return request;
+
+ }
+
+ private String genFrequencyChangeRequest(long wavelength) {
+ String request = "{\n" +
+ "\"ciena-ws-ptp-modem:frequency\": {\n" +
+ "\"value\": " + Long.toString(wavelength) + "\n" +
+ "}\n" +
+ "}";
+ log.debug("request:\n{}", request);
+ return request;
+
+ }
+
+ private String genChannelChangeRequest(int channel) {
+ String request = "{\n" +
+ "\"ciena-ws-ptp-modem:line-system-channel-number\": " +
+ Integer.toString(channel) + "\n}";
+ log.debug("request:\n{}", request);
+ return request;
+
+ }
+
+
+ private final String genUri(String uriFormat, PortNumber port) {
+ return String.format(uriFormat, port.name());
+ }
+
+ private boolean changePortState(PortNumber number, String state) {
+ log.debug("changing the port {} state to {}", number, state);
+ String uri = genUri(PORT_STATE_URI, number);
+ String request = genPortStateRequest(state);
+ return putNoReply(uri, request);
+ }
+
+ public boolean disablePort(PortNumber number) {
+ return changePortState(number, DISABLED);
+ }
+
+ public boolean enablePort(PortNumber number) {
+ return changePortState(number, ENABLED);
+ }
+
+ public final boolean changeFrequency(OchSignal signal, PortNumber outPort) {
+ String uri = genUri(FREQUENCY_URI, outPort);
+ long frequency = toFrequency(signal);
+ String request = genFrequencyChangeRequest(frequency);
+ return putNoReply(uri, request);
+ }
+
+ public final boolean changeChannel(OchSignal signal, PortNumber outPort) {
+ String uri = genUri(CHANNEL_URI, outPort);
+ int channel = signal.spacingMultiplier() + MULTIPLIER_OFFSET;
+ log.debug("channel is {} for port {} on device {}", channel, outPort.name(), deviceId);
+ String request = genChannelChangeRequest(channel);
+ return putNoReply(uri, request);
+ }
+
+ private final long toFrequency(OchSignal signal) {
+ double frequency = BASE_FREQUENCY.asGHz() +
+ (signal.channelSpacing().frequency().asGHz() * (double) signal.slotGranularity());
+ return Double.valueOf(frequency).longValue();
+ }
+
+ public static int getMultiplierOffset() {
+ return MULTIPLIER_OFFSET;
+ }
+
+ private int put(String uri, String request) {
+ InputStream payload = new ByteArrayInputStream(request.getBytes(StandardCharsets.UTF_8));
+ int response = controller.put(deviceId, uri, payload, MediaType.valueOf(MediaType.APPLICATION_JSON));
+ log.debug("response: {}", response);
+ return response;
+ }
+
+ private boolean putNoReply(String uri, String request) {
+ return put(uri, request) == Response.Status.NO_CONTENT.getStatusCode();
+ }
+
+}
diff --git a/drivers/ciena/src/main/java/org/onosproject/drivers/ciena/CienaWaveserverDeviceDescription.java b/drivers/ciena/src/main/java/org/onosproject/drivers/ciena/CienaWaveserverDeviceDescription.java
index 31de548..92aa0f5 100644
--- a/drivers/ciena/src/main/java/org/onosproject/drivers/ciena/CienaWaveserverDeviceDescription.java
+++ b/drivers/ciena/src/main/java/org/onosproject/drivers/ciena/CienaWaveserverDeviceDescription.java
@@ -51,6 +51,7 @@
/**
* Discovers the ports from a Ciena WaveServer Rest device.
*/
+//TODO: Use CienaRestDevice
public class CienaWaveserverDeviceDescription extends AbstractHandlerBehaviour
implements DeviceDescriptionDiscovery {
@@ -128,21 +129,15 @@
String portId = sub.getString(PORT_ID);
DefaultAnnotations.Builder annotations = DefaultAnnotations.builder();
if (LINESIDE_PORT_ID.contains(portId)) {
- // TX/OUT port
annotations.set(AnnotationKeys.CHANNEL_ID, sub.getString(CHANNEL_ID));
- annotations.set(AnnotationKeys.PORT_NAME, portId + " TX");
+ // TX/OUT and RX/IN ports
+ annotations.set(AnnotationKeys.PORT_OUT, sub.getString(PORT_OUT));
+ annotations.set(AnnotationKeys.PORT_IN, sub.getString(PORT_IN));
ports.add(parseWaveServerCienaOchPorts(
- sub.getLong(PORT_OUT),
+ Long.valueOf(portId),
sub,
annotations.build()));
- // RX/IN port
- annotations.set(AnnotationKeys.PORT_NAME, portId + " RX");
- annotations.set(AnnotationKeys.CHANNEL_ID, sub.getString(CHANNEL_ID));
- ports.add(parseWaveServerCienaOchPorts(
- sub.getLong(PORT_IN),
- sub,
- annotations.build()));
} else if (!portId.equals("5") && !portId.equals("49")) {
DefaultAnnotations.builder()
.set(AnnotationKeys.PORT_NAME, portId);
@@ -184,6 +179,10 @@
new OchSignal(gridType, chSpacing, spacingMult, 1), annotations);
}
+ public static ArrayList<String> getLinesidePortId() {
+ return LINESIDE_PORT_ID;
+ }
+
//FIXME remove when all optical types have two way information methods, see jira tickets
private static long toGbps(long speed) {
return speed * 1000;
diff --git a/drivers/ciena/src/main/java/org/onosproject/drivers/ciena/CienaWaveserverPortAdmin.java b/drivers/ciena/src/main/java/org/onosproject/drivers/ciena/CienaWaveserverPortAdmin.java
index 0f3b6d7..a943f7a 100644
--- a/drivers/ciena/src/main/java/org/onosproject/drivers/ciena/CienaWaveserverPortAdmin.java
+++ b/drivers/ciena/src/main/java/org/onosproject/drivers/ciena/CienaWaveserverPortAdmin.java
@@ -17,110 +17,41 @@
package org.onosproject.drivers.ciena;
import org.onlab.util.Tools;
-import org.onosproject.net.AnnotationKeys;
-import org.onosproject.net.DeviceId;
-import org.onosproject.net.Port;
import org.onosproject.net.PortNumber;
import org.onosproject.net.behaviour.PortAdmin;
-import org.onosproject.net.device.DeviceService;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
-import org.onosproject.protocol.rest.RestSBController;
import org.slf4j.Logger;
-import javax.ws.rs.core.MediaType;
import java.util.concurrent.CompletableFuture;
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import java.nio.charset.StandardCharsets;
-import javax.ws.rs.core.Response.Status;
-import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;
public class CienaWaveserverPortAdmin extends AbstractHandlerBehaviour
implements PortAdmin {
+ private CienaRestDevice restCiena;
private final Logger log = getLogger(getClass());
- private static final String APP_JSON = "application/json";
- private static final String ENABLE = "enabled";
- private static final String DISABLE = "disabled";
-
- private final String generateUri(long number) {
- return String.format("ws-ptps/ptps/%d/state", number);
- }
-
- private final String generateRequest(String state) {
- String request = "{\n" +
- "\"state\": {\n" +
- "\"admin-state\": \"" + state + "\"\n}\n}";
- log.debug("generated request: \n{}", request);
- return request;
- }
-
- private final boolean put(long number, String state) {
- String uri = generateUri(number);
- String request = generateRequest(state);
- DeviceId deviceId = handler().data().deviceId();
- RestSBController controller =
- checkNotNull(handler().get(RestSBController.class));
- InputStream payload =
- new ByteArrayInputStream(request.getBytes(StandardCharsets.UTF_8));
- int response = controller.put(deviceId, uri, payload,
- MediaType.valueOf(APP_JSON));
- log.debug("response: {}", response);
- // expecting 204/NO_CONTENT_RESPONSE as successful response
- return response == Status.NO_CONTENT.getStatusCode();
- }
-
- // returns null if specified port number was not a line side port
- private Long getLineSidePort(PortNumber number) {
- DeviceService deviceService = checkNotNull(handler().get(DeviceService.class));
- DeviceId deviceId = handler().data().deviceId();
- Port port = deviceService.getPort(deviceId, number);
- if (port != null) {
- String channelId = port.annotations().value(AnnotationKeys.CHANNEL_ID);
- // any port that has channel is lineSidePort and will have TX and RX
- if (channelId != null) {
- String portName = port.annotations().value(AnnotationKeys.PORT_NAME);
- // last three characters of portName will always be " TX" or " RX"
- portName = portName.substring(0, portName.length() - 3);
- log.debug("port number {} is mapped to {} lineside port",
- number, portName);
- return new Long(portName);
- }
- }
- // not a line-side port
- return null;
- }
@Override
public CompletableFuture<Boolean> disable(PortNumber number) {
- log.debug("disabling port {}", number);
- Long lineSidePort = getLineSidePort(number);
- long devicePortNum;
- if (lineSidePort != null) {
- devicePortNum = lineSidePort.longValue();
- } else {
- devicePortNum = number.toLong();
+ try {
+ restCiena = new CienaRestDevice(handler());
+ } catch (NullPointerException e) {
+ log.error("unable to create CienaRestDevice, {}", e);
+ return CompletableFuture.completedFuture(false);
}
- CompletableFuture<Boolean> result =
- CompletableFuture.completedFuture(put(devicePortNum, DISABLE));
- return result;
+ return CompletableFuture.completedFuture(restCiena.disablePort(number));
}
@Override
public CompletableFuture<Boolean> enable(PortNumber number) {
- log.debug("enabling port {}", number);
- Long lineSidePort = getLineSidePort(number);
- long devicePortNum;
- if (lineSidePort != null) {
- devicePortNum = lineSidePort.longValue();
- } else {
- devicePortNum = number.toLong();
+ try {
+ restCiena = new CienaRestDevice(handler());
+ } catch (NullPointerException e) {
+ log.error("unable to create CienaRestDevice, {}", e);
+ return CompletableFuture.completedFuture(false);
}
- CompletableFuture<Boolean> result =
- CompletableFuture.completedFuture(put(devicePortNum, ENABLE));
- return result;
+ return CompletableFuture.completedFuture(restCiena.enablePort(number));
}
@Override
diff --git a/drivers/ciena/src/main/resources/ciena-drivers.xml b/drivers/ciena/src/main/resources/ciena-drivers.xml
index 6ff5d75..57ed4cf 100644
--- a/drivers/ciena/src/main/resources/ciena-drivers.xml
+++ b/drivers/ciena/src/main/resources/ciena-drivers.xml
@@ -23,6 +23,8 @@
impl="org.onosproject.drivers.ciena.CienaWaveserverDeviceDescription"/>
<behaviour api="org.onosproject.net.behaviour.PortAdmin"
impl="org.onosproject.drivers.ciena.CienaWaveserverPortAdmin"/>
+ <behaviour api="org.onosproject.net.flow.FlowRuleProgrammable"
+ impl="org.onosproject.drivers.ciena.CienaFlowRuleProgrammable"/>
<behaviour api="org.onosproject.net.behaviour.LambdaQuery"
impl="org.onosproject.driver.optical.query.CBand50LambdaQuery"/>
</driver>
diff --git a/drivers/p4runtime/BUCK b/drivers/p4runtime/BUCK
index 57079be..5c50f12 100644
--- a/drivers/p4runtime/BUCK
+++ b/drivers/p4runtime/BUCK
@@ -5,14 +5,22 @@
'//protocols/p4runtime/api:onos-protocols-p4runtime-api',
'//incubator/grpc-dependencies:grpc-core-repkg-' + GRPC_VER,
'//lib:grpc-netty-' + GRPC_VER,
+ '//core/store/serializers:onos-core-serializers',
+ '//lib:KRYO',
]
BUNDLES = [
':onos-drivers-p4runtime',
]
-osgi_jar(
+TEST_DEPS = [
+ '//lib:TEST_ADAPTERS',
+ '//core/api:onos-api-tests',
+]
+
+osgi_jar_with_tests (
deps = COMPILE_DEPS,
+ test_deps = TEST_DEPS,
)
onos_app (
diff --git a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/DefaultP4Interpreter.java b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/DefaultP4Interpreter.java
index e14363e..75cf081 100644
--- a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/DefaultP4Interpreter.java
+++ b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/DefaultP4Interpreter.java
@@ -30,6 +30,7 @@
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.flow.instructions.Instruction;
import org.onosproject.net.flow.instructions.Instructions;
+import org.onosproject.net.flow.instructions.PiInstruction;
import org.onosproject.net.packet.DefaultInboundPacket;
import org.onosproject.net.packet.InboundPacket;
import org.onosproject.net.packet.OutboundPacket;
@@ -170,7 +171,7 @@
@Override
public PiAction mapTreatment(TrafficTreatment treatment, PiTableId piTableId) throws PiInterpreterException {
-
+ initTargetSpecificAttributes();
if (treatment.allInstructions().size() == 0) {
// No instructions means drop for us.
return actionWithName(DROP);
@@ -184,17 +185,10 @@
switch (instruction.type()) {
case OUTPUT:
Instructions.OutputInstruction outInstruction = (Instructions.OutputInstruction) instruction;
- PortNumber port = outInstruction.port();
- if (!port.isLogical()) {
- return PiAction.builder()
- .withId(PiActionId.of(SET_EGRESS_PORT))
- .withParameter(new PiActionParam(PiActionParamId.of(PORT), copyFrom(port.toLong())))
- .build();
- } else if (port.equals(CONTROLLER)) {
- return actionWithName(SEND_TO_CPU);
- } else {
- throw new PiInterpreterException(format("Egress on logical port '%s' not supported", port));
- }
+ return outputPiAction(outInstruction);
+ case PROTOCOL_INDEPENDENT:
+ PiInstruction piInstruction = (PiInstruction) instruction;
+ return (PiAction) piInstruction.action();
case NOACTION:
return actionWithName(DROP);
default:
@@ -202,6 +196,25 @@
}
}
+ private PiAction outputPiAction(Instructions.OutputInstruction outInstruction) throws PiInterpreterException {
+ PortNumber port = outInstruction.port();
+ if (!port.isLogical()) {
+ try {
+ return PiAction.builder()
+ .withId(PiActionId.of(SET_EGRESS_PORT))
+ .withParameter(new PiActionParam(PiActionParamId.of(PORT),
+ fit(copyFrom(port.toLong()), portFieldBitWidth)))
+ .build();
+ } catch (ImmutableByteSequence.ByteSequenceTrimException e) {
+ throw new PiInterpreterException(e.getMessage());
+ }
+ } else if (port.equals(CONTROLLER)) {
+ return actionWithName(SEND_TO_CPU);
+ } else {
+ throw new PiInterpreterException(format("Egress on logical port '%s' not supported", port));
+ }
+ }
+
@Override
public Optional<PiCounterId> mapTableCounter(PiTableId piTableId) {
return Optional.ofNullable(TABLE_COUNTER_MAP.get(piTableId));
diff --git a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeGroupProgrammable.java b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeGroupProgrammable.java
index 15a40ca..e108123 100644
--- a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeGroupProgrammable.java
+++ b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimeGroupProgrammable.java
@@ -16,71 +16,272 @@
package org.onosproject.drivers.p4runtime;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import org.onlab.util.KryoNamespace;
+import org.onosproject.core.GroupId;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
-import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.instructions.Instruction;
+import org.onosproject.net.flow.instructions.PiInstruction;
+import org.onosproject.net.group.Group;
import org.onosproject.net.group.GroupBucket;
-import org.onosproject.net.group.GroupDescription;
import org.onosproject.net.group.GroupOperation;
import org.onosproject.net.group.GroupOperations;
import org.onosproject.net.group.GroupProgrammable;
+import org.onosproject.net.group.GroupStore;
import org.onosproject.net.pi.model.PiPipelineInterpreter;
+import org.onosproject.net.pi.runtime.PiActionProfileId;
import org.onosproject.net.pi.runtime.PiAction;
import org.onosproject.net.pi.runtime.PiActionGroup;
import org.onosproject.net.pi.runtime.PiActionGroupId;
import org.onosproject.net.pi.runtime.PiActionGroupMember;
import org.onosproject.net.pi.runtime.PiActionGroupMemberId;
+import org.onosproject.net.pi.runtime.PiTableAction;
import org.onosproject.net.pi.runtime.PiTableId;
+import org.onosproject.p4runtime.api.P4RuntimeClient;
+import org.onosproject.p4runtime.api.P4RuntimeGroupReference;
+import org.onosproject.p4runtime.api.P4RuntimeGroupWrapper;
+import org.onosproject.store.serializers.KryoNamespaces;
+import org.slf4j.Logger;
import java.nio.ByteBuffer;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
-public class P4RuntimeGroupProgrammable extends AbstractHandlerBehaviour implements GroupProgrammable {
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Implementation of the group programmable behaviour for P4Runtime.
+ */
+public class P4RuntimeGroupProgrammable extends AbstractP4RuntimeHandlerBehaviour implements GroupProgrammable {
+ private static final String ACT_GRP_MEMS = "action group members";
+ private static final String DELETE = "delete";
+ private static final String ACT_GRP = "action group";
+ private static final String INSERT = "insert";
+ private static final Logger log = getLogger(P4RuntimeGroupProgrammable.class);
+ private static final int GROUP_ID_MASK = 0xffff;
+ public static final KryoNamespace KRYO = new KryoNamespace.Builder()
+ .register(KryoNamespaces.API)
+ .register(DefaultP4RuntimeGroupCookie.class)
+ .build("P4RuntimeGroupProgrammable");
/*
- Work in progress.
+ * About action groups in P4runtime:
+ * The type field is a place holder in p4runtime.proto right now, and we haven't defined it yet. You can assume all
+ * the groups are "select" as per the OF spec. As a remainder, in the P4 terminology a member corresponds to an OF
+ * bucket. Each member can also be used directly in the match table (kind of like an OF indirect group).
*/
- private Device device;
-
+ // TODO: make this attribute configurable by child drivers (e.g. BMv2 or Tofino)
/*
- About action groups in P4runtime:
- The type field is a place holder in p4runtime.proto right now, and we haven't defined it yet. You can assume all
- the groups are "select" as per the OF spec. As a remainder, in the P4 terminology a member corresponds to an OF
- bucket. Each member can also be used directly in the match table (kind of like an OF indirect group).
+ When updating an existing rule, if true, we issue a DELETE operation before inserting the new one, otherwise we
+ issue a MODIFY operation. This is useful fore devices that do not support MODIFY operations for table entries.
*/
+ private boolean deleteBeforeUpdate = true;
+
+ // TODO: can remove this check as soon as the multi-apply-per-same-flow rule bug is fixed.
+ /*
+ If true, we ignore re-installing rules that are already known in the ENTRY_STORE, i.e. same match key and action.
+ */
+ private boolean checkStoreBeforeUpdate = true;
+
+ // Needed to synchronize operations over the same group.
+ private static final Map<P4RuntimeGroupReference, Lock> GROUP_LOCKS = Maps.newConcurrentMap();
+
+ // TODO: replace with distribute store
+ private static final Map<P4RuntimeGroupReference, P4RuntimeGroupWrapper> GROUP_STORE = Maps.newConcurrentMap();
+
+ private PiPipelineInterpreter interpreter;
+
+ protected boolean init() {
+ if (!setupBehaviour()) {
+ return false;
+ }
+ Device device = deviceService.getDevice(deviceId);
+ // Need an interpreter to map the bucket treatment to a PI action
+ if (!device.is(PiPipelineInterpreter.class)) {
+ log.warn("Can't find interpreter for device {}", device.id());
+ } else {
+ interpreter = device.as(PiPipelineInterpreter.class);
+ }
+ return true;
+ }
@Override
public void performGroupOperation(DeviceId deviceId, GroupOperations groupOps) {
+ if (!init()) {
+ // Ignore group operation of not initialized.
+ return;
+ }
+ Device device = handler().get(DeviceService.class).getDevice(deviceId);
for (GroupOperation groupOp : groupOps.operations()) {
+ processGroupOp(device, groupOp);
+ }
+ }
+
+ private void processGroupOp(Device device, GroupOperation groupOp) {
+ GroupId groupId = groupOp.groupId();
+ GroupStore groupStore = handler().get(GroupStore.class);
+ Group group = groupStore.getGroup(device.id(), groupId);
+
+ // Most of this logic can go in a core service, e.g. PiGroupTranslationService
+ // From a P4Runtime perspective, we need first to insert members, then the group.
+ PiActionGroupId piActionGroupId = PiActionGroupId.of(groupOp.groupId().id());
+
+ PiActionGroup.Builder piActionGroupBuilder = PiActionGroup.builder()
+ .withId(piActionGroupId);
+
+ switch (group.type()) {
+ case SELECT:
+ piActionGroupBuilder.withType(PiActionGroup.Type.SELECT);
+ break;
+ default:
+ log.warn("Group type {} not supported, ignore group {}.", group.type(), groupId);
+ return;
+ }
+ /*
+ Problem:
+ In P4Runtime, action profiles (i.e. group tables) are specific to one or more tables.
+ Mapping of treatments depends on the target table. How do we derive the target table from here?
+
+ Solution:
+ - Add table information into app cookie and put into group description
+ */
+ // TODO: notify group service if we get deserialize error
+ DefaultP4RuntimeGroupCookie defaultP4RuntimeGroupCookie = KRYO.deserialize(group.appCookie().key());
+ PiTableId piTableId = defaultP4RuntimeGroupCookie.tableId();
+ PiActionProfileId piActionProfileId = defaultP4RuntimeGroupCookie.actionProfileId();
+ piActionGroupBuilder.withActionProfileId(piActionProfileId);
+
+ List<PiActionGroupMember> members = buildMembers(group, piActionGroupId, piTableId);
+ if (members == null) {
+ log.warn("Can't build members for group {} on {}", group, device.id());
+ return;
+ }
+
+ piActionGroupBuilder.addMembers(members);
+ PiActionGroup piActionGroup = piActionGroupBuilder.build();
+
+ P4RuntimeGroupReference groupRef =
+ new P4RuntimeGroupReference(deviceId, piActionProfileId, piActionGroupId);
+ Lock lock = GROUP_LOCKS.computeIfAbsent(groupRef, k -> new ReentrantLock());
+ lock.lock();
+
+
+ try {
+ P4RuntimeGroupWrapper oldGroupWrapper = GROUP_STORE.get(groupRef);
+ P4RuntimeGroupWrapper newGroupWrapper =
+ new P4RuntimeGroupWrapper(piActionGroup, group, System.currentTimeMillis());
+ boolean success;
switch (groupOp.opType()) {
case ADD:
- addGroup(deviceId, groupOp);
+ case MODIFY:
+ success = writeGroupToDevice(oldGroupWrapper, piActionGroup, members);
+ if (success) {
+ GROUP_STORE.put(groupRef, newGroupWrapper);
+ }
+ break;
+ case DELETE:
+ success = deleteGroupFromDevice(piActionGroup, members);
+ if (success) {
+ GROUP_STORE.remove(groupRef);
+ }
break;
default:
throw new UnsupportedOperationException();
}
+ } finally {
+ lock.unlock();
}
}
- private void addGroup(DeviceId deviceId, GroupOperation groupOp) {
-
- // Most of this logic can go in a core service, e.g. PiGroupTranslationService
-
- // From a P4Runtime perspective, we need first to insert members, then the group.
-
- PiActionGroupId piActionGroupId = PiActionGroupId.of(groupOp.groupId().id());
-
- PiActionGroup.Builder piActionGroupBuilder = PiActionGroup.builder()
- .withId(piActionGroupId)
- .withType(PiActionGroup.Type.SELECT);
-
- if (groupOp.groupType() != GroupDescription.Type.SELECT) {
- // log error
+ /**
+ * Installs action group and members to device via client interface.
+ *
+ * @param oldGroupWrapper old group wrapper for the group; null if not exists
+ * @param piActionGroup the action group to be installed
+ * @param members members of the action group
+ * @return true if install success; false otherwise
+ */
+ private boolean writeGroupToDevice(P4RuntimeGroupWrapper oldGroupWrapper,
+ PiActionGroup piActionGroup,
+ Collection<PiActionGroupMember> members) {
+ boolean success = true;
+ CompletableFuture<Boolean> writeSuccess;
+ if (checkStoreBeforeUpdate && oldGroupWrapper != null &&
+ oldGroupWrapper.piActionGroup().equals(piActionGroup)) {
+ // Action group already exists, ignore it
+ return true;
}
+ if (deleteBeforeUpdate && oldGroupWrapper != null) {
+ success = deleteGroupFromDevice(oldGroupWrapper.piActionGroup(),
+ oldGroupWrapper.piActionGroup().members());
+ }
+ writeSuccess = client.writeActionGroupMembers(piActionGroup,
+ members,
+ P4RuntimeClient.WriteOperationType.INSERT,
+ pipeconf);
+ success = success && completeSuccess(writeSuccess, ACT_GRP_MEMS, INSERT);
+
+ writeSuccess = client.writeActionGroup(piActionGroup,
+ P4RuntimeClient.WriteOperationType.INSERT,
+ pipeconf);
+ success = success && completeSuccess(writeSuccess, ACT_GRP, INSERT);
+ return success;
+ }
+
+ private boolean deleteGroupFromDevice(PiActionGroup piActionGroup,
+ Collection<PiActionGroupMember> members) {
+ boolean success;
+ CompletableFuture<Boolean> writeSuccess;
+ writeSuccess = client.writeActionGroup(piActionGroup,
+ P4RuntimeClient.WriteOperationType.DELETE,
+ pipeconf);
+ success = completeSuccess(writeSuccess, ACT_GRP, DELETE);
+ writeSuccess = client.writeActionGroupMembers(piActionGroup,
+ members,
+ P4RuntimeClient.WriteOperationType.DELETE,
+ pipeconf);
+ success = success && completeSuccess(writeSuccess, ACT_GRP_MEMS, DELETE);
+ return success;
+ }
+
+ private boolean completeSuccess(CompletableFuture<Boolean> completableFuture,
+ String topic, String action) {
+ try {
+ return completableFuture.get();
+ } catch (InterruptedException | ExecutionException e) {
+ log.warn("Can't {} {} due to {}", action, topic, e.getMessage());
+ return false;
+ }
+ }
+
+ /**
+ * Build pi action group members from group.
+ *
+ * @param group the group
+ * @param piActionGroupId the PI action group id of the group
+ * @param piTableId the PI table related to the group
+ * @return list of PI action group members; null if can't build member list
+ */
+ private List<PiActionGroupMember> buildMembers(Group group, PiActionGroupId piActionGroupId, PiTableId piTableId) {
+ GroupId groupId = group.id();
+ ImmutableList.Builder<PiActionGroupMember> membersBuilder = ImmutableList.builder();
int bucketIdx = 0;
- for (GroupBucket bucket : groupOp.buckets().buckets()) {
+ for (GroupBucket bucket : group.buckets().buckets()) {
/*
Problem:
In P4Runtime action group members, i.e. action buckets, are associated to a numeric ID chosen
@@ -95,40 +296,46 @@
Hack:
Statically derive member ID by combining groupId and position of the bucket in the list.
*/
- int memberId = ByteBuffer.allocate(4)
- .putShort((short) (piActionGroupId.id() % 2 ^ 16))
- .putShort((short) (bucketIdx % 2 ^ 16))
- .getInt();
+ ByteBuffer bb = ByteBuffer.allocate(4)
+ .putShort((short) (piActionGroupId.id() & GROUP_ID_MASK))
+ .putShort((short) bucketIdx);
+ bb.rewind();
+ int memberId = bb.getInt();
- // Need an interpreter to map the bucket treatment to a PI action
+ bucketIdx++;
+ PiAction action;
+ if (interpreter != null) {
+ // if we have interpreter, use interpreter
+ try {
+ action = interpreter.mapTreatment(bucket.treatment(), piTableId);
+ } catch (PiPipelineInterpreter.PiInterpreterException e) {
+ log.warn("Can't map treatment {} to action due to {}, ignore group {}",
+ bucket.treatment(), e.getMessage(), groupId);
+ return null;
+ }
+ } else {
+ // if we don't have interpreter, accept PiInstruction only
+ TrafficTreatment treatment = bucket.treatment();
- if (!device.is(PiPipelineInterpreter.class)) {
- // log error
- }
+ if (treatment.allInstructions().size() > 1) {
+ log.warn("Treatment {} has multiple instructions, ignore group {}",
+ treatment, groupId);
+ return null;
+ }
+ Instruction instruction = treatment.allInstructions().get(0);
+ if (instruction.type() != Instruction.Type.PROTOCOL_INDEPENDENT) {
+ log.warn("Instruction {} is not a PROTOCOL_INDEPENDENT type, ignore group {}",
+ instruction, groupId);
+ return null;
+ }
- PiPipelineInterpreter interpreter = device.as(PiPipelineInterpreter.class);
-
- /*
- Problem:
- In P4Runtime, action profiles (i.e. group tables) are specific to one or more tables.
- Mapping of treatments depends on the target table. How do we derive the target table from here?
-
- Solution:
- - Change GroupDescription to allow applications to specify a table where this group will be called from.
-
- Hack:
- Assume we support pipelines with only one action profile associated to only one table, i.e. derive the
- table ID by looking at the P4Info.
- */
-
- PiTableId piTableId = PiTableId.of("derive from P4Info");
-
-
- PiAction action = null;
- try {
- action = interpreter.mapTreatment(bucket.treatment(), piTableId);
- } catch (PiPipelineInterpreter.PiInterpreterException e) {
- // log error
+ PiInstruction piInstruction = (PiInstruction) instruction;
+ if (piInstruction.action().type() != PiTableAction.Type.ACTION) {
+ log.warn("Action {} is not an ACTION type, ignore group {}",
+ piInstruction.action(), groupId);
+ return null;
+ }
+ action = (PiAction) piInstruction.action();
}
PiActionGroupMember member = PiActionGroupMember.builder()
@@ -137,15 +344,97 @@
.withWeight(bucket.weight())
.build();
- piActionGroupBuilder.addMember(member);
+ membersBuilder.add(member);
+ }
+ return membersBuilder.build();
+ }
- // Use P4RuntimeClient to install member;
- // TODO: implement P4RuntimeClient method.
+ @Override
+ public Collection<Group> getGroups() {
+ if (!init()) {
+ return Collections.emptySet();
}
- PiActionGroup piActionGroup = piActionGroupBuilder.build();
+ Collection<Group> result = Sets.newHashSet();
+ Collection<PiActionProfileId> piActionProfileIds = Sets.newHashSet();
- // Use P4RuntimeClient to insert group.
- // TODO: implement P4RuntimeClient method.
+ // Collection action profile Ids
+ // TODO: find better way to get all action profile ids....
+ GROUP_STORE.forEach((groupRef, wrapper) -> piActionProfileIds.add(groupRef.actionProfileId()));
+
+ AtomicBoolean success = new AtomicBoolean(true);
+ piActionProfileIds.forEach(actionProfileId -> {
+ Collection<PiActionGroup> piActionGroups = Sets.newHashSet();
+ try {
+ Collection<PiActionGroup> groupsFromDevice =
+ client.dumpGroups(actionProfileId, pipeconf).get();
+ if (groupsFromDevice == null) {
+ // Got error
+ success.set(false);
+ } else {
+ piActionGroups.addAll(groupsFromDevice);
+ }
+ } catch (ExecutionException | InterruptedException e) {
+ log.error("Exception while dumping groups for action profile {}: {}",
+ actionProfileId.id(), deviceId, e);
+ success.set(false);
+ }
+
+ piActionGroups.forEach(piActionGroup -> {
+ PiActionGroupId actionGroupId = piActionGroup.id();
+ P4RuntimeGroupReference groupRef =
+ new P4RuntimeGroupReference(deviceId, actionProfileId, actionGroupId);
+ P4RuntimeGroupWrapper wrapper = GROUP_STORE.get(groupRef);
+
+ if (wrapper == null) {
+ // group exists in client, but can't find in ONOS
+ log.warn("Can't find action profile group {} from local store.",
+ groupRef);
+ return;
+ }
+ if (!wrapper.piActionGroup().equals(piActionGroup)) {
+ log.warn("Group from device is different to group from local store.");
+ return;
+ }
+ result.add(wrapper.group());
+
+ });
+ });
+
+ if (!success.get()) {
+ // Got error while dump groups from device.
+ return Collections.emptySet();
+ } else {
+ return result;
+ }
+ }
+
+ /**
+ * P4Runtime app cookie for group.
+ */
+ public static class DefaultP4RuntimeGroupCookie {
+ private PiTableId tableId;
+ private PiActionProfileId piActionProfileId;
+ private Integer groupId;
+
+ public DefaultP4RuntimeGroupCookie(PiTableId tableId,
+ PiActionProfileId piActionProfileId,
+ Integer groupId) {
+ this.tableId = tableId;
+ this.piActionProfileId = piActionProfileId;
+ this.groupId = groupId;
+ }
+
+ public PiTableId tableId() {
+ return tableId;
+ }
+
+ public PiActionProfileId actionProfileId() {
+ return piActionProfileId;
+ }
+
+ public Integer groupId() {
+ return groupId;
+ }
}
}
diff --git a/drivers/p4runtime/src/test/java/org/onosproject/drivers/p4runtime/P4runtimeGroupProgrammableTest.java b/drivers/p4runtime/src/test/java/org/onosproject/drivers/p4runtime/P4runtimeGroupProgrammableTest.java
new file mode 100644
index 0000000..c334218
--- /dev/null
+++ b/drivers/p4runtime/src/test/java/org/onosproject/drivers/p4runtime/P4runtimeGroupProgrammableTest.java
@@ -0,0 +1,291 @@
+/*
+ * Copyright 2017-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.drivers.p4runtime;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import org.easymock.Capture;
+import org.easymock.EasyMock;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.util.ImmutableByteSequence;
+import org.onosproject.TestApplicationId;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.GroupId;
+import org.onosproject.drivers.p4runtime.P4RuntimeGroupProgrammable.DefaultP4RuntimeGroupCookie;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+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.TrafficTreatment;
+import org.onosproject.net.flow.instructions.Instructions;
+import org.onosproject.net.group.DefaultGroup;
+import org.onosproject.net.group.DefaultGroupBucket;
+import org.onosproject.net.group.DefaultGroupDescription;
+import org.onosproject.net.group.DefaultGroupKey;
+import org.onosproject.net.group.Group;
+import org.onosproject.net.group.GroupBucket;
+import org.onosproject.net.group.GroupBuckets;
+import org.onosproject.net.group.GroupDescription;
+import org.onosproject.net.group.GroupKey;
+import org.onosproject.net.group.GroupOperation;
+import org.onosproject.net.group.GroupOperations;
+import org.onosproject.net.group.GroupStore;
+import org.onosproject.net.pi.model.DefaultPiPipeconf;
+import org.onosproject.net.pi.model.PiPipeconf;
+import org.onosproject.net.pi.model.PiPipeconfId;
+import org.onosproject.net.pi.model.PiPipelineInterpreter;
+import org.onosproject.net.pi.model.PiPipelineModel;
+import org.onosproject.net.pi.runtime.PiActionProfileId;
+import org.onosproject.net.pi.runtime.PiAction;
+import org.onosproject.net.pi.runtime.PiActionGroup;
+import org.onosproject.net.pi.runtime.PiActionGroupMember;
+import org.onosproject.net.pi.runtime.PiActionGroupMemberId;
+import org.onosproject.net.pi.runtime.PiActionId;
+import org.onosproject.net.pi.runtime.PiActionParam;
+import org.onosproject.net.pi.runtime.PiActionParamId;
+import org.onosproject.net.pi.runtime.PiPipeconfService;
+import org.onosproject.net.pi.runtime.PiTableAction;
+import org.onosproject.net.pi.runtime.PiTableId;
+import org.onosproject.p4runtime.api.P4RuntimeClient;
+import org.onosproject.p4runtime.api.P4RuntimeController;
+
+import java.net.URL;
+import java.util.Collection;
+import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.CompletableFuture;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.assertEquals;
+import static org.onosproject.net.group.GroupDescription.Type.SELECT;
+import static org.onosproject.net.pi.model.PiPipeconf.ExtensionType.P4_INFO_TEXT;
+import static org.onosproject.p4runtime.api.P4RuntimeClient.WriteOperationType.DELETE;
+import static org.onosproject.p4runtime.api.P4RuntimeClient.WriteOperationType.INSERT;
+
+public class P4runtimeGroupProgrammableTest {
+ private static final String P4INFO_PATH = "/default.p4info";
+ private static final DeviceId DEVICE_ID = DeviceId.deviceId("device:p4runtime:1");
+ private static final PiPipeconfId PIPECONF_ID = new PiPipeconfId("p4runtime-mock-pipeconf");
+ private static final PiPipeconf PIPECONF = buildPipeconf();
+ private static final PiTableId ECMP_TABLE_ID = PiTableId.of("ecmp");
+ private static final PiActionProfileId ACT_PROF_ID = PiActionProfileId.of("ecmp_selector");
+ private static final ApplicationId APP_ID = TestApplicationId.create("P4runtimeGroupProgrammableTest");
+ private static final GroupId GROUP_ID = GroupId.valueOf(1);
+ private static final PiActionId EGRESS_PORT_ACTION_ID = PiActionId.of("set_egress_port");
+ private static final PiActionParamId PORT_PARAM_ID = PiActionParamId.of("port");
+ private static final List<GroupBucket> BUCKET_LIST = ImmutableList.of(
+ outputBucket(1),
+ outputBucket(2),
+ outputBucket(3)
+ );
+ private static final DefaultP4RuntimeGroupCookie COOKIE =
+ new DefaultP4RuntimeGroupCookie(ECMP_TABLE_ID, ACT_PROF_ID, GROUP_ID.id());
+ private static final GroupKey GROUP_KEY =
+ new DefaultGroupKey(P4RuntimeGroupProgrammable.KRYO.serialize(COOKIE));
+ private static final GroupBuckets BUCKETS = new GroupBuckets(BUCKET_LIST);
+ private static final GroupDescription GROUP_DESC =
+ new DefaultGroupDescription(DEVICE_ID,
+ SELECT,
+ BUCKETS,
+ GROUP_KEY,
+ GROUP_ID.id(),
+ APP_ID);
+ private static final Group GROUP = new DefaultGroup(GROUP_ID, GROUP_DESC);
+ private static final int DEFAULT_MEMBER_WEIGHT = 1;
+ private static final int BASE_MEM_ID = 65535;
+ private static final Collection<PiActionGroupMember> EXPECTED_MEMBERS =
+ ImmutableSet.of(
+ outputMember(1),
+ outputMember(2),
+ outputMember(3)
+ );
+
+ private P4RuntimeGroupProgrammable programmable;
+ private DriverHandler driverHandler;
+ private DriverData driverData;
+ private P4RuntimeController controller;
+ private P4RuntimeClient client;
+ private PiPipeconfService piPipeconfService;
+ private DeviceService deviceService;
+ private Device device;
+ private GroupStore groupStore;
+
+ private static PiPipeconf buildPipeconf() {
+ final URL p4InfoUrl = P4runtimeGroupProgrammableTest.class.getResource(P4INFO_PATH);
+ return DefaultPiPipeconf.builder()
+ .withId(PIPECONF_ID)
+ .withPipelineModel(niceMock(PiPipelineModel.class))
+ .addExtension(P4_INFO_TEXT, p4InfoUrl)
+ .build();
+ }
+
+ private static GroupBucket outputBucket(int portNum) {
+ ImmutableByteSequence paramVal = ImmutableByteSequence.copyFrom(portNum);
+ PiActionParam param = new PiActionParam(PiActionParamId.of(PORT_PARAM_ID.name()), paramVal);
+ PiTableAction action = PiAction.builder().withId(EGRESS_PORT_ACTION_ID).withParameter(param).build();
+
+ TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .add(Instructions.piTableAction(action))
+ .build();
+
+ return DefaultGroupBucket.createSelectGroupBucket(treatment);
+ }
+
+ private static PiActionGroupMember outputMember(int portNum) {
+ PiActionParam param = new PiActionParam(PORT_PARAM_ID,
+ ImmutableByteSequence.copyFrom(portNum));
+ PiAction piAction = PiAction.builder()
+ .withId(EGRESS_PORT_ACTION_ID)
+ .withParameter(param).build();
+
+ return PiActionGroupMember.builder()
+ .withAction(piAction)
+ .withId(PiActionGroupMemberId.of(BASE_MEM_ID + portNum))
+ .withWeight(DEFAULT_MEMBER_WEIGHT)
+ .build();
+ }
+
+ @Before
+ public void setup() {
+ driverHandler = EasyMock.niceMock(DriverHandler.class);
+ driverData = EasyMock.niceMock(DriverData.class);
+ controller = EasyMock.niceMock(P4RuntimeController.class);
+ client = EasyMock.niceMock(P4RuntimeClient.class);
+ piPipeconfService = EasyMock.niceMock(PiPipeconfService.class);
+ deviceService = EasyMock.niceMock(DeviceService.class);
+ device = EasyMock.niceMock(Device.class);
+ groupStore = EasyMock.niceMock(GroupStore.class);
+
+ expect(controller.hasClient(DEVICE_ID)).andReturn(true).anyTimes();
+ expect(controller.getClient(DEVICE_ID)).andReturn(client).anyTimes();
+ expect(device.is(PiPipelineInterpreter.class)).andReturn(true).anyTimes();
+ expect(device.id()).andReturn(DEVICE_ID).anyTimes();
+ expect(deviceService.getDevice(DEVICE_ID)).andReturn(device).anyTimes();
+ expect(driverData.deviceId()).andReturn(DEVICE_ID).anyTimes();
+ expect(groupStore.getGroup(DEVICE_ID, GROUP_ID)).andReturn(GROUP).anyTimes();
+ expect(piPipeconfService.ofDevice(DEVICE_ID)).andReturn(Optional.of(PIPECONF_ID)).anyTimes();
+ expect(piPipeconfService.getPipeconf(PIPECONF_ID)).andReturn(Optional.of(PIPECONF)).anyTimes();
+ expect(driverHandler.data()).andReturn(driverData).anyTimes();
+ expect(driverHandler.get(P4RuntimeController.class)).andReturn(controller).anyTimes();
+ expect(driverHandler.get(PiPipeconfService.class)).andReturn(piPipeconfService).anyTimes();
+ expect(driverHandler.get(DeviceService.class)).andReturn(deviceService).anyTimes();
+ expect(driverHandler.get(GroupStore.class)).andReturn(groupStore).anyTimes();
+
+ programmable = new P4RuntimeGroupProgrammable();
+ programmable.setHandler(driverHandler);
+ programmable.setData(driverData);
+ EasyMock.replay(driverHandler, driverData, controller, piPipeconfService,
+ deviceService, device, groupStore);
+ }
+
+ /**
+ * Test init function.
+ */
+ @Test
+ public void testInit() {
+ programmable.init();
+ }
+
+ /**
+ * Test add group with buckets.
+ */
+ @Test
+ public void testAddGroup() {
+ List<GroupOperation> ops = Lists.newArrayList();
+ ops.add(GroupOperation.createAddGroupOperation(GROUP_ID, SELECT, BUCKETS));
+ GroupOperations groupOps = new GroupOperations(ops);
+ CompletableFuture<Boolean> completeTrue = new CompletableFuture<>();
+ completeTrue.complete(true);
+
+ Capture<PiActionGroup> groupCapture1 = EasyMock.newCapture();
+ expect(client.writeActionGroup(EasyMock.capture(groupCapture1), EasyMock.eq(INSERT), EasyMock.eq(PIPECONF)))
+ .andReturn(completeTrue).anyTimes();
+
+ Capture<PiActionGroup> groupCapture2 = EasyMock.newCapture();
+ Capture<Collection<PiActionGroupMember>> membersCapture = EasyMock.newCapture();
+ expect(client.writeActionGroupMembers(EasyMock.capture(groupCapture2),
+ EasyMock.capture(membersCapture),
+ EasyMock.eq(INSERT),
+ EasyMock.eq(PIPECONF)))
+ .andReturn(completeTrue).anyTimes();
+
+ EasyMock.replay(client);
+ programmable.performGroupOperation(DEVICE_ID, groupOps);
+
+ // verify group installed by group programmable
+ PiActionGroup group1 = groupCapture1.getValue();
+ PiActionGroup group2 = groupCapture2.getValue();
+ assertEquals("Groups should be equal", group1, group2);
+ assertEquals(GROUP_ID.id(), group1.id().id());
+ assertEquals(PiActionGroup.Type.SELECT, group1.type());
+ assertEquals(ACT_PROF_ID, group1.actionProfileId());
+
+ // members installed
+ Collection<PiActionGroupMember> members = group1.members();
+ assertEquals(3, members.size());
+
+ Assert.assertTrue(EXPECTED_MEMBERS.containsAll(members));
+ Assert.assertTrue(members.containsAll(EXPECTED_MEMBERS));
+ }
+
+ /**
+ * Test remove group with buckets.
+ */
+ @Test
+ public void testDelGroup() {
+ List<GroupOperation> ops = Lists.newArrayList();
+ ops.add(GroupOperation.createDeleteGroupOperation(GROUP_ID, SELECT));
+ GroupOperations groupOps = new GroupOperations(ops);
+ CompletableFuture<Boolean> completeTrue = new CompletableFuture<>();
+ completeTrue.complete(true);
+
+ Capture<PiActionGroup> groupCapture1 = EasyMock.newCapture();
+ expect(client.writeActionGroup(EasyMock.capture(groupCapture1), EasyMock.eq(DELETE), EasyMock.eq(PIPECONF)))
+ .andReturn(completeTrue).anyTimes();
+
+ Capture<PiActionGroup> groupCapture2 = EasyMock.newCapture();
+ Capture<Collection<PiActionGroupMember>> membersCapture = EasyMock.newCapture();
+ expect(client.writeActionGroupMembers(EasyMock.capture(groupCapture2),
+ EasyMock.capture(membersCapture),
+ EasyMock.eq(DELETE),
+ EasyMock.eq(PIPECONF)))
+ .andReturn(completeTrue).anyTimes();
+
+ EasyMock.replay(client);
+ programmable.performGroupOperation(DEVICE_ID, groupOps);
+
+ // verify group installed by group programmable
+ PiActionGroup group1 = groupCapture1.getValue();
+ PiActionGroup group2 = groupCapture2.getValue();
+ assertEquals("Groups should be equal", group1, group2);
+ assertEquals(GROUP_ID.id(), group1.id().id());
+ assertEquals(PiActionGroup.Type.SELECT, group1.type());
+ assertEquals(ACT_PROF_ID, group1.actionProfileId());
+
+ // members installed
+ Collection<PiActionGroupMember> members = group1.members();
+ assertEquals(3, members.size());
+
+ Assert.assertTrue(EXPECTED_MEMBERS.containsAll(members));
+ Assert.assertTrue(members.containsAll(EXPECTED_MEMBERS));
+ }
+}
diff --git a/drivers/p4runtime/src/test/resources/default.p4info b/drivers/p4runtime/src/test/resources/default.p4info
new file mode 120000
index 0000000..8f71cbe
--- /dev/null
+++ b/drivers/p4runtime/src/test/resources/default.p4info
@@ -0,0 +1 @@
+../../../../../tools/test/p4src/p4-16/p4c-out/default.p4info
\ No newline at end of file
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkFlowRuleStore.java b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkFlowRuleStore.java
index e41a5ff..6b532c3 100644
--- a/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkFlowRuleStore.java
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/VirtualNetworkFlowRuleStore.java
@@ -19,8 +19,8 @@
import org.onosproject.net.DeviceId;
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.FlowRuleBatchEvent;
-import org.onosproject.net.flow.FlowRuleBatchOperation;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchEvent;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchOperation;
import org.onosproject.net.flow.FlowRuleEvent;
import org.onosproject.net.flow.FlowRuleStoreDelegate;
import org.onosproject.net.flow.TableStatisticsEntry;
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualFlowRuleProvider.java b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualFlowRuleProvider.java
index 89eb591..8a4ec34 100644
--- a/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualFlowRuleProvider.java
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/virtual/provider/VirtualFlowRuleProvider.java
@@ -17,7 +17,7 @@
import org.onosproject.incubator.net.virtual.NetworkId;
import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.FlowRuleBatchOperation;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchOperation;
/**
* Abstraction of a virtual flow rule provider.
diff --git a/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkFlowRuleManager.java b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkFlowRuleManager.java
index 56c9489..237c3e8 100644
--- a/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkFlowRuleManager.java
+++ b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkFlowRuleManager.java
@@ -40,10 +40,10 @@
import org.onosproject.net.flow.DefaultFlowEntry;
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.FlowRuleBatchEntry;
-import org.onosproject.net.flow.FlowRuleBatchEvent;
-import org.onosproject.net.flow.FlowRuleBatchOperation;
-import org.onosproject.net.flow.FlowRuleBatchRequest;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchEntry;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchEvent;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchOperation;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchRequest;
import org.onosproject.net.flow.FlowRuleEvent;
import org.onosproject.net.flow.FlowRuleListener;
import org.onosproject.net.flow.FlowRuleOperation;
diff --git a/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/provider/DefaultVirtualFlowRuleProvider.java b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/provider/DefaultVirtualFlowRuleProvider.java
index bc519d4..8e497e8 100644
--- a/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/provider/DefaultVirtualFlowRuleProvider.java
+++ b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/provider/DefaultVirtualFlowRuleProvider.java
@@ -56,8 +56,8 @@
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.FlowRuleBatchEntry;
-import org.onosproject.net.flow.FlowRuleBatchOperation;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchEntry;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchOperation;
import org.onosproject.net.flow.FlowRuleEvent;
import org.onosproject.net.flow.FlowRuleListener;
import org.onosproject.net.flow.FlowRuleOperations;
diff --git a/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkFlowObjectiveManagerTest.java b/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkFlowObjectiveManagerTest.java
index 92dd4ab..d567a94 100644
--- a/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkFlowObjectiveManagerTest.java
+++ b/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkFlowObjectiveManagerTest.java
@@ -43,7 +43,7 @@
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.FlowRuleBatchOperation;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchOperation;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.Criteria;
diff --git a/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkFlowRuleManagerTest.java b/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkFlowRuleManagerTest.java
index 0a4cfed..c447755 100644
--- a/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkFlowRuleManagerTest.java
+++ b/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkFlowRuleManagerTest.java
@@ -49,7 +49,7 @@
import org.onosproject.net.flow.DefaultFlowRule;
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.FlowRuleBatchOperation;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchOperation;
import org.onosproject.net.flow.FlowRuleEvent;
import org.onosproject.net.flow.FlowRuleListener;
import org.onosproject.net.flow.FlowRuleService;
diff --git a/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkPacketManagerTest.java b/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkPacketManagerTest.java
index e2fddf4..5684a72 100644
--- a/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkPacketManagerTest.java
+++ b/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkPacketManagerTest.java
@@ -51,7 +51,7 @@
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.FlowRuleBatchOperation;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchOperation;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flowobjective.FlowObjectiveServiceAdapter;
import org.onosproject.net.flowobjective.ForwardingObjective;
diff --git a/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/core/ApplicationProtoTranslator.java b/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/core/ApplicationProtoTranslator.java
index a4b2ca6..eba30ee 100644
--- a/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/core/ApplicationProtoTranslator.java
+++ b/incubator/protobuf/models/src/main/java/org/onosproject/incubator/protobuf/models/core/ApplicationProtoTranslator.java
@@ -23,7 +23,6 @@
import org.onosproject.incubator.protobuf.models.security.PermissionProtoTranslator;
import org.onosproject.security.Permission;
-import java.util.Optional;
import java.util.Set;
import static org.onosproject.grpc.core.models.ApplicationProtoOuterClass.ApplicationProto.getDefaultInstance;
@@ -46,12 +45,21 @@
app.getPermissionsList().forEach(p ->
permissions.add(PermissionProtoTranslator.translate(p)));
- return new DefaultApplication(ApplicationIdProtoTranslator.translate(app.getAppId()),
- VersionProtoTranslator.translate(app.getVersion()), app.getTitle(),
- app.getDescription(), app.getOrigin(), app.getCategory(), app.getUrl(),
- app.getReadme(), app.toByteArray(),
- (ApplicationRole) ApplicationEnumsProtoTranslator.translate(app.getRole()).get(),
- permissions, Optional.empty(), app.getFeaturesList(), app.getRequiredAppsList());
+ return DefaultApplication.builder()
+ .withAppId(ApplicationIdProtoTranslator.translate(app.getAppId()))
+ .withVersion(VersionProtoTranslator.translate(app.getVersion()))
+ .withTitle(app.getTitle())
+ .withDescription(app.getDescription())
+ .withOrigin(app.getOrigin())
+ .withCategory(app.getCategory())
+ .withUrl(app.getUrl())
+ .withReadme(app.getReadme())
+ .withIcon(app.toByteArray())
+ .withRole((ApplicationRole) ApplicationEnumsProtoTranslator.translate(app.getRole()).get())
+ .withPermissions(permissions)
+ .withFeatures(app.getFeaturesList())
+ .withRequiredApps(app.getRequiredAppsList())
+ .build();
}
/**
diff --git a/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/DistributedVirtualFlowRuleStore.java b/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/DistributedVirtualFlowRuleStore.java
index 943627a..aaaf766 100644
--- a/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/DistributedVirtualFlowRuleStore.java
+++ b/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/DistributedVirtualFlowRuleStore.java
@@ -54,10 +54,10 @@
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowId;
import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.FlowRuleBatchEntry;
-import org.onosproject.net.flow.FlowRuleBatchEvent;
-import org.onosproject.net.flow.FlowRuleBatchOperation;
-import org.onosproject.net.flow.FlowRuleBatchRequest;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchEntry;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchEvent;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchOperation;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchRequest;
import org.onosproject.net.flow.FlowRuleEvent;
import org.onosproject.net.flow.FlowRuleService;
import org.onosproject.net.flow.FlowRuleStoreDelegate;
diff --git a/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/SimpleVirtualFlowRuleStore.java b/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/SimpleVirtualFlowRuleStore.java
index 3f02450..502796b 100644
--- a/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/SimpleVirtualFlowRuleStore.java
+++ b/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/SimpleVirtualFlowRuleStore.java
@@ -40,10 +40,10 @@
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowId;
import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.FlowRuleBatchEntry;
-import org.onosproject.net.flow.FlowRuleBatchEvent;
-import org.onosproject.net.flow.FlowRuleBatchOperation;
-import org.onosproject.net.flow.FlowRuleBatchRequest;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchEntry;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchEvent;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchOperation;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchRequest;
import org.onosproject.net.flow.FlowRuleEvent;
import org.onosproject.net.flow.FlowRuleStoreDelegate;
import org.onosproject.net.flow.StoredFlowEntry;
diff --git a/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/primitives/VirtualFlowRuleBatchEvent.java b/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/primitives/VirtualFlowRuleBatchEvent.java
index 6ca341d..21275f3 100644
--- a/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/primitives/VirtualFlowRuleBatchEvent.java
+++ b/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/primitives/VirtualFlowRuleBatchEvent.java
@@ -17,7 +17,7 @@
package org.onosproject.incubator.store.virtual.impl.primitives;
import org.onosproject.incubator.net.virtual.NetworkId;
-import org.onosproject.net.flow.FlowRuleBatchEvent;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchEvent;
import java.util.Objects;
diff --git a/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/primitives/VirtualFlowRuleBatchOperation.java b/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/primitives/VirtualFlowRuleBatchOperation.java
index c390ff6..5268d5f 100644
--- a/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/primitives/VirtualFlowRuleBatchOperation.java
+++ b/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/primitives/VirtualFlowRuleBatchOperation.java
@@ -17,7 +17,7 @@
package org.onosproject.incubator.store.virtual.impl.primitives;
import org.onosproject.incubator.net.virtual.NetworkId;
-import org.onosproject.net.flow.FlowRuleBatchOperation;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchOperation;
import java.util.Objects;
diff --git a/lib/BUCK b/lib/BUCK
index b4eed7b..8b6dc1d 100644
--- a/lib/BUCK
+++ b/lib/BUCK
@@ -1,4 +1,4 @@
-# ***** This file was auto-generated at Wed, 13 Sep 2017 22:16:27 GMT. Do not edit this file manually. *****
+# ***** This file was auto-generated at Fri, 22 Sep 2017 06:46:04 GMT. Do not edit this file manually. *****
# ***** Use onos-lib-gen *****
pass_thru_pom(
@@ -50,6 +50,7 @@
':junit',
':easymock',
':hamcrest-all',
+ ':hamcrest-optional',
':guava-testlib',
'//utils/junit:onlab-junit',
],
@@ -1509,3 +1510,12 @@
visibility = [ 'PUBLIC' ],
)
+remote_jar (
+ name = 'hamcrest-optional',
+ out = 'hamcrest-optional-1.1.0.jar',
+ url = 'mvn:com.spotify:hamcrest-optional:jar:1.1.0',
+ sha1 = 'c2dfe3a43794b15fb4c28de0027fe6e249855b3b',
+ maven_coords = 'com.spotify:hamcrest-optional:jar:NON-OSGI:1.1.0',
+ visibility = [ 'PUBLIC' ],
+)
+
diff --git a/lib/deps.json b/lib/deps.json
index 5a9124c..071d95f 100644
--- a/lib/deps.json
+++ b/lib/deps.json
@@ -29,6 +29,7 @@
"junit",
"easymock",
"hamcrest-all",
+ "hamcrest-optional",
"guava-testlib",
"//utils/junit:onlab-junit"
],
@@ -268,6 +269,7 @@
"google-errorprone-2.0.19": "mvn:com.google.errorprone:error_prone_annotations:2.0.19",
"google-instrumentation-0.3.0": "mvn:com.google.instrumentation:instrumentation-api:0.3.0",
"bcpkix-jdk15on": "mvn:org.bouncycastle:bcpkix-jdk15on:1.58",
- "bcprov-jdk15on": "mvn:org.bouncycastle:bcprov-jdk15on:1.58"
+ "bcprov-jdk15on": "mvn:org.bouncycastle:bcprov-jdk15on:1.58",
+ "hamcrest-optional": "mvn:com.spotify:hamcrest-optional:1.1.0"
}
}
diff --git a/lib/pom.xml b/lib/pom.xml
index 07ef09b..bae6e67 100644
--- a/lib/pom.xml
+++ b/lib/pom.xml
@@ -77,6 +77,12 @@
<version>1.3</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>com.spotify</groupId>
+ <artifactId>hamcrest-optional</artifactId>
+ <version>1.1.0</version>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>org.slf4j</groupId>
@@ -650,6 +656,12 @@
</dependency>
<dependency>
+ <groupId>com.spotify</groupId>
+ <artifactId>hamcrest-optional</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava-testlib</artifactId>
<scope>test</scope>
diff --git a/protocols/p4runtime/api/src/main/java/org/onosproject/p4runtime/api/P4RuntimeClient.java b/protocols/p4runtime/api/src/main/java/org/onosproject/p4runtime/api/P4RuntimeClient.java
index 9760ad4..a1b984b 100644
--- a/protocols/p4runtime/api/src/main/java/org/onosproject/p4runtime/api/P4RuntimeClient.java
+++ b/protocols/p4runtime/api/src/main/java/org/onosproject/p4runtime/api/P4RuntimeClient.java
@@ -18,9 +18,12 @@
import com.google.common.annotations.Beta;
import org.onosproject.net.pi.model.PiPipeconf;
+import org.onosproject.net.pi.runtime.PiActionProfileId;
import org.onosproject.net.pi.runtime.PiCounterCellData;
import org.onosproject.net.pi.runtime.PiCounterCellId;
import org.onosproject.net.pi.runtime.PiCounterId;
+import org.onosproject.net.pi.runtime.PiActionGroup;
+import org.onosproject.net.pi.runtime.PiActionGroupMember;
import org.onosproject.net.pi.runtime.PiPacketOperation;
import org.onosproject.net.pi.runtime.PiTableEntry;
import org.onosproject.net.pi.runtime.PiTableId;
@@ -129,6 +132,42 @@
PiPipeconf pipeconf);
/**
+ * Performs the given write operation for the given action group members and pipeconf.
+ *
+ * @param group action group
+ * @param members the collection of action group members
+ * @param opType write operation type
+ * @param pipeconf the pipeconf currently deployed on the device
+ * @return true if the operation was successful, false otherwise
+ */
+ CompletableFuture<Boolean> writeActionGroupMembers(PiActionGroup group,
+ Collection<PiActionGroupMember> members,
+ WriteOperationType opType,
+ PiPipeconf pipeconf);
+
+ /**
+ * Performs the given write operation for the given action group and pipeconf.
+ *
+ * @param group the action group
+ * @param opType write operation type
+ * @param pipeconf the pipeconf currently deployed on the device
+ * @return true if the operation was successful, false otherwise
+ */
+ CompletableFuture<Boolean> writeActionGroup(PiActionGroup group,
+ WriteOperationType opType,
+ PiPipeconf pipeconf);
+
+ /**
+ * Dumps all groups currently installed for the given action profile.
+ *
+ * @param actionProfileId the action profile id
+ * @param pipeconf the pipeconf currently deployed on the device
+ * @return completable future of a collection of groups
+ */
+ CompletableFuture<Collection<PiActionGroup>> dumpGroups(PiActionProfileId actionProfileId,
+ PiPipeconf pipeconf);
+
+ /**
* Shutdown the client by terminating any active RPC such as the stream channel.
*/
void shutdown();
diff --git a/protocols/p4runtime/api/src/main/java/org/onosproject/p4runtime/api/P4RuntimeGroupReference.java b/protocols/p4runtime/api/src/main/java/org/onosproject/p4runtime/api/P4RuntimeGroupReference.java
new file mode 100644
index 0000000..543ae4d
--- /dev/null
+++ b/protocols/p4runtime/api/src/main/java/org/onosproject/p4runtime/api/P4RuntimeGroupReference.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2017-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.p4runtime.api;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.pi.runtime.PiActionProfileId;
+import org.onosproject.net.pi.runtime.PiActionGroupId;
+
+/**
+ * Class containing the reference for a group in P4Runtime.
+ */
+@Beta
+public final class P4RuntimeGroupReference {
+ private final DeviceId deviceId;
+ private final PiActionProfileId piActionProfileId;
+ private final PiActionGroupId groupId;
+
+ /**
+ * Creates P4 runtime group reference.
+ *
+ * @param deviceId the device id of group
+ * @param piActionProfileId the action profile id
+ * @param groupId the group Id of group
+ */
+ public P4RuntimeGroupReference(DeviceId deviceId, PiActionProfileId piActionProfileId,
+ PiActionGroupId groupId) {
+ this.deviceId = deviceId;
+ this.piActionProfileId = piActionProfileId;
+ this.groupId = groupId;
+ }
+
+ /**
+ * Gets device id of this group.
+ *
+ * @return the device id
+ */
+ public DeviceId deviceId() {
+ return deviceId;
+ }
+
+ /**
+ * Gets action profile id of this group.
+ *
+ * @return the action profile id
+ */
+ public PiActionProfileId actionProfileId() {
+ return piActionProfileId;
+ }
+
+ /**
+ * Gets group id of this group.
+ *
+ * @return group id
+ */
+ public PiActionGroupId groupId() {
+ return groupId;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ P4RuntimeGroupReference that = (P4RuntimeGroupReference) o;
+ return Objects.equal(deviceId, that.deviceId) &&
+ Objects.equal(piActionProfileId, that.piActionProfileId) &&
+ Objects.equal(groupId, that.groupId);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(deviceId, piActionProfileId, groupId);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("deviceId", deviceId)
+ .add("piActionProfileId", piActionProfileId)
+ .add("groupId", groupId)
+ .toString();
+ }
+}
diff --git a/protocols/p4runtime/api/src/main/java/org/onosproject/p4runtime/api/P4RuntimeGroupWrapper.java b/protocols/p4runtime/api/src/main/java/org/onosproject/p4runtime/api/P4RuntimeGroupWrapper.java
new file mode 100644
index 0000000..8cb4b83
--- /dev/null
+++ b/protocols/p4runtime/api/src/main/java/org/onosproject/p4runtime/api/P4RuntimeGroupWrapper.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2017-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.p4runtime.api;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.net.group.Group;
+import org.onosproject.net.pi.runtime.PiActionGroup;
+
+/**
+ * A wrapper for a ONOS group installed on a P4Runtime device.
+ */
+@Beta
+public class P4RuntimeGroupWrapper {
+ private final PiActionGroup piActionGroup;
+ private final Group group;
+ private final long installMilliSeconds;
+
+ /**
+ * Creates new group wrapper.
+ *
+ * @param piActionGroup the Pi action group
+ * @param group the group
+ * @param installMilliSeconds the installation time
+ */
+ public P4RuntimeGroupWrapper(PiActionGroup piActionGroup, Group group,
+ long installMilliSeconds) {
+ this.piActionGroup = piActionGroup;
+ this.group = group;
+ this.installMilliSeconds = installMilliSeconds;
+ }
+
+ /**
+ * Gets PI action group from this wrapper.
+ *
+ * @return the PI action group
+ */
+ public PiActionGroup piActionGroup() {
+ return piActionGroup;
+ }
+
+ /**
+ * Gets group from this wrapper.
+ *
+ * @return the group
+ */
+ public Group group() {
+ return group;
+ }
+
+ /**
+ * Gets installation time of this wrapper.
+ *
+ * @return the installation time
+ */
+ public long installMilliSeconds() {
+ return installMilliSeconds;
+ }
+}
diff --git a/protocols/p4runtime/ctl/BUCK b/protocols/p4runtime/ctl/BUCK
index 899a1ff..cb22402 100644
--- a/protocols/p4runtime/ctl/BUCK
+++ b/protocols/p4runtime/ctl/BUCK
@@ -13,8 +13,9 @@
TEST_DEPS = [
'//lib:TEST',
+ '//lib:GRPC_TEST_1.3',
'//lib:minimal-json',
- '//incubator/bmv2/model:onos-incubator-bmv2-model',
+ '//lib:grpc-protobuf-lite-' + GRPC_VER,
]
osgi_jar_with_tests(
diff --git a/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/ActionProfileGroupEncoder.java b/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/ActionProfileGroupEncoder.java
new file mode 100644
index 0000000..472bf8e
--- /dev/null
+++ b/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/ActionProfileGroupEncoder.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2017-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.p4runtime.ctl;
+
+import com.google.common.collect.Maps;
+import org.onosproject.net.pi.model.PiPipeconf;
+import org.onosproject.net.pi.runtime.PiActionProfileId;
+import org.onosproject.net.pi.runtime.PiActionGroup;
+import org.onosproject.net.pi.runtime.PiActionGroupId;
+import p4.P4RuntimeOuterClass.ActionProfileGroup;
+import p4.P4RuntimeOuterClass.ActionProfileGroup.Member;
+import p4.P4RuntimeOuterClass.ActionProfileMember;
+import p4.config.P4InfoOuterClass;
+
+import java.util.Collection;
+import java.util.Map;
+
+import static java.lang.String.format;
+
+/**
+ * Encoder/Decoder for action profile group.
+ */
+public final class ActionProfileGroupEncoder {
+ private ActionProfileGroupEncoder() {
+ // hide default constructor
+ }
+
+ /**
+ * Encode a PI action group to a action profile group.
+ *
+ * @param piActionGroup the action profile group
+ * @param pipeconf the pipeconf
+ * @return a action profile group encoded from PI action group
+ * @throws P4InfoBrowser.NotFoundException if can't find action profile from P4Info browser
+ * @throws EncodeException if can't find P4Info from pipeconf
+ */
+ static ActionProfileGroup encode(PiActionGroup piActionGroup, PiPipeconf pipeconf)
+ throws P4InfoBrowser.NotFoundException, EncodeException {
+ P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);
+
+ if (browser == null) {
+ throw new EncodeException(format("Can't get P4 info browser from pipeconf %s", pipeconf));
+ }
+
+ PiActionProfileId piActionProfileId = piActionGroup.actionProfileId();
+ int actionProfileId;
+ P4InfoOuterClass.ActionProfile actionProfile =
+ browser.actionProfiles().getByName(piActionProfileId.id());
+ actionProfileId = actionProfile.getPreamble().getId();
+ ActionProfileGroup.Builder actionProfileGroupBuilder =
+ ActionProfileGroup.newBuilder()
+ .setGroupId(piActionGroup.id().id())
+ .setActionProfileId(actionProfileId);
+
+ switch (piActionGroup.type()) {
+ case SELECT:
+ actionProfileGroupBuilder.setType(ActionProfileGroup.Type.SELECT);
+ break;
+ default:
+ throw new EncodeException(format("Unsupported pi action group type %s",
+ piActionGroup.type()));
+ }
+
+ piActionGroup.members().forEach(m -> {
+ // TODO: currently we don't set "watch" field of member
+ Member member = Member.newBuilder()
+ .setMemberId(m.id().id())
+ .setWeight(m.weight())
+ .build();
+ actionProfileGroupBuilder.addMembers(member);
+ });
+
+ return actionProfileGroupBuilder.build();
+ }
+
+ /**
+ * Decode an action profile group with members information to a PI action group.
+ *
+ * @param actionProfileGroup the action profile group
+ * @param members members of the action profile group
+ * @param pipeconf the pipeconf
+ * @return decoded PI action group
+ * @throws P4InfoBrowser.NotFoundException if can't find action profile from P4Info browser
+ * @throws EncodeException if can't find P4Info from pipeconf
+ */
+ static PiActionGroup decode(ActionProfileGroup actionProfileGroup,
+ Collection<ActionProfileMember> members,
+ PiPipeconf pipeconf)
+ throws P4InfoBrowser.NotFoundException, EncodeException {
+ P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);
+ if (browser == null) {
+ throw new EncodeException(format("Can't get P4 info browser from pipeconf %s", pipeconf));
+ }
+ PiActionGroup.Builder piActionGroupBuilder = PiActionGroup.builder();
+
+ P4InfoOuterClass.ActionProfile actionProfile = browser.actionProfiles()
+ .getById(actionProfileGroup.getActionProfileId());
+ PiActionProfileId piActionProfileId = PiActionProfileId.of(actionProfile.getPreamble().getName());
+ piActionGroupBuilder.withActionProfileId(piActionProfileId)
+ .withId(PiActionGroupId.of(actionProfileGroup.getGroupId()));
+
+ switch (actionProfileGroup.getType()) {
+ case SELECT:
+ piActionGroupBuilder.withType(PiActionGroup.Type.SELECT);
+ break;
+ default:
+ throw new EncodeException(format("Unsupported action profile type %s",
+ actionProfileGroup.getType()));
+ }
+
+ Map<Integer, Integer> memberWeights = Maps.newHashMap();
+ actionProfileGroup.getMembersList().forEach(member -> {
+ int weight = member.getWeight();
+ if (weight < 1) {
+ // FIXME: currently PI has a bug which will always return weight 0
+ // ONOS won't accept group member with weight 0
+ weight = 1;
+ }
+ memberWeights.put(member.getMemberId(), weight);
+ });
+
+ for (ActionProfileMember member : members) {
+ int weight = memberWeights.get(member.getMemberId());
+ piActionGroupBuilder
+ .addMember(ActionProfileMemberEncoder.decode(member, weight, pipeconf));
+ }
+
+ return piActionGroupBuilder.build();
+ }
+}
diff --git a/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/ActionProfileMemberEncoder.java b/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/ActionProfileMemberEncoder.java
new file mode 100644
index 0000000..2f08a59
--- /dev/null
+++ b/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/ActionProfileMemberEncoder.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2017-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.p4runtime.ctl;
+
+import org.onosproject.net.pi.model.PiPipeconf;
+import org.onosproject.net.pi.runtime.PiActionGroup;
+import org.onosproject.net.pi.runtime.PiActionGroupMember;
+import org.onosproject.net.pi.runtime.PiActionGroupMemberId;
+import p4.P4RuntimeOuterClass;
+import p4.P4RuntimeOuterClass.ActionProfileMember;
+import p4.config.P4InfoOuterClass;
+
+import static java.lang.String.format;
+import static org.onosproject.p4runtime.ctl.TableEntryEncoder.decodeActionMsg;
+import static org.onosproject.p4runtime.ctl.TableEntryEncoder.encodePiAction;
+
+/**
+ * Encoder/Decoder of action profile member.
+ */
+public final class ActionProfileMemberEncoder {
+ private ActionProfileMemberEncoder() {
+ // Hide default constructor
+ }
+
+ /**
+ * Encode a PiActionGroupMember to a ActionProfileMember.
+ *
+ * @param group the PI action group of members
+ * @param member the member to encode
+ * @param pipeconf the pipeconf
+ * @return encoded member
+ */
+ /**
+ * Encode a PiActionGroupMember to a ActionProfileMember.
+ *
+ * @param group the PI action group of members
+ * @param member the member to encode
+ * @param pipeconf the pipeconf, as encode spec
+ * @return encoded member
+ * @throws P4InfoBrowser.NotFoundException can't find action profile from P4Info browser
+ * @throws EncodeException can't find P4Info from pipeconf
+ */
+ static ActionProfileMember encode(PiActionGroup group,
+ PiActionGroupMember member,
+ PiPipeconf pipeconf)
+ throws P4InfoBrowser.NotFoundException, EncodeException {
+
+ P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);
+
+ if (browser == null) {
+ throw new EncodeException(format("Can't get P4 info browser from pipeconf %s", pipeconf));
+ }
+
+ ActionProfileMember.Builder actionProfileMemberBuilder =
+ ActionProfileMember.newBuilder();
+
+ // member id
+ actionProfileMemberBuilder.setMemberId(member.id().id());
+
+ // action profile id
+ P4InfoOuterClass.ActionProfile actionProfile =
+ browser.actionProfiles().getByName(group.actionProfileId().id());
+
+ int actionProfileId = actionProfile.getPreamble().getId();
+ actionProfileMemberBuilder.setActionProfileId(actionProfileId);
+
+ // Action
+ P4RuntimeOuterClass.Action action = encodePiAction(member.action(), browser);
+ actionProfileMemberBuilder.setAction(action);
+
+ return actionProfileMemberBuilder.build();
+ }
+
+ /**
+ * Decode an action profile member to PI action group member.
+ *
+ * @param member the action profile member
+ * @param weight the weight of the member
+ * @param pipeconf the pipeconf, as decode spec
+ * @return decoded PI action group member
+ * @throws P4InfoBrowser.NotFoundException can't find definition of action from P4 info
+ * @throws EncodeException can't get P4 info browser from pipeconf
+ */
+ static PiActionGroupMember decode(ActionProfileMember member,
+ int weight,
+ PiPipeconf pipeconf)
+ throws P4InfoBrowser.NotFoundException, EncodeException {
+ P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);
+
+ if (browser == null) {
+ throw new EncodeException(format("Can't get P4 info browser from pipeconf %s", pipeconf));
+ }
+ return PiActionGroupMember.builder().withId(PiActionGroupMemberId.of(member.getMemberId()))
+ .withWeight(weight)
+ .withAction(decodeActionMsg(member.getAction(), browser))
+ .build();
+ }
+}
diff --git a/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/P4RuntimeClientImpl.java b/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/P4RuntimeClientImpl.java
index 4dff7ea..d9da345 100644
--- a/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/P4RuntimeClientImpl.java
+++ b/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/P4RuntimeClientImpl.java
@@ -17,7 +17,10 @@
package org.onosproject.p4runtime.ctl;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.google.protobuf.ByteString;
import io.grpc.Context;
@@ -26,13 +29,17 @@
import io.grpc.StatusRuntimeException;
import io.grpc.stub.StreamObserver;
import org.onlab.osgi.DefaultServiceDirectory;
+import org.onlab.util.Tools;
import org.onosproject.net.DeviceId;
import org.onosproject.net.pi.model.PiPipeconf;
+import org.onosproject.net.pi.runtime.PiActionProfileId;
import org.onosproject.net.pi.runtime.PiCounterCellData;
import org.onosproject.net.pi.runtime.PiCounterCellId;
import org.onosproject.net.pi.runtime.PiCounterId;
import org.onosproject.net.pi.runtime.PiDirectCounterCellId;
import org.onosproject.net.pi.runtime.PiIndirectCounterCellId;
+import org.onosproject.net.pi.runtime.PiActionGroup;
+import org.onosproject.net.pi.runtime.PiActionGroupMember;
import org.onosproject.net.pi.runtime.PiPacketOperation;
import org.onosproject.net.pi.runtime.PiPipeconfService;
import org.onosproject.net.pi.runtime.PiTableEntry;
@@ -41,6 +48,8 @@
import org.onosproject.p4runtime.api.P4RuntimeEvent;
import org.slf4j.Logger;
import p4.P4RuntimeGrpc;
+import p4.P4RuntimeOuterClass.ActionProfileGroup;
+import p4.P4RuntimeOuterClass.ActionProfileMember;
import p4.P4RuntimeOuterClass.Entity;
import p4.P4RuntimeOuterClass.ForwardingPipelineConfig;
import p4.P4RuntimeOuterClass.MasterArbitrationUpdate;
@@ -53,6 +62,7 @@
import p4.P4RuntimeOuterClass.TableEntry;
import p4.P4RuntimeOuterClass.Update;
import p4.P4RuntimeOuterClass.WriteRequest;
+import p4.config.P4InfoOuterClass;
import p4.config.P4InfoOuterClass.P4Info;
import p4.tmp.P4Config;
@@ -70,6 +80,8 @@
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Supplier;
@@ -79,6 +91,8 @@
import static org.onlab.util.Tools.groupedThreads;
import static org.onosproject.net.pi.model.PiPipeconf.ExtensionType;
import static org.slf4j.LoggerFactory.getLogger;
+import static p4.P4RuntimeOuterClass.Entity.EntityCase.ACTION_PROFILE_GROUP;
+import static p4.P4RuntimeOuterClass.Entity.EntityCase.ACTION_PROFILE_MEMBER;
import static p4.P4RuntimeOuterClass.Entity.EntityCase.TABLE_ENTRY;
import static p4.P4RuntimeOuterClass.PacketOut;
import static p4.P4RuntimeOuterClass.SetForwardingPipelineConfigRequest.Action.VERIFY_AND_COMMIT;
@@ -107,7 +121,14 @@
private final Lock writeLock = new ReentrantLock();
private final StreamObserver<StreamMessageRequest> streamRequestObserver;
-
+ /**
+ * Default constructor.
+ *
+ * @param deviceId the ONOS device id
+ * @param p4DeviceId the P4 device id
+ * @param channel gRPC channel
+ * @param controller runtime client controller
+ */
P4RuntimeClientImpl(DeviceId deviceId, long p4DeviceId, ManagedChannel channel,
P4RuntimeControllerImpl controller) {
this.deviceId = deviceId;
@@ -222,6 +243,30 @@
"readAllCounterCells-" + cellIds.hashCode());
}
+ @Override
+ public CompletableFuture<Boolean> writeActionGroupMembers(PiActionGroup group,
+ Collection<PiActionGroupMember> members,
+ WriteOperationType opType,
+ PiPipeconf pipeconf) {
+ return supplyInContext(() -> doWriteActionGroupMembers(group, members, opType, pipeconf),
+ "writeActionGroupMembers-" + opType.name());
+ }
+
+ @Override
+ public CompletableFuture<Boolean> writeActionGroup(PiActionGroup group,
+ WriteOperationType opType,
+ PiPipeconf pipeconf) {
+ return supplyInContext(() -> doWriteActionGroup(group, opType, pipeconf),
+ "writeActionGroup-" + opType.name());
+ }
+
+ @Override
+ public CompletableFuture<Collection<PiActionGroup>> dumpGroups(PiActionProfileId actionProfileId,
+ PiPipeconf pipeconf) {
+ return supplyInContext(() -> doDumpGroups(actionProfileId, pipeconf),
+ "dumpGroups-" + actionProfileId.id());
+ }
+
/* Blocking method implementations below */
private boolean doInitStreamChannel() {
@@ -481,6 +526,191 @@
return CounterEntryCodec.decodeCounterEntities(entities, counterIdMap, pipeconf);
}
+ private boolean doWriteActionGroupMembers(PiActionGroup group, Collection<PiActionGroupMember> members,
+ WriteOperationType opType, PiPipeconf pipeconf) {
+ WriteRequest.Builder writeRequestBuilder = WriteRequest.newBuilder();
+
+ Collection<ActionProfileMember> actionProfileMembers = Lists.newArrayList();
+ try {
+ for (PiActionGroupMember member : members) {
+ actionProfileMembers.add(
+ ActionProfileMemberEncoder.encode(group, member, pipeconf)
+ );
+ }
+ } catch (EncodeException | P4InfoBrowser.NotFoundException e) {
+ log.warn("Can't encode group member {} due to {}", members, e.getMessage());
+ return false;
+ }
+
+ Collection<Update> updateMsgs = actionProfileMembers.stream()
+ .map(actionProfileMember ->
+ Update.newBuilder()
+ .setEntity(Entity.newBuilder()
+ .setActionProfileMember(actionProfileMember)
+ .build())
+ .setType(UPDATE_TYPES.get(opType))
+ .build())
+ .collect(Collectors.toList());
+
+ if (updateMsgs.size() == 0) {
+ // Nothing to update
+ return true;
+ }
+
+ writeRequestBuilder
+ .setDeviceId(p4DeviceId)
+ .addAllUpdates(updateMsgs);
+ try {
+ blockingStub.write(writeRequestBuilder.build());
+ return true;
+ } catch (StatusRuntimeException e) {
+ log.warn("Unable to write table entries ({}): {}", opType, e.getMessage());
+ return false;
+ }
+ }
+
+ private Collection<PiActionGroup> doDumpGroups(PiActionProfileId piActionProfileId, PiPipeconf pipeconf) {
+ log.debug("Dumping groups from action profile {} from {} (pipeconf {})...",
+ piActionProfileId.id(), deviceId, pipeconf.id());
+ P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(pipeconf);
+ if (browser == null) {
+ log.warn("Unable to get a P4Info browser for pipeconf {}, skipping dump action profile {}",
+ pipeconf, piActionProfileId);
+ return Collections.emptySet();
+ }
+
+ int actionProfileId;
+ try {
+ P4InfoOuterClass.ActionProfile actionProfile =
+ browser.actionProfiles().getByName(piActionProfileId.id());
+ actionProfileId = actionProfile.getPreamble().getId();
+ } catch (P4InfoBrowser.NotFoundException e) {
+ log.warn("Can't find action profile {} from p4info", piActionProfileId);
+ return Collections.emptySet();
+ }
+
+ ActionProfileGroup actionProfileGroup =
+ ActionProfileGroup.newBuilder()
+ .setActionProfileId(actionProfileId)
+ .build();
+
+ ReadRequest requestMsg = ReadRequest.newBuilder()
+ .setDeviceId(p4DeviceId)
+ .addEntities(Entity.newBuilder()
+ .setActionProfileGroup(actionProfileGroup)
+ .build())
+ .build();
+
+ Iterator<ReadResponse> responses;
+ try {
+ responses = blockingStub.read(requestMsg);
+ } catch (StatusRuntimeException e) {
+ log.warn("Unable to read action profile {} due to {}", piActionProfileId, e.getMessage());
+ return Collections.emptySet();
+ }
+
+ List<ActionProfileGroup> actionProfileGroups =
+ Tools.stream(() -> responses)
+ .map(ReadResponse::getEntitiesList)
+ .flatMap(List::stream)
+ .filter(entity -> entity.getEntityCase() == ACTION_PROFILE_GROUP)
+ .map(Entity::getActionProfileGroup)
+ .collect(Collectors.toList());
+
+ log.debug("Retrieved {} groups from action profile {} on {}...",
+ actionProfileGroups.size(), piActionProfileId.id(), deviceId);
+
+ // group id -> members
+ Multimap<Integer, ActionProfileMember> actionProfileMemberMap = HashMultimap.create();
+ AtomicLong memberCount = new AtomicLong(0);
+ AtomicBoolean success = new AtomicBoolean(true);
+ actionProfileGroups.forEach(actProfGrp -> {
+ actProfGrp.getMembersList().forEach(member -> {
+ ActionProfileMember actProfMember =
+ ActionProfileMember.newBuilder()
+ .setActionProfileId(actProfGrp.getActionProfileId())
+ .setMemberId(member.getMemberId())
+ .build();
+ Entity entity = Entity.newBuilder()
+ .setActionProfileMember(actProfMember)
+ .build();
+
+ ReadRequest reqMsg = ReadRequest.newBuilder().setDeviceId(p4DeviceId)
+ .addEntities(entity)
+ .build();
+
+ Iterator<ReadResponse> resps;
+ try {
+ resps = blockingStub.read(reqMsg);
+ } catch (StatusRuntimeException e) {
+ log.warn("Unable to read member {} from action profile {} due to {}",
+ member, piActionProfileId, e.getMessage());
+ success.set(false);
+ return;
+ }
+ Tools.stream(() -> resps)
+ .map(ReadResponse::getEntitiesList)
+ .flatMap(List::stream)
+ .filter(e -> e.getEntityCase() == ACTION_PROFILE_MEMBER)
+ .map(Entity::getActionProfileMember)
+ .forEach(m -> {
+ actionProfileMemberMap.put(actProfGrp.getGroupId(), m);
+ memberCount.incrementAndGet();
+ });
+ });
+ });
+
+ if (!success.get()) {
+ // Can't read members
+ return Collections.emptySet();
+ }
+ log.info("Retrieved {} group members from action profile {} on {}...",
+ memberCount.get(), piActionProfileId.id(), deviceId);
+
+ Collection<PiActionGroup> piActionGroups = Sets.newHashSet();
+
+ for (ActionProfileGroup apg : actionProfileGroups) {
+ try {
+ Collection<ActionProfileMember> members = actionProfileMemberMap.get(apg.getGroupId());
+ PiActionGroup decodedGroup =
+ ActionProfileGroupEncoder.decode(apg, members, pipeconf);
+ piActionGroups.add(decodedGroup);
+ } catch (EncodeException | P4InfoBrowser.NotFoundException e) {
+ log.warn("Can't decode group {} due to {}", apg, e.getMessage());
+ return Collections.emptySet();
+ }
+ }
+
+ return piActionGroups;
+ }
+
+ private boolean doWriteActionGroup(PiActionGroup group, WriteOperationType opType, PiPipeconf pipeconf) {
+ WriteRequest.Builder writeRequestBuilder = WriteRequest.newBuilder();
+ ActionProfileGroup actionProfileGroup;
+ try {
+ actionProfileGroup = ActionProfileGroupEncoder.encode(group, pipeconf);
+ } catch (EncodeException | P4InfoBrowser.NotFoundException e) {
+ log.warn("Can't encode group {} due to {}", e.getMessage());
+ return false;
+ }
+ Update updateMessage = Update.newBuilder()
+ .setEntity(Entity.newBuilder()
+ .setActionProfileGroup(actionProfileGroup)
+ .build())
+ .setType(UPDATE_TYPES.get(opType))
+ .build();
+ writeRequestBuilder
+ .setDeviceId(p4DeviceId)
+ .addUpdates(updateMessage);
+ try {
+ blockingStub.write(writeRequestBuilder.build());
+ return true;
+ } catch (StatusRuntimeException e) {
+ log.warn("Unable to write table entries ({}): {}", opType, e.getMessage());
+ return false;
+ }
+ }
+
/**
* Returns the internal P4 device ID associated with this client.
*
diff --git a/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/P4RuntimeControllerImpl.java b/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/P4RuntimeControllerImpl.java
index e26341b..383b857 100644
--- a/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/P4RuntimeControllerImpl.java
+++ b/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/P4RuntimeControllerImpl.java
@@ -186,7 +186,7 @@
}
}
- void postEvent(P4RuntimeEvent event) {
+ public void postEvent(P4RuntimeEvent event) {
post(event);
}
}
diff --git a/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/P4RuntimeUtils.java b/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/P4RuntimeUtils.java
new file mode 100644
index 0000000..411e1fb
--- /dev/null
+++ b/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/P4RuntimeUtils.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2017-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.p4runtime.ctl;
+
+import com.google.protobuf.ByteString;
+
+import static java.lang.String.format;
+
+/**
+ * Utilities for P4 runtime control.
+ */
+public final class P4RuntimeUtils {
+
+ private P4RuntimeUtils() {
+ // Hide default construction
+ }
+
+ static void assertSize(String entityDescr, ByteString value, int bitWidth)
+ throws EncodeException {
+
+ int byteWidth = (int) Math.ceil((float) bitWidth / 8);
+ if (value.size() != byteWidth) {
+ throw new EncodeException(format("Wrong size for %s, expected %d bytes, but found %d",
+ entityDescr, byteWidth, value.size()));
+ }
+ }
+
+ static void assertPrefixLen(String entityDescr, int prefixLength, int bitWidth)
+ throws EncodeException {
+
+ if (prefixLength > bitWidth) {
+ throw new EncodeException(format(
+ "wrong prefix length for %s, field size is %d bits, but found one is %d",
+ entityDescr, bitWidth, prefixLength));
+ }
+ }
+}
diff --git a/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/TableEntryEncoder.java b/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/TableEntryEncoder.java
index 9ffc18f..8278b3e 100644
--- a/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/TableEntryEncoder.java
+++ b/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/TableEntryEncoder.java
@@ -17,10 +17,13 @@
package org.onosproject.p4runtime.ctl;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
import com.google.protobuf.ByteString;
import org.onlab.util.ImmutableByteSequence;
import org.onosproject.net.pi.model.PiPipeconf;
import org.onosproject.net.pi.runtime.PiAction;
+import org.onosproject.net.pi.runtime.PiActionGroupId;
+import org.onosproject.net.pi.runtime.PiActionGroupMemberId;
import org.onosproject.net.pi.runtime.PiActionId;
import org.onosproject.net.pi.runtime.PiActionParam;
import org.onosproject.net.pi.runtime.PiActionParamId;
@@ -36,25 +39,26 @@
import org.onosproject.net.pi.runtime.PiTernaryFieldMatch;
import org.onosproject.net.pi.runtime.PiValidFieldMatch;
import org.slf4j.Logger;
-import p4.P4RuntimeOuterClass.Action;
import p4.P4RuntimeOuterClass.FieldMatch;
import p4.P4RuntimeOuterClass.TableAction;
import p4.P4RuntimeOuterClass.TableEntry;
+import p4.P4RuntimeOuterClass.Action;
import p4.config.P4InfoOuterClass;
import java.util.Collection;
import java.util.Collections;
+import java.util.List;
import static java.lang.String.format;
import static org.onlab.util.ImmutableByteSequence.copyFrom;
+import static org.onosproject.p4runtime.ctl.P4RuntimeUtils.assertPrefixLen;
+import static org.onosproject.p4runtime.ctl.P4RuntimeUtils.assertSize;
import static org.slf4j.LoggerFactory.getLogger;
/**
- * Encoder of table entries, from ONOS Pi* format, to P4Runtime protobuf messages, and vice versa.
+ * Encoder/Decoder of table entries, from ONOS Pi* format, to P4Runtime protobuf messages, and vice versa.
*/
final class TableEntryEncoder {
-
-
private static final Logger log = getLogger(TableEntryEncoder.class);
private static final String HEADER_PREFIX = "hdr.";
@@ -422,7 +426,7 @@
}
}
- private static TableAction encodePiTableAction(PiTableAction piTableAction, P4InfoBrowser browser)
+ static TableAction encodePiTableAction(PiTableAction piTableAction, P4InfoBrowser browser)
throws P4InfoBrowser.NotFoundException, EncodeException {
TableAction.Builder tableActionMsgBuilder = TableAction.newBuilder();
@@ -430,24 +434,17 @@
switch (piTableAction.type()) {
case ACTION:
PiAction piAction = (PiAction) piTableAction;
- int actionId = browser.actions().getByName(piAction.id().name()).getPreamble().getId();
-
- Action.Builder actionMsgBuilder = Action.newBuilder().setActionId(actionId);
-
- for (PiActionParam p : piAction.parameters()) {
- P4InfoOuterClass.Action.Param paramInfo = browser.actionParams(actionId).getByName(p.id().name());
- ByteString paramValue = ByteString.copyFrom(p.value().asReadOnlyBuffer());
- assertSize(format("param '%s' of action '%s'", p.id(), piAction.id()),
- paramValue, paramInfo.getBitwidth());
- actionMsgBuilder.addParams(Action.Param.newBuilder()
- .setParamId(paramInfo.getId())
- .setValue(paramValue)
- .build());
- }
-
- tableActionMsgBuilder.setAction(actionMsgBuilder.build());
+ Action theAction = encodePiAction(piAction, browser);
+ tableActionMsgBuilder.setAction(theAction);
break;
-
+ case ACTION_GROUP_ID:
+ PiActionGroupId actionGroupId = (PiActionGroupId) piTableAction;
+ tableActionMsgBuilder.setActionProfileGroupId(actionGroupId.id());
+ break;
+ case GROUP_MEMBER_ID:
+ PiActionGroupMemberId actionGroupMemberId = (PiActionGroupMemberId) piTableAction;
+ tableActionMsgBuilder.setActionProfileMemberId(actionGroupMemberId.id());
+ break;
default:
throw new EncodeException(
format("Building of table action type %s not implemented", piTableAction.type()));
@@ -456,50 +453,56 @@
return tableActionMsgBuilder.build();
}
- private static PiTableAction decodeTableActionMsg(TableAction tableActionMsg, P4InfoBrowser browser)
+ static PiTableAction decodeTableActionMsg(TableAction tableActionMsg, P4InfoBrowser browser)
throws P4InfoBrowser.NotFoundException, EncodeException {
-
TableAction.TypeCase typeCase = tableActionMsg.getTypeCase();
-
switch (typeCase) {
case ACTION:
- PiAction.Builder piActionBuilder = PiAction.builder();
Action actionMsg = tableActionMsg.getAction();
- // Action ID.
- int actionId = actionMsg.getActionId();
- String actionName = browser.actions().getById(actionId).getPreamble().getName();
- piActionBuilder.withId(PiActionId.of(actionName));
- // Params.
- for (Action.Param paramMsg : actionMsg.getParamsList()) {
- String paramName = browser.actionParams(actionId).getById(paramMsg.getParamId()).getName();
- ImmutableByteSequence paramValue = copyFrom(paramMsg.getValue().asReadOnlyByteBuffer());
- piActionBuilder.withParameter(new PiActionParam(PiActionParamId.of(paramName), paramValue));
- }
- return piActionBuilder.build();
-
+ return decodeActionMsg(actionMsg, browser);
default:
throw new EncodeException(
format("Decoding of table action type %s not implemented", typeCase.name()));
}
}
- private static void assertSize(String entityDescr, ByteString value, int bitWidth)
- throws EncodeException {
+ static Action encodePiAction(PiAction piAction, P4InfoBrowser browser)
+ throws P4InfoBrowser.NotFoundException, EncodeException {
- int byteWidth = (int) Math.ceil((float) bitWidth / 8);
- if (value.size() != byteWidth) {
- throw new EncodeException(format("Wrong size for %s, expected %d bytes, but found %d",
- entityDescr, byteWidth, value.size()));
+ int actionId = browser.actions().getByName(piAction.id().name()).getPreamble().getId();
+
+ Action.Builder actionMsgBuilder =
+ Action.newBuilder().setActionId(actionId);
+
+ for (PiActionParam p : piAction.parameters()) {
+ P4InfoOuterClass.Action.Param paramInfo = browser.actionParams(actionId).getByName(p.id().name());
+ ByteString paramValue = ByteString.copyFrom(p.value().asReadOnlyBuffer());
+ assertSize(format("param '%s' of action '%s'", p.id(), piAction.id()),
+ paramValue, paramInfo.getBitwidth());
+ actionMsgBuilder.addParams(Action.Param.newBuilder()
+ .setParamId(paramInfo.getId())
+ .setValue(paramValue)
+ .build());
}
+
+ return actionMsgBuilder.build();
}
- private static void assertPrefixLen(String entityDescr, int prefixLength, int bitWidth)
- throws EncodeException {
+ static PiAction decodeActionMsg(Action action, P4InfoBrowser browser)
+ throws P4InfoBrowser.NotFoundException {
+ P4InfoBrowser.EntityBrowser<P4InfoOuterClass.Action.Param> paramInfo =
+ browser.actionParams(action.getActionId());
+ String actionName = browser.actions()
+ .getById(action.getActionId())
+ .getPreamble().getName();
+ PiActionId id = PiActionId.of(actionName);
+ List<PiActionParam> params = Lists.newArrayList();
- if (prefixLength > bitWidth) {
- throw new EncodeException(format(
- "wrong prefix length for %s, field size is %d bits, but found one is %d",
- entityDescr, bitWidth, prefixLength));
+ for (Action.Param p : action.getParamsList()) {
+ String paramName = paramInfo.getById(p.getParamId()).getName();
+ ImmutableByteSequence value = ImmutableByteSequence.copyFrom(p.getValue().toByteArray());
+ params.add(new PiActionParam(PiActionParamId.of(paramName), value));
}
+ return PiAction.builder().withId(id).withParameters(params).build();
}
}
diff --git a/protocols/p4runtime/ctl/src/test/java/org/onosproject/p4runtime/ctl/MockP4RuntimeServer.java b/protocols/p4runtime/ctl/src/test/java/org/onosproject/p4runtime/ctl/MockP4RuntimeServer.java
new file mode 100644
index 0000000..4773458
--- /dev/null
+++ b/protocols/p4runtime/ctl/src/test/java/org/onosproject/p4runtime/ctl/MockP4RuntimeServer.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2017-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.p4runtime.ctl;
+
+import com.google.common.collect.Lists;
+import io.grpc.stub.StreamObserver;
+import p4.P4RuntimeGrpc;
+import p4.P4RuntimeOuterClass;
+import p4.P4RuntimeOuterClass.GetForwardingPipelineConfigRequest;
+import p4.P4RuntimeOuterClass.GetForwardingPipelineConfigResponse;
+import p4.P4RuntimeOuterClass.ReadRequest;
+import p4.P4RuntimeOuterClass.ReadResponse;
+import p4.P4RuntimeOuterClass.SetForwardingPipelineConfigRequest;
+import p4.P4RuntimeOuterClass.SetForwardingPipelineConfigResponse;
+import p4.P4RuntimeOuterClass.StreamMessageResponse;
+import p4.P4RuntimeOuterClass.WriteRequest;
+import p4.P4RuntimeOuterClass.WriteResponse;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.atomic.AtomicLong;
+
+public class MockP4RuntimeServer extends P4RuntimeGrpc.P4RuntimeImplBase {
+ private CompletableFuture<Void> completeLock;
+ private AtomicLong counter;
+
+ // Requests
+ private List<WriteRequest> writeReqs;
+ private List<ReadRequest> readReqs;
+ private List<ReadResponse> readResps;
+
+ /**
+ * Expect N times request sent by client.
+ *
+ * @param times the number of request will sent by client.
+ * @return a completable future object, wll complete after client send N times requests.
+ */
+ public CompletableFuture<Void> expectRequests(long times) {
+ counter = new AtomicLong(times);
+ completeLock = new CompletableFuture<>();
+ readReqs = Lists.newArrayList();
+ writeReqs = Lists.newArrayList();
+ return completeLock;
+ }
+
+ private void complete() {
+ if (counter.decrementAndGet() == 0) {
+ completeLock.complete(null);
+ }
+ }
+
+ public void willReturnReadResult(Collection<ReadResponse> readResps) {
+ this.readResps = Lists.newArrayList(readResps);
+ }
+
+ public List<WriteRequest> getWriteReqs() {
+ return writeReqs;
+ }
+
+ public List<ReadRequest> getReadReqs() {
+ return readReqs;
+ }
+
+ @Override
+ public void write(WriteRequest request, StreamObserver<WriteResponse> responseObserver) {
+ writeReqs.add(request);
+ complete();
+ }
+
+ @Override
+ public void read(ReadRequest request, StreamObserver<ReadResponse> responseObserver) {
+ readReqs.add(request);
+ if (readResps != null && !readResps.isEmpty()) {
+ ReadResponse readResp = readResps.remove(0); // get first response
+ responseObserver.onNext(readResp);
+ responseObserver.onCompleted();
+ }
+ complete();
+ }
+
+ @Override
+ public void setForwardingPipelineConfig(SetForwardingPipelineConfigRequest request,
+ StreamObserver<SetForwardingPipelineConfigResponse> responseObserver) {
+ throw new UnsupportedOperationException("Not implement yet");
+ }
+
+ @Override
+ public void getForwardingPipelineConfig(GetForwardingPipelineConfigRequest request,
+ StreamObserver<GetForwardingPipelineConfigResponse> responseObserver) {
+ throw new UnsupportedOperationException("Not implement yet");
+ }
+
+ @Override
+ public StreamObserver<P4RuntimeOuterClass.StreamMessageRequest>
+ streamChannel(StreamObserver<StreamMessageResponse> responseObserver) {
+ // TODO: not implement yet
+ return null;
+ }
+}
diff --git a/protocols/p4runtime/ctl/src/test/java/org/onosproject/p4runtime/ctl/P4RuntimeGroupTest.java b/protocols/p4runtime/ctl/src/test/java/org/onosproject/p4runtime/ctl/P4RuntimeGroupTest.java
new file mode 100644
index 0000000..8932a16
--- /dev/null
+++ b/protocols/p4runtime/ctl/src/test/java/org/onosproject/p4runtime/ctl/P4RuntimeGroupTest.java
@@ -0,0 +1,279 @@
+/*
+ * Copyright 2017-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.p4runtime.ctl;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.protobuf.ByteString;
+import io.grpc.ManagedChannel;
+import io.grpc.Server;
+import io.grpc.inprocess.InProcessChannelBuilder;
+import io.grpc.inprocess.InProcessServerBuilder;
+import io.grpc.internal.AbstractServerImplBuilder;
+import org.easymock.EasyMock;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.onlab.util.ImmutableByteSequence;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.pi.model.DefaultPiPipeconf;
+import org.onosproject.net.pi.model.PiPipeconf;
+import org.onosproject.net.pi.model.PiPipeconfId;
+import org.onosproject.net.pi.model.PiPipelineModel;
+import org.onosproject.net.pi.runtime.PiActionProfileId;
+import org.onosproject.net.pi.runtime.PiAction;
+import org.onosproject.net.pi.runtime.PiActionGroup;
+import org.onosproject.net.pi.runtime.PiActionGroupId;
+import org.onosproject.net.pi.runtime.PiActionGroupMember;
+import org.onosproject.net.pi.runtime.PiActionGroupMemberId;
+import org.onosproject.net.pi.runtime.PiActionId;
+import org.onosproject.net.pi.runtime.PiActionParam;
+import org.onosproject.net.pi.runtime.PiActionParamId;
+import p4.P4RuntimeOuterClass.ActionProfileGroup;
+import p4.P4RuntimeOuterClass.ActionProfileMember;
+import p4.P4RuntimeOuterClass.Entity;
+import p4.P4RuntimeOuterClass.Update;
+import p4.P4RuntimeOuterClass.WriteRequest;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.onosproject.net.pi.model.PiPipeconf.ExtensionType.P4_INFO_TEXT;
+import static org.onosproject.net.pi.runtime.PiActionGroup.Type.SELECT;
+import static org.onosproject.p4runtime.api.P4RuntimeClient.WriteOperationType.INSERT;
+import static p4.P4RuntimeOuterClass.*;
+
+/**
+ * Tests for P4 Runtime Action Profile Group support.
+ */
+public class P4RuntimeGroupTest {
+ private static final String PIPECONF_ID = "p4runtime-mock-pipeconf";
+ private static final String P4INFO_PATH = "/default.p4info";
+ private static final PiPipeconf PIPECONF = buildPipeconf();
+ private static final int P4_INFO_ACT_PROF_ID = 285227860;
+ private static final PiActionProfileId ACT_PROF_ID = PiActionProfileId.of("ecmp_selector");
+ private static final PiActionGroupId GROUP_ID = PiActionGroupId.of(1);
+ private static final int DEFAULT_MEMBER_WEIGHT = 1;
+ private static final PiActionId EGRESS_PORT_ACTION_ID = PiActionId.of("set_egress_port");
+ private static final PiActionParamId PORT_PARAM_ID = PiActionParamId.of("port");
+ private static final int BASE_MEM_ID = 65535;
+ private static final List<Integer> MEMBER_IDS = ImmutableList.of(65536, 65537, 65538);
+ private static final Collection<PiActionGroupMember> GROUP_MEMBERS =
+ ImmutableSet.of(
+ outputMember((short) 1),
+ outputMember((short) 2),
+ outputMember((short) 3)
+ );
+ private static final PiActionGroup GROUP = PiActionGroup.builder()
+ .withId(GROUP_ID)
+ .addMembers(GROUP_MEMBERS)
+ .withActionProfileId(ACT_PROF_ID)
+ .withType(SELECT)
+ .build();
+ private static final DeviceId DEVICE_ID = DeviceId.deviceId("device:p4runtime:1");
+ private static final int P4_DEVICE_ID = 1;
+ private static final int SET_EGRESS_PORT_ID = 16794308;
+ private static final String GRPC_SERVER_NAME = "P4RuntimeGroupTest";
+ private static final long DEFAULT_TIMEOUT_TIME = 5;
+
+ private P4RuntimeClientImpl client;
+ private P4RuntimeControllerImpl controller;
+ private static MockP4RuntimeServer p4RuntimeServerImpl = new MockP4RuntimeServer();
+ private static Server grpcServer;
+ private static ManagedChannel grpcChannel;
+
+ private static PiActionGroupMember outputMember(short portNum) {
+ PiActionParam param = new PiActionParam(PORT_PARAM_ID,
+ ImmutableByteSequence.copyFrom(portNum));
+ PiAction piAction = PiAction.builder()
+ .withId(EGRESS_PORT_ACTION_ID)
+ .withParameter(param).build();
+
+ return PiActionGroupMember.builder()
+ .withAction(piAction)
+ .withId(PiActionGroupMemberId.of(BASE_MEM_ID + portNum))
+ .withWeight(DEFAULT_MEMBER_WEIGHT)
+ .build();
+ }
+
+ private static PiPipeconf buildPipeconf() {
+ final URL p4InfoUrl = P4RuntimeGroupTest.class.getResource(P4INFO_PATH);
+ return DefaultPiPipeconf.builder()
+ .withId(new PiPipeconfId(PIPECONF_ID))
+ .withPipelineModel(EasyMock.niceMock(PiPipelineModel.class))
+ .addExtension(P4_INFO_TEXT, p4InfoUrl)
+ .build();
+ }
+
+ @BeforeClass
+ public static void globalSetup() throws IOException {
+ AbstractServerImplBuilder builder = InProcessServerBuilder
+ .forName(GRPC_SERVER_NAME).directExecutor();
+ builder.addService(p4RuntimeServerImpl);
+ grpcServer = builder.build().start();
+ grpcChannel = InProcessChannelBuilder.forName(GRPC_SERVER_NAME)
+ .directExecutor()
+ .usePlaintext(true)
+ .build();
+ }
+
+ @AfterClass
+ public static void globalTeerDown() {
+ grpcServer.shutdown();
+ grpcChannel.shutdown();
+ }
+
+
+ @Before
+ public void setup() {
+ controller = niceMock(P4RuntimeControllerImpl.class);
+ client = new P4RuntimeClientImpl(DEVICE_ID, P4_DEVICE_ID,
+ grpcChannel,
+ controller);
+ }
+
+ @Test
+ public void testInsertPiActionGroup() throws Exception {
+ CompletableFuture<Void> complete = p4RuntimeServerImpl.expectRequests(1);
+ client.writeActionGroup(GROUP, INSERT, PIPECONF);
+ complete.get(DEFAULT_TIMEOUT_TIME, TimeUnit.SECONDS);
+ WriteRequest result = p4RuntimeServerImpl.getWriteReqs().get(0);
+ assertEquals(1, result.getDeviceId());
+ assertEquals(1, result.getUpdatesCount());
+
+ Update update = result.getUpdatesList().get(0);
+ assertEquals(Update.Type.INSERT, update.getType());
+
+ Entity entity = update.getEntity();
+ ActionProfileGroup actionProfileGroup = entity.getActionProfileGroup();
+ assertNotNull(actionProfileGroup);
+
+ assertEquals(P4_INFO_ACT_PROF_ID, actionProfileGroup.getActionProfileId());
+ assertEquals(3, actionProfileGroup.getMembersCount());
+ List<ActionProfileGroup.Member> members = actionProfileGroup.getMembersList();
+
+ for (ActionProfileGroup.Member member : members) {
+ // XXX: We can't guarantee the order of member, just make sure we
+ // have these member ids
+ assertTrue(MEMBER_IDS.contains(member.getMemberId()));
+ assertEquals(DEFAULT_MEMBER_WEIGHT, member.getWeight());
+ }
+ }
+
+ @Test
+ public void testInsertPiActionMembers() throws Exception {
+ CompletableFuture<Void> complete = p4RuntimeServerImpl.expectRequests(1);
+ client.writeActionGroupMembers(GROUP, GROUP_MEMBERS, INSERT, PIPECONF);
+ complete.get(DEFAULT_TIMEOUT_TIME, TimeUnit.SECONDS);
+ WriteRequest result = p4RuntimeServerImpl.getWriteReqs().get(0);
+ assertEquals(1, result.getDeviceId());
+ assertEquals(3, result.getUpdatesCount());
+
+ List<Update> updates = result.getUpdatesList();
+ for (Update update : updates) {
+ assertEquals(Update.Type.INSERT, update.getType());
+ Entity entity = update.getEntity();
+ ActionProfileMember member = entity.getActionProfileMember();
+ assertNotNull(member);
+ assertEquals(P4_INFO_ACT_PROF_ID, member.getActionProfileId());
+ assertTrue(MEMBER_IDS.contains(member.getMemberId()));
+ Action action = member.getAction();
+ assertEquals(SET_EGRESS_PORT_ID, action.getActionId());
+ assertEquals(1, action.getParamsCount());
+ Action.Param param = action.getParamsList().get(0);
+ assertEquals(1, param.getParamId());
+ byte outPort = (byte) (member.getMemberId() - BASE_MEM_ID);
+ ByteString bs = ByteString.copyFrom(new byte[]{0, outPort});
+ assertEquals(bs, param.getValue());
+ }
+ }
+
+ @Test
+ public void testReadGroups() throws Exception {
+ ActionProfileGroup.Builder group = ActionProfileGroup.newBuilder()
+ .setGroupId(GROUP_ID.id())
+ .setType(ActionProfileGroup.Type.SELECT)
+ .setActionProfileId(P4_INFO_ACT_PROF_ID);
+
+ List<ActionProfileMember> members = Lists.newArrayList();
+
+ MEMBER_IDS.forEach(id -> {
+ ActionProfileGroup.Member member = ActionProfileGroup.Member.newBuilder()
+ .setMemberId(id)
+ .setWeight(DEFAULT_MEMBER_WEIGHT)
+ .build();
+ group.addMembers(member);
+
+ byte outPort = (byte) (id - BASE_MEM_ID);
+ ByteString bs = ByteString.copyFrom(new byte[]{0, outPort});
+ Action.Param param = Action.Param.newBuilder()
+ .setParamId(1)
+ .setValue(bs)
+ .build();
+
+ Action action = Action.newBuilder()
+ .setActionId(SET_EGRESS_PORT_ID)
+ .addParams(param)
+ .build();
+
+
+ ActionProfileMember actProfMember =
+ ActionProfileMember.newBuilder()
+ .setMemberId(id)
+ .setAction(action)
+ .build();
+ members.add(actProfMember);
+ });
+
+ List<ReadResponse> responses = Lists.newArrayList();
+ responses.add(ReadResponse.newBuilder()
+ .addEntities(Entity.newBuilder().setActionProfileGroup(group))
+ .build()
+ );
+
+ members.forEach(m -> {
+ responses.add(ReadResponse.newBuilder()
+ .addEntities(Entity.newBuilder().setActionProfileMember(m))
+ .build());
+ });
+
+ p4RuntimeServerImpl.willReturnReadResult(responses);
+ CompletableFuture<Void> complete = p4RuntimeServerImpl.expectRequests(4);
+ CompletableFuture<Collection<PiActionGroup>> groupsComplete = client.dumpGroups(ACT_PROF_ID, PIPECONF);
+ complete.get(DEFAULT_TIMEOUT_TIME, TimeUnit.SECONDS);
+
+ Collection<PiActionGroup> groups = groupsComplete.get(DEFAULT_TIMEOUT_TIME, TimeUnit.SECONDS);
+ assertEquals(1, groups.size());
+ PiActionGroup piActionGroup = groups.iterator().next();
+ assertEquals(ACT_PROF_ID, piActionGroup.actionProfileId());
+ assertEquals(GROUP_ID, piActionGroup.id());
+ assertEquals(SELECT, piActionGroup.type());
+ assertEquals(3, piActionGroup.members().size());
+ assertTrue(GROUP_MEMBERS.containsAll(piActionGroup.members()));
+ assertTrue(piActionGroup.members().containsAll(GROUP_MEMBERS));
+ }
+}
diff --git a/protocols/p4runtime/ctl/src/test/java/org/onosproject/p4runtime/ctl/TableEntryEncoderTest.java b/protocols/p4runtime/ctl/src/test/java/org/onosproject/p4runtime/ctl/TableEntryEncoderTest.java
index 792e838..b3e9a1e 100644
--- a/protocols/p4runtime/ctl/src/test/java/org/onosproject/p4runtime/ctl/TableEntryEncoderTest.java
+++ b/protocols/p4runtime/ctl/src/test/java/org/onosproject/p4runtime/ctl/TableEntryEncoderTest.java
@@ -18,12 +18,13 @@
import com.google.common.collect.Lists;
import com.google.common.testing.EqualsTester;
+import org.easymock.EasyMock;
import org.junit.Test;
import org.onlab.util.ImmutableByteSequence;
-import org.onosproject.bmv2.model.Bmv2PipelineModelParser;
import org.onosproject.net.pi.model.DefaultPiPipeconf;
import org.onosproject.net.pi.model.PiPipeconf;
import org.onosproject.net.pi.model.PiPipeconfId;
+import org.onosproject.net.pi.model.PiPipelineModel;
import org.onosproject.net.pi.runtime.PiAction;
import org.onosproject.net.pi.runtime.PiActionId;
import org.onosproject.net.pi.runtime.PiActionParam;
@@ -33,7 +34,6 @@
import org.onosproject.net.pi.runtime.PiTableEntry;
import org.onosproject.net.pi.runtime.PiTableId;
import org.onosproject.net.pi.runtime.PiTernaryFieldMatch;
-import org.slf4j.Logger;
import p4.P4RuntimeOuterClass.Action;
import p4.P4RuntimeOuterClass.TableEntry;
@@ -47,19 +47,14 @@
import static org.onlab.util.ImmutableByteSequence.copyFrom;
import static org.onlab.util.ImmutableByteSequence.fit;
import static org.onlab.util.ImmutableByteSequence.ofOnes;
-import static org.onosproject.net.pi.model.PiPipeconf.ExtensionType.BMV2_JSON;
import static org.onosproject.net.pi.model.PiPipeconf.ExtensionType.P4_INFO_TEXT;
import static org.onosproject.p4runtime.ctl.TableEntryEncoder.decode;
import static org.onosproject.p4runtime.ctl.TableEntryEncoder.encode;
-import static org.slf4j.LoggerFactory.getLogger;
-//import org.onosproject.driver.pipeline.DefaultSingleTablePipeline;
-//import org.onosproject.drivers.bmv2.Bmv2DefaultInterpreter;
-
+/**
+ * Test for P4 runtime table entry encoder.
+ */
public class TableEntryEncoderTest {
-
- private final Logger log = getLogger(getClass());
-
private static final String TABLE_0 = "table0";
private static final String SET_EGRESS_PORT = "set_egress_port";
private static final String PORT = "port";
@@ -72,14 +67,11 @@
private final Random rand = new Random();
private final URL p4InfoUrl = this.getClass().getResource("/default.p4info");
- private final URL jsonUrl = this.getClass().getResource("/default.json");
private final PiPipeconf defaultPipeconf = DefaultPiPipeconf.builder()
.withId(new PiPipeconfId("mock"))
- .withPipelineModel(Bmv2PipelineModelParser.parse(jsonUrl))
-// .addBehaviour(PiPipelineInterpreter.class, Bmv2DefaultInterpreter.class)
+ .withPipelineModel(EasyMock.niceMock(PiPipelineModel.class))
.addExtension(P4_INFO_TEXT, p4InfoUrl)
- .addExtension(BMV2_JSON, jsonUrl)
.build();
private final P4InfoBrowser browser = PipeconfHelper.getP4InfoBrowser(defaultPipeconf);
diff --git a/protocols/p4runtime/ctl/src/test/resources/default.json b/protocols/p4runtime/ctl/src/test/resources/default.json
deleted file mode 100644
index 3a46dcc..0000000
--- a/protocols/p4runtime/ctl/src/test/resources/default.json
+++ /dev/null
@@ -1,2697 +0,0 @@
-{
- "program" : "default.p4",
- "__meta__" : {
- "version" : [2, 7],
- "compiler" : "https://github.com/p4lang/p4c"
- },
- "header_types" : [
- {
- "name" : "scalars_0",
- "id" : 0,
- "fields" : [
- ["tmp", 32, false],
- ["tmp_0", 32, false]
- ]
- },
- {
- "name" : "standard_metadata",
- "id" : 1,
- "fields" : [
- ["ingress_port", 9, false],
- ["egress_spec", 9, false],
- ["egress_port", 9, false],
- ["clone_spec", 32, false],
- ["instance_type", 32, false],
- ["drop", 1, false],
- ["recirculate_port", 16, false],
- ["packet_length", 32, false],
- ["enq_timestamp", 32, false],
- ["enq_qdepth", 19, false],
- ["deq_timedelta", 32, false],
- ["deq_qdepth", 19, false],
- ["ingress_global_timestamp", 48, false],
- ["lf_field_list", 32, false],
- ["mcast_grp", 16, false],
- ["resubmit_flag", 1, false],
- ["egress_rid", 16, false],
- ["_padding", 5, false]
- ]
- },
- {
- "name" : "ethernet_t",
- "id" : 2,
- "fields" : [
- ["dstAddr", 48, false],
- ["srcAddr", 48, false],
- ["etherType", 16, false]
- ]
- },
- {
- "name" : "ipv4_t",
- "id" : 3,
- "fields" : [
- ["version", 4, false],
- ["ihl", 4, false],
- ["diffserv", 8, false],
- ["totalLen", 16, false],
- ["identification", 16, false],
- ["flags", 3, false],
- ["fragOffset", 13, false],
- ["ttl", 8, false],
- ["protocol", 8, false],
- ["hdrChecksum", 16, false],
- ["srcAddr", 32, false],
- ["dstAddr", 32, false]
- ]
- },
- {
- "name" : "tcp_t",
- "id" : 4,
- "fields" : [
- ["srcPort", 16, false],
- ["dstPort", 16, false],
- ["seqNo", 32, false],
- ["ackNo", 32, false],
- ["dataOffset", 4, false],
- ["res", 3, false],
- ["ecn", 3, false],
- ["ctrl", 6, false],
- ["window", 16, false],
- ["checksum", 16, false],
- ["urgentPtr", 16, false]
- ]
- },
- {
- "name" : "udp_t",
- "id" : 5,
- "fields" : [
- ["srcPort", 16, false],
- ["dstPort", 16, false],
- ["length_", 16, false],
- ["checksum", 16, false]
- ]
- },
- {
- "name" : "ecmp_metadata_t",
- "id" : 6,
- "fields" : [
- ["groupId", 16, false],
- ["selector", 16, false]
- ]
- },
- {
- "name" : "wcmp_meta_t",
- "id" : 7,
- "fields" : [
- ["groupId", 16, false],
- ["numBits", 8, false],
- ["selector", 64, false]
- ]
- },
- {
- "name" : "intrinsic_metadata_t",
- "id" : 8,
- "fields" : [
- ["ingress_global_timestamp", 32, false],
- ["lf_field_list", 32, false],
- ["mcast_grp", 16, false],
- ["egress_rid", 16, false]
- ]
- }
- ],
- "headers" : [
- {
- "name" : "standard_metadata_3",
- "id" : 0,
- "header_type" : "standard_metadata",
- "metadata" : true,
- "pi_omit" : true
- },
- {
- "name" : "standard_metadata_4",
- "id" : 1,
- "header_type" : "standard_metadata",
- "metadata" : true,
- "pi_omit" : true
- },
- {
- "name" : "standard_metadata_5",
- "id" : 2,
- "header_type" : "standard_metadata",
- "metadata" : true,
- "pi_omit" : true
- },
- {
- "name" : "scalars",
- "id" : 3,
- "header_type" : "scalars_0",
- "metadata" : true,
- "pi_omit" : true
- },
- {
- "name" : "standard_metadata",
- "id" : 4,
- "header_type" : "standard_metadata",
- "metadata" : true,
- "pi_omit" : true
- },
- {
- "name" : "ethernet",
- "id" : 5,
- "header_type" : "ethernet_t",
- "metadata" : false,
- "pi_omit" : true
- },
- {
- "name" : "ipv4",
- "id" : 6,
- "header_type" : "ipv4_t",
- "metadata" : false,
- "pi_omit" : true
- },
- {
- "name" : "tcp",
- "id" : 7,
- "header_type" : "tcp_t",
- "metadata" : false,
- "pi_omit" : true
- },
- {
- "name" : "udp",
- "id" : 8,
- "header_type" : "udp_t",
- "metadata" : false,
- "pi_omit" : true
- },
- {
- "name" : "ecmp_metadata",
- "id" : 9,
- "header_type" : "ecmp_metadata_t",
- "metadata" : true,
- "pi_omit" : true
- },
- {
- "name" : "wcmp_meta",
- "id" : 10,
- "header_type" : "wcmp_meta_t",
- "metadata" : true,
- "pi_omit" : true
- },
- {
- "name" : "intrinsic_metadata",
- "id" : 11,
- "header_type" : "intrinsic_metadata_t",
- "metadata" : true,
- "pi_omit" : true
- }
- ],
- "header_stacks" : [],
- "header_union_types" : [],
- "header_unions" : [],
- "header_union_stacks" : [],
- "field_lists" : [],
- "errors" : [
- ["NoError", 1],
- ["PacketTooShort", 2],
- ["NoMatch", 3],
- ["StackOutOfBounds", 4],
- ["HeaderTooShort", 5],
- ["ParserTimeout", 6]
- ],
- "enums" : [],
- "parsers" : [
- {
- "name" : "parser",
- "id" : 0,
- "init_state" : "start",
- "parse_states" : [
- {
- "name" : "parse_ipv4",
- "id" : 0,
- "parser_ops" : [
- {
- "parameters" : [
- {
- "type" : "regular",
- "value" : "ipv4"
- }
- ],
- "op" : "extract"
- }
- ],
- "transitions" : [
- {
- "value" : "0x06",
- "mask" : null,
- "next_state" : "parse_tcp"
- },
- {
- "value" : "0x11",
- "mask" : null,
- "next_state" : "parse_udp"
- },
- {
- "value" : "default",
- "mask" : null,
- "next_state" : null
- }
- ],
- "transition_key" : [
- {
- "type" : "field",
- "value" : ["ipv4", "protocol"]
- }
- ]
- },
- {
- "name" : "parse_tcp",
- "id" : 1,
- "parser_ops" : [
- {
- "parameters" : [
- {
- "type" : "regular",
- "value" : "tcp"
- }
- ],
- "op" : "extract"
- }
- ],
- "transitions" : [
- {
- "value" : "default",
- "mask" : null,
- "next_state" : null
- }
- ],
- "transition_key" : []
- },
- {
- "name" : "parse_udp",
- "id" : 2,
- "parser_ops" : [
- {
- "parameters" : [
- {
- "type" : "regular",
- "value" : "udp"
- }
- ],
- "op" : "extract"
- }
- ],
- "transitions" : [
- {
- "value" : "default",
- "mask" : null,
- "next_state" : null
- }
- ],
- "transition_key" : []
- },
- {
- "name" : "start",
- "id" : 3,
- "parser_ops" : [
- {
- "parameters" : [
- {
- "type" : "regular",
- "value" : "ethernet"
- }
- ],
- "op" : "extract"
- }
- ],
- "transitions" : [
- {
- "value" : "0x0800",
- "mask" : null,
- "next_state" : "parse_ipv4"
- },
- {
- "value" : "default",
- "mask" : null,
- "next_state" : null
- }
- ],
- "transition_key" : [
- {
- "type" : "field",
- "value" : ["ethernet", "etherType"]
- }
- ]
- }
- ]
- }
- ],
- "deparsers" : [
- {
- "name" : "deparser",
- "id" : 0,
- "source_info" : {
- "filename" : "include/parsers.p4",
- "line" : 43,
- "column" : 8,
- "source_fragment" : "DeparserImpl"
- },
- "order" : ["ethernet", "ipv4", "udp", "tcp"]
- }
- ],
- "meter_arrays" : [],
- "counter_arrays" : [
- {
- "name" : "table0_counter",
- "id" : 0,
- "is_direct" : true,
- "binding" : "table0"
- },
- {
- "name" : "port_counters_control.egress_port_counter",
- "id" : 1,
- "source_info" : {
- "filename" : "include/port_counters.p4",
- "line" : 6,
- "column" : 38,
- "source_fragment" : "egress_port_counter"
- },
- "size" : 254,
- "is_direct" : false
- },
- {
- "name" : "port_counters_control.ingress_port_counter",
- "id" : 2,
- "source_info" : {
- "filename" : "include/port_counters.p4",
- "line" : 7,
- "column" : 38,
- "source_fragment" : "ingress_port_counter"
- },
- "size" : 254,
- "is_direct" : false
- }
- ],
- "register_arrays" : [],
- "calculations" : [],
- "learn_lists" : [],
- "actions" : [
- {
- "name" : "set_egress_port",
- "id" : 0,
- "runtime_data" : [
- {
- "name" : "port",
- "bitwidth" : 9
- }
- ],
- "primitives" : [
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_3", "ingress_port"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "ingress_port"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 8,
- "column" : 49,
- "source_fragment" : "standard_metadata, Port port) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_3", "egress_spec"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "egress_spec"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 8,
- "column" : 49,
- "source_fragment" : "standard_metadata, Port port) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_3", "egress_port"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "egress_port"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 8,
- "column" : 49,
- "source_fragment" : "standard_metadata, Port port) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_3", "clone_spec"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "clone_spec"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 8,
- "column" : 49,
- "source_fragment" : "standard_metadata, Port port) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_3", "instance_type"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "instance_type"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 8,
- "column" : 49,
- "source_fragment" : "standard_metadata, Port port) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_3", "drop"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "drop"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 8,
- "column" : 49,
- "source_fragment" : "standard_metadata, Port port) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_3", "recirculate_port"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "recirculate_port"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 8,
- "column" : 49,
- "source_fragment" : "standard_metadata, Port port) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_3", "packet_length"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "packet_length"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 8,
- "column" : 49,
- "source_fragment" : "standard_metadata, Port port) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_3", "enq_timestamp"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "enq_timestamp"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 8,
- "column" : 49,
- "source_fragment" : "standard_metadata, Port port) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_3", "enq_qdepth"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "enq_qdepth"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 8,
- "column" : 49,
- "source_fragment" : "standard_metadata, Port port) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_3", "deq_timedelta"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "deq_timedelta"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 8,
- "column" : 49,
- "source_fragment" : "standard_metadata, Port port) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_3", "deq_qdepth"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "deq_qdepth"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 8,
- "column" : 49,
- "source_fragment" : "standard_metadata, Port port) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_3", "ingress_global_timestamp"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "ingress_global_timestamp"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 8,
- "column" : 49,
- "source_fragment" : "standard_metadata, Port port) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_3", "lf_field_list"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "lf_field_list"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 8,
- "column" : 49,
- "source_fragment" : "standard_metadata, Port port) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_3", "mcast_grp"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "mcast_grp"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 8,
- "column" : 49,
- "source_fragment" : "standard_metadata, Port port) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_3", "resubmit_flag"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "resubmit_flag"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 8,
- "column" : 49,
- "source_fragment" : "standard_metadata, Port port) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_3", "egress_rid"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "egress_rid"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 8,
- "column" : 49,
- "source_fragment" : "standard_metadata, Port port) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_3", "egress_spec"]
- },
- {
- "type" : "runtime_data",
- "value" : 0
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 9,
- "column" : 4,
- "source_fragment" : "standard_metadata.egress_spec = port"
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "ingress_port"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_3", "ingress_port"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 8,
- "column" : 49,
- "source_fragment" : "standard_metadata, Port port) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "egress_spec"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_3", "egress_spec"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 8,
- "column" : 49,
- "source_fragment" : "standard_metadata, Port port) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "egress_port"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_3", "egress_port"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 8,
- "column" : 49,
- "source_fragment" : "standard_metadata, Port port) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "clone_spec"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_3", "clone_spec"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 8,
- "column" : 49,
- "source_fragment" : "standard_metadata, Port port) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "instance_type"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_3", "instance_type"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 8,
- "column" : 49,
- "source_fragment" : "standard_metadata, Port port) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "drop"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_3", "drop"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 8,
- "column" : 49,
- "source_fragment" : "standard_metadata, Port port) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "recirculate_port"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_3", "recirculate_port"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 8,
- "column" : 49,
- "source_fragment" : "standard_metadata, Port port) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "packet_length"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_3", "packet_length"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 8,
- "column" : 49,
- "source_fragment" : "standard_metadata, Port port) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "enq_timestamp"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_3", "enq_timestamp"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 8,
- "column" : 49,
- "source_fragment" : "standard_metadata, Port port) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "enq_qdepth"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_3", "enq_qdepth"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 8,
- "column" : 49,
- "source_fragment" : "standard_metadata, Port port) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "deq_timedelta"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_3", "deq_timedelta"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 8,
- "column" : 49,
- "source_fragment" : "standard_metadata, Port port) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "deq_qdepth"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_3", "deq_qdepth"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 8,
- "column" : 49,
- "source_fragment" : "standard_metadata, Port port) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "ingress_global_timestamp"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_3", "ingress_global_timestamp"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 8,
- "column" : 49,
- "source_fragment" : "standard_metadata, Port port) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "lf_field_list"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_3", "lf_field_list"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 8,
- "column" : 49,
- "source_fragment" : "standard_metadata, Port port) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "mcast_grp"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_3", "mcast_grp"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 8,
- "column" : 49,
- "source_fragment" : "standard_metadata, Port port) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "resubmit_flag"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_3", "resubmit_flag"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 8,
- "column" : 49,
- "source_fragment" : "standard_metadata, Port port) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "egress_rid"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_3", "egress_rid"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 8,
- "column" : 49,
- "source_fragment" : "standard_metadata, Port port) { ..."
- }
- }
- ]
- },
- {
- "name" : "send_to_cpu",
- "id" : 1,
- "runtime_data" : [],
- "primitives" : [
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_4", "ingress_port"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "ingress_port"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 4,
- "column" : 45,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_4", "egress_spec"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "egress_spec"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 4,
- "column" : 45,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_4", "egress_port"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "egress_port"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 4,
- "column" : 45,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_4", "clone_spec"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "clone_spec"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 4,
- "column" : 45,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_4", "instance_type"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "instance_type"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 4,
- "column" : 45,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_4", "drop"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "drop"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 4,
- "column" : 45,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_4", "recirculate_port"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "recirculate_port"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 4,
- "column" : 45,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_4", "packet_length"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "packet_length"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 4,
- "column" : 45,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_4", "enq_timestamp"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "enq_timestamp"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 4,
- "column" : 45,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_4", "enq_qdepth"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "enq_qdepth"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 4,
- "column" : 45,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_4", "deq_timedelta"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "deq_timedelta"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 4,
- "column" : 45,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_4", "deq_qdepth"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "deq_qdepth"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 4,
- "column" : 45,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_4", "ingress_global_timestamp"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "ingress_global_timestamp"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 4,
- "column" : 45,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_4", "lf_field_list"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "lf_field_list"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 4,
- "column" : 45,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_4", "mcast_grp"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "mcast_grp"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 4,
- "column" : 45,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_4", "resubmit_flag"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "resubmit_flag"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 4,
- "column" : 45,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_4", "egress_rid"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "egress_rid"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 4,
- "column" : 45,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_4", "egress_spec"]
- },
- {
- "type" : "hexstr",
- "value" : "0x00ff"
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 5,
- "column" : 4,
- "source_fragment" : "standard_metadata.egress_spec = 9w255"
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "ingress_port"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_4", "ingress_port"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 4,
- "column" : 45,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "egress_spec"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_4", "egress_spec"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 4,
- "column" : 45,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "egress_port"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_4", "egress_port"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 4,
- "column" : 45,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "clone_spec"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_4", "clone_spec"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 4,
- "column" : 45,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "instance_type"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_4", "instance_type"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 4,
- "column" : 45,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "drop"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_4", "drop"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 4,
- "column" : 45,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "recirculate_port"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_4", "recirculate_port"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 4,
- "column" : 45,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "packet_length"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_4", "packet_length"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 4,
- "column" : 45,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "enq_timestamp"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_4", "enq_timestamp"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 4,
- "column" : 45,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "enq_qdepth"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_4", "enq_qdepth"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 4,
- "column" : 45,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "deq_timedelta"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_4", "deq_timedelta"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 4,
- "column" : 45,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "deq_qdepth"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_4", "deq_qdepth"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 4,
- "column" : 45,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "ingress_global_timestamp"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_4", "ingress_global_timestamp"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 4,
- "column" : 45,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "lf_field_list"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_4", "lf_field_list"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 4,
- "column" : 45,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "mcast_grp"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_4", "mcast_grp"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 4,
- "column" : 45,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "resubmit_flag"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_4", "resubmit_flag"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 4,
- "column" : 45,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "egress_rid"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_4", "egress_rid"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 4,
- "column" : 45,
- "source_fragment" : "standard_metadata) { ..."
- }
- }
- ]
- },
- {
- "name" : "drop",
- "id" : 2,
- "runtime_data" : [],
- "primitives" : [
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_5", "ingress_port"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "ingress_port"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 12,
- "column" : 38,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_5", "egress_spec"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "egress_spec"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 12,
- "column" : 38,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_5", "egress_port"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "egress_port"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 12,
- "column" : 38,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_5", "clone_spec"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "clone_spec"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 12,
- "column" : 38,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_5", "instance_type"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "instance_type"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 12,
- "column" : 38,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_5", "drop"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "drop"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 12,
- "column" : 38,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_5", "recirculate_port"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "recirculate_port"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 12,
- "column" : 38,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_5", "packet_length"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "packet_length"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 12,
- "column" : 38,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_5", "enq_timestamp"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "enq_timestamp"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 12,
- "column" : 38,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_5", "enq_qdepth"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "enq_qdepth"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 12,
- "column" : 38,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_5", "deq_timedelta"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "deq_timedelta"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 12,
- "column" : 38,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_5", "deq_qdepth"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "deq_qdepth"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 12,
- "column" : 38,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_5", "ingress_global_timestamp"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "ingress_global_timestamp"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 12,
- "column" : 38,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_5", "lf_field_list"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "lf_field_list"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 12,
- "column" : 38,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_5", "mcast_grp"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "mcast_grp"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 12,
- "column" : 38,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_5", "resubmit_flag"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "resubmit_flag"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 12,
- "column" : 38,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_5", "egress_rid"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata", "egress_rid"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 12,
- "column" : 38,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata_5", "egress_spec"]
- },
- {
- "type" : "hexstr",
- "value" : "0x01ff"
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 13,
- "column" : 4,
- "source_fragment" : "standard_metadata.egress_spec = 9w511"
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "ingress_port"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_5", "ingress_port"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 12,
- "column" : 38,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "egress_spec"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_5", "egress_spec"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 12,
- "column" : 38,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "egress_port"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_5", "egress_port"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 12,
- "column" : 38,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "clone_spec"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_5", "clone_spec"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 12,
- "column" : 38,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "instance_type"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_5", "instance_type"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 12,
- "column" : 38,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "drop"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_5", "drop"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 12,
- "column" : 38,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "recirculate_port"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_5", "recirculate_port"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 12,
- "column" : 38,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "packet_length"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_5", "packet_length"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 12,
- "column" : 38,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "enq_timestamp"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_5", "enq_timestamp"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 12,
- "column" : 38,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "enq_qdepth"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_5", "enq_qdepth"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 12,
- "column" : 38,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "deq_timedelta"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_5", "deq_timedelta"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 12,
- "column" : 38,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "deq_qdepth"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_5", "deq_qdepth"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 12,
- "column" : 38,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "ingress_global_timestamp"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_5", "ingress_global_timestamp"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 12,
- "column" : 38,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "lf_field_list"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_5", "lf_field_list"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 12,
- "column" : 38,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "mcast_grp"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_5", "mcast_grp"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 12,
- "column" : 38,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "resubmit_flag"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_5", "resubmit_flag"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 12,
- "column" : 38,
- "source_fragment" : "standard_metadata) { ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["standard_metadata", "egress_rid"]
- },
- {
- "type" : "field",
- "value" : ["standard_metadata_5", "egress_rid"]
- }
- ],
- "source_info" : {
- "filename" : "include/actions.p4",
- "line" : 12,
- "column" : 38,
- "source_fragment" : "standard_metadata) { ..."
- }
- }
- ]
- },
- {
- "name" : "NoAction",
- "id" : 3,
- "runtime_data" : [],
- "primitives" : []
- },
- {
- "name" : "act",
- "id" : 4,
- "runtime_data" : [],
- "primitives" : [
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["scalars", "tmp"]
- },
- {
- "type" : "expression",
- "value" : {
- "type" : "expression",
- "value" : {
- "op" : "&",
- "left" : {
- "type" : "field",
- "value" : ["standard_metadata", "ingress_port"]
- },
- "right" : {
- "type" : "hexstr",
- "value" : "0xffffffff"
- }
- }
- }
- }
- ]
- },
- {
- "op" : "count",
- "parameters" : [
- {
- "type" : "counter_array",
- "value" : "port_counters_control.ingress_port_counter"
- },
- {
- "type" : "field",
- "value" : ["scalars", "tmp"]
- }
- ],
- "source_info" : {
- "filename" : "include/port_counters.p4",
- "line" : 11,
- "column" : 12,
- "source_fragment" : "ingress_port_counter.count((bit<32>)standard_metadata.ingress_port)"
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["scalars", "tmp_0"]
- },
- {
- "type" : "expression",
- "value" : {
- "type" : "expression",
- "value" : {
- "op" : "&",
- "left" : {
- "type" : "field",
- "value" : ["standard_metadata", "egress_spec"]
- },
- "right" : {
- "type" : "hexstr",
- "value" : "0xffffffff"
- }
- }
- }
- }
- ]
- },
- {
- "op" : "count",
- "parameters" : [
- {
- "type" : "counter_array",
- "value" : "port_counters_control.egress_port_counter"
- },
- {
- "type" : "field",
- "value" : ["scalars", "tmp_0"]
- }
- ],
- "source_info" : {
- "filename" : "include/port_counters.p4",
- "line" : 12,
- "column" : 12,
- "source_fragment" : "egress_port_counter.count((bit<32>)standard_metadata.egress_spec)"
- }
- }
- ]
- }
- ],
- "pipelines" : [
- {
- "name" : "ingress",
- "id" : 0,
- "source_info" : {
- "filename" : "default.p4",
- "line" : 10,
- "column" : 8,
- "source_fragment" : "ingress"
- },
- "init_table" : "table0",
- "tables" : [
- {
- "name" : "table0",
- "id" : 0,
- "source_info" : {
- "filename" : "default.p4",
- "line" : 13,
- "column" : 10,
- "source_fragment" : "table0"
- },
- "key" : [
- {
- "match_type" : "ternary",
- "target" : ["standard_metadata", "ingress_port"],
- "mask" : null
- },
- {
- "match_type" : "ternary",
- "target" : ["ethernet", "dstAddr"],
- "mask" : null
- },
- {
- "match_type" : "ternary",
- "target" : ["ethernet", "srcAddr"],
- "mask" : null
- },
- {
- "match_type" : "ternary",
- "target" : ["ethernet", "etherType"],
- "mask" : null
- }
- ],
- "match_type" : "ternary",
- "type" : "simple",
- "max_size" : 1024,
- "support_timeout" : false,
- "direct_meters" : null,
- "action_ids" : [0, 1, 2, 3],
- "actions" : ["set_egress_port", "send_to_cpu", "drop", "NoAction"],
- "base_default_next" : "node_3",
- "next_tables" : {
- "set_egress_port" : "node_3",
- "send_to_cpu" : "node_3",
- "drop" : "node_3",
- "NoAction" : "node_3"
- },
- "default_entry" : {
- "action_id" : 3,
- "action_const" : false,
- "action_data" : [],
- "action_entry_const" : false
- }
- },
- {
- "name" : "tbl_act",
- "id" : 1,
- "key" : [],
- "match_type" : "exact",
- "type" : "simple",
- "max_size" : 1024,
- "with_counters" : false,
- "support_timeout" : false,
- "direct_meters" : null,
- "action_ids" : [4],
- "actions" : ["act"],
- "base_default_next" : null,
- "next_tables" : {
- "act" : null
- },
- "default_entry" : {
- "action_id" : 4,
- "action_const" : true,
- "action_data" : [],
- "action_entry_const" : true
- }
- }
- ],
- "action_profiles" : [],
- "conditionals" : [
- {
- "name" : "node_3",
- "id" : 0,
- "source_info" : {
- "filename" : "include/port_counters.p4",
- "line" : 10,
- "column" : 12,
- "source_fragment" : "standard_metadata.egress_spec < 254"
- },
- "expression" : {
- "type" : "expression",
- "value" : {
- "op" : "<",
- "left" : {
- "type" : "field",
- "value" : ["standard_metadata", "egress_spec"]
- },
- "right" : {
- "type" : "hexstr",
- "value" : "0x00fe"
- }
- }
- },
- "false_next" : null,
- "true_next" : "tbl_act"
- }
- ]
- },
- {
- "name" : "egress",
- "id" : 1,
- "source_info" : {
- "filename" : "default.p4",
- "line" : 36,
- "column" : 8,
- "source_fragment" : "egress"
- },
- "init_table" : null,
- "tables" : [],
- "action_profiles" : [],
- "conditionals" : []
- }
- ],
- "checksums" : [],
- "force_arith" : [],
- "extern_instances" : [],
- "field_aliases" : [
- [
- "queueing_metadata.enq_timestamp",
- ["standard_metadata", "enq_timestamp"]
- ],
- [
- "queueing_metadata.enq_qdepth",
- ["standard_metadata", "enq_qdepth"]
- ],
- [
- "queueing_metadata.deq_timedelta",
- ["standard_metadata", "deq_timedelta"]
- ],
- [
- "queueing_metadata.deq_qdepth",
- ["standard_metadata", "deq_qdepth"]
- ],
- [
- "intrinsic_metadata.ingress_global_timestamp",
- ["standard_metadata", "ingress_global_timestamp"]
- ],
- [
- "intrinsic_metadata.lf_field_list",
- ["standard_metadata", "lf_field_list"]
- ],
- [
- "intrinsic_metadata.mcast_grp",
- ["standard_metadata", "mcast_grp"]
- ],
- [
- "intrinsic_metadata.resubmit_flag",
- ["standard_metadata", "resubmit_flag"]
- ],
- [
- "intrinsic_metadata.egress_rid",
- ["standard_metadata", "egress_rid"]
- ]
- ]
-}
\ No newline at end of file
diff --git a/protocols/p4runtime/ctl/src/test/resources/default.p4info b/protocols/p4runtime/ctl/src/test/resources/default.p4info
deleted file mode 100644
index b224b87..0000000
--- a/protocols/p4runtime/ctl/src/test/resources/default.p4info
+++ /dev/null
@@ -1,147 +0,0 @@
-tables {
- preamble {
- id: 33617813
- name: "table0"
- alias: "table0"
- }
- match_fields {
- id: 1
- name: "standard_metadata.ingress_port"
- bitwidth: 9
- match_type: TERNARY
- }
- match_fields {
- id: 2
- name: "hdr.ethernet.dstAddr"
- bitwidth: 48
- match_type: TERNARY
- }
- match_fields {
- id: 3
- name: "hdr.ethernet.srcAddr"
- bitwidth: 48
- match_type: TERNARY
- }
- match_fields {
- id: 4
- name: "hdr.ethernet.etherType"
- bitwidth: 16
- match_type: TERNARY
- }
- action_refs {
- id: 16794308
- }
- action_refs {
- id: 16829080
- }
- action_refs {
- id: 16793508
- }
- action_refs {
- id: 16800567
- annotations: "@defaultonly()"
- }
- direct_resource_ids: 301990488
- size: 1024
- with_entry_timeout: true
-}
-actions {
- preamble {
- id: 16794308
- name: "set_egress_port"
- alias: "set_egress_port"
- }
- params {
- id: 1
- name: "port"
- bitwidth: 9
- }
-}
-actions {
- preamble {
- id: 16829080
- name: "send_to_cpu"
- alias: "send_to_cpu"
- }
-}
-actions {
- preamble {
- id: 16793508
- name: "drop"
- alias: "drop"
- }
-}
-actions {
- preamble {
- id: 16800567
- name: "NoAction"
- alias: "NoAction"
- }
-}
-counters {
- preamble {
- id: 302025528
- name: "port_counters_control.egress_port_counter"
- alias: "egress_port_counter"
- }
- spec {
- unit: PACKETS
- }
- size: 254
-}
-counters {
- preamble {
- id: 301999025
- name: "port_counters_control.ingress_port_counter"
- alias: "ingress_port_counter"
- }
- spec {
- unit: PACKETS
- }
- size: 254
-}
-direct_counters {
- preamble {
- id: 301990488
- name: "table0_counter"
- alias: "table0_counter"
- }
- spec {
- unit: PACKETS
- }
- direct_table_id: 33617813
-}
-controller_packet_metadata {
- preamble {
- id: 2868941301
- name: "packet_in"
- annotations: "@controller_header(\"packet_in\")"
- }
- metadata {
- id: 1
- name: "ingress_port"
- bitwidth: 9
- }
- metadata {
- id: 2
- name: "other1"
- bitwidth: 32
- }
-}
-controller_packet_metadata {
- preamble {
- id: 2868916615
- name: "packet_out"
- annotations: "@controller_header(\"packet_out\")"
- }
- metadata {
- id: 1
- name: "egress_port"
- bitwidth: 9
- }
- metadata {
- id: 2
- name: "other2"
- bitwidth: 32
- }
-}
diff --git a/protocols/p4runtime/ctl/src/test/resources/default.p4info b/protocols/p4runtime/ctl/src/test/resources/default.p4info
new file mode 120000
index 0000000..4dda381
--- /dev/null
+++ b/protocols/p4runtime/ctl/src/test/resources/default.p4info
@@ -0,0 +1 @@
+../../../../../../tools/test/p4src/p4-16/p4c-out/default.p4info
\ No newline at end of file
diff --git a/providers/bgpcep/flow/src/main/java/org/onosproject/provider/bgpcep/flow/impl/BgpcepFlowRuleProvider.java b/providers/bgpcep/flow/src/main/java/org/onosproject/provider/bgpcep/flow/impl/BgpcepFlowRuleProvider.java
index 8868153..83aaac8 100644
--- a/providers/bgpcep/flow/src/main/java/org/onosproject/provider/bgpcep/flow/impl/BgpcepFlowRuleProvider.java
+++ b/providers/bgpcep/flow/src/main/java/org/onosproject/provider/bgpcep/flow/impl/BgpcepFlowRuleProvider.java
@@ -22,7 +22,7 @@
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.FlowRuleBatchOperation;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchOperation;
import org.onosproject.net.flow.FlowRuleProvider;
import org.onosproject.net.flow.FlowRuleProviderRegistry;
import org.onosproject.net.flow.FlowRuleProviderService;
diff --git a/providers/null/src/main/java/org/onosproject/provider/nil/NullFlowRuleProvider.java b/providers/null/src/main/java/org/onosproject/provider/nil/NullFlowRuleProvider.java
index 095bdc4..2cbb4d0 100644
--- a/providers/null/src/main/java/org/onosproject/provider/nil/NullFlowRuleProvider.java
+++ b/providers/null/src/main/java/org/onosproject/provider/nil/NullFlowRuleProvider.java
@@ -27,8 +27,8 @@
import org.onosproject.net.flow.DefaultFlowEntry;
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.FlowRuleBatchEntry;
-import org.onosproject.net.flow.FlowRuleBatchOperation;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchEntry;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchOperation;
import org.onosproject.net.flow.FlowRuleProvider;
import org.onosproject.net.flow.FlowRuleProviderService;
import org.slf4j.Logger;
diff --git a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowRuleProvider.java b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowRuleProvider.java
index 9a14393..9dc03cd 100644
--- a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowRuleProvider.java
+++ b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/impl/OpenFlowRuleProvider.java
@@ -41,8 +41,8 @@
import org.onosproject.net.flow.DefaultTableStatisticsEntry;
import org.onosproject.net.flow.FlowEntry;
import org.onosproject.net.flow.FlowRule;
-import org.onosproject.net.flow.FlowRuleBatchEntry;
-import org.onosproject.net.flow.FlowRuleBatchOperation;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchEntry;
+import org.onosproject.net.flow.oldbatch.FlowRuleBatchOperation;
import org.onosproject.net.flow.FlowRuleExtPayLoad;
import org.onosproject.net.flow.FlowRuleProvider;
import org.onosproject.net.flow.FlowRuleProviderRegistry;
diff --git a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/util/FlowEntryBuilder.java b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/util/FlowEntryBuilder.java
index 54e2f5f..083a74c 100644
--- a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/util/FlowEntryBuilder.java
+++ b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/util/FlowEntryBuilder.java
@@ -1121,9 +1121,15 @@
return obj.getVersion().wireVersion >= OFVersion.OF_13.wireVersion;
}
- private DriverHandler getDriver(DeviceId devId) {
- Driver driver = driverService.getDriver(devId);
- DriverHandler handler = new DefaultDriverHandler(new DefaultDriverData(driver, devId));
+ /**
+ * Retrieves the driver handler for the specified device.
+ *
+ * @param deviceId device identifier
+ * @return driver handler
+ */
+ protected DriverHandler getDriver(DeviceId deviceId) {
+ Driver driver = driverService.getDriver(deviceId);
+ DriverHandler handler = new DefaultDriverHandler(new DefaultDriverData(driver, deviceId));
return handler;
}
}
diff --git a/tools/build/onos-release-prerequisites b/tools/build/onos-release-prerequisites
index 1eb4cb9..f3d2b6b 100755
--- a/tools/build/onos-release-prerequisites
+++ b/tools/build/onos-release-prerequisites
@@ -92,11 +92,11 @@
echo "OK"
}
-# Test access to wiki.onosproject.org
+# Test access to api.onosproject.org
function testWikiAccess {
trap "echo 'FAILED'" ERR
printf "Checking Wiki access... "
- ssh $WIKI_USER@wiki.onosproject.org "test -w /var/www/api/index.html"
+ ssh $WIKI_USER@api.onosproject.org "test -w /var/www/api/index.html"
echo "OK"
}
diff --git a/tools/build/onos-upload-docs b/tools/build/onos-upload-docs
index 3133d41..79986b6 100755
--- a/tools/build/onos-upload-docs
+++ b/tools/build/onos-upload-docs
@@ -9,7 +9,7 @@
. $ONOS_ROOT/tools/build/envDefaults
user=${1:-${WIKI_USER:-$USER}}
-remote=$user@wiki.onosproject.org
+remote=$user@api.onosproject.org
docs=$(onos-buck build //docs:external --show-output 2>/dev/null | tail -1 | cut -d\ -f2)
diff --git a/web/api/src/test/java/org/onosproject/rest/resources/ApplicationsResourceTest.java b/web/api/src/test/java/org/onosproject/rest/resources/ApplicationsResourceTest.java
index 61e7174..48cbd2d 100644
--- a/web/api/src/test/java/org/onosproject/rest/resources/ApplicationsResourceTest.java
+++ b/web/api/src/test/java/org/onosproject/rest/resources/ApplicationsResourceTest.java
@@ -107,30 +107,55 @@
private static final URI FURL = URI.create("mvn:org.foo-features/1.2a/xml/features");
private static final Version VER = Version.version(1, 2, "a", null);
+ private DefaultApplication.Builder baseBuilder = DefaultApplication.builder()
+ .withVersion(VER)
+ .withIcon(new byte[0])
+ .withRole(ApplicationRole.ADMIN)
+ .withPermissions(ImmutableSet.of())
+ .withFeaturesRepo(Optional.of(FURL))
+ .withFeatures(ImmutableList.of("My Feature"))
+ .withRequiredApps(ImmutableList.of());
+
private Application app1 =
- new DefaultApplication(id1, VER, "title1",
- "desc1", "origin1", "category1", "url1",
- "readme1", new byte[0], ApplicationRole.ADMIN,
- ImmutableSet.of(), Optional.of(FURL),
- ImmutableList.of("My Feature"), ImmutableList.of());
+ DefaultApplication.builder(baseBuilder)
+ .withAppId(id1)
+ .withTitle("title1")
+ .withDescription("desc1")
+ .withOrigin("origin1")
+ .withCategory("category1")
+ .withUrl("url1")
+ .withReadme("readme1")
+ .build();
private Application app2 =
- new DefaultApplication(id2, VER, "title2",
- "desc2", "origin2", "category2", "url2",
- "readme2", new byte[0], ApplicationRole.ADMIN,
- ImmutableSet.of(), Optional.of(FURL),
- ImmutableList.of("My Feature"), ImmutableList.of());
+ DefaultApplication.builder(baseBuilder)
+ .withAppId(id2)
+ .withTitle("title2")
+ .withDescription("desc2")
+ .withOrigin("origin2")
+ .withCategory("category2")
+ .withUrl("url2")
+ .withReadme("readme2")
+ .build();
private Application app3 =
- new DefaultApplication(id3, VER, "title3",
- "desc3", "origin3", "category3", "url3",
- "readme3", new byte[0], ApplicationRole.ADMIN,
- ImmutableSet.of(), Optional.of(FURL),
- ImmutableList.of("My Feature"), ImmutableList.of());
+ DefaultApplication.builder(baseBuilder)
+ .withAppId(id3)
+ .withTitle("title3")
+ .withDescription("desc3")
+ .withOrigin("origin3")
+ .withCategory("category3")
+ .withUrl("url3")
+ .withReadme("readme3")
+ .build();
private Application app4 =
- new DefaultApplication(id4, VER, "title4",
- "desc4", "origin4", "category4", "url4",
- "readme4", new byte[0], ApplicationRole.ADMIN,
- ImmutableSet.of(), Optional.of(FURL),
- ImmutableList.of("My Feature"), ImmutableList.of());
+ DefaultApplication.builder(baseBuilder)
+ .withAppId(id4)
+ .withTitle("title4")
+ .withDescription("desc4")
+ .withOrigin("origin4")
+ .withCategory("category4")
+ .withUrl("url4")
+ .withReadme("readme4")
+ .build();
/**
* Hamcrest matcher to check that an application representation in JSON matches
diff --git a/web/gui/src/main/resources/org/onosproject/ui/lion/core/view/Topo.properties b/web/gui/src/main/resources/org/onosproject/ui/lion/core/view/Topo.properties
index 0c82575..b5c5398 100644
--- a/web/gui/src/main/resources/org/onosproject/ui/lion/core/view/Topo.properties
+++ b/web/gui/src/main/resources/org/onosproject/ui/lion/core/view/Topo.properties
@@ -129,12 +129,12 @@
lp_label_a_type=A type
lp_label_a_id=A id
-lp_label_a_friendly=A friendly
+lp_label_a_friendly=A name
lp_label_a_port=A port
lp_label_b_type=B type
lp_label_b_id=B id
-lp_label_b_friendly=B friendly
+lp_label_b_friendly=B name
lp_label_b_port=B port
lp_label_a2b=A to B
diff --git a/web/gui/src/main/resources/org/onosproject/ui/lion/core/view/Topo_es.properties b/web/gui/src/main/resources/org/onosproject/ui/lion/core/view/Topo_es.properties
index 6631bc5..3630c22 100644
--- a/web/gui/src/main/resources/org/onosproject/ui/lion/core/view/Topo_es.properties
+++ b/web/gui/src/main/resources/org/onosproject/ui/lion/core/view/Topo_es.properties
@@ -128,12 +128,12 @@
lp_label_a_type=Tipo A
lp_label_a_id=A id
-lp_label_a_friendly=A friendly
+lp_label_a_friendly=A name
lp_label_a_port=Puerto A
lp_label_b_type=Tipo B
lp_label_b_id=B id
-lp_label_b_friendly=B friendly
+lp_label_b_friendly=B name
lp_label_b_port=Puerto B
lp_label_a2b=A to B
diff --git a/web/gui/src/main/resources/org/onosproject/ui/lion/core/view/Topo_ko.properties b/web/gui/src/main/resources/org/onosproject/ui/lion/core/view/Topo_ko.properties
index f09adb8..08d7dc6 100644
--- a/web/gui/src/main/resources/org/onosproject/ui/lion/core/view/Topo_ko.properties
+++ b/web/gui/src/main/resources/org/onosproject/ui/lion/core/view/Topo_ko.properties
@@ -129,12 +129,12 @@
lp_label_a_type=A 타입
lp_label_a_id=A 아이디
-lp_label_a_friendly=A friendly
+lp_label_a_friendly=A name
lp_label_a_port=A 포트
lp_label_b_type=B 타입
lp_label_b_id=B 아이디
-lp_label_b_friendly=B friendly
+lp_label_b_friendly=B name
lp_label_b_port=B 포트
lp_label_a2b=A에서 B
diff --git a/web/gui/src/main/resources/org/onosproject/ui/lion/core/view/Topo_zh_CN.properties b/web/gui/src/main/resources/org/onosproject/ui/lion/core/view/Topo_zh_CN.properties
index 8aa7c5a..e02c978 100644
--- a/web/gui/src/main/resources/org/onosproject/ui/lion/core/view/Topo_zh_CN.properties
+++ b/web/gui/src/main/resources/org/onosproject/ui/lion/core/view/Topo_zh_CN.properties
@@ -128,11 +128,11 @@
lp_label_friendly=friendly
lp_label_a_type=A 类型
lp_label_a_id=A id
-lp_label_a_friendly=A friendly
+lp_label_a_friendly=A name
lp_label_a_port=A 端口
lp_label_b_type=B 类型
lp_label_b_id=B id
-lp_label_b_friendly=B friendly
+lp_label_b_friendly=B name
lp_label_b_port=B 端口
lp_label_a2b=A 到 B
lp_label_b2a=B 到 A
diff --git a/web/gui/src/main/resources/org/onosproject/ui/lion/core/view/Topo_zh_TW.properties b/web/gui/src/main/resources/org/onosproject/ui/lion/core/view/Topo_zh_TW.properties
index 000bd12..9eabe7c 100644
--- a/web/gui/src/main/resources/org/onosproject/ui/lion/core/view/Topo_zh_TW.properties
+++ b/web/gui/src/main/resources/org/onosproject/ui/lion/core/view/Topo_zh_TW.properties
@@ -127,12 +127,12 @@
lp_label_a_type=A 種類
lp_label_a_id=A ID
-lp_label_a_friendly=A friendly
+lp_label_a_friendly=A name
lp_label_a_port=A 連接埠
lp_label_b_type=B 種類
lp_label_b_id=B ID
-lp_label_b_friendly=B friendly
+lp_label_b_friendly=B name
lp_label_b_port=B 連接埠
lp_label_a2b=A 到 B