Merge branch 'master' of https://gerrit.opencord.org/fpcagent
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..bff2d76
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+*.iml
diff --git a/apps/fpcagent/BUCK b/apps/fpcagent/BUCK
new file mode 100644
index 0000000..4396a00
--- /dev/null
+++ b/apps/fpcagent/BUCK
@@ -0,0 +1,73 @@
+COMPILE_DEPS = [
+ '//lib:CORE_DEPS',
+ '//lib:JACKSON',
+ '//lib:KRYO',
+ '//models/fpcagent:onos-models-fpcagent',
+ '//models/common:onos-models-common',
+ '//lib:onos-yang-model',
+ '//apps/config:onos-apps-config',
+ '//core/api:onos-api',
+ '//lib:javax.ws.rs-api',
+ '//utils/rest:onlab-rest',
+ '//core/store/serializers:onos-core-serializers',
+ '//apps/restconf/utils:onos-apps-restconf-utils',
+ ':zeromq',
+ ':json',
+]
+
+TEST_DEPS = [
+ '//lib:TEST_ADAPTERS',
+ '//lib:TEST_REST',
+ '//utils/osgi:onlab-osgi-tests',
+]
+
+BUNDLES = [
+ '//apps/fpcagent:onos-apps-fpcagent',
+]
+
+EXCLUDED_BUNDLES = [
+ ':zeromq',
+ ':json',
+]
+
+APPS = [
+ 'org.onosproject.models.fpcagent',
+ 'org.onosproject.yang',
+ 'org.onosproject.yang-gui',
+ 'org.onosproject.config',
+ 'org.onosproject.restconf',
+ 'org.onosproject.protocols.restconfserver',
+]
+
+osgi_jar_with_tests(
+ deps = COMPILE_DEPS,
+ test_deps = TEST_DEPS,
+)
+
+onos_app(
+ app_name = 'org.onosproject.fpcagent',
+ title = 'YANG FPC Agent',
+ category = 'Traffic Steering',
+ url = 'http://onosproject.org',
+ description = 'FPC Agent YANG Application',
+ required_apps = APPS,
+ excluded_bundles = EXCLUDED_BUNDLES,
+)
+
+remote_jar (
+ name = 'json',
+ out = 'json-20090211.jar',
+ url = 'mvn:org.json:json:jar:20090211',
+ sha1 = 'c183aa3a2a6250293808bba12262c8920ce5a51c',
+ maven_coords = 'org.json:json:jar:NON-OSGI:20090211',
+ visibility = [ 'PUBLIC' ],
+)
+
+remote_jar (
+ name = 'zeromq',
+ out = 'jeromq-0.3.5.jar',
+ url = 'mvn:org.zeromq:jeromq:jar:0.3.5',
+ sha1 = '39a79082570d114bb5433762e836e4dd9c38b03d',
+ maven_coords = 'org.zeromq:jeromq:0.3.5',
+ visibility = [ 'PUBLIC' ],
+)
diff --git a/apps/fpcagent/fpcagent.json b/apps/fpcagent/fpcagent.json
new file mode 100644
index 0000000..a54290a
--- /dev/null
+++ b/apps/fpcagent/fpcagent.json
@@ -0,0 +1,16 @@
+{
+ "apps": {
+ "org.onosproject.fpcagent": {
+ "fpcagent": {
+ "dpn-subscriber-uri": "tcp://*:5560",
+ "dpn-publisher-uri": "tcp://*:5559",
+ "dpn-client-threads": 5,
+ "node-id": "node0",
+ "network-id": "network1",
+ "zmq-broadcast-all": "1",
+ "zmq-broadcast-controllers": "2",
+ "zmq-broadcast-dpns": "3"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/FpcConfig.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/FpcConfig.java
new file mode 100644
index 0000000..b9cbb9f
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/FpcConfig.java
@@ -0,0 +1,25 @@
+package org.onosproject.fpcagent;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import org.apache.commons.lang.exception.ExceptionUtils;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.fpcagent.helpers.ConfigHelper;
+import org.onosproject.net.config.Config;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Optional;
+
+public class FpcConfig extends Config<ApplicationId> {
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ public Optional<ConfigHelper> getConfig() {
+ try {
+ return Optional.of(mapper.treeToValue(object, ConfigHelper.class));
+ } catch (JsonProcessingException e) {
+ log.error(ExceptionUtils.getFullStackTrace(e));
+ }
+ return Optional.empty();
+ }
+}
+
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/FpcManager.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/FpcManager.java
new file mode 100644
index 0000000..27e6b8b
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/FpcManager.java
@@ -0,0 +1,285 @@
+/*
+ * 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.fpcagent;
+
+import org.apache.commons.lang.exception.ExceptionUtils;
+import org.apache.felix.scr.annotations.*;
+import org.onosproject.config.DynamicConfigService;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.fpcagent.helpers.ConfigHelper;
+import org.onosproject.fpcagent.workers.ZMQSBPublisherManager;
+import org.onosproject.fpcagent.workers.ZMQSBSubscriberManager;
+import org.onosproject.net.config.*;
+import org.onosproject.net.config.basics.SubjectFactories;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.IetfDmmFpcagentService;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.ErrorTypeId;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.Result;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.configure.DefaultConfigureInput;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.configure.DefaultConfigureOutput;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.configuredpn.DefaultConfigureDpnInput;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.configuredpn.DefaultConfigureDpnOutput;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.opinput.opbody.CreateOrUpdate;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.opinput.opbody.DeleteOrQuery;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.result.ResultEnum;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.resultbody.resulttype.DefaultErr;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.resultbodydpn.resulttype.DefaultEmptyCase;
+import org.onosproject.yang.model.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Optional;
+
+import static org.onosproject.fpcagent.FpcUtil.*;
+
+/**
+ * Fpc Manager.
+ */
+@Component(immediate = true)
+@Service
+public class FpcManager implements IetfDmmFpcagentService, FpcService {
+ private static final Logger log = LoggerFactory.getLogger(FpcManager.class);
+
+ private static final Class<FpcConfig> CONFIG_CLASS = FpcConfig.class;
+ private final InternalNetworkConfigListener configListener =
+ new InternalNetworkConfigListener();
+
+ /* Services */
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ private TenantService tenantService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ private ModelConverter modelConverter;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ private DynamicConfigService dynamicConfigService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ private RpcRegistry rpcRegistry;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ private NetworkConfigRegistry registry;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ private NetworkConfigService configService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ private CoreService coreService;
+
+ /* Variables */
+ private FpcConfig fpcConfig;
+
+ /* Config */
+ private ConfigFactory<ApplicationId, FpcConfig> fpcConfigConfigFactory =
+ new ConfigFactory<ApplicationId, FpcConfig>(
+ SubjectFactories.APP_SUBJECT_FACTORY, FpcConfig.class, "fpcagent") {
+ @Override
+ public FpcConfig createConfig() {
+ return new FpcConfig();
+ }
+ };
+
+ @Activate
+ protected void activate() {
+ coreService.registerApplication(FPC_APP_ID);
+ configService.addListener(configListener);
+ registry.registerConfigFactory(fpcConfigConfigFactory);
+
+ rpcRegistry.registerRpcService(this);
+
+ log.info("FPC Agent Started");
+ }
+
+ @Deactivate
+ protected void deactivate() {
+ configService.removeListener(configListener);
+ registry.unregisterConfigFactory(fpcConfigConfigFactory);
+
+ // TODO check if null before closing
+ ZMQSBSubscriberManager.getInstance().close();
+ ZMQSBPublisherManager.getInstance().close();
+
+ rpcRegistry.unregisterRpcService(this);
+
+ log.info("FPC Agent Stopped");
+ }
+
+ private void init() {
+ fpcConfig.getConfig().ifPresent(
+ helper -> {
+ ZMQSBSubscriberManager.createInstance(
+ helper.dpnSubscriberUri(),
+ helper.zmqBroadcastAll(),
+ helper.zmqBroadcastControllers(),
+ helper.zmqBroadcastDpns(),
+ helper.nodeId(),
+ helper.networkId()
+ );
+
+ ZMQSBPublisherManager.createInstance(
+ helper.dpnPublisherUri(),
+ helper.dpnClientThreads()
+ );
+
+ ZMQSBPublisherManager.getInstance().open();
+ ZMQSBSubscriberManager.getInstance().open();
+ }
+ );
+ }
+
+ @Override
+ public Optional<ConfigHelper> getConfig() {
+ return fpcConfig != null ? fpcConfig.getConfig() : Optional.empty();
+ }
+
+ @Override
+ public RpcOutput configureDpn(RpcInput rpcInput) {
+ DefaultConfigureDpnOutput output = new DefaultConfigureDpnOutput();
+ output.result(Result.of(ResultEnum.OK));
+ output.resultType(new DefaultEmptyCase());
+
+ try {
+ tenantService.getModelObjects(rpcInput.data(), configureDpnResourceId).forEach(
+ modelObject -> {
+ DefaultConfigureDpnInput input = (DefaultConfigureDpnInput) modelObject;
+ String dpnId = input.inputDpnId().fpcIdentity().union().string();
+ switch (input.operation().enumeration()) {
+ case ADD:
+ log.info("Adding DPN {}", dpnId);
+ // TODO
+ break;
+ case REMOVE:
+ log.info("Removing DPN {}", dpnId);
+ // TODO
+ break;
+ }
+ });
+ } catch (Exception e) {
+ log.error(ExceptionUtils.getFullStackTrace(e));
+ }
+
+ ResourceData dataNode = modelConverter.createDataNode(
+ DefaultModelObjectData.builder().addModelObject(output).build()
+ );
+ return new RpcOutput(RpcOutput.Status.RPC_SUCCESS, dataNode.dataNodes().get(0));
+ }
+
+ @Override
+ public RpcOutput configure(RpcInput rpcInput) {
+ DefaultConfigureOutput configureOutput = new DefaultConfigureOutput();
+
+ try {
+ for (ModelObject modelObject : tenantService.getModelObjects(rpcInput.data(), configureResourceId)) {
+ DefaultConfigureInput input = (DefaultConfigureInput) modelObject;
+ switch (input.opType()) {
+ case CREATE:
+ configureOutput = tenantService.configureCreate(
+ (CreateOrUpdate) input.opBody(),
+ input.clientId(),
+ input.opId()
+ );
+ break;
+ case UPDATE:
+ configureOutput = tenantService.configureUpdate(
+ (CreateOrUpdate) input.opBody(),
+ input.clientId(),
+ input.opId()
+ );
+ break;
+ case QUERY:
+ break;
+ case DELETE:
+ configureOutput = tenantService.configureDelete(
+ (DeleteOrQuery) input.opBody(),
+ input.clientId(),
+ input.opId()
+ );
+ break;
+ }
+ configureOutput.opId(input.opId());
+ }
+ // TODO fix DELETE to update the NODE correctly.
+ tenantService.getTenants().ifPresent(tenants -> tenantService.updateNode(tenants));
+ } catch (Exception e) {
+ DefaultErr defaultErr = new DefaultErr();
+ defaultErr.errorInfo(ExceptionUtils.getFullStackTrace(e));
+ defaultErr.errorTypeId(ErrorTypeId.of(0));
+ configureOutput.resultType(defaultErr);
+ configureOutput.result(Result.of(ResultEnum.ERR));
+ log.error(ExceptionUtils.getFullStackTrace(e));
+ }
+
+ ResourceData dataNode = modelConverter.createDataNode(
+ DefaultModelObjectData.builder()
+ .addModelObject(configureOutput)
+ .build()
+ );
+ return new RpcOutput(RpcOutput.Status.RPC_SUCCESS, dataNode.dataNodes().get(0));
+ }
+
+ @Override
+ public RpcOutput configureBundles(RpcInput rpcInput) {
+ return null;
+ }
+
+ @Override
+ public RpcOutput eventRegister(RpcInput rpcInput) {
+ return null;
+ }
+
+ @Override
+ public RpcOutput eventDeregister(RpcInput rpcInput) {
+ return null;
+ }
+
+ @Override
+ public RpcOutput probe(RpcInput rpcInput) {
+ return null;
+ }
+
+ private class InternalNetworkConfigListener implements NetworkConfigListener {
+
+ @Override
+ public void event(NetworkConfigEvent event) {
+ switch (event.type()) {
+ case CONFIG_REGISTERED:
+ case CONFIG_UNREGISTERED: {
+ break;
+ }
+ case CONFIG_REMOVED: {
+ if (event.configClass() == CONFIG_CLASS) {
+ fpcConfig = null;
+ }
+ break;
+ }
+ case CONFIG_UPDATED:
+ case CONFIG_ADDED: {
+ if (event.configClass() == CONFIG_CLASS) {
+ event.config().ifPresent(config -> {
+ fpcConfig = (FpcConfig) config;
+ init();
+ });
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ }
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/FpcService.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/FpcService.java
new file mode 100644
index 0000000..5e4e152
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/FpcService.java
@@ -0,0 +1,10 @@
+package org.onosproject.fpcagent;
+
+import org.onosproject.fpcagent.helpers.ConfigHelper;
+
+import java.util.Optional;
+
+public interface FpcService {
+
+ Optional<ConfigHelper> getConfig();
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/FpcUtil.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/FpcUtil.java
new file mode 100644
index 0000000..6f1ebf1
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/FpcUtil.java
@@ -0,0 +1,246 @@
+/*
+ * 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.fpcagent;
+
+import com.google.common.collect.Maps;
+import org.onosproject.restconf.utils.RestconfUtils;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.ClientIdentifier;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.OpIdentifier;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.yangautoprefixnotify.value.DefaultDownlinkDataNotification;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.yangautoprefixnotify.value.DownlinkDataNotification;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.FpcDpnId;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.FpcIdentity;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.fpcidentity.FpcIdentityUnion;
+import org.onosproject.yang.model.DataNode;
+import org.onosproject.yang.model.DefaultResourceData;
+import org.onosproject.yang.model.ResourceData;
+import org.onosproject.yang.model.ResourceId;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigInteger;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.AbstractMap;
+import java.util.Arrays;
+import java.util.Map;
+
+import static org.onosproject.fpcagent.helpers.Converter.fromIntToLong;
+import static org.onosproject.fpcagent.helpers.Converter.toBigInt;
+
+/**
+ * Helper class which stores all the static variables.
+ */
+public class FpcUtil {
+ protected static final Logger log = LoggerFactory.getLogger(FpcUtil.class);
+
+ public static final int MAX_EVENTS = 1000;
+ public static final int MAX_BATCH_MS = 5000;
+ public static final int MAX_IDLE_MS = 1000;
+ public static final String TIMER = "dynamic-config-fpcagent-timer";
+ public static final String UNKNOWN_EVENT = "FPC Agent listener: unknown event: {}";
+ public static final String EVENT_NULL = "Event cannot be null";
+ public static final String FPC_APP_ID = "org.onosproject.fpcagent";
+
+ private static final Map<String, FpcDpnId> uplinkDpnMap = Maps.newConcurrentMap();
+ private static final Map<String, Short> nodeToTopicMap = Maps.newConcurrentMap();
+
+ private static byte DPN_HELLO = 0b0000_0001;
+ private static byte DPN_BYE = 0b0000_0010;
+ private static byte DOWNLINK_DATA_NOTIFICATION = 0b0000_0101;
+ private static byte DPN_STATUS_INDICATION = 0b0000_1100;
+ private static byte DPN_OVERLOAD_INDICATION = 0b0000_0101;
+ private static byte DPN_REPLY = 0b0000_0100;
+ private static String DOWNLINK_DATA_NOTIFICATION_STRING = "Downlink-Data-Notification";
+
+ // Resource ID for Configure DPN RPC command
+ public static ResourceId configureDpnResourceId;
+ // Resource ID for Configure RPC command
+ public static ResourceId configureResourceId;
+ // Resource ID for tenants data
+ public static ResourceId tenantsResourceId;
+ public static ResourceId registerClientResourceId;
+ public static ResourceId deregisterClientResourceId;
+
+ static {
+ try {
+ configureDpnResourceId = RestconfUtils.convertUriToRid(
+ new URI("/onos/restconf/operations/ietf-dmm-fpcagent:configure-dpn")
+ );
+ configureResourceId = RestconfUtils.convertUriToRid(
+ new URI("/onos/restconf/operations/ietf-dmm-fpcagent:configure")
+ );
+ tenantsResourceId = RestconfUtils.convertUriToRid(
+ new URI("/onos/restconf/data/ietf-dmm-fpcagent:tenants")
+ );
+ registerClientResourceId = RestconfUtils.convertUriToRid(
+ new URI("/onos/restconf/data/fpc:register-client")
+ );
+ deregisterClientResourceId = RestconfUtils.convertUriToRid(
+ new URI("/onos/restconf/data/fpc:deregister-client")
+ );
+ } catch (URISyntaxException ignored) {
+ }
+ }
+
+ /**
+ * Returns the resource data from the data node and the resource id.
+ *
+ * @param dataNode data node
+ * @param resId resource id
+ * @return resource data
+ */
+ static ResourceData getResourceData(DataNode dataNode, ResourceId resId) {
+ if (resId != null) {
+ return DefaultResourceData.builder()
+ .addDataNode(dataNode)
+ .resourceId(resId)
+ .build();
+ } else {
+ return DefaultResourceData.builder()
+ .addDataNode(dataNode)
+ .build();
+ }
+ }
+
+ /**
+ * Ensures the session id is an unsigned 64 bit integer
+ *
+ * @param sessionId - session id received from the DPN
+ * @return unsigned session id
+ */
+ private static BigInteger checkSessionId(BigInteger sessionId) {
+ if (sessionId.compareTo(BigInteger.ZERO) < 0) {
+ sessionId = sessionId.add(BigInteger.ONE.shiftLeft(64));
+ }
+ return sessionId;
+ }
+
+ /**
+ * Decodes a DownlinkDataNotification
+ *
+ * @param buf - message buffer
+ * @param key - Concatenation of node id + / + network id
+ * @return DownlinkDataNotification or null if it could not be successfully decoded
+ */
+ private static DownlinkDataNotification processDDN(byte[] buf, String key) {
+ DownlinkDataNotification ddnB = new DefaultDownlinkDataNotification();
+ ddnB.sessionId(checkSessionId(toBigInt(buf, 2)));
+ ddnB.notificationMessageType(DOWNLINK_DATA_NOTIFICATION_STRING);
+ ddnB.clientId(ClientIdentifier.of(FpcIdentity.of(FpcIdentityUnion.of(fromIntToLong(buf, 10)))));
+ ddnB.opId(OpIdentifier.of(BigInteger.valueOf(fromIntToLong(buf, 14))));
+ ddnB.notificationDpnId(uplinkDpnMap.get(key));
+ return ddnB;
+ }
+
+ /**
+ * Decodes a DPN message.
+ *
+ * @param buf - message buffer
+ * @return - A pair with the DPN Id and decoded Object
+ */
+ public static Map.Entry<FpcDpnId, Object> decode(byte[] buf) {
+ if (buf[1] == DPN_REPLY) {
+ return null;
+ } else if (buf[1] == DOWNLINK_DATA_NOTIFICATION) {
+ short nodeIdLen = buf[18];
+ short networkIdLen = buf[19 + nodeIdLen];
+ String key = new String(Arrays.copyOfRange(buf, 19, 19 + nodeIdLen)) + "/" + new String(Arrays.copyOfRange(buf, 20 + nodeIdLen, 20 + nodeIdLen + networkIdLen));
+ return uplinkDpnMap.get(key) == null ? null : new AbstractMap.SimpleEntry<>(uplinkDpnMap.get(key), processDDN(buf, key));
+ } else if (buf[1] == DPN_STATUS_INDICATION) {
+ DPNStatusIndication.Status status = null;
+
+ short nodeIdLen = buf[8];
+ short networkIdLen = buf[9 + nodeIdLen];
+ String key = new String(Arrays.copyOfRange(buf, 9, 9 + nodeIdLen)) + "/" + new String(Arrays.copyOfRange(buf, 10 + nodeIdLen, 10 + nodeIdLen + networkIdLen));
+ if (buf[3] == DPN_OVERLOAD_INDICATION) {
+ status = DPNStatusIndication.Status.OVERLOAD_INDICATION;
+ } else if (buf[3] == DPN_HELLO) {
+ status = DPNStatusIndication.Status.HELLO;
+ log.info("Hello {} on topic {}", key, buf[2]);
+ nodeToTopicMap.put(key, (short) buf[2]);
+ } else if (buf[3] == DPN_BYE) {
+ status = DPNStatusIndication.Status.BYE;
+ log.info("Bye {}", key);
+ nodeToTopicMap.remove(key);
+ }
+ return new AbstractMap.SimpleEntry<>(uplinkDpnMap.get(key), new DPNStatusIndication(status, key));
+ }
+ return null;
+ }
+
+ /**
+ * Gets the mapping for node id / network id to ZMQ Topic
+ *
+ * @param Key - Concatenation of node id + / + network id
+ * @return - ZMQ Topic
+ */
+ public static Short getTopicFromNode(String Key) {
+ return nodeToTopicMap.get(Key);
+ }
+
+ /**
+ * Provides basic status changes,
+ */
+ public static class DPNStatusIndication {
+ private final Status status;
+ private final String key; //nodeId +"/"+ networkId
+ /**
+ * Node Reference of the DPN
+ */
+ public Short nodeRef;
+
+ /**
+ * Constructor providing the DPN and its associated Status.
+ *
+ * @param status - DPN Status
+ * @param key - Combination of node id and network id
+ */
+ public DPNStatusIndication(Status status,
+ String key) {
+ this.status = status;
+ this.key = key;
+ }
+
+ /**
+ * Provides DPN Status
+ *
+ * @return Status associated to the DPN.
+ */
+ public Status getStatus() {
+ return status;
+ }
+
+ /**
+ * Provides the DPN key - nodeId +"/"+ networkId
+ *
+ * @return FpcDpnId
+ */
+ public String getKey() {
+ return this.key;
+ }
+
+ /**
+ * Basic DPN Status
+ */
+ public enum Status {
+ HELLO,
+ BYE,
+ OVERLOAD_INDICATION
+ }
+ }
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/TenantManager.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/TenantManager.java
new file mode 100644
index 0000000..8b72165
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/TenantManager.java
@@ -0,0 +1,683 @@
+package org.onosproject.fpcagent;
+
+import com.google.common.collect.Maps;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.exception.ExceptionUtils;
+import org.apache.felix.scr.annotations.*;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.Ip4Prefix;
+import org.onlab.util.AbstractAccumulator;
+import org.onlab.util.Accumulator;
+import org.onosproject.config.DynamicConfigEvent;
+import org.onosproject.config.DynamicConfigListener;
+import org.onosproject.config.DynamicConfigService;
+import org.onosproject.config.Filter;
+import org.onosproject.fpcagent.helpers.DpnCommunicationService;
+import org.onosproject.fpcagent.helpers.DpnNgicCommunicator;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.IetfDmmFpcagentOpParam;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.*;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.configure.DefaultConfigureOutput;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.instructions.instructions.instrtype.Instr3GppMob;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.opinput.opbody.CreateOrUpdate;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.opinput.opbody.DeleteOrQuery;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.payload.Contexts;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.result.ResultEnum;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.resultbody.resulttype.DefaultCommonSuccess;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.resultbody.resulttype.DefaultDeleteSuccess;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.resultbody.resulttype.DefaultErr;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.tenants.DefaultTenant;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.tenants.Tenant;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.tenants.tenant.DefaultFpcMobility;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.tenants.tenant.DefaultFpcPolicy;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.tenants.tenant.DefaultFpcTopology;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.FpcIdentity;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.fpccontext.Dpns;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.mobilityinfo.mobprofileparameters.ThreegppTunnel;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.targetsvalue.Targets;
+import org.onosproject.yang.gen.v1.ietfdmmthreegpp.rev20160803.ietfdmmthreegpp.threegppinstr.Bits;
+import org.onosproject.yang.model.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigInteger;
+import java.util.*;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onosproject.fpcagent.FpcUtil.*;
+import static org.onosproject.fpcagent.helpers.Converter.convertContext;
+import static org.onosproject.fpcagent.helpers.Converter.getFpcIdentity;
+
+@Component(immediate = true)
+@Service
+public class TenantManager implements TenantService {
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ private final IetfDmmFpcagentOpParam fpcAgentData = new IetfDmmFpcagentOpParam();
+
+ private final Map<ClientIdentifier, Tenant> clientIdMap = Maps.newHashMap();
+
+ private final InternalConfigListener listener = new InternalConfigListener();
+
+ private final Accumulator<DynamicConfigEvent> accumulator = new InternalEventAccumulator();
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ private ModelConverter modelConverter;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ private DynamicConfigService dynamicConfigService;
+
+ private DpnCommunicationService dpnCommunicationService;
+
+ @Activate
+ protected void activate() {
+ dpnCommunicationService = new DpnNgicCommunicator();
+
+ dynamicConfigService.addListener(listener);
+
+ // Create the Default Tenant on activate
+ DefaultTenants tenants = new DefaultTenants();
+
+ DefaultTenant tenant = new DefaultTenant();
+ tenant.tenantId(getFpcIdentity.apply("default"));
+
+ tenant.fpcTopology(new DefaultFpcTopology());
+
+ tenant.fpcPolicy(new DefaultFpcPolicy());
+
+ tenant.fpcMobility(new DefaultFpcMobility());
+
+ tenants.addToTenant(tenant);
+
+ DefaultFpcAgentInfo fpcAgentInfo = new DefaultFpcAgentInfo();
+
+ fpcAgentData.tenants(tenants);
+ fpcAgentData.fpcAgentInfo(fpcAgentInfo);
+
+ createNode(tenants);
+ createNode(fpcAgentInfo);
+
+ log.info("Tenant Service Started");
+ }
+
+ @Deactivate
+ protected void deactivate() {
+ dynamicConfigService.removeListener(listener);
+ log.info("Tenant Service Stopped");
+ }
+
+ @Override
+ public Optional<Tenant> getDefaultTenant() {
+ return fpcAgentData.tenants().tenant().stream()
+ .filter(tenant -> tenant.tenantId().equals(getFpcIdentity.apply("default")))
+ .findFirst();
+ }
+
+ @Override
+ public Optional<DefaultTenants> getTenants() {
+ if (fpcAgentData.tenants() instanceof DefaultTenants) {
+ return Optional.ofNullable((DefaultTenants) fpcAgentData.tenants());
+ }
+ return Optional.empty();
+ }
+
+ public Optional<Tenant> getTenant(FpcIdentity tenantId) {
+ return fpcAgentData.tenants().tenant().stream()
+ .filter(tenant -> tenant.tenantId().equals(tenantId))
+ .findFirst();
+ }
+
+ public Optional<Tenant> getTenant(ClientIdentifier clientId) {
+ return Optional.ofNullable(clientIdMap.get(clientId));
+ }
+
+ public Optional<Tenant> registerClient(ClientIdentifier clientId, FpcIdentity tenantId) {
+ return getTenant(tenantId).map(tenant -> clientIdMap.put(clientId, tenant));
+ }
+
+ public Optional<Tenant> deregisterClient(ClientIdentifier clientId) {
+ return Optional.ofNullable(clientIdMap.remove(clientId));
+ }
+
+ private ResourceData getResourceData(DataNode dataNode, ResourceId resId) {
+ if (resId != null) {
+ return DefaultResourceData.builder()
+ .addDataNode(dataNode)
+ .resourceId(resId)
+ .build();
+ } else {
+ return DefaultResourceData.builder()
+ .addDataNode(dataNode)
+ .build();
+ }
+ }
+
+ public List<ModelObject> getModelObjects(DataNode dataNode, ResourceId resourceId) {
+ ResourceData data = getResourceData(dataNode, resourceId);
+ ModelObjectData modelData = modelConverter.createModel(data);
+ return modelData.modelObjects();
+ }
+
+ public void createNode(InnerModelObject innerModelObject) {
+ ResourceData dataNode = modelConverter.createDataNode(
+ DefaultModelObjectData.builder()
+ .addModelObject(innerModelObject)
+ .build()
+ );
+ dataNode.dataNodes().forEach(
+ node -> dynamicConfigService.createNode(dataNode.resourceId(), node)
+ );
+ }
+
+ public void updateNode(InnerModelObject innerModelObject) {
+ ResourceData dataNode = modelConverter.createDataNode(
+ DefaultModelObjectData.builder()
+ .addModelObject(innerModelObject)
+ .build()
+ );
+ dataNode.dataNodes().forEach(
+ node -> dynamicConfigService.updateNode(dataNode.resourceId(), node)
+ );
+ }
+
+ public DefaultConfigureOutput configureCreate(
+ CreateOrUpdate create,
+ ClientIdentifier clientId,
+ OpIdentifier operationId
+ ) {
+ DefaultConfigureOutput configureOutput = new DefaultConfigureOutput();
+ Collection<Callable<Object>> tasks = new ArrayList<>();
+ DefaultCommonSuccess defaultCommonSuccess = new DefaultCommonSuccess();
+ try {
+ for (Contexts context : create.contexts()) {
+ defaultCommonSuccess.addToContexts(context);
+
+ if (getDefaultTenant().map(
+ tenant -> tenant.fpcMobility().contexts() != null && tenant.fpcMobility()
+ .contexts()
+ .stream()
+ .anyMatch(contexts -> contexts.contextId().equals(context.contextId()))
+ ).orElse(false)) {
+ throw new IllegalStateException("Context already exists.");
+ }
+
+ for (Dpns dpn : context.dpns()) {
+ if (getDefaultTenant().map(
+ tenant -> tenant.fpcTopology().dpns() == null ||
+ tenant.fpcTopology().dpns().stream()
+ .noneMatch(dpns -> dpns.dpnId().equals(dpn.dpnId()))
+ ).orElse(false)) {
+ throw new IllegalStateException("DPN ID is not registered to the topology.");
+ }
+
+ if (context.instructions().instrType() instanceof Instr3GppMob) {
+ Instr3GppMob instr3GppMob = (Instr3GppMob) context.instructions().instrType();
+ String commands = Bits.toString(instr3GppMob.instr3GppMob().bits());
+
+ Ip4Address ulLocalAddress = Ip4Address.valueOf(context.ul().tunnelLocalAddress().toString()),
+ dlRemoteAddress = Ip4Address.valueOf(context.dl().tunnelRemoteAddress().toString());
+
+ long s1u_sgw_gtpu_teid, s1u_enb_gtpu_teid,
+ cId = clientId.fpcIdentity().union().int64(),
+ contextId = context.contextId().fpcIdentity().union().int64();
+
+ BigInteger opId = operationId.uint64(),
+ imsi = context.imsi().uint64();
+
+ short ebi = context.ebi().uint8(),
+ lbi = context.lbi().uint8();
+
+ Optional<String> key = getDefaultTenant().flatMap(tenant ->
+ tenant.fpcTopology()
+ .dpns()
+ .stream()
+ .filter(dpns -> dpns.dpnId().equals(dpn.dpnId()))
+ .findFirst().map(node -> node.nodeId() + "/" + node.networkId())
+ );
+
+ if (key.isPresent()) {
+ Short dpnTopic = FpcUtil.getTopicFromNode(key.get());
+
+ if (dpnTopic != null) {
+ if (context.ul().mobilityTunnelParameters().mobprofileParameters() instanceof ThreegppTunnel) {
+ s1u_sgw_gtpu_teid = ((ThreegppTunnel) context.ul().mobilityTunnelParameters().mobprofileParameters()).tunnelIdentifier();
+ } else {
+ throw new IllegalArgumentException("mobprofileParameters are not instance of ThreegppTunnel");
+ }
+ if (context.dl().mobilityTunnelParameters().mobprofileParameters() instanceof ThreegppTunnel) {
+ s1u_enb_gtpu_teid = ((ThreegppTunnel) context.dl().mobilityTunnelParameters().mobprofileParameters()).tunnelIdentifier();
+ } else {
+ throw new IllegalArgumentException("mobprofileParameters are not instance of ThreegppTunnel");
+ }
+
+
+ if (commands.contains("session")) {
+ tasks.add(Executors.callable(() -> {
+ dpnCommunicationService.create_session(
+ dpnTopic,
+ imsi,
+ Ip4Prefix.valueOf(context.delegatingIpPrefixes().get(0).toString()).address(),
+ ebi,
+ ulLocalAddress,
+ s1u_sgw_gtpu_teid,
+ cId,
+ opId,
+ contextId
+ );
+
+ getDefaultTenant().ifPresent(
+ tenant -> tenant.fpcMobility().addToContexts(convertContext(context))
+ );
+ }));
+
+ if (commands.contains("downlink")) {
+ tasks.add(Executors.callable(() -> {
+ dpnCommunicationService.modify_bearer_dl(
+ dpnTopic,
+ dlRemoteAddress,
+ s1u_enb_gtpu_teid,
+ s1u_sgw_gtpu_teid,
+ cId,
+ opId
+ );
+
+ getDefaultTenant().ifPresent(
+ tenant -> tenant.fpcMobility().addToContexts(convertContext(context))
+ );
+ }));
+ }
+ } else if (commands.contains("indirect-forward")) {
+ // TODO - Modify API for Indirect Forwarding to/from another SGW
+ } else if (commands.contains("uplink")) {
+ tasks.add(Executors.callable(() -> {
+ dpnCommunicationService.create_bearer_ul(
+ dpnTopic,
+ imsi,
+ lbi,
+ ebi,
+ ulLocalAddress,
+ s1u_sgw_gtpu_teid
+ );
+
+ getDefaultTenant().ifPresent(
+ tenant -> tenant.fpcMobility().addToContexts(convertContext(context))
+ );
+ }));
+ }
+ } else {
+ throw new IllegalArgumentException("Could not find Topic ID");
+ }
+ } else {
+ throw new IllegalArgumentException("DPN does not have node and network ID defined.");
+ }
+ }
+ }
+ }
+
+ ExecutorService executor = Executors.newWorkStealingPool();
+ executor.invokeAll(tasks).forEach(
+ future -> {
+ try {
+ future.get();
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ );
+
+ configureOutput.resultType(defaultCommonSuccess);
+ configureOutput.result(Result.of(ResultEnum.OK));
+ } catch (Exception e) {
+ log.error(ExceptionUtils.getFullStackTrace(e));
+ DefaultErr defaultErr = new DefaultErr();
+ configureOutput.resultType(defaultErr);
+ defaultErr.errorInfo(ExceptionUtils.getFullStackTrace(e));
+ defaultErr.errorTypeId(ErrorTypeId.of(0));
+ }
+
+ return configureOutput;
+ }
+
+ public DefaultConfigureOutput configureUpdate(
+ CreateOrUpdate update,
+ ClientIdentifier clientId,
+ OpIdentifier operationId
+ ) {
+ DefaultConfigureOutput configureOutput = new DefaultConfigureOutput();
+ Collection<Callable<Object>> tasks = new ArrayList<>();
+
+ try {
+ DefaultCommonSuccess defaultCommonSuccess = new DefaultCommonSuccess();
+ for (Contexts context : update.contexts()) {
+ defaultCommonSuccess.addToContexts(context);
+
+ if (getDefaultTenant().map(
+ tenant -> tenant.fpcMobility().contexts() == null ||
+ tenant.fpcMobility()
+ .contexts()
+ .parallelStream()
+ .noneMatch(contexts -> contexts.contextId().equals(context.contextId()))
+ ).orElse(false)) {
+ throw new IllegalStateException("Context doesn't exist.");
+ }
+
+ for (Dpns dpn : context.dpns()) {
+ if (getDefaultTenant().map(
+ tenant -> tenant.fpcTopology().dpns() == null ||
+ tenant.fpcTopology().dpns()
+ .stream()
+ .noneMatch(dpns -> dpns.dpnId().equals(dpn.dpnId()))
+ ).orElse(false)) {
+ throw new IllegalStateException("DPN ID is not registered to the topology.");
+ }
+
+ if (context.instructions().instrType() instanceof Instr3GppMob) {
+ Instr3GppMob instr3GppMob = (Instr3GppMob) context.instructions().instrType();
+ String commands = Bits.toString(instr3GppMob.instr3GppMob().bits());
+
+ Ip4Address ulLocalAddress = Ip4Address.valueOf(context.ul().tunnelLocalAddress().toString()),
+ dlRemoteAddress = Ip4Address.valueOf(context.dl().tunnelRemoteAddress().toString()),
+ dlLocalAddress = Ip4Address.valueOf(context.dl().tunnelLocalAddress().toString());
+
+ long s1u_sgw_gtpu_teid, s1u_enb_gtpu_teid,
+ cId = clientId.fpcIdentity().union().int64(),
+ contextId = context.contextId().fpcIdentity().union().int64();
+
+ BigInteger opId = operationId.uint64();
+
+ Optional<String> key = getDefaultTenant().flatMap(tenant ->
+ tenant.fpcTopology()
+ .dpns()
+ .stream()
+ .filter(dpns -> dpns.dpnId().equals(dpn.dpnId()))
+ .findFirst().map(node -> node.nodeId() + "/" + node.networkId())
+ );
+
+ if (key.isPresent()) {
+ Short dpnTopic = FpcUtil.getTopicFromNode(key.get());
+
+ if (dpnTopic != null) {
+ if (context.ul().mobilityTunnelParameters().mobprofileParameters() instanceof ThreegppTunnel) {
+ s1u_sgw_gtpu_teid = ((ThreegppTunnel) context.ul().mobilityTunnelParameters().mobprofileParameters()).tunnelIdentifier();
+ } else {
+ throw new IllegalArgumentException("mobprofileParameters are not instance of ThreegppTunnel");
+ }
+ if (context.dl().mobilityTunnelParameters().mobprofileParameters() instanceof ThreegppTunnel) {
+ s1u_enb_gtpu_teid = ((ThreegppTunnel) context.dl().mobilityTunnelParameters().mobprofileParameters()).tunnelIdentifier();
+ } else {
+ throw new IllegalArgumentException("mobprofileParameters are not instance of ThreegppTunnel");
+ }
+
+ if (commands.contains("downlink")) {
+ if (context.dl().lifetime() >= 0L) {
+ tasks.add(Executors.callable(() ->
+ dpnCommunicationService.modify_bearer_dl(
+ dpnTopic,
+ dlRemoteAddress,
+ s1u_enb_gtpu_teid,
+ dlLocalAddress,
+ contextId,
+ cId,
+ opId
+ )
+ ));
+ } else {
+ tasks.add(Executors.callable(() ->
+ dpnCommunicationService.delete_bearer(
+ dpnTopic,
+ s1u_enb_gtpu_teid
+ )
+ ));
+ }
+ }
+ if (commands.contains("uplink")) {
+ if (context.ul().lifetime() >= 0L) {
+ tasks.add(Executors.callable(() ->
+ dpnCommunicationService.modify_bearer_ul(
+ dpnTopic,
+ ulLocalAddress,
+ s1u_enb_gtpu_teid,
+ s1u_sgw_gtpu_teid
+ )
+ ));
+ } else {
+ tasks.add(Executors.callable(() ->
+ dpnCommunicationService.delete_bearer(
+ dpnTopic,
+ s1u_sgw_gtpu_teid
+ )
+ ));
+ }
+ }
+ } else {
+ throw new IllegalArgumentException("Could not find Topic ID");
+ }
+ } else {
+ throw new IllegalArgumentException("DPN does not have node and network ID defined.");
+ }
+ }
+ }
+ }
+
+ ExecutorService executor = Executors.newWorkStealingPool();
+ executor.invokeAll(tasks).forEach(
+ future -> {
+ try {
+ future.get();
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ );
+
+ configureOutput.resultType(defaultCommonSuccess);
+ configureOutput.result(Result.of(ResultEnum.OK));
+
+ update.contexts().forEach(
+ contexts -> getDefaultTenant().ifPresent(
+ tenant -> tenant.fpcMobility().addToContexts(convertContext(contexts))
+ )
+ );
+ } catch (Exception e) {
+ log.error(ExceptionUtils.getFullStackTrace(e));
+ DefaultErr defaultErr = new DefaultErr();
+ defaultErr.errorInfo(ExceptionUtils.getFullStackTrace(e));
+ defaultErr.errorTypeId(ErrorTypeId.of(0));
+ configureOutput.resultType(defaultErr);
+ configureOutput.result(Result.of(ResultEnum.ERR));
+ }
+
+ return configureOutput;
+ }
+
+ public DefaultConfigureOutput configureDelete(
+ DeleteOrQuery delete,
+ ClientIdentifier clientId,
+ OpIdentifier operationId
+ ) {
+ DefaultConfigureOutput configureOutput = new DefaultConfigureOutput();
+ Collection<Callable<Object>> tasks = new ArrayList<>();
+ DefaultDeleteSuccess defaultDeleteSuccess = new DefaultDeleteSuccess();
+ try {
+ for (Targets target : delete.targets()) {
+ defaultDeleteSuccess.addToTargets(target);
+ String targetStr = target.target().toString(),
+ s = StringUtils.substringBetween(targetStr, "contexts=", "/"),
+ trgt = s != null ? s : StringUtils.substringAfter(targetStr, "contexts=");
+
+ getDefaultTenant().map(
+ tenant -> {
+ if (tenant.fpcMobility().contexts() != null) {
+ return tenant.fpcMobility()
+ .contexts()
+ .stream()
+ .filter(contexts -> contexts.contextId().toString().equals(trgt))
+ .findFirst()
+ .orElseThrow(
+ () -> new IllegalArgumentException("Context doesn't exist.")
+ );
+ }
+ throw new IllegalArgumentException("Contexts are empty.");
+ }
+ ).ifPresent(
+ context -> context.dpns().forEach(
+ dpn -> {
+ Optional<String> key = getDefaultTenant().flatMap(tenant ->
+ tenant.fpcTopology()
+ .dpns()
+ .stream()
+ .filter(dpns -> dpns.dpnId().equals(dpn.dpnId()))
+ .findFirst().map(node -> node.nodeId() + "/" + node.networkId())
+ );
+
+ if (key.isPresent()) {
+ Short dpnTopic = FpcUtil.getTopicFromNode(key.get());
+
+ if (dpnTopic != null) {
+ Long teid;
+ if (context.ul().mobilityTunnelParameters().mobprofileParameters() instanceof ThreegppTunnel) {
+ teid = ((ThreegppTunnel) context.ul().mobilityTunnelParameters().mobprofileParameters()).tunnelIdentifier();
+ } else {
+ throw new IllegalArgumentException("mobprofileParameters are not instance of ThreegppTunnel");
+ }
+
+ long cId = clientId.fpcIdentity().union().int64();
+ BigInteger opId = operationId.uint64();
+
+ if (targetStr.endsWith("ul") || targetStr.endsWith("dl")) {
+ tasks.add(Executors.callable(() -> {
+ dpnCommunicationService.delete_bearer(
+ dpnTopic,
+ teid
+ );
+
+ context.dl(null);
+ context.ul(null);
+ }));
+ } else {
+ tasks.add(Executors.callable(() -> {
+ dpnCommunicationService.delete_session(
+ dpnTopic,
+ context.lbi().uint8(),
+ teid,
+ cId,
+ opId,
+ context.contextId().fpcIdentity().union().int64()
+ );
+
+ getDefaultTenant().ifPresent(
+ tenant -> tenant.fpcMobility()
+ .contexts()
+ .remove(context)
+ );
+ }));
+ }
+
+ } else {
+ throw new IllegalArgumentException("Could not find Topic ID");
+ }
+ } else {
+ throw new IllegalArgumentException("DPN does not have node and network ID defined.");
+ }
+ }
+ )
+ );
+
+ }
+
+ ExecutorService executor = Executors.newWorkStealingPool();
+ executor.invokeAll(tasks).forEach(
+ future -> {
+ try {
+ future.get();
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ );
+
+ configureOutput.resultType(defaultDeleteSuccess);
+ configureOutput.result(Result.of(ResultEnum.OK));
+
+ } catch (Exception e) {
+ log.error(ExceptionUtils.getFullStackTrace(e));
+ DefaultErr defaultErr = new DefaultErr();
+ configureOutput.resultType(defaultErr);
+ defaultErr.errorInfo(ExceptionUtils.getFullStackTrace(e));
+ defaultErr.errorTypeId(ErrorTypeId.of(0));
+ }
+
+ return configureOutput;
+ }
+
+ /**
+ * Accumulates events to allow processing after a desired number of
+ * events were accumulated.
+ */
+ private class InternalEventAccumulator extends AbstractAccumulator<DynamicConfigEvent> {
+
+ /**
+ * Constructs the event accumulator with timer and event limit.
+ */
+ private InternalEventAccumulator() {
+ super(new Timer(TIMER), MAX_EVENTS, MAX_BATCH_MS, MAX_IDLE_MS);
+ }
+
+ @Override
+ public void processItems(List<DynamicConfigEvent> events) {
+ events.forEach(
+ event -> {
+ checkNotNull(event, EVENT_NULL);
+ switch (event.type()) {
+ case NODE_ADDED:
+ case NODE_DELETED:
+ Filter filter = Filter.builder().build();
+ DataNode node = dynamicConfigService.readNode(tenantsResourceId, filter);
+ getModelObjects(node, null).forEach(
+ modelObject -> fpcAgentData.tenants((DefaultTenants) modelObject)
+ );
+ break;
+ case NODE_UPDATED:
+ case NODE_REPLACED:
+ break;
+ default:
+ log.warn(UNKNOWN_EVENT, event.type());
+ break;
+ }
+ }
+ );
+ }
+
+ }
+
+ /**
+ * Representation of internal listener, listening for dynamic config event.
+ */
+ private class InternalConfigListener implements DynamicConfigListener {
+ /**
+ * Returns true if the event resource id points to the root level node
+ * only and event is for addition and deletion; false otherwise.
+ *
+ * @param event config event
+ * @return true if event is supported; false otherwise
+ */
+ private boolean isSupported(DynamicConfigEvent event) {
+ ResourceId rsId = event.subject();
+ List<NodeKey> storeKeys = rsId.nodeKeys();
+ List<NodeKey> tenantKeys = tenantsResourceId.nodeKeys();
+ return storeKeys.size() >= 2 && storeKeys.get(0).equals(tenantKeys.get(1));
+ }
+
+ @Override
+ public boolean isRelevant(DynamicConfigEvent event) {
+ return isSupported(event);
+ }
+
+ @Override
+ public void event(DynamicConfigEvent event) {
+ accumulator.add(event);
+ }
+ }
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/TenantService.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/TenantService.java
new file mode 100644
index 0000000..4b88510
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/TenantService.java
@@ -0,0 +1,57 @@
+package org.onosproject.fpcagent;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.ClientIdentifier;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.DefaultTenants;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.OpIdentifier;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.configure.DefaultConfigureOutput;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.opinput.opbody.CreateOrUpdate;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.opinput.opbody.DeleteOrQuery;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.tenants.Tenant;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.FpcIdentity;
+import org.onosproject.yang.model.DataNode;
+import org.onosproject.yang.model.InnerModelObject;
+import org.onosproject.yang.model.ModelObject;
+import org.onosproject.yang.model.ResourceId;
+
+import java.util.List;
+import java.util.Optional;
+
+@Beta
+public interface TenantService {
+ Optional<DefaultTenants> getTenants();
+
+ void createNode(InnerModelObject innerModelObject);
+
+ void updateNode(InnerModelObject innerModelObject);
+
+ List<ModelObject> getModelObjects(DataNode dataNode, ResourceId appId);
+
+ Optional<Tenant> getDefaultTenant();
+
+ Optional<Tenant> getTenant(FpcIdentity tenantId);
+
+ Optional<Tenant> getTenant(ClientIdentifier clientId);
+
+ Optional<Tenant> registerClient(ClientIdentifier clientId, FpcIdentity tenantId);
+
+ Optional<Tenant> deregisterClient(ClientIdentifier clientId);
+
+ DefaultConfigureOutput configureCreate(
+ CreateOrUpdate create,
+ ClientIdentifier clientId,
+ OpIdentifier operationId
+ );
+
+ DefaultConfigureOutput configureUpdate(
+ CreateOrUpdate create,
+ ClientIdentifier clientId,
+ OpIdentifier operationId
+ );
+
+ DefaultConfigureOutput configureDelete(
+ DeleteOrQuery delete,
+ ClientIdentifier clientId,
+ OpIdentifier operationId
+ );
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/helpers/ConfigHelper.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/helpers/ConfigHelper.java
new file mode 100644
index 0000000..5a91d52
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/helpers/ConfigHelper.java
@@ -0,0 +1,315 @@
+package org.onosproject.fpcagent.helpers;
+
+import com.fasterxml.jackson.annotation.*;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonPropertyOrder({
+ "monitor-threads",
+ "scheduled-monitors-poolsize",
+ "dpn-subscriber-uri",
+ "dpn-listener-id",
+ "dpn-publisher-uri",
+ "dpn-client-threads",
+ "metricsupdate-ms",
+ "mobilityupdate-ms",
+ "activation-threads",
+ "target-read-limit",
+ "http-notifier-clients",
+ "zmq-nbi-server-poolsize",
+ "zmq-nbi-server-uri",
+ "zmq-nbi-inproc-uri",
+ "zmq-nbi-handler-poolsize",
+ "http-nio2-nb-poolsize",
+ "http-nio2-nb-port",
+ "node-id",
+ "network-id",
+ "zmq-broadcast-controllers",
+ "zmq-broadcast-dpns",
+ "zmq-broadcast-all"
+})
+public class ConfigHelper {
+ @JsonProperty("monitor-threads")
+ private Integer monitorThreads;
+ @JsonProperty("scheduled-monitors-poolsize")
+ private Integer scheduledMonitorsPoolsize;
+ @JsonProperty("dpn-subscriber-uri")
+ private String dpnSubscriberUri;
+ @JsonProperty("dpn-listener-id")
+ private Integer dpnListenerId;
+ @JsonProperty("dpn-publisher-uri")
+ private String dpnPublisherUri;
+ @JsonProperty("dpn-client-threads")
+ private Integer dpnClientThreads;
+ @JsonProperty("metricsupdate-ms")
+ private Integer metricsupdateMs;
+ @JsonProperty("mobilityupdate-ms")
+ private Integer mobilityupdateMs;
+ @JsonProperty("activation-threads")
+ private Integer activationThreads;
+ @JsonProperty("target-read-limit")
+ private Integer targetReadLimit;
+ @JsonProperty("http-notifier-clients")
+ private Integer httpNotifierClients;
+ @JsonProperty("zmq-nbi-server-poolsize")
+ private Integer zmqNbiServerPoolsize;
+ @JsonProperty("zmq-nbi-server-uri")
+ private String zmqNbiServerUri;
+ @JsonProperty("zmq-nbi-inproc-uri")
+ private String zmqNbiInprocUri;
+ @JsonProperty("zmq-nbi-handler-poolsize")
+ private Integer zmqNbiHandlerPoolsize;
+ @JsonProperty("http-nio2-nb-poolsize")
+ private Integer httpNio2NbPoolsize;
+ @JsonProperty("http-nio2-nb-port")
+ private Integer httpNio2NbPort;
+ @JsonProperty("node-id")
+ private String nodeId;
+ @JsonProperty("network-id")
+ private String networkId;
+ @JsonProperty("zmq-broadcast-controllers")
+ private String zmqBroadcastControllers;
+ @JsonProperty("zmq-broadcast-dpns")
+ private String zmqBroadcastDpns;
+ @JsonProperty("zmq-broadcast-all")
+ private String zmqBroadcastAll;
+ @JsonIgnore
+ private Map<String, Object> additionalProperties = new HashMap<>();
+
+ /**
+ * No args constructor for use in serialization
+ */
+ public ConfigHelper() {
+ }
+
+
+ public Integer monitorThreads() {
+ return monitorThreads;
+ }
+
+
+ public void setMonitorThreads(Integer monitorThreads) {
+ this.monitorThreads = monitorThreads;
+ }
+
+
+ public Integer scheduledMonitorsPoolsize() {
+ return scheduledMonitorsPoolsize;
+ }
+
+
+ public void setScheduledMonitorsPoolsize(Integer scheduledMonitorsPoolsize) {
+ this.scheduledMonitorsPoolsize = scheduledMonitorsPoolsize;
+ }
+
+
+ public String dpnSubscriberUri() {
+ return dpnSubscriberUri;
+ }
+
+
+ public void setDpnSubscriberUri(String dpnSubscriberUri) {
+ this.dpnSubscriberUri = dpnSubscriberUri;
+ }
+
+
+ public Integer dpnListenerId() {
+ return dpnListenerId;
+ }
+
+
+ public void setDpnListenerId(Integer dpnListenerId) {
+ this.dpnListenerId = dpnListenerId;
+ }
+
+
+ public String dpnPublisherUri() {
+ return dpnPublisherUri;
+ }
+
+ public void setDpnPublisherUri(String dpnPublisherUri) {
+ this.dpnPublisherUri = dpnPublisherUri;
+ }
+
+
+ public Integer dpnClientThreads() {
+ return dpnClientThreads;
+ }
+
+
+ public void setDpnClientThreads(Integer dpnClientThreads) {
+ this.dpnClientThreads = dpnClientThreads;
+ }
+
+
+ public Integer metricUpdateMs() {
+ return metricsupdateMs;
+ }
+
+
+ public void setMetricsupdateMs(Integer metricsupdateMs) {
+ this.metricsupdateMs = metricsupdateMs;
+ }
+
+
+ public Integer mobilityUpdateMs() {
+ return mobilityupdateMs;
+ }
+
+
+ public void setMobilityupdateMs(Integer mobilityupdateMs) {
+ this.mobilityupdateMs = mobilityupdateMs;
+ }
+
+
+ public Integer activationThreads() {
+ return activationThreads;
+ }
+
+
+ public void setActivationThreads(Integer activationThreads) {
+ this.activationThreads = activationThreads;
+ }
+
+
+ public Integer targetReadLimit() {
+ return targetReadLimit;
+ }
+
+
+ public void setTargetReadLimit(Integer targetReadLimit) {
+ this.targetReadLimit = targetReadLimit;
+ }
+
+
+ public Integer httpNotifierClients() {
+ return httpNotifierClients;
+ }
+
+
+ public void setHttpNotifierClients(Integer httpNotifierClients) {
+ this.httpNotifierClients = httpNotifierClients;
+ }
+
+
+ public Integer zmqServerPoolsize() {
+ return zmqNbiServerPoolsize;
+ }
+
+
+ public void setZmqNbiServerPoolsize(Integer zmqNbiServerPoolsize) {
+ this.zmqNbiServerPoolsize = zmqNbiServerPoolsize;
+ }
+
+
+ public String zmqServerUri() {
+ return zmqNbiServerUri;
+ }
+
+
+ public void setZmqNbiServerUri(String zmqNbiServerUri) {
+ this.zmqNbiServerUri = zmqNbiServerUri;
+ }
+
+
+ public String zmqInprocUri() {
+ return zmqNbiInprocUri;
+ }
+
+
+ public void setZmqNbiInprocUri(String zmqNbiInprocUri) {
+ this.zmqNbiInprocUri = zmqNbiInprocUri;
+ }
+
+
+ public Integer zmqHandlerPoolsize() {
+ return zmqNbiHandlerPoolsize;
+ }
+
+
+ public void setZmqNbiHandlerPoolsize(Integer zmqNbiHandlerPoolsize) {
+ this.zmqNbiHandlerPoolsize = zmqNbiHandlerPoolsize;
+ }
+
+
+ public Integer httpNio2Poolsize() {
+ return httpNio2NbPoolsize;
+ }
+
+
+ public void setHttpNio2NbPoolsize(Integer httpNio2NbPoolsize) {
+ this.httpNio2NbPoolsize = httpNio2NbPoolsize;
+ }
+
+
+ public Integer httpNio2Port() {
+ return httpNio2NbPort;
+ }
+
+
+ public void setHttpNio2NbPort(Integer httpNio2NbPort) {
+ this.httpNio2NbPort = httpNio2NbPort;
+ }
+
+
+ public String nodeId() {
+ return nodeId;
+ }
+
+
+ public void setNodeId(String node_id) {
+ this.nodeId = node_id;
+ }
+
+
+ public String networkId() {
+ return networkId;
+ }
+
+
+ public void setNetworkId(String network_id) {
+ this.networkId = network_id;
+ }
+
+
+ public String zmqBroadcastControllers() {
+ return zmqBroadcastControllers;
+ }
+
+
+ public void setZmqBroadcastControllers(String zmqBroadcastControllers) {
+ this.zmqBroadcastControllers = zmqBroadcastControllers;
+ }
+
+ public String zmqBroadcastDpns() {
+ return zmqBroadcastDpns;
+ }
+
+
+ public void setZmqBroadcastDpns(String zmqBroadcastDpns) {
+ this.zmqBroadcastDpns = zmqBroadcastDpns;
+ }
+
+
+ public String zmqBroadcastAll() {
+ return zmqBroadcastAll;
+ }
+
+
+ public void setZmqBroadcastAll(String zmqBroadcastAll) {
+ this.zmqBroadcastAll = zmqBroadcastAll;
+ }
+
+ @JsonAnyGetter
+ public Map<String, Object> getAdditionalProperties() {
+ return this.additionalProperties;
+ }
+
+ @JsonAnySetter
+ public void setAdditionalProperty(String name, Object value) {
+ this.additionalProperties.put(name, value);
+ }
+
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/helpers/Converter.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/helpers/Converter.java
new file mode 100644
index 0000000..d023cb8
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/helpers/Converter.java
@@ -0,0 +1,167 @@
+package org.onosproject.fpcagent.helpers;
+
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.ClientIdentifier;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.tenants.tenant.fpcmobility.Contexts;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.tenants.tenant.fpcmobility.DefaultContexts;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.FpcContextId;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.FpcDpnGroupId;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.FpcIdentity;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.FpcPortId;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.fpccontext.Dl;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.fpccontext.Dpns;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.fpccontext.Ul;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.fpcidentity.FpcIdentityUnion;
+import org.onosproject.yang.gen.v1.ietfdmmthreegpp.rev20160803.ietfdmmthreegpp.EbiType;
+import org.onosproject.yang.gen.v1.ietfdmmthreegpp.rev20160803.ietfdmmthreegpp.ImsiType;
+import org.onosproject.yang.gen.v1.ietfinettypes.rev20130715.ietfinettypes.IpPrefix;
+
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.List;
+import java.util.function.Function;
+
+public class Converter {
+ /**
+ * Short to Byte
+ *
+ * @param value - Short
+ * @return byte value
+ */
+ public static byte toUint8(Short value) {
+ return value.byteValue();
+ }
+
+ /**
+ * Short to byte array
+ *
+ * @param value - Short
+ * @return byte array
+ */
+ public static byte[] toUint16(Short value) {
+ return new byte[]{(byte) (value >>> 8), (byte) (value & 0xFF)};
+ }
+
+ /**
+ * Lower two bytes of an integer to byte array
+ *
+ * @param value - integer value
+ * @return byte array
+ */
+ public static byte[] toUint16(Integer value) {
+ return new byte[]{(byte) (value >>> 8), (byte) (value & 0xFF)};
+ }
+
+ /**
+ * Long to byte array.
+ *
+ * @param value - long
+ * @return byte array
+ */
+ public static byte[] toUint32(long value) {
+ return new byte[]{(byte) (value >>> 24), (byte) (value >>> 16), (byte) (value >>> 8), (byte) (value & 0xFF)};
+ }
+
+ /**
+ * BigInteger to byte array.
+ *
+ * @param value - BigInteger
+ * @return byte array
+ */
+ public static byte[] toUint64(BigInteger value) {
+ return new byte[]{value.shiftRight(56).byteValue(), value.shiftRight(48).byteValue(), value.shiftRight(40).byteValue(),
+ value.shiftRight(32).byteValue(), value.shiftRight(24).byteValue(), value.shiftRight(16).byteValue(),
+ value.shiftRight(8).byteValue(), value.and(BigInteger.valueOf(0xFF)).byteValue()};
+ }
+
+ /**
+ * Decodes a 32 bit value
+ *
+ * @param source - byte array
+ * @param offset - offset in the array where the 8 bytes begins
+ * @return integer
+ */
+ public static int toInt(byte[] source, int offset) {
+ return new BigInteger(Arrays.copyOfRange(source, offset, offset + 4)).intValue();
+ }
+
+ /**
+ * Converts a byte array to BigInteger
+ *
+ * @param source - byte array
+ * @param offset - offset in the array where the 8 bytes begins
+ * @return BigInteger representing a Uint64
+ */
+ public static BigInteger toBigInt(byte[] source, int offset) {
+ return new BigInteger(Arrays.copyOfRange(source, offset, offset + 8));
+ }
+
+ /**
+ * Converts an integer to a long (used for larger unsigned integers)
+ *
+ * @param source - message buffer (byte array)
+ * @param offset - offset in the array where the 4 bytes begins
+ * @return Long value of the unsigned integer
+ */
+ public static long fromIntToLong(byte[] source, int offset) {
+ long value = 0;
+ for (int i = offset; i < offset + 4; i++) {
+ value = (value << 8) + (source[i] & 0xff);
+ }
+ return value;
+ }
+
+ public static Function<String, FpcIdentity> getFpcIdentity = (v) -> new FpcIdentity(new FpcIdentityUnion(v));
+ public static Function<String, ClientIdentifier> getClientIdentity = (v) -> new ClientIdentifier(getFpcIdentity.apply(v));
+
+ public static Contexts convertContext(org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.payload.Contexts contexts) {
+ Contexts ctx = new DefaultContexts();
+ FpcContextId fpcContextId = contexts.contextId();
+ List<IpPrefix> ipPrefixes = contexts.delegatingIpPrefixes();
+ Dl dl = contexts.dl();
+ Ul ul = contexts.ul();
+ boolean dormant = contexts.dormant();
+ FpcDpnGroupId fpcDpnGroupId = contexts.dpnGroup();
+ List<Dpns> dpns = contexts.dpns();
+ EbiType ebi = contexts.ebi();
+ EbiType lbi = contexts.lbi();
+ ImsiType imsi = contexts.imsi();
+ FpcContextId fpcContextId1 = contexts.parentContext();
+ List<FpcPortId> ports = contexts.ports();
+
+ if (fpcContextId != null) {
+ ctx.contextId(fpcContextId);
+ }
+ if (ipPrefixes != null) {
+ ctx.delegatingIpPrefixes(ipPrefixes);
+ }
+ if (dl != null) {
+ ctx.dl(dl);
+ }
+ if (ul != null) {
+ ctx.ul(ul);
+ }
+ ctx.dormant(dormant);
+ if (fpcDpnGroupId != null) {
+ ctx.dpnGroup(fpcDpnGroupId);
+ }
+ if (dpns != null) {
+ ctx.dpns(dpns);
+ }
+ if (ebi != null) {
+ ctx.ebi(ebi);
+ }
+ if (lbi != null) {
+ ctx.lbi(lbi);
+ }
+ if (imsi != null) {
+ ctx.imsi(imsi);
+ }
+ if (fpcContextId1 != null) {
+ ctx.parentContext(fpcContextId1);
+ }
+ if (ports != null) {
+ ctx.ports(ports);
+ }
+ return ctx;
+ }
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/helpers/DpnCommunicationService.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/helpers/DpnCommunicationService.java
new file mode 100644
index 0000000..415e475
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/helpers/DpnCommunicationService.java
@@ -0,0 +1,167 @@
+/*
+ * 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.fpcagent.helpers;
+
+import org.onlab.packet.Ip4Address;
+
+import java.math.BigInteger;
+
+public interface DpnCommunicationService {
+ /**
+ * Creates Mobility Session
+ *
+ * @param topicId - DPN
+ * @param imsi - IMSI
+ * @param ue_ip - Session IP Address
+ * @param default_ebi - Default EBI
+ * @param s1u_sgw_gtpu_ipv4 - SGW GTP-U IPv4 Address
+ * @param s1u_sgw_gtpu_teid - SGW GTP-U TEID
+ * @param clientIdentifier - Client Identifier
+ * @param opIdentifier - Operation Identifier
+ * @param sessionId - Session Id
+ */
+ void create_session(
+ Short topicId,
+ BigInteger imsi,
+ Ip4Address ue_ip,
+ Short default_ebi,
+ Ip4Address s1u_sgw_gtpu_ipv4,
+ Long s1u_sgw_gtpu_teid,
+ Long clientIdentifier,
+ BigInteger opIdentifier,
+ Long sessionId
+ );
+
+ /**
+ * DeleteOrQuery Mobility Session.
+ *
+ * @param dpn - DPN
+ * @param del_default_ebi - Default EBI
+ * @param s1u_sgw_gtpu_teid - SGW GTP-U TEID
+ * @param clientIdentifier - Client Identifier
+ * @param opIdentifier - Operation Identifier
+ * @param sessionId - Session Id
+ */
+ void delete_session(
+ Short dpn,
+ Short del_default_ebi,
+ Long s1u_sgw_gtpu_teid,
+ Long clientIdentifier,
+ BigInteger opIdentifier,
+ Long sessionId
+ );
+
+ /**
+ * Create Uplink Bearer.
+ *
+ * @param dpn - DPN
+ * @param imsi - IMSI
+ * @param default_ebi - Default EBI
+ * @param dedicated_ebi - Dedicated EBI
+ * @param s1u_sgw_gtpu_ipv4 - SGW GTP-U IPv4 Address
+ * @param s1u_sgw_gtpu_teid - SGW GTP-U TEID
+ */
+ void create_bearer_ul(
+ Short dpn,
+ BigInteger imsi,
+ Short default_ebi,
+ Short dedicated_ebi,
+ Ip4Address s1u_sgw_gtpu_ipv4,
+ Long s1u_sgw_gtpu_teid
+ );
+
+ /**
+ * Create Downlink Bearer.
+ *
+ * @param dpn - DPN
+ * @param dedicated_ebi - Default EBI
+ * @param s1u_sgw_gtpu_teid - SGW GTP-U TEID
+ * @param s1u_enb_gtpu_ipv4 - ENodeB GTP-U IPv4 Address
+ * @param s1u_enb_gtpu_teid - ENodeB GTP-U TEID
+ */
+ void create_bearer_dl(
+ Short dpn,
+ Short dedicated_ebi,
+ Long s1u_sgw_gtpu_teid,
+ Ip4Address s1u_enb_gtpu_ipv4,
+ Long s1u_enb_gtpu_teid
+ );
+
+ /**
+ * Modify Downlink Bearer.
+ * @param topicId - DPN
+ * @param s1u_enodeb_ipv4 - ENodeB GTP-U IPv4 Address
+ * @param s1u_enodeb_teid - ENodeB TEID
+ * @param s1u_sgw_ipv4 - SGW GTP-U IPv4 Address
+ * @param sessionId - Session Id
+ * @param clientId - Operation Identifier
+ * @param opId - Session Id
+ */
+ void modify_bearer_dl(
+ Short topicId,
+ Ip4Address s1u_enodeb_ipv4,
+ Long s1u_enodeb_teid,
+ Ip4Address s1u_sgw_ipv4,
+ Long sessionId,
+ Long clientId,
+ BigInteger opId
+ );
+
+ /**
+ * Modify Uplink Bearer.
+ *
+ * @param dpn - DPN
+ * @param s1u_enb_gtpu_ipv4 - ENodeB GTP-U IPv4 Address
+ * @param s1u_enb_gtpu_teid - ENodeB GTP-U TEID
+ * @param s1u_sgw_gtpu_teid - SGW GTP-U TEID
+ */
+ void modify_bearer_ul(
+ Short dpn,
+ Ip4Address s1u_enb_gtpu_ipv4,
+ Long s1u_enb_gtpu_teid,
+ Long s1u_sgw_gtpu_teid
+ );
+
+ /**
+ * DeleteOrQuery Bearer.
+ *
+ * @param dpnTopic - DPN
+ * @param s1u_sgw_gtpu_teid - SGW GTP-U TEID
+ */
+ void delete_bearer(
+ Short dpnTopic,
+ Long s1u_sgw_gtpu_teid
+ );
+
+ /**
+ * Creates the byte buffer to send ADC rules over ZMQ
+ *
+ * @param topic - DPN Topic
+ * @param domain_name - domain
+ * @param ip - ipaddress/ipprefix (i.e. 127.0.0.1/32)
+ * @param drop - Drop if 1
+ * @param rating_group - Rating Group
+ * @param service_ID - Service ID
+ * @param sponsor_ID - Sponsor ID
+ */
+ void send_ADC_rules(
+ Short topic,
+ String domain_name, String ip,
+ Short drop, Long rating_group,
+ Long service_ID, String sponsor_ID
+ );
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/helpers/DpnNgicCommunicator.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/helpers/DpnNgicCommunicator.java
new file mode 100644
index 0000000..b12945c
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/helpers/DpnNgicCommunicator.java
@@ -0,0 +1,281 @@
+package org.onosproject.fpcagent.helpers;
+
+
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.Ip4Prefix;
+import org.onosproject.fpcagent.workers.ZMQSBPublisherManager;
+import org.onosproject.fpcagent.workers.ZMQSBSubscriberManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.math.BigInteger;
+import java.nio.ByteBuffer;
+
+import static org.onosproject.fpcagent.helpers.Converter.*;
+
+/**
+ * DPDK DPN API over ZeroMQ.
+ */
+public class DpnNgicCommunicator implements DpnCommunicationService {
+ protected static final Logger log = LoggerFactory.getLogger(DpnNgicCommunicator.class);
+ /**
+ * Topic for broadcasting
+ */
+ private static byte BROADCAST_TOPIC = 0b0000_0000;
+ private static byte CREATE_SESSION_TYPE = 0b0000_0001;
+ private static byte MODIFY_DL_BEARER_TYPE = 0b0000_0010;
+ private static byte DELETE_SESSION_TYPE = 0b0000_0011;
+ private static byte MODIFY_UL_BEARER_TYPE = 0b0000_0100;
+ private static byte CREATE_UL_BEARER_TYPE = 0b0000_0101;
+ private static byte CREATE_DL_BEARER_TYPE = 0b0000_0110;
+ private static byte DELETE_BEARER_TYPE = 0b0000_0110;
+ private static byte HELLO = 0b0000_1000;
+ private static byte BYE = 0b0000_1001;
+ private static byte SEND_ADC_TYPE = 0b001_0001;
+ private static byte DDN_ACK = 0b0000_0110;
+
+ enum s11MsgType {
+ CREATE_SESSION(1),
+ MODIFY_BEARER(2),
+ DELETE_SESSION(3),
+ DPN_RESPONSE(4),
+ DDN(5),
+ ASSIGN_TOPIC(10),
+ ASSIGN_CONFLICT(11),
+ DPN_STATUS_INDICATION(12),
+ DPN_STATUS_ACK(13),
+ CONTROLLER_STATUS_INDICATION(14),
+ ADC_RULE(17),
+ PCC_RULE(18),
+ METER_RULE(19),
+ SDF_RULE(20);
+
+ private byte type;
+
+ s11MsgType(int type) {
+ this.type = (byte) type;
+ }
+
+ public byte getType() {
+ return type;
+ }
+ }
+
+ @Override
+ public void create_session(
+ Short topicId,
+ BigInteger imsi,
+ Ip4Address ue_ip,
+ Short default_ebi,
+ Ip4Address s1u_sgw_gtpu_ipv4,
+ Long s1u_sgw_gtpu_teid,
+ Long clientIdentifier,
+ BigInteger opIdentifier,
+ Long sessionId
+ ) {
+ /* NGIC Create Session expected buffer:
+ value: topic_id bytes: 8
+ value: type bytes: 8
+ value: imsi bytes: 64
+ value: default_ebi bytes: 8
+ value: ue_ipv4 bytes: 32
+ value: s1u_sgw_teid bytes: 32
+ value: s1u_sgw_ipv4 bytes: 32
+ value: session_id bytes: 64
+ value: controller_topic bytes: 32
+ value: client_id bytes: 32
+ value: op_id bytes: 32
+ */
+ // TODO: check if subscriber is open.
+ ByteBuffer bb = ByteBuffer.allocate(41)
+ .put(toUint8(topicId))
+ .put(s11MsgType.CREATE_SESSION.getType())
+ .put(toUint64(imsi))
+ .put(toUint8(default_ebi))
+ .put(toUint32(ue_ip.toInt()))
+ .put(toUint32(s1u_sgw_gtpu_teid))
+ .put(toUint32(s1u_sgw_gtpu_ipv4.toInt()))
+ .put(toUint64(BigInteger.valueOf(sessionId)))
+ .put(toUint8(ZMQSBSubscriberManager.getControllerTopic()))
+ .put(toUint32(clientIdentifier))
+ .put(toUint32(opIdentifier.longValue()));
+
+ log.info("create_session: {}", bb.array());
+ ZMQSBPublisherManager.getInstance().send(bb);
+ }
+
+ @Override
+ public void delete_session(
+ Short dpn,
+ Short del_default_ebi,
+ Long s1u_sgw_gtpu_teid,
+ Long clientIdentifier,
+ BigInteger opIdentifier,
+ Long sessionId
+ ) {
+ ByteBuffer bb = ByteBuffer.allocate(19)
+ .put(toUint8(dpn))
+ .put(s11MsgType.DELETE_SESSION.getType())
+ .put(toUint64(BigInteger.valueOf(sessionId)))
+ .put(toUint8(ZMQSBSubscriberManager.getControllerTopic()))
+ .put(toUint32(clientIdentifier))
+ .put(toUint32(opIdentifier.longValue()));
+
+ log.info("delete_session: {}", bb.array());
+ ZMQSBPublisherManager.getInstance().send(bb);
+ }
+
+ @Override
+ public void create_bearer_ul(
+ Short dpn,
+ BigInteger imsi,
+ Short default_ebi,
+ Short dedicated_ebi,
+ Ip4Address s1u_sgw_gtpu_ipv4,
+ Long s1u_sgw_gtpu_teid
+ ) {
+ ByteBuffer bb = ByteBuffer.allocate(21)
+ .put(toUint8(dpn))
+ .put(CREATE_UL_BEARER_TYPE)
+ .put(toUint64(imsi))
+ .put(toUint8(default_ebi))
+ .put(toUint8(dedicated_ebi))
+ .put(toUint32(s1u_sgw_gtpu_ipv4.toInt()))
+ .put(toUint32(s1u_sgw_gtpu_teid));
+
+ log.info("create_bearer_ul: {}", bb.array());
+ ZMQSBPublisherManager.getInstance().send(bb);
+ }
+
+ @Override
+ public void create_bearer_dl(
+ Short dpn,
+ Short dedicated_ebi,
+ Long s1u_sgw_gtpu_teid,
+ Ip4Address s1u_enb_gtpu_ipv4,
+ Long s1u_enb_gtpu_teid
+ ) {
+ ByteBuffer bb = ByteBuffer.allocate(16)
+ .put(toUint8(dpn))
+ .put(CREATE_DL_BEARER_TYPE)
+ .put(toUint8(dedicated_ebi))
+ .put(toUint32(s1u_sgw_gtpu_teid))
+ .put(toUint32(s1u_enb_gtpu_ipv4.toInt()))
+ .put(toUint32(s1u_enb_gtpu_teid));
+
+ log.info("create_bearer_dl: {}", bb.array());
+ ZMQSBPublisherManager.getInstance().send(bb);
+ }
+
+ @Override
+ public void modify_bearer_dl(
+ Short topicId,
+ Ip4Address s1u_enodeb_ipv4,
+ Long s1u_enodeb_teid,
+ Ip4Address s1u_sgw_ipv4,
+ Long sessionId,
+ Long clientId,
+ BigInteger opId
+ ) {
+ /* NGIC Modify Session expected buffer:
+ value: topic_id bytes: 8
+ value: type bytes: 8
+ value: s1u_enodeb_ipv4 bytes: 32
+ value: s1u_enodeb_teid bytes: 32
+ value: s1u_sgw_ipv4 bytes: 32
+ value: session_id bytes: 64
+ value: controller_topic bytes: 8
+ value: client_id bytes: 32
+ value: op_id bytes: 32
+ */
+ ByteBuffer bb = ByteBuffer.allocate(32)
+ .put(toUint8(topicId))
+ .put(MODIFY_DL_BEARER_TYPE)
+ .put(toUint32(s1u_sgw_ipv4.toInt()))
+ .put(toUint32(s1u_enodeb_teid))
+ .put(toUint32(s1u_enodeb_ipv4.toInt()))
+ .put(toUint64(BigInteger.valueOf(sessionId)))
+ .put(toUint8(ZMQSBSubscriberManager.getControllerTopic()))
+ .put(toUint32(clientId))
+ .put(toUint32(opId.longValue()));
+
+ log.info("modify_bearer_dl: {}", bb.array());
+ ZMQSBPublisherManager.getInstance().send(bb);
+ }
+
+ @Override
+ public void modify_bearer_ul(
+ Short dpn,
+ Ip4Address s1u_enb_gtpu_ipv4,
+ Long s1u_enb_gtpu_teid,
+ Long s1u_sgw_gtpu_teid
+ ) {
+ ByteBuffer bb = ByteBuffer.allocate(15)
+ .put(toUint8(dpn))
+ .put(MODIFY_UL_BEARER_TYPE)
+ .put(toUint32(s1u_enb_gtpu_ipv4.toInt()))
+ .put(toUint32(s1u_enb_gtpu_teid))
+ .put(toUint32(s1u_sgw_gtpu_teid));
+
+ log.info("modify_bearer_ul: {}", bb.array());
+ ZMQSBPublisherManager.getInstance().send(bb);
+ }
+
+ @Override
+ public void delete_bearer(
+ Short dpnTopic,
+ Long s1u_sgw_gtpu_teid) {
+ ByteBuffer bb = ByteBuffer.allocate(7)
+ .put(toUint8(dpnTopic))
+ .put(DELETE_BEARER_TYPE)
+ .put(toUint32(s1u_sgw_gtpu_teid));
+
+ log.info("delete_bearer: {}", bb.array());
+ ZMQSBPublisherManager.getInstance().send(bb);
+ }
+
+ @Override
+ public void send_ADC_rules(Short topic,
+ String domain_name, String ip,
+ Short drop, Long rating_group,
+ Long service_ID, String sponsor_ID) {
+ Ip4Prefix ip_prefix = null;
+ if (ip != null) {
+ ip_prefix = Ip4Prefix.valueOf(ip);
+ }
+ Short selector_type = (short) (domain_name != null ? 0 : ip_prefix != null ? 2 : ip_prefix.address() != null ? 1 : 255);
+ if (selector_type == 255) {
+ log.warn("Domain/IP not found, failed to send rules");
+ return;
+ }
+ ByteBuffer bb = ByteBuffer.allocate(200);
+ bb.put(toUint8(topic))
+ .put(SEND_ADC_TYPE)
+ .put(toUint8(selector_type));
+ if (selector_type == 0) {
+ bb.put(toUint8((short) domain_name.length()))
+ .put(domain_name.getBytes());
+ }
+ if ((selector_type == 1) || (selector_type == 2)) {
+ int ip_address_long = ip_prefix.address().toInt();
+ bb.put(toUint32(ip_address_long));
+ }
+ if (selector_type == 2) {
+ bb.put(toUint16(ip_prefix.prefixLength()));
+ }
+ if (drop != null)
+ bb.put(toUint8(drop));
+ if (rating_group != null)
+ bb.put(toUint32(rating_group));
+ if (service_ID != null)
+ bb.put(toUint32(service_ID));
+ if (sponsor_ID != null && (short) sponsor_ID.length() > 0) {
+ bb.put(toUint8((short) sponsor_ID.length()))
+ .put(sponsor_ID.getBytes());
+ }
+ bb.put(toUint8(ZMQSBSubscriberManager.getControllerTopic()));
+
+ log.info("send_ADC_rules: {}", bb.array());
+ ZMQSBPublisherManager.getInstance().send(bb);
+ }
+}
\ No newline at end of file
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/package-info.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/package-info.java
new file mode 100644
index 0000000..45fe96c
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+/**
+ * FPC Agent.
+ */
+package org.onosproject.fpcagent;
\ No newline at end of file
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/workers/ZMQSBPublisherManager.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/workers/ZMQSBPublisherManager.java
new file mode 100644
index 0000000..541d7f5
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/workers/ZMQSBPublisherManager.java
@@ -0,0 +1,69 @@
+package org.onosproject.fpcagent.workers;
+
+import org.apache.commons.lang.exception.ExceptionUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.zeromq.ZContext;
+import org.zeromq.ZMQ;
+
+import java.nio.ByteBuffer;
+import java.util.concurrent.*;
+
+public class ZMQSBPublisherManager implements AutoCloseable {
+ private static final Logger log = LoggerFactory.getLogger(ZMQSBPublisherManager.class);
+ private static ZMQSBPublisherManager _instance = null;
+ private final ZContext ctx;
+ private final String address;
+ private final BlockingQueue<ByteBuffer> blockingQueue;
+ private final int poolSize;
+ private boolean run;
+
+ protected ZMQSBPublisherManager(String address, int poolSize) {
+ this.ctx = new ZContext();
+ this.address = address;
+ this.run = true;
+ this.blockingQueue = new LinkedBlockingQueue<>();
+ this.poolSize = poolSize;
+ }
+
+ public static ZMQSBPublisherManager createInstance(String address, int poolSize) {
+ if (_instance == null) {
+ _instance = new ZMQSBPublisherManager(address, poolSize);
+ }
+ return _instance;
+ }
+
+ public static ZMQSBPublisherManager getInstance() {
+ return _instance;
+ }
+
+ public void send(ByteBuffer buf) {
+ try {
+ blockingQueue.put(buf);
+ } catch (InterruptedException e) {
+ log.error(ExceptionUtils.getFullStackTrace(e));
+ }
+ }
+
+ public void open() {
+ ExecutorService executorService = Executors.newFixedThreadPool(this.poolSize);
+ executorService.submit(() -> {
+ ZMQ.Socket socket = ctx.createSocket(ZMQ.PUB);
+ socket.connect(address);
+ log.debug("Publisher at {}", address);
+ while ((!Thread.currentThread().isInterrupted()) && run) {
+ try {
+ byte[] array = blockingQueue.take().array();
+ socket.send(array);
+ } catch (InterruptedException e) {
+ log.error(ExceptionUtils.getFullStackTrace(e));
+ }
+ }
+ });
+ }
+
+ @Override
+ public void close() {
+ run = false;
+ }
+}
diff --git a/apps/fpcagent/src/main/java/org/onosproject/fpcagent/workers/ZMQSBSubscriberManager.java b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/workers/ZMQSBSubscriberManager.java
new file mode 100644
index 0000000..f259883
--- /dev/null
+++ b/apps/fpcagent/src/main/java/org/onosproject/fpcagent/workers/ZMQSBSubscriberManager.java
@@ -0,0 +1,320 @@
+package org.onosproject.fpcagent.workers;
+
+import org.apache.commons.lang.exception.ExceptionUtils;
+import org.onosproject.fpcagent.FpcUtil;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.ietfdmmfpcagent.yangautoprefixnotify.value.DownlinkDataNotification;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.ietfdmmfpcbase.FpcDpnId;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.zeromq.ZContext;
+import org.zeromq.ZMQ;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.ThreadLocalRandom;
+
+import static org.onosproject.fpcagent.helpers.Converter.*;
+
+public class ZMQSBSubscriberManager implements AutoCloseable {
+ private static final Logger log = LoggerFactory.getLogger(ZMQSBSubscriberManager.class);
+ private static int MIN_TOPIC_VAL = 4;
+ private static int MAX_TOPIC_VAL = 255;
+ private static byte ASSIGN_ID = 0b0000_1010;
+ private static byte ASSIGN_CONFLICT = 0b0000_1011;
+ private static byte HELLO_REPLY = 0b0000_1101;
+ private static byte CONTROLLER_STATUS_INDICATION = 0b0000_1110;
+ private static byte HELLO = 0b0000_0001;
+ private static byte GOODBYE = 0b0000_0010;
+ private static ZMQSBSubscriberManager _instance = null;
+ private static Long controllerSourceId;
+ private static Short subscriberId;
+ private final String address;
+ private final Short broadcastAllId;
+ private final Short broadcastControllersId;
+ private final Short broadcastDpnsId;
+ private final String nodeId;
+ private final String networkId;
+ private boolean run;
+ private boolean conflictingTopic;
+ private Future<?> broadcastAllWorker;
+ private Future<?> broadcastControllersWorker;
+ private Future<?> broadcastTopicWorker;
+ private Future<?> generalWorker;
+
+ protected ZMQSBSubscriberManager(String address, String broadcastAllId, String broadcastControllersId,
+ String broadcastDpnsId, String nodeId, String networkId) {
+ this.address = address;
+ this.run = true;
+
+ this.nodeId = nodeId;
+ this.networkId = networkId;
+ this.broadcastAllId = Short.parseShort(broadcastAllId);
+ this.broadcastControllersId = Short.parseShort(broadcastControllersId);
+ this.broadcastDpnsId = Short.parseShort(broadcastDpnsId);
+
+ this.conflictingTopic = false;
+ controllerSourceId = (long) ThreadLocalRandom.current().nextInt(0, 65535);
+ }
+
+ public static ZMQSBSubscriberManager createInstance(String address, String broadcastAllId,
+ String broadcastControllersId, String broadcastDpnsId,
+ String nodeId, String networkId) {
+ if (_instance == null) {
+ _instance = new ZMQSBSubscriberManager(address, broadcastAllId, broadcastControllersId,
+ broadcastDpnsId, nodeId, networkId);
+ }
+ return _instance;
+ }
+
+ public static ZMQSBSubscriberManager getInstance() {
+ return _instance;
+ }
+
+ public static Short getControllerTopic() {
+ return subscriberId;
+ }
+
+ public static Long getControllerSourceId() {
+ return controllerSourceId;
+ }
+
+ public void open() {
+ short subscriberId = (short) ThreadLocalRandom.current().nextInt(MIN_TOPIC_VAL, MAX_TOPIC_VAL + 1);
+
+ broadcastAllWorker = Executors.newSingleThreadExecutor()
+ .submit(new ZMQSubscriberWorker(broadcastAllId));
+
+ broadcastControllersWorker = Executors.newSingleThreadExecutor()
+ .submit(new ZMQSubscriberWorker(broadcastControllersId));
+
+ broadcastTopicWorker = Executors.newSingleThreadExecutor()
+ .submit(new BroadcastTopic(subscriberId));
+ }
+
+ @Override
+ public void close() {
+ run = false;
+ }
+
+ /**
+ * Interrupts the BroadcastTopicworker if there is an Assign topic Conflict
+ *
+ * @param conflict - Flag to indicate conflict
+ * @param subId - Topic Id that caused the conflict
+ */
+ protected void BroadcastAllSubIdCallBack(boolean conflict, Short subId) {
+ if (conflict && subscriberId.equals(subId)) {
+ this.conflictingTopic = true;
+ broadcastTopicWorker.cancel(true);
+ }
+ }
+
+ /**
+ * Broadcasts the GOODBYE message to all the DPNs
+ */
+ public void sendGoodbyeToDpns() {
+ ByteBuffer bb = ByteBuffer.allocate(10 + nodeId.length() + networkId.length());
+ bb.put(toUint8(broadcastDpnsId))
+ .put(CONTROLLER_STATUS_INDICATION)
+ .put(toUint8(subscriberId))
+ .put(GOODBYE)
+ .put(toUint32(controllerSourceId))
+ .put(toUint8((short) nodeId.length()))
+ .put(nodeId.getBytes())
+ .put(toUint8((short) networkId.length()))
+ .put(networkId.getBytes());
+
+ log.info("sendGoodbyeToDpns: {}", bb.array());
+ ZMQSBPublisherManager.getInstance().send(bb);
+ }
+
+ /**
+ * Broadcasts an Assign Conflict message
+ *
+ * @param contents - byte array received over the southbound.
+ */
+ protected void SendAssignConflictMessage(byte[] contents) {
+ byte topic = contents[2];
+ short nodeIdLen = contents[7];
+ short networkIdLen = contents[8 + nodeIdLen];
+ String node_id = new String(Arrays.copyOfRange(contents, 8, 8 + nodeIdLen));
+ String network_id = new String(Arrays.copyOfRange(contents, 9 + nodeIdLen, 9 + nodeIdLen + networkIdLen));
+
+ if (toUint8(subscriberId) == topic || nodeId.equals(node_id) || networkId.equals(network_id)) {
+ ByteBuffer bb = ByteBuffer.allocate(9 + nodeId.length() + networkId.length());
+ bb.put(toUint8(broadcastAllId))
+ .put(ASSIGN_CONFLICT)
+ .put(topic)
+ .put(toUint32(controllerSourceId))
+ .put(toUint8((short) nodeId.length()))
+ .put(nodeId.getBytes())
+ .put(toUint8((short) networkId.length()))
+ .put(networkId.getBytes());
+
+ log.info("SendAssignConflictMessage: {}", bb.array());
+ ZMQSBPublisherManager.getInstance().send(bb);
+ }
+ }
+
+ protected class ZMQSubscriberWorker implements Runnable {
+ private final Short subscriberId;
+ private ZContext ctx;
+
+ ZMQSubscriberWorker(Short subscriberId) {
+ this.subscriberId = subscriberId;
+ this.ctx = new ZContext();
+ }
+
+ /**
+ * Sends a reply to a DPN Hello
+ *
+ * @param dpnStatus - DPN Status Indication message received from the DPN
+ */
+ protected void sendHelloReply(FpcUtil.DPNStatusIndication dpnStatus) {
+ if (FpcUtil.getTopicFromNode(dpnStatus.getKey()) != null) {
+ ByteBuffer bb = ByteBuffer.allocate(9 + nodeId.length() + networkId.length())
+ .put(toUint8(FpcUtil.getTopicFromNode(dpnStatus.getKey())))
+ .put(HELLO_REPLY)
+ .put(toUint8(ZMQSBSubscriberManager.getControllerTopic()))
+ .put(toUint32(ZMQSBSubscriberManager.getControllerSourceId()))
+ .put(toUint8((short) nodeId.length()))
+ .put(nodeId.getBytes())
+ .put(toUint8((short) networkId.length()))
+ .put(networkId.getBytes());
+
+ log.info("sendHelloReply: {}", bb.array());
+ ZMQSBPublisherManager.getInstance().send(bb);
+ }
+ }
+
+ @Override
+ public void run() {
+ ZMQ.Socket subscriber = this.ctx.createSocket(ZMQ.SUB);
+ subscriber.connect(address);
+ subscriber.subscribe(new byte[]{toUint8(subscriberId)});
+ log.debug("Subscriber at {} / {}", address, subscriberId);
+ while ((!Thread.currentThread().isInterrupted()) && run) {
+ byte[] contents = subscriber.recv();
+ byte topic = contents[0];
+ byte messageType = contents[1];
+ log.debug("Received {}", contents);
+ switch (topic) {
+ case 1:
+ if (messageType == ASSIGN_CONFLICT && toInt(contents, 3) != controllerSourceId) {
+ BroadcastAllSubIdCallBack(true, (short) contents[2]);
+ } else if (messageType == ASSIGN_ID && toInt(contents, 3) != controllerSourceId) {
+ SendAssignConflictMessage(contents);
+ }
+ break;
+ default:
+ Map.Entry<FpcDpnId, Object> entry = FpcUtil.decode(contents);
+ if (entry != null) {
+ if (entry.getValue() instanceof DownlinkDataNotification) {
+ // TODO handle DL notification
+ } else if (entry.getValue() instanceof FpcUtil.DPNStatusIndication) {
+ FpcUtil.DPNStatusIndication dpnStatus = (FpcUtil.DPNStatusIndication) entry.getValue();
+ if (dpnStatus.getStatus() == FpcUtil.DPNStatusIndication.Status.HELLO) {
+ sendHelloReply(dpnStatus);
+ }
+ }
+ }
+ }
+ }
+ subscriber.disconnect(address);
+ subscriber.close();
+ ctx.destroySocket(subscriber);
+ try {
+ Thread.currentThread().join();
+ } catch (InterruptedException e) {
+ log.error(ExceptionUtils.getFullStackTrace(e));
+ }
+ }
+ }
+
+ /**
+ * Class to broadcast a topic for the controller
+ */
+ protected class BroadcastTopic implements Runnable {
+ private Short topic;
+
+ /**
+ * Constructor
+ *
+ * @param topic - Topic to broadcast
+ */
+ public BroadcastTopic(Short topic) {
+ this.topic = topic;
+ }
+
+ /**
+ * Broadcasts the topic
+ */
+ private void broadcastTopic() {
+ ByteBuffer bb = ByteBuffer.allocate(9 + nodeId.length() + networkId.length());
+ bb.put(toUint8(broadcastAllId))
+ .put(ASSIGN_ID)
+ .put(toUint8(this.topic))
+ .put(toUint32(controllerSourceId))
+ .put(toUint8((short) nodeId.length()))
+ .put(nodeId.getBytes())
+ .put(toUint8((short) networkId.length()))
+ .put(networkId.getBytes());
+
+ log.info("broadcastTopic: {}", bb.array());
+ ZMQSBPublisherManager.getInstance().send(bb);
+ }
+
+ /**
+ * Broadcasts the HELLO message to all the DPNs
+ */
+ private void sendHelloToDpns() {
+ ByteBuffer bb = ByteBuffer.allocate(10 + nodeId.length() + networkId.length());
+ bb.put(toUint8(broadcastDpnsId))
+ .put(CONTROLLER_STATUS_INDICATION)
+ .put(toUint8(subscriberId))
+ .put(HELLO)
+ .put(toUint32(controllerSourceId))
+ .put(toUint8((short) nodeId.length()))
+ .put(nodeId.getBytes())
+ .put(toUint8((short) networkId.length()))
+ .put(networkId.getBytes());
+
+
+ log.info("sendHelloToDpns: {}", bb.array());
+ ZMQSBPublisherManager.getInstance().send(bb);
+ }
+
+ @Override
+ public void run() {
+ try {
+ this.broadcastTopic();
+ log.debug("Thread sleeping: " + Thread.currentThread().getName());
+ Thread.sleep(2000);
+ } catch (InterruptedException e) {
+ if (conflictingTopic) {
+ conflictingTopic = false;
+ this.topic = (short) ThreadLocalRandom.current().nextInt(MIN_TOPIC_VAL, MAX_TOPIC_VAL + 1);
+ subscriberId = this.topic;
+ this.run();
+ return;
+ } else {
+ log.error(ExceptionUtils.getFullStackTrace(e));
+ }
+ }
+ subscriberId = this.topic;
+ log.info("Topic Id: " + this.topic);
+ generalWorker = Executors.newSingleThreadExecutor().submit(new ZMQSubscriberWorker(this.topic));
+
+ try {
+ Thread.sleep(2000);
+ } catch (InterruptedException e) {
+ log.error(ExceptionUtils.getFullStackTrace(e));
+ }
+ sendHelloToDpns();
+ }
+
+ }
+}
diff --git a/models/fpcagent/BUCK b/models/fpcagent/BUCK
new file mode 100644
index 0000000..70f780a
--- /dev/null
+++ b/models/fpcagent/BUCK
@@ -0,0 +1,16 @@
+COMPILE_DEPS = [
+ '//lib:CORE_DEPS',
+ '//models/common:onos-models-common',
+]
+
+APPS = [
+ 'org.onosproject.models.common',
+]
+
+yang_model(
+ app_name = 'org.onosproject.models.fpcagent',
+ title = 'FPC Agent YANG Models',
+ custom_registrator = True,
+ deps = COMPILE_DEPS,
+ required_apps = APPS,
+)
diff --git a/models/fpcagent/pom.xml b/models/fpcagent/pom.xml
new file mode 100644
index 0000000..a82844e
--- /dev/null
+++ b/models/fpcagent/pom.xml
@@ -0,0 +1,165 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-models</artifactId>
+ <version>1.13.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>onos-models-fpcagent</artifactId>
+ <packaging>bundle</packaging>
+
+ <properties>
+ <onos.app.name>org.onosproject.models.fpcagent</onos.app.name>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-yang-model</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-models-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-apps-yang</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions combine.children="append">
+ <Include-Resource>yang/resources/YangMetaData.ser=target/classes/yang/resources/YangMetaData.ser</Include-Resource>
+ </instructions>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-yang-compiler-maven-plugin</artifactId>
+ </plugin>
+
+ <plugin>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-maven-plugin</artifactId>
+ </plugin>
+
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <version>3.0.0</version>
+ <executions>
+ <execution>
+ <id>add-source</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>add-source</goal>
+ </goals>
+ <configuration>
+ <sources>
+ <source>${project.build.directory}/generated-sources</source>
+ </sources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-clean-plugin</artifactId>
+ <version>3.0.0</version>
+ <executions>
+ <execution>
+ <id>onos-yang-plugin-workaround</id>
+ <!-- yang plugin cannot handle non-clean compilation -->
+ <phase>initialize</phase>
+ <goals>
+ <goal>clean</goal>
+ </goals>
+ <configuration>
+ <excludeDefaultDirectories>true</excludeDefaultDirectories>
+ <filesets>
+ <fileset>
+ <directory>target/generated-sources</directory>
+ </fileset>
+ </filesets>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+
+ </plugins>
+
+ <pluginManagement>
+ <plugins>
+ <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
+ <plugin>
+ <groupId>org.eclipse.m2e</groupId>
+ <artifactId>lifecycle-mapping</artifactId>
+ <version>1.0.0</version>
+ <configuration>
+ <lifecycleMappingMetadata>
+ <pluginExecutions>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>
+ org.apache.maven.plugins
+ </groupId>
+ <artifactId>
+ maven-clean-plugin
+ </artifactId>
+ <versionRange>
+ [3.0.0,)
+ </versionRange>
+ <goals>
+ <goal>clean</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <ignore></ignore>
+ </action>
+ </pluginExecution>
+ </pluginExecutions>
+ </lifecycleMappingMetadata>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+
+</project>
diff --git a/models/fpcagent/src/main/java/org.onosproject.models.fpcagent/FpcAgentModelRegistrator.java b/models/fpcagent/src/main/java/org.onosproject.models.fpcagent/FpcAgentModelRegistrator.java
new file mode 100644
index 0000000..64ea413
--- /dev/null
+++ b/models/fpcagent/src/main/java/org.onosproject.models.fpcagent/FpcAgentModelRegistrator.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.models.fpcagent;
+
+import com.google.common.collect.ImmutableMap;
+import org.apache.felix.scr.annotations.Component;
+import org.onosproject.yang.AbstractYangModelRegistrator;
+import org.onosproject.yang.gen.v1.fpc.rev20150105.FpcService;
+import org.onosproject.yang.gen.v1.fpcconfig.rev20160927.FpcConfig;
+import org.onosproject.yang.gen.v1.ietfdmmfpcagent.rev20160803.IetfDmmFpcagent;
+import org.onosproject.yang.gen.v1.ietfdmmfpcbase.rev20160803.IetfDmmFpcbase;
+import org.onosproject.yang.gen.v1.ietfdmmfpcpmip.rev20160119.IetfDmmFpcPmip;
+import org.onosproject.yang.gen.v1.ietfdmmfpcpolicyext.rev20160803.IetfDmmFpcPolicyext;
+import org.onosproject.yang.gen.v1.ietfdmmthreegpp.rev20160803.IetfDmmThreegpp;
+import org.onosproject.yang.gen.v1.ietfpmipqos.rev20160210.IetfPmipQos;
+import org.onosproject.yang.gen.v1.ietftrafficselectortypes.rev20160114.IetfTrafficSelectorTypes;
+import org.onosproject.yang.model.DefaultYangModuleId;
+import org.onosproject.yang.model.YangModuleId;
+import org.onosproject.yang.runtime.AppModuleInfo;
+import org.onosproject.yang.runtime.DefaultAppModuleInfo;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.Map;
+
+@Component(immediate = true)
+public class FpcAgentModelRegistrator extends AbstractYangModelRegistrator {
+ static final Logger log = LoggerFactory.getLogger(FpcAgentModelRegistrator.class);
+
+ public FpcAgentModelRegistrator() {
+ super(FpcAgentModelRegistrator.class, getAppInfo());
+ }
+
+ private static Map<YangModuleId, AppModuleInfo> getAppInfo() {
+ Map<YangModuleId, AppModuleInfo> appInfo = new HashMap<>();
+ appInfo.put(new DefaultYangModuleId("ietf-dmm-fpcagent", "2016-08-03"),
+ new DefaultAppModuleInfo(IetfDmmFpcagent.class, null));
+ appInfo.put(new DefaultYangModuleId("ietf-dmm-fpcbase", "2016-08-03"),
+ new DefaultAppModuleInfo(IetfDmmFpcbase.class, null));
+ appInfo.put(new DefaultYangModuleId("fpc", "2015-01-05"),
+ new DefaultAppModuleInfo(FpcService.class, null));
+ appInfo.put(new DefaultYangModuleId("fpc-config", "2016-09-27"),
+ new DefaultAppModuleInfo(FpcConfig.class, null));
+ appInfo.put(new DefaultYangModuleId("ietf-dmm-fpc-pmip", "2016-01-19"),
+ new DefaultAppModuleInfo(IetfDmmFpcPmip.class, null));
+ appInfo.put(new DefaultYangModuleId("ietf-dmm-fpc-policyext", "2016-08-03"),
+ new DefaultAppModuleInfo(IetfDmmFpcPolicyext.class, null));
+ appInfo.put(new DefaultYangModuleId("ietf-dmm-threegpp", "2016-08-03"),
+ new DefaultAppModuleInfo(IetfDmmThreegpp.class, null));
+ appInfo.put(new DefaultYangModuleId("ietf-pmip-qos", "2016-02-10"),
+ new DefaultAppModuleInfo(IetfPmipQos.class, null));
+ appInfo.put(new DefaultYangModuleId("ietf-traffic-selector-types", "2016-01-14"),
+ new DefaultAppModuleInfo(IetfTrafficSelectorTypes.class, null));
+
+ return ImmutableMap.copyOf(appInfo);
+ }
+}
diff --git a/models/fpcagent/src/main/java/org.onosproject.models.fpcagent/package-info.java b/models/fpcagent/src/main/java/org.onosproject.models.fpcagent/package-info.java
new file mode 100644
index 0000000..3a46d78
--- /dev/null
+++ b/models/fpcagent/src/main/java/org.onosproject.models.fpcagent/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ */
+
+/**
+ * FPC Agent YANG models.
+ */
+package org.onosproject.models.fpcagent;
\ No newline at end of file
diff --git a/models/fpcagent/src/main/yang/fpc-config.yang b/models/fpcagent/src/main/yang/fpc-config.yang
new file mode 100644
index 0000000..9e28370
--- /dev/null
+++ b/models/fpcagent/src/main/yang/fpc-config.yang
@@ -0,0 +1,106 @@
+module fpc-config {
+ yang-version 1;
+ namespace "urn:onos:fpc:config";
+ prefix fpc-config;
+
+ description
+ "Configuration for ...";
+
+ revision "2016-09-27" {
+ description
+ "Initial revision.";
+ }
+
+ container fpc-config {
+ leaf use-memcached {
+ type boolean;
+ }
+ leaf memcached-uri {
+ type string;
+ }
+ leaf memcached-threads {
+ type uint16;
+ }
+ leaf scheduled-monitors-poolsize {
+ type uint16;
+ }
+ leaf monitor-threads {
+ type uint16;
+ }
+ leaf dpn-listener-uri {
+ type string;
+ }
+ leaf dpn-listener-id {
+ type string;
+ }
+ leaf dpn-client-uri {
+ type string;
+ }
+ leaf dpn-message-processor-threads{
+ type uint16;
+ }
+ leaf dpn-client-threads {
+ type uint16;
+ }
+ leaf metricsupdate-ms {
+ type uint32;
+ }
+ leaf mobilityupdate-ms {
+ type uint32;
+ }
+ leaf node-id {
+ type string;
+ }
+ leaf network-id {
+ type string;
+ }
+ leaf activation-threads {
+ type uint16;
+ }
+ leaf target-read-limit {
+ type uint16;
+ }
+ leaf default-tenant-id {
+ type string;
+ }
+ leaf default-group-id {
+ type string;
+ }
+ leaf prefers-fast-clients {
+ type boolean;
+ }
+ leaf http-notifier-clients {
+ type uint16;
+ }
+ leaf zmq-nbi-server-poolsize {
+ type uint16;
+ }
+ leaf zmq-nbi-server-uri {
+ type string;
+ }
+ leaf zmq-nbi-inproc-uri {
+ type string;
+ }
+ leaf zmq-nbi-handler-poolsize {
+ type uint16;
+ }
+ leaf zmq-broadcast-all {
+ type string;
+ }
+ leaf zmq-broadcast-controllers {
+ type string;
+ }
+ leaf zmq-broadcast-dpns {
+ type string;
+ }
+ leaf http-nio2-nb-poolsize {
+ type uint16;
+ }
+ leaf http-nio2-nb-port {
+ type uint16;
+ }
+ leaf max-trans-rate {
+ type uint16;
+ }
+ }
+}
diff --git a/models/fpcagent/src/main/yang/fpc.yang b/models/fpcagent/src/main/yang/fpc.yang
new file mode 100644
index 0000000..2996283
--- /dev/null
+++ b/models/fpcagent/src/main/yang/fpc.yang
@@ -0,0 +1,169 @@
+module fpc {
+ yang-version 1;
+ namespace "urn:onos:params:xml:ns:yang:fpc";
+ prefix "fpc";
+
+ import ietf-dmm-fpcagent { prefix fpcagent; }
+ import ietf-dmm-fpcbase { prefix fpcbase; }
+ import ietf-inet-types { prefix inet; }
+ import ietf-dmm-fpc-pmip { prefix fpc-pmip; }
+ import ietf-dmm-threegpp { prefix threegpp; }
+
+ revision "2015-01-05" {
+ description "Initial revision of fpc model";
+ }
+
+ // grouping zmq-dpn-config {
+ // leaf topic {
+ // type string;
+ // }
+ // }
+
+ // augment "/fpcagent:tenants/fpcagent:tenant/fpcagent:fpc-topology/fpcagent:dpns" {
+ // uses zmq-dpn-config;
+ // }
+
+ // New DPN Type
+ identity zmq-dpn-control-protocol {
+ base "fpcbase:fpc-dpn-control-protocol";
+ }
+
+ typedef membership-match-type {
+ type enumeration {
+ enum eq { value 0; }
+ enum super { value 1; }
+ enum psuper { value 2; }
+ enum sub { value 3; }
+ enum psub { value 4; }
+ enum overlap { value 5; }
+ enum nonoverlap { value 6; }
+ }
+ }
+
+ grouping membership-value {
+ leaf policy-membership {
+ type string;
+ }
+ }
+
+ augment "/fpcagent:tenants/fpcagent:tenant/fpcagent:fpc-policy/fpcagent:descriptors/fpcagent:descriptor-value" {
+ case tft-plusplus {
+ uses fpc:membership-value;
+ leaf membership-match-type {
+ type fpc:membership-match-type;
+ }
+ }
+ }
+
+ augment "/fpcagent:tenants/fpcagent:tenant/fpcagent:fpc-mobility/fpcagent:contexts" {
+ uses fpc:membership-value;
+ }
+ augment "/fpcagent:configure/fpcagent:input/fpcagent:op_body/fpcagent:create_or_update/fpcagent:contexts" {
+ uses fpc:membership-value;
+ }
+ augment "/fpcagent:configure-bundles/fpcagent:input/fpcagent:bundles/fpcagent:op_body/fpcagent:create_or_update/fpcagent:contexts" {
+ uses fpc:membership-value;
+ }
+ augment "/fpcagent:configure/fpcagent:output/fpcagent:result-type/fpcagent:common-success/fpcagent:contexts" {
+ uses fpc:membership-value;
+ }
+ augment "/fpcagent:configure-bundles/fpcagent:output/fpcagent:bundles/fpcagent:result-type/fpcagent:common-success/fpcagent:contexts" {
+ uses fpc:membership-value;
+ }
+ // TODO - Add Notification Augments for membership-value
+
+ container tx-stats {
+ config false;
+ leaf last-ts {
+ type string;
+ }
+ leaf total-txs {
+ type uint64;
+ }
+ list states {
+ key state;
+ leaf state {
+ type string;
+ }
+ leaf entries {
+ type uint64;
+ }
+ container total-time {
+ leaf mantissa {
+ type uint64;
+ }
+ leaf exponent {
+ type int32;
+ }
+ }
+ container average-time {
+ leaf mantissa {
+ type uint64;
+ }
+ leaf exponent {
+ type int32;
+ }
+ }
+ }
+ }
+
+ grouping connection-config {
+ leaf client-id {
+ type fpcagent:client-identifier;
+ }
+ leaf tenant-id {
+ type fpcbase:fpc-identity;
+ }
+ leaf-list supported-features {
+ type string;
+ }
+ leaf endpoint-uri {
+ type inet:uri;
+ }
+ leaf supports-oknotify-model {
+ type boolean;
+ }
+ leaf supports-ack-model {
+ type boolean;
+ }
+ }
+
+
+ container connection-info {
+ list connections {
+ config false;
+ key client-id;
+ leaf client-id {
+ type string;
+ }
+ container requested-info {
+ uses fpc:connection-config;
+ }
+ container assigned-info {
+ uses fpc:connection-config;
+ }
+ }
+ }
+
+ rpc register-client {
+ input {
+ uses fpc:connection-config;
+ }
+ output {
+ uses fpc:connection-config;
+ }
+ }
+
+ rpc deregister-client {
+ input {
+ leaf client-id {
+ type fpcagent:client-identifier;
+ }
+ }
+ output {
+ leaf client-id {
+ type fpcagent:client-identifier;
+ }
+ }
+ }
+}
diff --git a/models/fpcagent/src/main/yang/ietf-dmm-fpc-pmip.yang b/models/fpcagent/src/main/yang/ietf-dmm-fpc-pmip.yang
new file mode 100644
index 0000000..c44aaab
--- /dev/null
+++ b/models/fpcagent/src/main/yang/ietf-dmm-fpc-pmip.yang
@@ -0,0 +1,71 @@
+module ietf-dmm-fpc-pmip {
+ namespace "urn:ietf:params:xml:ns:yang:ietf-dmm-fpc-pmip";
+ prefix fpc-pmip;
+
+ organization "IETF DMM Working Group";
+ contact "Satoru Matsushima <satoru.matsushima@g.softbank.co.jp>";
+
+ description
+ "This module contains YANG definition for
+ Forwarding Policy Configuration Protocol.(FPCP)";
+
+ revision 2016-01-19 {
+ description "Changes based on -01 version of FPCP draft.";
+ reference "draft-ietf-dmm-fpc-cpdp-01";
+ }
+
+ identity pmip-tunnel-type {
+ description "PMIP Tunnel Type";
+ }
+ identity grev1 {
+ base "fpc-pmip:pmip-tunnel-type";
+ }
+ identity grev2 {
+ base "fpc-pmip:pmip-tunnel-type";
+ }
+ identity ipinip {
+ base "fpc-pmip:pmip-tunnel-type";
+ }
+ grouping pmip-mobility {
+ leaf type {
+ type identityref {
+ base "fpc-pmip:pmip-tunnel-type";
+ }
+ }
+ choice value {
+ case gre {
+ leaf key {
+ type uint32;
+ description "GRE_KEY";
+ }
+ }
+ }
+ }
+
+ typedef pmip-instr {
+ description "Instruction Set for PMIP";
+ type bits {
+ bit assign-ip {
+ position 0;
+ }
+ bit assign-dpn {
+ position 1;
+ }
+ bit session {
+ position 2;
+ }
+ bit uplink {
+ position 3;
+ }
+ bit downlink {
+ position 4;
+ }
+ }
+ }
+
+ grouping pmip-commandset {
+ leaf instr-pmip-mob {
+ type fpc-pmip:pmip-instr;
+ }
+ }
+}
diff --git a/models/fpcagent/src/main/yang/ietf-dmm-fpc-policyext.yang b/models/fpcagent/src/main/yang/ietf-dmm-fpc-policyext.yang
new file mode 100644
index 0000000..3845591
--- /dev/null
+++ b/models/fpcagent/src/main/yang/ietf-dmm-fpc-policyext.yang
@@ -0,0 +1,95 @@
+module ietf-dmm-fpc-policyext {
+ namespace "urn:ietf:params:xml:ns:yang:fpcpolicyext";
+ prefix fpcpolicyext;
+
+ import ietf-inet-types { prefix inet; revision-date 2013-07-15; }
+
+ organization "IETF DMM Working Group";
+ contact "Satoru Matsushima <satoru.matsushima@g.softbank.co.jp>";
+
+ description
+ "This module contains YANG definition for
+ Forwarding Policy Configuration Protocol (FPCP)
+ common Policy Action and Descriptor extensions";
+
+ revision 2016-08-03 {
+ description "Changes based on -04 version of FPC draft.";
+ reference "draft-ietf-dmm-fpc-cpdp-04";
+ }
+
+ grouping simple-nat {
+ leaf outbound-nat-address {
+ type inet:ip-address;
+ }
+ }
+
+ grouping simple-napt {
+ leaf source-port {
+ type inet:port-number;
+ }
+ leaf outbound-napt-address {
+ type inet:ip-address;
+ }
+ leaf destination-port {
+ type inet:port-number;
+ }
+ }
+
+ grouping prefix-traffic-descriptor {
+ description
+ "Traffic descriptor group collects parameters to
+ identify target traffic flow. It represents
+ source/destination as IP prefixes";
+
+ leaf destination-ip {
+ type inet:ip-prefix;
+ description "Rule of destination IP";
+ }
+ leaf source-ip {
+ type inet:ip-prefix;
+ description "Rule of source IP";
+ }
+ }
+
+ grouping rating-action {
+ description "Rudimentary rating action applied based upon RFC 4006 attributes";
+ leaf service-context-id {
+ type string;
+ description "Per RFC 4006 - Contains a unique identifier of the Diameter credit-control service
+ specific document that applies to the request. The format of the Service-Context-Id is:
+
+ <service-context>@<domain>
+
+ service-context = Token
+
+ The Token is an arbitrary string of characters and digits.
+
+ 'domain' represents the entity that allocated the Service-Context-Id.";
+ }
+ leaf service-identifier {
+ type uint32;
+ description "From RFC 4006 - Contains the identifier of a service. The specific service the
+ request relates to is uniquely identified by the combination of
+ Service-Context-Id and Service-Identifier AVPs.";
+ }
+ leaf rating-group {
+ type uint32;
+ description "From RFC 4006 - Contains the identifier of a rating group. All the services subject
+ to the same rating type are part of the same rating group. The
+ specific rating group the request relates to is uniquely identified
+ by the combination of Service-Context-Id and Rating-Group AVPs.";
+ }
+ }
+
+ grouping domain-descriptor-list {
+ description "Descriptors for list of domains";
+ leaf-list source-domains {
+ type inet:domain-name;
+ description "Source Domain Names";
+ }
+ leaf-list destination-domains {
+ type inet:domain-name;
+ description "Destination Domain Names";
+ }
+ }
+}
diff --git a/models/fpcagent/src/main/yang/ietf-dmm-fpcagent.yang b/models/fpcagent/src/main/yang/ietf-dmm-fpcagent.yang
new file mode 100644
index 0000000..1e5a7fc
--- /dev/null
+++ b/models/fpcagent/src/main/yang/ietf-dmm-fpcagent.yang
@@ -0,0 +1,663 @@
+module ietf-dmm-fpcagent {
+ namespace "urn:ietf:params:xml:ns:yang:fpcagent";
+ prefix fpcagent;
+
+ import ietf-dmm-fpcbase { prefix fpcbase; revision-date 2016-08-03; }
+ import ietf-inet-types { prefix inet; revision-date 2013-07-15; }
+ import ietf-dmm-fpc-pmip { prefix fpc-pmip; revision-date 2016-01-19; }
+ import ietf-dmm-threegpp { prefix threegpp; }
+
+ organization "IETF DMM Working Group";
+ contact "Satoru Matsushima <satoru.matsushima@g.softbank.co.jp>";
+
+ description
+ "This module contains YANG definition for
+ Forwarding Policy Configuration Protocol.(FPCP)";
+
+ revision 2016-08-03 {
+ description "Changes based on -04 version of FPC draft.";
+ reference "draft-ietf-dmm-fpc-cpdp-04";
+ }
+ feature fpc-cloning {
+ description "An ability to support cloning in the RPC.";
+ }
+ feature fpc-basename-registry {
+ description "Ability to track Base Names already provisioned on the Agent";
+ }
+ feature fpc-bundles {
+ description "Ability for Client to send multiple bundles of actions to
+ an Agent";
+ }
+ feature fpc-client-binding {
+ description "Allows a FPC Client to bind a DPN to an Topology Object";
+ }
+ feature fpc-auto-binding {
+ description "Allows a FPC Agent to advertise Topology Objects that could be DPNs";
+ }
+ feature instruction-bitset {
+ description "Allows the expression of instructions (bit sets) over FPC.";
+ }
+ feature operation-ref-scope {
+ description "Provides the scope of refeneces in an operation. Used to optmize
+ the Agent processing.";
+ }
+
+ typedef agent-identifier {
+ type fpcbase:fpc-identity;
+ }
+
+ typedef client-identifier {
+ type fpcbase:fpc-identity;
+ }
+
+ grouping basename-info {
+ leaf basename {
+ if-feature fpcagent:fpc-basename-registry;
+ description "Rules Basename";
+ type fpcbase:fpc-identity;
+ }
+ leaf base-state {
+ if-feature fpcagent:fpc-basename-registry;
+ type string;
+ }
+ leaf base-checkpoint {
+ if-feature fpcagent:fpc-basename-registry;
+ type string;
+ }
+ }
+
+ // Top Level Structures
+ container tenants {
+ description "";
+
+ list tenant {
+ description "";
+ key "tenant-id";
+ leaf tenant-id {
+ type fpcbase:fpc-identity;
+ }
+
+ container fpc-policy {
+ list policy-groups {
+ key "policy-group-id";
+ uses fpcbase:fpc-policy-group;
+ }
+ list policies {
+ key "policy-id";
+ uses fpcbase:fpc-policy;
+ }
+ list descriptors {
+ key descriptor-id;
+ uses fpcbase:fpc-descriptor;
+ }
+ list actions {
+ key action-id;
+ uses fpcbase:fpc-action;
+ }
+ }
+
+ container fpc-mobility {
+ config false;
+ list contexts {
+ key context-id;
+ uses fpcbase:fpc-context;
+ }
+ list ports {
+ key port-id;
+ uses fpcbase:fpc-port;
+ }
+ list monitors {
+ key monitor-id;
+ uses fpcbase:monitor-config;
+ }
+ }
+ container fpc-topology {
+ // Basic Agent Topology Structures
+ list domains {
+ key domain-id;
+ uses fpcbase:fpc-domain;
+ uses fpcagent:basename-info;
+ }
+
+ list dpn-group-peers {
+ if-feature fpcbase:fpc-basic-agent;
+ key "remote-dpn-group-id";
+ uses fpcbase:fpc-dpn-peer-group;
+ }
+ leaf topology-dpn-id {
+ if-feature fpcbase:fpc-basic-agent;
+ type fpcbase:fpc-dpn-id;
+ }
+ leaf-list control-protocols {
+ if-feature fpcbase:fpc-basic-agent;
+ type identityref {
+ base "fpcbase:fpc-dpn-control-protocol";
+ }
+ }
+
+ list dpn-groups {
+ if-feature fpcbase:fpc-multi-dpn;
+ key dpn-group-id;
+ uses fpcagent:fpc-dpn-group;
+ list domains {
+ key domain-id;
+ uses fpcbase:fpc-domain;
+ uses fpcagent:basename-info;
+ }
+ }
+ list dpns {
+ if-feature fpcbase:fpc-multi-dpn;
+ key dpn-id;
+ uses fpcbase:fpc-dpn;
+ }
+ }
+
+ }
+ }
+
+ container fpc-agent-info {
+ // General Agent Structures
+ leaf-list supported-features {
+ type string;
+ }
+
+ // Common Agent Info
+ list supported-events {
+ key event;
+ leaf event {
+ type identityref {
+ base "fpcbase:event-type";
+ }
+ }
+ leaf event-id {
+ type fpcbase:event-type-id;
+ }
+ }
+
+ list supported-error-types {
+ key error-type;
+ leaf error-type {
+ type identityref {
+ base "fpcagent:error-type";
+ }
+ }
+ leaf error-type-id {
+ type fpcagent:error-type-id;
+ }
+ }
+ }
+
+
+ // Multi-DPN Agent Structures
+ grouping fpc-dpn-group {
+ leaf dpn-group-id {
+ type fpcbase:fpc-dpn-group-id;
+ }
+ leaf data-plane-role {
+ type identityref {
+ base "fpcbase:fpc-forwaridingplane-role";
+ }
+ }
+ leaf access-type {
+ type identityref {
+ base "fpcbase:fpc-access-type";
+ }
+ }
+ leaf mobility-profile {
+ type identityref {
+ base "fpcbase:fpc-mobility-profile-type";
+ }
+ }
+ list dpn-group-peers {
+ key "remote-dpn-group-id";
+ uses fpcbase:fpc-dpn-peer-group;
+ }
+ }
+
+
+ // RPC
+ // RPC Specific Structures
+ //Input Structures
+ typedef admin-status {
+ type enumeration {
+ enum enabled { value 0; }
+ enum disabled { value 1; }
+ enum virtual { value 2; }
+ }
+ }
+
+ typedef session-status {
+ type enumeration {
+ enum complete { value 0; }
+ enum incomplete { value 1; }
+ enum outdated { value 2; }
+ }
+ }
+
+ typedef op-delay {
+ type uint32;
+ }
+
+ typedef op-identifier {
+ type uint64;
+ }
+
+ typedef ref-scope {
+ description "Search scope for references in the operation.
+ op - All references are contained in the operation body (intra-op)
+ bundle - All references in exist in bundle (inter-operation/intra-bundle).
+ NOTE - If this value comes in CONFIG call it is equivalen to 'op'.
+ storage - One or more references exist outside of the operation and bundle.
+ A lookup to a cache / storage is required.
+ unknown - the location of the references are unknown. This is treated as
+ a 'storage' type.";
+ type enumeration {
+ enum none { value 0; }
+ enum op { value 1; }
+ enum bundle { value 2; }
+ enum storage { value 3; }
+ enum unknown { value 4; }
+ }
+ }
+
+ grouping instructions {
+ container instructions {
+ if-feature instruction-bitset;
+ choice instr-type {
+ case pmip-instr {
+ uses fpc-pmip:pmip-commandset;
+ }
+ case instr-3gpp-mob {
+ uses threegpp:threegpp-commandset;
+ }
+ }
+ }
+ }
+
+ grouping op-header {
+ leaf client-id {
+ type fpcagent:client-identifier;
+ }
+ leaf delay {
+ type op-delay;
+ }
+ leaf session-state {
+ type session-status;
+ }
+ leaf admin-state {
+ type admin-status;
+ }
+ leaf op-type {
+ type enumeration {
+ enum create { value 0; }
+ enum update { value 1; }
+ enum query { value 2; }
+ enum delete { value 3; }
+ }
+ }
+ leaf op-ref-scope {
+ if-feature operation-ref-scope;
+ type fpcagent:ref-scope;
+ }
+ uses fpcagent:instructions;
+ }
+
+ grouping clone-ref {
+ leaf entity {
+ type fpcbase:fpc-identity;
+ }
+ leaf source {
+ type fpcbase:fpc-identity;
+ }
+ }
+
+ identity command-set {
+ description "protocol specific commands";
+ }
+
+ grouping context-operation {
+ uses fpcbase:fpc-context;
+ uses fpcagent:instructions;
+ }
+
+ grouping port-operation {
+ uses fpcbase:fpc-port;
+ uses fpcagent:instructions;
+ }
+
+ // Output Structure
+ grouping payload {
+ list ports {
+ uses fpcagent:port-operation;
+ }
+ list contexts {
+ uses fpcagent:context-operation;
+ }
+ }
+
+ grouping op-input {
+ uses fpcagent:op-header;
+ leaf op-id {
+ type op-identifier;
+ }
+ choice op_body {
+ case create_or_update {
+ list clones {
+ if-feature fpc-cloning;
+ key entity;
+ uses fpcagent:clone-ref;
+ }
+ uses fpcagent:payload;
+ }
+ case delete_or_query {
+ uses fpcbase:targets-value;
+ }
+ }
+ }
+
+ typedef result {
+ type enumeration {
+ enum ok { value 0; }
+ enum err { value 1; }
+ enum ok-notify-follows { value 2; }
+ }
+ }
+
+ identity error-type {
+ description "Base Error Type";
+ }
+ identity name-already-exists {
+ description "Notification that an entity of the same name already exists";
+ }
+
+ typedef error-type-id {
+ description "Integer form of the Error Type";
+ type uint32;
+ }
+
+ grouping op-status-value {
+ leaf op-status {
+ type enumeration {
+ enum ok { value 0; }
+ enum err { value 1; }
+ }
+ }
+ }
+
+ grouping result-body {
+ leaf op-id {
+ type op-identifier;
+ }
+ leaf result {
+ type result;
+ }
+ choice result-type {
+ case err {
+ leaf error-type-id {
+ type fpcagent:error-type-id;
+ }
+ leaf error-info {
+ type string {
+ length "1..1024";
+ }
+ }
+ }
+ case common-success {
+ uses fpcagent:payload;
+ }
+ case delete-success {
+ uses fpcbase:targets-value;
+ }
+ case empty-case {
+ }
+ }
+ }
+
+ grouping result-body-dpn {
+ leaf result {
+ type result; }
+ choice result-type {
+ case err {
+ leaf error-type-id {
+ type fpcagent:error-type-id;
+ }
+ leaf error-info {
+ type string {
+ length "1..1024";
+ }
+ }
+ }
+ case common-delete-success {
+ uses fpcbase:fpc-dpn;
+ }
+ case empty-case {
+ }
+ }
+ }
+
+ typedef dpn-operation {
+ type enumeration {
+ enum add { value 0; }
+ enum remove { value 1; }
+ }
+ }
+
+ grouping dpn-input {
+ leaf abstract-dpn-id {
+ type fpcbase:fpc-dpn-id;
+ }
+ leaf input-dpn-id {
+ type fpcbase:fpc-dpn-id;
+ }
+ leaf operation {
+ type fpcagent:dpn-operation;
+ }
+ }
+
+ // Common RPCs
+ rpc configure-dpn {
+ input {
+ uses fpcagent:dpn-input;
+ }
+ output {
+ uses fpcagent:result-body-dpn;
+ }
+ }
+
+ rpc configure {
+ input {
+ uses fpcagent:op-input;
+ }
+ output {
+ uses fpcagent:result-body;
+ }
+ }
+
+ rpc configure-bundles {
+ if-feature fpcagent:fpc-bundles;
+ input {
+ leaf client-id {
+ type fpcagent:client-identifier;
+ }
+ leaf highest-op-ref-scope {
+ if-feature operation-ref-scope;
+ type fpcagent:ref-scope;
+ }
+ list bundles {
+ key op-id;
+ uses fpcagent:op-input;
+ }
+ }
+ output {
+ list bundles {
+ key op-id;
+ uses fpcagent:result-body;
+ }
+ }
+ }
+
+ // Notification Messages & Structures
+ typedef notification-id {
+ type uint32;
+ }
+
+ grouping notification-header {
+ leaf notification-id {
+ type fpcagent:notification-id;
+ }
+ leaf timestamp {
+ type uint64;
+ }
+ }
+
+ grouping cause-values {
+ leaf cause-value {
+ type uint32;
+ }
+ }
+
+ notification config-result-notification {
+ uses fpcagent:notification-header;
+ choice value {
+ case config-result {
+ uses fpcagent:op-status-value;
+ uses fpcagent:cause-values;
+ uses fpcagent:result-body;
+ }
+ case config-bundle-result {
+ list bundles {
+ uses fpcagent:op-status-value;
+ uses fpcagent:cause-values;
+ uses fpcagent:result-body;
+ }
+ }
+ }
+ }
+
+ rpc event_register {
+ description "Used to register monitoring of parameters/events";
+ input {
+ uses fpcbase:monitor-config;
+ leaf client-id {
+ type fpcagent:client-identifier;
+ }
+ }
+ output {
+ leaf monitor-result {
+ type fpcagent:result;
+ }
+ }
+ }
+
+ rpc event_deregister {
+ description "Used to de-register monitoring of parameters/events";
+ input {
+ list monitors {
+ uses fpcbase:monitor-id;
+ }
+ leaf client-id {
+ type fpcagent:client-identifier;
+ }
+ }
+ output {
+ leaf monitor-result {
+ type fpcagent:result;
+ }
+ }
+ }
+
+ rpc probe {
+ description "Probe the status of a registered monitor";
+ input {
+ uses fpcbase:targets-value;
+ leaf client-id {
+ type fpcagent:client-identifier;
+ }
+ }
+ output {
+ leaf monitor-result {
+ type fpcagent:result;
+ }
+ }
+ }
+
+ grouping dpn-status-value {
+ leaf dpn-status {
+ type enumeration {
+ enum available { value 0; }
+ enum unavailable { value 1; }
+ }
+ }
+ }
+
+ notification notify {
+ uses fpcagent:notification-header;
+ choice value {
+ case dpn-candidate-available {
+ if-feature fpcagent:fpc-auto-binding;
+ leaf candidate-node-id {
+ type inet:uri;
+ }
+ leaf-list access-types {
+ type identityref {
+ base "fpcbase:fpc-access-type";
+ }
+ }
+ leaf-list mobility-profiles {
+ type identityref {
+ base "fpcbase:fpc-mobility-profile-type";
+ }
+ }
+ leaf-list forwarding-plane-roles {
+ type identityref {
+ base "fpcbase:fpc-forwaridingplane-role";
+ }
+ }
+ }
+
+ case dpn-availability {
+ leaf availability-message-type {
+ type string;
+ }
+ uses fpcagent:dpn-status-value;
+ leaf load {
+ description "A percentage value (between 0 and 100) of the system load. This is a combined measurement.";
+ type int8;
+ }
+ uses fpcbase:fpc-dpn;
+ }
+
+ case monitor-notification {
+ choice monitor-notification-value {
+ case simple-monitor {
+ uses fpcbase:report;
+ }
+ case bulk-monitors {
+ list reports {
+ uses fpcbase:report;
+ }
+ }
+ }
+ }
+ // Added as part of the augment issue
+ // TODO - Remove once resolved
+ case downlink-data-notification {
+ leaf notification-message-type {
+ type string;
+ }
+ leaf notification-dpn-id {
+ type fpcbase:fpc-dpn-id;
+ }
+ leaf session-id {
+ type uint64;
+ }
+ leaf client-id {
+ type fpcagent:client-identifier;
+ }
+ leaf op-id {
+ type fpcagent:op-identifier;
+ }
+ }
+ }
+ }
+}
diff --git a/models/fpcagent/src/main/yang/ietf-dmm-fpcbase.yang b/models/fpcagent/src/main/yang/ietf-dmm-fpcbase.yang
new file mode 100644
index 0000000..8785850
--- /dev/null
+++ b/models/fpcagent/src/main/yang/ietf-dmm-fpcbase.yang
@@ -0,0 +1,706 @@
+module ietf-dmm-fpcbase {
+ namespace "urn:ietf:params:xml:ns:yang:fpcbase";
+ prefix fpcbase;
+
+ import ietf-inet-types { prefix inet; revision-date 2013-07-15; }
+ import ietf-dmm-fpc-pmip { prefix fpc-pmip; revision-date 2016-01-19; }
+ import ietf-traffic-selector-types { prefix traffic-selectors; }
+ import ietf-dmm-fpc-policyext { prefix fpcpolicyext; }
+ import ietf-dmm-threegpp { prefix threegpp; }
+ import ietf-pmip-qos { prefix qos-pmip; }
+
+ organization "IETF DMM Working Group";
+ contact "Satoru Matsushima <satoru.matsushima@g.softbank.co.jp>";
+
+ description
+ "This module contains YANG definition for
+ Forwarding Policy Configuration Protocol.(FPCP)";
+
+ revision 2016-08-03 {
+ description "Changes based on -04 version of FPC draft.";
+ reference "draft-ietf-dmm-fpc-cpdp-04";
+ }
+
+ feature fpc-basic-agent {
+ description "This is an agent co-located with a DPN. In this case
+ only DPN Peer Groups, the DPN Id and Control Protocols are exposed
+ along with the core structures.";
+ }
+ feature fpc-multi-dpn {
+ description "The agent supports multiple DPNs.";
+ }
+
+ typedef fpc-identity {
+ type union {
+ type int64;
+ type string;
+ }
+ }
+
+ grouping target-value {
+ leaf target {
+ type fpc-identity;
+ }
+ }
+
+ grouping targets-value {
+ list targets {
+ key "target";
+ leaf target {
+ type fpc-identity;
+ }
+ leaf-list dpn-id {
+ type fpcbase:fpc-dpn-id;
+ }
+ }
+ }
+
+ // Descriptor Structure
+ typedef fpc-descriptor-id-type {
+ type fpcbase:fpc-identity;
+ description "Descriptor-ID";
+ }
+ identity fpc-descriptor-type {
+ description "A traffic descriptor";
+ }
+ grouping fpc-descriptor-id {
+ leaf descriptor-id {
+ type fpcbase:fpc-identity;
+ }
+ }
+
+ identity pmip-selector-descriptor {
+ base "fpcbase:fpc-descriptor-type";
+ }
+ identity prefix-descriptor {
+ base "fpcbase:fpc-descriptor-type";
+ }
+ identity threegpp-tft-decriptor {
+ base "fpcbase:fpc-descriptor-type";
+ }
+ identity domain-descriptor {
+ base "fpcbase:fpc-descriptor-type";
+ }
+
+ grouping fpc-descriptor {
+ uses fpcbase:fpc-descriptor-id;
+ leaf descriptor-type {
+ mandatory true;
+ type identityref {
+ base "fpc-descriptor-type";
+ }
+ description "Descriptor Type";
+ }
+ choice descriptor-value {
+ case all-traffic {
+ leaf all-traffic {
+ type empty;
+ }
+ }
+ case pmip-selector {
+ uses traffic-selectors:traffic-selector;
+ }
+ case prefix-descriptor {
+ uses fpcpolicyext:prefix-traffic-descriptor;
+ }
+ case threegpp-tft {
+ uses threegpp:tft;
+ }
+ case domain-descriptor {
+ uses fpcpolicyext:domain-descriptor-list;
+ }
+ }
+ }
+
+ // Action Structure
+ typedef fpc-action-id-type {
+ type fpcbase:fpc-identity;
+ description "Action-ID";
+ }
+ identity fpc-action-type {
+ description "Action Type";
+ }
+ grouping fpc-action-id {
+ leaf action-id {
+ type fpcbase:fpc-action-id-type;
+ }
+ }
+
+ identity simple-nat-action {
+ base "fpcbase:fpc-action-type";
+ }
+ identity simple-napt-action {
+ base "fpcbase:fpc-action-type";
+ }
+ identity copy-action {
+ base "fpcbase:fpc-action-type";
+ }
+ identity drop-action {
+ base "fpcbase:fpc-action-type";
+ }
+ identity rate-action {
+ base "fpcbase:fpc-action-type";
+ }
+
+ grouping fpc-action {
+ uses fpcbase:fpc-action-id;
+ leaf action-type {
+ mandatory true;
+ type identityref {
+ base "fpc-action-type";
+ }
+ description "Action Type";
+ }
+ choice action-value {
+ case drop {
+ leaf drop {
+ mandatory true;
+ type empty;
+ }
+ container rate-info{
+ leaf sponsor-identity {
+ type threegpp:sponsor-identity-type;
+ }
+ uses fpcpolicyext:rating-action;
+ }
+ }
+ case simple-nat {
+ uses fpcpolicyext:simple-nat;
+ }
+ case simple-napt {
+ uses fpcpolicyext:simple-napt;
+ }
+ case copy-forward {
+ uses fpcbase:copy-forward;
+ }
+ case rate {
+ leaf sponsor-identity {
+ type threegpp:sponsor-identity-type;
+ }
+ uses fpcpolicyext:rating-action;
+ }
+ }
+ }
+
+ // Rule Structure
+ grouping fpc-rule {
+ description
+ "FPC Rule. When no actions are present the action is DROP.
+ When no Descriptors are empty the default is 'all traffic'.";
+ list descriptors {
+ key descriptor-id;
+ uses fpcbase:fpc-descriptor-id;
+ leaf direction {
+ type fpc-direction;
+ }
+ }
+ list actions {
+ key action-id;
+ leaf order {
+ type uint32;
+ }
+ uses fpcbase:fpc-action-id;
+ }
+ }
+
+ // Policy Structures
+ typedef fpc-policy-id {
+ type fpcbase:fpc-identity;
+ }
+ grouping fpc-policy {
+ leaf policy-id {
+ type fpcbase:fpc-policy-id;
+ }
+ list rules {
+ key order;
+ leaf order {
+ type uint32;
+ }
+ uses fpcbase:fpc-rule;
+ }
+ }
+
+ // Policy Group
+ typedef fpc-policy-group-id {
+ type fpcbase:fpc-identity;
+ }
+ grouping fpc-policy-group {
+ leaf policy-group-id {
+ type fpcbase:fpc-policy-group-id;
+ }
+ leaf-list policies {
+ type fpcbase:fpc-policy-id;
+ }
+ }
+
+ // Mobility Structures
+ // Port Group
+ typedef fpc-port-id {
+ type fpcbase:fpc-identity;
+ }
+ grouping fpc-port {
+ leaf port-id {
+ type fpcbase:fpc-port-id;
+ }
+ leaf-list policy-groups {
+ type fpcbase:fpc-policy-group-id;
+ }
+ }
+
+ // Context Group
+ typedef fpc-context-id {
+ type fpcbase:fpc-identity;
+ }
+ grouping fpc-context-profile {
+ description "A profile that applies to a specific direction";
+ leaf tunnel-local-address {
+ type inet:ip-address;
+ description "Uplink endpoint address of the DPN which agent exists.";
+ }
+ leaf tunnel-remote-address {
+ type inet:ip-address;
+ description "Uplink endpoint address of the DPN which agent exists.";
+ }
+ leaf lifetime {
+ type uint32;
+ }
+ leaf tunnel-mtu-size {
+ type uint32;
+ description "Tunnel MTU size";
+ }
+ container mobility-tunnel-parameters {
+ description "Specifies profile specific uplink tunnel parameters to the DPN which the agent exists. The profiles includes GTP/TEID for 3gpp profile, GRE/Key for ietf-pmip profile, or new profile if anyone will define it.";
+ uses fpcbase:mobility-info;
+ }
+ container nexthop {
+ uses fpcbase:fpc-nexthop;
+ }
+ container qos-profile-parameters {
+ uses fpcbase:fpc-qos-profile;
+ }
+ container dpn-parameters {
+ }
+ list vendor-parameters {
+ key "vendor-id vendor-type";
+ uses fpcbase:vendor-attributes;
+ }
+ }
+
+ typedef fpc-direction {
+ type enumeration {
+ enum uplink;
+ enum downlink;
+ }
+ }
+
+ grouping fpc-context {
+ leaf context-id {
+ type fpcbase:fpc-context-id;
+ }
+ leaf dormant {
+ type boolean;
+ }
+ leaf-list ports {
+ type fpcbase:fpc-port-id;
+ }
+ leaf dpn-group {
+ type fpcbase:fpc-dpn-group-id;
+ }
+ leaf-list delegating-ip-prefixes {
+ type inet:ip-prefix;
+ }
+ container ul {
+ if-feature fpcbase:fpc-basic-agent;
+ uses fpcbase:fpc-context-profile;
+ }
+ container dl {
+ if-feature fpcbase:fpc-basic-agent;
+ uses fpcbase:fpc-context-profile;
+ }
+ list dpns {
+ if-feature fpcbase:fpc-multi-dpn;
+ key "dpn-id direction";
+ leaf dpn-id {
+ type fpcbase:fpc-dpn-id;
+ }
+ leaf direction {
+ mandatory true;
+ type fpcbase:fpc-direction;
+ }
+ uses fpcbase:fpc-context-profile;
+ }
+ leaf parent-context {
+ type fpcbase:fpc-context-id;
+ }
+ uses threegpp:threegpp-properties;
+ }
+
+ // Mobility (Tunnel) Information
+ grouping mobility-info {
+ choice mobprofile-parameters {
+ case nothing {
+ leaf none {
+ type empty;
+ }
+ }
+ case pmip-tunnel {
+ uses fpc-pmip:pmip-mobility;
+ choice pmiptunnel-or-ref {
+ case defined-selector {
+ uses traffic-selectors:traffic-selector;
+ }
+ case predefined-selector {
+ leaf selector-reference {
+ type fpcbase:fpc-identity;
+ }
+ }
+ }
+ }
+ case threegpp-tunnel {
+ uses threegpp:threeGPP-tunnel;
+ choice tft-or-ref {
+ case defined-tft {
+ uses threegpp:tft;
+ }
+ case predefined-tft {
+ leaf tft-reference {
+ type fpcbase:fpc-identity;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // Next Hop Structures
+ typedef fpcp-service-path-id {
+ type uint32 {
+ range "0..33554431";
+ }
+ description "SERVICE_PATH_ID";
+ }
+
+ identity fpc-nexthop-type {
+ description "Next Hop Type";
+ }
+ identity fpc-nexthop-ip {
+ base "fpcbase:fpc-nexthop-type";
+ }
+ identity fpc-nexthop-servicepath {
+ base "fpcbase:fpc-nexthop-type";
+ }
+ grouping fpc-nexthop {
+ leaf nexthop-type {
+ type identityref {
+ base "fpcbase:fpc-nexthop-type";
+ }
+ }
+ choice nexthop-value {
+ case ip {
+ leaf ip {
+ type inet:ip-address;
+ }
+ }
+ case servicepath {
+ leaf servicepath {
+ type fpcbase:fpcp-service-path-id;
+ }
+ }
+ }
+ }
+
+ // QoS Information
+ identity fpc-qos-type {
+ description "Base identity from which specific uses of QoS types are derived.";
+ }
+ grouping fpc-qos-profile {
+ leaf qos-type {
+ type identityref {
+ base fpcbase:fpc-qos-type;
+ }
+ description "the profile type";
+ }
+ choice value {
+ case qos-pmip {
+ uses qos-pmip:qosattribute;
+ }
+ case threegpp-qos {
+ uses threegpp:threeGPP-QoS;
+ }
+ }
+ }
+
+ // Vendor Specific Attributes
+ identity vendor-specific-type {
+ description "Vendor Specific Attribute Type";
+ }
+ grouping vendor-attributes {
+ leaf vendor-id {
+ type fpcbase:fpc-identity;
+ }
+ leaf vendor-type {
+ type identityref {
+ base "fpcbase:vendor-specific-type";
+ }
+ }
+ choice value {
+ case empty-type {
+ leaf empty-type {
+ type empty;
+ }
+ }
+ }
+ }
+
+ // Topology
+ typedef fpc-domain-id {
+ type fpcbase:fpc-identity;
+ }
+ grouping fpc-domain {
+ leaf domain-id {
+ type fpcbase:fpc-domain-id;
+ }
+ leaf domain-name {
+ type string;
+ }
+ leaf domain-type {
+ type string;
+ }
+ }
+
+ typedef fpc-dpn-id {
+ type fpcbase:fpc-identity;
+ description "DPN Identifier";
+ }
+ identity fpc-dpn-control-protocol {
+ description "DPN Control Protocol";
+ }
+ grouping fpc-dpn {
+ leaf dpn-id {
+ type fpcbase:fpc-dpn-id;
+ }
+ leaf dpn-name {
+ type string;
+ }
+ leaf-list dpn-groups {
+ type fpcbase:fpc-dpn-group-id;
+ }
+ leaf node-reference {
+ type instance-identifier;
+ }
+ leaf abstract {
+ type boolean;
+ }
+ leaf strategy {
+ type string;
+ }
+ leaf-list dpn-ids {
+ type fpcbase:fpc-dpn-id;
+ }
+ leaf node-id {
+ type string;
+ }
+ leaf network-id {
+ type string;
+ }
+ }
+
+ typedef fpc-dpn-group-id {
+ type fpcbase:fpc-identity;
+ description "DPN Group Identifier";
+ }
+ identity fpc-forwaridingplane-role {
+ description "Role of DPN Group in the Forwarding Plane";
+ }
+ identity fpc-access-type {
+ description "Access Type of the DPN Group";
+ }
+ identity fpc-mobility-profile-type {
+ description "Mobility Profile Type";
+ }
+
+ grouping fpc-dpn-peer-group {
+ leaf remote-dpn-group-id {
+ type fpcbase:fpc-dpn-group-id;
+ }
+ leaf remote-mobility-profile {
+ type identityref {
+ base "fpcbase:fpc-mobility-profile-type";
+ }
+ }
+ leaf remote-data-plane-role {
+ type identityref {
+ base "fpcbase:fpc-forwaridingplane-role";
+ }
+ }
+ leaf remote-endpoint-address {
+ type inet:ip-address;
+ }
+ leaf local-endpoint-address {
+ type inet:ip-address;
+ }
+ leaf tunnel-mtu-size {
+ type uint32;
+ }
+ }
+
+ // Events, Probes & Notifications
+ identity event-type {
+ description "Base Event Type";
+ }
+
+ typedef event-type-id {
+ type uint32;
+ }
+
+ grouping monitor-id {
+ leaf monitor-id {
+ type fpcbase:fpc-identity;
+ }
+ }
+
+ identity report-type {
+ description "Type of Report";
+ }
+ identity periodic-report {
+ base "fpcbase:report-type";
+ }
+ identity threshold-report {
+ base "fpcbase:report-type";
+ }
+ identity scheduled-report {
+ base "fpcbase:report-type";
+ }
+ identity events-report {
+ base "fpcbase:report-type";
+ }
+
+ grouping report-config {
+ choice event-config-value {
+ case periodic-config {
+ leaf period {
+ type uint32;
+ }
+ }
+ case threshold-config {
+ leaf lo-thresh {
+ type uint32;
+ }
+ leaf hi-thresh {
+ type uint32;
+ }
+ }
+ case scheduled-config {
+ leaf report-time {
+ type uint32;
+ }
+ }
+ case events-config-ident {
+ leaf-list event-identities {
+ type identityref {
+ base "fpcbase:event-type";
+ }
+ }
+ }
+ case events-config {
+ leaf-list event-ids {
+ type uint32;
+ }
+ }
+ }
+ }
+
+ grouping monitor-config {
+ uses fpcbase:monitor-id;
+ uses fpcbase:target-value;
+ uses fpcbase:report-config;
+ }
+
+ grouping report {
+ uses fpcbase:monitor-config;
+ choice report-value {
+ leaf trigger {
+ type fpcbase:event-type-id;
+ }
+ case simple-empty {
+ leaf nothing {
+ type empty;
+ }
+ }
+ case simple-val32 {
+ leaf val32 {
+ type uint32;
+ }
+ }
+ case any-data {
+ leaf data {
+ type string;
+ }
+ }
+ }
+ }
+
+ // PMIP Identities
+ identity ietf-pmip-access-type {
+ base "fpcbase:fpc-access-type";
+ }
+
+ identity fpcp-qos-index-pmip {
+ base "fpcbase:fpc-qos-type";
+ }
+ identity traffic-selector-mip6 {
+ base "fpcbase:fpc-descriptor-type";
+ }
+ identity ietf-pmip {
+ base "fpcbase:fpc-mobility-profile-type";
+ }
+
+ // Threegpp
+ identity threeGPP-qos-profile-parameters {
+ base "fpcbase:fpc-qos-type";
+ }
+
+ identity threeGPP-access-type {
+ base "fpcbase:fpc-access-type";
+ }
+
+ // Profile Type
+ identity threeGPP-mobility {
+ base "fpcbase:fpc-mobility-profile-type";
+ }
+
+ // Policy Extensions
+ identity service-function {
+ base "fpcbase:fpc-descriptor-type";
+ description "Base Identifier for Service Functions.";
+ }
+
+ identity napt-service {
+ base "service-function";
+ }
+
+ identity nat-service {
+ base "service-function";
+ }
+
+ identity copy-forward {
+ base "fpcbase:fpc-descriptor-type";
+ description "Copies a packet then forwards to a specific destination";
+ }
+ grouping copy-forward {
+ container destination {
+ choice value {
+ case port-ref {
+ leaf port-ref {
+ type fpcbase:fpc-port-id;
+ }
+ }
+ case context-ref {
+ leaf context-ref {
+ type fpcbase:fpc-context-id;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/models/fpcagent/src/main/yang/ietf-dmm-threegpp.yang b/models/fpcagent/src/main/yang/ietf-dmm-threegpp.yang
new file mode 100644
index 0000000..1439224
--- /dev/null
+++ b/models/fpcagent/src/main/yang/ietf-dmm-threegpp.yang
@@ -0,0 +1,330 @@
+module ietf-dmm-threegpp {
+ namespace "urn:ietf:params:xml:ns:yang:threegpp";
+ prefix threegpp;
+
+ import ietf-inet-types { prefix inet; revision-date 2013-07-15; }
+ import ietf-traffic-selector-types { prefix traffic-selectors; revision-date 2016-01-14; }
+ import ietf-pmip-qos { prefix pmipqos; revision-date 2016-02-10; }
+
+
+ organization "IETF DMM Working Group";
+ contact "Satoru Matsushima <satoru.matsushima@g.softbank.co.jp>";
+
+ description
+ "This module contains YANG definition for
+ 3GPP Related Mobility Structures";
+
+ revision 2016-08-03 {
+ description "Initial";
+ reference "draft-ietf-dmm-fpc-cpdp-04";
+ }
+
+ // Tunnel Types
+ identity threeGPP-tunnel-type {
+ description "Base Tunnel Type";
+ }
+
+ identity gtpv1 {
+ base "threegpp:threeGPP-tunnel-type";
+ }
+
+ identity gtpv2 {
+ base "threegpp:threeGPP-tunnel-type";
+ }
+
+ grouping teid-value {
+ leaf tunnel-identifier {
+ description "TEID";
+ type uint32;
+ }
+ }
+
+ grouping threeGPP-tunnel {
+ leaf tunnel-type {
+ type identityref {
+ base "threegpp:threeGPP-tunnel-type";
+ }
+ }
+ uses threegpp:teid-value;
+ }
+
+ // QoS Profile
+ typedef fpc-qos-class-identifier {
+ type uint8 {
+ range "1..9";
+ }
+ description "QCI";
+ }
+
+ grouping threeGPP-QoS {
+ leaf qci {
+ type fpc-qos-class-identifier;
+ }
+ leaf gbr {
+ type uint32;
+ }
+ leaf mbr {
+ type uint32;
+ }
+ leaf apn-ambr {
+ type uint32;
+ }
+ leaf ue-ambr {
+ type uint32;
+ }
+ container arp {
+ uses pmipqos:Allocation-Retention-Priority-Value;
+ }
+ }
+
+ typedef ebi-type {
+ type uint8 {
+ range "0..15";
+ }
+ }
+
+ // From 3GPP TS 24.008 version 13.5.0 Release 13
+ typedef component-type-enum {
+ type enumeration {
+ enum ipv4RemoteAddress { value 16; }
+ enum ipv4LocalAddress { value 17; }
+ enum ipv6RemoteAddress { value 32; }
+ enum ipv6RemoteAddressPrefix { value 33; }
+ enum ipv6LocalAddressPrefix { value 35; }
+ enum protocolNextHeader { value 48; }
+ enum localPort { value 64; }
+ enum localPortRange { value 65; }
+ enum reomotePort { value 80; }
+ enum remotePortRange { value 81; }
+ enum secParamIndex { value 96; }
+ enum tosTraffClass { value 112; }
+ enum flowLabel { value 128; }
+ }
+ }
+
+ typedef packet-filter-direction {
+ type enumeration {
+ enum preRel7Tft { value 0; }
+ enum uplink { value 1; }
+ enum downlink { value 2; }
+ enum bidirectional { value 3; }
+ }
+ }
+
+ typedef component-type-id {
+ type uint8 {
+ range "16 | 17 | 32 | 33 | 35 | 48 | 64 | 65 | 80 | 81 | 96 | 112 | 128";
+ }
+ }
+
+ typedef sponsor-identity-type {
+ type string;
+ }
+
+ grouping packet-filter {
+ leaf direction {
+ type threegpp:packet-filter-direction;
+ }
+ leaf identifier {
+ type uint8 {
+ range "1..15";
+ }
+ }
+ leaf evaluation-precedence {
+ type uint8;
+ }
+ list contents {
+ key component-type-identifier;
+ leaf component-type-identifier {
+ type threegpp:component-type-id;
+ }
+ choice value {
+ case ipv4-local {
+ leaf ipv4-local {
+ type inet:ipv4-address;
+ }
+ leaf ipv4-local-mask {
+ type inet:ipv4-address;
+ }
+ }
+ case ipv6-address-local {
+ leaf ipv6-address-local {
+ type inet:ipv6-prefix;
+ }
+ leaf ipv6-address-local-mask {
+ type inet:ipv6-prefix;
+ }
+ }
+ case ipv6-prefix-local {
+ leaf ipv6-prefix-local {
+ type inet:ipv6-prefix;
+ }
+ }
+
+ case ipv4-ipv6-remote {
+ leaf ipv4-ipv6-remote {
+ type inet:ip-address;
+ }
+ leaf ipv4-ipv6-remote-mask {
+ type inet:ip-address;
+ }
+ }
+
+ case ipv4-remote {
+ leaf ipv4-remote {
+ type inet:ipv4-address;
+ }
+ leaf ipv4-remote-mask {
+ type inet:ipv4-address;
+ }
+ }
+ case ipv6-address-remote {
+ leaf ipv6-address-remote {
+ type inet:ipv6-prefix;
+ }
+ leaf ipv6-address-remote-mask {
+ type inet:ipv6-prefix;
+ }
+ }
+ case ipv6-prefix-remote {
+ leaf ipv6-prefix-remote {
+ type inet:ipv6-prefix;
+ }
+ }
+
+ case protocol-next-header {
+ leaf next-header {
+ type uint8;
+ }
+ }
+
+ case local-port {
+ leaf local-port {
+ type inet:port-number;
+ }
+ }
+ case local-port-range {
+ leaf local-port-lo {
+ type inet:port-number;
+ }
+ leaf local-port-hi {
+ type inet:port-number;
+ }
+ }
+ case remote-port {
+ leaf remote-port {
+ type inet:port-number;
+ }
+ }
+ case remote-port-range {
+ leaf remote-port-lo {
+ type inet:port-number;
+ }
+ leaf remote-port-hi {
+ type inet:port-number;
+ }
+ }
+ case ipsec-index {
+ leaf ipsec-index {
+ type traffic-selectors:ipsec-spi;
+ }
+ }
+ case traffic-class {
+ leaf traffic-class {
+ type inet:dscp;
+ }
+ }
+ case traffic-class-range {
+ leaf traffic-class-lo {
+ type inet:dscp;
+ }
+ leaf traffic-class-hi {
+ type inet:dscp;
+ }
+ }
+ case flow-label-type {
+ leaf-list flow-label-type {
+ type inet:ipv6-flow-label;
+ }
+ }
+ }
+ }
+ }
+
+ grouping tft {
+ list packet-filters {
+ key identifier;
+ uses threegpp:packet-filter;
+ }
+ }
+
+ typedef imsi-type {
+ type uint64;
+ }
+
+ typedef threegpp-instr {
+ description "Instruction Set for 3GPP R11";
+ type bits {
+ bit assign-ip {
+ position 0;
+ }
+ bit assign-fteid-ip {
+ position 1;
+ }
+ bit assign-fteid-teid {
+ position 2;
+ }
+ bit session {
+ position 3;
+ }
+ bit uplink {
+ position 4;
+ }
+ bit downlink {
+ position 5;
+ }
+ bit assign-dpn {
+ position 6;
+ }
+ bit indirect-forward {
+ position 7;
+ }
+ bit create_new_tft {
+ position 8;
+ }
+ bit delete_existing_tft {
+ position 9;
+ }
+ bit add_filters_to_existing_tft {
+ position 10;
+ }
+ bit replace_filters_in_existing_tft {
+ position 11;
+ }
+ bit delete_filters_from_existing_tft {
+ position 12;
+ }
+ bit no_tft_op {
+ position 13;
+ }
+ }
+ }
+
+ grouping threegpp-properties {
+ leaf imsi {
+ type threegpp:imsi-type;
+ }
+ leaf ebi {
+ type threegpp:ebi-type;
+ }
+ leaf lbi {
+ type threegpp:ebi-type;
+ }
+ }
+
+ grouping threegpp-commandset {
+ leaf instr-3gpp-mob {
+ type threegpp:threegpp-instr;
+ }
+ }
+}
diff --git a/models/fpcagent/src/main/yang/ietf-pmip-qos.yang b/models/fpcagent/src/main/yang/ietf-pmip-qos.yang
new file mode 100644
index 0000000..4a22355
--- /dev/null
+++ b/models/fpcagent/src/main/yang/ietf-pmip-qos.yang
@@ -0,0 +1,564 @@
+module ietf-pmip-qos {
+ yang-version 1;
+
+ namespace
+ "urn:ietf:params:xml:ns:yang:ietf-pmip-qos";
+
+ prefix "qos-pmip";
+
+ import ietf-inet-types {
+ prefix inet;
+ revision-date 2013-07-15;
+ }
+ import ietf-traffic-selector-types { prefix traffic-selectors; }
+
+ organization
+ "IETF DMM (Dynamic Mobility Management) Working Group";
+
+ contact
+ "WG Web: <https://datatracker.ietf.org/wg/dmm/>
+ WG List: <mailto:dmm@ietf.org>
+
+ WG Chair: Dapeng Liu
+ <mailto:maxpassion@gmail.com>
+
+ WG Chair: Jouni Korhonen
+ <mailto:jouni.nospam@gmail.com>
+
+ Editor:
+ <mailto:>";
+
+ description
+ "This module contains a collection of YANG definitions for
+ quality of service paramaters used in Proxy Mobile IPv6.
+
+ Copyright (c) 2015 IETF Trust and the persons identified as
+ authors of the code. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or
+ without modification, is permitted pursuant to, and subject
+ to the license terms contained in, the Simplified BSD License
+ set forth in Section 4.c of the IETF Trust's Legal Provisions
+ Relating to IETF Documents
+ (http://trustee.ietf.org/license-info).
+
+ This version of this YANG module was created as part of the IETF
+ DMM FPC YANG modules; see the RFC itself for full legal notices.";
+
+ revision 2016-02-10 {
+ description "Initial revision";
+ reference
+ "RFC 7222: Quality-of-Service Option for Proxy Mobile IPv6";
+ }
+
+ // Type Definitions
+
+ // QoS Option Field Type Definitions
+ typedef sr-id {
+ type uint8;
+ description
+ "An 8-bit unsigned integer used
+ for identifying the QoS Service Request. Its uniqueness is within
+ the scope of a mobility session. The local mobility anchor always
+ allocates the Service Request Identifier. When a new QoS Service
+ Request is initiated by a mobile access gateway, the Service
+ Request Identifier in the initial request message is set to a
+ value of (0), and the local mobility anchor allocates a Service
+ Request Identifier and includes it in the response. For any new
+ QoS Service Requests initiated by a local mobility anchor, the
+ Service Request Identifier is set to the allocated value.";
+ }
+
+ typedef traffic-class {
+ type inet:dscp;
+ description
+ "Traffic Class consists of a 6-bit DSCP field followed by a 2-bit
+ reserved field.";
+ reference
+ "RFC 3289: Management Information Base for the Differentiated
+ Services Architecture
+ RFC 2474: Definition of the Differentiated Services Field
+ (DS Field) in the IPv4 and IPv6 Headers
+ RFC 2780: IANA Allocation Guidelines For Values In
+ the Internet Protocol and Related Headers";
+ }
+
+ typedef operational-code {
+ type enumeration {
+ enum RESPONSE { value 0; }
+ enum ALLOCATE { value 1; }
+ enum DE-ALLOCATE { value 2; }
+ enum MODIFY { value 3; }
+ enum QUERY { value 4; }
+ enum NEGOTIATE { value 5; }
+ }
+ description
+ "1-octet Operational code indicates the type of QoS request.
+
+ RESPONSE: (0)
+ Response to a QoS request
+
+ ALLOCATE: (1)
+ Request to allocate QoS resources
+
+ DE-ALLOCATE: (2)
+ Request to de-Allocate QoS resources
+
+ MODIFY: (3)
+ Request to modify QoS parameters for a previously negotiated
+ QoS Service Request
+
+ QUERY: (4)
+ Query to list the previously negotiated QoS Service Requests
+ that are still active
+
+ NEGOTIATE: (5)
+ Response to a QoS Service Request with a counter QoS proposal
+
+ Reserved: (6) to (255)
+ Currently not used. Receiver MUST ignore the option received
+ with any value in this range.";
+ }
+
+ // QoS Attribute Types
+
+ //The enumeration value for mapping - don't confuse with the identities
+ typedef qos-attrubite-type-enum {
+ type enumeration {
+ enum Reserved { value 0; }
+ enum Per-MN-Agg-Max-DL-Bit-Rate { value 1; }
+ enum Per-MN-Agg-Max-UL-Bit-Rate { value 2; }
+ enum Per-Session-Agg-Max-DL-Bit-Rate { value 3; }
+ enum Per-Session-Agg-Max-UL-Bit-Rate { value 4; }
+ enum Allocation-Retention-Priority { value 5; }
+ enum Aggregate-Max-DL-Bit-Rate { value 6; }
+ enum Aggregate-Max-UL-Bit-Rate { value 7; }
+ enum Guaranteed-DL-Bit-Rate { value 8; }
+ enum Guaranteed-UL-Bit-Rate { value 9; }
+ enum QoS-Traffic-Selector { value 10; }
+ enum QoS-Vendor-Specific-Attribute { value 11; }
+ }
+ description
+ "8-bit unsigned integer indicating the type of the QoS
+ attribute. This specification reserves the following values.
+ (0) - Reserved
+ This value is reserved and cannot be used
+
+ (1) - Per-MN-Agg-Max-DL-Bit-Rate
+ Per-Mobile-Node Aggregate Maximum Downlink Bit Rate.
+
+ (2) - Per-MN-Agg-Max-UL-Bit-Rate
+ Per-Mobile-Node Aggregate Maximum Uplink Bit Rate.
+
+ (3) - Per-Session-Agg-Max-DL-Bit-Rate
+ Per-Mobility-Session Aggregate Maximum Downlink Bit Rate.
+
+ (4) - Per-Session-Agg-Max-UL-Bit-Rate
+ Per-Mobility-Session Aggregate Maximum Uplink Bit Rate.
+
+ (5) - Allocation-Retention-Priority
+ Allocation and Retention Priority.
+
+ (6) - Aggregate-Max-DL-Bit-Rate
+ Aggregate Maximum Downlink Bit Rate.
+
+ (7) - Aggregate-Max-UL-Bit-Rate
+ Aggregate Maximum Uplink Bit Rate.
+
+ (8) - Guaranteed-DL-Bit-Rate
+ Guaranteed Downlink Bit Rate.
+
+ (9) - Guaranteed-UL-Bit-Rate
+ Guaranteed Uplink Bit Rate.
+
+ (10) - QoS-Traffic-Selector
+ QoS Traffic Selector.
+
+ (11) - QoS-Vendor-Specific-Attribute
+ QoS Vendor-Specific Attribute.
+
+ (12) to (254) - Reserved
+ These values are reserved for future allocation.
+
+ (255) - Reserved
+ This value is reserved and cannot be used.";
+ }
+
+ // Attribute Type as Identities
+ // Added for convenience of inclusion and extension in other YANG modules.
+ identity qos-attribute-type {
+ description
+ "Base type for Quality of Service Attributes";
+ }
+
+ identity Per-MN-Agg-Max-DL-Bit-Rate-type {
+ base qos-attribute-type;
+ description
+ "Per-Mobile-Node Aggregate Maximum Downlink Bit Rate.";
+ }
+
+ identity Per-MN-Agg-Max-UL-Bit-Rate-type {
+ base qos-attribute-type;
+ description
+ "Per-Mobile-Node Aggregate Maximum Uplink Bit Rate";
+ }
+
+ identity Per-Session-Agg-Max-DL-Bit-Rate-type {
+ base qos-attribute-type;
+ description
+ "Per-Mobility-Session Aggregate Maximum Downlink Bit Rate.";
+ }
+
+ identity Per-Session-Agg-Max-UL-Bit-Rate-type {
+ base qos-attribute-type;
+ description
+ "Per-Mobility-Session Aggregate Maximum Uplink Bit Rate.";
+ }
+
+ identity Allocation-Retention-Priority-type {
+ base qos-attribute-type;
+ description
+ "Allocation and Retention Priority.";
+ }
+
+ identity Aggregate-Max-DL-Bit-Rate-type {
+ base qos-attribute-type;
+ description "Aggregate Maximum Downlink Bit Rate.";
+ }
+
+ identity Aggregate-Max-UL-Bit-Rate-type {
+ base qos-attribute-type;
+ description "Aggregate Maximum Uplink Bit Rate.";
+ }
+
+ identity Guaranteed-DL-Bit-Rate-type {
+ base qos-attribute-type;
+ description "Guaranteed Downlink Bit Rate.";
+ }
+
+ identity Guaranteed-UL-Bit-Rate-type {
+ base qos-attribute-type;
+ description "Guaranteed Uplink Bit Rate.";
+ }
+
+ identity QoS-Traffic-Selector-type {
+ base qos-attribute-type;
+ description "QoS Traffic Selector.";
+ }
+
+ identity QoS-Vendor-Specific-Attribute-type {
+ base qos-attribute-type;
+ description "QoS Vendor-Specific Attribute.";
+ }
+
+ //value definitions
+ typedef Per-MN-Agg-Max-DL-Bit-Rate-Value {
+ type uint32;
+ description
+ "This is a 32-bit unsigned integer that
+ indicates the aggregate maximum downlink bit rate that is
+ requested/allocated for all the mobile node's IP flows. The
+ measurement units for Per-MN-Agg-Max-DL-Bit-Rate are bits per
+ second.";
+ }
+
+ typedef Per-MN-Agg-Max-UL-Bit-Rate-Value {
+ type uint32;
+ description
+ "This is a 32-bit unsigned integer that
+ indicates the aggregate maximum uplink bit rate that is requested/
+ allocated for the mobile node's IP flows. The measurement units
+ for Per-MN-Agg-Max-UL-Bit-Rate are bits per second.";
+ }
+
+ // Generic Structure for the uplink and downlink
+ grouping Per-Session-Agg-Max-Bit-Rate-Value {
+ leaf max-rate {
+ type uint32;
+ mandatory true;
+ description
+ "This is a 32-bit unsigned integer
+ that indicates the aggregate maximum bit rate that is requested/allocated
+ for all the IP flows associated with that mobility session. The measurement
+ units for Per-Session-Agg-Max-UL/DL-Bit-Rate are bits per second.";
+ }
+ leaf service-flag {
+ type boolean;
+ mandatory true;
+ description
+ "This flag is used for extending the scope of the
+ target flows for Per-Session-Agg-Max-UL/DL-Bit-Rate from(UL)/to(DL) the mobile
+ node's other mobility sessions sharing the same Service
+ Identifier. 3GPP Access Point Name (APN) is an example of a
+ Service Identifier, and that identifier is carried using the
+ Service Selection mobility option [RFC5149].
+
+ * When the (S) flag is set to a value of (1), then the Per-
+ Session-Agg-Max-Bit-Rate is measured as an aggregate across
+ all the mobile node's other mobility sessions sharing the same
+ Service Identifier associated with this mobility session.
+
+ * When the (S) flag is set to a value of (0), then the target
+ flows are limited to the current mobility session.
+
+ * The (S) flag MUST NOT be set to a value of (1) when there is no
+ Service Identifier associated with the mobility session.";
+ reference
+ "RFC 5149 - Service Selection mobility option";
+ }
+ leaf exclude-flag {
+ type boolean;
+ mandatory true;
+ description
+ "This flag is used to request that the uplink/downlink
+ flows for which the network is providing Guaranteed-Bit-Rate
+ service be excluded from the target IP flows for which Per-
+ Session-Agg-Max-UL/DL-Bit-Rate is measured.
+
+ * When the (E) flag is set to a value of (1), then the request is
+ to exclude the IP flows for which Guaranteed-UL/DL-Bit-Rate
+ is negotiated from the flows for which Per-Session-Agg-Max-UL/DL-Bit-Rate
+ is measured.
+
+ * When the (E) flag is set to a value of (0), then the request is
+ not to exclude any IP flows from the target IP flows for which
+ Per-Session-Agg-Max-UL/DL-Bit-Rate is measured.
+
+ * When the (S) flag and (E) flag are both set to a value of (1),
+ then the request is to exclude all the IP flows sharing the
+ Service Identifier associated with this mobility session from
+ the target flows for which Per-Session-Agg-Max-UL/DL-Bit-Rate is
+ measured.";
+ }
+ }
+
+ grouping Allocation-Retention-Priority-Value {
+ leaf prioirty-level {
+ type uint8 {
+ range "0..15";
+ }
+ mandatory true;
+ description
+ "This is a 4-bit unsigned integer value. It
+ is used to decide whether a mobility session establishment or
+ modification request can be accepted; this is typically used for
+ admission control of Guaranteed Bit Rate traffic in case of
+ resource limitations. The priority level can also be used to
+
+ decide which existing mobility session to preempt during resource
+ limitations. The priority level defines the relative timeliness
+ of a resource request.
+
+ Values 1 to 15 are defined, with value 1 as the highest level of
+ priority.
+
+ Values 1 to 8 should only be assigned for services that are
+ authorized to receive prioritized treatment within an operator
+ domain. Values 9 to 15 may be assigned to resources that are
+ authorized by the home network and thus applicable when a mobile
+ node is roaming.";
+ }
+ leaf premption-capability {
+ type enumeration {
+ enum enabled { value 0; }
+ enum disabled { value 1; }
+ enum reserved1 { value 2; }
+ enum reserved2 { value 3; }
+ }
+ mandatory true;
+ description
+ "This is a 2-bit unsigned integer
+ value. It defines whether a service data flow can get resources
+ that were already assigned to another service data flow with a
+ lower priority level. The following values are defined:
+
+ Enabled (0): This value indicates that the service data flow is
+ allowed to get resources that were already assigned to another
+ IP data flow with a lower priority level.
+
+ Disabled (1): This value indicates that the service data flow
+ is not allowed to get resources that were already assigned to
+ another IP data flow with a lower priority level. The values
+ (2) and (3) are reserved.";
+ }
+ leaf premption-vulnerability {
+ type enumeration {
+ enum enabled { value 0; }
+ enum disabled { value 1; }
+ enum reserved1 { value 2; }
+ enum reserved2 { value 3; }
+ }
+ mandatory true;
+ description
+ "This is a 2-bit unsigned integer
+ value. It defines whether a service data flow can lose the
+ resources assigned to it in order to admit a service data flow
+ with a higher priority level. The following values are defined:
+
+ Enabled (0): This value indicates that the resources assigned
+ to the IP data flow can be preempted and allocated to a service
+ data flow with a higher priority level.
+
+ Disabled (1): This value indicates that the resources assigned
+ to the IP data flow shall not be preempted and allocated to a
+ service data flow with a higher priority level. The values (2)
+ and (3) are reserved.";
+ }
+ }
+
+ typedef Aggregate-Max-DL-Bit-Rate-Value {
+ type uint32;
+ description
+ "This is a 32-bit unsigned integer that
+ indicates the aggregate maximum downlink bit rate that is
+ requested/allocated for downlink IP flows. The measurement units
+ for Aggregate-Max-DL-Bit-Rate are bits per second.";
+ }
+
+ typedef Aggregate-Max-UL-Bit-Rate-Value {
+ type uint32;
+ description
+ "This is a 32-bit unsigned integer that
+ indicates the aggregate maximum downlink bit rate that is
+ requested/allocated for downlink IP flows. The measurement units
+ for Aggregate-Max-DL-Bit-Rate are bits per second.";
+ }
+
+ typedef Guaranteed-DL-Bit-Rate-Value {
+ type uint32;
+ description
+ "This is a 32-bit unsigned integer that
+ indicates the guaranteed bandwidth in bits per second for downlink
+ IP flows. The measurement units for Guaranteed-DL-Bit-Rate are
+ bits per second.";
+ }
+
+ typedef Guaranteed-UL-Bit-Rate-Value {
+ type uint32;
+ description
+ "This is a 32-bit unsigned integer that
+ indicates the guaranteed bandwidth in bits per second for uplink
+ IP flows. The measurement units for Guaranteed-UL-Bit-Rate are
+ bits per second.";
+ }
+
+ grouping QoS-Vendor-Specific-Attribute-Value-Base {
+ leaf vendorid {
+ type uint32;
+ mandatory true;
+ description
+ "The Vendor ID is the SMI (Structure of Management
+ Information) Network Management Private Enterprise Code of the
+ IANA-maintained 'Private Enterprise Numbers' registry [SMI].";
+ reference
+ "'PRIVATE ENTERPRISE NUMBERS', SMI Network Management
+ Private Enterprise Codes, April 2014,
+ <http://www.iana.org/assignments/enterprise-numbers>";
+ }
+ leaf subtype {
+ type uint8;
+ mandatory true;
+ description
+ "An 8-bit field indicating the type of vendor-specific
+ information carried in the option. The namespace for this sub-
+ type is managed by the vendor identified by the Vendor ID field.";
+ }
+ description
+ "QoS Vendor-Specific Attribute.";
+ }
+
+ //NOTE - We do NOT add the Status Codes or other changes in PMIP in this module
+
+ //Primary Structures (groupings)
+ grouping qosattribute {
+ leaf attributetype {
+ type identityref {
+ base qos-attribute-type;
+ }
+ mandatory true;
+ description "the attribute type";
+ }
+
+ //All of the sub-types by constraint
+ choice attribute-choice {
+ case per-mn-agg-max-dl-case {
+ when "../attributetype = 'Per-MN-Agg-Max-DL-Bit-Rate-type'";
+ leaf per-mn-agg-max-dl {
+ type qos-pmip:Per-MN-Agg-Max-DL-Bit-Rate-Value;
+ }
+ }
+ case per-mn-agg-max-ul-case {
+ when "../attributetype = 'Per-MN-Agg-Max-UL-Bit-Rate-type'";
+ leaf per-mn-agg-max-ul {
+ type qos-pmip:Per-MN-Agg-Max-UL-Bit-Rate-Value;
+ }
+ }
+ case per-session-agg-max-dl-case {
+ when "../attributetype = 'Per-Session-Agg-Max-DL-Bit-Rate-type'";
+ container per-session-agg-max-dl {
+ uses qos-pmip:Per-Session-Agg-Max-Bit-Rate-Value;
+ }
+ }
+ case per-session-agg-max-ul-case {
+ when "../attributetype = 'Per-Session-Agg-Max-UL-Bit-Rate-type'";
+ container per-session-agg-max-ul {
+ uses qos-pmip:Per-Session-Agg-Max-Bit-Rate-Value;
+ }
+ }
+ case allocation-retention-priority-case {
+ when "../attributetype = 'Allocation-Retention-Priority-type'";
+ uses qos-pmip:Allocation-Retention-Priority-Value;
+ }
+ case agg-max-dl-case {
+ when "../attributetype = 'Aggregate-Max-DL-Bit-Rate-type'";
+ leaf agg-max-dl {
+ type qos-pmip:Aggregate-Max-DL-Bit-Rate-Value;
+ }
+ }
+ case agg-max-ul-case {
+ when "../attributetype = 'Aggregate-Max-UL-Bit-Rate-type'";
+ leaf agg-max-ul {
+ type qos-pmip:Aggregate-Max-UL-Bit-Rate-Value;
+ }
+ }
+ case gbr-dl-case {
+ when "../attributetype = 'Guaranteed-DL-Bit-Rate-type'";
+ leaf gbr-dl {
+ type qos-pmip:Guaranteed-DL-Bit-Rate-Value;
+ }
+ }
+ case gbr-ul-case {
+ when "../attributetype = 'Guaranteed-UL-Bit-Rate-type'";
+ leaf gbr-ul {
+ type qos-pmip:Guaranteed-UL-Bit-Rate-Value;
+ }
+ }
+ case traffic-selector-case {
+ when "../attributetype = 'QoS-Traffic-Selector-type'";
+ container traffic-selector {
+ uses traffic-selectors:traffic-selector;
+ }
+ }
+ }
+ }
+
+ grouping qosoption {
+ leaf srid {
+ type sr-id;
+ mandatory true;
+ }
+ leaf trafficclass {
+ type traffic-class;
+ mandatory true;
+ }
+ leaf operationcode {
+ type operational-code;
+ mandatory true;
+ }
+ list attributes {
+ unique "attributetype";
+ uses qosattribute;
+ min-elements 1;
+ }
+ }
+}
diff --git a/models/fpcagent/src/main/yang/ietf-traffic-selector-types.yang b/models/fpcagent/src/main/yang/ietf-traffic-selector-types.yang
new file mode 100644
index 0000000..029f3ec
--- /dev/null
+++ b/models/fpcagent/src/main/yang/ietf-traffic-selector-types.yang
@@ -0,0 +1,508 @@
+module ietf-traffic-selector-types {
+ yang-version 1;
+
+ namespace
+ "urn:ietf:params:xml:ns:yang:ietf-traffic-selector-types";
+
+ prefix "ietf-traffic-selectors";
+
+ import ietf-inet-types {
+ prefix inet;
+ revision-date 2013-07-15;
+ }
+
+ organization
+ "IETF DMM (Dynamic Mobility Management) Working Group";
+
+ contact
+ "WG Web: <https://datatracker.ietf.org/wg/dmm/>
+ WG List: <mailto:dmm@ietf.org>
+
+ WG Chair: Dapeng Liu
+ <mailto:maxpassion@gmail.com>
+
+ WG Chair: Jouni Korhonen
+ <mailto:jouni.nospam@gmail.com>
+
+ Editor:
+ <mailto:>";
+
+ description
+ "This module contains a collection of YANG definitions for
+ traffic selectors for flow bindings.
+
+ Copyright (c) 2015 IETF Trust and the persons identified as
+ authors of the code. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or
+ without modification, is permitted pursuant to, and subject
+ to the license terms contained in, the Simplified BSD License
+ set forth in Section 4.c of the IETF Trust's Legal Provisions
+ Relating to IETF Documents
+ (http://trustee.ietf.org/license-info).
+
+ This version of this YANG module was created as part of the IETF
+ DMM FPC YANG modules; see the RFC itself for full legal notices.";
+
+ revision 2016-01-14 {
+ description "Updated for IETF-PACKET-FIELDS module alignment";
+ reference
+ "draft-ietf-netmod-acl-model-06";
+ }
+
+ revision 2016-01-12 {
+ description "Initial revision";
+ reference
+ "RFC 6088: Traffic Selectors for Flow Bindings";
+ }
+
+ // Identities
+ identity traffic-selector-format {
+ description "The base type for Traffic-Selector Formats";
+ }
+
+ identity ipv4-binary-selector-format {
+ base traffic-selector-format;
+ description
+ "IPv4 Binary Traffic Selector Format";
+ }
+
+ identity ipv6-binary-selector-format {
+ base traffic-selector-format;
+ description
+ "IPv6 Binary Traffic Selector Format";
+ }
+
+ // Type definitions and groupings
+ typedef ipsec-spi {
+ type uint32;
+ description "This type defines the first 32-bit IPsec Security Parameter
+ Index (SPI) value on data packets sent from a corresponding
+ node to the mobile node as seen by the home agent. This field
+ is defined in [RFC4303].";
+ reference
+ "RFC 4303: IP Encapsulating Security Payload (ESP)";
+ }
+
+ grouping traffic-selector-base {
+ description "A grouping of the commen leaves between the v4 and v6 Traffic Selectors";
+ container ipsec-spi-range {
+ presence "Enables setting ipsec spi range";
+ description
+ "Inclusive range representing IPSec Security Parameter Indices to be used.
+ When only start-spi is present, it represents a single spi.";
+ leaf start-spi {
+ type ipsec-spi;
+ mandatory true;
+ description
+ "This field identifies the first 32-bit IPsec SPI value, from the
+ range of SPI values to be matched, on data packets sent from a
+ corresponding node to the mobile node as seen by the home agent.
+ This field is defined in [RFC4303].";
+ }
+ leaf end-spi {
+ type ipsec-spi;
+ must ". >= ../start-spi" {
+ error-message
+ "The end-spi must be greater than or equal to start-spi";
+ }
+ description
+ "If more than one contiguous SPI value needs to be matched, then
+ this field can be used to indicate the end value of a range
+ starting from the value of the Start SPI field. This field
+ MUST NOT be included unless the Start SPI field is included
+ and has a value less than or equal to this field.
+
+ When this field is included, the receiver will match all of the
+ SPI values between fields start-spi and end-spi,
+ inclusive of start-spi and end-spi.";
+ }
+ }
+ container source-port-range {
+ presence "Enables setting source port range";
+ description
+ "Inclusive range representing source ports to be used.
+ When only start-port is present, it represents a single port.";
+ leaf start-port {
+ type inet:port-number;
+ mandatory true;
+ description
+ "This field identifies the first 16-bit source port number, from
+ the range of port numbers to be matched, on data packets sent from
+ a corresponding node to the mobile node as seen by the home agent.
+ This is from the range of port numbers defined by IANA
+ (http://www.iana.org).";
+ }
+ leaf end-port {
+ type inet:port-number;
+ must ". >= ../start-port" {
+ error-message
+ "The end-port must be greater than or equal to start-port";
+ }
+ description
+ "If more than one contiguous source port number needs to be
+ matched, then this field can be used to indicate the end value of
+ a range starting from the value of the Start Port field.
+ This field MUST NOT be included unless the Start Port field
+ is included and has a value less than or equal to this field.
+
+ When this field is included, the receiver will match
+ all of the port numbers between fields start-port and
+ end-port, inclusive of start-port and end-port.";
+ }
+ }
+ container destination-port-range {
+ presence "Enables setting destination port range";
+ description
+ "Inclusive range representing destination ports to be used. When
+ only start-port is present, it represents a single port.";
+ leaf start-port {
+ type inet:port-number;
+ mandatory true;
+ description
+ "This field identifies the first 16-bit destination port number,
+ from the range of port numbers to be matched, on data packets sent
+ from a corresponding node to the mobile node as seen by the home
+ agent.";
+ }
+ leaf end-port {
+ type inet:port-number;
+ must ". >= ../start-port" {
+ error-message
+ "The end-port must be greater than or equal to start-port";
+ }
+ description
+ "If more than one contiguous destination port number needs to be
+ matched, then this field can be used to indicate the end value of
+ a range starting from the value of the Start Destination Port
+ field. This field MUST NOT be included unless the Start
+ Port field is included and has a value less than or equal to this
+ field.
+
+ When this field is included, the receiver will match all of the
+ port numbers between fields start-port and end-port, inclusive of
+ start-port and end-port.";
+ }
+ }
+ }
+
+ grouping ipv4-binary-traffic-selector {
+ container source-address-range-v4 {
+ presence "Enables setting source IPv4 address range";
+ description
+ "Inclusive range representing IPv4 addresses to be used. When
+ only start-address is present, it represents a single address.";
+ leaf start-address {
+ type inet:ipv4-address;
+ mandatory true;
+ description
+ "This field identifies the first source address, from the range of
+ 32-bit IPv4 addresses to be matched, on data packets sent from a
+ corresponding node to the mobile node as seen by the home agent.
+ In other words, this is one of the addresses of the correspondent
+ node.";
+ }
+ leaf end-address {
+ type inet:ipv4-address;
+ description
+ "If more than one contiguous source address needs to be matched,
+ then this field can be used to indicate the end value of a range
+ starting from the value of the Start Address field. This
+ field MUST NOT be included unless the Start Address field
+ is included. When this field is included, the receiver will match
+ all of the addresses between fields start-address and
+ end-address, inclusive of start-address and end-address.";
+ }
+ }
+ container destination-address-range-v4 {
+ presence "Enables setting destination IPv4 address range";
+ description
+ "Inclusive range representing IPv4 addresses to be used. When
+ only start-address is present, it represents a single address.";
+ leaf start-address {
+ type inet:ipv4-address;
+ mandatory true;
+ description
+ "This field identifies the first destination address, from the
+ range of 32-bit IPv4 addresses to be matched, on data packets sent
+ from a corresponding node to the mobile node as seen by the home
+ agent. In other words, this is one of the registered home
+ addresses of the mobile node.";
+ }
+ leaf end-address {
+ type inet:ipv4-address;
+ description
+ "If more than one contiguous destination address needs to be
+ matched, then this field can be used to indicate the end value of
+ a range starting from the value of the Start Destination Address
+ field. This field MUST NOT be included unless the Start
+ Address field is included. When this field is included, the receiver
+ will match all of the addresses between fields start-address and
+ end-address, inclusive of start-address and end-address.";
+ }
+ }
+ container ds-range {
+ presence "Enables setting dscp range";
+ description
+ "Inclusive range representing DiffServ Codepoints to be used. When
+ only start-ds is present, it represents a single Codepoint.";
+ leaf start-ds {
+ type inet:dscp;
+ mandatory true;
+ description
+ "This field identifies the first differential services value, from
+ the range of differential services values to be matched, on data
+ packets sent from a corresponding node to the mobile node as seen
+ by the home agent. Note that this field is called a 'Type of
+ Service field' in [RFC0791]. [RFC3260] then clarified that the
+ field has been redefined as a 6-bit DS field with 2 bits reserved,
+ later claimed by Explicit Congestion Notification (ECN) [RFC3168].
+ For the purpose of this specification, the Start DS field is 8
+ bits long, where the 6 most significant bits indicate the DS field
+ to be matched and the 2 least significant bits' values MUST be
+ ignored in any comparison.";
+ }
+ leaf end-ds {
+ type inet:dscp;
+ must ". >= ../start-ds" {
+ error-message
+ "The end-ds must be greater than or equal to start-ds";
+ }
+ description
+ "If more than one contiguous DS value needs to be matched, then
+ this field can be used to indicate the end value of a range
+ starting from the value of the Start DS field. This field MUST
+ NOT be included unless the Start DS field is included. When this
+ field is included, it MUST be coded the same way as defined for
+ start-ds. When this field is included, the receiver will match all of
+ the values between fields start-ds and end-ds, inclusive of start-ds
+ and end-ds.";
+ }
+ }
+ container protocol-range {
+ presence "Enables setting protocol range";
+ description
+ "Inclusive range representing IP protocol(s) to be used. When
+ only start-protocol is present, it represents a single protocol.";
+ leaf start-protocol {
+ type uint8;
+ mandatory true;
+ description
+ "This field identifies the first 8-bit protocol value, from the
+ range of protocol values to be matched, on data packets sent from
+ a corresponding node to the mobile node as seen by the home agent.";
+ }
+ leaf end-protocol {
+ type uint8;
+ must ". >= ../start-protocol" {
+ error-message
+ "The end-protocol must be greater than or equal to start-protocol";
+ }
+ description
+ "If more than one contiguous protocol value needs to be matched,
+ then this field can be used to indicate the end value of a range
+ starting from the value of the Start Protocol field. This field
+ MUST NOT be included unless the Start Protocol field is included.
+ When this field is included, the receiver will match all of the
+ values between fields start-protocol and end-protocol, inclusive
+ of start-protocol and end-protocol.";
+ }
+ }
+ }
+
+ grouping ipv6-binary-traffic-selector {
+ container source-address-range-v6 {
+ presence "Enables setting source IPv6 address range";
+ description
+ "Inclusive range representing IPv6 addresses to be used. When
+ only start-address is present, it represents a single address.";
+ leaf start-address {
+ type inet:ipv6-address;
+ mandatory true;
+ description
+ "This field identifies the first source address, from the range of
+ 128-bit IPv6 addresses to be matched, on data packets sent from a
+ corresponding node to the mobile node as seen by the home agent.
+ In other words, this is one of the addresses of the correspondent
+ node.";
+ }
+ leaf end-address {
+ type inet:ipv6-address;
+ description
+ "If more than one contiguous source address needs to be matched,
+ then this field can be used to indicate the end value of a range
+ starting from the value of the Start Address field. This
+ field MUST NOT be included unless the Start Address field is included.
+ When this field is included, the receiver will match all of the addresses
+ between fields start-address and end-address, inclusive of start-address
+ and end-address .";
+ }
+ }
+ container destination-address-range-v6 {
+ presence "Enables setting destination IPv6 address range";
+ description
+ "Inclusive range representing IPv6 addresses to be used. When
+ only start-address is present, it represents a single address.";
+ leaf start-address {
+ type inet:ipv6-address;
+ mandatory true;
+ description
+ "This field identifies the first destination address, from the
+ range of 128-bit IPv6 addresses to be matched, on data packets
+ sent from a corresponding node to the mobile node as seen by the
+ home agent. In other words, this is one of the registered home
+ addresses of the mobile node.";
+ }
+ leaf end-address {
+ type inet:ipv6-address;
+ description
+ "If more than one contiguous destination address needs to be
+ matched, then this field can be used to indicate the end value of
+ a range starting from the value of the Start Address field. This
+ field MUST NOT be included unless the Start Address field is included.
+ When this field is included, the receiver will match all of the
+ addresses between fields start-address and end-address, inclusive of
+ start-address and end-address.";
+ }
+ }
+ container flow-label-range {
+ presence "Enables setting Flow Label range";
+ description
+ "Inclusive range representing IPv4 addresses to be used. When
+ only start-flow-label is present, it represents a single flow label.";
+ leaf start-flow-label {
+ type inet:ipv6-flow-label;
+ description
+ "This field identifies the first flow label value, from the range
+ of flow label values to be matched, on data packets sent from a
+ corresponding node to the mobile node as seen by the home agent.
+ According to [RFC2460], the flow label is 24 bits long. For the
+ purpose of this specification, the sender of this option MUST
+ prefix the flow label value with 8 bits of '0' before inserting it
+ in the start-flow-label field. The receiver SHOULD ignore the
+ first 8 bits of this field before using it in comparisons with
+ flow labels in packets.";
+ }
+ leaf end-flow-label {
+ type inet:ipv6-flow-label;
+ must ". >= ../start-flow-label" {
+ error-message
+ "The end-flow-lable must be greater than or equal to start-flow-label";
+ }
+ description
+ "If more than one contiguous flow label value needs to be matched,
+ then this field can be used to indicate the end value of a range
+ starting from the value of the Start Flow Label field. This field
+ MUST NOT be included unless the Start Flow Label field is
+ included. When this field is included, the receiver will match
+ all of the flow label values between fields start-flow-label
+ and end-flow-label, inclusive of start-flow-label and end-flow-label.
+ When this field is included, it MUST be coded the same way as defined
+ for end-flow-label.";
+ }
+ }
+ container traffic-class-range {
+ presence "Enables setting the traffic class range";
+ description
+ "Inclusive range representing IPv4 addresses to be used. When
+ only start-traffic-class is present, it represents a single traffic class.";
+ leaf start-traffic-class {
+ type inet:dscp;
+ description
+ "This field identifies the first traffic class value, from the
+ range of traffic class values to be matched, on data packets sent
+ from a corresponding node to the mobile node as seen by the home
+ agent. This field is equivalent to the Start DS field in the IPv4
+ traffic selector in Figure 1. As per RFC 3260, the field is
+ defined as a 6-bit DS field with 2 bits reserved, later claimed by
+ Explicit Congestion Notification (ECN) RFC 3168. For the purpose
+ of this specification, the start-traffic-class field is 8 bits long, where
+ the 6 most significant bits indicate the DS field to be matched
+ and the 2 least significant bits' values MUST be ignored in any
+ comparison.";
+ reference
+ "RFC 3260: New Terminology and Clarifications for Diffserv
+ RFC 3168: The Addition of Explicit Congestion Notification (ECN) to IP";
+ }
+ leaf end-traffic-class {
+ type inet:dscp;
+ must ". >= ../start-traffic-class" {
+ error-message
+ "The end-traffic-class must be greater than or equal to start-traffic-class";
+ }
+ description
+ "If more than one contiguous TC value needs to be matched, then
+ this field can be used to indicate the end value of a range
+ starting from the value of the Start TC field. This field MUST
+ NOT be included unless the Start TC field is included. When this
+ field is included, it MUST be coded the same way as defined for
+ start-traffic-class. When this field is included, the receiver
+ will match all of the values between fields start-traffic-class
+ and end-traffic-class, inclusive of start-traffic-class and
+ end-traffic-class.";
+ }
+ }
+ container next-header-range {
+ presence "Enables setting Next Header range";
+ description
+ "Inclusive range representing Next Headers to be used. When
+ only start-next-header is present, it represents a single Next Header.";
+ leaf start-next-header {
+ type uint8;
+ description
+ "This field identifies the first 8-bit next header value, from the
+ range of next header values to be matched, on data packets sent
+ from a corresponding node to the mobile node as seen by the home
+ agent.";
+ }
+ leaf end-next-header {
+ type uint8;
+ must ". >= ../start-next-header" {
+ error-message
+ "The end-next-header must be greater than or equal to start-next-header";
+ }
+ description
+ "If more than one contiguous next header value needs to be matched,
+ then this field can be used to indicate the end value of a range
+ starting from the value of the Start NH field. This field MUST
+ NOT be included unless the Start next header field is included.
+ When this field is included, the receiver will match all of the
+ values between fields start-next-header and end-next-header,
+ inclusive of start-next-header and end-next-header.";
+ }
+ }
+ }
+
+ grouping traffic-selector {
+ leaf ts-format {
+ type identityref {
+ base traffic-selector-format;
+ }
+ description "Traffic Selector Format";
+ }
+ uses traffic-selector-base {
+ when "boolean(../ts-format/text() = 'ipv6-binary-selector-format') | boolean(../ts-format/text() = 'ipv4-binary-selector-format')";
+ }
+ uses ipv4-binary-traffic-selector {
+ when "boolean(../ts-format/text() = 'ipv4-binary-selector-format')";
+ }
+ uses ipv6-binary-traffic-selector {
+ when "boolean(../ts-format/text() = 'ipv6-binary-selector-format')";
+ }
+ description
+ "The traffic selector includes the parameters used to match
+ packets for a specific flow binding.";
+ reference
+ "RFC 6089: Flow Bindings in Mobile IPv6 and Network Mobility (NEMO) Basic Support";
+ }
+
+ grouping ts-list {
+ list selectors {
+ key index;
+ leaf index {
+ type uint64;
+ }
+ uses traffic-selector;
+ }
+ }
+}
diff --git a/modules.defs b/modules.defs
new file mode 100644
index 0000000..ad0e561
--- /dev/null
+++ b/modules.defs
@@ -0,0 +1,275 @@
+UTILS = [
+ '//utils/osgi:onlab-osgi',
+ '//utils/junit:onlab-junit',
+ '//utils/misc:onlab-misc',
+ '//utils/rest:onlab-rest',
+ '//tools/build/conf:onos-build-conf',
+]
+
+API = [
+ '//core/api:onos-api',
+ '//incubator/api:onos-incubator-api',
+]
+
+CORE = UTILS + API + [
+ '//core/net:onos-core-net',
+ '//core/common:onos-core-common',
+ '//core/store/primitives:onos-core-primitives',
+ '//core/store/serializers:onos-core-serializers',
+ '//core/store/dist:onos-core-dist',
+ '//core/security:onos-security',
+ '//core/store/persistence:onos-core-persistence',
+
+ '//incubator/net:onos-incubator-net',
+ '//incubator/store:onos-incubator-store',
+ '//incubator/rpc:onos-incubator-rpc',
+
+ '//cli:onos-cli',
+
+ '//protocols/rest/api:onos-protocols-rest-api',
+ '//protocols/rest/ctl:onos-protocols-rest-ctl',
+ '//protocols/bgp/bgpio:onos-protocols-bgp-bgpio',
+ '//protocols/bgp/api:onos-protocols-bgp-api',
+ '//protocols/bgp/ctl:onos-protocols-bgp-ctl',
+ '//protocols/netconf/api:onos-protocols-netconf-api',
+ '//protocols/netconf/ctl:onos-protocols-netconf-ctl',
+ '//protocols/openflow/api:onos-protocols-openflow-api',
+ '//protocols/openflow/ctl:onos-protocols-openflow-ctl',
+ '//protocols/ospf/api:onos-protocols-ospf-api',
+ '//protocols/ospf/protocol:onos-protocols-ospf-protocol',
+ '//protocols/ospf/ctl:onos-protocols-ospf-ctl',
+ '//protocols/ovsdb/rfc:onos-protocols-ovsdb-rfc',
+ '//protocols/ovsdb/api:onos-protocols-ovsdb-api',
+ '//protocols/ovsdb/ctl:onos-protocols-ovsdb-ctl',
+ '//protocols/pcep/pcepio:onos-protocols-pcep-pcepio',
+ '//protocols/pcep/server/api:onos-protocols-pcep-server-api',
+ '//protocols/pcep/server/ctl:onos-protocols-pcep-server-ctl',
+ '//protocols/snmp/api:onos-protocols-snmp-api',
+ '//protocols/snmp/ctl:onos-protocols-snmp-ctl',
+ '//protocols/isis/api:onos-protocols-isis-api',
+ '//protocols/isis/ctl:onos-protocols-isis-ctl',
+ '//protocols/isis/isisio:onos-protocols-isis-isisio',
+ '//protocols/lisp/api:onos-protocols-lisp-api',
+ '//protocols/lisp/ctl:onos-protocols-lisp-ctl',
+ '//protocols/lisp/msg:onos-protocols-lisp-msg',
+ '//protocols/tl1/api:onos-protocols-tl1-api',
+ '//protocols/tl1/ctl:onos-protocols-tl1-ctl',
+ '//protocols/restconf/client/api:onos-protocols-restconf-client-api',
+ '//protocols/restconf/client/ctl:onos-protocols-restconf-client-ctl',
+
+ '//drivers/utilities:onos-drivers-utilities',
+
+ '//providers/netconf/device:onos-providers-netconf-device',
+ '//providers/openflow/device:onos-providers-openflow-device',
+ '//providers/openflow/packet:onos-providers-openflow-packet',
+ '//providers/openflow/flow:onos-providers-openflow-flow',
+ '//providers/openflow/group:onos-providers-openflow-group',
+ '//providers/openflow/meter:onos-providers-openflow-meter',
+ '//providers/ovsdb/device:onos-providers-ovsdb-device',
+ '//providers/ovsdb/tunnel:onos-providers-ovsdb-tunnel',
+ '//providers/rest/device:onos-providers-rest-device',
+ '//providers/snmp/device:onos-providers-snmp-device',
+ '//providers/isis/cfg:onos-providers-isis-cfg',
+ '//providers/isis/topology:onos-providers-isis-topology',
+ '//providers/lisp/device:onos-providers-lisp-device',
+ '//providers/tl1/device:onos-providers-tl1-device',
+ '//providers/general/device:onos-providers-general-device',
+ '//providers/p4runtime/packet:onos-providers-p4runtime-packet',
+
+ '//web/api:onos-rest',
+ '//web/gui:onos-gui',
+
+ '//incubator/protobuf/models:onos-incubator-protobuf-models',
+ '//incubator/protobuf/services/nb:onos-incubator-protobuf-services-nb',
+]
+
+ONOS_DRIVERS = [
+ # Drivers
+ '//drivers/default:onos-drivers-default-oar',
+ '//drivers/arista:onos-drivers-arista-oar',
+ # TODO ONOS-5554 excluding from the build
+ #'//drivers/bti:onos-drivers-bti-oar',
+ '//drivers/ciena:onos-drivers-ciena-oar',
+ '//drivers/cisco/netconf:onos-drivers-cisco-netconf-oar',
+ '//drivers/cisco/rest:onos-drivers-cisco-rest-oar',
+ '//drivers/corsa:onos-drivers-corsa-oar',
+ '//drivers/fujitsu:onos-drivers-fujitsu-oar',
+ '//drivers/lumentum:onos-drivers-lumentum-oar',
+ '//drivers/netconf:onos-drivers-netconf-oar',
+ '//drivers/optical:onos-drivers-optical-oar',
+ '//drivers/ovsdb:onos-drivers-ovsdb-oar',
+ '//drivers/juniper:onos-drivers-juniper-oar',
+ '//drivers/lisp:onos-drivers-lisp-oar',
+ '//drivers/flowspec:onos-drivers-flowspec-oar',
+ '//drivers/huawei:onos-drivers-huawei-oar',
+ '//drivers/microsemi:onos-drivers-microsemi-oar',
+ '//drivers/oplink:onos-drivers-oplink-oar',
+ '//drivers/bmv2:onos-drivers-bmv2-oar',
+ '//drivers/barefoot:onos-drivers-barefoot-oar',
+ '//drivers/hp:onos-drivers-hp-oar',
+ '//drivers/p4runtime:onos-drivers-p4runtime-oar',
+ '//drivers/polatis/netconf:onos-drivers-polatis-netconf-oar',
+]
+
+ONOS_PROVIDERS = [
+ # Providers
+ '//providers/bgp:onos-providers-bgp-oar',
+ '//providers/bgpcep:onos-providers-bgpcep-oar',
+ '//providers/host:onos-providers-host-oar',
+ '//providers/lldp:onos-providers-lldp-oar',
+ '//providers/netcfghost:onos-providers-netcfghost-oar',
+ '//providers/netcfglinks:onos-providers-netcfglinks-oar',
+ '//providers/netconf:onos-providers-netconf-oar',
+ '//providers/openflow/message:onos-providers-openflow-message-oar',
+ '//providers/ovsdb:onos-providers-ovsdb-oar',
+ '//providers/ovsdb/host:onos-providers-ovsdb-host-oar',
+ '//providers/ovsdb/base:onos-providers-ovsdb-base-oar',
+ '//providers/pcep:onos-providers-pcep-oar',
+ '//providers/null:onos-providers-null-oar',
+ '//providers/openflow/base:onos-providers-openflow-base-oar',
+ '//providers/openflow/app:onos-providers-openflow-app-oar',
+ '//providers/rest:onos-providers-rest-oar',
+ '//providers/isis:onos-providers-isis-oar',
+ '//providers/snmp:onos-providers-snmp-oar',
+ '//providers/link:onos-providers-link-oar',
+ '//providers/lisp:onos-providers-lisp-oar',
+ '//providers/tl1:onos-providers-tl1-oar',
+ '//providers/general:onos-providers-general-oar',
+ '//providers/p4runtime:onos-providers-p4runtime-oar',
+# '//providers/ietfte:onos-providers-ietfte-oar',
+]
+
+ONOS_APPS = [
+ # Apps
+ '//apps/dhcp:onos-apps-dhcp-oar',
+ '//apps/dhcprelay:onos-apps-dhcprelay-oar',
+ '//apps/fwd:onos-apps-fwd-oar',
+ '//apps/packet-stats:onos-apps-packet-stats-oar',
+ '//apps/acl:onos-apps-acl-oar',
+ '//apps/bgprouter:onos-apps-bgprouter-oar',
+ '//apps/cip:onos-apps-cip-oar',
+ '//apps/drivermatrix:onos-apps-drivermatrix-oar',
+ '//apps/events:onos-apps-events-oar',
+ '//apps/proxyarp:onos-apps-proxyarp-oar',
+ '//apps/segmentrouting:onos-apps-segmentrouting-oar',
+ '//apps/gangliametrics:onos-apps-gangliametrics-oar',
+ '//apps/graphitemetrics:onos-apps-graphitemetrics-oar',
+ '//apps/flowanalyzer:onos-apps-flowanalyzer-oar',
+ '//apps/intentsync:onos-apps-intentsync-oar',
+ '//apps/influxdbmetrics:onos-apps-influxdbmetrics-oar',
+ '//apps/metrics:onos-apps-metrics-oar',
+ '//apps/mfwd:onos-apps-mfwd-oar',
+ '//apps/mlb:onos-apps-mlb-oar',
+ '//apps/openstacknetworking:onos-apps-openstacknetworking-oar',
+ '//apps/mobility:onos-apps-mobility-oar',
+ '//apps/newoptical:onos-apps-newoptical-oar',
+ '//apps/optical-model:onos-apps-optical-model-oar',
+ '//apps/optical-rest:onos-apps-optical-rest-oar',
+ '//apps/pathpainter:onos-apps-pathpainter-oar',
+ '//apps/pcep-api:onos-apps-pcep-api-oar',
+ '//apps/pim:onos-apps-pim-oar',
+ '//apps/linkprops:onos-apps-linkprops-oar',
+ '//apps/reactive-routing:onos-apps-reactive-routing-oar',
+ '//apps/roadm:onos-apps-roadm-oar',
+ '//apps/sdnip:onos-apps-sdnip-oar',
+ '//apps/test/demo:onos-apps-test-demo-oar',
+ '//apps/test/distributed-primitives:onos-apps-test-distributed-primitives-oar',
+ '//apps/test/election:onos-apps-test-election-oar',
+ '//apps/test/flow-perf:onos-apps-test-flow-perf-oar',
+ '//apps/test/intent-perf:onos-apps-test-intent-perf-oar',
+ '//apps/test/loadtest:onos-apps-test-loadtest-oar',
+ '//apps/test/netcfg-monitor:onos-apps-test-netcfg-monitor-oar',
+ '//apps/test/messaging-perf:onos-apps-test-messaging-perf-oar',
+ '//apps/test/primitive-perf:onos-apps-test-primitive-perf-oar',
+ '//apps/test/transaction-perf:onos-apps-test-transaction-perf-oar',
+ '//apps/virtualbng:onos-apps-virtualbng-oar',
+ '//apps/vpls:onos-apps-vpls-oar',
+ '//apps/vrouter:onos-apps-vrouter-oar',
+ '//apps/routing/fibinstaller:onos-apps-routing-fibinstaller-oar',
+ '//apps/routing/cpr:onos-apps-routing-cpr-oar',
+ '//apps/routing/fpm:onos-apps-routing-fpm-oar',
+ '//apps/vtn:onos-apps-vtn-oar',
+ '//apps/faultmanagement:onos-apps-faultmanagement-oar',
+ '//apps/openstacknode:onos-apps-openstacknode-oar',
+ '//apps/cpman/app:onos-apps-cpman-app-oar',
+ '//apps/scalablegateway:onos-apps-scalablegateway-oar',
+ '//apps/castor:onos-apps-castor-oar',
+# '//apps/yms:onos-apps-yms-oar',
+ '//apps/ofagent:onos-apps-ofagent-oar',
+ '//apps/mappingmanagement:onos-apps-mappingmanagement-oar',
+ '//apps/config:onos-apps-config-oar',
+ '//apps/configsync:onos-apps-configsync-oar',
+ '//apps/configsync-netconf:onos-apps-configsync-netconf-oar',
+ '//apps/netconf/client:onos-apps-netconf-client-oar',
+ '//apps/tetopology:onos-apps-tetopology-oar',
+ '//apps/tetunnel:onos-apps-tetunnel-oar',
+# '//apps/tenbi/yangmodel:onos-apps-tenbi-yangmodel-feature',
+# '//apps/tenbi:onos-apps-tenbi-oar',
+ '//protocols/restconf/server:onos-protocols-restconf-server-oar',
+ '//apps/restconf:onos-apps-restconf-oar',
+ '//apps/flowspec-api:onos-apps-flowspec-api-oar',
+ '//apps/yang:onos-apps-yang-oar',
+ '//apps/yang-gui:onos-apps-yang-gui-oar',
+ '//apps/cord-support:onos-apps-cord-support-oar',
+ '//apps/network-troubleshoot:onos-apps-network-troubleshoot-oar',
+ '//apps/l3vpn:onos-apps-l3vpn-oar',
+ '//apps/openroadm:onos-apps-openroadm-oar',
+ '//apps/artemis:onos-apps-artemis-oar',
+ '//apps/pi-demo/ecmp:onos-apps-pi-demo-ecmp-oar',
+ '//apps/gluon:onos-apps-gluon-oar',
+ '//apps/evpnopenflow:onos-apps-evpnopenflow-oar',
+ '//apps/route-service:onos-apps-route-service-oar',
+ '//apps/evpn-route-service:onos-apps-evpn-route-service-oar',
+ '//incubator/protobuf/registry:onos-incubator-protobuf-registry-oar',
+ '//incubator/protobuf/services/nb:onos-incubator-protobuf-services-nb-oar',
+ '//apps/openstacknetworkingui:onos-apps-openstacknetworkingui-oar',
+ '//apps/p4-tutorial/pipeconf:onos-apps-p4-tutorial-pipeconf-oar',
+ '//apps/p4-tutorial/icmpdropper:onos-apps-p4-tutorial-icmpdropper-oar',
+ '//apps/cfm:onos-apps-cfm-oar',
+ '//apps/routeradvertisement:onos-apps-routeradvertisement-oar',
+ '//apps/powermanagement:onos-apps-powermanagement-oar',
+ '//apps/t3:onos-apps-t3-oar',
+ '//apps/fpcagent:onos-apps-fpcagent-oar',
+]
+
+PROTOCOL_APPS = [
+ '//protocols/grpc:onos-protocols-grpc-oar',
+ '//protocols/p4runtime:onos-protocols-p4runtime-oar',
+]
+
+MODELS = [
+ '//models/common:onos-models-common-oar',
+ '//models/huawei:onos-models-huawei-oar',
+ '//models/openconfig:onos-models-openconfig-oar',
+ '//models/openroadm:onos-models-openroadm-oar',
+ '//models/tapi:onos-models-tapi-oar',
+ '//models/l3vpn:onos-models-l3vpn-oar',
+ '//models/microsemi:onos-models-microsemi-oar',
+ '//models/polatis:onos-models-polatis-oar',
+ '//models/fpcagent:onos-models-fpcagent-oar',
+]
+
+PIPELINES = [
+ '//pipelines/basic:onos-pipelines-basic-oar',
+ '//pipelines/fabric:onos-pipelines-fabric-oar',
+]
+
+APP_JARS = [
+ '//apps/cpman/api:onos-apps-cpman-api',
+ '//apps/routing-api:onos-apps-routing-api',
+ '//apps/dhcp/api:onos-apps-dhcp-api',
+ '//apps/dhcp/app:onos-apps-dhcp-app',
+ '//apps/dhcprelay:onos-apps-dhcprelay',
+ '//apps/fwd:onos-apps-fwd',
+ '//apps/iptopology-api:onos-apps-iptopology-api',
+ '//apps/routing/common:onos-apps-routing-common',
+ '//apps/vtn/vtnrsc:onos-apps-vtn-vtnrsc',
+ '//apps/vtn/sfcmgr:onos-apps-vtn-sfcmgr',
+ '//apps/vtn/vtnmgr:onos-apps-vtn-vtnmgr',
+ '//apps/vtn/vtnweb:onos-apps-vtn-vtnweb',
+# '//apps/p4runtime-test:onos-apps-p4runtime-test',
+]
+
+APPS = ONOS_DRIVERS + ONOS_PROVIDERS + ONOS_APPS + MODELS + PIPELINES \
+ + PROTOCOL_APPS
+
diff --git a/scripts/addDPN.sh b/scripts/addDPN.sh
new file mode 100755
index 0000000..9c77d37
--- /dev/null
+++ b/scripts/addDPN.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+curl -i --header "Content-type: application/json" --request POST -u onos:rocks --data '{
+ "dpns": [
+ {
+ "dpn-id": "1",
+ "dpn-name": "site1-anchor1",
+ "dpn-groups": [
+ "foo"
+ ],
+ "node-id": "node1",
+ "network-id": "network1"
+ }
+ ]
+}' 'http://localhost:8181/onos/restconf/data/ietf-dmm-fpcagent:tenants/tenant=default/fpc-topology'
+./getTenants.sh
\ No newline at end of file
diff --git a/scripts/createRPC.sh b/scripts/createRPC.sh
new file mode 100755
index 0000000..621f6df
--- /dev/null
+++ b/scripts/createRPC.sh
@@ -0,0 +1,51 @@
+#!/bin/bash
+curl -X POST --header 'Content-Type: application/json' -u onos:rocks --header 'Accept: application/json' -d '{
+ "input": {
+ "admin-state": "enabled",
+ "client-id": "1",
+ "contexts": [
+ {
+ "context-id": 202374887,
+ "delegating-ip-prefixes": [
+ "192.168.1.5/32"
+ ],
+ "dl": {
+ "dpn-parameters": {},
+ "mobility-tunnel-parameters": {
+ "tunnel-identifier": "2222",
+ "tunnel-type": "gtpv1"
+ },
+ "tunnel-local-address": "192.168.1.1",
+ "tunnel-remote-address": "10.1.1.1"
+ },
+ "dpn-group": "foo",
+ "dpns": [
+ {
+ "direction": "uplink",
+ "dpn-id": "1",
+ "dpn-parameters": {}
+ }
+ ],
+ "ebi": "5",
+ "imsi": "9135551234",
+ "instructions": {
+ "instr-3gpp-mob": "session uplink"
+ },
+ "lbi": "5",
+ "ul": {
+ "dpn-parameters": {},
+ "mobility-tunnel-parameters": {
+ "tunnel-identifier": "1111",
+ "tunnel-type": "gtpv1"
+ },
+ "tunnel-local-address": "192.168.1.1",
+ "tunnel-remote-address": "10.1.1.1"
+ }
+ }
+ ],
+ "op-id": "1",
+ "op-ref-scope": "op",
+ "op-type": "create",
+ "session-state": "complete"
+ }
+}' 'http://localhost:8181/onos/restconf/operations/ietf-dmm-fpcagent:configure' | python -m json.tool
diff --git a/scripts/deleteContext.sh b/scripts/deleteContext.sh
new file mode 100755
index 0000000..0e9eda8
--- /dev/null
+++ b/scripts/deleteContext.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+curl -X DELETE -u onos:rocks 'http://localhost:8181/onos/restconf/data/ietf-dmm-fpcagent:tenants/tenant=default/fpc-mobility/contexts=202374887'
+./getTenants.sh
\ No newline at end of file
diff --git a/scripts/deleteContextDl.sh b/scripts/deleteContextDl.sh
new file mode 100755
index 0000000..64f6c2b
--- /dev/null
+++ b/scripts/deleteContextDl.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+curl -X DELETE -u onos:rocks 'http://localhost:8181/onos/restconf/data/ietf-dmm-fpcagent:tenants/tenant=default/fpc-mobility/contexts=202374887/dl'
+./getTenants.sh
\ No newline at end of file
diff --git a/scripts/deleteDPN.sh b/scripts/deleteDPN.sh
new file mode 100755
index 0000000..f210b60
--- /dev/null
+++ b/scripts/deleteDPN.sh
@@ -0,0 +1,3 @@
+#!/bin/bash
+curl -X DELETE -u onos:rocks 'http://localhost:8181/onos/restconf/data/ietf-dmm-fpcagent:tenants/tenant=default/fpc-topology/dpns=1'
+./getTenants.sh
diff --git a/scripts/deleteRPC.sh b/scripts/deleteRPC.sh
new file mode 100755
index 0000000..772b61b
--- /dev/null
+++ b/scripts/deleteRPC.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+curl -X POST --header 'Content-Type: application/json' -u onos:rocks --header 'Accept: application/json' -d '{
+ "input": {
+ "op-id": "3",
+ "targets": [
+ {
+ "target": "/ietf-dmm-fpcagent:tenants/tenant=default/fpc-mobility/contexts=202374887"
+ }
+ ],
+ "client-id": "1",
+ "session-state": "complete",
+ "admin-state": "enabled",
+ "op-type": "delete",
+ "op-ref-scope": "none"
+ }
+}' 'http://localhost:8181/onos/restconf/operations/ietf-dmm-fpcagent:configure' | python -m json.tool
diff --git a/scripts/forwarder_device.py b/scripts/forwarder_device.py
new file mode 100755
index 0000000..04f2a18
--- /dev/null
+++ b/scripts/forwarder_device.py
@@ -0,0 +1,38 @@
+#!/usr/bin/python
+# coding: utf8
+#Copyright © 2016 - 2017 Copyright (c) Sprint, Inc. and others. All rights reserved.
+#
+#This program and the accompanying materials are made available under the
+#terms of the Eclipse Public License v1.0 which accompanies this distribution,
+#and is available at http://www.eclipse.org/legal/epl-v10.html
+
+import zmq
+
+def main():
+
+ try:
+ context = zmq.Context(1)
+
+ # Socket facing clients
+ frontend = context.socket(zmq.SUB)
+ frontend.bind("tcp://*:5559")
+
+ frontend.setsockopt(zmq.SUBSCRIBE, "")
+
+ # Socket facing services
+ backend = context.socket(zmq.PUB)
+ backend.bind("tcp://*:5560")
+
+
+ zmq.device(zmq.FORWARDER, frontend, backend)
+ except Exception, e:
+ print e
+ print "bringing down zmq device"
+ finally:
+ pass
+ frontend.close()
+ backend.close()
+ context.term()
+
+if __name__ == "__main__":
+ main()
\ No newline at end of file
diff --git a/scripts/forwarder_subscriber_with_ACK.py b/scripts/forwarder_subscriber_with_ACK.py
new file mode 100755
index 0000000..fbc5088
--- /dev/null
+++ b/scripts/forwarder_subscriber_with_ACK.py
@@ -0,0 +1,248 @@
+#!/usr/bin/python
+# coding: utf8
+#Copyright © 2016 - 2017 Copyright (c) Sprint, Inc. and others. All rights reserved.
+#
+#This program and the accompanying materials are made available under the
+#terms of the Eclipse Public License v1.0 which accompanies this distribution,
+#and is available at http://www.eclipse.org/legal/epl-v10.html
+
+import signal
+import sys
+import zmq
+import struct
+import socket as socketlib
+import datetime
+import time
+import random
+import thread
+from multiprocessing.pool import ThreadPool
+
+pool = ThreadPool(processes=1)
+
+conflict = False
+topicId = None
+#nodeId = "node3"
+#networkId = "network4"
+nodeId = "node"+sys.argv[1]
+networkId = "network"+sys.argv[2]
+toSend = sys.argv[3]
+source = random.randrange(0,65535)
+topicId = random.randrange(4,255)
+
+def signal_handler(signal, frame):
+ print "\nExiting... Sending DPN Status Indication message with Status = GOODBYE"
+ pub_socket.send("%s" % (struct.pack("!BBBBIB",2,12,topicId,2,source,len(nodeId)) + nodeId + struct.pack('!B',len(networkId)) + networkId))
+ sys.exit(0)
+
+signal.signal(signal.SIGINT, signal_handler)
+
+def sendAssignId(pub_socket):
+ global conflict
+ global topicId
+ time.sleep(1)
+ pub_socket.send("%s" % (struct.pack('!BBBIB',1,10,topicId,source,len(nodeId)) + nodeId + struct.pack('!B',len(networkId)) + networkId))
+ count = 0
+ while True:
+ time.sleep(1)
+ sys.stdout.write("\r"+str(9-count)+" ")
+ sys.stdout.flush()
+ count += 1
+ if conflict:
+ conflict = False
+ sendAssignId(pub_socket)
+ return
+ if count > 9:
+ break
+ print "\nDPN Topic = ", topicId
+ print "Node Id = ", nodeId
+ print "Network Id = ", networkId
+ print "Source Id = ", source
+ print "Sending Hello Message . . ."
+ pub_socket.send("%s" % (struct.pack("!BBBBIB",2,12,topicId,1,source,len(nodeId)) + nodeId + struct.pack('!B',len(networkId)) + networkId))
+
+ print "Ready to receive messages. Press Ctrl+C when ready to exit."
+
+subscriber_uri = "tcp://localhost:5560"
+publisher_uri = "tcp://localhost:5559"
+# Socket to talk to server
+context = zmq.Context()
+sub_socket = context.socket(zmq.SUB)
+pub_socket = context.socket(zmq.PUB)
+sub_socket.connect(subscriber_uri)
+pub_socket.connect(publisher_uri)
+topicfilter = ""
+controller_topic= 252
+sub_socket.setsockopt(zmq.SUBSCRIBE, topicfilter)
+print "Subscriber to ", subscriber_uri
+print "Publisher to ", publisher_uri
+print "DPN Lifecycle start up . . . Please wait."
+
+async_result = pool.apply_async(sendAssignId,(pub_socket,))
+
+count = 0
+msgnum1count = 0
+msgnum2count = 0
+msgnum3count = 0
+msgnum4count = 0
+msgnum5count = 0
+msgnum6count = 0
+for update_nbr in range(900000):
+ string = sub_socket.recv()
+ ts = time.time()
+ st = datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M:%S')
+
+ topic,msgnum = struct.unpack('!BB',string[:2])
+
+ print 'received %s %s' % (topic, msgnum)
+
+ if topic == 1 and msgnum == 10: #Assign_Id
+ top,msg,topId,src,nodeIdLen = struct.unpack('!BBBIB',string[:8])
+ top,msg,topId,src,nodeIdLen,nodeId1,networkIdLen = struct.unpack('!BBBIB'+str(nodeIdLen)+'sB',string[:8+nodeIdLen+1])
+ top,msg,topId,src,nodeIdLen,nodeId1,networkIdLen,networkId1 = struct.unpack('!BBBIB'+str(nodeIdLen)+'sB'+str(networkIdLen)+'s',string[:8+nodeIdLen+1+networkIdLen])
+ #print nodeId1, networkId1
+ if src != source and (topId == topicId or nodeId1 == nodeId):
+ pub_socket.send("%s" % struct.pack('!BBBIBsBs',1,11,topicId,source,len(nodeId),nodeId,len(networkId),networkId))
+ continue
+
+ elif topic == 1 and msgnum == 11: #Assign_Conflict
+ top,msg,topId,src,nodeIdLen = struct.unpack('!BBBIB',string[:8])
+ top,msg,topId,src,nodeIdLen,nodeId1,networkIdLen = struct.unpack('!BBBIB'+str(nodeIdLen)+'sB',string[:8+nodeIdLen+1])
+ top,msg,topId,src,nodeIdLen,nodeId1,networkIdLen,networkId1 = struct.unpack('!BBBIB'+str(nodeIdLen)+'sB'+str(networkIdLen)+'s',string[:8+nodeIdLen+1+networkIdLen])
+
+ if src != source:
+ if(nodeId == nodeId1):
+ print "Received assign conflict for node id. Change the node id and restart this script."
+ exit(0)
+ if(networkId == networkId1):
+ print "Received assign conflict for network id. Change the network id and restart this script."
+ exit(0)
+ if(top == topicId):
+ print "Received assign conflict for topic id. Generating new topic id and resending Assign Topic Id Message."
+ topicId = random.randrange(0,255)
+ conflict = True
+ continue
+
+ elif topic == topicId and msgnum == 13:
+ top, msg, controller_topic, controller_status = struct.unpack('!BBBB',string[:4])
+ print "DPN Status ACK received. Controller Topic = ",controller_topic
+ continue
+
+ elif topic == 3 and msgnum == 14:
+ top, msg, controller_topic, controller_status = struct.unpack('!BBBB',string[:4])
+ if controller_status == 1:
+ print "Received controller Hello. Controller Topic = ",controller_topic
+ print "Sending Hello To Controller that has a topic id of ", controller_topic
+ pub_socket.send("%s" % (struct.pack("!BBBBIB",controller_topic,12,topicId,1,source,len(nodeId)) + nodeId + struct.pack('!B',len(networkId)) + networkId))
+
+ elif controller_status == 2:
+ print "Received controller Goodbye. Controller Topic = ",controller_topic
+
+ if topic != topicId:
+ continue
+ print 'Receiving message', count, ' at ', st, ' ..... '
+ count += 1
+ print 'length of message = ', len(string)
+ print 'topic =', topic
+ print 'msgnum =', msgnum
+
+ if msgnum == 1:
+ msgnum1count += 1
+ topic,msgnum, imsi, default_ebi, ue_ip, s1u_sgw_gtpu_teid, s1u_sgw_gtpu_ipv4, sessionid, ctopic, cid, opid = struct.unpack('!cBQBLLLQBLL',string[:40])
+ print 'imsi = ', imsi
+ ipa = socketlib.inet_ntoa(struct.pack('!L',ue_ip))
+ print 'ue_ip = ', ipa
+ print 'default_ebi = ', default_ebi
+ s1u_sgw_gtpu_ipv4a = socketlib.inet_ntoa(struct.pack('!L',s1u_sgw_gtpu_ipv4))
+ print 's1u_sgw_gtpu_ipv4 = ', s1u_sgw_gtpu_ipv4a
+ print 's1u_sgw_gtpu_teid = ', s1u_sgw_gtpu_teid
+ print 'sessionid = ', sessionid
+ print 'controller topic = ', ctopic
+ print 'cid = ', cid
+ print 'opid = ', opid
+ responsedata = struct.pack('!BBBLL',controller_topic,4, 16, cid, opid)
+ if toSend == "true":
+ pub_socket.send("%s" % (responsedata))
+ #uncomment the following lines to send a DDN for every create session message
+ #time.sleep(5)
+ #pub_socket.send("%s" % (struct.pack('!BBQLLB'+str(len(nodeId))+'sB'+str(len(networkId))+'s',controller_topic,5,sessionid,cid,opid,len(nodeId),nodeId,len(networkId),networkId)))
+
+ elif msgnum == 2:
+ msgnum2count += 1
+ topic, msgnum, s1u_enb_gtpu_ipv4, s1u_enb_gtpu_teid, s1u_sgw_gtpu_ipv4, sessionid, ctopic, cid, opid = struct.unpack("!cBLLLQBLL",string[:31])
+ s1u_enb_gtpu_ipv4a = socketlib.inet_ntoa(struct.pack('!L',s1u_enb_gtpu_ipv4))
+ print 's1u_enb_gtpu_ipv4 = ', s1u_enb_gtpu_ipv4a
+ print 'dl s1u_enb_gtpu_teid = ', s1u_enb_gtpu_teid
+ print 'dl s1u_sgw_gtpu_ipv4 = ', socketlib.inet_ntoa(struct.pack('!L',s1u_sgw_gtpu_ipv4))
+ print 'sessionid = ', sessionid
+ print 'controller topic = ', ctopic
+ print 'cid = ', cid
+ print 'opid = ', opid
+ responsedata = struct.pack('!BBBLL',controller_topic,4, 16, cid, opid)
+ if toSend == "true":
+ pub_socket.send("%s" % (responsedata))
+
+ elif msgnum == 3:
+ msgnum3count += 1
+ topic, msgnum, sessionid, ctopic, cid, opid = struct.unpack("!cBQBLL",string[:19])
+ print 'sessionid = ', sessionid
+ print 'controller topic = ', ctopic
+ print 'cid = ', cid
+ print 'opid = ', opid
+ responsedata = struct.pack('!BBBLL',controller_topic,4, 0, cid, opid)
+ if toSend == "true":
+ pub_socket.send("%s" % (responsedata))
+
+ elif msgnum == 6:
+ if(len(string)==14):
+ #topic,msgnum,bufduration,bufcount,controller_topic,cid,opid = struct.unpack('!BBBHBLL',string[:14])
+ topic,msgnum,controller_topic,cid,opid = struct.unpack('!BBBLL',string[:11])
+ #print "dl-buffering-duration",bufduration
+ #print "dl-buffering-suggested-count",bufcount
+ print "Controller Topic = ",controller_topic
+ print "Client id = ", cid
+ print "Op Id = ", opid
+
+ elif msgnum == 17:
+ print "-------------------------------------------------------------"
+ print "ADC Rule received. Details:"
+ topic,msgnum,selector_type = struct.unpack('!BBB',string[:3])
+
+ #Domain
+ if(selector_type == 0):
+ domain_name_length, = struct.unpack('!B',string[3:4])
+ domain_name, = struct.unpack('!'+str(domain_name_length)+'s',string[4:4+int(domain_name_length)])
+ next_index = 4+int(domain_name_length)
+ print "Domain Name = ",domain_name
+
+ #IP Address
+ if(selector_type == 1 or selector_type == 2):
+ ip_address, = struct.unpack('!L',string[3:7])
+ ip_addressa = socketlib.inet_ntoa(struct.pack('!L',ip_address))
+ next_index = 7
+ print "IP Address = ",ip_addressa
+
+ #IP Prefix
+ if selector_type == 2:
+ ip_prefix, = struct.unpack('!H',string[7:9])
+ next_index += 2
+ print "IP Prefix = ",ip_prefix
+
+ #rule_id, = struct.unpack('!L',string[rule_id_index:rule_id_index+4])
+ #print "Rule Id = ", rule_id
+
+ #rating_group,service_id,sponsor_id_length = struct.unpack('!LLB', string[rule_id_index+4:rule_id_index+4+9])
+ drop,rating_group,service_id,sponsor_id_length = struct.unpack('!BLLB', string[next_index:next_index+10])
+ print "Drop = ", drop
+ print "Rating Group = ", rating_group
+ print "Service Id = ", service_id
+ #print "Sponsor Length = ", sponsor_id_length
+ #sponsor_id, = struct.unpack('!'+str(sponsor_id_length)+'s',string[rule_id_index+4+9:rule_id_index+4+9+int(sponsor_id_length)])
+ sponsor_id, = struct.unpack('!'+str(sponsor_id_length)+'s',string[next_index+10:next_index+10+int(sponsor_id_length)])
+ print "Sponsor = ", sponsor_id
+ print "-------------------------------------------------------------"
+ #precedence, = struct.unpack('!L',string[rule_id_index+4+9+int(sponsor_id_length):rule_id_index+4+9+int(sponsor_id_length)+4])
+ #print "precedence = ", precedence
+
+ print '================'
+ print 'Total = ', count, 'msgnum1 count', msgnum1count, 'msgnum2 count', msgnum2count, 'msgnum3 count', msgnum3count, 'msgnum4 count', msgnum4count,'msgnum5 count', msgnum5count, 'msgnum6 count', msgnum6count
+sub_socket.close()
diff --git a/scripts/getFpcAgentInfo.sh b/scripts/getFpcAgentInfo.sh
new file mode 100755
index 0000000..4a45b20
--- /dev/null
+++ b/scripts/getFpcAgentInfo.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+curl -u onos:rocks http://localhost:8181/onos/restconf/data/ietf-dmm-fpcagent:fpc-agent-info
diff --git a/scripts/getTenants.sh b/scripts/getTenants.sh
new file mode 100755
index 0000000..abe3bd1
--- /dev/null
+++ b/scripts/getTenants.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+curl -u onos:rocks http://localhost:8181/onos/restconf/data/ietf-dmm-fpcagent:tenants | python -m json.tool
diff --git a/scripts/updateRPC.sh b/scripts/updateRPC.sh
new file mode 100755
index 0000000..de934bf
--- /dev/null
+++ b/scripts/updateRPC.sh
@@ -0,0 +1,51 @@
+#!/bin/bash
+curl -X POST --header 'Content-Type: application/json' -u onos:rocks --header 'Accept: application/json' -d '{
+ "input": {
+ "admin-state": "enabled",
+ "client-id": "1",
+ "contexts": [
+ {
+ "context-id": 202374887,
+ "delegating-ip-prefixes": [
+ "192.168.1.5/32"
+ ],
+ "dl": {
+ "dpn-parameters": {},
+ "mobility-tunnel-parameters": {
+ "tunnel-identifier": "2222",
+ "tunnel-type": "gtpv1"
+ },
+ "tunnel-local-address": "192.168.1.1",
+ "tunnel-remote-address": "10.1.1.1"
+ },
+ "dpn-group": "foo",
+ "dpns": [
+ {
+ "direction": "uplink",
+ "dpn-id": "1",
+ "dpn-parameters": {}
+ }
+ ],
+ "ebi": "5",
+ "imsi": "9135551234",
+ "instructions": {
+ "instr-3gpp-mob": "session uplink"
+ },
+ "lbi": "5",
+ "ul": {
+ "dpn-parameters": {},
+ "mobility-tunnel-parameters": {
+ "tunnel-identifier": "1111",
+ "tunnel-type": "gtpv1"
+ },
+ "tunnel-local-address": "192.168.1.1",
+ "tunnel-remote-address": "10.1.1.1"
+ }
+ }
+ ],
+ "op-id": "1",
+ "op-ref-scope": "op",
+ "op-type": "update",
+ "session-state": "complete"
+ }
+}' 'http://localhost:8181/onos/restconf/operations/ietf-dmm-fpcagent:configure' | python -m json.tool