diff --git a/apps/cfm/BUCK b/apps/cfm/BUCK new file mode 100644 index 0000000000..7c8cb71d10 --- /dev/null +++ b/apps/cfm/BUCK @@ -0,0 +1,28 @@ +COMPILE_DEPS = [ + '//lib:CORE_DEPS', + '//lib:javax.ws.rs-api', + '//utils/rest:onlab-rest', + '//lib:JACKSON', + '//cli:onos-cli', + '//lib:org.apache.karaf.shell.console', + '//incubator/api:onos-incubator-api' +] + +TEST_DEPS = [ + '//lib:TEST_REST', + '//utils/osgi:onlab-osgi-tests', + '//web/api:onos-rest-tests', +] + +osgi_jar_with_tests ( + deps = COMPILE_DEPS, + test_deps = TEST_DEPS, + web_context = '/onos/cfm', +) + +onos_app ( + title = 'Layer 2 Monitoring CFM Application', + category = 'default', + url = 'http://onosproject.org', + description = 'Layer 2 Monitoring Connectivity Fault Management App', +) diff --git a/apps/cfm/README.md b/apps/cfm/README.md new file mode 100644 index 0000000000..c2c27fab82 --- /dev/null +++ b/apps/cfm/README.md @@ -0,0 +1,3 @@ +# Layer 2 Monitoring with CFM and SOAM in ONOS +Please see the README.md file in the API at +incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/README.md \ No newline at end of file diff --git a/apps/cfm/pom.xml b/apps/cfm/pom.xml new file mode 100644 index 0000000000..ad63ddd6ac --- /dev/null +++ b/apps/cfm/pom.xml @@ -0,0 +1,96 @@ + + + + 4.0.0 + + + org.onosproject + onos-apps + 1.12.0-SNAPSHOT + + + onos-app-cfm + bundle + 1.12.0-SNAPSHOT + + ONOS OSGi bundle archetype + http://onosproject.org + + + UTF-8 + /onos/cfm + Layer 2 Monitoring CFM REST API + 1.0.0 + org.onosproject.cfm + Layer 2 Monitoring CFM REST API + org.onosproject.cfm + Layer 2 Monitoring CFM App + Microsemi Inc + default + http://onosproject.org + Layer 2 Monitoring Connectivity Fault Management App + + + + + org.onosproject + onos-api + + + + org.onosproject + onos-incubator-api + + + + org.onosproject + onos-core-common + + + + org.onosproject + onos-cli + ${project.version} + + + + org.apache.karaf.shell + org.apache.karaf.shell.console + + + + org.onosproject + onlab-junit + test + + + + + + + org.apache.felix + maven-bundle-plugin + true + + + <_wab>src/main/webapp/ + WEB-INF/classes/apidoc/swagger.json=target/swagger.json, + {maven-resources} + ${project.groupId}.${project.artifactId} + *,org.glassfish.jersey.servlet + ${web.context} + + + + + + + diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/CfmWebComponent.java b/apps/cfm/src/main/java/org/onosproject/cfm/CfmWebComponent.java new file mode 100644 index 0000000000..6ead985621 --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/cfm/CfmWebComponent.java @@ -0,0 +1,195 @@ +/* + * 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.cfm; + +import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Deactivate; +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.ReferenceCardinality; +import org.onlab.packet.VlanId; +import org.onosproject.cfm.web.ComponentCodec; +import org.onosproject.cfm.web.FngAddressCodec; +import org.onosproject.cfm.web.MaintenanceAssociationCodec; +import org.onosproject.cfm.web.MaintenanceDomainCodec; +import org.onosproject.cfm.web.MepCodec; +import org.onosproject.cfm.web.MepEntryCodec; +import org.onosproject.cfm.web.MepLbCreateCodec; +import org.onosproject.cfm.web.MepLbEntryCodec; +import org.onosproject.cfm.web.MepLtCreateCodec; +import org.onosproject.cfm.web.RemoteMepEntryCodec; +import org.onosproject.cfm.web.VidCodec; +import org.onosproject.codec.CodecService; +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceAssociation; +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep.FngAddress; +import org.onosproject.incubator.net.l2monitoring.cfm.MepEntry; +import org.onosproject.incubator.net.l2monitoring.cfm.MepLbCreate; +import org.onosproject.incubator.net.l2monitoring.cfm.MepLbEntry; +import org.onosproject.incubator.net.l2monitoring.cfm.MepLtCreate; +import org.onosproject.incubator.net.l2monitoring.cfm.RemoteMepEntry; +import org.onosproject.incubator.net.l2monitoring.soam.StartTime; +import org.onosproject.incubator.net.l2monitoring.soam.StopTime; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.MeasurementOption; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementEntry; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStat; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStatCurrent; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStatHistory; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossAvailabilityStat; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossAvailabilityStatCurrent; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossAvailabilityStatHistory; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementCreate; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementCreate.CounterOption; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementEntry; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementStat; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementStatCurrent; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementStatHistory; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementThreshold; +import org.onosproject.soam.web.DelayMeasurementStatCodec; +import org.onosproject.soam.web.DelayMeasurementStatCurrentCodec; +import org.onosproject.soam.web.DelayMeasurementStatHistoryCodec; +import org.onosproject.soam.web.DmCreateCodec; +import org.onosproject.soam.web.DmEntryCodec; +import org.onosproject.soam.web.DmMeasurementOptionCodec; +import org.onosproject.soam.web.LmCounterOptionCodec; +import org.onosproject.soam.web.LmCreateCodec; +import org.onosproject.soam.web.LmEntryCodec; +import org.onosproject.soam.web.LmThresholdOptionCodec; +import org.onosproject.soam.web.LossAvailabilityStatCodec; +import org.onosproject.soam.web.LossAvailabilityStatCurrentCodec; +import org.onosproject.soam.web.LossAvailabilityStatHistoryCodec; +import org.onosproject.soam.web.LossMeasurementStatCodec; +import org.onosproject.soam.web.LossMeasurementStatCurrentCodec; +import org.onosproject.soam.web.LossMeasurementStatHistoryCodec; +import org.onosproject.soam.web.LossMeasurementThresholdCodec; +import org.onosproject.soam.web.StartTimeCodec; +import org.onosproject.soam.web.StopTimeCodec; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementThreshold.*; + +/** + * Enables the CFM REST Web Service component at /onos/cfm. + * Each codec for the rest interfaces should be registered here. + */ +@Component(immediate = true) +public class CfmWebComponent { + private final Logger log = LoggerFactory.getLogger(getClass()); + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected CodecService codecService; + + @Activate + public void activate() { + codecService.registerCodec(MaintenanceDomain.class, + new MaintenanceDomainCodec()); + codecService.registerCodec(MaintenanceAssociation.class, + new MaintenanceAssociationCodec()); + codecService.registerCodec(org.onosproject.incubator.net.l2monitoring.cfm.Component.class, + new ComponentCodec()); + codecService.registerCodec(VlanId.class, new VidCodec()); + codecService.registerCodec(Mep.class, new MepCodec()); + codecService.registerCodec(MepEntry.class, new MepEntryCodec()); + codecService.registerCodec(MepLbCreate.class, new MepLbCreateCodec()); + codecService.registerCodec(MepLbEntry.class, new MepLbEntryCodec()); + codecService.registerCodec(MepLtCreate.class, new MepLtCreateCodec()); + codecService.registerCodec(RemoteMepEntry.class, new RemoteMepEntryCodec()); + codecService.registerCodec(FngAddress.class, new FngAddressCodec()); + + + codecService.registerCodec(DelayMeasurementCreate.class, + new DmCreateCodec()); + codecService.registerCodec(DelayMeasurementEntry.class, + new DmEntryCodec()); + codecService.registerCodec(DelayMeasurementStat.class, + new DelayMeasurementStatCodec()); + codecService.registerCodec(DelayMeasurementStatCurrent.class, + new DelayMeasurementStatCurrentCodec()); + codecService.registerCodec(DelayMeasurementStatHistory.class, + new DelayMeasurementStatHistoryCodec()); + codecService.registerCodec(MeasurementOption.class, + new DmMeasurementOptionCodec()); + + codecService.registerCodec(LossMeasurementCreate.class, + new LmCreateCodec()); + codecService.registerCodec(LossMeasurementThreshold.class, + new LossMeasurementThresholdCodec()); + codecService.registerCodec(LossMeasurementEntry.class, + new LmEntryCodec()); + codecService.registerCodec(LossMeasurementStat.class, + new LossMeasurementStatCodec()); + codecService.registerCodec(LossMeasurementStatCurrent.class, + new LossMeasurementStatCurrentCodec()); + codecService.registerCodec(LossMeasurementStatHistory.class, + new LossMeasurementStatHistoryCodec()); + codecService.registerCodec(LossAvailabilityStat.class, + new LossAvailabilityStatCodec()); + codecService.registerCodec(LossAvailabilityStatCurrent.class, + new LossAvailabilityStatCurrentCodec()); + codecService.registerCodec(LossAvailabilityStatHistory.class, + new LossAvailabilityStatHistoryCodec()); + codecService.registerCodec(CounterOption.class, + new LmCounterOptionCodec()); + codecService.registerCodec(ThresholdOption.class, + new LmThresholdOptionCodec()); + + codecService.registerCodec(StartTime.class, new StartTimeCodec()); + codecService.registerCodec(StopTime.class, new StopTimeCodec()); + + log.info("CFM Web Component Started"); + } + + @Deactivate + public void deactivate() { + log.info("CFM Web Component Stopped"); + codecService.unregisterCodec(MaintenanceDomain.class); + codecService.unregisterCodec(MaintenanceAssociation.class); + codecService.unregisterCodec(org.onosproject.incubator.net.l2monitoring.cfm.Component.class); + codecService.unregisterCodec(VlanId.class); + codecService.unregisterCodec(Mep.class); + codecService.unregisterCodec(MepEntry.class); + codecService.unregisterCodec(MepLbCreate.class); + codecService.unregisterCodec(MepLbEntry.class); + codecService.unregisterCodec(MepLtCreate.class); + codecService.unregisterCodec(RemoteMepEntry.class); + codecService.unregisterCodec(FngAddress.class); + + codecService.unregisterCodec(DelayMeasurementCreate.class); + codecService.unregisterCodec(DelayMeasurementEntry.class); + codecService.unregisterCodec(DelayMeasurementStat.class); + codecService.unregisterCodec(DelayMeasurementStatCurrent.class); + codecService.unregisterCodec(DelayMeasurementStatHistory.class); + codecService.unregisterCodec(MeasurementOption.class); + codecService.unregisterCodec(StartTime.class); + codecService.unregisterCodec(StopTime.class); + + codecService.unregisterCodec(LossMeasurementCreate.class); + codecService.unregisterCodec(LossMeasurementThreshold.class); + codecService.unregisterCodec(LossMeasurementEntry.class); + codecService.unregisterCodec(LossMeasurementStat.class); + codecService.unregisterCodec(LossMeasurementStatCurrent.class); + codecService.unregisterCodec(LossMeasurementStatHistory.class); + codecService.unregisterCodec(LossAvailabilityStat.class); + codecService.unregisterCodec(LossAvailabilityStatCurrent.class); + codecService.unregisterCodec(LossAvailabilityStatHistory.class); + codecService.unregisterCodec(CounterOption.class); + codecService.unregisterCodec(ThresholdOption.class); + + } +} diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/cli/CfmMaAddCommand.java b/apps/cfm/src/main/java/org/onosproject/cfm/cli/CfmMaAddCommand.java new file mode 100644 index 0000000000..d449cce9b8 --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/cfm/cli/CfmMaAddCommand.java @@ -0,0 +1,184 @@ +/* + * 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.cfm.cli; + +import org.apache.karaf.shell.commands.Argument; +import org.apache.karaf.shell.commands.Command; +import org.onlab.packet.VlanId; +import org.onosproject.cli.AbstractShellCommand; +import org.onosproject.incubator.net.l2monitoring.cfm.Component; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultComponent; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMaintenanceAssociation; +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceAssociation; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaId2Octet; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdIccY1731; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdPrimaryVid; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdRfc2685VpnId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdDomainName; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdMacUint; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdNone; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMdService; + +/** + * Adds a Maintenance Association to a Maintenance Domain. + */ +@Command(scope = "onos", name = "cfm-ma-add", + description = "Add a CFM Maintenance Association to a Maintenance Domain.") +public class CfmMaAddCommand extends AbstractShellCommand { + @Argument(index = 0, name = "name", + description = "Maintenance Domain name and type (in brackets)", + required = true, multiValued = false) + String mdName = null; + + @Argument(index = 1, name = "name-type", + description = "Maintenance Assocation name type", + required = true, multiValued = false) + String nameType = null; + + @Argument(index = 2, name = "name", + description = "Maintenance Assocation name. Restrictions apply depending " + + "on name-type", + required = true, multiValued = false) + String name = null; + + @Argument(index = 3, name = "ccm-interval", + description = "CCM Interval values from list", + required = true, multiValued = false) + String ccmInterval = null; + + @Argument(index = 4, name = "numeric-id", + description = "An optional numeric id for Maintenance Association [1-65535]", + required = false, multiValued = false) + short numericId = 0; + + @Argument(index = 5, name = "component-id", + description = "An id for a Component in the Component List [1-65535]." + + "The CLI allows creation of only 1 component. If more are " + + "required use the REST interface", + required = false, multiValued = false) + short componentId = 0; + + @Argument(index = 6, name = "component-tag-type", + description = "Tag Type value for the component", + required = false, multiValued = false) + String tagType = null; + + @Argument(index = 7, name = "component-mhf-creation", + description = "MEP Half function creation type for the component", + required = false, multiValued = false) + String mhfCreationType = null; + + @Argument(index = 8, name = "component-vid", + description = "A VID for the component [1-4095]. This CLI allows " + + "only the specification of 1 VID. If more are required use " + + "the REST interface", + required = false, multiValued = false) + short vid = 0; + + @Argument(index = 9, name = "rmep", + description = "Remote Mep numeric identifier [1-8192]", + required = true, multiValued = true) + String[] rmepArray = null; + + @Override + protected void execute() { + CfmMdService service = get(CfmMdService.class); + + String[] mdNameParts = mdName.split("[()]"); + if (mdNameParts.length != 2) { + throw new IllegalArgumentException("Invalid name format. " + + "Must be in the format of "); + } + + MdId mdId = null; + MdId.MdNameType mdNameTypeEnum = MdId.MdNameType.valueOf(mdNameParts[1]); + switch (mdNameTypeEnum) { + case DOMAINNAME: + mdId = MdIdDomainName.asMdId(mdNameParts[0]); + break; + case MACANDUINT: + mdId = MdIdMacUint.asMdId(mdNameParts[0]); + break; + case NONE: + mdId = MdIdNone.asMdId(); + break; + case CHARACTERSTRING: + default: + mdId = MdIdCharStr.asMdId(mdNameParts[0]); + } + + MaIdShort maId = null; + MaIdShort.MaIdType maNameTypeEnum = MaIdShort.MaIdType.valueOf(nameType); + switch (maNameTypeEnum) { + case TWOOCTET: + maId = MaId2Octet.asMaId(name); + break; + case ICCY1731: + maId = MaIdIccY1731.asMaId(name); + break; + case PRIMARYVID: + maId = MaIdPrimaryVid.asMaId(name); + break; + case RFC2685VPNID: + maId = MaIdRfc2685VpnId.asMaIdHex(name); + break; + case CHARACTERSTRING: + default: + maId = MaIdCharStr.asMaId(name); + } + + MaintenanceAssociation.MaBuilder builder = null; + try { + builder = DefaultMaintenanceAssociation.builder(maId, mdId.getNameLength()); + if (ccmInterval != null && !ccmInterval.isEmpty()) { + builder = builder.ccmInterval(MaintenanceAssociation.CcmInterval.valueOf(ccmInterval)); + } + for (String rmep:rmepArray) { + builder = builder.addToRemoteMepIdList(MepId.valueOf(Short.parseShort(rmep))); + } + if (numericId > 0) { + builder = builder.maNumericId(numericId); + } + if (componentId > 0) { + Component.ComponentBuilder compBuilder = + DefaultComponent.builder(componentId); + if (tagType != null && !tagType.isEmpty()) { + compBuilder = compBuilder.tagType( + Component.TagType.valueOf(tagType)); + } + if (mhfCreationType != null && !mhfCreationType.isEmpty()) { + compBuilder = compBuilder.mhfCreationType( + Component.MhfCreationType.valueOf(mhfCreationType)); + } + if (vid > 0) { + compBuilder = compBuilder.addToVidList(VlanId.vlanId(vid)); + } + builder = builder.addToComponentList(compBuilder.build()); + } + boolean created = service.createMaintenanceAssociation(mdId, builder.build()); + print("Maintenance Association %s is successfully %s on MD %s", + maId, created ? "updated" : "created", mdId); + } catch (CfmConfigException e) { + throw new IllegalArgumentException(e); + } + } +} diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/cli/CfmMaDeleteCommand.java b/apps/cfm/src/main/java/org/onosproject/cfm/cli/CfmMaDeleteCommand.java new file mode 100644 index 0000000000..4228b78812 --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/cfm/cli/CfmMaDeleteCommand.java @@ -0,0 +1,103 @@ +/* + * Copyright 2017-present Open Networking Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.cfm.cli; + +import org.apache.karaf.shell.commands.Argument; +import org.apache.karaf.shell.commands.Command; +import org.onosproject.cli.AbstractShellCommand; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaId2Octet; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdIccY1731; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdPrimaryVid; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdRfc2685VpnId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdDomainName; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdMacUint; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdNone; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMdService; + +/** + * Delete a Maintenance Association from the existing list of a Maintenance Domain. + */ +@Command(scope = "onos", name = "cfm-ma-delete", + description = "Delete a CFM Maintenance Association and its children.") +public class CfmMaDeleteCommand extends AbstractShellCommand { + + @Argument(index = 0, name = "name", + description = "Maintenance Domain name and type (in brackets) " + + "and the Maintenance Association name and type (in brackets)", + required = true, multiValued = false) + String name = null; + + @Override + protected void execute() { + CfmMdService service = get(CfmMdService.class); + + String[] nameParts = name.split("[()]"); + if (nameParts.length != 4) { + throw new IllegalArgumentException("Invalid name format. Must be in " + + "the format of "); + } + + MdId mdId = null; + MdId.MdNameType nameTypeEnum = MdId.MdNameType.valueOf(nameParts[1]); + switch (nameTypeEnum) { + case DOMAINNAME: + mdId = MdIdDomainName.asMdId(nameParts[0]); + break; + case MACANDUINT: + mdId = MdIdMacUint.asMdId(nameParts[0]); + break; + case NONE: + mdId = MdIdNone.asMdId(); + break; + case CHARACTERSTRING: + default: + mdId = MdIdCharStr.asMdId(nameParts[0]); + } + + MaIdShort maId = null; + MaIdShort.MaIdType maNameTypeEnum = MaIdShort.MaIdType.valueOf(nameParts[3]); + switch (maNameTypeEnum) { + case TWOOCTET: + maId = MaId2Octet.asMaId(nameParts[2]); + break; + case ICCY1731: + maId = MaIdIccY1731.asMaId(nameParts[2]); + break; + case PRIMARYVID: + maId = MaIdPrimaryVid.asMaId(nameParts[2]); + break; + case RFC2685VPNID: + maId = MaIdRfc2685VpnId.asMaIdHex(nameParts[2]); + break; + case CHARACTERSTRING: + default: + maId = MaIdCharStr.asMaId(nameParts[2]); + } + + try { + boolean deleted = service.deleteMaintenanceAssociation(mdId, maId); + print("Maintenance Association %s-%s is %ssuccessfully deleted.", + mdId, maId, deleted ? "" : "NOT "); + } catch (CfmConfigException e) { + throw new IllegalArgumentException(e); + } + } +} diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/cli/CfmMdAddCommand.java b/apps/cfm/src/main/java/org/onosproject/cfm/cli/CfmMdAddCommand.java new file mode 100644 index 0000000000..922ed64fee --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/cfm/cli/CfmMdAddCommand.java @@ -0,0 +1,100 @@ +/* + * 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.cfm.cli; + +import org.apache.karaf.shell.commands.Command; +import org.apache.karaf.shell.commands.Argument; +import org.onosproject.cli.AbstractShellCommand; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMaintenanceDomain; +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdDomainName; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdMacUint; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdNone; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMdService; + +import java.util.Optional; + +/** + * Adds a Maintenance Domain to the existing list. + */ +@Command(scope = "onos", name = "cfm-md-add", + description = "Add a CFM Maintenance Domain.") +public class CfmMdAddCommand extends AbstractShellCommand { + + @Argument(index = 0, name = "name-type", + description = "Maintenance Domain name type", + required = true, multiValued = false) + String nameType = null; + + @Argument(index = 1, name = "name", + description = "Maintenance Domain name. Restrictions apply depending " + + "on name-type. Leave empty if name type is none", + required = true, multiValued = false) + String name = null; + + @Argument(index = 2, name = "level", + description = "Maintenance Domain level LEVEL0-LEVEL7", + required = true, multiValued = false) + String level = null; + + @Argument(index = 3, name = "numeric-id", + description = "An optional numeric id for Maintenance Domain [1-65535]", + required = false, multiValued = false) + short numericId = 0; + + @Override + protected void execute() { + CfmMdService service = get(CfmMdService.class); + MdId mdId = null; + MdId.MdNameType nameTypeEnum = MdId.MdNameType.valueOf(nameType); + switch (nameTypeEnum) { + case DOMAINNAME: + mdId = MdIdDomainName.asMdId(name); + break; + case MACANDUINT: + mdId = MdIdMacUint.asMdId(name); + break; + case NONE: + mdId = MdIdNone.asMdId(); + break; + case CHARACTERSTRING: + default: + mdId = MdIdCharStr.asMdId(name); + } + MaintenanceDomain.MdLevel levelEnum = + MaintenanceDomain.MdLevel.valueOf(level); + Optional numericIdOpt = Optional.empty(); + if (numericId > 0) { + numericIdOpt = Optional.of(numericId); + } + + MaintenanceDomain.MdBuilder builder = null; + try { + builder = DefaultMaintenanceDomain.builder(mdId).mdLevel(levelEnum); + if (numericIdOpt.isPresent()) { + builder = builder.mdNumericId(numericIdOpt.get()); + } + boolean created = service.createMaintenanceDomain(builder.build()); + print("Maintenance Domain with id %s is successfully %s.", + mdId, created ? "updated" : "created"); + } catch (CfmConfigException e) { + throw new IllegalArgumentException(e); + } + } +} diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/cli/CfmMdDeleteCommand.java b/apps/cfm/src/main/java/org/onosproject/cfm/cli/CfmMdDeleteCommand.java new file mode 100644 index 0000000000..3cf3c26b4d --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/cfm/cli/CfmMdDeleteCommand.java @@ -0,0 +1,76 @@ +/* + * 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.cfm.cli; + +import org.apache.karaf.shell.commands.Argument; +import org.apache.karaf.shell.commands.Command; +import org.onosproject.cli.AbstractShellCommand; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdDomainName; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdMacUint; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdNone; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMdService; + +/** + * Deletes a Maintenance Domain from the existing list. + */ +@Command(scope = "onos", name = "cfm-md-delete", + description = "Delete a CFM Maintenance Domain and its children.") +public class CfmMdDeleteCommand extends AbstractShellCommand { + + @Argument(index = 0, name = "name", + description = "Maintenance Domain name and type (in brackets)", + required = true, multiValued = false) + String name = null; + + @Override + protected void execute() { + CfmMdService service = get(CfmMdService.class); + + String[] nameParts = name.split("[()]"); + if (nameParts.length != 2) { + throw new IllegalArgumentException("Invalid name format. " + + "Must be in the format of "); + } + + MdId mdId = null; + MdId.MdNameType nameTypeEnum = MdId.MdNameType.valueOf(nameParts[1]); + switch (nameTypeEnum) { + case DOMAINNAME: + mdId = MdIdDomainName.asMdId(nameParts[0]); + break; + case MACANDUINT: + mdId = MdIdMacUint.asMdId(nameParts[0]); + break; + case NONE: + mdId = MdIdNone.asMdId(); + break; + case CHARACTERSTRING: + default: + mdId = MdIdCharStr.asMdId(nameParts[0]); + } + + try { + boolean deleted = service.deleteMaintenanceDomain(mdId); + print("Maintenance Domain %s is %ssuccessfully deleted.", + mdId, deleted ? "" : "NOT "); + } catch (CfmConfigException e) { + throw new IllegalArgumentException(e); + } + } +} diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/cli/CfmMdListMdCommand.java b/apps/cfm/src/main/java/org/onosproject/cfm/cli/CfmMdListMdCommand.java new file mode 100644 index 0000000000..341bd7dd34 --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/cfm/cli/CfmMdListMdCommand.java @@ -0,0 +1,134 @@ +/* + * 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.cfm.cli; + +import org.apache.karaf.shell.commands.Argument; +import org.apache.karaf.shell.commands.Command; +import org.onosproject.cli.AbstractShellCommand; +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceAssociation; +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdDomainName; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdMacUint; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdNone; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMdService; + +import java.util.Optional; + +/** + * Lists a particular Maintenance Domain. + */ +@Command(scope = "onos", name = "cfm-md-list", + description = "Lists a single CFM Maintenance Domain or all if none specified.") +public class CfmMdListMdCommand extends AbstractShellCommand { + @Argument(index = 0, name = "name", + description = "Maintenance Domain name and type (in brackets)", + required = false, multiValued = false) + String name = null; + + @Override + protected void execute() { + CfmMdService service = get(CfmMdService.class); + + if (name != null) { + String[] nameParts = name.split("[()]"); + if (nameParts.length != 2) { + throw new IllegalArgumentException("Invalid name format. " + + "Must be in the format of "); + } + + MdId mdId = null; + MdId.MdNameType nameTypeEnum = MdId.MdNameType.valueOf(nameParts[1]); + switch (nameTypeEnum) { + case DOMAINNAME: + mdId = MdIdDomainName.asMdId(nameParts[0]); + break; + case MACANDUINT: + mdId = MdIdMacUint.asMdId(nameParts[0]); + break; + case NONE: + mdId = MdIdNone.asMdId(); + break; + case CHARACTERSTRING: + default: + mdId = MdIdCharStr.asMdId(nameParts[0]); + } + + print("Maintenance Domain:"); + Optional md = service.getMaintenanceDomain(mdId); + print(printMd(md)); + md.get().maintenanceAssociationList().forEach(ma -> printMa(Optional.of(ma))); + } else { + service.getAllMaintenanceDomain().forEach(md -> { + print(printMd(Optional.of(md))); + }); + } + } + + public static String printMd(Optional md) { + if (!md.isPresent()) { + return new String("MD not found"); + } else { + StringBuffer sb = new StringBuffer("\tMD: "); + sb.append(md.get().mdId().mdName()); + sb.append("(" + md.get().mdId().nameType()); + sb.append(") Lvl:" + md.get().mdLevel().ordinal()); + sb.append(", Num: " + md.get().mdNumericId()); + + md.get().maintenanceAssociationList(). + forEach(ma -> sb.append(printMa(Optional.of(ma)))); + return sb.toString(); + } + } + + public static String printMa(Optional ma) { + if (!ma.isPresent()) { + return "\n\tNo MA found"; + } + + StringBuilder sb = new StringBuilder("\n\t\tMA: "); + sb.append(ma.get().maId().maName()); + sb.append("("); + sb.append(ma.get().maId().nameType()); + sb.append(") CCM: "); + sb.append(ma.get().ccmInterval()); + sb.append(" Num: "); + sb.append(ma.get().maNumericId()); + + ma.get().remoteMepIdList().forEach(rmep -> { + sb.append("\n\t\t\tRmep: "); + sb.append(rmep); + }); + ma.get().componentList().forEach(comp -> { + sb.append("\n\t\t\tComponent: "); + sb.append(comp.componentId()); + sb.append(" Perm: "); + sb.append(comp.idPermission()); + sb.append(" MHF: "); + sb.append(comp.mhfCreationType()); + sb.append(" Tag: "); + sb.append(comp.tagType()); + + comp.vidList().forEach(vid -> { + sb.append("\n\t\t\t\tVID: "); + sb.append(vid); + }); + }); + + return sb.toString(); + } +} diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/cli/completer/CfmCompMhfCompleter.java b/apps/cfm/src/main/java/org/onosproject/cfm/cli/completer/CfmCompMhfCompleter.java new file mode 100644 index 0000000000..499b84dae4 --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/cfm/cli/completer/CfmCompMhfCompleter.java @@ -0,0 +1,39 @@ +/* + * 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.cfm.cli.completer; + +import org.onosproject.cli.AbstractChoicesCompleter; +import org.onosproject.incubator.net.l2monitoring.cfm.Component; + +import java.util.ArrayList; +import java.util.List; + +/** + * CLI completer for Component MEP Half Function creation. + */ +public class CfmCompMhfCompleter extends AbstractChoicesCompleter { + @Override + public List choices() { + List choices = new ArrayList<>(); + + for (Component.MhfCreationType mhfCreationType: Component.MhfCreationType.values()) { + choices.add(String.valueOf(mhfCreationType.toString())); + } + + return choices; + } + +} diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/cli/completer/CfmCompTagTypeCompleter.java b/apps/cfm/src/main/java/org/onosproject/cfm/cli/completer/CfmCompTagTypeCompleter.java new file mode 100644 index 0000000000..d9197802a7 --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/cfm/cli/completer/CfmCompTagTypeCompleter.java @@ -0,0 +1,39 @@ +/* + * 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.cfm.cli.completer; + +import org.onosproject.cli.AbstractChoicesCompleter; +import org.onosproject.incubator.net.l2monitoring.cfm.Component; + +import java.util.ArrayList; +import java.util.List; + +/** + * CLI completer for Component TagType creation. + */ +public class CfmCompTagTypeCompleter extends AbstractChoicesCompleter { + @Override + public List choices() { + List choices = new ArrayList<>(); + + for (Component.TagType tagType: Component.TagType.values()) { + choices.add(String.valueOf(tagType.toString())); + } + + return choices; + } + +} diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/cli/completer/CfmMaCcmIntervalCompleter.java b/apps/cfm/src/main/java/org/onosproject/cfm/cli/completer/CfmMaCcmIntervalCompleter.java new file mode 100644 index 0000000000..6599ed35a8 --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/cfm/cli/completer/CfmMaCcmIntervalCompleter.java @@ -0,0 +1,39 @@ +/* + * 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.cfm.cli.completer; + +import org.onosproject.cli.AbstractChoicesCompleter; +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceAssociation; + +import java.util.ArrayList; +import java.util.List; + +/** + * CLI completer for Ccm Interval creation. + */ +public class CfmMaCcmIntervalCompleter extends AbstractChoicesCompleter { + @Override + public List choices() { + List choices = new ArrayList<>(); + + for (MaintenanceAssociation.CcmInterval ccmInterval: MaintenanceAssociation.CcmInterval.values()) { + choices.add(ccmInterval.toString()); + } + + return choices; + } + +} diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/cli/completer/CfmMaNameCompleter.java b/apps/cfm/src/main/java/org/onosproject/cfm/cli/completer/CfmMaNameCompleter.java new file mode 100644 index 0000000000..b484212a60 --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/cfm/cli/completer/CfmMaNameCompleter.java @@ -0,0 +1,51 @@ +/* + * Copyright 2017-present Open Networking Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.cfm.cli.completer; + +import org.onosproject.cli.AbstractChoicesCompleter; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMdService; + +import java.util.ArrayList; +import java.util.List; + +import static org.onosproject.cli.AbstractShellCommand.get; + +/** + * CLI completer for MA Name creation. + */ +public class CfmMaNameCompleter extends AbstractChoicesCompleter { + @Override + public List choices() { + List choices = new ArrayList<>(); + + CfmMdService service = get(CfmMdService.class); + service.getAllMaintenanceDomain().forEach(md -> + md.maintenanceAssociationList().forEach(ma -> + choices.add(new StringBuilder(md.mdId().mdName()) + .append("(") + .append(md.mdId().nameType()) + .append(")") + .append(ma.maId().maName()) + .append("(") + .append(ma.maId().nameType()) + .append(")").toString()) + ) + ); + + return choices; + } + +} diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/cli/completer/CfmMaNameTypeCompleter.java b/apps/cfm/src/main/java/org/onosproject/cfm/cli/completer/CfmMaNameTypeCompleter.java new file mode 100644 index 0000000000..d59a5c8dc7 --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/cfm/cli/completer/CfmMaNameTypeCompleter.java @@ -0,0 +1,43 @@ +/* + * 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.cfm.cli.completer; + +import org.apache.karaf.shell.console.Completer; +import org.apache.karaf.shell.console.completer.StringsCompleter; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort; + +import java.util.List; +import java.util.SortedSet; + +/** + * CLI completer for MA name type creation. + */ +public class CfmMaNameTypeCompleter implements Completer { + @Override + public int complete(String buffer, int cursor, List candidates) { + // Delegate string completer + StringsCompleter delegate = new StringsCompleter(); + SortedSet strings = delegate.getStrings(); + + for (MaIdShort.MaIdType nameType : MaIdShort.MaIdType.values()) { + strings.add(nameType.toString()); + } + + // Now let the completer do the work for figuring out what to offer. + return delegate.complete(buffer, cursor, candidates); + } + +} diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/cli/completer/CfmMdLevelCompleter.java b/apps/cfm/src/main/java/org/onosproject/cfm/cli/completer/CfmMdLevelCompleter.java new file mode 100644 index 0000000000..374e549623 --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/cfm/cli/completer/CfmMdLevelCompleter.java @@ -0,0 +1,39 @@ +/* + * 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.cfm.cli.completer; + +import org.onosproject.cli.AbstractChoicesCompleter; +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain; + +import java.util.ArrayList; +import java.util.List; + +/** + * CLI completer for MD Level creation. + */ +public class CfmMdLevelCompleter extends AbstractChoicesCompleter { + @Override + public List choices() { + List choices = new ArrayList<>(); + + for (MaintenanceDomain.MdLevel mdLevel:MaintenanceDomain.MdLevel.values()) { + choices.add(String.valueOf(mdLevel.toString())); + } + + return choices; + } + +} diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/cli/completer/CfmMdNameCompleter.java b/apps/cfm/src/main/java/org/onosproject/cfm/cli/completer/CfmMdNameCompleter.java new file mode 100644 index 0000000000..7a336e74fe --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/cfm/cli/completer/CfmMdNameCompleter.java @@ -0,0 +1,40 @@ +/* + * 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.cfm.cli.completer; + +import org.onosproject.cli.AbstractChoicesCompleter; +import static org.onosproject.cli.AbstractShellCommand.get; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMdService; + +import java.util.ArrayList; +import java.util.List; + +/** + * CLI completer for MD Name creation. + */ +public class CfmMdNameCompleter extends AbstractChoicesCompleter { + @Override + public List choices() { + List choices = new ArrayList<>(); + + CfmMdService service = get(CfmMdService.class); + service.getAllMaintenanceDomain().forEach(md -> + choices.add(md.mdId().mdName() + "(" + md.mdId().nameType() + ")")); + + return choices; + } + +} diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/cli/completer/CfmMdNameTypeCompleter.java b/apps/cfm/src/main/java/org/onosproject/cfm/cli/completer/CfmMdNameTypeCompleter.java new file mode 100644 index 0000000000..6e24fc7c36 --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/cfm/cli/completer/CfmMdNameTypeCompleter.java @@ -0,0 +1,43 @@ +/* + * 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.cfm.cli.completer; + +import org.apache.karaf.shell.console.Completer; +import org.apache.karaf.shell.console.completer.StringsCompleter; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; + +import java.util.List; +import java.util.SortedSet; + +/** + * CLI completer for MD Name Type creation. + */ +public class CfmMdNameTypeCompleter implements Completer { + @Override + public int complete(String buffer, int cursor, List candidates) { + // Delegate string completer + StringsCompleter delegate = new StringsCompleter(); + SortedSet strings = delegate.getStrings(); + + for (MdId.MdNameType nameType : MdId.MdNameType.values()) { + strings.add(nameType.toString()); + } + + // Now let the completer do the work for figuring out what to offer. + return delegate.complete(buffer, cursor, candidates); + } + +} diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/cli/completer/package-info.java b/apps/cfm/src/main/java/org/onosproject/cfm/cli/completer/package-info.java new file mode 100644 index 0000000000..419084d39e --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/cfm/cli/completer/package-info.java @@ -0,0 +1,19 @@ +/* + * 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. + */ +/** + * Completion of Commands for creating and deleting Maintenance Domains and Maintenance Associations. + */ +package org.onosproject.cfm.cli.completer; \ No newline at end of file diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/cli/package-info.java b/apps/cfm/src/main/java/org/onosproject/cfm/cli/package-info.java new file mode 100644 index 0000000000..4c57e221b5 --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/cfm/cli/package-info.java @@ -0,0 +1,19 @@ +/* + * 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. + */ +/** + * Commands for creating and deleting Maintenance Domains and Maintenance Associations. + */ +package org.onosproject.cfm.cli; \ No newline at end of file diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/impl/CfmWebApplication.java b/apps/cfm/src/main/java/org/onosproject/cfm/impl/CfmWebApplication.java new file mode 100644 index 0000000000..f21b66d313 --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/cfm/impl/CfmWebApplication.java @@ -0,0 +1,38 @@ +/* + * 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.cfm.impl; + +import java.util.Set; + +import org.onlab.rest.AbstractWebApplication; +import org.onosproject.soam.impl.DmWebResource; +import org.onosproject.soam.impl.LmWebResource; + +/** + * CFM REST API web application. + */ +public class CfmWebApplication extends AbstractWebApplication { + @Override + public Set> getClasses() { + return getClasses( + MdWebResource.class, + MaWebResource.class, + MepWebResource.class, + DmWebResource.class, + LmWebResource.class); + } +} diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/impl/MaWebResource.java b/apps/cfm/src/main/java/org/onosproject/cfm/impl/MaWebResource.java new file mode 100644 index 0000000000..c8613149d8 --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/cfm/impl/MaWebResource.java @@ -0,0 +1,177 @@ +/* + * 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.cfm.impl; + +import java.io.InputStream; +import java.net.URI; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.onosproject.cfm.web.MaintenanceAssociationCodec; +import org.onosproject.codec.JsonCodec; +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceAssociation; +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMdService; +import org.onosproject.rest.AbstractWebResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * Layer 2 CFM Maintenance Association web resource. + */ +@Path("md/{md_name}/ma") +public class MaWebResource extends AbstractWebResource { + private final Logger log = LoggerFactory.getLogger(getClass()); + + /** + * Get Maintenance Association by MD and MA name. + * + * @param mdName The name of a Maintenance Domain + * @param maName The name of a Maintenance Association belonging to the MD + * @return 200 OK with details of MA or 500 on Error + */ + @GET + @Path("{ma_name}") + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + public Response getMa(@PathParam("md_name") String mdName, + @PathParam("ma_name") String maName) { + log.debug("GET called for MA {}/{}", mdName, maName); + try { + MdId mdId = MdIdCharStr.asMdId(mdName); + MaIdShort maId = MaIdCharStr.asMaId(maName); + MaintenanceAssociation ma = get(CfmMdService.class) + .getMaintenanceAssociation(mdId, maId) + .orElseThrow(() -> new IllegalArgumentException( + "MA " + maName + " not Found")); + ObjectNode node = mapper().createObjectNode(); + node.set("ma", codec(MaintenanceAssociation.class).encode(ma, this)); + return ok(node).build(); + } catch (IllegalArgumentException e) { + log.error("Get MA {} failed", mdName + "/" + maName, e); + return Response.serverError() + .entity("{ \"failure\":\"" + e.toString() + "\" }").build(); + } + } + + /** + * Delete the Maintenance Association by MD and MA name. + * + * @param mdName The name of a Maintenance Domain + * @param maName The name of a Maintenance Association belonging to the MD + * @return 200 OK if removed, 304 if item was not found or 500 on Error + */ + @DELETE + @Path("{ma_name}") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response deleteMa(@PathParam("md_name") String mdName, + @PathParam("ma_name") String maName) { + log.debug("DELETE called for MA {}/{}", mdName, maName); + try { + MdId mdId = MdIdCharStr.asMdId(mdName); + MaIdShort maId = MaIdCharStr.asMaId(maName); + boolean deleted = get(CfmMdService.class) + .deleteMaintenanceAssociation(mdId, maId); + if (!deleted) { + return Response.notModified(mdName + "/" + + maName + " did not exist").build(); + } else { + return ok("{ \"success\":\"deleted " + mdName + + "/" + maName + "\" }").build(); + } + } catch (CfmConfigException e) { + log.error("Delete Maintenance Association {} failed", + mdName + "/" + maName, e); + return Response.serverError().entity("{ \"failure\":\"" + + e.toString() + "\" }").build(); + } + } + + /** + * Create Maintenance Association by MD and MA name. + * + * @param mdName The name of a Maintenance Domain + * @param input A JSON formatted input stream specifying the MA parameters + * @return 200 OK or 500 on error + */ + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response createMaintenanceAssociation(@PathParam("md_name") String mdName, + InputStream input) { + log.debug("POST called to Create MA"); + try { + MdId mdId = MdIdCharStr.asMdId(mdName); + MaintenanceDomain md = get(CfmMdService.class) + .getMaintenanceDomain(mdId).get(); + if (md == null) { + return Response.serverError().entity("{ \"failure\":\"md " + + mdName + " does not exist\" }").build(); + } + + ObjectMapper mapper = new ObjectMapper(); + JsonNode cfg = mapper.readTree(input); + JsonCodec maCodec = + codec(MaintenanceAssociation.class); + + MaintenanceAssociation ma; + try { + ma = ((MaintenanceAssociationCodec) maCodec) + .decode((ObjectNode) cfg, this, mdId.getNameLength()); + } catch (Exception e) { + log.error("Create MaintenanceAssociation on MD {} failed", mdName, e); + return Response.serverError() + .entity("{ \"failure\":\"" + e.toString() + "\" }") + .build(); + } + + Boolean alreadyExists = get(CfmMdService.class) + .createMaintenanceAssociation(mdId, ma); + if (alreadyExists) { + return Response.notModified(mdName + "/" + ma.maId() + + " already exists").build(); + } + return Response + .created(new URI("md/" + mdName + "/ma/" + ma.maId())) + .entity("{ \"success\":\"" + mdName + "/" + ma.maId() + " created\" }") + .build(); + + } catch (Exception | CfmConfigException e) { + log.error("Create MaintenanceAssociation on MD {} failed", mdName, e); + return Response.serverError() + .entity("{ \"failure\":\"" + e.toString() + "\" }") + .build(); + } + } +} diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/impl/MdWebResource.java b/apps/cfm/src/main/java/org/onosproject/cfm/impl/MdWebResource.java new file mode 100644 index 0000000000..ecf1fe9b5b --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/cfm/impl/MdWebResource.java @@ -0,0 +1,156 @@ +/* + * 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.cfm.impl; + +import java.io.InputStream; +import java.net.URI; +import java.util.Collection; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMdService; +import org.onosproject.rest.AbstractWebResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * Layer 2 CFM Maintenance Domain web resource. + */ +@Path("md") +public class MdWebResource extends AbstractWebResource { + private final Logger log = LoggerFactory.getLogger(getClass()); + public static final String JSON_NOT_NULL = "JsonNode can not be null"; + + /** + * Get all Maintenance Domains. + * + * @return 200 OK with a list of MDs and their children + */ + @GET + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + public Response getMds() { + log.debug("GET called for all MDs"); + Collection mdMap = + get(CfmMdService.class).getAllMaintenanceDomain(); + ArrayNode arrayNode = mapper().createArrayNode(); + arrayNode.add(codec(MaintenanceDomain.class).encode(mdMap, this)); + return ok(mapper().createObjectNode().set("mds", arrayNode)).build(); + } + + /** + * Get Maintenance Domain by name. + * + * @param mdName The name of a Maintenance Domain + * @return 200 OK with the details of the MD and its children or 500 on error + */ + @GET + @Path("{md_name}") + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + public Response getMd(@PathParam("md_name") String mdName) { + log.debug("GET called for MD {}", mdName); + try { + MaintenanceDomain md = get(CfmMdService.class) + .getMaintenanceDomain(MdIdCharStr.asMdId(mdName)) + .orElseThrow(() -> new IllegalArgumentException( + "MD " + mdName + " not Found")); + ObjectNode result = mapper().createObjectNode(); + result.set("md", codec(MaintenanceDomain.class).encode(md, this)); + return ok(result.toString()).build(); + } catch (IllegalArgumentException e) { + log.error("Get MD {} failed", mdName, e); + return Response.serverError() + .entity("{ \"failure\":\"" + e.toString() + "\" }").build(); + } + } + + /** + * Delete Maintenance Domain by name. + * + * @param mdName The name of a Maintenance Domain + * @return 200 OK, or 304 if not found or 500 on error + */ + @DELETE + @Path("{md_name}") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response deleteMd(@PathParam("md_name") String mdName) { + log.debug("DELETE called for MD {}", mdName); + try { + MdId mdId = MdIdCharStr.asMdId(mdName); + boolean deleted = get(CfmMdService.class).deleteMaintenanceDomain(mdId); + if (!deleted) { + return Response.notModified(mdName + " did not exist").build(); + } else { + return ok("{ \"success\":\"deleted " + mdName + "\" }").build(); + } + } catch (CfmConfigException e) { + log.error("Delete Maintenance Domain {} failed", mdName, e); + return Response.serverError() + .entity("{ \"failure\":\"" + e.toString() + "\" }").build(); + } + } + + /** + * Create Maintenance Domain. + * + * @param input A JSON formatted input stream specifying the MA parameters + * @return 200 OK, 304 if MD already exists or 500 on error + */ + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response createMaintenanceDomain(InputStream input) { + log.debug("POST called to Create MD"); + try { + ObjectMapper mapper = new ObjectMapper(); + JsonNode cfg = mapper.readTree(input); + MaintenanceDomain md = codec(MaintenanceDomain.class).decode((ObjectNode) cfg, this); + + if (get(CfmMdService.class).createMaintenanceDomain(md)) { + return Response.notModified(md.mdId().toString() + " already exists").build(); + } + return Response + .created(new URI("md/" + md.mdId())) + .entity("{ \"success\":\"" + md.mdId() + " created\" }") + .build(); + + } catch (Exception | CfmConfigException e) { + log.error("Create MaintenanceDomain", e); + return Response.serverError() + .entity("{ \"failure\":\"" + e.toString() + "\" }") + .build(); + } + } +} diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/impl/MepWebResource.java b/apps/cfm/src/main/java/org/onosproject/cfm/impl/MepWebResource.java new file mode 100644 index 0000000000..2486df07da --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/cfm/impl/MepWebResource.java @@ -0,0 +1,343 @@ +/* + * 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.cfm.impl; + +import java.io.InputStream; +import java.net.URI; +import java.util.Collection; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.onosproject.cfm.web.MepCodec; +import org.onosproject.codec.JsonCodec; +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceAssociation; +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep; +import org.onosproject.incubator.net.l2monitoring.cfm.MepEntry; +import org.onosproject.incubator.net.l2monitoring.cfm.MepLbCreate; +import org.onosproject.incubator.net.l2monitoring.cfm.MepLtCreate; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMdService; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepService; +import org.onosproject.rest.AbstractWebResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * Layer 2 CFM Maintenance Association Endpoint (MEP) web resource. + */ +@Path("md/{md_name}/ma/{ma_name}/mep") +public class MepWebResource extends AbstractWebResource { + private final Logger log = LoggerFactory.getLogger(getClass()); + + /** + * Get all MEPs by MD name, MA name. + * + * @param mdName The name of a Maintenance Domain + * @param maName The name of a Maintenance Association belonging to the MD + * @return 200 OK with a list of MEPS or 500 on error + */ + @GET + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + public Response getAllMepsForMa(@PathParam("md_name") String mdName, + @PathParam("ma_name") String maName) { + log.debug("GET all Meps called for MA {}", mdName + "/" + maName); + try { + MdId mdId = MdIdCharStr.asMdId(mdName); + MaIdShort maId = MaIdCharStr.asMaId(maName); + Collection mepCollection = get(CfmMepService.class).getAllMeps(mdId, maId); + ArrayNode an = mapper().createArrayNode(); + an.add(codec(MepEntry.class).encode(mepCollection, this)); + return ok(mapper().createObjectNode().set("meps", an)).build(); + } catch (CfmConfigException e) { + log.error("Get all Meps on {} failed because of exception", + mdName + "/" + maName, e); + return Response.serverError().entity("{ \"failure\":\"" + e.toString() + "\" }").build(); + } + + } + + /** + * Get MEP by MD name, MA name and Mep Id. + * + * @param mdName The name of a Maintenance Domain + * @param maName The name of a Maintenance Association belonging to the MD + * @param mepId The Id of the MEP + * @return 200 OK with details of the MEP or 500 on error + */ + @GET + @Path("{mep_id}") + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + public Response getMep(@PathParam("md_name") String mdName, + @PathParam("ma_name") String maName, + @PathParam("mep_id") short mepId) { + log.debug("GET called for MEP {}", mdName + "/" + maName + "/" + mepId); + try { + MdId mdId = MdIdCharStr.asMdId(mdName); + MaIdShort maId = MaIdCharStr.asMaId(maName); + MepEntry mepEntry = get(CfmMepService.class) + .getMep(mdId, maId, MepId.valueOf(mepId)); + if (mepEntry == null) { + return Response.serverError().entity("{ \"failure\":\"MEP " + + mdName + "/" + maName + "/" + mepId + " not found\" }").build(); + } + ObjectNode node = mapper().createObjectNode(); + node.set("mep", codec(MepEntry.class).encode(mepEntry, this)); + return ok(node).build(); + } catch (CfmConfigException e) { + log.error("Get Mep {} failed because of exception", + mdName + "/" + maName + "/" + mepId, e); + return Response.serverError().entity("{ \"failure\":\"" + e.toString() + "\" }").build(); + } + } + + /** + * Delete MEP by MD name, MA name and Mep Id. + * + * @param mdName The name of a Maintenance Domain + * @param maName The name of a Maintenance Association belonging to the MD + * @param mepIdShort The Id of the MEP + * @return 200 OK or 304 if not found, or 500 on error + */ + @DELETE + @Path("{mep_id}") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response deleteMep(@PathParam("md_name") String mdName, + @PathParam("ma_name") String maName, + @PathParam("mep_id") short mepIdShort) { + log.debug("DELETE called for MEP " + mdName + "/" + maName + "/" + mepIdShort); + try { + MdId mdId = MdIdCharStr.asMdId(mdName); + MaIdShort maId = MaIdCharStr.asMaId(maName); + boolean deleted = get(CfmMepService.class) + .deleteMep(mdId, maId, MepId.valueOf(mepIdShort)); + if (!deleted) { + return Response.notModified(mdName + "/" + maName + "/" + + mepIdShort + " did not exist").build(); + } else { + return ok("{ \"success\":\"deleted " + mdName + "/" + maName + + "/" + mepIdShort + "\" }").build(); + } + } catch (CfmConfigException e) { + log.error("Delete Mep {} failed because of exception ", + mdName + "/" + maName + "/" + mepIdShort, e); + return Response.serverError().entity("{ \"failure\":\"" + + e.toString() + "\" }").build(); + } + } + + /** + * Create MEP with MD name, MA name and Mep Json. + * + * @param mdName The name of a Maintenance Domain + * @param maName The name of a Maintenance Association belonging to the MD + * @param input A JSON formatted input stream specifying the Mep parameters + * @return 201 Created or 304 if already exists or 500 on error + */ + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response createMep(@PathParam("md_name") String mdName, + @PathParam("ma_name") String maName, InputStream input) { + log.debug("POST called to Create Mep"); + try { + MdId mdId = MdIdCharStr.asMdId(mdName); + MaIdShort maId = MaIdCharStr.asMaId(maName); + MaintenanceAssociation ma = get(CfmMdService.class).getMaintenanceAssociation(mdId, maId).get(); + + ObjectMapper mapper = new ObjectMapper(); + JsonNode cfg = mapper.readTree(input); + JsonCodec mepCodec = codec(Mep.class); + + Mep mep = ((MepCodec) mepCodec).decode((ObjectNode) cfg, this, mdName, maName); + + Boolean issuccess = get(CfmMepService.class).createMep(mdId, maId, mep); + if (!issuccess) { + return Response.notModified(mdName + "/" + ma.maId() + "/" + mep.mepId() + + " already exists").build(); + } + return Response + .created(new URI("md/" + mdName + "/ma/" + ma.maId() + "/mep/" + mep.mepId())) + .entity("{ \"success\":\"mep " + mdName + "/" + ma.maId() + "/" + mep.mepId() + " created\" }") + .build(); + } catch (Exception | CfmConfigException e) { + log.error("Create Mep on " + mdName + "/" + maName + " failed because of exception {}", + e.toString()); + return Response.serverError() + .entity("{ \"failure\":\"" + e.toString() + "\" }") + .build(); + } + } + + /** + * Transmit Loopback on MEP with MD name, MA name and Mep Id. + * + * @param mdName The name of a Maintenance Domain + * @param maName The name of a Maintenance Association belonging to the MD + * @param mepIdShort The id of a MEP belonging to the MA + * @param input A JSON formatted input stream specifying the Mep parameters + * @return 202 Received with success message or 500 on error + */ + @PUT + @Path("{mep_id}/transmit-loopback") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response transmitLoopback( + @PathParam("md_name") String mdName, + @PathParam("ma_name") String maName, + @PathParam("mep_id") short mepIdShort, + InputStream input) { + log.debug("PUT called to Transmit Loopback on Mep"); + + MdId mdId = MdIdCharStr.asMdId(mdName); + MaIdShort maId = MaIdCharStr.asMaId(maName); + MaintenanceDomain md = get(CfmMdService.class).getMaintenanceDomain(mdId).get(); + MaintenanceAssociation ma = get(CfmMdService.class) + .getMaintenanceAssociation(mdId, maId).get(); + + MepId mepId = MepId.valueOf(mepIdShort); + + try { + ObjectMapper mapper = new ObjectMapper(); + JsonNode cfg = mapper.readTree(input); + JsonCodec mepLbCreateCodec = codec(MepLbCreate.class); + + MepLbCreate lbCreate = mepLbCreateCodec.decode((ObjectNode) cfg, this); + get(CfmMepService.class).transmitLoopback(md.mdId(), ma.maId(), mepId, lbCreate); + } catch (Exception | CfmConfigException e) { + log.error("Transmit Loopback on " + mdName + "/" + maName + + "/{} failed", String.valueOf(mepIdShort), e); + return Response.serverError() + .entity("{ \"failure\":\"" + e.toString() + "\" }") + .build(); + } + + return Response.accepted() + .entity("{ \"success\":\"Loopback on MEP " + mdName + "/" + ma.maId() + "/" + + mepId.id() + " started\" }").build(); + } + + /** + * Abort Loopback on MEP with MD name, MA name and Mep Id. + * + * @param mdName The name of a Maintenance Domain + * @param maName The name of a Maintenance Association belonging to the MD + * @param mepIdShort The id of a MEP belonging to the MA + * @return 202 Received with success message or 500 on error + */ + @PUT + @Path("{mep_id}/abort-loopback") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response abortLoopback( + @PathParam("md_name") String mdName, + @PathParam("ma_name") String maName, + @PathParam("mep_id") short mepIdShort) { + log.debug("PUT called to Abort Loopback on Mep"); + + MdId mdId = MdIdCharStr.asMdId(mdName); + MaIdShort maId = MaIdCharStr.asMaId(maName); + MaintenanceDomain md = get(CfmMdService.class).getMaintenanceDomain(mdId).get(); + MaintenanceAssociation ma = get(CfmMdService.class) + .getMaintenanceAssociation(mdId, maId).get(); + + MepId mepId = MepId.valueOf(mepIdShort); + + try { + get(CfmMepService.class).abortLoopback(md.mdId(), ma.maId(), mepId); + } catch (CfmConfigException e) { + log.error("Abort Loopback on " + mdName + "/" + maName + + "/{} failed", String.valueOf(mepIdShort), e); + return Response.serverError() + .entity("{ \"failure\":\"" + e.toString() + "\" }") + .build(); + } + + return Response.accepted() + .entity("{ \"success\":\"Loopback on MEP " + mdName + "/" + ma.maId() + "/" + + mepId.id() + " aborted\" }").build(); + } + + /** + * Transmit Linktrace on MEP with MD name, MA name and Mep Id. + * + * @param mdName The name of a Maintenance Domain + * @param maName The name of a Maintenance Association belonging to the MD + * @param mepIdShort The id of a MEP belonging to the MA + * @param input A JSON formatted input stream specifying the Linktrace parameters + * @return 202 Received with success message or 500 on error + */ + @PUT + @Path("{mep_id}/transmit-linktrace") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response transmitLinktrace( + @PathParam("md_name") String mdName, + @PathParam("ma_name") String maName, + @PathParam("mep_id") short mepIdShort, + InputStream input) { + log.debug("PUT called to Transmit Linktrace on Mep"); + + MdId mdId = MdIdCharStr.asMdId(mdName); + MaIdShort maId = MaIdCharStr.asMaId(maName); + MaintenanceDomain md = get(CfmMdService.class).getMaintenanceDomain(mdId).get(); + MaintenanceAssociation ma = get(CfmMdService.class) + .getMaintenanceAssociation(mdId, maId).get(); + + MepId mepId = MepId.valueOf(mepIdShort); + + try { + ObjectMapper mapper = new ObjectMapper(); + JsonNode cfg = mapper.readTree(input); + JsonCodec mepLtCreateCodec = codec(MepLtCreate.class); + + MepLtCreate ltCreate = mepLtCreateCodec.decode((ObjectNode) cfg, this); + get(CfmMepService.class).transmitLinktrace(md.mdId(), ma.maId(), mepId, ltCreate); + } catch (Exception | CfmConfigException e) { + log.error("Transmit Linktrace on " + mdName + "/" + maName + + "/{} failed", String.valueOf(mepIdShort), e); + return Response.serverError() + .entity("{ \"failure\":\"" + e.toString() + "\" }") + .build(); + } + + return Response.accepted() + .entity("{ \"success\":\"Linktrace on MEP " + mdName + "/" + ma.maId() + "/" + + mepId.id() + " started\" }").build(); + } +} diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/impl/package-info.java b/apps/cfm/src/main/java/org/onosproject/cfm/impl/package-info.java new file mode 100644 index 0000000000..798317dce5 --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/cfm/impl/package-info.java @@ -0,0 +1,19 @@ +/* + * 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. + */ +/** + * REST Web Application for CFM. + */ +package org.onosproject.cfm.impl; \ No newline at end of file diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/package-info.java b/apps/cfm/src/main/java/org/onosproject/cfm/package-info.java new file mode 100644 index 0000000000..2522fb4f41 --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/cfm/package-info.java @@ -0,0 +1,19 @@ +/* + * 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. + */ +/** + * REST Web Component for CFM and SOAM. + */ +package org.onosproject.cfm; \ No newline at end of file diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/web/ComponentCodec.java b/apps/cfm/src/main/java/org/onosproject/cfm/web/ComponentCodec.java new file mode 100644 index 0000000000..6a534979aa --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/cfm/web/ComponentCodec.java @@ -0,0 +1,123 @@ +/* + * 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.cfm.web; + +import static org.onlab.util.Tools.nullIsIllegal; + +import java.util.ArrayList; +import java.util.List; + +import org.onlab.packet.VlanId; +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.incubator.net.l2monitoring.cfm.Component; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultComponent; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * Encode and decode to/from JSON to Component object. + */ +public class ComponentCodec extends JsonCodec { + + private static final String COMPONENT_ID = "component-id"; + private static final String COMPONENT = "component"; + private static final String VID_LIST = "vid-list"; + private static final String TAG_TYPE = "tag-type"; + private static final String MHF_CREATION_TYPE = "mhf-creation-type"; + private static final String ID_PERMISSION = "id-permission"; + + @Override + public ObjectNode encode(Component component, CodecContext context) { + + ObjectNode node = context.mapper().createObjectNode() + .put(COMPONENT_ID, component.componentId()); + + node.set(VID_LIST, new VidCodec().encode(component.vidList(), context)); + + if (component.mhfCreationType() != null) { + node.put(MHF_CREATION_TYPE, component.mhfCreationType().name()); + } + if (component.idPermission() != null) { + node.put(ID_PERMISSION, component.idPermission().name()); + } + if (component.tagType() != null) { + node.put(TAG_TYPE, component.tagType().name()); + } + + return (ObjectNode) context.mapper().createObjectNode().set(COMPONENT, node); + } + + @Override + public ArrayNode encode(Iterable components, CodecContext context) { + ArrayNode an = context.mapper().createArrayNode(); + components.forEach(component -> { + an.add(encode(component, context)); + }); + return an; + } + + @Override + public Component decode(ObjectNode json, CodecContext context) { + if (json == null || !json.isObject()) { + return null; + } + + JsonNode componentNode = json.get(COMPONENT); + + int componentId = nullIsIllegal(componentNode.get(COMPONENT_ID), + "component-id is required").asInt(); + Component.ComponentBuilder componentBuilder = + DefaultComponent.builder(componentId); + + List vidList = (new VidCodec()).decode((ArrayNode) + nullIsIllegal(componentNode.get(VID_LIST), "vid-list is required"), context); + if (vidList == null || vidList.size() < 1) { + throw new IllegalArgumentException("A least one VID is required in component: " + componentId); + } + for (VlanId vid:vidList) { + componentBuilder = componentBuilder.addToVidList(vid); + } + + if (componentNode.get(TAG_TYPE) != null) { + componentBuilder = componentBuilder + .tagType(Component.TagType.valueOf( + componentNode.get(TAG_TYPE).asText())); + } + + if (componentNode.get(MHF_CREATION_TYPE) != null) { + componentBuilder = componentBuilder + .mhfCreationType(Component.MhfCreationType.valueOf( + componentNode.get(MHF_CREATION_TYPE).asText())); + } + if (componentNode.get(ID_PERMISSION) != null) { + componentBuilder = componentBuilder + .idPermission(Component.IdPermissionType.valueOf( + componentNode.get(ID_PERMISSION).asText())); + } + + return componentBuilder.build(); + } + + @Override + public List decode(ArrayNode json, CodecContext context) { + List componentList = new ArrayList<>(); + json.forEach(node -> componentList.add(decode((ObjectNode) node, context))); + return componentList; + } +} diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/web/FngAddressCodec.java b/apps/cfm/src/main/java/org/onosproject/cfm/web/FngAddressCodec.java new file mode 100644 index 0000000000..47cc9b6054 --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/cfm/web/FngAddressCodec.java @@ -0,0 +1,75 @@ +/* + * Copyright 2017-present Open Networking Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.cfm.web; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.onlab.packet.Ip4Address; +import org.onlab.packet.Ip6Address; +import org.onlab.packet.IpAddress; +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep.FngAddress; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.onlab.util.Tools.nullIsIllegal; + +/** + * Encode and decode to/from JSON to FngAddress object. + */ +public class FngAddressCodec extends JsonCodec { + + @Override + public ObjectNode encode(FngAddress fngAddress, CodecContext context) { + checkNotNull(fngAddress, "FngAddress cannot be null"); + ObjectNode result = context.mapper().createObjectNode() + .put("address-type", fngAddress.addressType().name()); + + if (fngAddress.addressType().equals(Mep.FngAddressType.IPV4) || + fngAddress.addressType().equals(Mep.FngAddressType.IPV6)) { + result.put("ip-address", fngAddress.ipAddress().toString()); + } + + return result; + } + + @Override + public FngAddress decode(ObjectNode json, CodecContext context) { + if (json == null || !json.isObject()) { + return null; + } + + JsonNode node = json.get("fng-address"); + + String addressType = nullIsIllegal(node.get("address-type"), + "address type is required").asText(); + Mep.FngAddressType type = Mep.FngAddressType.valueOf(addressType.toUpperCase()); + JsonNode ipAddressNode = node.get("ipAddress"); + + switch (type) { + case IPV4: + return FngAddress.ipV4Address(Ip4Address.valueOf(ipAddressNode.asText())); + case IPV6: + return FngAddress.ipV6Address(Ip6Address.valueOf(ipAddressNode.asText())); + case NOT_TRANSMITTED: + return FngAddress.notTransmitted(IpAddress.valueOf(ipAddressNode.asText())); + case NOT_SPECIFIED: + default: + return FngAddress.notSpecified(); + } + } +} diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/web/MaintenanceAssociationCodec.java b/apps/cfm/src/main/java/org/onosproject/cfm/web/MaintenanceAssociationCodec.java new file mode 100644 index 0000000000..62be35d03e --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/cfm/web/MaintenanceAssociationCodec.java @@ -0,0 +1,146 @@ +/* + * 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.cfm.web; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.onlab.util.Tools.nullIsIllegal; + +import java.util.List; + +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.incubator.net.l2monitoring.cfm.Component; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMaintenanceAssociation; +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceAssociation; +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceAssociation.CcmInterval; +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceAssociation.MaBuilder; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaId2Octet; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdIccY1731; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdPrimaryVid; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdRfc2685VpnId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * Encode and decode to/from JSON to MaintenanceAssociation object. + */ +public class MaintenanceAssociationCodec extends JsonCodec { + + private static final String MA_NAME_TYPE = "maNameType"; + private static final String MA_NUMERIC_ID = "maNumericId"; + private static final String MA_NAME = "maName"; + private static final String CCM_INTERVAL = "ccm-interval"; + private static final String COMPONENT_LIST = "component-list"; + private static final String RMEP_LIST = "rmep-list"; + private static final String MA = "ma"; + + @Override + public ObjectNode encode(MaintenanceAssociation ma, CodecContext context) { + checkNotNull(ma, "Maintenance Association cannot be null"); + ObjectNode result = context.mapper().createObjectNode() + .put(MA_NAME, ma.maId().toString()) + .put(MA_NAME_TYPE, ma.maId().nameType().name()); + if (ma.maNumericId() > 0) { + result = result.put(MA_NUMERIC_ID, ma.maNumericId()); + } + if (ma.ccmInterval() != null) { + result = result.put(CCM_INTERVAL, ma.ccmInterval().name()); + } + + result.set(COMPONENT_LIST, new ComponentCodec().encode(ma.componentList(), context)); + result.set(RMEP_LIST, new RMepCodec().encode(ma.remoteMepIdList(), context)); + + return result; + } + + public MaintenanceAssociation decode(ObjectNode json, CodecContext context, int mdNameLen) { + if (json == null || !json.isObject()) { + return null; + } + + JsonNode maNode = json.get(MA); + + String maName = nullIsIllegal(maNode.get(MA_NAME), "maName is required").asText(); + String maNameType = MaIdShort.MaIdType.CHARACTERSTRING.name(); + if (maNode.get(MA_NAME_TYPE) != null) { + maNameType = maNode.get(MA_NAME_TYPE).asText(); + } + + try { + MaIdShort maId = null; + MaIdShort.MaIdType maIdType = MaIdShort.MaIdType.valueOf(maNameType); + switch (maIdType) { + case PRIMARYVID: + maId = MaIdPrimaryVid.asMaId(maName); + break; + case TWOOCTET: + maId = MaId2Octet.asMaId(maName); + break; + case RFC2685VPNID: + maId = MaIdRfc2685VpnId.asMaIdHex(maName); + break; + case ICCY1731: + maId = MaIdIccY1731.asMaId(maName); + break; + case CHARACTERSTRING: + default: + maId = MaIdCharStr.asMaId(maName); + } + MaBuilder builder = + DefaultMaintenanceAssociation.builder(maId, mdNameLen); + + JsonNode maNumericIdNode = maNode.get(MA_NUMERIC_ID); + if (maNumericIdNode != null) { + short mdNumericId = (short) maNumericIdNode.asInt(); + builder = builder.maNumericId(mdNumericId); + } + if (maNode.get(CCM_INTERVAL) != null) { + builder.ccmInterval(CcmInterval.valueOf(maNode.get(CCM_INTERVAL).asText())); + } + + List componentList = (new ComponentCodec()).decode((ArrayNode) + nullIsIllegal(maNode.get(COMPONENT_LIST), + "component-list is required"), context); + for (Component component:componentList) { + builder = builder.addToComponentList(component); + } + + List remoteMeps = (new RMepCodec()).decode( + (ArrayNode) nullIsIllegal(maNode.get(RMEP_LIST), "rmep-list is required"), context); + for (MepId remoteMep:remoteMeps) { + builder = builder.addToRemoteMepIdList(remoteMep); + } + + return builder.build(); + } catch (CfmConfigException e) { + throw new IllegalArgumentException(e); + } + + } + + @Override + public ArrayNode encode(Iterable maEntities, CodecContext context) { + ArrayNode an = context.mapper().createArrayNode(); + maEntities.forEach(ma -> an.add(encode(ma, context))); + return an; + } +} diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/web/MaintenanceDomainCodec.java b/apps/cfm/src/main/java/org/onosproject/cfm/web/MaintenanceDomainCodec.java new file mode 100644 index 0000000000..a6bcf01a20 --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/cfm/web/MaintenanceDomainCodec.java @@ -0,0 +1,127 @@ +/* + * 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.cfm.web; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.onlab.util.Tools.nullIsIllegal; + +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMaintenanceDomain; +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain; +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain.MdLevel; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdDomainName; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdMacUint; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdNone; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * Encode and decode to/from JSON to MaintenanceDomain object. + */ +public class MaintenanceDomainCodec extends JsonCodec { + + private static final String MD_LEVEL = "mdLevel"; + private static final String MD_NUMERIC_ID = "mdNumericId"; + private static final String MD = "md"; + private static final String MD_NAME = "mdName"; + private static final String MD_NAME_TYPE = "mdNameType"; + + public MaintenanceDomainCodec() { + super(); + + } + + @Override + public ObjectNode encode(MaintenanceDomain md, CodecContext context) { + checkNotNull(md, "Maintenance Domain cannot be null"); + ObjectNode result = context.mapper().createObjectNode() + .put(MD_NAME, md.mdId().toString()) + .put(MD_NAME_TYPE, md.mdId().nameType().name()) + .put(MD_LEVEL, md.mdLevel().name()); + if (md.mdNumericId() > 0) { + result = result.put(MD_NUMERIC_ID, md.mdNumericId()); + } + result.set("maList", + new MaintenanceAssociationCodec() + .encode(md.maintenanceAssociationList(), context)); + + return result; + } + + @Override + public MaintenanceDomain decode(ObjectNode json, CodecContext context) { + if (json == null || !json.isObject()) { + return null; + } + + JsonNode mdNode = json.get(MD); + + String mdName = nullIsIllegal(mdNode.get(MD_NAME), "mdName is required").asText(); + String mdNameType = MdId.MdNameType.CHARACTERSTRING.name(); + if (mdNode.get(MD_NAME_TYPE) != null) { + mdNameType = mdNode.get(MD_NAME_TYPE).asText(); + } + + try { + MdId mdId = null; + MdId.MdNameType nameType = + MdId.MdNameType.valueOf(mdNameType); + switch (nameType) { + case DOMAINNAME: + mdId = MdIdDomainName.asMdId(mdName); + break; + case MACANDUINT: + mdId = MdIdMacUint.asMdId(mdName); + break; + case NONE: + mdId = MdIdNone.asMdId(); + break; + case CHARACTERSTRING: + default: + mdId = MdIdCharStr.asMdId(mdName); + } + + MaintenanceDomain.MdBuilder builder = DefaultMaintenanceDomain.builder(mdId); + JsonNode mdLevelNode = mdNode.get(MD_LEVEL); + if (mdLevelNode != null) { + MdLevel mdLevel = MdLevel.valueOf(mdLevelNode.asText()); + builder = builder.mdLevel(mdLevel); + } + JsonNode mdNumericIdNode = mdNode.get(MD_NUMERIC_ID); + if (mdNumericIdNode != null) { + short mdNumericId = (short) mdNumericIdNode.asInt(); + builder = builder.mdNumericId(mdNumericId); + } + + return builder.build(); + } catch (CfmConfigException e) { + throw new IllegalArgumentException(e); + } + } + + @Override + public ArrayNode encode(Iterable mdEntities, CodecContext context) { + ArrayNode an = context.mapper().createArrayNode(); + mdEntities.forEach(md -> an.add(encode(md, context))); + return an; + } +} diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/web/MepCodec.java b/apps/cfm/src/main/java/org/onosproject/cfm/web/MepCodec.java new file mode 100644 index 0000000000..73a58b63db --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/cfm/web/MepCodec.java @@ -0,0 +1,163 @@ +/* + * 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.cfm.web; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.onlab.util.Tools.nullIsIllegal; + +import org.onlab.packet.VlanId; +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMep; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep.MepBuilder; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep.MepDirection; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep.Priority; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; +import org.onosproject.net.DeviceId; +import org.onosproject.net.PortNumber; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +import java.time.Duration; + +/** + * Encode and decode to/from JSON to Mep object. + */ +public class MepCodec extends JsonCodec { + private static final String ADMINISTRATIVE_STATE = "administrative-state"; + private static final String PRIMARY_VID = "primary-vid"; + private static final String CCM_LTM_PRIORITY = "ccm-ltm-priority"; + private static final String CCI_ENABLED = "cci-enabled"; + private static final String FNG_ADDRESS = "fng-address"; + private static final String LOWEST_FAULT_PRIORITY_DEFECT = "lowest-fault-priority-defect"; + private static final String DEFECT_PRESENT_TIME = "defect-present-time"; + private static final String DEFECT_ABSENT_TIME = "defect-absent-time"; + + public Mep decode(ObjectNode json, CodecContext context, String + mdName, String maName) { + if (json == null || !json.isObject()) { + return null; + } + + JsonNode mepNode = json.get("mep"); + + int mepId = Integer.parseInt( + nullIsIllegal(mepNode.get("mepId"), "mepId is required").asText()); + DeviceId deviceId = DeviceId.deviceId( + nullIsIllegal(mepNode.get("deviceId"), "deviceId is required") + .asText()); + PortNumber port = PortNumber + .portNumber(Long.parseLong( + nullIsIllegal(mepNode.get("port"), "port is required") + .asText())); + MepDirection direction = MepDirection.valueOf( + nullIsIllegal(mepNode.get("direction"), "direction is required"). + asText()); + + try { + MdId mdId = MdIdCharStr.asMdId(mdName); + MaIdShort maId = MaIdCharStr.asMaId(maName); + MepBuilder mepBuilder = DefaultMep + .builder(MepId.valueOf((short) mepId), + deviceId, port, direction, mdId, maId); + + if (mepNode.get(PRIMARY_VID) != null) { + mepBuilder.primaryVid(VlanId.vlanId( + (short) mepNode.get(PRIMARY_VID).asInt(0))); + } + + if (mepNode.get(ADMINISTRATIVE_STATE) != null) { + mepBuilder.administrativeState(mepNode.get(ADMINISTRATIVE_STATE) + .asBoolean()); + } + + if (mepNode.get(CCM_LTM_PRIORITY) != null) { + mepBuilder.ccmLtmPriority( + Priority.values()[mepNode.get(CCM_LTM_PRIORITY).asInt(0)]); + } + + if (mepNode.get(CCI_ENABLED) != null) { + mepBuilder.cciEnabled(mepNode.get(CCI_ENABLED).asBoolean()); + } + + if (mepNode.get(LOWEST_FAULT_PRIORITY_DEFECT) != null) { + mepBuilder.lowestFaultPriorityDefect( + Mep.LowestFaultDefect.values()[mepNode.get(LOWEST_FAULT_PRIORITY_DEFECT).asInt()]); + } + + if (mepNode.get(DEFECT_ABSENT_TIME) != null) { + mepBuilder.defectAbsentTime( + Duration.parse(mepNode.get(DEFECT_ABSENT_TIME).asText())); + } + + if (mepNode.get(DEFECT_PRESENT_TIME) != null) { + mepBuilder.defectPresentTime( + Duration.parse(mepNode.get(DEFECT_PRESENT_TIME).asText())); + } + + if (mepNode.get(FNG_ADDRESS) != null) { + mepBuilder.fngAddress((new FngAddressCodec()) + .decode((ObjectNode) mepNode, context)); + } + + + return mepBuilder.build(); + } catch (CfmConfigException e) { + throw new IllegalArgumentException(e); + } + } + + @Override + public ObjectNode encode(Mep mep, CodecContext context) { + checkNotNull(mep, "Mep cannot be null"); + ObjectNode result = context.mapper().createObjectNode() + .put("mepId", mep.mepId().id()) + .put("deviceId", mep.deviceId().toString()) + .put("port", mep.port().toLong()) + .put("direction", mep.direction().name()) + .put("mdName", mep.mdId().toString()) + .put("maName", mep.maId().toString()) + .put(ADMINISTRATIVE_STATE, mep.administrativeState()) + .put(CCI_ENABLED, mep.cciEnabled()); + if (mep.ccmLtmPriority() != null) { + result.put(CCM_LTM_PRIORITY, mep.ccmLtmPriority().ordinal()); + } + if (mep.primaryVid() != null) { + result.put(PRIMARY_VID, mep.primaryVid().toShort()); + } + if (mep.fngAddress() != null) { + result.put(FNG_ADDRESS, new FngAddressCodec().encode(mep.fngAddress(), context)); + } + if (mep.lowestFaultPriorityDefect() != null) { + result.put(LOWEST_FAULT_PRIORITY_DEFECT, mep.lowestFaultPriorityDefect().ordinal()); + } + if (mep.defectPresentTime() != null) { + result.put(DEFECT_PRESENT_TIME, mep.defectPresentTime().toString()); + } + if (mep.defectAbsentTime() != null) { + result.put(DEFECT_ABSENT_TIME, mep.defectAbsentTime().toString()); + } + + return result; + } +} diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/web/MepEntryCodec.java b/apps/cfm/src/main/java/org/onosproject/cfm/web/MepEntryCodec.java new file mode 100644 index 0000000000..d1618a7d85 --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/cfm/web/MepEntryCodec.java @@ -0,0 +1,93 @@ +/* + * 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.cfm.web; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Iterator; +import java.util.Map.Entry; + +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep; +import org.onosproject.incubator.net.l2monitoring.cfm.MepEntry; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * Encode and decode to/from JSON to MepEntry object. + */ +public class MepEntryCodec extends JsonCodec { + + @Override + public ObjectNode encode(MepEntry mepEntry, CodecContext context) { + checkNotNull(mepEntry, "Mep cannot be null"); + + ObjectNode result = context.mapper().createObjectNode(); + + //Get the common attributes + Mep mep = (Mep) mepEntry; + ObjectNode mepAttrs = new MepCodec().encode(mep, context); + Iterator> elements = mepAttrs.fields(); + while (elements.hasNext()) { + Entry element = elements.next(); + result.set(element.getKey(), element.getValue()); + } + + if (mepEntry.macAddress() != null) { + result.put("macAddress", mepEntry.macAddress().toString()); + } + + if (mepEntry.loopbackAttributes() != null) { + result.set("loopback", new MepLbEntryCodec() + .encode(mepEntry.loopbackAttributes(), context)); + } + + if (mepEntry.activeRemoteMepList() != null) { + result.set("remoteMeps", new RemoteMepEntryCodec() + .encode(mepEntry.activeRemoteMepList(), context)); + } + + if (mepEntry.activeErrorCcmDefect()) { + result.put("activeErrorCcmDefect", true); + } + if (mepEntry.activeMacStatusDefect()) { + result.put("activeMacStatusDefect", true); + } + if (mepEntry.activeRdiCcmDefect()) { + result.put("activeRdiCcmDefect", true); + } + if (mepEntry.activeRemoteCcmDefect()) { + result.put("activeRemoteCcmDefect", true); + } + if (mepEntry.activeXconCcmDefect()) { + result.put("activeXconCcmDefect", true); + } + return result; + } + + @Override + public ArrayNode encode(Iterable mepEntryEntities, CodecContext context) { + ArrayNode an = context.mapper().createArrayNode(); + if (mepEntryEntities != null) { + mepEntryEntities.forEach(mepEntry -> an.add(encode(mepEntry, context))); + } + return an; + } + +} diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/web/MepLbCreateCodec.java b/apps/cfm/src/main/java/org/onosproject/cfm/web/MepLbCreateCodec.java new file mode 100644 index 0000000000..e29415c89c --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/cfm/web/MepLbCreateCodec.java @@ -0,0 +1,122 @@ +/* + * 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.cfm.web; + +import org.onlab.packet.MacAddress; +import org.onlab.util.HexString; +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMepLbCreate; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep.Priority; +import org.onosproject.incubator.net.l2monitoring.cfm.MepLbCreate; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Encode and decode to/from JSON to MepLbCreate object. + */ +public class MepLbCreateCodec extends JsonCodec { + + public static final String NUMBER_MESSAGES = "numberMessages"; + public static final String REMOTE_MEP_ID = "remoteMepId"; + public static final String REMOTE_MEP_MAC = "remoteMepMac"; + public static final String DATA_TLV_HEX = "dataTlvHex"; + public static final String VLAN_DROP_ELIGIBLE = "vlanDropEligible"; + public static final String VLAN_PRIORITY = "vlanPriority"; + public static final String LOOPBACK = "loopback"; + + @Override + public ObjectNode encode(MepLbCreate mepLbCreate, CodecContext context) { + checkNotNull(mepLbCreate, "Mep Lb Create cannot be null"); + ObjectNode result = context.mapper().createObjectNode() + .put(NUMBER_MESSAGES, mepLbCreate.numberMessages()); + + if (mepLbCreate.remoteMepId() != null) { + result.put(REMOTE_MEP_ID, mepLbCreate.remoteMepId().value()); + } else { + result.put(REMOTE_MEP_MAC, mepLbCreate.remoteMepAddress().toString()); + } + + if (mepLbCreate.dataTlvHex() != null) { + result.put(DATA_TLV_HEX, mepLbCreate.dataTlvHex()); + } + if (mepLbCreate.vlanDropEligible() != null) { + result.put(VLAN_DROP_ELIGIBLE, mepLbCreate.vlanDropEligible()); + } + if (mepLbCreate.vlanPriority() != null) { + result.put(VLAN_PRIORITY, mepLbCreate.vlanPriority().ordinal()); + } + return result; + } + + + @Override + public MepLbCreate decode(ObjectNode json, CodecContext context) { + if (json == null || !json.isObject()) { + return null; + } + + JsonNode loopbackNode = json.get(LOOPBACK); + + JsonNode remoteMepIdNode = loopbackNode.get(REMOTE_MEP_ID); + JsonNode remoteMepMacNode = loopbackNode.get(REMOTE_MEP_MAC); + + MepLbCreate.MepLbCreateBuilder lbCreateBuilder = null; + if (remoteMepIdNode != null) { + MepId remoteMepId = MepId.valueOf((short) remoteMepIdNode.asInt()); + lbCreateBuilder = DefaultMepLbCreate.builder(remoteMepId); + } else if (remoteMepMacNode != null) { + MacAddress remoteMepMac = MacAddress.valueOf( + remoteMepMacNode.asText()); + lbCreateBuilder = DefaultMepLbCreate.builder(remoteMepMac); + } else { + throw new IllegalArgumentException( + "Either a remoteMepId or a remoteMepMac"); + } + + JsonNode numMessagesNode = loopbackNode.get(NUMBER_MESSAGES); + if (numMessagesNode != null) { + int numMessages = numMessagesNode.asInt(); + lbCreateBuilder.numberMessages(numMessages); + } + + JsonNode vlanDropEligibleNode = loopbackNode.get(VLAN_DROP_ELIGIBLE); + if (vlanDropEligibleNode != null) { + boolean vlanDropEligible = vlanDropEligibleNode.asBoolean(); + lbCreateBuilder.vlanDropEligible(vlanDropEligible); + } + + JsonNode vlanPriorityNode = loopbackNode.get(VLAN_PRIORITY); + if (vlanPriorityNode != null) { + short vlanPriority = (short) vlanPriorityNode.asInt(); + lbCreateBuilder.vlanPriority(Priority.values()[vlanPriority]); + } + + JsonNode dataTlvHexNode = loopbackNode.get(DATA_TLV_HEX); + if (dataTlvHexNode != null) { + String dataTlvHex = loopbackNode.get(DATA_TLV_HEX).asText(); + if (!dataTlvHex.isEmpty()) { + lbCreateBuilder.dataTlv(HexString.fromHexString(dataTlvHex)); + } + } + + return lbCreateBuilder.build(); + } +} diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/web/MepLbEntryCodec.java b/apps/cfm/src/main/java/org/onosproject/cfm/web/MepLbEntryCodec.java new file mode 100644 index 0000000000..62409cda7a --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/cfm/web/MepLbEntryCodec.java @@ -0,0 +1,44 @@ +/* + * 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.cfm.web; + +import static com.google.common.base.Preconditions.checkNotNull; + +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.incubator.net.l2monitoring.cfm.MepLbEntry; + +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * Encode and decode to/from JSON to MepLbEntry object. + */ +public class MepLbEntryCodec extends JsonCodec { + + @Override + public ObjectNode encode(MepLbEntry mepLbEntry, CodecContext context) { + checkNotNull(mepLbEntry, "Mep Lb Entry cannot be null"); + ObjectNode result = context.mapper().createObjectNode() + .put("nextLbmIdentifier", mepLbEntry.nextLbmIdentifier()) + .put("countLbrTransmitted", mepLbEntry.countLbrTransmitted()) + .put("countLbrReceived", mepLbEntry.countLbrReceived()) + .put("countLbrValidInOrder", mepLbEntry.countLbrValidInOrder()) + .put("countLbrValidOutOfOrder", mepLbEntry.countLbrValidOutOfOrder()) + .put("countLbrMacMisMatch", mepLbEntry.countLbrMacMisMatch()); + + return result; + } +} diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/web/MepLtCreateCodec.java b/apps/cfm/src/main/java/org/onosproject/cfm/web/MepLtCreateCodec.java new file mode 100644 index 0000000000..0141a739df --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/cfm/web/MepLtCreateCodec.java @@ -0,0 +1,110 @@ +/* + * 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.cfm.web; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.onlab.packet.MacAddress; +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMepLtCreate; +import org.onosproject.incubator.net.l2monitoring.cfm.MepLtCreate; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; + +import java.util.BitSet; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Encode and decode to/from JSON to MepLtCreate object. + */ +public class MepLtCreateCodec extends JsonCodec { + + private static final String REMOTE_MEP_ID = "remoteMepId"; + private static final String REMOTE_MEP_MAC = "remoteMepMac"; + private static final String DEFAULT_TTL = "defaultTtl"; + private static final String TRANSMIT_LTM_FLAGS = "transmitLtmFlags"; + private static final String LINKTRACE = "linktrace"; + private static final String USE_FDB_ONLY = "use-fdb-only"; + + @Override + public ObjectNode encode(MepLtCreate mepLtCreate, CodecContext context) { + checkNotNull(mepLtCreate, "Mep Lt Create cannot be null"); + ObjectNode result = context.mapper().createObjectNode(); + + if (mepLtCreate.remoteMepId() != null) { + result.put(REMOTE_MEP_ID, mepLtCreate.remoteMepId().value()); + } else { + result.put(REMOTE_MEP_MAC, mepLtCreate.remoteMepAddress().toString()); + } + + if (mepLtCreate.defaultTtl() != null) { + result.put(DEFAULT_TTL, mepLtCreate.defaultTtl()); + } + if (mepLtCreate.transmitLtmFlags() != null) { + result.put(TRANSMIT_LTM_FLAGS, + mepLtCreate.transmitLtmFlags().get(0) ? USE_FDB_ONLY : ""); + } + + return result; + } + + + @Override + public MepLtCreate decode(ObjectNode json, CodecContext context) { + if (json == null || !json.isObject()) { + return null; + } + + JsonNode linktraceNode = json.get(LINKTRACE); + + JsonNode remoteMepIdNode = linktraceNode.get(REMOTE_MEP_ID); + JsonNode remoteMepMacNode = linktraceNode.get(REMOTE_MEP_MAC); + + MepLtCreate.MepLtCreateBuilder ltCreateBuilder = null; + if (remoteMepIdNode != null) { + MepId remoteMepId = MepId.valueOf((short) remoteMepIdNode.asInt()); + ltCreateBuilder = DefaultMepLtCreate.builder(remoteMepId); + } else if (remoteMepMacNode != null) { + MacAddress remoteMepMac = MacAddress.valueOf( + remoteMepMacNode.asText()); + ltCreateBuilder = DefaultMepLtCreate.builder(remoteMepMac); + } else { + throw new IllegalArgumentException( + "Either a remoteMepId or a remoteMepMac"); + } + + JsonNode defaultTtlNode = linktraceNode.get(DEFAULT_TTL); + if (defaultTtlNode != null) { + short defaultTtl = (short) defaultTtlNode.asInt(); + ltCreateBuilder.defaultTtl(defaultTtl); + } + + JsonNode transmitLtmFlagsNode = linktraceNode.get(TRANSMIT_LTM_FLAGS); + if (transmitLtmFlagsNode != null) { + if (transmitLtmFlagsNode.asText().isEmpty()) { + ltCreateBuilder.transmitLtmFlags(BitSet.valueOf(new long[]{0})); + } else if (transmitLtmFlagsNode.asText().equals(USE_FDB_ONLY)) { + ltCreateBuilder.transmitLtmFlags(BitSet.valueOf(new long[]{1})); + } else { + throw new IllegalArgumentException("Expecting value 'use-fdb-only' " + + "or '' for " + TRANSMIT_LTM_FLAGS); + } + } + + return ltCreateBuilder.build(); + } +} diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/web/RMepCodec.java b/apps/cfm/src/main/java/org/onosproject/cfm/web/RMepCodec.java new file mode 100644 index 0000000000..7edb204f08 --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/cfm/web/RMepCodec.java @@ -0,0 +1,69 @@ +/* + * 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.cfm.web; + +import static org.onlab.util.Tools.nullIsIllegal; + +import java.util.ArrayList; +import java.util.List; + +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * Encode and decode to/from JSON to RMep object. + */ +public class RMepCodec extends JsonCodec { + + @Override + public ObjectNode encode(MepId rmep, CodecContext context) { + return context.mapper().createObjectNode().put("rmep", rmep.id()); + } + + @Override + public ArrayNode encode(Iterable rmeps, CodecContext context) { + ArrayNode an = context.mapper().createArrayNode(); + rmeps.forEach(rmep -> { + an.add(encode(rmep, context)); + }); + return an; + } + + @Override + public MepId decode(ObjectNode json, CodecContext context) { + if (json == null || !json.isObject()) { + return null; + } + + JsonNode vidNode = json.get("rmep"); + + return MepId.valueOf( + nullIsIllegal((short) vidNode.asInt(), "rmep is required")); + + } + + @Override + public List decode(ArrayNode json, CodecContext context) { + List rmepList = new ArrayList<>(); + json.forEach(node -> rmepList.add(decode((ObjectNode) node, context))); + return rmepList; + } +} diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/web/RemoteMepEntryCodec.java b/apps/cfm/src/main/java/org/onosproject/cfm/web/RemoteMepEntryCodec.java new file mode 100644 index 0000000000..4f8344a31a --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/cfm/web/RemoteMepEntryCodec.java @@ -0,0 +1,74 @@ +/* + * 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.cfm.web; + +import static com.google.common.base.Preconditions.checkNotNull; + +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.incubator.net.l2monitoring.cfm.RemoteMepEntry; + +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * Encode and decode to/from JSON to RemoteMepEntry object. + */ +public class RemoteMepEntryCodec extends JsonCodec { + + @Override + public ObjectNode encode(RemoteMepEntry remoteMepEntry, CodecContext context) { + checkNotNull(remoteMepEntry, "Mep cannot be null"); + ObjectNode result = context.mapper().createObjectNode() + .put("remoteMepId", remoteMepEntry.remoteMepId().toString()) + .put("remoteMepState", remoteMepEntry.state().name()) + .put("rdi", remoteMepEntry.rdi()); + + if (remoteMepEntry.failedOrOkTime() != null) { + result = result.put("failedOrOkTime", + remoteMepEntry.failedOrOkTime().toString()); + } + + if (remoteMepEntry.macAddress() != null) { + result = result.put("macAddress", remoteMepEntry.macAddress().toString()); + } + + if (remoteMepEntry.portStatusTlvType() != null) { + result = result.put("portStatusTlvType", + remoteMepEntry.portStatusTlvType().name()); + } + if (remoteMepEntry.interfaceStatusTlvType() != null) { + result = result.put("interfaceStatusTlvType", + remoteMepEntry.interfaceStatusTlvType().name()); + } + if (remoteMepEntry.senderIdTlvType() != null) { + result = result.put("senderIdTlvType", + remoteMepEntry.senderIdTlvType().name()); + } + + return result; + } + + @Override + public ArrayNode encode(Iterable remoteMepEntries, + CodecContext context) { + ArrayNode an = context.mapper().createArrayNode(); + remoteMepEntries.forEach(remoteMepEntry -> + an.add(encode(remoteMepEntry, context))); + return an; + } + +} diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/web/VidCodec.java b/apps/cfm/src/main/java/org/onosproject/cfm/web/VidCodec.java new file mode 100644 index 0000000000..a673719915 --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/cfm/web/VidCodec.java @@ -0,0 +1,71 @@ +/* + * 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.cfm.web; + +import static org.onlab.util.Tools.nullIsIllegal; + +import java.util.ArrayList; +import java.util.List; + +import org.onlab.packet.VlanId; +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * Encode and decode to/from JSON to Vid object. + */ +public class VidCodec extends JsonCodec { + + @Override + public ObjectNode encode(VlanId vid, CodecContext context) { + return context.mapper().createObjectNode().put("vid", vid.toString()); + } + + @Override + public ArrayNode encode(Iterable vids, CodecContext context) { + ArrayNode an = context.mapper().createArrayNode(); + vids.forEach(vid -> { + an.add(encode(vid, context)); + }); + return an; + } + + @Override + public VlanId decode(ObjectNode json, CodecContext context) { + if (json == null || !json.isObject()) { + return null; + } + + JsonNode vidNode = json.get("vid"); + + int vid = (nullIsIllegal(vidNode.asInt(), "vid is required")); + if (vid < 0 || vid > 4095) { + throw new IllegalArgumentException("VID values must be between 0 and 4095"); + } + return VlanId.vlanId((short) vid); + } + + @Override + public List decode(ArrayNode json, CodecContext context) { + List vidList = new ArrayList<>(); + json.forEach(node -> vidList.add(decode((ObjectNode) node, context))); + return vidList; + } +} diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/web/package-info.java b/apps/cfm/src/main/java/org/onosproject/cfm/web/package-info.java new file mode 100644 index 0000000000..265a1fa22f --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/cfm/web/package-info.java @@ -0,0 +1,19 @@ +/* + * 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. + */ +/** + * Codecs for converting CFM objects to and from JSON. + */ +package org.onosproject.cfm.web; \ No newline at end of file diff --git a/apps/cfm/src/main/java/org/onosproject/soam/impl/DmWebResource.java b/apps/cfm/src/main/java/org/onosproject/soam/impl/DmWebResource.java new file mode 100644 index 0000000000..b7324503be --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/soam/impl/DmWebResource.java @@ -0,0 +1,257 @@ +/* + * 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.soam.impl; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Collection; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.onosproject.codec.JsonCodec; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepService; +import org.onosproject.incubator.net.l2monitoring.soam.SoamConfigException; +import org.onosproject.incubator.net.l2monitoring.soam.SoamId; +import org.onosproject.incubator.net.l2monitoring.soam.SoamService; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementEntry; +import org.onosproject.rest.AbstractWebResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * Layer 2 SOAM Delay Measurement web resource. + */ +@Path("md/{md_name}/ma/{ma_name}/mep/{mep_id}/dm") +public class DmWebResource extends AbstractWebResource { + private final Logger log = LoggerFactory.getLogger(getClass()); + + /** + * Get all DMs for a Mep. + * + * @param mdName The name of a Maintenance Domain + * @param maName The name of a Maintenance Association belonging to the MD + * @param mepId The ID of a Mep belonging to the MA + * @return 200 OK with a list of DMs or 500 on error + */ + @GET + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + public Response getAllDmsForMep(@PathParam("md_name") String mdName, + @PathParam("ma_name") String maName, + @PathParam("mep_id") short mepId) { + log.debug("GET all DMs called for MEP {}", mdName + "/" + maName + "/" + mepId); + try { + MdId mdId = MdIdCharStr.asMdId(mdName); + MaIdShort maId = MaIdCharStr.asMaId(maName); + MepId mepIdObj = MepId.valueOf(mepId); + Collection dmCollection = + get(SoamService.class).getAllDms(mdId, maId, mepIdObj); + ArrayNode an = mapper().createArrayNode(); + an.add(codec(DelayMeasurementEntry.class).encode(dmCollection, this)); + return ok(mapper().createObjectNode().set("dms", an)).build(); + } catch (CfmConfigException | SoamConfigException e) { + log.error("Get DM {} failed because of exception {}", + mdName + "/" + maName + "/" + mepId, e.toString()); + return Response.serverError().entity("{ \"failure\":\"" + e.toString() + "\" }").build(); + } + } + + /** + * Get DM by MD name, MA name, Mep Id and Dm id. + * + * @param mdName The name of a Maintenance Domain + * @param maName The name of a Maintenance Association belonging to the MD + * @param mepId The Id of the MEP + * @param dmId The Id of the DM + * @return 200 OK with details of the DM or 500 on error + */ + @GET + @Path("{dm_id}") + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + public Response getDm(@PathParam("md_name") String mdName, + @PathParam("ma_name") String maName, + @PathParam("mep_id") short mepId, @PathParam("dm_id") int dmId) { + log.debug("GET called for DM {}", mdName + "/" + maName + "/" + mepId + "/" + dmId); + try { + MdId mdId = MdIdCharStr.asMdId(mdName); + MaIdShort maId = MaIdCharStr.asMaId(maName); + MepId mepIdObj = MepId.valueOf(mepId); + SoamId dmIdObj = SoamId.valueOf(dmId); + DelayMeasurementEntry dm = get(SoamService.class) + .getDm(mdId, maId, mepIdObj, dmIdObj); + if (dm == null) { + return Response.serverError().entity("{ \"failure\":\"DM " + + mdName + "/" + maName + "/" + mepId + "/" + dmId + " not found\" }").build(); + } + ObjectNode node = mapper().createObjectNode(); + node.set("dm", codec(DelayMeasurementEntry.class).encode(dm, this)); + return ok(node).build(); + } catch (CfmConfigException | SoamConfigException e) { + log.error("Get DM {} failed because of exception {}", + mdName + "/" + maName + "/" + mepId + "/" + dmId, e.toString()); + return Response.serverError().entity("{ \"failure\":\"" + e.toString() + "\" }").build(); + } + } + + /** + * Abort DM by MD name, MA name, Mep Id and DM Id. + * In the API the measurement is aborted, and not truly deleted. It still + * remains so that its results may be read. Depending on the device it will + * get overwritten on the creation of subsequent measurements. + * Use clear stats to delete old results + * measurements. + * + * @param mdName The name of a Maintenance Domain + * @param maName The name of a Maintenance Association belonging to the MD + * @param mepId The Id of the MEP + * @param dmId The Id of the DM + * @return 200 OK or 304 if not found, or 500 on error + */ + @DELETE + @Path("{dm_id}") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response abortDm(@PathParam("md_name") String mdName, + @PathParam("ma_name") String maName, + @PathParam("mep_id") short mepId, + @PathParam("dm_id") int dmId) { + log.debug("DELETE called for DM {}", mdName + "/" + maName + "/" + mepId + "/" + dmId); + try { + MdId mdId = MdIdCharStr.asMdId(mdName); + MaIdShort maId = MaIdCharStr.asMaId(maName); + MepId mepIdObj = MepId.valueOf(mepId); + SoamId dmIdObj = SoamId.valueOf(dmId); + + get(SoamService.class).abortDm(mdId, maId, mepIdObj, dmIdObj); + return ok("{ \"success\":\"deleted (aborted) " + mdName + "/" + maName + + "/" + mepId + "/" + dmId + "\" }").build(); + } catch (CfmConfigException e) { + log.error("Delete (abort) DM {} failed because of exception {}", + mdName + "/" + maName + "/" + mepId + "/" + dmId, e.toString()); + return Response.serverError().entity("{ \"failure\":\"" + e.toString() + "\" }").build(); + } + } + + /** + * Create DM with MD name, MA name, Mep id and DM Json. + * + * @param mdName The name of a Maintenance Domain + * @param maName The name of a Maintenance Association belonging to the MD + * @param mepId The Id of the MEP belonging to the MEP + * @param input A JSON formatted input stream specifying the DM parameters + * @return 201 Created or 304 if already exists or 500 on error + */ + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response createDm(@PathParam("md_name") String mdName, + @PathParam("ma_name") String maName, + @PathParam("mep_id") short mepId, InputStream input) { + log.debug("POST called to Create Dm"); + try { + MdId mdId = MdIdCharStr.asMdId(mdName); + MaIdShort maId = MaIdCharStr.asMaId(maName); + MepId mepIdObj = MepId.valueOf(mepId); + + Mep mep = get(CfmMepService.class).getMep(mdId, maId, mepIdObj); + if (mep == null) { + return Response.serverError().entity("{ \"failure\":\"mep " + + mdName + "/" + maName + "/" + mepId + " does not exist\" }").build(); + } + + ObjectMapper mapper = new ObjectMapper(); + JsonNode cfg = mapper.readTree(input); + JsonCodec dmCodec = codec(DelayMeasurementCreate.class); + + DelayMeasurementCreate dm = dmCodec.decode((ObjectNode) cfg, this); + get(SoamService.class).createDm(mdId, maId, mepIdObj, dm); + return Response + .created(new URI("md/" + mdName + "/ma/" + maName + "/mep/" + + mepId + "/dm")) + .entity("{ \"success\":\"dm " + mdName + "/" + maName + "/" + + mepId + " created\" }") + .build(); + } catch (CfmConfigException | SoamConfigException | IllegalArgumentException | + IOException | URISyntaxException e) { + log.error("Create DM on " + mdName + "/" + maName + "/" + mepId + + " failed because of exception {}", e.toString()); + return Response.serverError() + .entity("{ \"failure\":\"" + e.toString() + "\" }") + .build(); + } + } + + /** + * Clear DM history stats by MD name, MA name, Mep Id and DM Id. + * + * @param mdName The name of a Maintenance Domain + * @param maName The name of a Maintenance Association belonging to the MD + * @param mepId The Id of the MEP + * @param dmId The Id of the DM + * @return 200 OK or 304 if not found, or 500 on error + */ + @PUT + @Path("{dm_id}/clear-history") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response clearDmHistory(@PathParam("md_name") String mdName, + @PathParam("ma_name") String maName, + @PathParam("mep_id") short mepId, + @PathParam("dm_id") int dmId) { + log.debug("clear-history called for DM {}", mdName + "/" + maName + + "/" + mepId + "/" + dmId); + try { + MdId mdId = MdIdCharStr.asMdId(mdName); + MaIdShort maId = MaIdCharStr.asMaId(maName); + MepId mepIdObj = MepId.valueOf(mepId); + SoamId dmIdObj = SoamId.valueOf(dmId); + + get(SoamService.class).clearDelayHistoryStats(mdId, maId, mepIdObj, dmIdObj); + return ok("{ \"success\":\"cleared DM history stats for " + + mdName + "/" + maName + "/" + mepId + "/" + dmId + "\" }").build(); + } catch (CfmConfigException e) { + log.error("Clear history stats for DM {} failed because of exception {}", + mdName + "/" + maName + "/" + mepId + "/" + dmId, e.toString()); + return Response.serverError().entity("{ \"failure\":\"" + + e.toString() + "\" }").build(); + } + } +} diff --git a/apps/cfm/src/main/java/org/onosproject/soam/impl/LmWebResource.java b/apps/cfm/src/main/java/org/onosproject/soam/impl/LmWebResource.java new file mode 100644 index 0000000000..d88966888e --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/soam/impl/LmWebResource.java @@ -0,0 +1,256 @@ +/* + * 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.soam.impl; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.onosproject.codec.JsonCodec; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepService; +import org.onosproject.incubator.net.l2monitoring.soam.SoamConfigException; +import org.onosproject.incubator.net.l2monitoring.soam.SoamId; +import org.onosproject.incubator.net.l2monitoring.soam.SoamService; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementCreate; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementEntry; +import org.onosproject.rest.AbstractWebResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Collection; + +/** + * Layer 2 SOAM Loss Measurement web resource. + */ +@Path("md/{md_name}/ma/{ma_name}/mep/{mep_id}/lm") +public class LmWebResource extends AbstractWebResource { + private final Logger log = LoggerFactory.getLogger(getClass()); + + /** + * Get all LMs for a Mep. + * + * @param mdName The name of a Maintenance Domain + * @param maName The name of a Maintenance Association belonging to the MD + * @param mepId The ID of a Mep belonging to the MA + * @return 200 OK with a list of LMs or 500 on error + */ + @GET + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + public Response getAllLmsForMep(@PathParam("md_name") String mdName, + @PathParam("ma_name") String maName, + @PathParam("mep_id") short mepId) { + + log.debug("GET all LMs called for MEP {}", mdName + "/" + maName + "/" + mepId); + try { + MdId mdId = MdIdCharStr.asMdId(mdName); + MaIdShort maId = MaIdCharStr.asMaId(maName); + MepId mepIdObj = MepId.valueOf(mepId); + Collection lmCollection = + get(SoamService.class).getAllLms(mdId, maId, mepIdObj); + ArrayNode an = mapper().createArrayNode(); + an.add(codec(LossMeasurementEntry.class).encode(lmCollection, this)); + return ok(mapper().createObjectNode().set("lms", an)).build(); + } catch (CfmConfigException | SoamConfigException e) { + log.error("Get LM {} failed because of exception {}", + mdName + "/" + maName + "/" + mepId, e.toString()); + return Response.serverError().entity("{ \"failure\":\"" + e.toString() + "\" }").build(); + } + } + + /** + * Get LM by MD name, MA name, Mep Id and Dm id. + * + * @param mdName The name of a Maintenance Domain + * @param maName The name of a Maintenance Association belonging to the MD + * @param mepId The Id of the MEP + * @param lmId The Id of the LM + * @return 200 OK with details of the LM or 500 on error + */ + @GET + @Path("{lm_id}") + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.APPLICATION_JSON) + public Response getLm(@PathParam("md_name") String mdName, + @PathParam("ma_name") String maName, + @PathParam("mep_id") short mepId, @PathParam("lm_id") int lmId) { + log.debug("GET called for LM {}", mdName + "/" + maName + "/" + mepId + "/" + lmId); + try { + MdId mdId = MdIdCharStr.asMdId(mdName); + MaIdShort maId = MaIdCharStr.asMaId(maName); + MepId mepIdObj = MepId.valueOf(mepId); + SoamId lmIdObj = SoamId.valueOf(lmId); + LossMeasurementEntry lm = get(SoamService.class) + .getLm(mdId, maId, mepIdObj, lmIdObj); + if (lm == null) { + return Response.serverError().entity("{ \"failure\":\"LM " + + mdName + "/" + maName + "/" + mepId + "/" + lmId + " not found\" }").build(); + } + ObjectNode node = mapper().createObjectNode(); + node.set("lm", codec(LossMeasurementEntry.class).encode(lm, this)); + return ok(node).build(); + } catch (CfmConfigException | SoamConfigException e) { + log.error("Get LM {} failed because of exception {}", + mdName + "/" + maName + "/" + mepId + "/" + lmId, e.toString()); + return Response.serverError().entity("{ \"failure\":\"" + e.toString() + "\" }").build(); + } + } + + /** + * Abort LM by MD name, MA name, Mep Id and LM Id. + * In the API the measurement is aborted, and not truly deleted. It still + * remains so that its results may be read. Depending on the device it will + * get overwritten on the creation of subsequent measurements. + * Use clear stats to delete old results measurements. + * + * @param mdName The name of a Maintenance Domain + * @param maName The name of a Maintenance Association belonging to the MD + * @param mepId The Id of the MEP + * @param lmId The Id of the LM + * @return 200 OK or 304 if not found, or 500 on error + */ + @DELETE + @Path("{lm_id}") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response abortLm(@PathParam("md_name") String mdName, + @PathParam("ma_name") String maName, + @PathParam("mep_id") short mepId, + @PathParam("lm_id") int lmId) { + log.debug("DELETE called for LM {}", mdName + "/" + maName + "/" + mepId + "/" + lmId); + try { + MdId mdId = MdIdCharStr.asMdId(mdName); + MaIdShort maId = MaIdCharStr.asMaId(maName); + MepId mepIdObj = MepId.valueOf(mepId); + SoamId lmIdObj = SoamId.valueOf(lmId); + + get(SoamService.class).abortLm(mdId, maId, mepIdObj, lmIdObj); + return ok("{ \"success\":\"deleted (aborted) " + mdName + "/" + maName + + "/" + mepId + "/" + lmId + "\" }").build(); + } catch (CfmConfigException e) { + log.error("Delete (abort) LM {} failed because of exception {}", + mdName + "/" + maName + "/" + mepId + "/" + lmId, e.toString()); + return Response.serverError().entity("{ \"failure\":\"" + e.toString() + "\" }").build(); + } + } + + /** + * Create LM with MD name, MA name, Mep id and LM Json. + * + * @param mdName The name of a Maintenance Domain + * @param maName The name of a Maintenance Association belonging to the MD + * @param mepId The Id of the MEP belonging to the MEP + * @param input A JSON formatted input stream specifying the LM parameters + * @return 201 Created or 304 if already exists or 500 on error + */ + @POST + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response createLm(@PathParam("md_name") String mdName, + @PathParam("ma_name") String maName, + @PathParam("mep_id") short mepId, InputStream input) { + log.debug("POST called to Create Lm"); + try { + MdId mdId = MdIdCharStr.asMdId(mdName); + MaIdShort maId = MaIdCharStr.asMaId(maName); + MepId mepIdObj = MepId.valueOf(mepId); + + Mep mep = get(CfmMepService.class).getMep(mdId, maId, mepIdObj); + if (mep == null) { + return Response.serverError().entity("{ \"failure\":\"mep " + + mdName + "/" + maName + "/" + mepId + " does not exist\" }").build(); + } + + ObjectMapper mapper = new ObjectMapper(); + JsonNode cfg = mapper.readTree(input); + JsonCodec lmCodec = codec(LossMeasurementCreate.class); + + LossMeasurementCreate lm = lmCodec.decode((ObjectNode) cfg, this); + get(SoamService.class).createLm(mdId, maId, mepIdObj, lm); + return Response + .created(new URI("md/" + mdName + "/ma/" + maName + "/mep/" + + mepId + "/lm")) + .entity("{ \"success\":\"lm " + mdName + "/" + maName + "/" + + mepId + " created\" }") + .build(); + } catch (CfmConfigException | SoamConfigException | IllegalArgumentException | + IOException | URISyntaxException e) { + log.error("Create LM on " + mdName + "/" + maName + "/" + mepId + + " failed because of exception {}", e.toString()); + return Response.serverError() + .entity("{ \"failure\":\"" + e.toString() + "\" }") + .build(); + } + } + + /** + * Clear LM history stats by MD name, MA name, Mep Id and LM Id. + * + * @param mdName The name of a Maintenance Domain + * @param maName The name of a Maintenance Association belonging to the MD + * @param mepId The Id of the MEP + * @param lmId The Id of the LM + * @return 200 OK or 304 if not found, or 500 on error + */ + @PUT + @Path("{lm_id}/clear-history") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response clearLmHistory(@PathParam("md_name") String mdName, + @PathParam("ma_name") String maName, + @PathParam("mep_id") short mepId, + @PathParam("lm_id") int lmId) { + log.debug("clear-history called for LM {}", mdName + "/" + maName + + "/" + mepId + "/" + lmId); + try { + MdId mdId = MdIdCharStr.asMdId(mdName); + MaIdShort maId = MaIdCharStr.asMaId(maName); + MepId mepIdObj = MepId.valueOf(mepId); + SoamId lmIdObj = SoamId.valueOf(lmId); + + get(SoamService.class).clearDelayHistoryStats(mdId, maId, mepIdObj, lmIdObj); + return ok("{ \"success\":\"cleared LM history stats for " + + mdName + "/" + maName + "/" + mepId + "/" + lmId + "\" }").build(); + } catch (CfmConfigException e) { + log.error("Clear history stats for LM {} failed because of exception {}", + mdName + "/" + maName + "/" + mepId + "/" + lmId, e.toString()); + return Response.serverError().entity("{ \"failure\":\"" + + e.toString() + "\" }").build(); + } + } + +} diff --git a/apps/cfm/src/main/java/org/onosproject/soam/impl/package-info.java b/apps/cfm/src/main/java/org/onosproject/soam/impl/package-info.java new file mode 100644 index 0000000000..370030f1fc --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/soam/impl/package-info.java @@ -0,0 +1,19 @@ +/* + * 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. + */ +/** + * REST Web Application for SOAM. + */ +package org.onosproject.soam.impl; \ No newline at end of file diff --git a/apps/cfm/src/main/java/org/onosproject/soam/web/DelayMeasurementStatCodec.java b/apps/cfm/src/main/java/org/onosproject/soam/web/DelayMeasurementStatCodec.java new file mode 100644 index 0000000000..7bd0d7a531 --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/soam/web/DelayMeasurementStatCodec.java @@ -0,0 +1,205 @@ +/* + * 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.soam.web; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.time.Duration; +import java.util.Map; + +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStat; + +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * Encode and decode to/from JSON to DelayMeasurementStat object. + */ +public class DelayMeasurementStatCodec extends JsonCodec { + + private static final String LOWER_LIMIT = "lowerLimit"; + private static final String COUNT = "count"; + private static final String BINS = "bins"; + private static final String SOAM_PDUS_SENT = "soamPdusSent"; + private static final String SOAM_PDUS_RECEIVED = "soamPdusReceived"; + + @Override + public ObjectNode encode(DelayMeasurementStat dmStat, CodecContext context) { + checkNotNull(dmStat, "DM stat cannot be null"); + ObjectNode result = context.mapper().createObjectNode() + .put("elapsedTime", dmStat.elapsedTime().toString()) + .put("suspectStatus", String.valueOf(dmStat.suspectStatus())); + + if (dmStat.frameDelayTwoWayMin() != null) { + result = result.put("frameDelayTwoWayMin", + dmStat.frameDelayTwoWayMin().toString()); + } + if (dmStat.frameDelayTwoWayMax() != null) { + result = result.put("frameDelayTwoWayMax", + dmStat.frameDelayTwoWayMax().toString()); + } + if (dmStat.frameDelayTwoWayAvg() != null) { + result = result.put("frameDelayTwoWayAvg", + dmStat.frameDelayTwoWayAvg().toString()); + } + if (dmStat.frameDelayTwoWayBins() != null) { + result = (ObjectNode) result.set("frameDelayTwoWayBins", + encode(dmStat.frameDelayTwoWayBins(), context)); + } + if (dmStat.frameDelayForwardMin() != null) { + result = result.put("frameDelayForwardMin", + dmStat.frameDelayForwardMin().toString()); + } + if (dmStat.frameDelayForwardMax() != null) { + result = result.put("frameDelayForwardMax", + dmStat.frameDelayForwardMax().toString()); + } + if (dmStat.frameDelayForwardAvg() != null) { + result = result.put("frameDelayForwardAvg", + dmStat.frameDelayForwardAvg().toString()); + } + if (dmStat.frameDelayForwardBins() != null) { + result = (ObjectNode) result.set("frameDelayForwardBins", + encode(dmStat.frameDelayForwardBins(), context)); + } + if (dmStat.frameDelayBackwardMin() != null) { + result = result.put("frameDelayBackwardMin", + dmStat.frameDelayBackwardMin().toString()); + } + if (dmStat.frameDelayBackwardMax() != null) { + result = result.put("frameDelayBackwardMax", + dmStat.frameDelayBackwardMax().toString()); + } + if (dmStat.frameDelayBackwardAvg() != null) { + result = result.put("frameDelayBackwardAvg", + dmStat.frameDelayBackwardAvg().toString()); + } + if (dmStat.frameDelayBackwardBins() != null) { + result = (ObjectNode) result.set("frameDelayBackwardBins", + encode(dmStat.frameDelayBackwardBins(), context)); + } + if (dmStat.interFrameDelayVariationTwoWayMin() != null) { + result = result.put("interFrameDelayVariationTwoWayMin", + dmStat.interFrameDelayVariationTwoWayMin().toString()); + } + if (dmStat.interFrameDelayVariationTwoWayMax() != null) { + result.put("interFrameDelayVariationTwoWayMax", + dmStat.interFrameDelayVariationTwoWayMax().toString()); + } + if (dmStat.interFrameDelayVariationTwoWayAvg() != null) { + result.put("interFrameDelayVariationTwoWayAvg", + dmStat.interFrameDelayVariationTwoWayAvg().toString()); + } + if (dmStat.interFrameDelayVariationTwoWayBins() != null) { + result = (ObjectNode) result.set("interFrameDelayVariationTwoWayBins", + encode(dmStat.interFrameDelayVariationTwoWayBins(), context)); + } + if (dmStat.interFrameDelayVariationForwardMin() != null) { + result = result.put("interFrameDelayVariationForwardMin", + dmStat.interFrameDelayVariationForwardMin().toString()); + } + if (dmStat.interFrameDelayVariationForwardMax() != null) { + result = result.put("interFrameDelayVariationForwardMax", + dmStat.interFrameDelayVariationForwardMax().toString()); + } + if (dmStat.interFrameDelayVariationForwardAvg() != null) { + result = result.put("interFrameDelayVariationForwardAvg", + dmStat.interFrameDelayVariationForwardAvg().toString()); + } + if (dmStat.interFrameDelayVariationForwardBins() != null) { + result = (ObjectNode) result.set("interFrameDelayVariationForwardBins", + encode(dmStat.interFrameDelayVariationForwardBins(), context)); + } + if (dmStat.interFrameDelayVariationBackwardMin() != null) { + result = result.put("interFrameDelayVariationBackwardMin", + dmStat.interFrameDelayVariationBackwardMin().toString()); + } + if (dmStat.interFrameDelayVariationBackwardMax() != null) { + result = result.put("interFrameDelayVariationBackwardMax", + dmStat.interFrameDelayVariationBackwardMax().toString()); + } + if (dmStat.interFrameDelayVariationBackwardAvg() != null) { + result = result.put("interFrameDelayVariationBackwardAvg", + dmStat.interFrameDelayVariationBackwardAvg().toString()); + } + if (dmStat.interFrameDelayVariationBackwardBins() != null) { + result = (ObjectNode) result.set("interFrameDelayVariationBackwardBins", + encode(dmStat.interFrameDelayVariationBackwardBins(), context)); + } + if (dmStat.frameDelayRangeTwoWayMax() != null) { + result = result.put("frameDelayRangeTwoWayMax", + dmStat.frameDelayRangeTwoWayMax().toString()); + } + if (dmStat.frameDelayRangeTwoWayAvg() != null) { + result = result.put("frameDelayRangeTwoWayAvg", + dmStat.frameDelayRangeTwoWayAvg().toString()); + } + if (dmStat.frameDelayRangeTwoWayBins() != null) { + result = (ObjectNode) result.set("frameDelayRangeTwoWayBins", + encode(dmStat.frameDelayRangeTwoWayBins(), context)); + } + if (dmStat.frameDelayRangeForwardMax() != null) { + result = result.put("frameDelayRangeForwardMax", + dmStat.frameDelayRangeForwardMax().toString()); + } + if (dmStat.frameDelayRangeForwardAvg() != null) { + result = result.put("frameDelayRangeForwardAvg", + dmStat.frameDelayRangeForwardAvg().toString()); + } + if (dmStat.frameDelayRangeForwardBins() != null) { + result = (ObjectNode) result.set("frameDelayRangeForwardBins", + encode(dmStat.frameDelayRangeForwardBins(), context)); + } + if (dmStat.frameDelayRangeBackwardMax() != null) { + result = result.put("frameDelayRangeBackwardMax", + dmStat.frameDelayRangeBackwardMax().toString()); + } + if (dmStat.frameDelayRangeBackwardAvg() != null) { + result = result.put("frameDelayRangeBackwardAvg", + dmStat.frameDelayRangeBackwardAvg().toString()); + } + if (dmStat.frameDelayRangeBackwardBins() != null) { + result = (ObjectNode) result.set("frameDelayRangeBackwardBins", + encode(dmStat.frameDelayRangeBackwardBins(), context)); + } + + if (dmStat.soamPdusReceived() != null) { + result = result.put(SOAM_PDUS_RECEIVED, dmStat.soamPdusReceived().toString()); + } + + if (dmStat.soamPdusSent() != null) { + result = result.put(SOAM_PDUS_SENT, dmStat.soamPdusSent().toString()); + } + + return result; + } + + private ObjectNode encode(Map bins, CodecContext context) { + checkNotNull(bins, "Bins cannot be null"); + ArrayNode binsResult = context.mapper().createArrayNode(); + bins.keySet().forEach(lwrLimit -> binsResult.add(encode(lwrLimit, bins.get(lwrLimit), context))); + + return (ObjectNode) context.mapper().createObjectNode().set(BINS, binsResult); + } + + private ObjectNode encode(Duration duration, Integer count, CodecContext context) { + return context.mapper().createObjectNode() + .put(LOWER_LIMIT, duration.toString()) + .put(COUNT, count); + } +} diff --git a/apps/cfm/src/main/java/org/onosproject/soam/web/DelayMeasurementStatCurrentCodec.java b/apps/cfm/src/main/java/org/onosproject/soam/web/DelayMeasurementStatCurrentCodec.java new file mode 100644 index 0000000000..a79cd90d82 --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/soam/web/DelayMeasurementStatCurrentCodec.java @@ -0,0 +1,43 @@ +/* + * 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.soam.web; + +import static com.google.common.base.Preconditions.checkNotNull; + +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStatCurrent; + +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * Encode and decode to/from JSON to DelayMeasurementStatCurrent object. + */ +public class DelayMeasurementStatCurrentCodec extends JsonCodec { + + @Override + public ObjectNode encode(DelayMeasurementStatCurrent dmCurrent, CodecContext context) { + checkNotNull(dmCurrent, "DM current cannot be null"); + ObjectNode result = context.mapper().createObjectNode() + .put("startTime", dmCurrent.startTime().toString()) + .put("elapsedTime", dmCurrent.elapsedTime().toString()); + + ObjectNode resultAbstract = new DelayMeasurementStatCodec().encode(dmCurrent, context); + result.setAll(resultAbstract); + + return result; + } +} diff --git a/apps/cfm/src/main/java/org/onosproject/soam/web/DelayMeasurementStatHistoryCodec.java b/apps/cfm/src/main/java/org/onosproject/soam/web/DelayMeasurementStatHistoryCodec.java new file mode 100644 index 0000000000..8901958e22 --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/soam/web/DelayMeasurementStatHistoryCodec.java @@ -0,0 +1,49 @@ +/* + * Copyright 2017-present Open Networking Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.soam.web; + +import static com.google.common.base.Preconditions.checkNotNull; + +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStatHistory; + +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * Encode and decode to/from JSON to DelayMeasurementStatHistory object. + */ +public class DelayMeasurementStatHistoryCodec extends JsonCodec { + + @Override + public ObjectNode encode(DelayMeasurementStatHistory dmHistory, CodecContext context) { + checkNotNull(dmHistory, "DM history cannot be null"); + ObjectNode result = context.mapper().createObjectNode() + .put("historyId", String.valueOf(dmHistory.historyStatsId())) + .put("endTime", dmHistory.endTime().toString()); + ObjectNode resultAbstract = new DelayMeasurementStatCodec().encode(dmHistory, context); + result.setAll(resultAbstract); + return result; + } + + @Override + public ArrayNode encode(Iterable historyEntities, CodecContext context) { + ArrayNode an = context.mapper().createArrayNode(); + historyEntities.forEach(history -> an.add(encode(history, context))); + return an; + } +} diff --git a/apps/cfm/src/main/java/org/onosproject/soam/web/DmCreateCodec.java b/apps/cfm/src/main/java/org/onosproject/soam/web/DmCreateCodec.java new file mode 100644 index 0000000000..8743eb4f07 --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/soam/web/DmCreateCodec.java @@ -0,0 +1,174 @@ +/* + * 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.soam.web; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.onlab.util.Tools.nullIsIllegal; + +import java.time.Duration; + +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep.Priority; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.soam.SoamConfigException; +import org.onosproject.incubator.net.l2monitoring.soam.StartTime; +import org.onosproject.incubator.net.l2monitoring.soam.StopTime; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DefaultDelayMeasurementCreate; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.DmCreateBuilder; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.DmType; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.MeasurementOption; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.Version; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * Encode and decode to/from JSON to DelayMeasurementCreate object. + */ +public class DmCreateCodec extends JsonCodec { + + private static final String VERSION = "version"; + private static final String DM = "dm"; + private static final String DM_CFG_TYPE = "dmCfgType"; + private static final String DMDMM = "DMDMM"; + private static final String REMOTE_MEP_ID = "remoteMepId"; + private static final String PRIORITY = "priority"; + private static final String MEASUREMENTS_ENABLED = "measurementsEnabled"; + private static final String BINS_PER_FD_INTERVAL = "binsPerFdInterval"; + private static final String BINS_PER_IFDV_INTERVAL = "binsPerIfdvInterval"; + private static final String IFDV_SELECTION_OFFSET = "ifdvSelectionOffset"; + private static final String BINS_PER_FDR_INTERVAL = "binsPerFdrInterval"; + private static final String FRAME_SIZE = "frameSize"; + private static final String MESSAGE_PERIOD_MS = "messagePeriodMs"; + private static final String MEASUREMENT_INTERVAL_MINS = "measurementIntervalMins"; + private static final String ALIGN_MEASUREMENT_INTERVALS = "alignMeasurementIntervals"; + private static final String ALIGN_MEASUREMENT_OFFSET_MINS = "alignMeasurementOffsetMins"; + private static final String START_TIME = "startTime"; + private static final String STOP_TIME = "stopTime"; + + @Override + public DelayMeasurementCreate decode(ObjectNode json, + CodecContext context) { + + if (json == null || !json.isObject()) { + return null; + } + + JsonNode dmNode = json.get(DM); + Version version = Version.Y17312011; + if (dmNode.get(VERSION) != null) { + version = Version.valueOf(dmNode.get(VERSION).asText()); + } + DmType dmCfgType = DmType.DMDMM; + if (dmNode.get(DM_CFG_TYPE) != null) { + dmCfgType = DmType.valueOf(dmNode.get(DM_CFG_TYPE).asText(DMDMM)); + } + MepId remoteMepId = MepId.valueOf( + nullIsIllegal(dmNode.get(REMOTE_MEP_ID), REMOTE_MEP_ID + " is required") + .shortValue()); + Priority prio = Priority.valueOf(nullIsIllegal(dmNode.get(PRIORITY), + PRIORITY + " is required in the format 'PRIOn'").asText()); + + try { + DmCreateBuilder builder = DefaultDelayMeasurementCreate + .builder(dmCfgType, version, remoteMepId, prio); + + if (dmNode.get(MEASUREMENTS_ENABLED) != null) { + context.codec(MeasurementOption.class) + .decode((ArrayNode) (dmNode.get(MEASUREMENTS_ENABLED)), context) + .forEach(builder::addToMeasurementsEnabled); + } + + if (dmNode.get(BINS_PER_FD_INTERVAL) != null) { + builder = builder.binsPerFdInterval( + (short) dmNode.get(BINS_PER_FD_INTERVAL).asInt()); + } + if (dmNode.get(BINS_PER_IFDV_INTERVAL) != null) { + builder = builder.binsPerIfdvInterval( + (short) dmNode.get(BINS_PER_IFDV_INTERVAL).asInt()); + } + if (dmNode.get(IFDV_SELECTION_OFFSET) != null) { + builder = builder.ifdvSelectionOffset( + (short) dmNode.get(IFDV_SELECTION_OFFSET).asInt()); + } + if (dmNode.get(BINS_PER_FDR_INTERVAL) != null) { + builder = builder.binsPerFdrInterval( + (short) dmNode.get(BINS_PER_FDR_INTERVAL).asInt()); + } + if (dmNode.get(FRAME_SIZE) != null) { + builder = (DmCreateBuilder) builder.frameSize( + (short) dmNode.get(FRAME_SIZE).asInt()); + } + if (dmNode.get(MESSAGE_PERIOD_MS) != null) { + builder = (DmCreateBuilder) builder.messagePeriod(Duration.ofMillis( + dmNode.get(MESSAGE_PERIOD_MS).asInt())); + } + if (dmNode.get(MEASUREMENT_INTERVAL_MINS) != null) { + builder = (DmCreateBuilder) builder.measurementInterval( + Duration.ofMinutes( + dmNode.get(MEASUREMENT_INTERVAL_MINS).asInt())); + } + if (dmNode.get(ALIGN_MEASUREMENT_INTERVALS) != null) { + builder = (DmCreateBuilder) builder.alignMeasurementIntervals( + dmNode.get(ALIGN_MEASUREMENT_INTERVALS).asBoolean()); + } + if (dmNode.get(ALIGN_MEASUREMENT_OFFSET_MINS) != null) { + builder = (DmCreateBuilder) builder.alignMeasurementOffset(Duration.ofMinutes( + dmNode.get(ALIGN_MEASUREMENT_OFFSET_MINS).asInt())); + } + if (dmNode.get(START_TIME) != null) { + builder = (DmCreateBuilder) builder.startTime(context.codec(StartTime.class) + .decode((ObjectNode) dmNode.get(START_TIME), context)); + } + if (dmNode.get(STOP_TIME) != null) { + builder = (DmCreateBuilder) builder.stopTime(context.codec(StopTime.class) + .decode((ObjectNode) dmNode.get(STOP_TIME), context)); + } + + return builder.build(); + } catch (SoamConfigException e) { + throw new IllegalArgumentException(e); + } + } + + @Override + public ObjectNode encode(DelayMeasurementCreate dm, CodecContext context) { + checkNotNull(dm, "DM cannot be null"); + ObjectNode result = context.mapper().createObjectNode() + .put(DM_CFG_TYPE, dm.dmCfgType().name()) + .put(VERSION, dm.version().name()) + .put(REMOTE_MEP_ID, dm.remoteMepId().id()) + .put(PRIORITY, dm.priority().name()); + + if (dm.measurementsEnabled() != null) { + result.set(MEASUREMENTS_ENABLED, new DmMeasurementOptionCodec() + .encode(dm.measurementsEnabled(), context)); + } + + if (dm.messagePeriod() != null) { + result.put(MESSAGE_PERIOD_MS, dm.messagePeriod().toMillis()); + } + if (dm.frameSize() != null) { + result.put(FRAME_SIZE, dm.frameSize()); + } + + + return result; + } +} diff --git a/apps/cfm/src/main/java/org/onosproject/soam/web/DmEntryCodec.java b/apps/cfm/src/main/java/org/onosproject/soam/web/DmEntryCodec.java new file mode 100644 index 0000000000..ce851d6fd3 --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/soam/web/DmEntryCodec.java @@ -0,0 +1,104 @@ +/* + * 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.soam.web; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.util.Iterator; +import java.util.Map.Entry; + +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementEntry; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * Encode and decode to/from JSON to DelayMeasurementEntry object. + */ +public class DmEntryCodec extends JsonCodec { + + private static final String DM_ID = "dmId"; + private static final String SESSION_STATUS = "sessionStatus"; + private static final String FRAME_DELAY_TWO_WAY = "frameDelayTwoWay"; + private static final String FRAME_DELAY_FORWARD = "frameDelayForward"; + private static final String FRAME_DELAY_BACKWARD = "frameDelayBackward"; + private static final String INTER_FRAME_DELAY_VARIATION_TWO_WAY = "interFrameDelayVariationTwoWay"; + private static final String INTER_FRAME_DELAY_VARIATION_FORWARD = "interFrameDelayVariationForward"; + private static final String INTER_FRAME_DELAY_VARIATION_BACKWARD = "interFrameDelayVariationBackward"; + private static final String CURRENT = "current"; + private static final String HISTORIC = "historic"; + + @Override + public ObjectNode encode(DelayMeasurementEntry dm, CodecContext context) { + checkNotNull(dm, "DM cannot be null"); + ObjectNode result = context.mapper().createObjectNode() + .put(DM_ID, dm.dmId().toString()); + + if (dm.sessionStatus() != null) { + result.put(SESSION_STATUS, dm.sessionStatus().name()); + } + if (dm.frameDelayTwoWay() != null) { + result.put(FRAME_DELAY_TWO_WAY, dm.frameDelayTwoWay().toString()); + } + if (dm.frameDelayForward() != null) { + result.put(FRAME_DELAY_FORWARD, dm.frameDelayForward().toString()); + } + if (dm.frameDelayBackward() != null) { + result.put(FRAME_DELAY_BACKWARD, dm.frameDelayBackward().toString()); + } + if (dm.interFrameDelayVariationTwoWay() != null) { + result.put(INTER_FRAME_DELAY_VARIATION_TWO_WAY, + dm.interFrameDelayVariationTwoWay().toString()); + } + if (dm.interFrameDelayVariationForward() != null) { + result.put(INTER_FRAME_DELAY_VARIATION_FORWARD, + dm.interFrameDelayVariationForward().toString()); + } + if (dm.interFrameDelayVariationBackward() != null) { + result.put(INTER_FRAME_DELAY_VARIATION_BACKWARD, + dm.interFrameDelayVariationBackward().toString()); + } + + ObjectNode dmAttrs = new DmCreateCodec().encode(dm, context); + Iterator> elements = dmAttrs.fields(); + while (elements.hasNext()) { + Entry element = elements.next(); + result.set(element.getKey(), element.getValue()); + } + + if (dm.currentResult() != null) { + result.set(CURRENT, new DelayMeasurementStatCurrentCodec() + .encode(dm.currentResult(), context)); + } + + if (dm.historicalResults() != null) { + result.set(HISTORIC, new DelayMeasurementStatHistoryCodec() + .encode(dm.historicalResults(), context)); + } + + return result; + } + + @Override + public ArrayNode encode(Iterable dmEntities, CodecContext context) { + ArrayNode an = context.mapper().createArrayNode(); + dmEntities.forEach(dm -> an.add(encode(dm, context))); + return an; + } +} diff --git a/apps/cfm/src/main/java/org/onosproject/soam/web/DmMeasurementOptionCodec.java b/apps/cfm/src/main/java/org/onosproject/soam/web/DmMeasurementOptionCodec.java new file mode 100644 index 0000000000..8c8a5a02df --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/soam/web/DmMeasurementOptionCodec.java @@ -0,0 +1,52 @@ +/* + * Copyright 2017-present Open Networking Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.soam.web; + +import java.util.ArrayList; +import java.util.List; + +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.MeasurementOption; + +import com.fasterxml.jackson.databind.node.ArrayNode; + +/** + * Encode and decode to/from JSON to MeasurementOption object. + */ +public class DmMeasurementOptionCodec extends JsonCodec { + + @Override + public ArrayNode encode(Iterable entities, + CodecContext context) { + ArrayNode an = context.mapper().createArrayNode(); + entities.forEach(node -> an.add(node.name())); + + return an; + } + + @Override + public List decode(ArrayNode json, + CodecContext context) { + if (json == null) { + return null; + } + List moList = new ArrayList<>(); + json.forEach(node -> moList.add(MeasurementOption.valueOf(node.asText()))); + return moList; + } + +} diff --git a/apps/cfm/src/main/java/org/onosproject/soam/web/LmCounterOptionCodec.java b/apps/cfm/src/main/java/org/onosproject/soam/web/LmCounterOptionCodec.java new file mode 100644 index 0000000000..9e3e40e186 --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/soam/web/LmCounterOptionCodec.java @@ -0,0 +1,51 @@ +/* + * Copyright 2017-present Open Networking Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.soam.web; + +import com.fasterxml.jackson.databind.node.ArrayNode; +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementCreate.CounterOption; + +import java.util.ArrayList; +import java.util.List; + +/** + * Encode and decode to/from JSON to CounterOption object. + */ +public class LmCounterOptionCodec extends JsonCodec { + + @Override + public ArrayNode encode(Iterable entities, + CodecContext context) { + ArrayNode an = context.mapper().createArrayNode(); + entities.forEach(node -> an.add(node.name())); + + return an; + } + + @Override + public List decode(ArrayNode json, + CodecContext context) { + if (json == null) { + return null; + } + List moList = new ArrayList<>(); + json.forEach(node -> moList.add(CounterOption.valueOf(node.asText()))); + return moList; + } + +} diff --git a/apps/cfm/src/main/java/org/onosproject/soam/web/LmCreateCodec.java b/apps/cfm/src/main/java/org/onosproject/soam/web/LmCreateCodec.java new file mode 100644 index 0000000000..e88fb2f635 --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/soam/web/LmCreateCodec.java @@ -0,0 +1,196 @@ +/* + * 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.soam.web; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep.Priority; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.soam.MilliPct; +import org.onosproject.incubator.net.l2monitoring.soam.SoamConfigException; +import org.onosproject.incubator.net.l2monitoring.soam.StartTime; +import org.onosproject.incubator.net.l2monitoring.soam.StopTime; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.Version; +import org.onosproject.incubator.net.l2monitoring.soam.loss.DefaultLmCreate; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementCreate; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementThreshold; + +import java.time.Duration; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.onlab.util.Tools.nullIsIllegal; +import static org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementCreate.CounterOption; +import static org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementCreate.LmType; +import static org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementCreate.LmCreateBuilder; + +/** + * Encode and decode to/from JSON to LossMeasurementCreate object. + */ +public class LmCreateCodec extends JsonCodec { + + public static final String LM = "lm"; + public static final String VERSION = "version"; + public static final String LM_CFG_TYPE = "lmCfgType"; + public static final String LMLMM = "LMLMM"; + public static final String REMOTE_MEP_ID = "remoteMepId"; + public static final String PRIORITY = "priority"; + public static final String COUNTERS_ENABLED = "countersEnabled"; + public static final String THRESHOLDS = "thresholds"; + public static final String AVAILABILITY_MEASUREMENT_INTERVAL_MINS = + "availabilityMeasurementIntervalMins"; + public static final String AVAILABILITY_NUMBER_CONSECUTIVE_FLR_MEASUREMENTS = + "availabilityNumberConsecutiveFlrMeasurements"; + public static final String AVAILABILITY_FLR_THRESHOLD_PCT = + "availabilityFlrThresholdPct"; + public static final String AVAILABILITY_NUMBER_CONSECUTIVE_INTERVALS = + "availabilityNumberConsecutiveIntervals"; + public static final String AVAILABILITY_NUMBER_CONSECUTIVE_HIGH_FLR = + "availabilityNumberConsecutiveHighFlr"; + public static final String FRAME_SIZE = "frameSize"; + public static final String MESSAGE_PERIOD_MS = "messagePeriodMs"; + public static final String MEASUREMENT_INTERVAL_MINS = + "measurementIntervalMins"; + public static final String ALIGN_MEASUREMENT_INTERVALS = + "alignMeasurementIntervals"; + public static final String ALIGN_MEASUREMENT_OFFSET_MINS = + "alignMeasurementOffsetMins"; + public static final String START_TIME = "startTime"; + public static final String STOP_TIME = "stopTime"; + + @Override + public LossMeasurementCreate decode(ObjectNode json, + CodecContext context) { + + if (json == null || !json.isObject()) { + return null; + } + + JsonNode lmNode = json.get(LM); + Version version = Version.Y17312011; + if (lmNode.get(VERSION) != null) { + version = Version.valueOf(lmNode.get(VERSION).asText()); + } + LmType lmCfgType = LmType.LMLMM; + if (lmNode.get(LM_CFG_TYPE) != null) { + lmCfgType = LmType.valueOf(lmNode.get(LM_CFG_TYPE).asText(LMLMM)); + } + MepId remoteMepId = MepId.valueOf( + nullIsIllegal(lmNode.get(REMOTE_MEP_ID), REMOTE_MEP_ID + " is required") + .shortValue()); + Priority prio = Priority.valueOf(nullIsIllegal(lmNode.get(PRIORITY), + PRIORITY + " is required in the format 'PRIOn'").asText()); + + try { + LmCreateBuilder builder = DefaultLmCreate + .builder(version, remoteMepId, prio, lmCfgType); + + if (lmNode.get(COUNTERS_ENABLED) != null) { + context.codec(CounterOption.class) + .decode((ArrayNode) (lmNode.get(COUNTERS_ENABLED)), context) + .forEach(builder::addToCountersEnabled); + } + + if (lmNode.get(THRESHOLDS) != null) { + context.codec(LossMeasurementThreshold.class) + .decode((ArrayNode) (lmNode.get(THRESHOLDS)), context) + .forEach(builder::addToLossMeasurementThreshold); + } + + if (lmNode.get(AVAILABILITY_MEASUREMENT_INTERVAL_MINS) != null) { + builder = builder.availabilityMeasurementInterval( + Duration.ofMinutes(lmNode.get(AVAILABILITY_MEASUREMENT_INTERVAL_MINS).asInt())); + } + if (lmNode.get(AVAILABILITY_NUMBER_CONSECUTIVE_FLR_MEASUREMENTS) != null) { + builder = builder.availabilityNumberConsecutiveFlrMeasurements( + lmNode.get(AVAILABILITY_NUMBER_CONSECUTIVE_FLR_MEASUREMENTS).asInt()); + } + if (lmNode.get(AVAILABILITY_FLR_THRESHOLD_PCT) != null) { + builder = builder.availabilityFlrThreshold( + MilliPct.ofPercent((float) lmNode.get(AVAILABILITY_FLR_THRESHOLD_PCT).asDouble())); + } + if (lmNode.get(AVAILABILITY_NUMBER_CONSECUTIVE_INTERVALS) != null) { + builder = builder.availabilityNumberConsecutiveIntervals( + (short) lmNode.get(AVAILABILITY_NUMBER_CONSECUTIVE_INTERVALS).asInt()); + } + if (lmNode.get(AVAILABILITY_NUMBER_CONSECUTIVE_HIGH_FLR) != null) { + builder = builder.availabilityNumberConsecutiveHighFlr( + (short) lmNode.get(AVAILABILITY_NUMBER_CONSECUTIVE_HIGH_FLR).asInt()); + } + if (lmNode.get(FRAME_SIZE) != null) { + builder = (LmCreateBuilder) builder.frameSize( + (short) lmNode.get(FRAME_SIZE).asInt()); + } + if (lmNode.get(MESSAGE_PERIOD_MS) != null) { + builder = (LmCreateBuilder) builder.messagePeriod(Duration.ofMillis( + lmNode.get(MESSAGE_PERIOD_MS).asInt())); + } + if (lmNode.get(MEASUREMENT_INTERVAL_MINS) != null) { + builder = (LmCreateBuilder) builder.measurementInterval( + Duration.ofMinutes( + lmNode.get(MEASUREMENT_INTERVAL_MINS).asInt())); + } + if (lmNode.get(ALIGN_MEASUREMENT_INTERVALS) != null) { + builder = (LmCreateBuilder) builder.alignMeasurementIntervals( + lmNode.get(ALIGN_MEASUREMENT_INTERVALS).asBoolean()); + } + if (lmNode.get(ALIGN_MEASUREMENT_OFFSET_MINS) != null) { + builder = (LmCreateBuilder) builder.alignMeasurementOffset(Duration.ofMinutes( + lmNode.get(ALIGN_MEASUREMENT_OFFSET_MINS).asInt())); + } + if (lmNode.get(START_TIME) != null) { + builder = (LmCreateBuilder) builder.startTime(context.codec(StartTime.class) + .decode((ObjectNode) lmNode.get(START_TIME), context)); + } + if (lmNode.get(STOP_TIME) != null) { + builder = (LmCreateBuilder) builder.stopTime(context.codec(StopTime.class) + .decode((ObjectNode) lmNode.get(STOP_TIME), context)); + } + + + return builder.build(); + } catch (SoamConfigException e) { + throw new IllegalArgumentException(e); + } + } + + @Override + public ObjectNode encode(LossMeasurementCreate lm, CodecContext context) { + checkNotNull(lm, "LM cannot be null"); + ObjectNode result = context.mapper().createObjectNode() + .put(LM_CFG_TYPE, lm.lmCfgType().name()) + .put(VERSION, lm.version().name()) + .put(REMOTE_MEP_ID, lm.remoteMepId().id()) + .put(PRIORITY, lm.priority().name()); + + if (lm.countersEnabled() != null) { + result.set(COUNTERS_ENABLED, new LmCounterOptionCodec() + .encode(lm.countersEnabled(), context)); + } + + if (lm.messagePeriod() != null) { + result.put(MESSAGE_PERIOD_MS, lm.messagePeriod().toMillis()); + } + if (lm.frameSize() != null) { + result.put(FRAME_SIZE, lm.frameSize()); + } + + + return result; + } +} diff --git a/apps/cfm/src/main/java/org/onosproject/soam/web/LmEntryCodec.java b/apps/cfm/src/main/java/org/onosproject/soam/web/LmEntryCodec.java new file mode 100644 index 0000000000..251bcd9571 --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/soam/web/LmEntryCodec.java @@ -0,0 +1,100 @@ +/* + * 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.soam.web; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementEntry; + +import java.util.Iterator; +import java.util.Map.Entry; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Encode and decode to/from JSON to LossMeasurementEntry object. + */ +public class LmEntryCodec extends JsonCodec { + + @Override + public ObjectNode encode(LossMeasurementEntry lm, CodecContext context) { + checkNotNull(lm, "LM cannot be null"); + ObjectNode result = context.mapper().createObjectNode() + .put("lmId", lm.lmId().toString()); + + if (lm.measuredForwardFlr() != null) { + result.put("measuredForwardFlr", lm.measuredForwardFlr().percentValue()); + } + if (lm.measuredBackwardFlr() != null) { + result.put("measuredBackwardFlr", lm.measuredBackwardFlr().percentValue()); + } + if (lm.measuredAvailabilityForwardStatus() != null) { + result.put("measuredAvailabilityForwardStatus", + lm.measuredAvailabilityForwardStatus().name()); + } + if (lm.measuredAvailabilityBackwardStatus() != null) { + result.put("measuredAvailabilityBackwardStatus", + lm.measuredAvailabilityBackwardStatus().name()); + } + if (lm.measuredForwardLastTransitionTime() != null) { + result.put("measuredForwardLastTransitionTime", + lm.measuredForwardLastTransitionTime().toString()); + } + if (lm.measuredBackwardLastTransitionTime() != null) { + result.put("measuredBackwardLastTransitionTime", + lm.measuredBackwardLastTransitionTime().toString()); + } + + ObjectNode lmAttrs = new LmCreateCodec().encode(lm, context); + Iterator> elements = lmAttrs.fields(); + while (elements.hasNext()) { + Entry element = elements.next(); + result.set(element.getKey(), element.getValue()); + } + + if (lm.measurementCurrent() != null) { + result.set("measurementCurrent", new LossMeasurementStatCurrentCodec() + .encode(lm.measurementCurrent(), context)); + } + + if (lm.measurementHistories() != null) { + result.set("measurementHistories", new LossMeasurementStatHistoryCodec() + .encode(lm.measurementHistories(), context)); + } + + if (lm.availabilityCurrent() != null) { + result.set("availabilityCurrent", new LossAvailabilityStatCurrentCodec() + .encode(lm.availabilityCurrent(), context)); + } + + if (lm.availabilityHistories() != null) { + result.set("availabilityHistories", new LossAvailabilityStatHistoryCodec() + .encode(lm.availabilityHistories(), context)); + } + + return result; + } + + @Override + public ArrayNode encode(Iterable lmEntities, CodecContext context) { + ArrayNode an = context.mapper().createArrayNode(); + lmEntities.forEach(dm -> an.add(encode(dm, context))); + return an; + } +} diff --git a/apps/cfm/src/main/java/org/onosproject/soam/web/LmThresholdOptionCodec.java b/apps/cfm/src/main/java/org/onosproject/soam/web/LmThresholdOptionCodec.java new file mode 100644 index 0000000000..98c0b621eb --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/soam/web/LmThresholdOptionCodec.java @@ -0,0 +1,51 @@ +/* + * Copyright 2017-present Open Networking Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.soam.web; + +import com.fasterxml.jackson.databind.node.ArrayNode; +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementThreshold.ThresholdOption; + +import java.util.ArrayList; +import java.util.List; + +/** + * Encode and decode to/from JSON to ThresholdOption object. + */ +public class LmThresholdOptionCodec extends JsonCodec { + + @Override + public ArrayNode encode(Iterable entities, + CodecContext context) { + ArrayNode an = context.mapper().createArrayNode(); + entities.forEach(node -> an.add(node.name())); + + return an; + } + + @Override + public List decode(ArrayNode json, + CodecContext context) { + if (json == null) { + return null; + } + List moList = new ArrayList<>(); + json.forEach(node -> moList.add(ThresholdOption.valueOf(node.asText()))); + return moList; + } + +} diff --git a/apps/cfm/src/main/java/org/onosproject/soam/web/LossAvailabilityStatCodec.java b/apps/cfm/src/main/java/org/onosproject/soam/web/LossAvailabilityStatCodec.java new file mode 100644 index 0000000000..3124976050 --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/soam/web/LossAvailabilityStatCodec.java @@ -0,0 +1,96 @@ +/* + * 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.soam.web; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossAvailabilityStat; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Encode and decode to/from JSON to LossAvailabilityStat object. + */ +public class LossAvailabilityStatCodec extends JsonCodec { + + @Override + public ObjectNode encode(LossAvailabilityStat laStat, CodecContext context) { + checkNotNull(laStat, "LA stat cannot be null"); + ObjectNode result = context.mapper().createObjectNode() + .put("elapsedTime", laStat.elapsedTime().toString()) + .put("suspectStatus", String.valueOf(laStat.suspectStatus())); + + if (laStat.forwardHighLoss() != null) { + result = result.put("forwardHighLoss", + laStat.forwardHighLoss().toString()); + } + if (laStat.backwardHighLoss() != null) { + result = result.put("backwardHighLoss", + laStat.backwardHighLoss().toString()); + } + if (laStat.forwardConsecutiveHighLoss() != null) { + result = result.put("forwardConsecutiveHighLoss", + laStat.forwardConsecutiveHighLoss().toString()); + } + if (laStat.backwardConsecutiveHighLoss() != null) { + result = result.put("backwardConsecutiveHighLoss", + laStat.backwardConsecutiveHighLoss().toString()); + } + if (laStat.forwardAvailable() != null) { + result = result.put("forwardAvailable", + laStat.forwardAvailable().toString()); + } + if (laStat.backwardAvailable() != null) { + result = result.put("backwardAvailable", + laStat.backwardAvailable().toString()); + } + if (laStat.forwardUnavailable() != null) { + result = result.put("forwardUnavailable", + laStat.forwardUnavailable().toString()); + } + if (laStat.backwardUnavailable() != null) { + result = result.put("backwardUnavailable", + laStat.backwardUnavailable().toString()); + } + if (laStat.backwardMinFrameLossRatio() != null) { + result = result.put("backwardMinFrameLossRatio", + laStat.backwardMinFrameLossRatio().toString()); + } + if (laStat.backwardMaxFrameLossRatio() != null) { + result = result.put("backwardMaxFrameLossRatio", + laStat.backwardMaxFrameLossRatio().toString()); + } + if (laStat.backwardAverageFrameLossRatio() != null) { + result = result.put("backwardAverageFrameLossRatio", + laStat.backwardAverageFrameLossRatio().toString()); + } + if (laStat.forwardMinFrameLossRatio() != null) { + result = result.put("forwardMinFrameLossRatio", + laStat.forwardMinFrameLossRatio().toString()); + } + if (laStat.forwardMaxFrameLossRatio() != null) { + result = result.put("forwardMaxFrameLossRatio", + laStat.forwardMaxFrameLossRatio().toString()); + } + if (laStat.forwardAverageFrameLossRatio() != null) { + result = result.put("forwardAverageFrameLossRatio", + laStat.forwardAverageFrameLossRatio().toString()); + } + + return result; + } +} diff --git a/apps/cfm/src/main/java/org/onosproject/soam/web/LossAvailabilityStatCurrentCodec.java b/apps/cfm/src/main/java/org/onosproject/soam/web/LossAvailabilityStatCurrentCodec.java new file mode 100644 index 0000000000..a6dc5defaa --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/soam/web/LossAvailabilityStatCurrentCodec.java @@ -0,0 +1,42 @@ +/* + * 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.soam.web; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossAvailabilityStatCurrent; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Encode and decode to/from JSON to LossAvailabilityStatCurrent object. + */ +public class LossAvailabilityStatCurrentCodec extends JsonCodec { + + @Override + public ObjectNode encode(LossAvailabilityStatCurrent laCurrent, CodecContext context) { + checkNotNull(laCurrent, "LA current cannot be null"); + ObjectNode result = context.mapper().createObjectNode() + .put("startTime", laCurrent.startTime().toString()) + .put("elapsedTime", laCurrent.elapsedTime().toString()); + + ObjectNode resultAbstract = new LossAvailabilityStatCodec().encode(laCurrent, context); + result.setAll(resultAbstract); + + return result; + } +} diff --git a/apps/cfm/src/main/java/org/onosproject/soam/web/LossAvailabilityStatHistoryCodec.java b/apps/cfm/src/main/java/org/onosproject/soam/web/LossAvailabilityStatHistoryCodec.java new file mode 100644 index 0000000000..54e5160580 --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/soam/web/LossAvailabilityStatHistoryCodec.java @@ -0,0 +1,48 @@ +/* + * 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.soam.web; + +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossAvailabilityStatHistory; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Encode and decode to/from JSON to LossAvailabilityStatHistory object. + */ +public class LossAvailabilityStatHistoryCodec extends JsonCodec { + + @Override + public ObjectNode encode(LossAvailabilityStatHistory laHistory, CodecContext context) { + checkNotNull(laHistory, "LA history cannot be null"); + ObjectNode result = context.mapper().createObjectNode() + .put("historyId", String.valueOf(laHistory.historyStatsId())) + .put("endTime", laHistory.endTime().toString()); + ObjectNode resultAbstract = new LossAvailabilityStatCodec().encode(laHistory, context); + result.setAll(resultAbstract); + return result; + } + + @Override + public ArrayNode encode(Iterable historyEntities, CodecContext context) { + ArrayNode an = context.mapper().createArrayNode(); + historyEntities.forEach(history -> an.add(encode(history, context))); + return an; + } +} diff --git a/apps/cfm/src/main/java/org/onosproject/soam/web/LossMeasurementStatCodec.java b/apps/cfm/src/main/java/org/onosproject/soam/web/LossMeasurementStatCodec.java new file mode 100644 index 0000000000..eac21e65b7 --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/soam/web/LossMeasurementStatCodec.java @@ -0,0 +1,88 @@ +/* + * 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.soam.web; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementStat; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Encode and decode to/from JSON to LossMeasurementStat object. + */ +public class LossMeasurementStatCodec extends JsonCodec { + + @Override + public ObjectNode encode(LossMeasurementStat lmStat, CodecContext context) { + checkNotNull(lmStat, "LM stat cannot be null"); + ObjectNode result = context.mapper().createObjectNode() + .put("elapsedTime", lmStat.elapsedTime().toString()) + .put("suspectStatus", String.valueOf(lmStat.suspectStatus())); + + if (lmStat.forwardTransmittedFrames() != null) { + result = result.put("forwardTransmittedFrames", + lmStat.forwardTransmittedFrames().toString()); + } + if (lmStat.forwardReceivedFrames() != null) { + result = result.put("forwardReceivedFrames", + lmStat.forwardReceivedFrames().toString()); + } + if (lmStat.forwardMinFrameLossRatio() != null) { + result = result.put("forwardMinFrameLossRatio", + lmStat.forwardMinFrameLossRatio().toString()); + } + if (lmStat.forwardMaxFrameLossRatio() != null) { + result = result.put("forwardMaxFrameLossRatio", + lmStat.forwardMaxFrameLossRatio().toString()); + } + if (lmStat.forwardAverageFrameLossRatio() != null) { + result = result.put("forwardAverageFrameLossRatio", + lmStat.forwardAverageFrameLossRatio().toString()); + } + if (lmStat.backwardTransmittedFrames() != null) { + result = result.put("backwardTransmittedFrames", + lmStat.backwardTransmittedFrames().toString()); + } + if (lmStat.backwardReceivedFrames() != null) { + result = result.put("backwardReceivedFrames", + lmStat.backwardReceivedFrames().toString()); + } + if (lmStat.backwardMinFrameLossRatio() != null) { + result = result.put("backwardMinFrameLossRatio", + lmStat.backwardMinFrameLossRatio().toString()); + } + if (lmStat.backwardMaxFrameLossRatio() != null) { + result = result.put("backwardMaxFrameLossRatio", + lmStat.backwardMaxFrameLossRatio().toString()); + } + if (lmStat.backwardAverageFrameLossRatio() != null) { + result = result.put("backwardAverageFrameLossRatio", + lmStat.backwardAverageFrameLossRatio().toString()); + } + if (lmStat.soamPdusSent() != null) { + result = result.put("soamPdusSent", + lmStat.soamPdusSent().toString()); + } + if (lmStat.soamPdusReceived() != null) { + result.put("soamPdusReceived", + lmStat.soamPdusReceived().toString()); + } + + return result; + } +} diff --git a/apps/cfm/src/main/java/org/onosproject/soam/web/LossMeasurementStatCurrentCodec.java b/apps/cfm/src/main/java/org/onosproject/soam/web/LossMeasurementStatCurrentCodec.java new file mode 100644 index 0000000000..d525493cb5 --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/soam/web/LossMeasurementStatCurrentCodec.java @@ -0,0 +1,42 @@ +/* + * 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.soam.web; + +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementStatCurrent; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Encode and decode to/from JSON to LossMeasurementStatCurrent object. + */ +public class LossMeasurementStatCurrentCodec extends JsonCodec { + + @Override + public ObjectNode encode(LossMeasurementStatCurrent lmCurrent, CodecContext context) { + checkNotNull(lmCurrent, "LM current cannot be null"); + ObjectNode result = context.mapper().createObjectNode() + .put("startTime", lmCurrent.startTime().toString()) + .put("elapsedTime", lmCurrent.elapsedTime().toString()); + + ObjectNode resultAbstract = new LossMeasurementStatCodec().encode(lmCurrent, context); + result.setAll(resultAbstract); + + return result; + } +} diff --git a/apps/cfm/src/main/java/org/onosproject/soam/web/LossMeasurementStatHistoryCodec.java b/apps/cfm/src/main/java/org/onosproject/soam/web/LossMeasurementStatHistoryCodec.java new file mode 100644 index 0000000000..e4ec28256a --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/soam/web/LossMeasurementStatHistoryCodec.java @@ -0,0 +1,48 @@ +/* + * 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.soam.web; + +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementStatHistory; + +import static com.google.common.base.Preconditions.checkNotNull; + +/** + * Encode and decode to/from JSON to LossMeasurementStatHistory object. + */ +public class LossMeasurementStatHistoryCodec extends JsonCodec { + + @Override + public ObjectNode encode(LossMeasurementStatHistory lmHistory, CodecContext context) { + checkNotNull(lmHistory, "LM history cannot be null"); + ObjectNode result = context.mapper().createObjectNode() + .put("historyId", String.valueOf(lmHistory.historyStatsId())) + .put("endTime", lmHistory.endTime().toString()); + ObjectNode resultAbstract = new LossMeasurementStatCodec().encode(lmHistory, context); + result.setAll(resultAbstract); + return result; + } + + @Override + public ArrayNode encode(Iterable historyEntities, CodecContext context) { + ArrayNode an = context.mapper().createArrayNode(); + historyEntities.forEach(history -> an.add(encode(history, context))); + return an; + } +} diff --git a/apps/cfm/src/main/java/org/onosproject/soam/web/LossMeasurementThresholdCodec.java b/apps/cfm/src/main/java/org/onosproject/soam/web/LossMeasurementThresholdCodec.java new file mode 100644 index 0000000000..3a17f9466b --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/soam/web/LossMeasurementThresholdCodec.java @@ -0,0 +1,192 @@ +/* + * 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.soam.web; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.incubator.net.l2monitoring.soam.MilliPct; +import org.onosproject.incubator.net.l2monitoring.soam.SoamId; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementThreshold; + +import java.util.ArrayList; +import java.util.List; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.onlab.util.Tools.nullIsIllegal; +import static org.onosproject.incubator.net.l2monitoring.soam.loss.DefaultLmThreshold.*; + +/** + * Encode and decode to/from JSON to LossMeasurementThreshold object. + */ +public class LossMeasurementThresholdCodec extends JsonCodec { + static final String MEASUREDFLRFORWARD = "measuredFlrForward"; + static final String MAXFLRFORWARD = "maxFlrForward"; + static final String AVERAGEFLRFORWARD = "averageFlrForward"; + static final String MEASUREDFLRBACKWARD = "measuredFlrBackward"; + static final String MAXFLRBACKWARD = "maxFlrBackward"; + static final String AVERAGEFLRBACKWARD = "averageFlrBackward"; + static final String FORWARDHIGHLOSS = "forwardHighLoss"; + static final String FORWARDCONSECUTIVEHIGHLOSS = "forwardConsecutiveHighLoss"; + static final String BACKWARDHIGHLOSS = "backwardHighLoss"; + static final String BACKWARDCONSECUTIVEHIGHLOSS = "backwardConsecutiveHighLoss"; + static final String FORWARDUNAVAILABLECOUNT = "forwardUnavailableCount"; + static final String FORWARDAVAILABLERATIO = "forwardAvailableRatio"; + static final String BACKWARDUNAVAILABLECOUNT = "backwardUnavailableCount"; + static final String BACKWARDAVAILABLERATIO = "backwardAvailableRatio"; + static final String THRESHOLDOPTIONS = "thresholdOptions"; + + @Override + public ObjectNode encode(LossMeasurementThreshold lmt, CodecContext context) { + checkNotNull(lmt, "LM thresholds cannot be null"); + ObjectNode result = context.mapper().createObjectNode() + .put("id", lmt.thresholdId().value()); + + if (lmt.thresholds() != null) { + result.set(THRESHOLDOPTIONS, new LmThresholdOptionCodec() + .encode(lmt.thresholds(), context)); + } + + if (lmt.measuredFlrForward() != null) { + result.put(MEASUREDFLRFORWARD, lmt.measuredFlrForward().percentValue()); + } + if (lmt.maxFlrForward() != null) { + result.put(MAXFLRFORWARD, lmt.maxFlrForward().percentValue()); + } + if (lmt.averageFlrForward() != null) { + result.put(AVERAGEFLRFORWARD, lmt.averageFlrForward().percentValue()); + } + if (lmt.measuredFlrBackward() != null) { + result.put(MEASUREDFLRBACKWARD, lmt.measuredFlrBackward().percentValue()); + } + if (lmt.maxFlrBackward() != null) { + result.put(MAXFLRBACKWARD, lmt.maxFlrBackward().percentValue()); + } + if (lmt.averageFlrBackward() != null) { + result.put(AVERAGEFLRBACKWARD, lmt.averageFlrBackward().percentValue()); + } + if (lmt.forwardHighLoss() != null) { + result.put(FORWARDHIGHLOSS, lmt.forwardHighLoss().longValue()); + } + if (lmt.forwardConsecutiveHighLoss() != null) { + result.put(FORWARDCONSECUTIVEHIGHLOSS, lmt.measuredFlrForward().longValue()); + } + if (lmt.backwardHighLoss() != null) { + result.put(BACKWARDHIGHLOSS, lmt.backwardHighLoss().longValue()); + } + if (lmt.backwardConsecutiveHighLoss() != null) { + result.put(BACKWARDCONSECUTIVEHIGHLOSS, lmt.backwardConsecutiveHighLoss().longValue()); + } + if (lmt.forwardUnavailableCount() != null) { + result.put(FORWARDUNAVAILABLECOUNT, lmt.forwardUnavailableCount().longValue()); + } + if (lmt.forwardAvailableRatio() != null) { + result.put(FORWARDAVAILABLERATIO, lmt.forwardAvailableRatio().percentValue()); + } + if (lmt.backwardUnavailableCount() != null) { + result.put(BACKWARDUNAVAILABLECOUNT, lmt.backwardUnavailableCount().longValue()); + } + if (lmt.backwardAvailableRatio() != null) { + result.put(BACKWARDAVAILABLERATIO, lmt.backwardAvailableRatio().percentValue()); + } + + return result; + } + + @Override + public List decode(ArrayNode json, CodecContext context) { + if (json == null) { + return null; + } + List thrList = new ArrayList<>(); + json.forEach(node -> thrList.add(decode((ObjectNode) node, context))); + return thrList; + } + + @Override + public LossMeasurementThreshold decode(ObjectNode json, CodecContext context) { + if (json == null || !json.isObject()) { + return null; + } + + JsonNode thrNode = json.get("threshold"); + + SoamId thresholdId = SoamId.valueOf(nullIsIllegal(thrNode.get("id"), + "thresholdId must not be null").asInt()); + LossMeasurementThreshold.LmThresholdBuilder builder = builder(thresholdId); + + if (thrNode.get("thresholds") != null) { + context.codec(ThresholdOption.class) + .decode((ArrayNode) (thrNode.get("thresholds")), context) + .forEach(builder::addToThreshold); + } + + if (thrNode.get(MEASUREDFLRFORWARD) != null) { + builder.measuredFlrForward(MilliPct.ofPercent( + (float) thrNode.get(MEASUREDFLRFORWARD).asDouble())); + } + if (thrNode.get(MAXFLRFORWARD) != null) { + builder.maxFlrForward(MilliPct.ofPercent( + (float) thrNode.get(MAXFLRFORWARD).asDouble())); + } + if (thrNode.get(AVERAGEFLRFORWARD) != null) { + builder.averageFlrForward(MilliPct.ofPercent( + (float) thrNode.get(AVERAGEFLRFORWARD).asDouble())); + } + if (thrNode.get(MEASUREDFLRBACKWARD) != null) { + builder.measuredFlrBackward(MilliPct.ofPercent( + (float) thrNode.get(MEASUREDFLRBACKWARD).asDouble())); + } + if (thrNode.get(MAXFLRBACKWARD) != null) { + builder.maxFlrBackward(MilliPct.ofPercent( + (float) thrNode.get(MAXFLRBACKWARD).asDouble())); + } + if (thrNode.get(AVERAGEFLRBACKWARD) != null) { + builder.averageFlrBackward(MilliPct.ofPercent( + (float) thrNode.get(AVERAGEFLRBACKWARD).asDouble())); + } + if (thrNode.get(FORWARDHIGHLOSS) != null) { + builder.forwardHighLoss(thrNode.get(FORWARDHIGHLOSS).asLong()); + } + if (thrNode.get(FORWARDCONSECUTIVEHIGHLOSS) != null) { + builder.forwardConsecutiveHighLoss(thrNode.get(FORWARDCONSECUTIVEHIGHLOSS).asLong()); + } + if (thrNode.get(BACKWARDHIGHLOSS) != null) { + builder.backwardHighLoss(thrNode.get(BACKWARDHIGHLOSS).asLong()); + } + if (thrNode.get(BACKWARDCONSECUTIVEHIGHLOSS) != null) { + builder.backwardConsecutiveHighLoss(thrNode.get(BACKWARDCONSECUTIVEHIGHLOSS).asLong()); + } + if (thrNode.get(FORWARDUNAVAILABLECOUNT) != null) { + builder.forwardUnavailableCount(thrNode.get(FORWARDUNAVAILABLECOUNT).asLong()); + } + if (thrNode.get(FORWARDAVAILABLERATIO) != null) { + builder.forwardAvailableRatio(MilliPct.ofPercent( + (float) thrNode.get(FORWARDAVAILABLERATIO).asDouble())); + } + if (thrNode.get(BACKWARDUNAVAILABLECOUNT) != null) { + builder.backwardUnavailableCount(thrNode.get(BACKWARDUNAVAILABLECOUNT).asLong()); + } + if (thrNode.get(BACKWARDAVAILABLERATIO) != null) { + builder.backwardAvailableRatio(MilliPct.ofPercent( + (float) thrNode.get(BACKWARDAVAILABLERATIO).asDouble())); + } + + return builder.build(); + } +} diff --git a/apps/cfm/src/main/java/org/onosproject/soam/web/StartTimeCodec.java b/apps/cfm/src/main/java/org/onosproject/soam/web/StartTimeCodec.java new file mode 100644 index 0000000000..f84bffe647 --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/soam/web/StartTimeCodec.java @@ -0,0 +1,57 @@ +/* + * 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.soam.web; + +import java.time.Duration; +import java.time.OffsetDateTime; + +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.incubator.net.l2monitoring.soam.StartTime; + +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * Encode and decode to/from JSON to StartTime object. + */ +public class StartTimeCodec extends JsonCodec { + + @Override + public StartTime decode(ObjectNode json, CodecContext context) { + if (json == null || !json.isObject()) { + return null; + } + + if (json.get("immediate") != null) { + return StartTime.immediate(); + } else if (json.get("absolute") != null) { + if (json.get("absolute").get("start-time") != null) { + return StartTime.absolute(OffsetDateTime + .parse(json.get("absolute").get("start-time").asText()) + .toInstant()); + } + throw new IllegalArgumentException("StartTime absolute must contain " + + "a start-time in date-time format with offset"); + } else if (json.get("relative") != null) { + if (json.get("relative").get("start-time") != null) { + return StartTime.relative(Duration.parse(json.get("relative").get("start-time").asText())); + } + throw new IllegalArgumentException("StartTime relative must contain a start-time duration"); + } else { + throw new IllegalArgumentException("StartTime must be either immediate, absolute or relative"); + } + } +} diff --git a/apps/cfm/src/main/java/org/onosproject/soam/web/StopTimeCodec.java b/apps/cfm/src/main/java/org/onosproject/soam/web/StopTimeCodec.java new file mode 100644 index 0000000000..30a1538aee --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/soam/web/StopTimeCodec.java @@ -0,0 +1,57 @@ +/* + * 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.soam.web; + +import java.time.Duration; +import java.time.OffsetDateTime; + +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.JsonCodec; +import org.onosproject.incubator.net.l2monitoring.soam.StopTime; + +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * Encode and decode to/from JSON to StopTime object. + */ +public class StopTimeCodec extends JsonCodec { + + @Override + public StopTime decode(ObjectNode json, CodecContext context) { + if (json == null || !json.isObject()) { + return null; + } + + if (json.get("none") != null) { + return StopTime.none(); + } else if (json.get("absolute") != null) { + if (json.get("absolute").get("stop-time") != null) { + return StopTime.absolute(OffsetDateTime + .parse(json.get("absolute").get("stop-time").asText()) + .toInstant()); + } + throw new IllegalArgumentException("StopTime absolute must contain " + + "a stop-time in date-time format with offset"); + } else if (json.get("relative") != null) { + if (json.get("relative").get("stop-time") != null) { + return StopTime.relative(Duration.parse(json.get("relative").get("stop-time").asText())); + } + throw new IllegalArgumentException("StopTime relative must contain a stop-time duration"); + } else { + throw new IllegalArgumentException("StopTime must be either none, absolute or relative"); + } + } +} diff --git a/apps/cfm/src/main/java/org/onosproject/soam/web/package-info.java b/apps/cfm/src/main/java/org/onosproject/soam/web/package-info.java new file mode 100644 index 0000000000..473be2407e --- /dev/null +++ b/apps/cfm/src/main/java/org/onosproject/soam/web/package-info.java @@ -0,0 +1,19 @@ +/* + * 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. + */ +/** + * Codecs for converting SOAM objects to and from JSON. + */ +package org.onosproject.soam.web; \ No newline at end of file diff --git a/apps/cfm/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/apps/cfm/src/main/resources/OSGI-INF/blueprint/shell-config.xml new file mode 100644 index 0000000000..5f53ebab75 --- /dev/null +++ b/apps/cfm/src/main/resources/OSGI-INF/blueprint/shell-config.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/cfm/src/main/webapp/WEB-INF/web.xml b/apps/cfm/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..71c89e9f78 --- /dev/null +++ b/apps/cfm/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,57 @@ + + + + Layer 2 Cfm REST API v1.0 + + + + Secured + /* + + + admin + + + + + admin + + + + BASIC + karaf + + + + JAX-RS Service + org.glassfish.jersey.servlet.ServletContainer + + javax.ws.rs.Application + org.onosproject.cfm.impl.CfmWebApplication + + 1 + + + + JAX-RS Service + /* + + diff --git a/apps/cfm/src/test/java/org/onosproject/cfm/CfmCodecContext.java b/apps/cfm/src/test/java/org/onosproject/cfm/CfmCodecContext.java new file mode 100644 index 0000000000..0f1de5e7b1 --- /dev/null +++ b/apps/cfm/src/test/java/org/onosproject/cfm/CfmCodecContext.java @@ -0,0 +1,66 @@ +/* + * 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.cfm; + +import org.onosproject.codec.CodecContext; +import org.onosproject.codec.CodecService; +import org.onosproject.codec.JsonCodec; +import org.onosproject.codec.impl.CodecManager; + +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * Mock codec context for use in codec unit tests. + */ +public class CfmCodecContext implements CodecContext { + + private final ObjectMapper mapper = new ObjectMapper(); + private final CodecManager codecManager = new CodecManager(); + private final CfmWebComponent manager = new CfmWebComponent(); + + /** + * Constructs a new mock codec context. + */ + public CfmCodecContext() { + codecManager.activate(); + manager.codecService = codecManager; + manager.activate(); + } + + @Override + public ObjectMapper mapper() { + return mapper; + } + + @Override + public T getService(Class serviceClass) { + return null; + } + + @Override + public JsonCodec codec(Class entityClass) { + return codecManager.getCodec(entityClass); + } + + /** + * Get the codec manager. + * + * @return instance of codec manager + */ + public CodecService codecManager() { + return codecManager; + } +} diff --git a/apps/cfm/src/test/java/org/onosproject/cfm/impl/CfmResourceTest.java b/apps/cfm/src/test/java/org/onosproject/cfm/impl/CfmResourceTest.java new file mode 100644 index 0000000000..bcbaa9a24a --- /dev/null +++ b/apps/cfm/src/test/java/org/onosproject/cfm/impl/CfmResourceTest.java @@ -0,0 +1,32 @@ +/* + * 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.cfm.impl; + +import org.glassfish.jersey.server.ResourceConfig; +import org.onosproject.rest.resources.ResourceTest; + +/** + * Base class for CFM REST API tests. Performs common configuration operations. + */ +public class CfmResourceTest extends ResourceTest { + + /** + * Creates a new web-resource test. + */ + public CfmResourceTest() { + super(ResourceConfig.forApplicationClass(CfmWebApplication.class)); + } +} diff --git a/apps/cfm/src/test/java/org/onosproject/cfm/impl/MaWebResourceTest.java b/apps/cfm/src/test/java/org/onosproject/cfm/impl/MaWebResourceTest.java new file mode 100644 index 0000000000..6378ea93b2 --- /dev/null +++ b/apps/cfm/src/test/java/org/onosproject/cfm/impl/MaWebResourceTest.java @@ -0,0 +1,199 @@ +/* + * 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.cfm.impl; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.junit.Before; +import org.junit.Test; +import org.onlab.osgi.ServiceDirectory; +import org.onlab.osgi.TestServiceDirectory; +import org.onlab.packet.VlanId; +import org.onlab.rest.BaseResource; +import org.onosproject.cfm.CfmCodecContext; +import org.onosproject.codec.CodecService; +import org.onosproject.incubator.net.l2monitoring.cfm.Component; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultComponent; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMaintenanceAssociation; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMaintenanceDomain; +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceAssociation; +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMdService; + +import javax.ws.rs.InternalServerErrorException; +import javax.ws.rs.client.Entity; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.Response; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Optional; + +import static junit.framework.TestCase.fail; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +public class MaWebResourceTest extends CfmResourceTest { + private final CfmMdService mdService = createMock(CfmMdService.class); + + private static final MdId MDNAME1 = MdIdCharStr.asMdId("md-1"); + private static final MaIdShort MANAME1 = MaIdCharStr.asMaId("ma-1-1"); + + private MaintenanceAssociation ma1; + + @Before + public void setUpTest() throws CfmConfigException { + CfmCodecContext context = new CfmCodecContext(); + ServiceDirectory testDirectory = new TestServiceDirectory() + .add(CfmMdService.class, mdService) + .add(CodecService.class, context.codecManager()); + BaseResource.setServiceDirectory(testDirectory); + + ma1 = DefaultMaintenanceAssociation + .builder(MANAME1, MDNAME1.getNameLength()) + .addToRemoteMepIdList(MepId.valueOf((short) 101)) + .addToRemoteMepIdList(MepId.valueOf((short) 102)) + .ccmInterval(MaintenanceAssociation.CcmInterval.INTERVAL_3MS) + .maNumericId((short) 1) + .addToComponentList( + DefaultComponent.builder(1) + .tagType(Component.TagType.VLAN_STAG) + .mhfCreationType(Component.MhfCreationType.NONE) + .idPermission(Component.IdPermissionType.MANAGE) + .addToVidList(VlanId.vlanId((short) 1010)) + .build()) + .build(); + } + + @Test + public void testGetMa() { + + expect(mdService.getMaintenanceAssociation(MDNAME1, MANAME1)) + .andReturn(Optional.ofNullable(ma1)).anyTimes(); + replay(mdService); + + final WebTarget wt = target(); + final String response = wt.path("md/" + MDNAME1.mdName() + + "/ma/" + MANAME1.maName()).request().get(String.class); + + assertThat(response, is("{\"ma\":" + + "{\"maName\":\"ma-1-1\"," + + "\"maNameType\":\"CHARACTERSTRING\"," + + "\"maNumericId\":1," + + "\"ccm-interval\":\"INTERVAL_3MS\"," + + "\"component-list\":[{\"component\":" + + "{\"component-id\":1," + + "\"vid-list\":[{\"vid\":\"1010\"}]," + + "\"mhf-creation-type\":\"NONE\"," + + "\"id-permission\":\"MANAGE\"," + + "\"tag-type\":\"VLAN_STAG\"}}]," + + "\"rmep-list\":" + + "[{\"rmep\":101}," + + "{\"rmep\":102}]}}")); + } + + @Test + public void testGetMaEmpty() throws IOException { + MaIdShort maId2 = MaIdCharStr.asMaId("ma-2"); + expect(mdService + .getMaintenanceAssociation(MDNAME1, maId2)) + .andReturn(Optional.empty()).anyTimes(); + replay(mdService); + + final WebTarget wt = target(); + try { + final String response = wt.path("md/" + MDNAME1.mdName() + + "/ma/" + maId2.maName()).request().get(String.class); + fail("Expected InternalServerErrorException, as MA is unknown"); + } catch (InternalServerErrorException e) { + ByteArrayInputStream is = (ByteArrayInputStream) e.getResponse().getEntity(); + BufferedReader br = new BufferedReader(new InputStreamReader(is)); + String line = null; + StringBuffer sb = new StringBuffer(); + while ((line = br.readLine()) != null) { + sb.append(line); + } + + assertThat(sb.toString(), is("{ \"failure\":" + + "\"java.lang.IllegalArgumentException: MA ma-2 not Found\" }")); + } + } + + @Test + public void testDeleteMa() throws CfmConfigException { + + expect(mdService.deleteMaintenanceAssociation(MDNAME1, MANAME1)) + .andReturn(true).anyTimes(); + replay(mdService); + + final WebTarget wt = target(); + final Response response = wt.path("md/" + MDNAME1.mdName() + + "/ma/" + MANAME1.maName()).request().delete(); + + assertEquals(200, response.getStatus()); + } + + @Test + public void testDeleteMaEmpty() throws CfmConfigException { + MaIdShort maId2 = MaIdCharStr.asMaId("ma-2"); + + expect(mdService.deleteMaintenanceAssociation(MDNAME1, maId2)) + .andReturn(false).anyTimes(); + replay(mdService); + + final WebTarget wt = target(); + final Response response = wt.path("md/" + MDNAME1.mdName() + + "/ma/" + maId2.maName()).request().delete(); + + assertEquals(304, response.getStatus()); + } + + @Test + public void testCreateMa() throws CfmConfigException { + MaintenanceDomain md1 = DefaultMaintenanceDomain + .builder(MDNAME1).mdLevel(MaintenanceDomain.MdLevel.LEVEL2).build(); + + expect(mdService.getMaintenanceDomain(MDNAME1)) + .andReturn(Optional.ofNullable(md1)).anyTimes(); + expect(mdService.createMaintenanceAssociation(MDNAME1, ma1)) + .andReturn(false).anyTimes(); + replay(mdService); + + ObjectMapper mapper = new ObjectMapper(); + CfmCodecContext context = new CfmCodecContext(); + ObjectNode node = mapper.createObjectNode(); + node.set("ma", context.codec(MaintenanceAssociation.class) + .encode(ma1, context)); + + final WebTarget wt = target(); + final Response response = wt.path("md/" + MDNAME1.mdName() + + "/ma").request().post(Entity.json(node.toString())); + + assertEquals(201, response.getStatus()); + } +} diff --git a/apps/cfm/src/test/java/org/onosproject/cfm/impl/MdWebResourceTest.java b/apps/cfm/src/test/java/org/onosproject/cfm/impl/MdWebResourceTest.java new file mode 100644 index 0000000000..f4c9b5a6d3 --- /dev/null +++ b/apps/cfm/src/test/java/org/onosproject/cfm/impl/MdWebResourceTest.java @@ -0,0 +1,193 @@ +/* + * 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.cfm.impl; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.junit.Before; +import org.junit.Test; +import org.onlab.osgi.ServiceDirectory; +import org.onlab.osgi.TestServiceDirectory; +import org.onlab.rest.BaseResource; +import org.onosproject.cfm.CfmCodecContext; +import org.onosproject.codec.CodecService; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMaintenanceDomain; +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMdService; + +import javax.ws.rs.InternalServerErrorException; +import javax.ws.rs.client.Entity; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.Response; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import static junit.framework.TestCase.fail; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +public class MdWebResourceTest extends CfmResourceTest { + private final CfmMdService mdService = createMock(CfmMdService.class); + + private static final MdId MDNAME1 = MdIdCharStr.asMdId("md-1"); + private static final MdId MDNAME2 = MdIdCharStr.asMdId("md-2"); + + private List mdList; + + @Before + public void setUpTest() throws CfmConfigException { + CfmCodecContext context = new CfmCodecContext(); + ServiceDirectory testDirectory = new TestServiceDirectory() + .add(CfmMdService.class, mdService) + .add(CodecService.class, context.codecManager()); + BaseResource.setServiceDirectory(testDirectory); + + mdList = new ArrayList<>(); + + mdList.add(DefaultMaintenanceDomain.builder(MDNAME1) + .mdLevel(MaintenanceDomain.MdLevel.LEVEL1).build()); + mdList.add(DefaultMaintenanceDomain.builder(MDNAME2) + .mdLevel(MaintenanceDomain.MdLevel.LEVEL2).build()); + } + + @Test + public void testGetMds() { + expect(mdService.getAllMaintenanceDomain()).andReturn(mdList).anyTimes(); + replay(mdService); + + final WebTarget wt = target(); + final String response = wt.path("md").request().get(String.class); + + assertThat(response, is("{\"mds\":[[" + + "{\"mdName\":\"md-1\",\"mdNameType\":\"CHARACTERSTRING\"," + + "\"mdLevel\":\"LEVEL1\",\"maList\":[]}," + + "{\"mdName\":\"md-2\",\"mdNameType\":\"CHARACTERSTRING\"," + + "\"mdLevel\":\"LEVEL2\",\"maList\":[]}]]}")); + } + + @Test + public void testGetMdsEmpty() { + expect(mdService.getAllMaintenanceDomain()) + .andReturn(new ArrayList<>()).anyTimes(); + replay(mdService); + + final WebTarget wt = target(); + final String response = wt.path("md").request().get(String.class); + + assertThat(response, is("{\"mds\":[[]]}")); + } + + @Test + public void testGetMd() { + expect(mdService.getMaintenanceDomain(MDNAME1)) + .andReturn(Optional.ofNullable(mdList.get(0))).anyTimes(); + replay(mdService); + + final WebTarget wt = target(); + final String response = wt.path("md/" + MDNAME1).request().get(String.class); + + assertThat(response, is("{\"md\":" + + "{\"mdName\":\"md-1\",\"mdNameType\":\"CHARACTERSTRING\"," + + "\"mdLevel\":\"LEVEL1\",\"maList\":[]}}")); + } + + @Test + public void testGetMdEmpty() throws IOException { + final MdId mdName3 = MdIdCharStr.asMdId("md-3"); + expect(mdService.getMaintenanceDomain(mdName3)) + .andReturn(Optional.empty()).anyTimes(); + replay(mdService); + + final WebTarget wt = target(); + try { + final String response = wt.path("md/" + mdName3).request().get(String.class); + fail("Expected InternalServerErrorException, as MD is unknown"); + } catch (InternalServerErrorException e) { + ByteArrayInputStream is = (ByteArrayInputStream) e.getResponse().getEntity(); + BufferedReader br = new BufferedReader(new InputStreamReader(is)); + String line = null; + StringBuffer sb = new StringBuffer(); + while ((line = br.readLine()) != null) { + sb.append(line); + } + + assertThat(sb.toString(), is("{ \"failure\":" + + "\"java.lang.IllegalArgumentException: MD md-3 not Found\" }")); + } + } + + @Test + public void testDeleteMd() throws CfmConfigException { + expect(mdService.deleteMaintenanceDomain(MDNAME1)) + .andReturn(true).anyTimes(); + replay(mdService); + + final WebTarget wt = target(); + final Response response = wt.path("md/" + MDNAME1).request().delete(); + + assertEquals(200, response.getStatus()); + } + + @Test + public void testDeleteMdNotPresent() throws CfmConfigException { + expect(mdService.deleteMaintenanceDomain(MDNAME1)) + .andReturn(false).anyTimes(); + replay(mdService); + + final WebTarget wt = target(); + final Response response = wt.path("md/" + MDNAME1).request().delete(); + + assertEquals(304, response.getStatus()); + } + + @Test + public void testCreateMd() throws CfmConfigException { + MaintenanceDomain md3 = DefaultMaintenanceDomain + .builder(MdIdCharStr.asMdId("md-3")) + .mdLevel(MaintenanceDomain.MdLevel.LEVEL3) + .mdNumericId((short) 3) + .build(); + + expect(mdService.createMaintenanceDomain(mdList.get(1))) + .andReturn(false).anyTimes(); + replay(mdService); + + ObjectMapper mapper = new ObjectMapper(); + CfmCodecContext context = new CfmCodecContext(); + ObjectNode node = mapper.createObjectNode(); + node.set("md", context.codec(MaintenanceDomain.class) + .encode(mdList.get(1), context)); + + + final WebTarget wt = target(); + final Response response = wt.path("md") + .request().post(Entity.json(node.toString())); + + assertEquals(201, response.getStatus()); + } +} diff --git a/apps/cfm/src/test/java/org/onosproject/cfm/impl/MepWebResourceTest.java b/apps/cfm/src/test/java/org/onosproject/cfm/impl/MepWebResourceTest.java new file mode 100644 index 0000000000..4dd83dba0c --- /dev/null +++ b/apps/cfm/src/test/java/org/onosproject/cfm/impl/MepWebResourceTest.java @@ -0,0 +1,378 @@ +/* + * 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.cfm.impl; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.junit.Before; +import org.junit.Test; +import org.onlab.osgi.ServiceDirectory; +import org.onlab.osgi.TestServiceDirectory; +import org.onlab.packet.VlanId; +import org.onlab.rest.BaseResource; +import org.onosproject.cfm.CfmCodecContext; +import org.onosproject.codec.CodecService; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMaintenanceAssociation; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMaintenanceDomain; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMep; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMepEntry; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMepLbCreate; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMepLtCreate; +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceAssociation; +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep; +import org.onosproject.incubator.net.l2monitoring.cfm.MepEntry; +import org.onosproject.incubator.net.l2monitoring.cfm.MepLbCreate; +import org.onosproject.incubator.net.l2monitoring.cfm.MepLtCreate; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMdService; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepService; +import org.onosproject.net.DeviceId; +import org.onosproject.net.PortNumber; + +import javax.ws.rs.InternalServerErrorException; +import javax.ws.rs.client.Entity; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.Response; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.time.Duration; +import java.util.ArrayList; +import java.util.BitSet; +import java.util.Collection; +import java.util.Optional; + +import static junit.framework.TestCase.fail; +import static org.easymock.EasyMock.*; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +public class MepWebResourceTest extends CfmResourceTest { + private final CfmMepService mepService = createMock(CfmMepService.class); + private final CfmMdService mdService = createMock(CfmMdService.class); + + private static final MdId MDNAME1 = MdIdCharStr.asMdId("md-1"); + private static final MaIdShort MANAME1 = MaIdCharStr.asMaId("ma-1-1"); + private static final MepId MEPID1 = MepId.valueOf((short) 1); + + private MepEntry mepEntry1 = null; + + @Before + public void setUpTest() throws CfmConfigException { + CfmCodecContext context = new CfmCodecContext(); + ServiceDirectory testDirectory = new TestServiceDirectory() + .add(CfmMepService.class, mepService) + .add(CfmMdService.class, mdService) + .add(CodecService.class, context.codecManager()); + BaseResource.setServiceDirectory(testDirectory); + + mepEntry1 = DefaultMepEntry.builder( + MEPID1, + DeviceId.deviceId("netconf:1.2.3.4:830"), + PortNumber.portNumber(1), + Mep.MepDirection.UP_MEP, MDNAME1, MANAME1) + .buildEntry(); + + } + + @Test + public void testGetAllMepsForMaEmpty() throws CfmConfigException { + + expect(mepService.getAllMeps(MDNAME1, MANAME1)).andReturn(null).anyTimes(); + replay(mepService); + + final WebTarget wt = target(); + final String response = wt.path("md/" + MDNAME1.mdName() + "/ma/" + + MANAME1.maName() + "/mep").request().get(String.class); + assertThat(response, is("{\"meps\":[[]]}")); + } + + @Test + public void testGetAllMepsForMa1Mep() throws CfmConfigException { + Collection meps = new ArrayList<>(); + meps.add(mepEntry1); + + expect(mepService.getAllMeps(MDNAME1, MANAME1)).andReturn(meps).anyTimes(); + replay(mepService); + + final WebTarget wt = target(); + final String response = wt.path("md/" + MDNAME1.mdName() + "/ma/" + + MANAME1.maName() + "/mep").request().get(String.class); + + assertThat(response, is("{\"meps\":" + + "[[{" + + "\"mepId\":" + MEPID1.value() + "," + + "\"deviceId\":\"netconf:1.2.3.4:830\"," + + "\"port\":1," + + "\"direction\":\"UP_MEP\"," + + "\"mdName\":\"" + MDNAME1.mdName() + "\"," + + "\"maName\":\"" + MANAME1.maName() + "\"," + + "\"administrative-state\":false," + + "\"cci-enabled\":false," + + "\"remoteMeps\":[]}]]}")); + } + + @Test + public void testGetMepValid() throws CfmConfigException { + + expect(mepService.getMep(MDNAME1, MANAME1, MepId.valueOf((short) 1))) + .andReturn(mepEntry1).anyTimes(); + replay(mepService); + + final WebTarget wt = target(); + final String response = wt.path("md/" + MDNAME1.mdName() + "/ma/" + + MANAME1.maName() + "/mep/" + MEPID1.value()).request().get(String.class); + + assertThat(response, is("{\"mep\":" + + "{" + + "\"mepId\":" + MEPID1.value() + "," + + "\"deviceId\":\"netconf:1.2.3.4:830\"," + + "\"port\":1," + + "\"direction\":\"UP_MEP\"," + + "\"mdName\":\"" + MDNAME1.mdName() + "\"," + + "\"maName\":\"" + MANAME1.maName() + "\"," + + "\"administrative-state\":false," + + "\"cci-enabled\":false," + + "\"remoteMeps\":[]}}")); + } + + @Test + public void testGetMepNotFound() throws CfmConfigException, IOException { + + expect(mepService.getMep(MDNAME1, MANAME1, MepId.valueOf((short) 2))) + .andReturn(null).anyTimes(); + replay(mepService); + + final WebTarget wt = target(); + + try { + final String response = wt.path("md/" + MDNAME1.mdName() + "/ma/" + + MANAME1.maName() + "/mep/" + 2).request().get(String.class); + fail("Expected exception to be thrown"); + } catch (InternalServerErrorException e) { + ByteArrayInputStream is = (ByteArrayInputStream) e.getResponse().getEntity(); + BufferedReader br = new BufferedReader(new InputStreamReader(is)); + String line = null; + StringBuffer sb = new StringBuffer(); + while ((line = br.readLine()) != null) { + sb.append(line); + } + assertEquals("{ \"failure\":\"MEP md-1/ma-1-1/2 not found\" }", sb.toString()); + } + } + + @Test + public void testDeleteMepValid() throws CfmConfigException { + + expect(mepService.deleteMep(MDNAME1, MANAME1, MepId.valueOf((short) 1))) + .andReturn(true).anyTimes(); + replay(mepService); + + final WebTarget wt = target(); + final Response response = wt.path("md/" + MDNAME1.mdName() + "/ma/" + + MANAME1.maName() + "/mep/" + MEPID1.value()).request().delete(); + + assertEquals("Expecting 200", 200, response.getStatus()); + } + + @Test + public void testDeleteMepNotFound() throws CfmConfigException { + + expect(mepService.deleteMep(MDNAME1, MANAME1, MepId.valueOf((short) 2))) + .andReturn(false).anyTimes(); + replay(mepService); + + final WebTarget wt = target(); + final Response response = wt.path("md/" + MDNAME1.mdName() + "/ma/" + + MANAME1.maName() + "/mep/2").request().delete(); + + assertEquals("Expecting 304", 304, response.getStatus()); + } + + @Test + public void testCreateMep() throws CfmConfigException, IOException { + MepId mepId2 = MepId.valueOf((short) 2); + Mep mep2 = DefaultMep.builder( + mepId2, + DeviceId.deviceId("netconf:2.2.3.4:830"), + PortNumber.portNumber(2), + Mep.MepDirection.UP_MEP, MDNAME1, MANAME1).build(); + + MaintenanceAssociation ma1 = DefaultMaintenanceAssociation + .builder(MANAME1, MDNAME1.getNameLength()).build(); + + expect(mdService.getMaintenanceAssociation(MDNAME1, MANAME1)) + .andReturn(Optional.ofNullable(ma1)).anyTimes(); + replay(mdService); + expect(mepService.createMep(MDNAME1, MANAME1, mep2)) + .andReturn(true).anyTimes(); + replay(mepService); + + ObjectMapper mapper = new ObjectMapper(); + CfmCodecContext context = new CfmCodecContext(); + ObjectNode node = mapper.createObjectNode(); + node.set("mep", context.codec(Mep.class).encode(mep2, context)); + + final WebTarget wt = target(); + final Response response = wt.path("md/" + MDNAME1.mdName() + "/ma/" + + MANAME1.maName() + "/mep") + .request() + .post(Entity.json(node.toString())); + + assertEquals("Expecting 201", 201, response.getStatus()); + } + + @Test + public void testCreateMepAlreadyExists() throws CfmConfigException, IOException { + MepId mepId3 = MepId.valueOf((short) 3); + Mep mep3 = DefaultMep.builder( + mepId3, + DeviceId.deviceId("netconf:3.2.3.4:830"), + PortNumber.portNumber(3), + Mep.MepDirection.UP_MEP, MDNAME1, MANAME1) + .cciEnabled(true) + .ccmLtmPriority(Mep.Priority.PRIO3) + .administrativeState(false) + .primaryVid(VlanId.vlanId((short) 3)) + .defectAbsentTime(Duration.ofMinutes(2)) + .defectPresentTime(Duration.ofMinutes(3)) + .fngAddress(Mep.FngAddress.notSpecified()) + .lowestFaultPriorityDefect(Mep.LowestFaultDefect.ALL_DEFECTS) + .build(); + + MaintenanceAssociation ma1 = DefaultMaintenanceAssociation + .builder(MANAME1, MDNAME1.getNameLength()).build(); + + expect(mdService.getMaintenanceAssociation(MDNAME1, MANAME1)) + .andReturn(Optional.ofNullable(ma1)).anyTimes(); + replay(mdService); + expect(mepService.createMep(MDNAME1, MANAME1, mep3)) + .andReturn(false).anyTimes(); + replay(mepService); + + ObjectMapper mapper = new ObjectMapper(); + CfmCodecContext context = new CfmCodecContext(); + ObjectNode node = mapper.createObjectNode(); + node.set("mep", context.codec(Mep.class).encode(mep3, context)); + + final WebTarget wt = target(); + final Response response = wt.path("md/" + MDNAME1.mdName() + "/ma/" + + MANAME1.maName() + "/mep") + .request() + .post(Entity.json(node.toString())); + + assertEquals("Expecting 304", 304, response.getStatus()); + } + + @Test + public void testTransmitLoopback() throws CfmConfigException { + MepLbCreate mepLbCreate1 = DefaultMepLbCreate + .builder(MEPID1) + .numberMessages(20) + .dataTlvHex("AA:BB:CC:DD") + .vlanDropEligible(true) + .build(); + + MaintenanceAssociation ma1 = DefaultMaintenanceAssociation + .builder(MANAME1, MDNAME1.getNameLength()).build(); + MaintenanceDomain md1 = DefaultMaintenanceDomain.builder(MDNAME1) + .addToMaList(ma1).build(); + expect(mdService.getMaintenanceDomain(MDNAME1)) + .andReturn(Optional.ofNullable(md1)).anyTimes(); + expect(mdService.getMaintenanceAssociation(MDNAME1, MANAME1)) + .andReturn(Optional.ofNullable(ma1)).anyTimes(); + replay(mdService); + + ObjectMapper mapper = new ObjectMapper(); + CfmCodecContext context = new CfmCodecContext(); + ObjectNode node = mapper.createObjectNode(); + node.set("loopback", context.codec(MepLbCreate.class).encode(mepLbCreate1, context)); + + final WebTarget wt = target(); + final Response response = wt.path("md/" + MDNAME1.mdName() + "/ma/" + + MANAME1.maName() + "/mep/" + MEPID1.value() + "/transmit-loopback") + .request() + .put(Entity.json(node.toString())); + + assertEquals("Expecting 202", 202, response.getStatus()); + } + + @Test + public void testAbortLoopback() throws CfmConfigException { + + MepLbCreate mepLbCreate1 = DefaultMepLbCreate.builder(MEPID1).build(); + + MaintenanceAssociation ma1 = DefaultMaintenanceAssociation + .builder(MANAME1, MDNAME1.getNameLength()).build(); + MaintenanceDomain md1 = DefaultMaintenanceDomain.builder(MDNAME1) + .addToMaList(ma1).build(); + expect(mdService.getMaintenanceDomain(MDNAME1)) + .andReturn(Optional.ofNullable(md1)).anyTimes(); + expect(mdService.getMaintenanceAssociation(MDNAME1, MANAME1)) + .andReturn(Optional.ofNullable(ma1)).anyTimes(); + replay(mdService); + + final WebTarget wt = target(); + final Response response = wt.path("md/" + MDNAME1.mdName() + "/ma/" + + MANAME1.maName() + "/mep/" + MEPID1.value() + "/abort-loopback") + .request() + .put(Entity.json("")); + + assertEquals("Expecting 202", 202, response.getStatus()); + + } + + @Test + public void testTransmitLinktrace() throws CfmConfigException { + MepLtCreate mepLtCreate1 = DefaultMepLtCreate + .builder(MEPID1) + .defaultTtl((short) 20) + .transmitLtmFlags(BitSet.valueOf(new byte[]{1})) + .build(); + + MaintenanceAssociation ma1 = DefaultMaintenanceAssociation + .builder(MANAME1, MDNAME1.getNameLength()).build(); + MaintenanceDomain md1 = DefaultMaintenanceDomain.builder(MDNAME1) + .addToMaList(ma1).build(); + expect(mdService.getMaintenanceDomain(MDNAME1)) + .andReturn(Optional.ofNullable(md1)).anyTimes(); + expect(mdService.getMaintenanceAssociation(MDNAME1, MANAME1)) + .andReturn(Optional.ofNullable(ma1)).anyTimes(); + replay(mdService); + + ObjectMapper mapper = new ObjectMapper(); + CfmCodecContext context = new CfmCodecContext(); + ObjectNode node = mapper.createObjectNode(); + node.set("linktrace", context.codec(MepLtCreate.class).encode(mepLtCreate1, context)); + + final WebTarget wt = target(); + final Response response = wt.path("md/" + MDNAME1.mdName() + "/ma/" + + MANAME1.maName() + "/mep/" + MEPID1.value() + "/transmit-linktrace") + .request() + .put(Entity.json(node.toString())); + + assertEquals("Expecting 202", 202, response.getStatus()); + } +} diff --git a/apps/cfm/src/test/java/org/onosproject/cfm/web/MaintenanceAssociationCodecTest.java b/apps/cfm/src/test/java/org/onosproject/cfm/web/MaintenanceAssociationCodecTest.java new file mode 100644 index 0000000000..9712c7d658 --- /dev/null +++ b/apps/cfm/src/test/java/org/onosproject/cfm/web/MaintenanceAssociationCodecTest.java @@ -0,0 +1,248 @@ +/* + * 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.cfm.web; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.junit.Before; +import org.junit.Test; +import org.onosproject.cfm.CfmCodecContext; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMaintenanceAssociation; +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceAssociation; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaId2Octet; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdIccY1731; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdPrimaryVid; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdRfc2685VpnId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; + +import static org.junit.Assert.assertEquals; + +/** + * Test that the MaintenanceAssociationCodec can successfully parse Json in to a MaintenanceAssociation. + */ +public class MaintenanceAssociationCodecTest { + private static final MaIdShort MAID1_CHAR = MaIdCharStr.asMaId("ma-1"); + private static final MaIdShort MAID2_VID = MaIdPrimaryVid.asMaId(1234); + private static final MaIdShort MAID3_OCTET = MaId2Octet.asMaId(12467); + private static final MaIdShort MAID4_RFC = MaIdRfc2685VpnId.asMaIdHex("aa:bb:cc:dd:ee:ff:99"); + private static final MaIdShort MAID5_Y1731 = MaIdIccY1731.asMaId("abc", "defghij"); + + + private ObjectMapper mapper; + private CfmCodecContext context; + + @Before + public void setUp() throws Exception, CfmConfigException { + mapper = new ObjectMapper(); + context = new CfmCodecContext(); + } + + @Test + public void testDecodeMa1() throws IOException { + String mdString = "{\"ma\": { \"maName\": \"ma-1\"," + + "\"maNameType\": \"CHARACTERSTRING\"," + + "\"component-list\": [], " + + "\"rmep-list\": [], " + + "\"maNumericId\": 1}}"; + + InputStream input = new ByteArrayInputStream( + mdString.getBytes(StandardCharsets.UTF_8)); + JsonNode cfg = mapper.readTree(input); + MaintenanceAssociation maDecode1 = ((MaintenanceAssociationCodec) context + .codec(MaintenanceAssociation.class)) + .decode((ObjectNode) cfg, context, 10); + assertEquals(MAID1_CHAR, maDecode1.maId()); + assertEquals(1, maDecode1.maNumericId()); + } + + @Test + public void testDecodeMa1NoTypeGiven() throws IOException { + String mdString = "{\"ma\": { \"maName\": \"ma-1\"," + + "\"component-list\": [], " + + "\"rmep-list\": [], " + + "\"maNumericId\": 1}}"; + + InputStream input = new ByteArrayInputStream( + mdString.getBytes(StandardCharsets.UTF_8)); + JsonNode cfg = mapper.readTree(input); + MaintenanceAssociation maDecode1 = ((MaintenanceAssociationCodec) context + .codec(MaintenanceAssociation.class)) + .decode((ObjectNode) cfg, context, 10); + assertEquals(MAID1_CHAR, maDecode1.maId()); + assertEquals(1, maDecode1.maNumericId()); + } + + @Test + public void testDecodeMa2() throws IOException { + String mdString = "{\"ma\": { \"maName\": 1234," + + "\"maNameType\": \"PRIMARYVID\"," + + "\"component-list\": [], " + + "\"rmep-list\": [], " + + "\"maNumericId\": 2}}"; + + InputStream input = new ByteArrayInputStream( + mdString.getBytes(StandardCharsets.UTF_8)); + JsonNode cfg = mapper.readTree(input); + MaintenanceAssociation maDecode2 = ((MaintenanceAssociationCodec) context + .codec(MaintenanceAssociation.class)) + .decode((ObjectNode) cfg, context, 10); + assertEquals(MAID2_VID, maDecode2.maId()); + } + + @Test + public void testDecodeMa3() throws IOException { + String mdString = "{\"ma\": { \"maName\": 12467," + + "\"maNameType\": \"TWOOCTET\"," + + "\"component-list\": [], " + + "\"rmep-list\": [], " + + "\"maNumericId\": 3}}"; + + InputStream input = new ByteArrayInputStream( + mdString.getBytes(StandardCharsets.UTF_8)); + JsonNode cfg = mapper.readTree(input); + MaintenanceAssociation maDecode3 = ((MaintenanceAssociationCodec) context + .codec(MaintenanceAssociation.class)) + .decode((ObjectNode) cfg, context, 10); + assertEquals(MAID3_OCTET, maDecode3.maId()); + } + + @Test + public void testDecodeMa4() throws IOException { + String mdString = "{\"ma\": { \"maName\": \"aa:bb:cc:dd:ee:ff:99\"," + + "\"maNameType\": \"RFC2685VPNID\"," + + "\"component-list\": [], " + + "\"rmep-list\": [], " + + "\"maNumericId\": 4}}"; + + InputStream input = new ByteArrayInputStream( + mdString.getBytes(StandardCharsets.UTF_8)); + JsonNode cfg = mapper.readTree(input); + MaintenanceAssociation maDecode4 = ((MaintenanceAssociationCodec) context + .codec(MaintenanceAssociation.class)) + .decode((ObjectNode) cfg, context, 10); + assertEquals(MAID4_RFC, maDecode4.maId()); + } + + @Test + public void testDecodeMa5() throws IOException { + String mdString = "{\"ma\": { \"maName\": \"abc:defghij\"," + + "\"maNameType\": \"ICCY1731\"," + + "\"component-list\": [], " + + "\"rmep-list\": [], " + + "\"maNumericId\": 5}}"; + + InputStream input = new ByteArrayInputStream( + mdString.getBytes(StandardCharsets.UTF_8)); + JsonNode cfg = mapper.readTree(input); + MaintenanceAssociation maDecode5 = ((MaintenanceAssociationCodec) context + .codec(MaintenanceAssociation.class)) + .decode((ObjectNode) cfg, context, 10); + assertEquals(MAID5_Y1731, maDecode5.maId()); + } + + @Test + public void testEncodeMa1() throws CfmConfigException { + MaintenanceAssociation ma1 = DefaultMaintenanceAssociation.builder(MAID1_CHAR, 10) + .maNumericId((short) 1) + .build(); + + ObjectNode node = mapper.createObjectNode(); + node.set("ma", context.codec(MaintenanceAssociation.class).encode(ma1, context)); + + assertEquals("{\"ma\":{" + + "\"maName\":\"ma-1\"," + + "\"maNameType\":\"CHARACTERSTRING\"," + + "\"maNumericId\":1," + + "\"component-list\":[]," + + "\"rmep-list\":[]}}", node.toString()); + } + + @Test + public void testEncodeMa2() throws CfmConfigException { + MaintenanceAssociation ma1 = DefaultMaintenanceAssociation.builder(MAID2_VID, 10) + .maNumericId((short) 2) + .build(); + + ObjectNode node = mapper.createObjectNode(); + node.set("ma", context.codec(MaintenanceAssociation.class).encode(ma1, context)); + + assertEquals("{\"ma\":{" + + "\"maName\":\"1234\"," + + "\"maNameType\":\"PRIMARYVID\"," + + "\"maNumericId\":2," + + "\"component-list\":[]," + + "\"rmep-list\":[]}}", node.toString()); + } + + @Test + public void testEncodeMa3() throws CfmConfigException { + MaintenanceAssociation ma1 = DefaultMaintenanceAssociation.builder(MAID3_OCTET, 10) + .maNumericId((short) 3) + .build(); + + ObjectNode node = mapper.createObjectNode(); + node.set("ma", context.codec(MaintenanceAssociation.class).encode(ma1, context)); + + assertEquals("{\"ma\":{" + + "\"maName\":\"12467\"," + + "\"maNameType\":\"TWOOCTET\"," + + "\"maNumericId\":3," + + "\"component-list\":[]," + + "\"rmep-list\":[]}}", node.toString()); + } + + @Test + public void testEncodeMa4() throws CfmConfigException { + MaintenanceAssociation ma1 = DefaultMaintenanceAssociation.builder(MAID4_RFC, 10) + .maNumericId((short) 4) + .build(); + + ObjectNode node = mapper.createObjectNode(); + node.set("ma", context.codec(MaintenanceAssociation.class).encode(ma1, context)); + + assertEquals("{\"ma\":{" + + "\"maName\":\"aa:bb:cc:dd:ee:ff:99\"," + + "\"maNameType\":\"RFC2685VPNID\"," + + "\"maNumericId\":4," + + "\"component-list\":[]," + + "\"rmep-list\":[]}}", node.toString()); + } + + @Test + public void testEncodeMa5() throws CfmConfigException { + MaintenanceAssociation ma1 = DefaultMaintenanceAssociation.builder(MAID5_Y1731, 10) + .maNumericId((short) 5) + .build(); + + ObjectNode node = mapper.createObjectNode(); + node.set("ma", context.codec(MaintenanceAssociation.class).encode(ma1, context)); + + assertEquals("{\"ma\":{" + + "\"maName\":\"abc:defghij\"," + + "\"maNameType\":\"ICCY1731\"," + + "\"maNumericId\":5," + + "\"component-list\":[]," + + "\"rmep-list\":[]}}", node.toString()); + } +} diff --git a/apps/cfm/src/test/java/org/onosproject/cfm/web/MaintenanceDomainCodecTest.java b/apps/cfm/src/test/java/org/onosproject/cfm/web/MaintenanceDomainCodecTest.java new file mode 100644 index 0000000000..b1fff520f2 --- /dev/null +++ b/apps/cfm/src/test/java/org/onosproject/cfm/web/MaintenanceDomainCodecTest.java @@ -0,0 +1,197 @@ +/* + * 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.cfm.web; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import com.google.common.net.InternetDomainName; +import org.junit.Before; +import org.junit.Test; +import org.onlab.packet.MacAddress; +import org.onosproject.cfm.CfmCodecContext; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMaintenanceDomain; +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdDomainName; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdMacUint; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdNone; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; + +import static org.junit.Assert.assertEquals; + +/** + * Test that the MaintenanceDomainCodec can successfully parse Json in to a MaintenanceDomain. + */ +public class MaintenanceDomainCodecTest { + private static final MdId MDID1_CHAR = MdIdCharStr.asMdId("test-1"); + private static final MdId MDID2_DOMAIN = MdIdDomainName.asMdId( + InternetDomainName.from("test.opennetworking.org")); + private static final MdId MDID3_MACUINT = + MdIdMacUint.asMdId(MacAddress.valueOf("aa:bb:cc:dd:ee:ff"), 181); + private static final MdId MDID4_NONE = MdIdNone.asMdId(); + + private ObjectMapper mapper; + private CfmCodecContext context; + + @Before + public void setUp() throws Exception, CfmConfigException { + mapper = new ObjectMapper(); + context = new CfmCodecContext(); + } + + @Test + public void testDecodeMd1() throws IOException { + String mdString = "{\"md\": { \"mdName\": \"test-1\"," + + "\"mdNameType\": \"CHARACTERSTRING\"," + + "\"mdLevel\": \"LEVEL1\", \"mdNumericId\": 1}}"; + + InputStream input = new ByteArrayInputStream( + mdString.getBytes(StandardCharsets.UTF_8)); + JsonNode cfg = mapper.readTree(input); + MaintenanceDomain mdDecode1 = context + .codec(MaintenanceDomain.class).decode((ObjectNode) cfg, context); + assertEquals(MDID1_CHAR, mdDecode1.mdId()); + assertEquals(MaintenanceDomain.MdLevel.LEVEL1, mdDecode1.mdLevel()); + assertEquals(1, mdDecode1.mdNumericId()); + } + + @Test + public void testDecodeMd1NoTypeGiven() throws IOException { + String mdString = "{\"md\": { \"mdName\": \"test-1\"," + + "\"mdLevel\": \"LEVEL1\", \"mdNumericId\": 1}}"; + + InputStream input = new ByteArrayInputStream( + mdString.getBytes(StandardCharsets.UTF_8)); + JsonNode cfg = mapper.readTree(input); + MaintenanceDomain mdDecode1 = context + .codec(MaintenanceDomain.class).decode((ObjectNode) cfg, context); + assertEquals(MDID1_CHAR, mdDecode1.mdId()); + assertEquals(MaintenanceDomain.MdLevel.LEVEL1, mdDecode1.mdLevel()); + assertEquals(1, mdDecode1.mdNumericId()); + } + + + @Test + public void testDecodeMd2() throws IOException { + String mdString = "{\"md\": { \"mdName\": \"test.opennetworking.org\"," + + "\"mdNameType\": \"DOMAINNAME\"}}"; + + InputStream input = new ByteArrayInputStream( + mdString.getBytes(StandardCharsets.UTF_8)); + JsonNode cfg = mapper.readTree(input); + MaintenanceDomain mdDecode1 = context + .codec(MaintenanceDomain.class).decode((ObjectNode) cfg, context); + assertEquals(MDID2_DOMAIN, mdDecode1.mdId()); + assertEquals(MaintenanceDomain.MdLevel.LEVEL0, mdDecode1.mdLevel()); + assertEquals(0, mdDecode1.mdNumericId()); + } + + @Test + public void testDecodeMd3() throws IOException { + String mdString = "{\"md\": { \"mdName\": \"aa:bb:cc:dd:ee:ff:181\"," + + "\"mdNameType\": \"MACANDUINT\"}}"; + + InputStream input = new ByteArrayInputStream( + mdString.getBytes(StandardCharsets.UTF_8)); + JsonNode cfg = mapper.readTree(input); + MaintenanceDomain mdDecode1 = context + .codec(MaintenanceDomain.class).decode((ObjectNode) cfg, context); + assertEquals(MDID3_MACUINT, mdDecode1.mdId()); + } + + @Test + public void testDecodeMd4() throws IOException { + String mdString = "{\"md\": { \"mdName\": \"\"," + + "\"mdNameType\": \"NONE\"}}"; + + InputStream input = new ByteArrayInputStream( + mdString.getBytes(StandardCharsets.UTF_8)); + JsonNode cfg = mapper.readTree(input); + MaintenanceDomain mdDecode1 = context + .codec(MaintenanceDomain.class).decode((ObjectNode) cfg, context); + assertEquals(MDID4_NONE, mdDecode1.mdId()); + } + + @Test + public void testEncodeMd1() throws CfmConfigException { + MaintenanceDomain md1 = DefaultMaintenanceDomain.builder(MDID1_CHAR) + .mdLevel(MaintenanceDomain.MdLevel.LEVEL1) + .mdNumericId((short) 1) + .build(); + + ObjectNode node = mapper.createObjectNode(); + node.set("md", context.codec(MaintenanceDomain.class).encode(md1, context)); + + assertEquals("{\"md\":{" + + "\"mdName\":\"test-1\"," + + "\"mdNameType\":\"CHARACTERSTRING\"," + + "\"mdLevel\":\"LEVEL1\"," + + "\"mdNumericId\":1," + + "\"maList\":[]}}", node.toString()); + } + + @Test + public void testEncodeMd2() throws CfmConfigException { + MaintenanceDomain md2 = DefaultMaintenanceDomain.builder(MDID2_DOMAIN) + .mdLevel(MaintenanceDomain.MdLevel.LEVEL2).build(); + + ObjectNode node = mapper.createObjectNode(); + node.set("md", context.codec(MaintenanceDomain.class).encode(md2, context)); + + assertEquals("{\"md\":{" + + "\"mdName\":\"test.opennetworking.org\"," + + "\"mdNameType\":\"DOMAINNAME\"," + + "\"mdLevel\":\"LEVEL2\"," + + "\"maList\":[]}}", node.toString()); + } + + @Test + public void testEncodeMd3() throws CfmConfigException { + MaintenanceDomain md3 = DefaultMaintenanceDomain.builder(MDID3_MACUINT) + .mdLevel(MaintenanceDomain.MdLevel.LEVEL3).build(); + + ObjectNode node = mapper.createObjectNode(); + node.set("md", context.codec(MaintenanceDomain.class).encode(md3, context)); + + assertEquals("{\"md\":{" + + "\"mdName\":\"AA:BB:CC:DD:EE:FF:181\"," + + "\"mdNameType\":\"MACANDUINT\"," + + "\"mdLevel\":\"LEVEL3\"," + + "\"maList\":[]}}", node.toString()); + } + + @Test + public void testEncodeMd4() throws CfmConfigException { + MaintenanceDomain md4 = DefaultMaintenanceDomain.builder(MDID4_NONE) + .mdLevel(MaintenanceDomain.MdLevel.LEVEL4).build(); + + ObjectNode node = mapper.createObjectNode(); + node.set("md", context.codec(MaintenanceDomain.class).encode(md4, context)); + + assertEquals("{\"md\":{" + + "\"mdName\":\"\"," + + "\"mdNameType\":\"NONE\"," + + "\"mdLevel\":\"LEVEL4\"," + + "\"maList\":[]}}", node.toString()); + } +} diff --git a/apps/cfm/src/test/java/org/onosproject/cfm/web/MepEntryCodecTest.java b/apps/cfm/src/test/java/org/onosproject/cfm/web/MepEntryCodecTest.java new file mode 100644 index 0000000000..ea07b8ea6c --- /dev/null +++ b/apps/cfm/src/test/java/org/onosproject/cfm/web/MepEntryCodecTest.java @@ -0,0 +1,112 @@ +/* + * Copyright 2017-present Open Networking Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.cfm.web; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.Iterator; + +import org.junit.Before; +import org.junit.Test; +import org.onlab.packet.MacAddress; +import org.onosproject.cfm.CfmCodecContext; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMepEntry; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep.MepDirection; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep.Priority; +import org.onosproject.incubator.net.l2monitoring.cfm.MepEntry; +import org.onosproject.incubator.net.l2monitoring.cfm.MepEntry.MepEntryBuilder; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; +import org.onosproject.net.DeviceId; +import org.onosproject.net.PortNumber; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; + +/** + * Test that the MepEntryCodec can successfully parse Json in to a Mep. + */ +public class MepEntryCodecTest { + ObjectMapper mapper; + CfmCodecContext context; + MepEntry mepEntry1; + + @Before + public void setUp() throws Exception, CfmConfigException { + mapper = new ObjectMapper(); + context = new CfmCodecContext(); + MepEntryBuilder builder = DefaultMepEntry.builder( + MepId.valueOf((short) 22), + DeviceId.deviceId("netconf:1234:830"), + PortNumber.portNumber(2), + MepDirection.UP_MEP, + MdIdCharStr.asMdId("md-1"), + MaIdCharStr.asMaId("ma-1-1")) + .macAddress(MacAddress.valueOf("aa:bb:cc:dd:ee:ff")); + builder = (MepEntryBuilder) builder + .administrativeState(true) + .cciEnabled(true) + .ccmLtmPriority(Priority.PRIO1); + mepEntry1 = builder.buildEntry(); + + } + + @Test + public void testEncodeMepEntryCodecContext() { + ObjectNode node = mapper.createObjectNode(); + node.set("mep", context.codec(MepEntry.class).encode(mepEntry1, context)); + + assertEquals(22, node.get("mep").get("mepId").asInt()); + assertEquals("aa:bb:cc:dd:ee:ff".toUpperCase(), + node.get("mep").get("macAddress").asText()); + assertTrue(node.get("mep").get("administrative-state").asBoolean()); + assertTrue(node.get("mep").get("cci-enabled").asBoolean()); + assertEquals(Priority.PRIO1.ordinal(), + node.get("mep").get("ccm-ltm-priority").asInt()); + } + + @Test + public void testEncodeIterableOfMepEntryCodecContext() throws CfmConfigException { + MepEntry mepEntry2 = DefaultMepEntry.builder( + MepId.valueOf((short) 33), + DeviceId.deviceId("netconf:4321:830"), + PortNumber.portNumber(1), + MepDirection.DOWN_MEP, + MdIdCharStr.asMdId("md-2"), + MaIdCharStr.asMaId("ma-2-2")) + .buildEntry(); + + ArrayList meps = new ArrayList<>(); + meps.add(mepEntry1); + meps.add(mepEntry2); + + ObjectNode node = mapper.createObjectNode(); + node.set("mep", context.codec(MepEntry.class) + .encode(meps, context)); + + Iterator an = node.get("mep").elements(); + while (an.hasNext()) { + JsonNode jn = an.next(); + assertEquals("md-", jn.get("mdName").asText().substring(0, 3)); + } + } + +} diff --git a/apps/cfm/src/test/java/org/onosproject/cfm/web/MepLbCreateCodecTest.java b/apps/cfm/src/test/java/org/onosproject/cfm/web/MepLbCreateCodecTest.java new file mode 100644 index 0000000000..e2c853ac47 --- /dev/null +++ b/apps/cfm/src/test/java/org/onosproject/cfm/web/MepLbCreateCodecTest.java @@ -0,0 +1,80 @@ +/* + * 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.cfm.web; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; + +import org.junit.Before; +import org.junit.Test; +import org.onosproject.cfm.CfmCodecContext; +import org.onosproject.incubator.net.l2monitoring.cfm.MepLbCreate; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; + +public class MepLbCreateCodecTest { + ObjectMapper mapper; + CfmCodecContext context; + + @Before + public void setUp() throws Exception { + mapper = new ObjectMapper(); + context = new CfmCodecContext(); + } + + @Test + public void testDecodeMepLbCreateMepId() throws JsonProcessingException, IOException { + String loopbackString = "{\"loopback\": { \"remoteMepId\": 20," + + "\"numberMessages\": 10, \"vlanDropEligible\": true," + + "\"vlanPriority\": 6, \"dataTlvHex\": \"0A:BB:CC\" }}"; + + InputStream input = new ByteArrayInputStream( + loopbackString.getBytes(StandardCharsets.UTF_8)); + JsonNode cfg = mapper.readTree(input); + MepLbCreate mepLbCreate = context + .codec(MepLbCreate.class).decode((ObjectNode) cfg, context); + + assertNull(mepLbCreate.remoteMepAddress()); + assertEquals(20, mepLbCreate.remoteMepId().id().shortValue()); + assertEquals(10, mepLbCreate.numberMessages().intValue()); + assertEquals(6, mepLbCreate.vlanPriority().ordinal()); + assertEquals(true, mepLbCreate.vlanDropEligible()); + assertEquals("0A:BB:CC".toLowerCase(), mepLbCreate.dataTlvHex()); + } + + @Test + public void testDecodeMepLbCreateMepMac() throws JsonProcessingException, IOException { + String loopbackString = "{\"loopback\": { " + + "\"remoteMepMac\": \"AA:BB:CC:DD:EE:FF\" }}"; + InputStream input = new ByteArrayInputStream( + loopbackString.getBytes(StandardCharsets.UTF_8)); + JsonNode cfg = mapper.readTree(input); + MepLbCreate mepLbCreate = context + .codec(MepLbCreate.class).decode((ObjectNode) cfg, context); + + assertNull(mepLbCreate.remoteMepId()); + assertEquals("AA:BB:CC:DD:EE:FF", mepLbCreate.remoteMepAddress().toString()); + assertNull(mepLbCreate.dataTlvHex()); + } +} diff --git a/apps/cfm/src/test/java/org/onosproject/cfm/web/MepLbEntryCodecTest.java b/apps/cfm/src/test/java/org/onosproject/cfm/web/MepLbEntryCodecTest.java new file mode 100644 index 0000000000..844e4a2809 --- /dev/null +++ b/apps/cfm/src/test/java/org/onosproject/cfm/web/MepLbEntryCodecTest.java @@ -0,0 +1,57 @@ +/* + * 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.cfm.web; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.Test; +import org.onosproject.cfm.CfmCodecContext; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMepLbEntry; +import org.onosproject.incubator.net.l2monitoring.cfm.MepLbEntry; + +import com.fasterxml.jackson.databind.ObjectMapper; + +public class MepLbEntryCodecTest { + ObjectMapper mapper; + CfmCodecContext context; + + @Before + public void setUp() throws Exception { + mapper = new ObjectMapper(); + context = new CfmCodecContext(); + } + + @Test + public void testEncodeMepLbEntryCodecContext() { + MepLbEntry mepLbEntry1 = DefaultMepLbEntry.builder() + .countLbrMacMisMatch(987654321L) + .countLbrReceived(987654322L) + .countLbrTransmitted(987654323L) + .countLbrValidInOrder(987654324L) + .countLbrValidOutOfOrder(987654325L) + .nextLbmIdentifier(987654326L) + .build(); + + assertEquals(987654321L, mepLbEntry1.countLbrMacMisMatch()); + assertEquals(987654322L, mepLbEntry1.countLbrReceived()); + assertEquals(987654323L, mepLbEntry1.countLbrTransmitted()); + assertEquals(987654324L, mepLbEntry1.countLbrValidInOrder()); + assertEquals(987654325L, mepLbEntry1.countLbrValidOutOfOrder()); + assertEquals(987654326L, mepLbEntry1.nextLbmIdentifier()); + } + +} diff --git a/apps/cfm/src/test/java/org/onosproject/cfm/web/MepLtCreateCodecTest.java b/apps/cfm/src/test/java/org/onosproject/cfm/web/MepLtCreateCodecTest.java new file mode 100644 index 0000000000..3e0ec46dfa --- /dev/null +++ b/apps/cfm/src/test/java/org/onosproject/cfm/web/MepLtCreateCodecTest.java @@ -0,0 +1,104 @@ +/* + * 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.cfm.web; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.junit.Before; +import org.junit.Test; +import org.onosproject.cfm.CfmCodecContext; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMepLtCreate; +import org.onosproject.incubator.net.l2monitoring.cfm.MepLtCreate; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.BitSet; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +public class MepLtCreateCodecTest { + ObjectMapper mapper; + CfmCodecContext context; + + @Before + public void setUp() throws Exception { + mapper = new ObjectMapper(); + context = new CfmCodecContext(); + } + + @Test + public void testDecodeMepLtCreateMepId() throws JsonProcessingException, IOException { + String linktraceString = "{\"linktrace\": { " + + "\"remoteMepId\": 20," + + "\"defaultTtl\": 21," + + "\"transmitLtmFlags\": \"use-fdb-only\"}}"; + + InputStream input = new ByteArrayInputStream( + linktraceString.getBytes(StandardCharsets.UTF_8)); + JsonNode cfg = mapper.readTree(input); + MepLtCreate mepLtCreate = context + .codec(MepLtCreate.class).decode((ObjectNode) cfg, context); + + assertNull(mepLtCreate.remoteMepAddress()); + assertEquals(20, mepLtCreate.remoteMepId().id().shortValue()); + assertEquals(21, mepLtCreate.defaultTtl().intValue()); + assertEquals(BitSet.valueOf(new byte[]{1}), mepLtCreate.transmitLtmFlags()); + } + + @Test + public void testDecodeMepLtCreateInvalidTransmitLtmFlags() + throws JsonProcessingException, IOException { + String linktraceString = "{\"linktrace\": { " + + "\"remoteMepId\": 20," + + "\"transmitLtmFlags\": \"1\"}}"; + + InputStream input = new ByteArrayInputStream( + linktraceString.getBytes(StandardCharsets.UTF_8)); + JsonNode cfg = mapper.readTree(input); + try { + context.codec(MepLtCreate.class).decode((ObjectNode) cfg, context); + } catch (IllegalArgumentException e) { + assertEquals("Expecting value 'use-fdb-only' or '' " + + "for transmitLtmFlags", e.getMessage()); + } + } + + @Test + public void testEncodeMepLtCreate() { + MepId mepId1 = MepId.valueOf((short) 1); + MepLtCreate mepLtCreate1 = DefaultMepLtCreate + .builder(mepId1) + .defaultTtl((short) 20) + .transmitLtmFlags(BitSet.valueOf(new byte[]{1})) + .build(); + + ObjectMapper mapper = new ObjectMapper(); + CfmCodecContext context = new CfmCodecContext(); + ObjectNode node = mapper.createObjectNode(); + node.set("linktrace", context.codec(MepLtCreate.class).encode(mepLtCreate1, context)); + + assertEquals("{\"linktrace\":{" + + "\"remoteMepId\":1," + + "\"defaultTtl\":20," + + "\"transmitLtmFlags\":\"use-fdb-only\"}}", node.toString()); + } +} diff --git a/apps/cfm/src/test/java/org/onosproject/cfm/web/RemoteMepEntryCodecTest.java b/apps/cfm/src/test/java/org/onosproject/cfm/web/RemoteMepEntryCodecTest.java new file mode 100644 index 0000000000..7ad77ac0ac --- /dev/null +++ b/apps/cfm/src/test/java/org/onosproject/cfm/web/RemoteMepEntryCodecTest.java @@ -0,0 +1,91 @@ +/* + * 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.cfm.web; + +import static org.junit.Assert.assertEquals; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.Iterator; + +import org.junit.Before; +import org.junit.Test; +import org.onlab.packet.MacAddress; +import org.onosproject.cfm.CfmCodecContext; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultRemoteMepEntry; +import org.onosproject.incubator.net.l2monitoring.cfm.RemoteMepEntry; +import org.onosproject.incubator.net.l2monitoring.cfm.RemoteMepEntry.InterfaceStatusTlvType; +import org.onosproject.incubator.net.l2monitoring.cfm.RemoteMepEntry.PortStatusTlvType; +import org.onosproject.incubator.net.l2monitoring.cfm.RemoteMepEntry.RemoteMepState; +import org.onosproject.incubator.net.l2monitoring.cfm.SenderIdTlv.SenderIdTlvType; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; + +public class RemoteMepEntryCodecTest { + ObjectMapper mapper; + CfmCodecContext context; + RemoteMepEntry remoteMep1; + + @Before + public void setUp() throws Exception, CfmConfigException { + mapper = new ObjectMapper(); + context = new CfmCodecContext(); + remoteMep1 = DefaultRemoteMepEntry + .builder(MepId.valueOf((short) 10), RemoteMepState.RMEP_OK) + .failedOrOkTime(Duration.ofMillis(546546546L)) + .interfaceStatusTlvType(InterfaceStatusTlvType.IS_LOWERLAYERDOWN) + .macAddress(MacAddress.IPV4_MULTICAST) + .portStatusTlvType(PortStatusTlvType.PS_NO_STATUS_TLV) + .rdi(true) + .senderIdTlvType(SenderIdTlvType.SI_NETWORK_ADDRESS) + .build(); + } + + @Test + public void testEncodeRemoteMepEntryCodecContext() { + ObjectNode node = mapper.createObjectNode(); + node.set("remoteMep", context.codec(RemoteMepEntry.class) + .encode(remoteMep1, context)); + + assertEquals(10, node.get("remoteMep").get("remoteMepId").asInt()); + } + + @Test + public void testEncodeIterableOfRemoteMepEntryCodecContext() + throws CfmConfigException { + RemoteMepEntry remoteMep2 = DefaultRemoteMepEntry + .builder(MepId.valueOf((short) 20), RemoteMepState.RMEP_IDLE) + .build(); + + ArrayList remoteMeps = new ArrayList<>(); + remoteMeps.add(remoteMep1); + remoteMeps.add(remoteMep2); + + ObjectNode node = mapper.createObjectNode(); + node.set("remoteMep", context.codec(RemoteMepEntry.class) + .encode(remoteMeps, context)); + + Iterator an = node.get("remoteMep").elements(); + while (an.hasNext()) { + JsonNode jn = an.next(); + assertEquals("RMEP_", jn.get("remoteMepState").asText().substring(0, 5)); + } + } +} diff --git a/apps/cfm/src/test/java/org/onosproject/soam/impl/DmWebResourceTest.java b/apps/cfm/src/test/java/org/onosproject/soam/impl/DmWebResourceTest.java new file mode 100644 index 0000000000..702bc090b9 --- /dev/null +++ b/apps/cfm/src/test/java/org/onosproject/soam/impl/DmWebResourceTest.java @@ -0,0 +1,299 @@ +/* + * 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.soam.impl; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.junit.Before; +import org.junit.Test; +import org.onlab.osgi.ServiceDirectory; +import org.onlab.osgi.TestServiceDirectory; +import org.onlab.rest.BaseResource; +import org.onosproject.cfm.CfmCodecContext; +import org.onosproject.cfm.impl.CfmResourceTest; +import org.onosproject.codec.CodecService; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMepEntry; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep; +import org.onosproject.incubator.net.l2monitoring.cfm.MepEntry; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepService; +import org.onosproject.incubator.net.l2monitoring.soam.SoamConfigException; +import org.onosproject.incubator.net.l2monitoring.soam.SoamId; +import org.onosproject.incubator.net.l2monitoring.soam.SoamService; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DefaultDelayMeasurementEntry; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DefaultDelayMeasurementStatCurrent; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementEntry; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStatCurrent; +import org.onosproject.net.DeviceId; +import org.onosproject.net.PortNumber; + +import javax.ws.rs.InternalServerErrorException; +import javax.ws.rs.client.Entity; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.Response; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.time.Duration; +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; + +import static junit.framework.TestCase.fail; +import static org.easymock.EasyMock.*; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +public class DmWebResourceTest extends CfmResourceTest { + private final CfmMepService mepService = createMock(CfmMepService.class); + private final SoamService soamService = createMock(SoamService.class); + + private static final MdId MDNAME1 = MdIdCharStr.asMdId("md-1"); + private static final MaIdShort MANAME1 = MaIdCharStr.asMaId("ma-1-1"); + private static final MepId MEPID1 = MepId.valueOf((short) 1); + private static final SoamId DM1 = SoamId.valueOf(1); + private static final SoamId DM2 = SoamId.valueOf(2); + + private DelayMeasurementEntry dm1; + private DelayMeasurementEntry dm2; + + private final Instant now = Instant.now(); + + @Before + public void setUpTest() throws CfmConfigException, SoamConfigException { + CfmCodecContext context = new CfmCodecContext(); + ServiceDirectory testDirectory = new TestServiceDirectory() + .add(CfmMepService.class, mepService) + .add(SoamService.class, soamService) + .add(CodecService.class, context.codecManager()); + BaseResource.setServiceDirectory(testDirectory); + + DelayMeasurementStatCurrent.DmStatCurrentBuilder dmCurrBuilder1 = + (DelayMeasurementStatCurrent.DmStatCurrentBuilder) + DefaultDelayMeasurementStatCurrent + .builder(Duration.ofMinutes(1), false) + .startTime(now) + .frameDelayBackwardAvg(Duration.ofMillis(10)) + .frameDelayForwardAvg(Duration.ofMillis(11)) + .frameDelayRangeBackwardAvg(Duration.ofMillis(12)); + + dm1 = DefaultDelayMeasurementEntry.builder(DM1, + DelayMeasurementCreate.DmType.DMDMM, + DelayMeasurementCreate.Version.Y17312008, + MepId.valueOf((short) 2), + Mep.Priority.PRIO1) + .sessionStatus(DelayMeasurementEntry.SessionStatus.ACTIVE) + .frameDelayTwoWay(Duration.ofMillis(40)) + .frameDelayBackward(Duration.ofMillis(30)) + .frameDelayForward(Duration.ofMillis(10)) + .interFrameDelayVariationTwoWay(Duration.ofMillis(8)) + .interFrameDelayVariationBackward(Duration.ofMillis(3)) + .interFrameDelayVariationForward(Duration.ofMillis(5)) + .currentResult((DelayMeasurementStatCurrent) dmCurrBuilder1.build()) + .build(); + + dm2 = DefaultDelayMeasurementEntry.builder(DM2, + DelayMeasurementCreate.DmType.DMDMM, + DelayMeasurementCreate.Version.Y17312011, + MepId.valueOf((short) 2), + Mep.Priority.PRIO2) + .build(); + } + + @Test + public void testGetAllDmsForMep() throws CfmConfigException, SoamConfigException { + + List dmList = new ArrayList<>(); + dmList.add(dm1); + dmList.add(dm2); + + expect(soamService.getAllDms(MDNAME1, MANAME1, MEPID1)).andReturn(dmList).anyTimes(); + replay(soamService); + + final WebTarget wt = target(); + final String response = wt.path("md/" + MDNAME1.mdName() + "/ma/" + + MANAME1.maName() + "/mep/" + MEPID1.value() + "/dm") + .request().get(String.class); + + assertThat(response, is("{\"dms\":[[" + + "{" + + "\"dmId\":\"1\"," + + "\"sessionStatus\":\"ACTIVE\"," + + "\"frameDelayTwoWay\":\"PT0.04S\"," + + "\"frameDelayForward\":\"PT0.01S\"," + + "\"frameDelayBackward\":\"PT0.03S\"," + + "\"interFrameDelayVariationTwoWay\":\"PT0.008S\"," + + "\"interFrameDelayVariationForward\":\"PT0.005S\"," + + "\"interFrameDelayVariationBackward\":\"PT0.003S\"," + + "\"dmCfgType\":\"DMDMM\"," + + "\"version\":\"Y17312008\"," + + "\"remoteMepId\":2," + + "\"priority\":\"PRIO1\"," + + "\"measurementsEnabled\":[]," + + "\"current\":{" + + "\"startTime\":\"" + now + "\"," + + "\"elapsedTime\":\"PT1M\"," + + "\"suspectStatus\":\"false\"," + + "\"frameDelayForwardAvg\":\"PT0.011S\"," + + "\"frameDelayBackwardAvg\":\"PT0.01S\"," + + "\"frameDelayRangeBackwardAvg\":\"PT0.012S\"" + + "}," + + "\"historic\":[]" + + "},{" + + "\"dmId\":\"2\"," + + "\"dmCfgType\":\"DMDMM\"," + + "\"version\":\"Y17312011\"," + + "\"remoteMepId\":2," + + "\"priority\":\"PRIO2\"," + + "\"measurementsEnabled\":[]," + + "\"historic\":[]}]]" + + "}")); + } + + @Test + public void testGetAllDmsForMepEmpty() throws CfmConfigException, SoamConfigException { + + List dmListEmpty = new ArrayList<>(); + + expect(soamService.getAllDms(MDNAME1, MANAME1, MEPID1)).andReturn(dmListEmpty).anyTimes(); + replay(soamService); + + final WebTarget wt = target(); + final String response = wt.path("md/" + MDNAME1.mdName() + "/ma/" + + MANAME1.maName() + "/mep/" + MEPID1.value() + "/dm") + .request().get(String.class); + + assertThat(response, is("{\"dms\":[[]]}")); + } + + @Test + public void testGetDm() throws CfmConfigException, SoamConfigException { + + expect(soamService.getDm(MDNAME1, MANAME1, MEPID1, DM1)).andReturn(dm1).anyTimes(); + replay(soamService); + + final WebTarget wt = target(); + final String response = wt.path("md/" + MDNAME1.mdName() + "/ma/" + + MANAME1.maName() + "/mep/" + MEPID1.value() + "/dm/" + DM1.value()) + .request().get(String.class); + + assertThat(response, is("{\"dm\":" + + "{" + + "\"dmId\":\"1\"," + + "\"sessionStatus\":\"ACTIVE\"," + + "\"frameDelayTwoWay\":\"PT0.04S\"," + + "\"frameDelayForward\":\"PT0.01S\"," + + "\"frameDelayBackward\":\"PT0.03S\"," + + "\"interFrameDelayVariationTwoWay\":\"PT0.008S\"," + + "\"interFrameDelayVariationForward\":\"PT0.005S\"," + + "\"interFrameDelayVariationBackward\":\"PT0.003S\"," + + "\"dmCfgType\":\"DMDMM\"," + + "\"version\":\"Y17312008\"," + + "\"remoteMepId\":2," + + "\"priority\":\"PRIO1\"," + + "\"measurementsEnabled\":[]," + + "\"current\":{" + + "\"startTime\":\"" + now + "\"," + + "\"elapsedTime\":\"PT1M\"," + + "\"suspectStatus\":\"false\"," + + "\"frameDelayForwardAvg\":\"PT0.011S\"," + + "\"frameDelayBackwardAvg\":\"PT0.01S\"," + + "\"frameDelayRangeBackwardAvg\":\"PT0.012S\"" + + "}," + + "\"historic\":[]" + + "}}")); + } + + @Test + public void testGetDmInvalid() throws CfmConfigException, SoamConfigException, IOException { + + SoamId dm3 = SoamId.valueOf(3); + + expect(soamService.getDm(MDNAME1, MANAME1, MEPID1, dm3)).andReturn(null).anyTimes(); + replay(soamService); + + final WebTarget wt = target(); + try { + final String response = wt.path("md/" + MDNAME1.mdName() + "/ma/" + + MANAME1.maName() + "/mep/" + MEPID1.value() + "/dm/" + dm3.value()) + .request().get(String.class); + fail("Expecting excpetion"); + } catch (InternalServerErrorException e) { + ByteArrayInputStream is = (ByteArrayInputStream) e.getResponse().getEntity(); + BufferedReader br = new BufferedReader(new InputStreamReader(is)); + String line = null; + StringBuffer sb = new StringBuffer(); + while ((line = br.readLine()) != null) { + sb.append(line); + } + assertEquals("{ \"failure\":\"DM md-1/ma-1-1/1/3 not found\" }", sb.toString()); + } + } + + @Test + public void testAbortDm() { + + final WebTarget wt = target(); + final Response response = wt.path("md/" + MDNAME1.mdName() + "/ma/" + + MANAME1.maName() + "/mep/" + MEPID1.value() + "/dm/" + DM1.value()) + .request().delete(); + + assertEquals(200, response.getStatus()); + } + + @Test + public void testCreateDm() throws CfmConfigException, SoamConfigException { + MepEntry mep1 = DefaultMepEntry.builder(MEPID1, DeviceId.deviceId("netconf:1.2.3.4:830"), + PortNumber.portNumber(1), Mep.MepDirection.UP_MEP, MDNAME1, MANAME1).buildEntry(); + + expect(mepService.getMep(MDNAME1, MANAME1, MEPID1)).andReturn(mep1).anyTimes(); + replay(mepService); + + ObjectMapper mapper = new ObjectMapper(); + CfmCodecContext context = new CfmCodecContext(); + ObjectNode node = mapper.createObjectNode(); + node.set("dm", context.codec(DelayMeasurementCreate.class).encode(dm1, context)); + + final WebTarget wt = target(); + final Response response = wt.path("md/" + MDNAME1.mdName() + "/ma/" + + MANAME1.maName() + "/mep/" + MEPID1.value() + "/dm") + .request().post(Entity.json(node.toString())); + + assertEquals(201, response.getStatus()); + } + + @Test + public void testClearDmHistory() { + + final WebTarget wt = target(); + final Response response = wt.path("md/" + MDNAME1.mdName() + "/ma/" + + MANAME1.maName() + "/mep/" + MEPID1.value() + "/dm/" + DM1.value() + + "/clear-history") + .request().put(Entity.json("")); + + assertEquals(200, response.getStatus()); + } + +} diff --git a/apps/cfm/src/test/java/org/onosproject/soam/impl/LmWebResourceTest.java b/apps/cfm/src/test/java/org/onosproject/soam/impl/LmWebResourceTest.java new file mode 100644 index 0000000000..9dd70e6b47 --- /dev/null +++ b/apps/cfm/src/test/java/org/onosproject/soam/impl/LmWebResourceTest.java @@ -0,0 +1,262 @@ +/* + * 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.soam.impl; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.junit.Before; +import org.junit.Test; +import org.onlab.osgi.ServiceDirectory; +import org.onlab.osgi.TestServiceDirectory; +import org.onlab.rest.BaseResource; +import org.onosproject.cfm.CfmCodecContext; +import org.onosproject.cfm.impl.CfmResourceTest; +import org.onosproject.codec.CodecService; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMepEntry; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep; +import org.onosproject.incubator.net.l2monitoring.cfm.MepEntry; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepService; +import org.onosproject.incubator.net.l2monitoring.soam.MilliPct; +import org.onosproject.incubator.net.l2monitoring.soam.SoamConfigException; +import org.onosproject.incubator.net.l2monitoring.soam.SoamId; +import org.onosproject.incubator.net.l2monitoring.soam.SoamService; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate; +import org.onosproject.incubator.net.l2monitoring.soam.loss.DefaultLmEntry; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementCreate; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementEntry; +import org.onosproject.net.DeviceId; +import org.onosproject.net.PortNumber; + +import javax.ws.rs.InternalServerErrorException; +import javax.ws.rs.client.Entity; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.Response; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; + +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +public class LmWebResourceTest extends CfmResourceTest { + private final CfmMepService mepService = createMock(CfmMepService.class); + private final SoamService soamService = createMock(SoamService.class); + + private static final MdId MDNAME1 = MdIdCharStr.asMdId("md-1"); + private static final MaIdShort MANAME1 = MaIdCharStr.asMaId("ma-1-1"); + private static final MepId MEPID1 = MepId.valueOf((short) 1); + private static final SoamId LMID1 = SoamId.valueOf(1); + private static final SoamId LMID2 = SoamId.valueOf(2); + + private LossMeasurementEntry lm1; + private LossMeasurementEntry lm2; + + private final Instant now = Instant.now(); + + @Before + public void setUpTest() throws CfmConfigException, SoamConfigException { + CfmCodecContext context = new CfmCodecContext(); + ServiceDirectory testDirectory = new TestServiceDirectory() + .add(CfmMepService.class, mepService) + .add(SoamService.class, soamService) + .add(CodecService.class, context.codecManager()); + BaseResource.setServiceDirectory(testDirectory); + + lm1 = DefaultLmEntry.builder( + DelayMeasurementCreate.Version.Y17312008, + MepId.valueOf((short) 10), + Mep.Priority.PRIO1, + LossMeasurementCreate.LmType.LMLMM, + LMID1) + .build(); + lm2 = DefaultLmEntry.builder( + DelayMeasurementCreate.Version.Y17312011, + MepId.valueOf((short) 10), + Mep.Priority.PRIO2, + LossMeasurementCreate.LmType.LMLMM, + LMID2) + .measuredAvailabilityBackwardStatus(LossMeasurementEntry.AvailabilityType.AVAILABLE) + .measuredAvailabilityForwardStatus(LossMeasurementEntry.AvailabilityType.UNKNOWN) + .measuredBackwardFlr(MilliPct.ofPercent(49.9f)) + .measuredForwardFlr(MilliPct.ofRatio(0.51f)) + .measuredBackwardLastTransitionTime(now) + .measuredForwardLastTransitionTime(now) + .build(); + + } + + @Test + public void testGetAllLmsForMep() throws CfmConfigException, SoamConfigException { + List lmList = new ArrayList<>(); + lmList.add(lm1); + lmList.add(lm2); + + expect(soamService.getAllLms(MDNAME1, MANAME1, MEPID1)).andReturn(lmList).anyTimes(); + replay(soamService); + + final WebTarget wt = target(); + final String response = wt.path("md/" + MDNAME1.mdName() + "/ma/" + + MANAME1.maName() + "/mep/" + MEPID1.value() + "/lm") + .request().get(String.class); + + assertThat(response, is("{\"lms\":[[" + + "{" + + "\"lmId\":\"1\"," + + "\"lmCfgType\":\"LMLMM\"," + + "\"version\":\"Y17312008\"," + + "\"remoteMepId\":10," + + "\"priority\":\"PRIO1\"," + + "\"countersEnabled\":[]," + + "\"measurementHistories\":[]," + + "\"availabilityHistories\":[]" + + "},{" + + "\"lmId\":\"2\"," + + "\"measuredForwardFlr\":51.0," + + "\"measuredBackwardFlr\":49.9," + + "\"measuredAvailabilityForwardStatus\":\"UNKNOWN\"," + + "\"measuredAvailabilityBackwardStatus\":\"AVAILABLE\"," + + "\"measuredForwardLastTransitionTime\":\"" + now + "\"," + + "\"measuredBackwardLastTransitionTime\":\"" + now + "\"," + + "\"lmCfgType\":\"LMLMM\"," + + "\"version\":\"Y17312011\"," + + "\"remoteMepId\":10," + + "\"priority\":\"PRIO2\"," + + "\"countersEnabled\":[]," + + "\"measurementHistories\":[]," + + "\"availabilityHistories\":[]" + + "}]]}")); + } + + @Test + public void testGetAllLmsForMepEmpty() throws CfmConfigException, SoamConfigException { + List lmList = new ArrayList<>(); + + expect(soamService.getAllLms(MDNAME1, MANAME1, MEPID1)).andReturn(lmList).anyTimes(); + replay(soamService); + + final WebTarget wt = target(); + final String response = wt.path("md/" + MDNAME1.mdName() + "/ma/" + + MANAME1.maName() + "/mep/" + MEPID1.value() + "/lm") + .request().get(String.class); + + assertThat(response, is("{\"lms\":[[]]}")); + } + + @Test + public void testGetLm() throws CfmConfigException, SoamConfigException { + + expect(soamService.getLm(MDNAME1, MANAME1, MEPID1, LMID1)).andReturn(lm1).anyTimes(); + replay(soamService); + + final WebTarget wt = target(); + final String response = wt.path("md/" + MDNAME1.mdName() + "/ma/" + + MANAME1.maName() + "/mep/" + MEPID1.value() + "/lm/" + LMID1.value()) + .request().get(String.class); + + assertThat(response, is("{\"lm\":" + + "{" + + "\"lmId\":\"1\"," + + "\"lmCfgType\":\"LMLMM\"," + + "\"version\":\"Y17312008\"," + + "\"remoteMepId\":10," + + "\"priority\":\"PRIO1\"," + + "\"countersEnabled\":[]," + + "\"measurementHistories\":[]," + + "\"availabilityHistories\":[]" + + "}}")); + } + + @Test + public void testGetLmEmpty() throws CfmConfigException, SoamConfigException, IOException { + SoamId lmId3 = SoamId.valueOf(3); + expect(soamService.getLm(MDNAME1, MANAME1, MEPID1, lmId3)) + .andReturn(null).anyTimes(); + replay(soamService); + + final WebTarget wt = target(); + try { + final String response = wt.path("md/" + MDNAME1.mdName() + "/ma/" + + MANAME1.maName() + "/mep/" + MEPID1.value() + "/lm/" + lmId3.value()) + .request().get(String.class); + } catch (InternalServerErrorException e) { + ByteArrayInputStream is = (ByteArrayInputStream) e.getResponse().getEntity(); + BufferedReader br = new BufferedReader(new InputStreamReader(is)); + String line = null; + StringBuffer sb = new StringBuffer(); + while ((line = br.readLine()) != null) { + sb.append(line); + } + assertEquals("{ \"failure\":\"LM md-1/ma-1-1/1/3 not found\" }", + sb.toString()); + } + } + + @Test + public void testAbortLm() { + + final WebTarget wt = target(); + final Response response = wt.path("md/" + MDNAME1.mdName() + "/ma/" + + MANAME1.maName() + "/mep/" + MEPID1.value() + "/lm/" + LMID1.value()) + .request().delete(); + assertEquals(200, response.getStatus()); + } + + @Test + public void testCreateLm() throws CfmConfigException, SoamConfigException { + MepEntry mep1 = DefaultMepEntry.builder(MEPID1, DeviceId.deviceId("netconf:1.2.3.4:830"), + PortNumber.portNumber(1), Mep.MepDirection.UP_MEP, MDNAME1, MANAME1).buildEntry(); + + expect(mepService.getMep(MDNAME1, MANAME1, MEPID1)).andReturn(mep1).anyTimes(); + replay(mepService); + + ObjectMapper mapper = new ObjectMapper(); + CfmCodecContext context = new CfmCodecContext(); + ObjectNode node = mapper.createObjectNode(); + node.set("lm", context.codec(LossMeasurementCreate.class).encode(lm1, context)); + + final WebTarget wt = target(); + final Response response = wt.path("md/" + MDNAME1.mdName() + "/ma/" + + MANAME1.maName() + "/mep/" + MEPID1.value() + "/lm") + .request().post(Entity.json(node.toString())); + assertEquals(201, response.getStatus()); + } + + @Test + public void testClearLmHistory() { + + final WebTarget wt = target(); + final Response response = wt.path("md/" + MDNAME1.mdName() + "/ma/" + + MANAME1.maName() + "/mep/" + MEPID1.value() + "/lm/" + LMID1.value() + + "/clear-history") + .request().put(Entity.json("")); + + assertEquals(200, response.getStatus()); + } +} diff --git a/apps/cfm/src/test/java/org/onosproject/soam/web/DmCreateCodecTest.java b/apps/cfm/src/test/java/org/onosproject/soam/web/DmCreateCodecTest.java new file mode 100644 index 0000000000..2f31310415 --- /dev/null +++ b/apps/cfm/src/test/java/org/onosproject/soam/web/DmCreateCodecTest.java @@ -0,0 +1,129 @@ +/* + * 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.soam.web; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.time.Duration; + +import org.junit.Before; +import org.junit.Test; +import org.onosproject.cfm.CfmCodecContext; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep.Priority; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.soam.SoamConfigException; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DefaultDelayMeasurementCreate; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.DmCreateBuilder; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.DmType; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.MeasurementOption; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.Version; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +public class DmCreateCodecTest { + ObjectMapper mapper; + CfmCodecContext context; + + @Before + public void setUp() throws Exception { + mapper = new ObjectMapper(); + context = new CfmCodecContext(); + } + + @Test + public void testDecodeObjectNodeCodecContext1() + throws JsonProcessingException, IOException { + String moStr = "{\"dm\": {}}"; + + InputStream input = new ByteArrayInputStream( + moStr.getBytes(StandardCharsets.UTF_8)); + JsonNode cfg = mapper.readTree(input); + + try { + context.codec(DelayMeasurementCreate.class) + .decode((ObjectNode) cfg, context); + fail("Expecting an exception"); + } catch (IllegalArgumentException e) { + assertEquals("remoteMepId is required", e.getMessage()); + } + } + + @Test + public void testDecodeObjectNodeCodecContext2() + throws JsonProcessingException, IOException { + String moStr = "{\"dm\": {" + + "\"version\":\"Y17312008\"," + + "\"dmType\":\"DMDMM\"," + + "\"remoteMepId\":12," + + "\"priority\":\"PRIO6\"," + + "\"measurementsEnabled\" :" + + "[\"FRAME_DELAY_RANGE_BACKWARD_AVERAGE\", " + + "\"INTER_FRAME_DELAY_VARIATION_FORWARD_AVERAGE\"]" + + "}}"; + + InputStream input = new ByteArrayInputStream( + moStr.getBytes(StandardCharsets.UTF_8)); + JsonNode cfg = mapper.readTree(input); + + DelayMeasurementCreate dmCreate = context + .codec(DelayMeasurementCreate.class) + .decode((ObjectNode) cfg, context); + + assertEquals(Version.Y17312008, dmCreate.version()); + assertEquals(DmType.DMDMM, dmCreate.dmCfgType()); + assertEquals(12, dmCreate.remoteMepId().id().shortValue()); + } + + @Test + public void testEncodeDelayMeasurementCreateCodecContext() + throws SoamConfigException { + DmCreateBuilder builder = DefaultDelayMeasurementCreate + .builder(DmType.DM1DMRX, Version.Y17312011, + MepId.valueOf((short) 16), Priority.PRIO5); + builder.addToMeasurementsEnabled( + MeasurementOption.FRAME_DELAY_BACKWARD_MAX); + builder.addToMeasurementsEnabled( + MeasurementOption.FRAME_DELAY_TWO_WAY_MAX); + builder.addToMeasurementsEnabled( + MeasurementOption.INTER_FRAME_DELAY_VARIATION_BACKWARD_BINS); + builder = (DmCreateBuilder) builder.messagePeriod(Duration.ofMillis(100)); + builder = (DmCreateBuilder) builder.frameSize((short) 1200); + + ObjectNode node = mapper.createObjectNode(); + node.set("dm", context.codec(DelayMeasurementCreate.class) + .encode(builder.build(), context)); + + assertEquals(DmType.DM1DMRX.name(), node.get("dm").get("dmCfgType").asText()); + assertEquals(Version.Y17312011.name(), node.get("dm").get("version").asText()); + assertEquals(16, node.get("dm").get("remoteMepId").asInt()); + assertEquals(Priority.PRIO5.name(), node.get("dm").get("priority").asText()); + assertEquals(100, node.get("dm").get("messagePeriodMs").asInt()); + assertEquals(1200, node.get("dm").get("frameSize").asInt()); + + assertEquals(3, ((ArrayNode) node.get("dm").get("measurementsEnabled")).size()); + } + +} diff --git a/apps/cfm/src/test/java/org/onosproject/soam/web/DmEntryCodecTest.java b/apps/cfm/src/test/java/org/onosproject/soam/web/DmEntryCodecTest.java new file mode 100644 index 0000000000..028fad822d --- /dev/null +++ b/apps/cfm/src/test/java/org/onosproject/soam/web/DmEntryCodecTest.java @@ -0,0 +1,121 @@ +/* + * 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.soam.web; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; +import java.time.Duration; +import java.util.ArrayList; +import java.util.Collection; + +import org.junit.Before; +import org.junit.Test; +import org.onosproject.cfm.CfmCodecContext; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep.Priority; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.soam.SoamConfigException; +import org.onosproject.incubator.net.l2monitoring.soam.SoamId; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DefaultDelayMeasurementEntry; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.DmType; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.MeasurementOption; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.Version; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementEntry; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementEntry.DmEntryBuilder; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementEntry.SessionStatus; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.ObjectNode; + +public class DmEntryCodecTest { + ObjectMapper mapper; + CfmCodecContext context; + DelayMeasurementEntry dmEntry1; + + @Before + public void setUp() throws Exception, SoamConfigException { + mapper = new ObjectMapper(); + context = new CfmCodecContext(); + DmEntryBuilder builder = DefaultDelayMeasurementEntry + .builder(SoamId.valueOf(12), DmType.DM1DMTX, + Version.Y17312008, MepId.valueOf((short) 10), Priority.PRIO4); + builder = builder.sessionStatus(SessionStatus.NOT_ACTIVE); + builder = builder.frameDelayTwoWay(Duration.ofNanos(101 * 1000)); + builder = builder.frameDelayForward(Duration.ofNanos(102 * 1000)); + builder = builder.frameDelayBackward(Duration.ofNanos(103 * 1000)); + builder = builder.interFrameDelayVariationTwoWay(Duration.ofNanos(104 * 1000)); + builder = builder.interFrameDelayVariationForward(Duration.ofNanos(105 * 1000)); + builder = builder.interFrameDelayVariationBackward(Duration.ofNanos(106 * 1000)); + builder.addToMeasurementsEnabled(MeasurementOption.FRAME_DELAY_BACKWARD_MAX); + builder.addToMeasurementsEnabled(MeasurementOption.FRAME_DELAY_TWO_WAY_MAX); + builder.addToMeasurementsEnabled(MeasurementOption.INTER_FRAME_DELAY_VARIATION_BACKWARD_BINS); + + dmEntry1 = builder.build(); + } + + @Test + public void testEncodeDelayMeasurementEntryCodecContext() + throws JsonProcessingException, IOException { + ObjectNode node = mapper.createObjectNode(); + node.set("dm", context.codec(DelayMeasurementEntry.class) + .encode(dmEntry1, context)); + + assertEquals(12, node.get("dm").get("dmId").asInt()); + assertEquals(DmType.DM1DMTX.name(), node.get("dm").get("dmCfgType").asText()); + assertEquals(Version.Y17312008.name(), node.get("dm").get("version").asText()); + assertEquals(10, node.get("dm").get("remoteMepId").asInt()); + assertEquals(3, ((ArrayNode) node.get("dm").get("measurementsEnabled")).size()); + + assertEquals(SessionStatus.NOT_ACTIVE.name(), + node.get("dm").get("sessionStatus").asText()); + assertEquals("PT0.000101S", + node.get("dm").get("frameDelayTwoWay").asText()); + assertEquals("PT0.000102S", + node.get("dm").get("frameDelayForward").asText()); + assertEquals("PT0.000103S", + node.get("dm").get("frameDelayBackward").asText()); + assertEquals("PT0.000104S", + node.get("dm").get("interFrameDelayVariationTwoWay").asText()); + assertEquals("PT0.000105S", + node.get("dm").get("interFrameDelayVariationForward").asText()); + assertEquals("PT0.000106S", + node.get("dm").get("interFrameDelayVariationBackward").asText()); + + } + + @Test + public void testEncodeIterableOfDelayMeasurementEntryCodecContext() + throws SoamConfigException { + DmEntryBuilder builder2 = DefaultDelayMeasurementEntry + .builder(SoamId.valueOf(14), DmType.DM1DMRX, + Version.Y17312011, MepId.valueOf((short) 16), Priority.PRIO5); + builder2.addToMeasurementsEnabled(MeasurementOption.FRAME_DELAY_BACKWARD_MIN); + builder2.addToMeasurementsEnabled(MeasurementOption.FRAME_DELAY_TWO_WAY_MIN); + builder2.addToMeasurementsEnabled(MeasurementOption.INTER_FRAME_DELAY_VARIATION_BACKWARD_MIN); + + Collection dmEntries = new ArrayList<>(); + dmEntries.add(dmEntry1); + dmEntries.add(builder2.build()); + ObjectNode node = mapper.createObjectNode(); + node.set("dm", context.codec(DelayMeasurementEntry.class) + .encode(dmEntries, context)); + + assertEquals(2, ((ArrayNode) node.get("dm")).size()); + } + +} diff --git a/apps/cfm/src/test/java/org/onosproject/soam/web/DmMeasurementOptionCodecTest.java b/apps/cfm/src/test/java/org/onosproject/soam/web/DmMeasurementOptionCodecTest.java new file mode 100644 index 0000000000..4986d5ae61 --- /dev/null +++ b/apps/cfm/src/test/java/org/onosproject/soam/web/DmMeasurementOptionCodecTest.java @@ -0,0 +1,86 @@ +/* + * 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.soam.web; + +import static org.junit.Assert.assertEquals; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; +import org.onosproject.cfm.CfmCodecContext; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.MeasurementOption; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; + +public class DmMeasurementOptionCodecTest { + ObjectMapper mapper; + CfmCodecContext context; + + @Before + public void setUp() throws Exception { + mapper = new ObjectMapper(); + context = new CfmCodecContext(); + } + + @Test + public void testEncodeIterableOfMeasurementOptionCodecContext() { + List moList = new ArrayList<>(); + moList.add(MeasurementOption.FRAME_DELAY_BACKWARD_MAX); + moList.add(MeasurementOption.FRAME_DELAY_FORWARD_BINS); + + ArrayNode an = + context.codec(MeasurementOption.class).encode(moList, context); + + assertEquals(MeasurementOption.FRAME_DELAY_BACKWARD_MAX.toString(), + an.get(0).asText()); + assertEquals(MeasurementOption.FRAME_DELAY_FORWARD_BINS.toString(), + an.get(1).asText()); + } + + @Test + public void testDecodeArrayNodeCodecContext() + throws JsonProcessingException, IOException { + String moStr = "{\"measurementsEnabled\": " + + "[\"FRAME_DELAY_RANGE_BACKWARD_AVERAGE\", " + + "\"INTER_FRAME_DELAY_VARIATION_FORWARD_AVERAGE\"]}"; + InputStream input = new ByteArrayInputStream( + moStr.getBytes(StandardCharsets.UTF_8)); + JsonNode cfg = mapper.readTree(input); + Iterable moIter = context + .codec(MeasurementOption.class) + .decode((ArrayNode) cfg.get("measurementsEnabled"), context); + + Iterator source = moIter.iterator(); + List moList = new ArrayList<>(); + source.forEachRemaining(moList::add); + + assertEquals(MeasurementOption.FRAME_DELAY_RANGE_BACKWARD_AVERAGE.toString(), + moList.get(0).name()); + assertEquals(MeasurementOption.INTER_FRAME_DELAY_VARIATION_FORWARD_AVERAGE.toString(), + moList.get(1).name()); + } + +} diff --git a/apps/cfm/src/test/resources/examples/CreateDM_Mep10.json b/apps/cfm/src/test/resources/examples/CreateDM_Mep10.json new file mode 100644 index 0000000000..4b8a962818 --- /dev/null +++ b/apps/cfm/src/test/resources/examples/CreateDM_Mep10.json @@ -0,0 +1,18 @@ +{ + "dm": { + "remoteMepId":20, + "dmCfgType": "DMDMM", + "version": "Y17312008", + "priority": "PRIO1", + "messagePeriodMs": 100, + "startTime": { + "immediate":true + }, + "stopTime": { + "none":true + }, + "frameSize": 1500, + "measurementIntervalMins": 1, + "measurementsEnabled": ["FRAME_DELAY_TWO_WAY_BINS","FRAME_DELAY_TWO_WAY_AVERAGE"] + } +} \ No newline at end of file diff --git a/apps/cfm/src/test/resources/examples/CreateMa1InDomainA.json b/apps/cfm/src/test/resources/examples/CreateMa1InDomainA.json new file mode 100644 index 0000000000..0790aee3fd --- /dev/null +++ b/apps/cfm/src/test/resources/examples/CreateMa1InDomainA.json @@ -0,0 +1,23 @@ +{ + "ma": { + "maName": "ma-vlan-1", + "maNameType": "CHARACTERSTRING", + "maNumericId": 1, + "ccm-interval": "INTERVAL_1S", + "component-list": [ + { "component": { + "component-id":"1", + "tag-type": "VLAN_STAG", + "vid-list": [ + {"vid":1} + ] + } + } + ], + "rmep-list": [ + { "rmep":10 }, + { "rmep":20 }, + { "rmep":30 } + ] + } +} \ No newline at end of file diff --git a/apps/cfm/src/test/resources/examples/CreateMa2InDomainA.json b/apps/cfm/src/test/resources/examples/CreateMa2InDomainA.json new file mode 100644 index 0000000000..67afdbae5e --- /dev/null +++ b/apps/cfm/src/test/resources/examples/CreateMa2InDomainA.json @@ -0,0 +1,22 @@ +{ + "ma": { + "maName": "ma-vlan-2", + "maNameType": "CHARACTERSTRING", + "maNumericId": 2, + "ccm-interval": "INTERVAL_1S", + "component-list": [ + { "component": { + "component-id":"1", + "tag-type": "VLAN_STAG", + "vid-list": [ + {"vid":2} + ] + } + } + ], + "rmep-list": [ + { "rmep":10 }, + { "rmep":20 } + ] + } +} \ No newline at end of file diff --git a/apps/cfm/src/test/resources/examples/CreateMdDomainA.json b/apps/cfm/src/test/resources/examples/CreateMdDomainA.json new file mode 100644 index 0000000000..2dbb761d72 --- /dev/null +++ b/apps/cfm/src/test/resources/examples/CreateMdDomainA.json @@ -0,0 +1,7 @@ +{"md": { + "mdName": "DomainA", + "mdNameType": "CHARACTERSTRING", + "mdLevel": "LEVEL3", + "mdNumeridId": 1 +} +} \ No newline at end of file diff --git a/apps/cfm/src/test/resources/examples/CreateMep10.json b/apps/cfm/src/test/resources/examples/CreateMep10.json new file mode 100644 index 0000000000..3b393c27ff --- /dev/null +++ b/apps/cfm/src/test/resources/examples/CreateMep10.json @@ -0,0 +1,14 @@ +{ + "mep": { + "mepId": 10, + "deviceId": "netconf:192.168.56.10:830", + "port": 0, + "direction": "DOWN_MEP", + "mdName": "DomainA", + "maName": "ma-vlan-1", + "primary-vid": 1, + "administrative-state": true, + "ccm-ltm-priority": 4, + "cci-enabled" :true + } +} \ No newline at end of file diff --git a/apps/cfm/src/test/resources/examples/README.md b/apps/cfm/src/test/resources/examples/README.md new file mode 100644 index 0000000000..3557cff1a2 --- /dev/null +++ b/apps/cfm/src/test/resources/examples/README.md @@ -0,0 +1,12 @@ +Run: + +* curl --user onos:rocks -d @CreateMdDomainA.json http://localhost:8181/onos/cfm/md --header "Content-Type:application/json" +* curl --user onos:rocks -d @CreateMa1InDomainA.json http://localhost:8181/onos/cfm/md/DomainA/ma --header "Content-Type:application/json" +* curl --user onos:rocks -d @CreateMa2InDomainA.json http://localhost:8181/onos/cfm/md/DomainA/ma --header "Content-Type:application/json" +* curl --user onos:rocks http://localhost:8181/onos/cfm/md + +Create a Device that supports CFM Programmable, say at netconf:192.168.56.10:830 +* curl --user onos:rocks -d @CreateMep10.json http://localhost:8181/onos/cfm/md/DomainA/ma/ma-vlan-1/mep --header "Content-Type:application/json" + +Now call the RPC to create a Delay Measurement on that device +* curl --user onos:rocks -X PUT -d @CreateDM_Mep10.json http://localhost:8181/onos/cfm/md/DomainA/ma/ma-vlan-1/mep/10/dm --header "Content-Type:application/json" diff --git a/apps/pom.xml b/apps/pom.xml index 26deeee453..a5dba521d2 100644 --- a/apps/pom.xml +++ b/apps/pom.xml @@ -97,6 +97,7 @@ evpn-route-service l3vpn openstacknetworkingui + cfm diff --git a/drivers/microsemi/BUCK b/drivers/microsemi/BUCK index 379e63d07c..398fff75fa 100644 --- a/drivers/microsemi/BUCK +++ b/drivers/microsemi/BUCK @@ -13,7 +13,8 @@ TEST_DEPS = [ '//lib:TEST_ADAPTERS', '//core/api:onos-api-tests', '//drivers/netconf:onos-drivers-netconf-tests', - '//utils/osgi:onlab-osgi-tests' + '//utils/osgi:onlab-osgi-tests', + '//incubator/net:onos-incubator-net' ] APPS = [ diff --git a/drivers/microsemi/pom.xml b/drivers/microsemi/pom.xml index 645918647b..154768fe54 100644 --- a/drivers/microsemi/pom.xml +++ b/drivers/microsemi/pom.xml @@ -48,6 +48,11 @@ onos-api + + org.onosproject + onos-incubator-api + + org.onosproject onos-yang-model @@ -133,6 +138,12 @@ tests + + org.onosproject + onos-incubator-net + test + + diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/EA1000CfmMepProgrammable.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/EA1000CfmMepProgrammable.java new file mode 100755 index 0000000000..df6844e37b --- /dev/null +++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/EA1000CfmMepProgrammable.java @@ -0,0 +1,610 @@ +/* + * Copyright 2017-present Open Networking Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.drivers.microsemi; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.slf4j.LoggerFactory.getLogger; + +import java.time.Duration; +import java.util.Collection; + +import org.onlab.packet.IpAddress; +import org.onlab.packet.MacAddress; +import org.onlab.packet.VlanId; +import org.onlab.util.HexString; +import org.onosproject.drivers.microsemi.yang.MseaCfmNetconfService; +import org.onosproject.drivers.microsemi.yang.utils.MaNameUtil; +import org.onosproject.incubator.net.l2monitoring.cfm.Component; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMepEntry; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMepLbEntry; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultRemoteMepEntry; +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceAssociation; +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep.MepDirection; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep.Priority; +import org.onosproject.incubator.net.l2monitoring.cfm.MepEntry; +import org.onosproject.incubator.net.l2monitoring.cfm.MepLbCreate; +import org.onosproject.incubator.net.l2monitoring.cfm.MepLbEntry.MepLbEntryBuilder; +import org.onosproject.incubator.net.l2monitoring.cfm.MepLtCreate; +import org.onosproject.incubator.net.l2monitoring.cfm.RemoteMepEntry; +import org.onosproject.incubator.net.l2monitoring.cfm.RemoteMepEntry.InterfaceStatusTlvType; +import org.onosproject.incubator.net.l2monitoring.cfm.RemoteMepEntry.PortStatusTlvType; +import org.onosproject.incubator.net.l2monitoring.cfm.RemoteMepEntry.RemoteMepEntryBuilder; +import org.onosproject.incubator.net.l2monitoring.cfm.RemoteMepEntry.RemoteMepState; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdDomainName; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdMacUint; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdNone; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMdService; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepProgrammable; +import org.onosproject.net.DeviceId; +import org.onosproject.net.PortNumber; +import org.onosproject.net.driver.AbstractHandlerBehaviour; +import org.onosproject.netconf.DatastoreId; +import org.onosproject.netconf.NetconfController; +import org.onosproject.netconf.NetconfException; +import org.onosproject.netconf.NetconfSession; +import org.onosproject.yang.gen.v1.ietfinettypes.rev20130715.ietfinettypes.DomainName; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.MseaCfm; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.MseaCfmOpParam; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.DefaultMefCfm; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.MefCfm; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.abortloopback.AbortLoopbackInput; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.abortloopback.DefaultAbortLoopbackInput; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.faultalarmdefectbitstype.Bits; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.DefaultMaintenanceDomain; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.DefaultMaintenanceAssociation; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.MdNameAndTypeCombo; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.CcmIntervalEnum; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.ComponentList; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.DefaultComponentList; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.DefaultMaintenanceAssociationEndPoint; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.MaNameAndTypeCombo; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.MaintenanceAssociationEndPoint; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.componentlist.TagTypeEnum; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.ContinuityCheck; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.DefaultContinuityCheck; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.InterfaceEnum; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.DefaultMacAddressAndUint; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.DefaultNameCharacterString; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.DefaultNameDomainName; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.DefaultNameNone; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.namedomainname.NameDomainNameUnion; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.remotemepstatetype.RemoteMepStateTypeEnum; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.targetaddressgroup.addresstype.DefaultMacAddress; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.targetaddressgroup.addresstype.DefaultMepId; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitloopback.DefaultTransmitLoopbackInput; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitloopback.TransmitLoopbackInput; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitloopback.transmitloopbackinput.DefaultTargetAddress; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitloopback.transmitloopbackinput.TargetAddress; +import org.onosproject.yang.gen.v1.mseasoamfm.rev20160229.mseasoamfm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.AugmentedMseaCfmMaintenanceAssociationEndPoint; +import org.onosproject.yang.gen.v1.mseasoamfm.rev20160229.mseasoamfm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint; +import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.Identifier45; +import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.MacAddressAndUintStr; +import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.MdLevelType; +import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.MepIdType; +import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.PriorityType; +import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.VlanIdType; +import org.slf4j.Logger; + +/** + * Implementation of CfmMepProgrammable for Microsemi EA1000. + */ +public class EA1000CfmMepProgrammable extends AbstractHandlerBehaviour + implements CfmMepProgrammable { + + private static final int NUMERIC_ID_MAX = 64; + private static final int REMOTEMEPLIST_MIN_COUNT = 2; + private static final int REMOTEMEPLIST_MAX_COUNT = 9; + private static final int COMPONENT_LIST_SIZE = 1; + private static final int VIDLIST_SIZE_MIN = 1; + private static final int MEP_PORT_MIN = 0; + private static final int MEP_PORT_MAX = 1; + private final Logger log = getLogger(getClass()); + + public EA1000CfmMepProgrammable() { + log.debug("Loaded handler behaviour EA1000CfmMepProgrammable"); + } + + @Override + public boolean createMep(MdId mdName, MaIdShort maName, Mep mep) + throws CfmConfigException { + NetconfController controller = checkNotNull(handler().get(NetconfController.class)); + NetconfSession session = controller.getDevicesMap() + .get(handler().data().deviceId()).getSession(); + MseaCfmNetconfService mseaCfmService = + checkNotNull(handler().get(MseaCfmNetconfService.class)); + + MaintenanceAssociationEndPoint yangMep = buildYangMepFromApiMep(mep); + + CfmMdService cfmMdService = checkNotNull(handler().get(CfmMdService.class)); + MaintenanceDomain md = cfmMdService.getMaintenanceDomain(mdName).get(); + MaintenanceAssociation ma = cfmMdService.getMaintenanceAssociation(mdName, maName).get(); + + if (!ma.remoteMepIdList().contains(mep.mepId())) { + throw new CfmConfigException("Mep Id " + mep.mepId() + + " is not present in the remote Mep list for MA " + ma.maId() + + ". This is required for EA1000."); + } else if (md.mdNumericId() <= 0 || md.mdNumericId() > NUMERIC_ID_MAX) { + throw new CfmConfigException("Numeric id of MD " + mdName + " must" + + " be between 1 and 64 inclusive for EA1000"); + } else if (ma.maNumericId() <= 0 || ma.maNumericId() > NUMERIC_ID_MAX) { + throw new CfmConfigException("Numeric id of MA " + maName + " must" + + " be between 1 and 64 inclusive for EA1000"); + } + + org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain + .MaintenanceAssociation yangMa = buildYangMaFromApiMa(ma); + yangMa.addToMaintenanceAssociationEndPoint(yangMep); + + org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm + .mefcfm.MaintenanceDomain yangMd = buildYangMdFromApiMd(md); + yangMd.addToMaintenanceAssociation(yangMa); + + MefCfm mefCfm = new DefaultMefCfm(); + mefCfm.addToMaintenanceDomain(yangMd); + + MseaCfmOpParam mseaCfmOpParam = new MseaCfmOpParam(); + mseaCfmOpParam.mefCfm(mefCfm); + try { + mseaCfmService.setMseaCfm(mseaCfmOpParam, session, DatastoreId.RUNNING); + log.info("Created MEP {} on device {}", mdName + "/" + maName + + "/" + mep.mepId(), handler().data().deviceId()); + return true; + } catch (NetconfException e) { + log.error("Unable to create MEP {}/{}/{} on device {}", + mdName, maName, mep.mepId(), handler().data().deviceId()); + throw new CfmConfigException("Unable to create MEP :" + e.getMessage()); + } + } + + @Override + public Collection getAllMeps(MdId mdName, MaIdShort maName) throws CfmConfigException { + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public MepEntry getMep(MdId mdName, MaIdShort maName, MepId mepId) + throws CfmConfigException { + NetconfController controller = checkNotNull(handler().get(NetconfController.class)); + if (handler().data().deviceId() == null) { + throw new CfmConfigException("Device is not ready - connecting or " + + "disconnected for MEP " + mdName + "/" + maName + "/" + mepId); + } + NetconfSession session = controller.getDevicesMap().get(handler().data().deviceId()).getSession(); + MseaCfmNetconfService mseaCfmService = checkNotNull(handler().get(MseaCfmNetconfService.class)); + + try { + MseaCfm mseacfm = + mseaCfmService.getMepFull(mdName, maName, mepId, session); + for (org.onosproject.yang.gen.v1.mseacfm.rev20160229. + mseacfm.mefcfm.MaintenanceDomain replyMd:mseacfm.mefCfm().maintenanceDomain()) { + for (org.onosproject.yang.gen.v1.mseacfm.rev20160229. + mseacfm.mefcfm.maintenancedomain. + MaintenanceAssociation replyMa:replyMd.maintenanceAssociation()) { + for (MaintenanceAssociationEndPoint replyMep:replyMa.maintenanceAssociationEndPoint()) { + return buildApiMepEntryFromYangMep(replyMep, handler().data().deviceId(), mdName, maName); + } + } + } + log.warn("Mep " + mepId + " not found on device " + handler().data().deviceId()); + return null; + } catch (NetconfException e) { + log.error("Unable to get MEP {}/{}/{} on device {}", + mdName, maName, mepId, handler().data().deviceId()); + throw new CfmConfigException("Unable to create MEP :" + e.getMessage()); + } + } + + @Override + public boolean deleteMep(MdId mdName, MaIdShort maName, MepId mepId) throws CfmConfigException { + + NetconfController controller = checkNotNull(handler().get(NetconfController.class)); + NetconfSession session = controller.getDevicesMap().get(handler().data().deviceId()).getSession(); + MseaCfmNetconfService mseaCfmService = checkNotNull(handler().get(MseaCfmNetconfService.class)); + + MaintenanceAssociationEndPoint mep = + new DefaultMaintenanceAssociationEndPoint(); + mep.mepIdentifier(MepIdType.of(mepId.id())); + + org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain + .MaintenanceAssociation yangMa = new DefaultMaintenanceAssociation(); + yangMa.maNameAndTypeCombo(MaNameUtil.getYangMaNameFromApiMaId(maName)); + yangMa.addToMaintenanceAssociationEndPoint(mep); + + org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.MaintenanceDomain yangMd = + new DefaultMaintenanceDomain(); + yangMd.mdNameAndTypeCombo(getYangMdNameFromApiMdId(mdName)); + yangMd.addToMaintenanceAssociation(yangMa); + + MefCfm mefCfm = new DefaultMefCfm(); + mefCfm.addToMaintenanceDomain(yangMd); + + MseaCfmOpParam mseaCfmOpParam = new MseaCfmOpParam(); + mseaCfmOpParam.mefCfm(mefCfm); + + try { + mseaCfmService.deleteMseaMep(mseaCfmOpParam, session, DatastoreId.RUNNING); + log.info("Deleted MEP {} on device {}", mdName + "/" + maName + + "/" + mepId, handler().data().deviceId()); + return true; + } catch (NetconfException e) { + log.error("Unable to delete MEP {}/{}/{} on device {}", + mdName, maName, mepId, handler().data().deviceId()); + throw new CfmConfigException("Unable to delete MEP :" + e.getMessage()); + } + + } + + @Override + public void transmitLoopback(MdId mdName, MaIdShort maName, MepId mepId, + MepLbCreate lbCreate) throws CfmConfigException { + NetconfController controller = + checkNotNull(handler().get(NetconfController.class)); + NetconfSession session = controller.getDevicesMap() + .get(handler().data().deviceId()).getSession(); + MseaCfmNetconfService mseaCfmService = + checkNotNull(handler().get(MseaCfmNetconfService.class)); + CfmMdService mdService = checkNotNull(handler().get(CfmMdService.class)); + + Short mdNumericId = mdService.getMaintenanceDomain(mdName).get().mdNumericId(); + Short maNumericId = + mdService.getMaintenanceAssociation(mdName, maName).get().maNumericId(); + + TransmitLoopbackInput lb = new DefaultTransmitLoopbackInput(); + lb.maintenanceDomain(mdNumericId); + lb.maintenanceAssociation(maNumericId); + lb.maintenanceAssociationEndPoint(mepId.id()); + if (lbCreate.numberMessages() != null) { + lb.numberOfMessages(lbCreate.numberMessages()); + } + if (lbCreate.vlanDropEligible() != null) { + lb.vlanDropEligible(lbCreate.vlanDropEligible()); + } + + if (lbCreate.remoteMepId() != null) { + org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.targetaddressgroup.addresstype + .MepId yangMepId = new DefaultMepId(); + yangMepId.mepId(MepIdType.of(lbCreate.remoteMepId().id())); + TargetAddress ta = new DefaultTargetAddress(); + ta.addressType(yangMepId); + lb.targetAddress(ta); + } else if (lbCreate.remoteMepAddress() != null) { + org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.targetaddressgroup.addresstype + .MacAddress yangMacAddress = new DefaultMacAddress(); + yangMacAddress.macAddress( + org.onosproject.yang.gen.v1.ietfyangtypes.rev20130715.ietfyangtypes + .MacAddress.of(lbCreate.remoteMepAddress().toString())); + TargetAddress ta = new DefaultTargetAddress(); + ta.addressType(yangMacAddress); + lb.targetAddress(ta); + } else { + throw new CfmConfigException("Either a remote MEP ID or Remote MEP " + + "MacAddress must be specified when calling Transmit Loopback"); + } + + if (lbCreate.dataTlvHex() != null && !lbCreate.dataTlvHex().isEmpty()) { + lb.dataTlv(HexString.fromHexString(lbCreate.dataTlvHex())); + } + if (lbCreate.vlanPriority() != null) { + lb.vlanPriority(PriorityType.of((short) lbCreate.vlanPriority().ordinal())); + } + + try { + mseaCfmService.transmitLoopback(lb, session); + log.info("Transmit Loopback called on MEP {} on device {}", + mdName + "/" + maName + "/" + mepId, + handler().data().deviceId()); + } catch (NetconfException e) { + throw new CfmConfigException(e); + } + } + + @Override + public void abortLoopback(MdId mdName, MaIdShort maName, MepId mepId) + throws CfmConfigException { + NetconfController controller = + checkNotNull(handler().get(NetconfController.class)); + NetconfSession session = controller.getDevicesMap() + .get(handler().data().deviceId()).getSession(); + MseaCfmNetconfService mseaCfmService = + checkNotNull(handler().get(MseaCfmNetconfService.class)); + CfmMdService mdService = checkNotNull(handler().get(CfmMdService.class)); + + Short mdNumericId = mdService.getMaintenanceDomain(mdName).get().mdNumericId(); + Short maNumericId = + mdService.getMaintenanceAssociation(mdName, maName).get().maNumericId(); + + AbortLoopbackInput lbAbort = new DefaultAbortLoopbackInput(); + lbAbort.maintenanceDomain(mdNumericId); + lbAbort.maintenanceAssociation(maNumericId); + lbAbort.maintenanceAssociationEndPoint(mepId.id()); + + try { + mseaCfmService.abortLoopback(lbAbort, session); + log.info("Loopback on MEP {} on device {} aborted", + mdName + "/" + maName + "/" + mepId, + handler().data().deviceId()); + } catch (NetconfException e) { + throw new CfmConfigException(e); + } + } + + @Override + public void transmitLinktrace(MdId mdName, MaIdShort maName, MepId mepId, + MepLtCreate ltCreate) { + throw new UnsupportedOperationException("Not yet implemented"); + } + + private org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm + .MaintenanceDomain buildYangMdFromApiMd(MaintenanceDomain md) + throws CfmConfigException { + MdNameAndTypeCombo mdName = getYangMdNameFromApiMdId(md.mdId()); + + org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm + .MaintenanceDomain mdYang = new DefaultMaintenanceDomain(); + mdYang.id(md.mdNumericId()); + mdYang.mdNameAndTypeCombo(mdName); + mdYang.mdLevel(MdLevelType.of((short) md.mdLevel().ordinal())); + + return mdYang; + } + + protected static MdNameAndTypeCombo getYangMdNameFromApiMdId(MdId mdId) + throws CfmConfigException { + MdNameAndTypeCombo mdName; + if (mdId instanceof MdIdDomainName) { + boolean isIpAddr = false; + try { + if (IpAddress.valueOf(mdId.mdName()) != null) { + isIpAddr = true; + } + } catch (IllegalArgumentException e) { + //continue + } + if (isIpAddr) { + mdName = new DefaultNameDomainName(); + ((DefaultNameDomainName) mdName).nameDomainName(NameDomainNameUnion.of( + org.onosproject.yang.gen.v1.ietfinettypes.rev20130715.ietfinettypes. + IpAddress.fromString(mdId.mdName()))); + } else { + mdName = new DefaultNameDomainName(); + ((DefaultNameDomainName) mdName).nameDomainName(NameDomainNameUnion + .of(DomainName.fromString(mdId.mdName()))); + } + } else if (mdId instanceof MdIdMacUint) { + mdName = new DefaultMacAddressAndUint(); + ((DefaultMacAddressAndUint) mdName).nameMacAddressAndUint(MacAddressAndUintStr.fromString(mdId.mdName())); + } else if (mdId instanceof MdIdNone) { + mdName = new DefaultNameNone(); + } else if (mdId instanceof MdIdCharStr) { + mdName = new DefaultNameCharacterString(); + ((DefaultNameCharacterString) mdName).name(Identifier45.fromString(mdId.mdName())); + } else { + throw new CfmConfigException("Unexpected error creating MD " + + mdId.getClass().getSimpleName()); + } + return mdName; + } + + private org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm + .maintenancedomain.MaintenanceAssociation buildYangMaFromApiMa( + MaintenanceAssociation apiMa) throws CfmConfigException { + + MaNameAndTypeCombo maName = MaNameUtil.getYangMaNameFromApiMaId(apiMa.maId()); + + org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain + .MaintenanceAssociation yamgMa = new DefaultMaintenanceAssociation(); + yamgMa.maNameAndTypeCombo(maName); + + if (apiMa.remoteMepIdList() == null || apiMa.remoteMepIdList().size() < REMOTEMEPLIST_MIN_COUNT + || apiMa.remoteMepIdList().size() > REMOTEMEPLIST_MAX_COUNT) { + throw new CfmConfigException("EA1000 requires between " + + REMOTEMEPLIST_MIN_COUNT + " and " + REMOTEMEPLIST_MAX_COUNT + + " remote meps in an MA"); + } + for (MepId rmep:apiMa.remoteMepIdList()) { + yamgMa.addToRemoteMeps(MepIdType.of(rmep.id())); + } + + if (apiMa.ccmInterval() != null) { + switch (apiMa.ccmInterval()) { + case INTERVAL_3MS: + yamgMa.ccmInterval(CcmIntervalEnum.YANGAUTOPREFIX3_3MS); + break; + case INVERVAL_10MS: + yamgMa.ccmInterval(CcmIntervalEnum.YANGAUTOPREFIX10MS); + break; + case INVERVAL_100MS: + yamgMa.ccmInterval(CcmIntervalEnum.YANGAUTOPREFIX100MS); + break; + case INTERVAL_1S: + yamgMa.ccmInterval(CcmIntervalEnum.YANGAUTOPREFIX1S); + break; + default: + throw new CfmConfigException("EA1000 only supports " + + "3ms, 10ms, 100ms and 1s for CCM Interval. Rejecting: " + + apiMa.ccmInterval().name()); + } + } + if (apiMa.componentList() == null || apiMa.componentList().size() != COMPONENT_LIST_SIZE) { + throw new CfmConfigException("EA1000 supports only 1 Component in an MA"); + } + + Component maComponent = apiMa.componentList().iterator().next(); + if (maComponent.vidList() == null || maComponent.vidList().size() < VIDLIST_SIZE_MIN) { + throw new CfmConfigException("EA1000 requires at least 1 VID in " + + "the Component of an MA"); + } + ComponentList compList = new DefaultComponentList(); + for (VlanId vid:maComponent.vidList()) { + compList.addToVid(VlanIdType.of(vid.toShort())); + } + + if (maComponent.tagType() != null) { + switch (maComponent.tagType()) { + case VLAN_STAG: + compList.tagType(TagTypeEnum.VLAN_STAG); + break; + case VLAN_CTAG: + compList.tagType(TagTypeEnum.VLAN_CTAG); + break; + case VLAN_NONE: + default: + compList.tagType(TagTypeEnum.VLAN_NONE); + break; + } + } + + yamgMa.componentList(compList); + yamgMa.id(apiMa.maNumericId()); + return yamgMa; + } + + private MaintenanceAssociationEndPoint buildYangMepFromApiMep(Mep mep) + throws CfmConfigException { + MaintenanceAssociationEndPoint mepBuilder = + new DefaultMaintenanceAssociationEndPoint(); + mepBuilder.mepIdentifier(MepIdType.of(mep.mepId().id())); + ContinuityCheck cc = new DefaultContinuityCheck(); + cc.cciEnabled(mep.cciEnabled()); + mepBuilder.continuityCheck(cc); + mepBuilder.ccmLtmPriority( + PriorityType.of((short) mep.ccmLtmPriority().ordinal())); + mepBuilder.administrativeState(mep.administrativeState()); + + if (mep.direction() == MepDirection.UP_MEP) { + throw new CfmConfigException("EA1000 only supports DOWN Meps"); + } + + if (mep.port() == null || mep.port().toLong() < MEP_PORT_MIN + || mep.port().toLong() > MEP_PORT_MAX) { + throw new CfmConfigException("EA1000 has only ports 0 and 1. " + + "Rejecting Port: " + mep.port()); + } + mepBuilder.yangAutoPrefixInterface( + (mep.port().toLong() == 0) ? InterfaceEnum.ETH0 : InterfaceEnum.ETH1); + + return mepBuilder; + } + + private MepEntry buildApiMepEntryFromYangMep( + MaintenanceAssociationEndPoint yangMep, DeviceId deviceId, + MdId mdName, MaIdShort maName) throws CfmConfigException { + MepId mepId = MepId.valueOf((short) yangMep.mepIdentifier().uint16()); + MepEntry.MepEntryBuilder builder = DefaultMepEntry.builder(mepId, + deviceId, + (yangMep.yangAutoPrefixInterface() == InterfaceEnum.ETH0) ? + PortNumber.portNumber(0) : PortNumber.portNumber(1), + MepDirection.DOWN_MEP, //Always down for EA1000 + mdName, maName); + + if (yangMep.loopback() != null) { + MepLbEntryBuilder lbEntryBuilder = DefaultMepLbEntry.builder(); + if (yangMep.loopback().repliesReceived() != null) { + lbEntryBuilder = lbEntryBuilder.countLbrReceived( + yangMep.loopback().repliesReceived().uint32()); + } + if (yangMep.loopback().repliesTransmitted() != null) { + lbEntryBuilder = lbEntryBuilder.countLbrTransmitted( + yangMep.loopback().repliesTransmitted().uint32()); + } + builder.loopbackAttributes(lbEntryBuilder.build()); + } + + if (yangMep.remoteMepDatabase() != null && + yangMep.remoteMepDatabase().remoteMep() != null) { + for (org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm + .maintenancedomain.maintenanceassociation + .maintenanceassociationendpoint.remotemepdatabase.RemoteMep + rmep:yangMep.remoteMepDatabase().remoteMep()) { + builder = (MepEntry.MepEntryBuilder) builder.addToActiveRemoteMepList( + getApiRemoteMepFromYangRemoteMep(rmep)); + } + } + + if (yangMep.ccmLtmPriority() != null) { + builder = (MepEntry.MepEntryBuilder) builder.ccmLtmPriority( + Priority.values()[yangMep.ccmLtmPriority().uint8()]); + } + + //And the the state attributes + builder = (MepEntry.MepEntryBuilder) builder + .macAddress(MacAddress.valueOf(yangMep.macAddress().toString())) + .administrativeState(yangMep.administrativeState()) + .cciEnabled(yangMep.continuityCheck().cciEnabled()); + + AugmentedMseaCfmMaintenanceAssociationEndPoint augmentedyangMep = yangMep + .augmentation(DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint.class); + + if (augmentedyangMep != null) { + if (augmentedyangMep.lastDefectSent() != null) { + builder = (MepEntry.MepEntryBuilder) builder + .activeXconCcmDefect(augmentedyangMep.lastDefectSent().bits() + .get(Bits.CROSS_CONNECT_CCM.bits())) + .activeErrorCcmDefect(augmentedyangMep.lastDefectSent().bits() + .get(Bits.INVALID_CCM.bits())) + .activeMacStatusDefect(augmentedyangMep.lastDefectSent().bits() + .get(Bits.REMOTE_MAC_ERROR.bits())) + .activeRdiCcmDefect(augmentedyangMep.lastDefectSent().bits() + .get(Bits.REMOTE_RDI.bits())) + .activeRemoteCcmDefect(augmentedyangMep.lastDefectSent().bits() + .get(Bits.REMOTE_INVALID_CCM.bits())); + } + } + + return builder.buildEntry(); + } + + private RemoteMepEntry getApiRemoteMepFromYangRemoteMep( + org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain. + maintenanceassociation.maintenanceassociationendpoint.remotemepdatabase. + RemoteMep yangRemoteMep) throws CfmConfigException { + + MepId remoteMepId = MepId.valueOf((short) yangRemoteMep.remoteMepId().uint16()); + RemoteMepStateTypeEnum state = RemoteMepStateTypeEnum.FAILED; + if (yangRemoteMep.remoteMepState() != null) { + state = yangRemoteMep.remoteMepState().enumeration(); + } + RemoteMepEntryBuilder rmepBuilder = DefaultRemoteMepEntry.builder( + remoteMepId, RemoteMepState.valueOf("RMEP_" + state.name())) + .rdi(yangRemoteMep.rdi()); + if (yangRemoteMep.macAddress() != null) { + rmepBuilder = rmepBuilder.macAddress( + MacAddress.valueOf(yangRemoteMep.macAddress().toString())); + } + if (yangRemoteMep.failedOkTime() != null) { + //Currently EA1000 is reporting this as 1/1000s even though yang type + // is time ticks 1/100s - to be fixed + rmepBuilder = rmepBuilder.failedOrOkTime(Duration.ofMillis( + yangRemoteMep.failedOkTime().uint32())); + } + if (yangRemoteMep.portStatusTlv() != null) { + rmepBuilder = rmepBuilder.portStatusTlvType(PortStatusTlvType.valueOf( + "PS_" + yangRemoteMep.portStatusTlv().enumeration().name())); + } + if (yangRemoteMep.interfaceStatusTlv() != null) { + rmepBuilder = rmepBuilder.interfaceStatusTlvType(InterfaceStatusTlvType.valueOf( + "IS_" + yangRemoteMep.interfaceStatusTlv().enumeration().name())); + } + return rmepBuilder.build(); + } +} diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/EA1000SoamDmProgrammable.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/EA1000SoamDmProgrammable.java new file mode 100755 index 0000000000..5a8fddb658 --- /dev/null +++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/EA1000SoamDmProgrammable.java @@ -0,0 +1,740 @@ +/* + * Copyright 2017-present Open Networking Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.drivers.microsemi; + +import static com.google.common.base.Preconditions.checkNotNull; +import static org.slf4j.LoggerFactory.getLogger; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.BitSet; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Optional; + +import org.onosproject.drivers.microsemi.yang.MseaCfmNetconfService; +import org.onosproject.drivers.microsemi.yang.MseaCfmNetconfService.DmEntryParts; +import org.onosproject.drivers.microsemi.yang.utils.IetfYangTypesUtils; +import org.onosproject.drivers.microsemi.yang.utils.MepIdUtil; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep.Priority; +import org.onosproject.incubator.net.l2monitoring.cfm.MepTsCreate; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMdService; +import org.onosproject.incubator.net.l2monitoring.soam.SoamConfigException; +import org.onosproject.incubator.net.l2monitoring.soam.SoamDmProgrammable; +import org.onosproject.incubator.net.l2monitoring.soam.SoamId; +import org.onosproject.incubator.net.l2monitoring.soam.StartTime.StartTimeOption; +import org.onosproject.incubator.net.l2monitoring.soam.StopTime.StopTimeOption; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DefaultDelayMeasurementEntry; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DefaultDelayMeasurementStatCurrent; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DefaultDelayMeasurementStatHistory; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.DmType; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.MeasurementOption; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.Version; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementEntry; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementEntry.DmEntryBuilder; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementEntry.SessionStatus; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStatCurrent; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStatCurrent.DmStatCurrentBuilder; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStatHistory; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStatHistory.DmStatHistoryBuilder; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementCreate; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementEntry; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementStatCurrent; +import org.onosproject.net.driver.AbstractHandlerBehaviour; +import org.onosproject.netconf.DatastoreId; +import org.onosproject.netconf.NetconfController; +import org.onosproject.netconf.NetconfException; +import org.onosproject.netconf.NetconfSession; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.MseaCfm; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.MseaCfmOpParam; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.DefaultMefCfm; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.MefCfm; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.DefaultMaintenanceDomain; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.DefaultMaintenanceAssociation; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.DefaultMaintenanceAssociationEndPoint; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.MaintenanceAssociationEndPoint; +import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.delaymeasurementbinsgroup.bins.FrameDelay; +import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.delaymeasurementbinsgroup.bins.InterFrameDelayVariation; +import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.AugmentedMseaCfmMaintenanceAssociationEndPoint; +import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint; +import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.augmentedmseacfmmaintenanceassociationendpoint.DefaultDelayMeasurements; +import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.augmentedmseacfmmaintenanceassociationendpoint.DelayMeasurements; +import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.augmentedmseacfmmaintenanceassociationendpoint.delaymeasurements.DefaultDelayMeasurement; +import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.augmentedmseacfmmaintenanceassociationendpoint.delaymeasurements.DelayMeasurement; +import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.augmentedmseacfmmaintenanceassociationendpoint.delaymeasurements.delaymeasurement.HistoryStats; +import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.augmentedmseacfmmaintenanceassociationendpoint.delaymeasurements.delaymeasurement.MeasurementEnable; +import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.augmentedmseacfmmaintenanceassociationendpoint.delaymeasurements.delaymeasurement.MessagePeriodEnum; +import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.remotemepgroup.remotemep.DefaultMepId; +import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.MepIdType; +import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.PriorityType; +import org.slf4j.Logger; + +/** + * Implementation of SoamDmProgrammable for Microsemi EA1000. + */ +public class EA1000SoamDmProgrammable extends AbstractHandlerBehaviour + implements SoamDmProgrammable { + private static final Logger log = getLogger(EA1000SoamDmProgrammable.class); + private static final int MAX_DMS = 2; + + public EA1000SoamDmProgrammable() { + log.debug("Loaded handler behaviour EA1000SoamDmProgrammable"); + } + + @Override + public Collection getAllDms( + MdId mdName, MaIdShort maName, MepId mepId) + throws CfmConfigException, SoamConfigException { + return getAllDmsOrOneDm(mdName, maName, mepId, null, DmEntryParts.ALL_PARTS); + } + + @Override + public DelayMeasurementEntry getDm(MdId mdName, MaIdShort maName, + MepId mepId, SoamId dmId) throws CfmConfigException, SoamConfigException { + Collection allDms = + getAllDmsOrOneDm(mdName, maName, mepId, dmId, DmEntryParts.ALL_PARTS); + + if (allDms != null && allDms.size() >= 1) { + return allDms.toArray(new DelayMeasurementEntry[1])[0]; + } + return null; + } + + @Override + public DelayMeasurementStatCurrent getDmCurrentStat( + MdId mdName, MaIdShort maName, MepId mepId, SoamId dmId) + throws CfmConfigException, SoamConfigException { + Collection dms = + getAllDmsOrOneDm(mdName, maName, mepId, dmId, DmEntryParts.CURRENT_ONLY); + + //There should be only one + if (dms != null && dms.size() == 1) { + return dms.toArray((new DelayMeasurementEntry[1]))[0].currentResult(); + } + return null; + } + + @Override + public Collection getDmHistoricalStats( + MdId mdName, MaIdShort maName, MepId mepId, SoamId dmId) + throws CfmConfigException, SoamConfigException { + Collection dms = + getAllDmsOrOneDm(mdName, maName, mepId, dmId, DmEntryParts.HISTORY_ONLY); + + //There should only be one in the result + if (dms != null && dms.size() == 1) { + return dms.toArray(new DelayMeasurementEntry[1])[0].historicalResults(); + } + return new ArrayList<>(); + } + + @Override + public Optional createDm( + MdId mdName, MaIdShort maName, MepId mepId, DelayMeasurementCreate dm) + throws CfmConfigException, SoamConfigException { + NetconfController controller = checkNotNull(handler().get(NetconfController.class)); + NetconfSession session = controller.getDevicesMap().get(handler().data().deviceId()).getSession(); + MseaCfmNetconfService mseaCfmService = checkNotNull(handler().get(MseaCfmNetconfService.class)); + + MseaCfm mepEssentials; + try { + mepEssentials = mseaCfmService.getMepEssentials( + mdName, maName, mepId, session); + } catch (NetconfException e) { + throw new CfmConfigException(e); + } + short mdNumber = mepEssentials.mefCfm().maintenanceDomain().get(0).id(); + short maNumber = mepEssentials.mefCfm().maintenanceDomain().get(0) + .maintenanceAssociation().get(0).id(); + MaintenanceAssociationEndPoint currentMep = + mepEssentials.mefCfm().maintenanceDomain().get(0) + .maintenanceAssociation().get(0) + .maintenanceAssociationEndPoint().get(0); + AugmentedMseaCfmMaintenanceAssociationEndPoint currAugMep = + currentMep.augmentation(DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint.class); + + if (dm.startTime() != null && !dm.startTime().option().equals(StartTimeOption.IMMEDIATE)) { + throw new SoamConfigException( + "Only start time: IMMEDIATE is supported on EA1000"); + } else if (dm.stopTime() != null && !dm.stopTime().option().equals(StopTimeOption.NONE)) { + throw new SoamConfigException( + "Only stop time: NONE is supported on EA1000"); + } + + MessagePeriodEnum mpEnum = MessagePeriodEnum.YANGAUTOPREFIX1000MS; + if (dm.messagePeriod() != null) { + if (dm.messagePeriod().toMillis() == 1000) { + mpEnum = MessagePeriodEnum.YANGAUTOPREFIX1000MS; + } else if (dm.messagePeriod().toMillis() == 100) { + mpEnum = MessagePeriodEnum.YANGAUTOPREFIX100MS; + } else if (dm.messagePeriod().toMillis() == 10) { + mpEnum = MessagePeriodEnum.YANGAUTOPREFIX10MS; + } else if (dm.messagePeriod().toMillis() == 3) { + mpEnum = MessagePeriodEnum.YANGAUTOPREFIX3MS; + } else { + throw new SoamConfigException("EA1000 supports only Message " + + "Periods 1000ms,100ms, 10ms and 3ms for Delay Measurements"); + } + } + + short lastDmId = 0; + short newDmId = 1; + if (currAugMep != null && currAugMep.delayMeasurements() != null) { + Iterator dmIterator = + currAugMep.delayMeasurements().delayMeasurement().iterator(); + while (dmIterator.hasNext()) { + lastDmId = dmIterator.next().dmId(); + } + + if (lastDmId == 0) { + //Indicates that no DM was found under this MEP. + //We will just create the next one as 1 + log.info("Creating DM 1"); + newDmId = 1; + } else if (lastDmId == 1) { + log.info("Creating DM 2"); + newDmId = 2; + } else if (lastDmId == MAX_DMS) { + log.warn("Maximum number of DMs (2) have been created on MEP {}/{}/{}" + + "on device {} - delete DMs before creating more", + mdName.mdName(), maName.maName(), mepId.id(), + handler().data().deviceId()); + throw new CfmConfigException("Maximum number of DMs (2) exist on MEP. " + + "Please call abort on a DM before creating more"); + } + } + + + DelayMeasurement dmBuilder = new DefaultDelayMeasurement(); + dmBuilder.dmId((short) newDmId); + DefaultMepId dMepId = new DefaultMepId(); + dMepId.mepId(MepIdType.of(dm.remoteMepId().id())); + dmBuilder.remoteMep(dMepId); + + BitSet measurementEnable = getMeasurementEnabledSet(dm.measurementsEnabled()); + if (measurementEnable != null && !measurementEnable.isEmpty()) { + dmBuilder.measurementEnable(measurementEnable); + } + dmBuilder.administrativeState(true); + dmBuilder.priority(PriorityType.of((short) dm.priority().ordinal())); + dmBuilder.messagePeriod(mpEnum); + + if (dm.numberIntervalsStored() != null) { + //Here we pass in num intervals stored - for EA1000 32 are always + //stored so it's not controllable - instead we set number returned + dmBuilder.numberIntervalsReturned(dm.numberIntervalsStored()); + } + + if (dm.measurementInterval() != null) { + dmBuilder.measurementInterval(dm.measurementInterval().toMinutes()); + } + if (dm.frameSize() != null) { + dmBuilder.frameSize(dm.frameSize()); + } + DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint augmentedMep = + new DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint(); + DelayMeasurements dms = new DefaultDelayMeasurements(); + dms.addToDelayMeasurement(dmBuilder); + augmentedMep.delayMeasurements(dms); + + MaintenanceAssociationEndPoint mep = + new DefaultMaintenanceAssociationEndPoint(); + mep.mepIdentifier(MepIdType.of(mepId.id())); + mep.addAugmentation(augmentedMep); + + + org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain + .MaintenanceAssociation yangMa = new DefaultMaintenanceAssociation(); + yangMa.id(maNumber); + yangMa.addToMaintenanceAssociationEndPoint(mep); + + org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm + .MaintenanceDomain yangMd = new DefaultMaintenanceDomain(); + yangMd.id(mdNumber); + yangMd.addToMaintenanceAssociation(yangMa); + + MefCfm mefCfm = new DefaultMefCfm(); + mefCfm.addToMaintenanceDomain(yangMd); + + MseaCfmOpParam mseaCfmOpParam = new MseaCfmOpParam(); + mseaCfmOpParam.mefCfm(mefCfm); + + try { + mseaCfmService.setMseaCfm(mseaCfmOpParam, session, DatastoreId.RUNNING); + return Optional.empty(); + } catch (NetconfException e) { + log.error("Unable to create DM {}/{}/{} on device {}", + mdName, maName, mepId, handler().data().deviceId()); + throw new CfmConfigException("Unable to create DM :" + e.getMessage()); + } + + } + + @Override + public void abortDm(MdId mdName, MaIdShort maName, MepId mepId, SoamId dmId) + throws CfmConfigException { + NetconfController controller = checkNotNull(handler().get(NetconfController.class)); + NetconfSession session = controller.getDevicesMap().get(handler().data() + .deviceId()).getSession(); + MseaCfmNetconfService mseaCfmService = checkNotNull(handler() + .get(MseaCfmNetconfService.class)); + CfmMdService cfmMdService = checkNotNull(handler().get(CfmMdService.class)); + + + org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain + .maintenanceassociation.maintenanceassociationendpoint + .augmentedmseacfmmaintenanceassociationendpoint.delaymeasurements + .DelayMeasurement dm = new DefaultDelayMeasurement(); + dm.dmId(dmId.id().shortValue()); + + DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint augmentedMep = + new DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint(); + DelayMeasurements ddms = new DefaultDelayMeasurements(); + ddms.addToDelayMeasurement(dm); + augmentedMep.delayMeasurements(ddms); + + MaintenanceAssociationEndPoint mep = + new DefaultMaintenanceAssociationEndPoint(); + mep.mepIdentifier(MepIdType.of(mepId.id())); + mep.addAugmentation(augmentedMep); + + + short mdNumericId = cfmMdService.getMaintenanceDomain(mdName).get().mdNumericId(); + short maNumericId = cfmMdService + .getMaintenanceAssociation(mdName, maName).get().maNumericId(); + + DefaultMaintenanceAssociation yangMa = new DefaultMaintenanceAssociation(); + yangMa.id(maNumericId); + yangMa.addToMaintenanceAssociationEndPoint(mep); + + DefaultMaintenanceDomain yangMd = new DefaultMaintenanceDomain(); + yangMd.id(mdNumericId); + yangMd.addToMaintenanceAssociation(yangMa); + + MefCfm mefCfm = new DefaultMefCfm(); + mefCfm.addToMaintenanceDomain(yangMd); + + MseaCfmOpParam mseaCfmOpParam = new MseaCfmOpParam(); + mseaCfmOpParam.mefCfm(mefCfm); + + try { + mseaCfmService.deleteMseaCfmDm(mseaCfmOpParam, session, DatastoreId.RUNNING); + } catch (NetconfException e) { + log.error("Unable to delete DM {}/{}/{}/{} on device {}", + mdName, maName, mepId, dm.dmId(), handler().data().deviceId()); + throw new CfmConfigException("Unable to delete DM :" + e.getMessage()); + } + } + + @Override + public void abortDm(MdId mdName, MaIdShort maName, MepId mepId) + throws CfmConfigException { + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public void clearDelayHistoryStats(MdId mdName, MaIdShort maName, + MepId mepId) throws CfmConfigException { + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public void clearDelayHistoryStats(MdId mdName, MaIdShort maName, + MepId mepId, SoamId dmId) throws CfmConfigException { + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public Collection getAllLms(MdId mdName, + MaIdShort maName, MepId mepId) throws CfmConfigException { + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public LossMeasurementEntry getLm(MdId mdName, MaIdShort maName, + MepId mepId, SoamId lmId) throws CfmConfigException { + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public LossMeasurementStatCurrent getLmCurrentStat(MdId mdName, + MaIdShort maName, MepId mepId, SoamId lmId) { + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public Collection getLmHistoricalStats( + MdId mdName, MaIdShort maName, MepId mepId, SoamId lmId) { + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public Optional createLm(MdId mdName, MaIdShort maName, MepId mepId, + LossMeasurementCreate lm) throws CfmConfigException { + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public void abortLm(MdId mdName, MaIdShort maName, MepId mepId) + throws CfmConfigException { + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public void abortLm(MdId mdName, MaIdShort maName, MepId mepId, SoamId lmId) + throws CfmConfigException { + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public void clearLossHistoryStats(MdId mdName, MaIdShort maName, + MepId mepId) throws CfmConfigException { + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public void clearLossHistoryStats(MdId mdName, MaIdShort maName, + MepId mepId, SoamId lmId) throws CfmConfigException { + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public void createTestSignal(MdId mdName, MaIdShort maName, MepId mepId, + MepTsCreate tsCreate) throws CfmConfigException { + throw new UnsupportedOperationException("Not supported by EA1000"); + } + + @Override + public void abortTestSignal(MdId mdName, MaIdShort maName, MepId mepId) + throws CfmConfigException { + throw new UnsupportedOperationException("Not supported by EA1000"); + } + + private static DelayMeasurementEntry buildApiDmFromYangDm(DelayMeasurement dm, + MdId mdName, MaIdShort maName, MepId mepId) + throws SoamConfigException, CfmConfigException { + + org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.remotemepgroup.remotemep + .MepId rmep = MepIdUtil.convertRemoteMepId(dm.remoteMep()); + + DmEntryBuilder dmBuilder = (DmEntryBuilder) DefaultDelayMeasurementEntry.builder( + SoamId.valueOf(dm.dmId()), DmType.DMDMM, Version.Y17312011, + MepId.valueOf((short) ((MepIdType) rmep.mepId()).uint16()), + Priority.values()[dm.priority().uint8()]); + if (dm.sessionStatus() != null) { + dmBuilder = dmBuilder.sessionStatus(SessionStatus.valueOf( + dm.sessionStatus().enumeration().name())); + } + + if (dm.frameDelayTwoWay() != null) { + dmBuilder = dmBuilder.frameDelayTwoWay(Duration.ofNanos( + dm.frameDelayTwoWay().uint32() * 1000)); + } + if (dm.interFrameDelayVariationTwoWay() != null) { + dmBuilder = dmBuilder.interFrameDelayVariationTwoWay(Duration.ofNanos( + dm.interFrameDelayVariationTwoWay().uint32() * 1000)); + } + + if (dm.frameSize() != 0) { + dmBuilder = (DmEntryBuilder) dmBuilder.frameSize((short) dm.frameSize()); + } + + if (dm.messagePeriod() != null) { + switch (dm.messagePeriod()) { + case YANGAUTOPREFIX1000MS: + dmBuilder = (DmEntryBuilder) dmBuilder.messagePeriod(Duration.ofMillis(1000)); + break; + case YANGAUTOPREFIX100MS: + dmBuilder = (DmEntryBuilder) dmBuilder.messagePeriod(Duration.ofMillis(100)); + break; + case YANGAUTOPREFIX10MS: + dmBuilder = (DmEntryBuilder) dmBuilder.messagePeriod(Duration.ofMillis(10)); + break; + case YANGAUTOPREFIX3MS: + dmBuilder = (DmEntryBuilder) dmBuilder.messagePeriod(Duration.ofMillis(3)); + break; + default: + throw new SoamConfigException("EA1000 supports only 1000," + + "100, 10 and 3ms for Message Period on DM"); + } + } + + Collection moSet = + EA1000SoamDmProgrammable.getMeasurementOptions(dm.measurementEnable()); + moSet.forEach(dmBuilder::addToMeasurementsEnabled); + + dmBuilder = dmBuilder + .currentResult(buildApiDmCurrFromYangDmCurr(dm, mdName, maName, mepId)); + + for (DelayMeasurementStatHistory historyStat: + buildApiDmHistFromYangDm(dm, mdName, maName, mepId)) { + dmBuilder = dmBuilder.addToHistoricalResults(historyStat); + } + + return dmBuilder.build(); + } + + private static Collection buildApiDmHistFromYangDm( + DelayMeasurement dm, MdId mdName, MaIdShort maName, MepId mepId) + throws SoamConfigException, CfmConfigException { + + Collection historyStatsCollection = new ArrayList<>(); + if (dm.historyStats() != null) { + for (HistoryStats dmHistory:dm.historyStats()) { + DmStatHistoryBuilder historyBuilder = + DefaultDelayMeasurementStatHistory.builder( + SoamId.valueOf((int) dmHistory.id()), + Duration.ofMillis(dmHistory.elapsedTime() * 10), //Values are in 1/100th sec + dmHistory.suspectStatus() != null ? + dmHistory.suspectStatus().yangAutoPrefixBoolean() : false); + historyBuilder = historyBuilder.endTime( + IetfYangTypesUtils.fromYangDateTimeToInstant(dmHistory.endTime())); + + if (dmHistory.frameDelayTwoWayMin() != null) { + historyBuilder = (DmStatHistoryBuilder) historyBuilder + .frameDelayTwoWayMin(Duration.ofNanos(dmHistory.frameDelayTwoWayMin().uint32() * 1000)); + } + + if (dmHistory.frameDelayTwoWayMax() != null) { + historyBuilder = (DmStatHistoryBuilder) historyBuilder + .frameDelayTwoWayMax(Duration.ofNanos(dmHistory.frameDelayTwoWayMax().uint32() * 1000)); + } + + if (dmHistory.frameDelayTwoWayAverage() != null) { + historyBuilder = (DmStatHistoryBuilder) historyBuilder + .frameDelayTwoWayAvg(Duration.ofNanos(dmHistory.frameDelayTwoWayAverage().uint32() * 1000)); + } + + if (dmHistory.interFrameDelayVariationTwoWayMin() != null) { + historyBuilder = (DmStatHistoryBuilder) historyBuilder + .interFrameDelayVariationTwoWayMin(Duration.ofNanos( + dmHistory.interFrameDelayVariationTwoWayMin().uint32() * 1000)); + } + + if (dmHistory.interFrameDelayVariationTwoWayMax() != null) { + historyBuilder = (DmStatHistoryBuilder) historyBuilder + .interFrameDelayVariationTwoWayMax(Duration.ofNanos( + dmHistory.interFrameDelayVariationTwoWayMax().uint32() * 1000)); + } + + if (dmHistory.interFrameDelayVariationTwoWayAverage() != null) { + historyBuilder = (DmStatHistoryBuilder) historyBuilder + .interFrameDelayVariationTwoWayAvg(Duration.ofNanos( + dmHistory.interFrameDelayVariationTwoWayAverage().uint32() * 1000)); + } + + if (dmHistory.soamPdusReceived() != null) { + historyBuilder = (DmStatHistoryBuilder) historyBuilder + .soamPdusReceived(Integer.valueOf((int) dmHistory.soamPdusReceived().uint32())); + } + + if (dmHistory.bins() != null && dmHistory.bins().frameDelay() != null) { + Map frameDelayTwoWayBins = new HashMap<>(); + for (FrameDelay fdBin:dmHistory.bins().frameDelay()) { + frameDelayTwoWayBins.put( + Duration.ofNanos(fdBin.lowerBound().uint32() * 1000), + Integer.valueOf((int) fdBin.counter().uint32())); + } + historyBuilder = (DmStatHistoryBuilder) historyBuilder + .frameDelayTwoWayBins(frameDelayTwoWayBins); + } + + if (dmHistory.bins() != null && dmHistory.bins().interFrameDelayVariation() != null) { + Map ifdvTwoWayBins = new HashMap<>(); + for (InterFrameDelayVariation ifdvBin:dmHistory.bins().interFrameDelayVariation()) { + ifdvTwoWayBins.put( + Duration.ofNanos(ifdvBin.lowerBound().uint32() * 1000), + Integer.valueOf((int) ifdvBin.counter().uint32())); + } + historyBuilder = + (DmStatHistoryBuilder) historyBuilder.interFrameDelayVariationTwoWayBins(ifdvTwoWayBins); + } + + historyStatsCollection.add((DelayMeasurementStatHistory) historyBuilder.build()); + } + } + return historyStatsCollection; + } + + private static DelayMeasurementStatCurrent buildApiDmCurrFromYangDmCurr( + DelayMeasurement dm, MdId mdName, MaIdShort maName, MepId mepId) + throws SoamConfigException, CfmConfigException { + if (dm == null || dm.currentStats() == null || mdName == null || + maName == null || mepId == null) { + return null; + } + + DmStatCurrentBuilder statCurrBuilder = + DefaultDelayMeasurementStatCurrent.builder( + Duration.ofMillis(dm.currentStats().elapsedTime() * 10), //Values are in 1/100th sec + dm.currentStats().suspectStatus() != null ? + dm.currentStats().suspectStatus().yangAutoPrefixBoolean() : false); + statCurrBuilder = statCurrBuilder.startTime( + IetfYangTypesUtils.fromYangDateTimeToInstant(dm.currentStats().startTime())); + + if (dm.currentStats().frameDelayTwoWayMin() != null) { + statCurrBuilder = (DmStatCurrentBuilder) statCurrBuilder + .frameDelayTwoWayMin(Duration.ofNanos( + dm.currentStats().frameDelayTwoWayMin().uint32() * 1000)); + } + + if (dm.currentStats().frameDelayTwoWayMax() != null) { + statCurrBuilder = (DmStatCurrentBuilder) statCurrBuilder + .frameDelayTwoWayMax(Duration.ofNanos( + dm.currentStats().frameDelayTwoWayMax().uint32() * 1000)); + } + + if (dm.currentStats().frameDelayTwoWayAverage() != null) { + statCurrBuilder = (DmStatCurrentBuilder) statCurrBuilder + .frameDelayTwoWayAvg(Duration.ofNanos( + dm.currentStats().frameDelayTwoWayAverage().uint32() * 1000)); + } + + if (dm.currentStats().interFrameDelayVariationTwoWayMin() != null) { + statCurrBuilder = (DmStatCurrentBuilder) statCurrBuilder + .interFrameDelayVariationTwoWayMin(Duration.ofNanos( + dm.currentStats().interFrameDelayVariationTwoWayMin().uint32() * 1000)); + } + + if (dm.currentStats().interFrameDelayVariationTwoWayMax() != null) { + statCurrBuilder = (DmStatCurrentBuilder) statCurrBuilder + .interFrameDelayVariationTwoWayMax(Duration.ofNanos( + dm.currentStats().interFrameDelayVariationTwoWayMax().uint32() * 1000)); + } + + if (dm.currentStats().interFrameDelayVariationTwoWayAverage() != null) { + statCurrBuilder = (DmStatCurrentBuilder) statCurrBuilder + .interFrameDelayVariationTwoWayAvg(Duration.ofNanos( + dm.currentStats().interFrameDelayVariationTwoWayAverage().uint32() * 1000)); + } + + if (dm.currentStats().soamPdusReceived() != null) { + statCurrBuilder = (DmStatCurrentBuilder) statCurrBuilder + .soamPdusReceived(Integer.valueOf((int) dm.currentStats().soamPdusReceived().uint32())); + } + + if (dm.currentStats().bins() != null && dm.currentStats().bins().frameDelay() != null) { + Map frameDelayTwoWayBins = new HashMap<>(); + for (FrameDelay fdBin:dm.currentStats().bins().frameDelay()) { + frameDelayTwoWayBins.put( + Duration.ofNanos(fdBin.lowerBound().uint32() * 1000), + Integer.valueOf((int) fdBin.counter().uint32())); + } + statCurrBuilder = (DmStatCurrentBuilder) statCurrBuilder.frameDelayTwoWayBins(frameDelayTwoWayBins); + } + + if (dm.currentStats().bins() != null && dm.currentStats().bins().interFrameDelayVariation() != null) { + Map ifdvTwoWayBins = new HashMap<>(); + for (InterFrameDelayVariation ifdvBin:dm.currentStats().bins().interFrameDelayVariation()) { + ifdvTwoWayBins.put( + Duration.ofNanos(ifdvBin.lowerBound().uint32() * 1000), + Integer.valueOf((int) ifdvBin.counter().uint32())); + } + statCurrBuilder = + (DmStatCurrentBuilder) statCurrBuilder.interFrameDelayVariationTwoWayBins(ifdvTwoWayBins); + } + + return (DelayMeasurementStatCurrent) statCurrBuilder.build(); + } + + private Collection getAllDmsOrOneDm( + MdId mdName, MaIdShort maName, MepId mepId, SoamId dmId, DmEntryParts parts) + throws CfmConfigException, SoamConfigException { + NetconfController controller = + checkNotNull(handler().get(NetconfController.class)); + NetconfSession session = + controller.getDevicesMap().get(handler().data().deviceId()).getSession(); + MseaCfmNetconfService mseaCfmService = + checkNotNull(handler().get(MseaCfmNetconfService.class)); + + Collection dmResults = new ArrayList<>(); + try { + MseaCfm mseacfm = + mseaCfmService.getSoamDm(mdName, maName, mepId, dmId, parts, session); + for (org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm + .MaintenanceDomain replyMd:mseacfm.mefCfm().maintenanceDomain()) { + for (org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm + .mefcfm.maintenancedomain.MaintenanceAssociation replyMa: + replyMd.maintenanceAssociation()) { + for (MaintenanceAssociationEndPoint replyMep: + replyMa.maintenanceAssociationEndPoint()) { + AugmentedMseaCfmMaintenanceAssociationEndPoint augmentedMep = + replyMep.augmentation( + DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint.class); + if (augmentedMep == null || + augmentedMep.delayMeasurements() == null || + augmentedMep.delayMeasurements() + .delayMeasurement().isEmpty()) { + log.info("No Delay Measurements retrieved from MEP " + + mdName + "/" + maName + "/" + mepId); + } else { + for (org.onosproject.yang.gen.v1.mseasoampm.rev20160229 + .mseasoampm.mefcfm.maintenancedomain.maintenanceassociation + .maintenanceassociationendpoint + .augmentedmseacfmmaintenanceassociationendpoint + .delaymeasurements.DelayMeasurement dm + :augmentedMep.delayMeasurements().delayMeasurement()) { + dmResults.add(buildApiDmFromYangDm(dm, mdName, maName, mepId)); + } + } + } + } + } + return dmResults; + } catch (NetconfException e) { + log.error("Unable to get MEP {}/{}/{} on device {}", + mdName, maName, mepId, handler().data().deviceId()); + throw new CfmConfigException("Unable to create MEP :" + e.getMessage()); + } + } + + + protected static BitSet getMeasurementEnabledSet( + Collection measEnabled) throws SoamConfigException { + BitSet measurementEnable = new BitSet(); + try { + measEnabled.forEach(mo -> { + MeasurementEnable me = MeasurementEnable.valueOf(mo.name()); + measurementEnable.set(me.measurementEnable()); + }); + } catch (IllegalArgumentException e) { + throw new SoamConfigException( + "Measurement Option is not supported on EA1000: ", e); + } + + return measurementEnable; + } + + protected static Collection getMeasurementOptions(BitSet meBs) { + Collection meList = new ArrayList<>(); + if (meBs != null && !meBs.isEmpty()) { + for (int i = 0; i < meBs.size(); i++) { + if (meBs.get(i)) { + meList.add(MeasurementOption.valueOf(MeasurementEnable.of(i).name())); + } + } + } + + return meList; + } +} \ No newline at end of file diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/MseaCfmNetconfService.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/MseaCfmNetconfService.java index d10b75065b..1bc32ca7ac 100644 --- a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/MseaCfmNetconfService.java +++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/MseaCfmNetconfService.java @@ -15,6 +15,10 @@ */ package org.onosproject.drivers.microsemi.yang; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.soam.SoamId; import org.onosproject.netconf.DatastoreId; import org.onosproject.netconf.NetconfException; import org.onosproject.netconf.NetconfSession; @@ -34,32 +38,48 @@ import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitloopback. public interface MseaCfmNetconfService { /** - * Returns attributes of MEP. + * Returns minimal set of attributes of MEP. * - * @param mdName The name of the MD - * @param maName The name of the MA + * @param mdId The name of the MD + * @param maId The name of the MA * @param mepId The ID of the MEP * @param session An active NETCONF session * @return mseaCfm * @throws NetconfException if the session has any error */ - MseaCfm getMepEssentials(String mdName, String maName, int mepId, - NetconfSession session) throws NetconfException; + MseaCfm getMepEssentials(MdId mdId, MaIdShort maId, MepId mepId, + NetconfSession session) throws NetconfException; + /** + * Returns full set of attributes of MEP. + * This returns config and state attributes of all children of the MEP + * except for Delay Measurements and Loss Measurements - these have to be + * retrieved separately, because of their potential size + * @param mdId The name of the MD + * @param maId The name of the MA + * @param mepId The ID of the MEP + * @param session An active NETCONF session + * @return mseaCfm + * @throws NetconfException if the session has any error + */ + MseaCfm getMepFull(MdId mdId, MaIdShort maId, MepId mepId, + NetconfSession session) throws NetconfException; /** * Returns attributes of DM. * - * @param mdName The name of the MD - * @param maName The name of the MA + * @param mdId The name of the MD + * @param maId The name of the MA * @param mepId The ID of the MEP - * @param dmId The Id of the Delay Measurement + * @param dmId The Id of the Delay Measurement - if null then all DMs + * @param parts The parts of the DM to return * @param session An active NETCONF session * @return mseaCfm * @throws NetconfException if the session has any error */ - MseaCfm getSoamDm(String mdName, String maName, int mepId, - int dmId, NetconfSession session) throws NetconfException; + MseaCfm getSoamDm(MdId mdId, MaIdShort maId, MepId mepId, + SoamId dmId, DmEntryParts parts, NetconfSession session) + throws NetconfException; /** * Sets the value to attribute mseaCfm. @@ -73,6 +93,33 @@ public interface MseaCfmNetconfService { boolean setMseaCfm(MseaCfmOpParam mseaCfm, NetconfSession session, DatastoreId targetDs) throws NetconfException; + /** + * Deletes named Meps of mseaCfm. + * Expects to see a list of Meps + * + * @param mseaCfm value of mseaCfm + * @param session An active NETCONF session + * @param targetDs one of running, candidate or startup + * @return Boolean to indicate success or failure + * @throws NetconfException if the session has any error + */ + boolean deleteMseaMep(MseaCfmOpParam mseaCfm, NetconfSession session, + DatastoreId targetDs) throws NetconfException; + + + /** + * Deletes named delay measurements of mseaCfm. + * Expects to see a list of Delay Measurements + * + * @param mseaCfm value of mseaCfm + * @param session An active NETCONF session + * @param targetDs one of running, candidate or startup + * @return Boolean to indicate success or failure + * @throws NetconfException if the session has any error + */ + boolean deleteMseaCfmDm(MseaCfmOpParam mseaCfm, NetconfSession session, + DatastoreId targetDs) throws NetconfException; + /** * Service interface of transmitLoopback. * @@ -103,4 +150,10 @@ public interface MseaCfmNetconfService { */ TransmitLinktraceOutput transmitLinktrace(TransmitLinktraceInput inputVar, NetconfSession session) throws NetconfException; + + public enum DmEntryParts { + ALL_PARTS, + CURRENT_ONLY, + HISTORY_ONLY; + } } diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/AbstractYangServiceImpl.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/AbstractYangServiceImpl.java index 8339501cb7..27c1e86867 100644 --- a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/AbstractYangServiceImpl.java +++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/AbstractYangServiceImpl.java @@ -35,6 +35,8 @@ import org.onosproject.core.CoreService; import org.onosproject.netconf.DatastoreId; import org.onosproject.netconf.NetconfException; import org.onosproject.netconf.NetconfSession; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.CcmIntervalEnum; +import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.augmentedmseacfmmaintenanceassociationendpoint.lossmeasurements.lossmeasurement.MessagePeriodEnum; import org.onosproject.yang.model.ModelConverter; import org.onosproject.yang.model.ModelObjectData; import org.onosproject.yang.model.ResourceData; @@ -100,7 +102,8 @@ public abstract class AbstractYangServiceImpl { Pattern.compile("()"); protected static final Pattern REGEX_RPC_REPLY_CLOSE = Pattern.compile("()"); - + protected static final Pattern REGEX_RPC_OK = + Pattern.compile("\\R?\\s*()\\R?"); @Activate public void activate() { Set yangSer = ((YangSerializerRegistry) yangModelRegistry).getSerializers(); @@ -189,18 +192,65 @@ public abstract class AbstractYangServiceImpl { if (moConfig == null) { throw new NetconfException("Query object cannot be null"); } else if (session == null) { - throw new NetconfException("Session is null when calling getMseaSaFiltering()"); + throw new NetconfException("Session is null when calling setNetconfObject()"); } else if (targetDs == null) { - throw new NetconfException("TargetDs is null when calling getMseaSaFiltering()"); + throw new NetconfException("TargetDs is null when calling setNetconfObject()"); } String xmlQueryStr = encodeMoToXmlStr(moConfig, annotations); log.debug("Sending query on NETCONF session " + session.getSessionId() + ":\n" + xmlQueryStr); + //Some encoded values just have to be replaced + xmlQueryStr = xmlQueryStr.replace(MessagePeriodEnum.YANGAUTOPREFIX3MS.toString(), "3ms"); + xmlQueryStr = xmlQueryStr.replace(MessagePeriodEnum.YANGAUTOPREFIX10MS.toString(), "10ms"); + xmlQueryStr = xmlQueryStr.replace(MessagePeriodEnum.YANGAUTOPREFIX100MS.toString(), "100ms"); + xmlQueryStr = xmlQueryStr.replace(MessagePeriodEnum.YANGAUTOPREFIX1000MS.toString(), "1000ms"); + + xmlQueryStr = xmlQueryStr.replace(CcmIntervalEnum.YANGAUTOPREFIX3_3MS.toString(), "3.3ms"); + xmlQueryStr = xmlQueryStr.replace(CcmIntervalEnum.YANGAUTOPREFIX10MS.toString(), "10ms"); + xmlQueryStr = xmlQueryStr.replace(CcmIntervalEnum.YANGAUTOPREFIX100MS.toString(), "100ms"); + xmlQueryStr = xmlQueryStr.replace(CcmIntervalEnum.YANGAUTOPREFIX1S.toString(), "1s"); + return session.editConfig(targetDs, null, xmlQueryStr); } + /** + * Internal method to generically call a NETCONF custom RPC from a set of YANG objects. + * + * @param customRpcInput A YANG object model + * @param rpcName The name of the RPC - replaces 'input' in the XML payload + * @param session A NETCONF session + * @return ModelObjectData value indicating success or failure of command + * @throws NetconfException if the session has any error + */ + protected final ModelObjectData customRpcNetconf( + ModelObjectData customRpcInput, String rpcName, NetconfSession session) + throws NetconfException { + if (customRpcInput == null) { + throw new NetconfException("Input object cannot be null"); + } else if (session == null) { + throw new NetconfException("Session is null when calling customRpcNetconf()"); + } + + String xmlQueryStr = encodeMoToXmlStr(customRpcInput, null); + xmlQueryStr = xmlQueryStr.replace("input", rpcName); + log.debug("Sending query on NETCONF session " + session.getSessionId() + + ":\n" + xmlQueryStr); + + String xmlResult = session.doWrappedRpc(xmlQueryStr); + xmlResult = removeRpcReplyData(xmlResult); + if (REGEX_RPC_OK.matcher(xmlResult).matches()) { + return null; + } + + DefaultCompositeStream resultDcs = new DefaultCompositeStream( + null, new ByteArrayInputStream(xmlResult.getBytes())); + CompositeData compositeData = xSer.decode(resultDcs, yCtx); + + return ((ModelConverter) yangModelRegistry).createModel(compositeData.resourceData()); + } + protected final String encodeMoToXmlStr(ModelObjectData yangObjectOpParamFilter, List annotations) throws NetconfException { @@ -231,8 +281,12 @@ public abstract class AbstractYangServiceImpl { } } - protected static final String removeRpcReplyData(String rpcReplyXml) { + protected static final String removeRpcReplyData(String rpcReplyXml) throws NetconfException { rpcReplyXml = REGEX_XML_HEADER.matcher(rpcReplyXml).replaceFirst(""); + if (rpcReplyXml.contains(" for " + + String xmlQueryStr = buildMepEssentialsQueryString(mdId, maId, mepId); + log.debug("Sending for MEP essentials" + " query on NETCONF session " + session.getSessionId() + ":\n" + xmlQueryStr); String xmlResult = session.get(xmlQueryStr, null); - xmlResult = removeRpcReplyData(xmlResult); + xmlResult = removePrefixedMessagePeriod(xmlResult); + DefaultCompositeStream resultDcs = new DefaultCompositeStream( + null, new ByteArrayInputStream(xmlResult.getBytes())); + CompositeData compositeData = xSer.decode(resultDcs, yCtx); + + ModelObjectData mod = ((ModelConverter) yangModelRegistry).createModel( + compositeData.resourceData()); + + MseaCfmOpParam mseaCfm = new MseaCfmOpParam(); + for (ModelObject mo:mod.modelObjects()) { + if (mo instanceof DefaultMefCfm) { + mseaCfm.mefCfm((DefaultMefCfm) mo); + } + } + return mseaCfm; + } + + @Override + public MseaCfm getMepFull(MdId mdId, MaIdShort maId, MepId mepId, + NetconfSession session) throws NetconfException { + if (session == null) { + throw new NetconfException("Session is null when calling getMepFull()"); + } + + String xmlQueryStr = buildMepFullQueryString(mdId, maId, mepId); + log.debug("Sending for full MEP" + + " query on NETCONF session " + session.getSessionId() + + ":\n" + xmlQueryStr); + + String xmlResult = session.get(xmlQueryStr, null); + xmlResult = removeRpcReplyData(xmlResult); + xmlResult = removePrefixedCcmInterval(xmlResult); DefaultCompositeStream resultDcs = new DefaultCompositeStream( null, new ByteArrayInputStream(xmlResult.getBytes())); CompositeData compositeData = xSer.decode(resultDcs, yCtx); @@ -94,41 +145,151 @@ public class MseaCfmManager extends AbstractYangServiceImpl } @Override - public MseaCfm getSoamDm(String mdName, String maName, int mepId, - int dmId, NetconfSession session) throws NetconfException { - String xmlQueryStr = buildDmQueryString(mdName, maName, mepId, dmId); - throw new UnsupportedOperationException("Not yet implemented"); + public MseaCfm getSoamDm(MdId mdName, MaIdShort maName, MepId mepId, + SoamId dmId, DmEntryParts parts, NetconfSession session) + throws NetconfException { + String xmlQueryStr = buildDmQueryString(mdName, maName, mepId, dmId, parts); + log.debug("Sending for " + + " query on NETCONF session " + session.getSessionId() + + ":\n" + xmlQueryStr); + + String xmlResult = session.get(xmlQueryStr, null); + xmlResult = removeRpcReplyData(xmlResult); + xmlResult = removePrefixedMessagePeriod(xmlResult); + DefaultCompositeStream resultDcs = new DefaultCompositeStream( + null, new ByteArrayInputStream(xmlResult.getBytes())); + CompositeData compositeData = xSer.decode(resultDcs, yCtx); + + ModelObjectData mod = ((ModelConverter) yangModelRegistry).createModel(compositeData.resourceData()); + + MseaCfmOpParam mseaCfm = new MseaCfmOpParam(); + for (ModelObject mo:mod.modelObjects()) { + if (mo instanceof DefaultMefCfm) { + mseaCfm.mefCfm((DefaultMefCfm) mo); + } + } + + return mseaCfm; } @Override public boolean setMseaCfm(MseaCfmOpParam mseaCfm, NetconfSession session, - DatastoreId targetDs) throws NetconfException { - ModelObjectData moEdit = DefaultModelObjectData.builder() - .addModelObject(mseaCfm).build(); + DatastoreId targetDs) throws NetconfException { - return setNetconfObject(moEdit, session, targetDs, null); + ModelObjectData moQuery = DefaultModelObjectData.builder() + .addModelObject((ModelObject) mseaCfm.mefCfm()).build(); + return setNetconfObject(moQuery, session, targetDs, null); } + @Override + public boolean deleteMseaCfmDm(MseaCfmOpParam mseaCfm, NetconfSession session, + DatastoreId targetDs) throws NetconfException { + + ModelObjectData mseCfmDmList = DefaultModelObjectData.builder() + .addModelObject((ModelObject) mseaCfm).build(); + + ArrayList anis = new ArrayList(); + if (mseaCfm != null && mseaCfm.mefCfm() != null) { + for (MaintenanceDomain md:mseaCfm.mefCfm().maintenanceDomain()) { + for (MaintenanceAssociation ma:md.maintenanceAssociation()) { + for (MaintenanceAssociationEndPoint mep:ma.maintenanceAssociationEndPoint()) { + AugmentedMseaCfmMaintenanceAssociationEndPoint mepAugment = + mep.augmentation(DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint.class); + if (mepAugment != null && mepAugment.delayMeasurements() != null) { + for (DelayMeasurement dms:mepAugment.delayMeasurements().delayMeasurement()) { + ResourceId.Builder ridBuilder = ResourceId.builder() + .addBranchPointSchema("/", null) + .addBranchPointSchema("mef-cfm", MSEA_CFM_NS) + .addBranchPointSchema("maintenance-domain", MSEA_CFM_NS) + .addKeyLeaf("id", MSEA_CFM_NS, md.id()) + .addBranchPointSchema("maintenance-association", MSEA_CFM_NS) + .addKeyLeaf("id", MSEA_CFM_NS, ma.id()) + .addBranchPointSchema("maintenance-association-end-point", MSEA_CFM_NS) + .addKeyLeaf("mep-id", MSEA_CFM_NS, mep.mepIdentifier()) + .addBranchPointSchema("delay-measurements", MSEA_CFM_PM_NS) + .addBranchPointSchema("delay-measurement", MSEA_CFM_PM_NS) + .addKeyLeaf("dm-id", MSEA_CFM_PM_NS, mep.mepIdentifier()); + AnnotatedNodeInfo ani = DefaultAnnotatedNodeInfo.builder() + .resourceId(ridBuilder.build()) + .addAnnotation(new DefaultAnnotation(NC_OPERATION, OP_DELETE)) + .build(); + anis.add(ani); + } + } + } + } + } + } + + return setNetconfObject(mseCfmDmList, session, targetDs, anis); + } + + @Override + public boolean deleteMseaMep(MseaCfmOpParam mseaCfm, NetconfSession session, + DatastoreId targetDs) throws NetconfException { + + ModelObjectData mseCfmMepList = DefaultModelObjectData.builder() + .addModelObject((ModelObject) mseaCfm.mefCfm()).build(); + + ArrayList anis = new ArrayList(); + if (mseaCfm != null && mseaCfm.mefCfm() != null) { + for (MaintenanceDomain md:mseaCfm.mefCfm().maintenanceDomain()) { + for (MaintenanceAssociation ma:md.maintenanceAssociation()) { + for (MaintenanceAssociationEndPoint mep:ma.maintenanceAssociationEndPoint()) { + ResourceId.Builder ridBuilder = ResourceId.builder() + .addBranchPointSchema("/", null) + .addBranchPointSchema("mef-cfm", MSEA_CFM_NS) + .addBranchPointSchema("maintenance-domain", MSEA_CFM_NS) + .addBranchPointSchema("maintenance-association", MSEA_CFM_NS) + .addBranchPointSchema("maintenance-association-end-point", MSEA_CFM_NS) + .addKeyLeaf("mep-identifier", MSEA_CFM_NS, mep.mepIdentifier().uint16()); + AnnotatedNodeInfo ani = DefaultAnnotatedNodeInfo.builder() + .resourceId(ridBuilder.build()) + .addAnnotation(new DefaultAnnotation(NC_OPERATION, OP_DELETE)) + .build(); + anis.add(ani); + } + } + } + } + + return setNetconfObject(mseCfmMepList, session, targetDs, anis); + } + + /** * Call RPCs on the device through NETCONF. */ @Override - public void transmitLoopback(TransmitLoopbackInput inputVar, NetconfSession session) throws NetconfException { - throw new UnsupportedOperationException("Not yet implemented"); + public void transmitLoopback(TransmitLoopbackInput inputVar, + NetconfSession session) throws NetconfException { + + ModelObjectData transLoopbackMo = DefaultModelObjectData.builder() + .addModelObject((ModelObject) inputVar).build(); + + customRpcNetconf(transLoopbackMo, + "transmit-loopback", session); } @Override - public void abortLoopback(AbortLoopbackInput inputVar, NetconfSession session) throws NetconfException { - throw new UnsupportedOperationException("Not yet implemented"); + public void abortLoopback(AbortLoopbackInput inputVar, + NetconfSession session) throws NetconfException { + ModelObjectData abortLoopbackMo = DefaultModelObjectData.builder() + .addModelObject((ModelObject) inputVar).build(); + + customRpcNetconf(abortLoopbackMo, "abort-loopback", session); } @Override - public TransmitLinktraceOutput transmitLinktrace(TransmitLinktraceInput inputVar, NetconfSession session) + public TransmitLinktraceOutput transmitLinktrace( + TransmitLinktraceInput inputVar, NetconfSession session) throws NetconfException { throw new UnsupportedOperationException("Not yet implemented"); } - private String buildMepQueryString(String mdName, String maName, int mepId) { + @Deprecated //Replace this with a ModelObject defintion + private String buildMepEssentialsQueryString(MdId mdId, MaIdShort maId, + MepId mepId) { StringBuilder rpc = new StringBuilder(); rpc.append("\n"); rpc.append("\n"); rpc.append("\n"); - rpc.append("" + mdName + "\n"); - rpc.append("\n"); + rpc.append("" + mdId.mdName() + "\n"); rpc.append("\n"); rpc.append("\n"); - rpc.append("" + maName + "\n"); + rpc.append("" + maId.maName() + "\n"); rpc.append("10ms\n"); rpc.append("\n"); rpc.append("\n"); rpc.append("\n"); - rpc.append("" + mepId + "\n"); - rpc.append("\n"); - rpc.append("\n"); - rpc.append("\n"); - rpc.append("\n"); - rpc.append("\n"); + rpc.append("" + mepId.id() + "\n"); rpc.append("\n"); - rpc.append("\n"); - rpc.append("\n"); - rpc.append("\n"); - rpc.append("\n"); - rpc.append("\n"); - rpc.append("\n"); - rpc.append("\n"); + rpc.append("\n"); + rpc.append("\n"); + rpc.append("\n"); + rpc.append("\n"); + rpc.append("\n"); + rpc.append("\n"); + rpc.append("\n"); + rpc.append("\n"); + rpc.append("\n"); + rpc.append("\n"); + rpc.append("\n"); + rpc.append("\n"); + rpc.append("\n"); + rpc.append("\n"); + rpc.append("\n"); rpc.append("\n"); rpc.append("\n"); rpc.append("\n"); @@ -167,8 +330,8 @@ public class MseaCfmManager extends AbstractYangServiceImpl return rpc.toString(); } - - private String buildDmQueryString(String mdName, String maName, int mepId, int dmId) { + @Deprecated //Replace this with a ModelObject defintion + private String buildMepFullQueryString(MdId mdId, MaIdShort maId, MepId mepId) { StringBuilder rpc = new StringBuilder(); rpc.append("\n"); rpc.append("\n"); rpc.append("\n"); - rpc.append("" + mdName + "\n"); - rpc.append("\n"); + rpc.append("" + mdId.mdName() + "\n"); rpc.append("\n"); rpc.append("\n"); - rpc.append("" + maName + "\n"); - rpc.append("10ms\n"); + rpc.append("" + maId.maName() + "\n"); rpc.append("\n"); - rpc.append("" + mepId + "\n"); - rpc.append(""); - rpc.append(""); - rpc.append("" + dmId + ""); - rpc.append(""); - rpc.append(""); + rpc.append("" + mepId.id() + "\n"); + rpc.append("\n"); + //Direction will always be DOWN for EA1000 + rpc.append("\n"); + rpc.append("\n"); + rpc.append("\n"); + rpc.append("\n"); + rpc.append("\n"); //Container + rpc.append("\n"); //Container + rpc.append("\n"); //Container + rpc.append("\n"); //Container + rpc.append("\n"); + rpc.append("\n"); + rpc.append("\n"); + rpc.append("\n"); + rpc.append("\n"); + rpc.append("\n"); rpc.append("\n"); rpc.append("\n"); rpc.append("\n"); @@ -197,4 +369,95 @@ public class MseaCfmManager extends AbstractYangServiceImpl return rpc.toString(); } + @Deprecated //Replace this with a ModelObject defintion + private String buildDmQueryString(MdId mdId, MaIdShort maId, MepId mepId, + SoamId dmId, DmEntryParts parts) { + StringBuilder rpc = new StringBuilder(); + + rpc.append("\n"); + rpc.append("\n"); + rpc.append("\n"); + rpc.append("" + mdId.mdName() + "\n"); + rpc.append("\n"); + rpc.append("\n"); + rpc.append("" + maId.maName() + "\n"); + rpc.append("\n"); + rpc.append("" + mepId.id() + "\n"); + if (dmId != null) { + rpc.append(""); + rpc.append("\n"); + rpc.append("" + dmId.id() + "\n"); + rpc.append(""); + rpc.append(""); + rpc.append("\n"); + rpc.append("\n"); + rpc.append("\n"); + rpc.append("\n"); + rpc.append("\n"); + rpc.append("\n"); + rpc.append("\n"); + rpc.append("\n"); + rpc.append("\n"); + rpc.append("\n"); + if (parts != null && (parts.equals(DmEntryParts.CURRENT_ONLY) || + parts.equals(DmEntryParts.ALL_PARTS))) { + rpc.append("\n"); + } + if (parts != null && (parts.equals(DmEntryParts.HISTORY_ONLY) || + parts.equals(DmEntryParts.ALL_PARTS))) { + rpc.append("\n"); + } + rpc.append("\n"); + rpc.append(""); + } else { + rpc.append(""); + } + rpc.append("\n"); + rpc.append("\n"); + rpc.append("\n"); + rpc.append(""); + + return rpc.toString(); + } + + @Deprecated //Replace this with a ModelObject defintion + private String buildAbortLoopbackQueryString(Short mdId, Short maId, + Short mepId) { + StringBuilder rpc = new StringBuilder(); + + rpc.append(""); + rpc.append("" + mdId + ""); + rpc.append("" + maId + ""); + rpc.append("" + mepId + ""); + rpc.append(""); + + return rpc.toString(); + } + + private static final String removePrefixedMessagePeriod(String xmlResult) { + xmlResult = xmlResult.replace("message-period>3ms" + MessagePeriodEnum.YANGAUTOPREFIX3MS.toString() + "10ms" + MessagePeriodEnum.YANGAUTOPREFIX10MS.toString() + "100ms" + MessagePeriodEnum.YANGAUTOPREFIX100MS.toString() + "1000ms" + MessagePeriodEnum.YANGAUTOPREFIX1000MS.toString() + "3.3ms" + CcmIntervalEnum.YANGAUTOPREFIX3_3MS.toString() + "10ms" + CcmIntervalEnum.YANGAUTOPREFIX10MS.toString() + "100ms" + CcmIntervalEnum.YANGAUTOPREFIX100MS.toString() + "1s" + CcmIntervalEnum.YANGAUTOPREFIX1S.toString() + " - - - - - - - - - - - + + + + + + + + + diff --git a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/EA1000CfmMepProgrammableTest.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/EA1000CfmMepProgrammableTest.java new file mode 100644 index 0000000000..1b8135c9e8 --- /dev/null +++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/EA1000CfmMepProgrammableTest.java @@ -0,0 +1,173 @@ +/* + * Copyright 2017-present Open Networking Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.drivers.microsemi; + +import static junit.framework.TestCase.fail; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.onosproject.drivers.microsemi.yang.utils.MaNameUtil; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMepLbCreate; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep.Priority; +import org.onosproject.incubator.net.l2monitoring.cfm.MepEntry; +import org.onosproject.incubator.net.l2monitoring.cfm.MepLbCreate; +import org.onosproject.incubator.net.l2monitoring.cfm.RemoteMepEntry.InterfaceStatusTlvType; +import org.onosproject.incubator.net.l2monitoring.cfm.RemoteMepEntry.PortStatusTlvType; +import org.onosproject.incubator.net.l2monitoring.cfm.RemoteMepEntry.RemoteMepState; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.MdNameAndTypeCombo; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.MaNameAndTypeCombo; + +/** + * Test of the CFM implementation on EA1000 through the incubator/net/l2monitoring interface. + */ +public class EA1000CfmMepProgrammableTest { + EA1000CfmMepProgrammable cfmProgrammable; + MdId mdId1 = MdIdCharStr.asMdId("md-1"); + MaIdShort maId11 = MaIdCharStr.asMaId("ma-1-1"); + MepId mep111 = MepId.valueOf((short) 1); + + @Before + public void setUp() throws Exception { + cfmProgrammable = new EA1000CfmMepProgrammable(); + cfmProgrammable.setHandler(new MockEa1000DriverHandler()); + assertNotNull(cfmProgrammable.handler().data().deviceId()); + } + + + @Ignore + @Test + public void testCreateMep() { + fail("Not yet implemented"); + } + + @Ignore + @Test + public void testGetAllMeps() { + fail("Not yet implemented"); + } + + @Test + public void testGetMep() throws CfmConfigException { + MepEntry mepEntry = cfmProgrammable.getMep(mdId1, maId11, mep111); + + //Result will come from MockNetconfSessionEa1000.SAMPLE_MSEACFM_MD_MA_MEP_FULL_REPLY + assertNotNull(mepEntry); + assertTrue(mepEntry.administrativeState()); + assertTrue(mepEntry.cciEnabled()); + assertEquals(Priority.PRIO5.name(), mepEntry.ccmLtmPriority().name()); + + assertTrue(mepEntry.activeMacStatusDefect()); //remote-mac-error + assertTrue(mepEntry.activeRdiCcmDefect()); //remote-rdi + + assertNotNull(mepEntry.activeRemoteMepList()); + + //TODO Comment back in this test - this is a serious issue with onos-yang-tools that only 1 is found + // See https://gerrit.onosproject.org/#/c/15164/ +// assertEquals("Expecting 2 Remote Meps", 2, mepEntry.activeRemoteMepList().size()); + mepEntry.activeRemoteMepList().forEach(rmep -> { + if (rmep.remoteMepId().value() == 1) { + assertEquals(RemoteMepState.RMEP_FAILED.name(), + rmep.state().toString()); + assertEquals(54654654L, rmep.failedOrOkTime().toMillis()); + assertEquals("aa:bb:cc:dd:ee:ff".toUpperCase(), rmep.macAddress().toString()); + assertFalse(rmep.rdi()); + assertEquals(PortStatusTlvType.PS_NO_STATUS_TLV.name(), + rmep.portStatusTlvType().toString()); + assertEquals(InterfaceStatusTlvType.IS_DORMANT.name(), + rmep.interfaceStatusTlvType().toString()); + } + }); + + } + + /** + * For sampleXmlRegexDeleteMseaCfmMep. + * @throws CfmConfigException If an error occurs + */ + @Test + public void testDeleteMep() throws CfmConfigException { + assertTrue(cfmProgrammable.deleteMep(mdId1, maId11, mep111)); + } + + /** + * For sampleXmlRegexTransmitLoopback. + * @throws CfmConfigException If an error occurs + */ + @Test + public void testTransmitLoopback() throws CfmConfigException { + MepLbCreate.MepLbCreateBuilder lbCreate = + DefaultMepLbCreate.builder(MepId.valueOf((short) 12)); + lbCreate.numberMessages(5); +// lbCreate.dataTlvHex("AA:BB:CC:DD:EE"); + lbCreate.vlanPriority(Priority.PRIO3); + lbCreate.vlanDropEligible(true); + + cfmProgrammable.transmitLoopback(mdId1, maId11, mep111, lbCreate.build()); + } + + @Test + public void testAbortLoopback() throws CfmConfigException { + cfmProgrammable.abortLoopback(mdId1, maId11, mep111); + } + +// @Test +// public void testTransmitLinktrace() { +// fail("Not yet implemented"); +// } + + @Test + public void testGetYangMdNameFromApiMdId() throws CfmConfigException { + MdNameAndTypeCombo name = EA1000CfmMepProgrammable + .getYangMdNameFromApiMdId(MdIdCharStr.asMdId("md-1")); + + assertEquals(org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm + .maintenancedomain.mdnameandtypecombo + .DefaultNameCharacterString.class, name.getClass()); + +//There's a problem with checkstyle for typecast on really long paths +// assertEquals("md-1", ((org.onosproject.yang.gen.v1.http.www.microsemi.com +// .microsemi.edge.assure.msea.cfm.rev20160229.mseacfm.mefcfm +// .maintenancedomain.mdnameandtypecombo +// .DefaultNameCharacterString) name).name().string()); + } + + @Test + public void testGetYangMaNameFromApiMaId() throws CfmConfigException { + MaNameAndTypeCombo name = MaNameUtil + .getYangMaNameFromApiMaId(MaIdCharStr.asMaId("ma-1-1")); + assertEquals(org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm + .maintenancedomain.maintenanceassociation.manameandtypecombo + .DefaultNameCharacterString.class, name.getClass()); + +//There's a problem with checkstyle for typecast on really long paths +// assertEquals("ma-1-1", ((org.onosproject.yang.gen.v1.http.www.microsemi.com +// .microsemi.edge.assure.msea.cfm.rev20160229.mseacfm.mefcfm +// .maintenancedomain.maintenanceassociation.manameandtypecombo +// .DefaultNameCharacterString) name).name().string()); + } + +} diff --git a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/EA1000SoamDmProgrammableTest.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/EA1000SoamDmProgrammableTest.java new file mode 100644 index 0000000000..59c674e5fa --- /dev/null +++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/EA1000SoamDmProgrammableTest.java @@ -0,0 +1,267 @@ +/* + * Copyright 2017-present Open Networking Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.drivers.microsemi; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.BitSet; +import java.util.Collection; + +import org.junit.Before; +import org.junit.Test; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep.Priority; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; +import org.onosproject.incubator.net.l2monitoring.soam.SoamConfigException; +import org.onosproject.incubator.net.l2monitoring.soam.SoamId; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DefaultDelayMeasurementCreate; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.DmCreateBuilder; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.DmType; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.MeasurementOption; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.Version; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementEntry; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementEntry.SessionStatus; + +public class EA1000SoamDmProgrammableTest { + + EA1000SoamDmProgrammable dmProgrammable; + MdId mdId1 = MdIdCharStr.asMdId("md-1"); + MaIdShort maId11 = MaIdCharStr.asMaId("ma-1-1"); + MepId mep111 = MepId.valueOf((short) 1); + + @Before + public void setUp() throws Exception { + dmProgrammable = new EA1000SoamDmProgrammable(); + dmProgrammable.setHandler(new MockEa1000DriverHandler()); + assertNotNull(dmProgrammable.handler().data().deviceId()); + } + + //TODO Implement all these tests +// @Test +// public void testEA1000SoamDmProgrammable() { +// fail("Not yet implemented"); +// } +// +// @Test +// public void testGetAllDms() { +// fail("Not yet implemented"); +// } + + /** + * From SAMPLE_MSEACFM_DELAY_MEASUREMENT_FULL_REPLY. + * @throws CfmConfigException + * @throws SoamConfigException + */ + @Test + public void testGetDm() throws CfmConfigException, SoamConfigException { + DelayMeasurementEntry dmEntry = + dmProgrammable.getDm(mdId1, maId11, mep111, SoamId.valueOf(1)); + assertEquals(1, dmEntry.dmId().id().intValue()); + assertEquals(2, dmEntry.measurementsEnabled().size()); + assertEquals(SessionStatus.ACTIVE.name(), dmEntry.sessionStatus().name()); + assertEquals(100, dmEntry.frameDelayTwoWay().toNanos() / 1000); + assertEquals(101, dmEntry.interFrameDelayVariationTwoWay().toNanos() / 1000); + } + + @Test + public void testCreateDm() throws CfmConfigException, SoamConfigException { + DmCreateBuilder dmBuilder = (DmCreateBuilder) DefaultDelayMeasurementCreate + .builder(DmType.DMDMM, Version.Y17312011, + MepId.valueOf((short) 10), Priority.PRIO3) + .frameSize((short) 1200); + + dmProgrammable.createDm(mdId1, maId11, mep111, dmBuilder.build()); + } + + @Test + public void testCreateDmWrongMsgPeriod() + throws CfmConfigException, SoamConfigException { + DmCreateBuilder dmBuilder = (DmCreateBuilder) DefaultDelayMeasurementCreate + .builder(DmType.DMDMM, Version.Y17312011, + MepId.valueOf((short) 10), Priority.PRIO3) + .messagePeriod(Duration.ofMillis(1234)); + + try { + dmProgrammable.createDm(mdId1, maId11, mep111, dmBuilder.build()); + fail("Expecting to get an exception"); + } catch (SoamConfigException e) { + assertTrue(e.getMessage() + .contains("EA1000 supports only Message Periods")); + } + + } + +// @Test +// public void testGetDmCurrentStat() { +// fail("Not yet implemented"); +// } +// +// @Test +// public void testGetDmHistoricalStats() { +// fail("Not yet implemented"); +// } +// +// @Test +// public void testAbortDmMdIdMaIdShortMepIdSoamId() { +// fail("Not yet implemented"); +// } +// +// @Test +// public void testBuildApiDmFromYangDm() { +// fail("Not yet implemented"); +// } +// +// @Test +// public void testAbortDmMdIdMaIdShortMepId() { +// fail("Not yet implemented"); +// } +// +// @Test +// public void testClearDelayHistoryStatsMdIdMaIdShortMepId() { +// fail("Not yet implemented"); +// } +// +// @Test +// public void testClearDelayHistoryStatsMdIdMaIdShortMepIdSoamId() { +// fail("Not yet implemented"); +// } +// +// @Test +// public void testGetAllLms() { +// fail("Not yet implemented"); +// } +// +// @Test +// public void testGetLm() { +// fail("Not yet implemented"); +// } +// +// @Test +// public void testGetLmCurrentStat() { +// fail("Not yet implemented"); +// } +// +// @Test +// public void testGetLmHistoricalStats() { +// fail("Not yet implemented"); +// } +// +// @Test +// public void testCreateLm() { +// fail("Not yet implemented"); +// } +// +// @Test +// public void testAbortLmMdIdMaIdShortMepId() { +// fail("Not yet implemented"); +// } +// +// @Test +// public void testAbortLmMdIdMaIdShortMepIdSoamId() { +// fail("Not yet implemented"); +// } +// +// @Test +// public void testClearLossHistoryStatsMdIdMaIdShortMepId() { +// fail("Not yet implemented"); +// } +// +// @Test +// public void testClearLossHistoryStatsMdIdMaIdShortMepIdSoamId() { +// fail("Not yet implemented"); +// } + + @Test + public void testCreateTestSignal() { + try { + dmProgrammable.createTestSignal(mdId1, maId11, mep111, null); + fail("Expected an exception"); + } catch (UnsupportedOperationException e) { + assertEquals("Not supported by EA1000", e.getMessage()); + } catch (CfmConfigException e) { + fail("CfmConfigException was not expected"); + } + } + + @Test + public void testAbortTestSignal() { + try { + dmProgrammable.abortTestSignal(mdId1, maId11, mep111); + fail("Expected an exception"); + } catch (UnsupportedOperationException e) { + assertEquals("Not supported by EA1000", e.getMessage()); + } catch (CfmConfigException e) { + fail("CfmConfigException was not expected"); + } + } + + @Test + public void testMeasurementEnableCollectionOfMeasurementOption() { + BitSet meBs = BitSet.valueOf(new byte[]{0x05}); + Collection moSet = + EA1000SoamDmProgrammable.getMeasurementOptions(meBs); + assertTrue(moSet.contains(MeasurementOption.SOAM_PDUS_RECEIVED)); + assertTrue(moSet.contains(MeasurementOption.FRAME_DELAY_TWO_WAY_MIN)); + } + + @Test + public void testMeasurementEnableBitSetEmpty() { + Collection moSet = new ArrayList<>(); + try { + BitSet bitSet = EA1000SoamDmProgrammable.getMeasurementEnabledSet(moSet); + assertEquals("{}", bitSet.toString()); + } catch (SoamConfigException e) { + fail("Was not expecting exception here"); + } + } + + @Test + public void testMeasurementEnableBitSetInvalid() { + Collection moSet = new ArrayList<>(); + moSet.add(MeasurementOption.FRAME_DELAY_BACKWARD_BINS); + moSet.add(MeasurementOption.FRAME_DELAY_RANGE_BACKWARD_AVERAGE); + try { + EA1000SoamDmProgrammable.getMeasurementEnabledSet(moSet); + fail("Was expecting an exception"); + } catch (SoamConfigException e) { + assertTrue(e.getMessage() + .contains("Measurement Option is not supported on EA1000")); + } + } + + @Test + public void testMeasurementEnableBitSet2Good() { + Collection moSet = new ArrayList<>(); + moSet.add(MeasurementOption.FRAME_DELAY_TWO_WAY_BINS); + moSet.add(MeasurementOption.FRAME_DELAY_TWO_WAY_AVERAGE); + try { + BitSet bitSet = EA1000SoamDmProgrammable.getMeasurementEnabledSet(moSet); + assertEquals("{1, 4}", bitSet.toString()); + } catch (SoamConfigException e) { + fail("Was not expecting exception here"); + } + } + +} diff --git a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/MockEa1000DriverHandler.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/MockEa1000DriverHandler.java index 75c6811940..58a8a5b090 100644 --- a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/MockEa1000DriverHandler.java +++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/MockEa1000DriverHandler.java @@ -19,14 +19,18 @@ import java.util.HashMap; import java.util.Map; import org.onosproject.core.CoreService; +import org.onosproject.drivers.microsemi.yang.MockCfmMdService; +import org.onosproject.drivers.microsemi.yang.MockMseaCfmManager; import org.onosproject.drivers.microsemi.yang.MockMseaSaFilteringManager; import org.onosproject.drivers.microsemi.yang.MockMseaUniEvcServiceManager; import org.onosproject.drivers.microsemi.yang.MockNetconfSessionEa1000; +import org.onosproject.drivers.microsemi.yang.MseaCfmNetconfService; import org.onosproject.drivers.microsemi.yang.MseaSaFilteringNetconfService; import org.onosproject.drivers.microsemi.yang.MseaUniEvcServiceNetconfService; import org.onosproject.drivers.netconf.MockCoreService; import org.onosproject.drivers.netconf.MockNetconfController; import org.onosproject.drivers.netconf.MockNetconfDevice; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMdService; import org.onosproject.net.DeviceId; import org.onosproject.net.driver.Behaviour; import org.onosproject.net.driver.DefaultDriver; @@ -53,6 +57,8 @@ public class MockEa1000DriverHandler implements DriverHandler { private NetconfController ncc; private MockMseaSaFilteringManager mseaSaFilteringService; private MockMseaUniEvcServiceManager mseaUniEvcService; + private MockMseaCfmManager mseaCfmService; + private MockCfmMdService mockMdService; private CoreService coreService; public MockEa1000DriverHandler() throws NetconfException { @@ -63,7 +69,9 @@ public class MockEa1000DriverHandler implements DriverHandler { Map properties = new HashMap(); Driver mockDriver = - new DefaultDriver("mockDriver", null, "ONOSProject", "1.0.0", "1.0.0", behaviours, properties); + new DefaultDriver("mockDriver", null, + "ONOSProject", "1.0.0", + "1.0.0", behaviours, properties); DeviceId mockDeviceId = DeviceId.deviceId("netconf:1.2.3.4:830"); mockDriverData = new DefaultDriverData(mockDriver, mockDeviceId); @@ -78,6 +86,12 @@ public class MockEa1000DriverHandler implements DriverHandler { mseaUniEvcService = new MockMseaUniEvcServiceManager(); mseaUniEvcService.activate(); + mseaCfmService = new MockMseaCfmManager(); + mseaCfmService.activate(); + + mockMdService = new MockCfmMdService(); + mockMdService.activate(); + coreService = new MockCoreService(); coreService.registerApplication(MICROSEMI_DRIVERS); } @@ -109,9 +123,14 @@ public class MockEa1000DriverHandler implements DriverHandler { } else if (serviceClass.equals(MseaUniEvcServiceNetconfService.class)) { return (T) mseaUniEvcService; + } else if (serviceClass.equals(MseaCfmNetconfService.class)) { + return (T) mseaCfmService; + } else if (serviceClass.equals(CoreService.class)) { return (T) coreService; + } else if (serviceClass.equals(CfmMdService.class)) { + return (T) mockMdService; } return null; diff --git a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockCfmMdService.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockCfmMdService.java new file mode 100644 index 0000000000..ba6d6561eb --- /dev/null +++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockCfmMdService.java @@ -0,0 +1,63 @@ +/* + * Copyright 2017-present Open Networking Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.drivers.microsemi.yang; + +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMaintenanceAssociation; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMaintenanceDomain; +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceAssociation; +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.impl.CfmMdManager; +import static org.easymock.EasyMock.*; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; +import org.onosproject.incubator.net.l2monitoring.cfm.service.MdStore; + +import java.util.Optional; + +public class MockCfmMdService extends CfmMdManager { + + @Override + public void activate() { + store = createMock(MdStore.class); + + try { + MaintenanceAssociation ma = DefaultMaintenanceAssociation + .builder(MaIdCharStr.asMaId("ma-1-1"), 6) + .maNumericId((short) 1) + .ccmInterval(MaintenanceAssociation.CcmInterval.INTERVAL_3MS) + .build(); + + MdId md1Name = MdIdCharStr.asMdId("md-1"); + MaintenanceDomain md1 = DefaultMaintenanceDomain + .builder(md1Name) + .mdNumericId((short) 1) + .mdLevel(MaintenanceDomain.MdLevel.LEVEL3) + .addToMaList(ma) + .build(); + + expect(store.createUpdateMaintenanceDomain(md1)) + .andReturn(true); + expect(store.getMaintenanceDomain(md1Name)) + .andReturn(Optional.of(md1)).anyTimes(); + replay(store); + + } catch (CfmConfigException e) { + throw new IllegalArgumentException("Error creating Md md-1 for test"); + } + } +} diff --git a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockNetconfSessionEa1000.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockNetconfSessionEa1000.java index 8068cffe86..d2c07e5edc 100644 --- a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockNetconfSessionEa1000.java +++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockNetconfSessionEa1000.java @@ -72,10 +72,23 @@ public class MockNetconfSessionEa1000 extends NetconfSessionAdapter { private Pattern sampleXmlRegexSaFiltering = Pattern.compile("(<\\?xml).*" - + "().*" - + "().*().*().*().*" - + "(]]>){2}", Pattern.DOTALL); + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?()\\R?()\\R?(]]>){2}", Pattern.DOTALL); + + private Pattern sampleXmlRegexSaFilteringErrorScenario = + Pattern.compile("(<\\?xml).*" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()10()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?()\\R?()\\R?(]]>){2}", Pattern.DOTALL); private Pattern sampleXmlRegexEditConfigSaFilt = Pattern.compile("(<\\?xml).*().*" @@ -328,7 +341,7 @@ public class MockNetconfSessionEa1000 extends NetconfSessionAdapter { + "()\\R?" + "()\\R?" + "()([a-zA-Z0-9\\-:\\.]){1,48}()\\R?" - + "()\\R?" + + "()?\\R?" + "()\\R?" + "()\\R?" + "()([a-zA-Z0-9\\-:\\.]){1,48}()\\R?" @@ -337,19 +350,22 @@ public class MockNetconfSessionEa1000 extends NetconfSessionAdapter { + "()\\R?" + "()\\R?" + "()[0-9]{1,4}()\\R?" - + "()\\R?" - + "()\\R?" - + "()\\R?" - + "()\\R?" - + "()\\R?" - + "()\\R?" - + "()\\R?" - + "()\\R?" - + "()\\R?" - + "()\\R?" - + "()\\R?" - + "()\\R?" - + "()\\R?" + + "()?\\R?" + + "(()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "())?\\R?" + + "(()\\R?" + + "()\\R?" + + "(()|([0-9]*))\\R?" + + "()\\R?" + + "())?\\R?" + + "(()\\R?" + + "()\\R?" + + "(()|([0-9]*))\\R?" + + "()\\R?" + + "())?\\R?" + "()\\R?" + "()\\R?" + "()\\R?" @@ -359,6 +375,164 @@ public class MockNetconfSessionEa1000 extends NetconfSessionAdapter { + "()\\R?" + "(]]>){2}", Pattern.DOTALL); + //For testGetConfigMseaCfmEssentials + private Pattern sampleXmlRegexGetMseaCfmFull = + Pattern.compile("(<\\?xml).*()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()([a-zA-Z0-9\\-:\\.]){1,48}()\\R?" + + "()?\\R?" + + "()\\R?" + + "()\\R?" + + "()([a-zA-Z0-9\\-:\\.]){1,48}()\\R?" + + "()\\R?" + + "()[0-9]{1,4}()\\R?" + + "()?\\R?" + + "()?\\R?" + + "()?\\R?" + + "()?\\R?" + + "()?\\R?" + + "()?\\R?" + + "()?\\R?" + + "()?\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "(]]>){2}", Pattern.DOTALL); + + //For testGetConfigMseaCfmEssentials + private Pattern sampleXmlRegexGetMseaDelay = + Pattern.compile("(<\\?xml).*()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()([a-zA-Z0-9\\-:\\.]){1,48}()\\R?" + + "()\\R?" + + "()\\R?" + + "()([a-zA-Z0-9\\-:\\.]){1,48}()\\R?" + + "()\\R?" + + "()[0-9]{1,4}()\\R?" + + "(()\\R?" + + "()\\R?" + + "(()|([0-9]*))\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()?\\R?" + + "()?\\R?" + + "()\\R?" + + "())?\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "(]]>){2}", Pattern.DOTALL); + + //For testGetConfigMseaCfmEssentials + private Pattern sampleXmlRegexDeleteMseaCfmMep = + Pattern.compile("(<\\?xml).*()\\R?" + + "(\\R?\\R?)\\R?" + + "()\\R?" + + "()\\R?" + + "()?\\R?" + + "()([a-zA-Z0-9\\-:\\.]){1,48}()\\R?" + + "()\\R?" + + "()?\\R?" + + "()([a-zA-Z0-9\\-:\\.]){1,48}()\\R?" + + "()\\R?" + + "()[0-9]{1,4}()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?()\\R?(]]>){2}", Pattern.DOTALL); + + + private Pattern sampleXmlRegexTransmitLoopback = + Pattern.compile("(<\\?xml).*()\\R?" + + "(()[0-9]*())?\\R?" + + "(()[a-zA-Z0-9+=/]*())?\\R?" + + "(()[0-9]{1}())?\\R?" + + "(()((true)|(false))())?\\R?" + + "()[0-9]{1,4}()\\R?" + + "()[0-9]{1,5}()\\R?" + + "()[0-9]{1,5}()\\R?" + + "()\\R?" + + "(()[0-9]{1,4}())?\\R?" + + "(()[a-fA-F0-9:-]{17}())?\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "(]]>){2}", Pattern.DOTALL); + + private Pattern sampleXmlRegexAbortLoopback = + Pattern.compile("(<\\?xml).*()\\R?" + + "()[0-9]{1,4}()\\R?" + + "()[0-9]{1,5}()\\R?" + + "()[0-9]{1,5}()\\R?" + + "()\\R?" + + "()\\R?" + + "(]]>){2}", Pattern.DOTALL); + + //For testCreateDm() + private Pattern sampleXmlRegexEditConfigDmCreate = + Pattern.compile("(<\\?xml).*()\\R?" + + "(\\R?\\R?)\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()[0-9]*()\\R?" + + "()\\R?" + + "()[0-9]*()\\R?" + + "()\\R?" + + "()[0-9]*()\\R?" + + "()\\R?" + + "()\\R?" + + "()[0-9]*()\\R?" + + "(()(true|false)())?\\R?" + + "(()(1000ms|100ms|10ms|3ms)())?\\R?" + + "()[0-9]*()\\R?" + + "(()[0-9]*())?\\R?" + + "()[0-9]*()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?" + + "()\\R?()\\R?(]]>){2}", Pattern.DOTALL); + private static final String SAMPLE_SYSTEM_REPLY = "\n" + "\n" @@ -410,6 +584,17 @@ public class MockNetconfSessionEa1000 extends NetconfSessionAdapter { + "\n" + ""; + private static final String SAMPLE_ERROR_REPLY = "\n" + + "\n" + + "" + + "application" + + "data-missing" + + "error" + + "Request could not be completed because " + + "the relevant data model content does not exist." + + "" + + ""; + private static final String SAMPLE_MSEAEVCUNI_REPLY_INIT = "\n" + "\n" + "\n" @@ -592,7 +777,7 @@ public class MockNetconfSessionEa1000 extends NetconfSessionAdapter { + "\n" + ""; - private static final String SAMPLE_MSEACFM_MD_MA_MEP_REPLY = + private static final String SAMPLE_MSEACFM_MD_MA_MEP_ESSENTIALS_REPLY = "" + "" + "" @@ -602,72 +787,41 @@ public class MockNetconfSessionEa1000 extends NetconfSessionAdapter { + "" + "1" + "md-1" - + "3" + "" + "1" + "ma-1-1" - + "10ms" //Causing problems on create of MA - + "1" - + "2" - + "" - + "100" - + "vlan-stag" - + "" + "" + "1" - + "eth1" - + "100" - + "true" - + "4" - + "" - + "true" - + "report-defect" - + "remote-mac-error" - + " remote-mac-error invalid-ccm" - + "U2FtcGxlIGxhc3QgZXJyb3IgY2NtAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" - + "AAAAAAAAAAAAAAAAAAAAAAAAAAAA==" - + "10" - + "15" - + "" - + "53:65:61:6e:20:43" - + "no-status-tlv" - + "no-status-tlv" -// + "" --Can't handle this at the moment - + "false" - + "" - + "123" - + "456" - + "" + + "00:b0:ae:03:ff:31" + "" + "" + + "1" + + "" + + "" + "2" - + "ok" - + "1490692834" - + "53:65:61:6e:20:43" - + "true" - + "up" - + "dormant" + "" + "" - + "" - + "0" - + "2" - + "2" - + "2" - + "2" - + "" - + "" + + "" + + "" + + "1" + + "" + + "" + + "" + + "" + + "1" + + "" + + "" + + "2" + + "" + + "" + "" - + "4" + "" + "" + "" + "" + ""; - private static final String SAMPLE_MSEACFM_MD_MA_MEP_REPLY2 = + private static final String SAMPLE_MSEACFM_MD_MA_MEP_FULL_REPLY = "" + "" + "" @@ -676,63 +830,100 @@ public class MockNetconfSessionEa1000 extends NetconfSessionAdapter { + "xmlns:msea-soam-pm=\"http://www.microsemi.com/microsemi-edge-assure/msea-soam-pm\">" + "" + "1" - + "Microsemi" - + "2" + + "md-1" + "" + "1" - + "example-ma" - + "1" - + "2" - + "" - + "100" - + "vlan-stag" - + "" + + "ma-1-1" + + "3.3ms" + "" - + "4" - + "eth1" - + "100" + + "1" + + "eth0" + + "20" + "true" - + "4" + + "00:b0:ae:03:ff:31" + + "5" + "" + "true" + "defect-reported" + "remote-invalid-ccm" -// + " remote-invalid-ccm" - + "" + + "remote-rdi remote-invalid-ccm" + "0" - + "41013" + + "197" + "" - + "00:b0:ae:03:ff:31" + + "" + + "" + + "" + + "" + + "" + + "" + + "1" + + "failed" + + "54654654" + + "aa:bb:cc:dd:ee:ff" + + "false" + + "no-status-tlv" + + "dormant" + + "" + + "" + + "2" + + "failed" + + "54654654" + + "aa:bb:cc:dd:ee:ff" + + "false" + + "no-status-tlv" + + "dormant" + + "" + + "" + + "enabled" + + "partially-active" + "up" + "up" + + "remote-rdi remote-mac-error" + "true" - + "" - + "0" - + "0" - + "" - + "" - + "" - + "1" - + "failed" - + "26315533" - + "00:00:00:00:00:00" - + "false" - + "no-status-tlv" - + "no-status-tlv" - + "" - + "" - + "2" - + "failed" - + "26315541" - + "00:00:00:00:00:00" - + "false" - + "no-status-tlv" - + "no-status-tlv" - + "" - + "" - + "" + "" - + "4" + + "" + + "" + + "" + + "" + + ""; + + private static final String SAMPLE_MSEACFM_DELAY_MEASUREMENT_FULL_REPLY = + "" + + "" + + "" + + "" + + "" + + "1" + + "md-1" + + "" + + "1" + + "ma-1-1" + + "" + + "1" + + "" + + "" + + "1" + + "10" + + "true" + + "frame-delay-two-way-bins " + + "frame-delay-two-way-max" + + "3ms" + + "6" + + "1000" + + "15" + + "32" + + "active" + + "100" + + "101" +// + "" +// + "" +// + "" +// + "" + + "" + + "" + + "" + "" + "" + "" @@ -966,6 +1157,9 @@ public class MockNetconfSessionEa1000 extends NetconfSessionAdapter { } else if (sampleXmlRegex2.matcher(request).matches()) { return SAMPLE_SYSTEM_REPLY_INIT; + } else if (sampleXmlRegexSaFilteringErrorScenario.matcher(request).matches()) { + return SAMPLE_ERROR_REPLY; + } else if (sampleXmlRegexSaFiltering.matcher(request).matches()) { return SAMPLE_MSEASAFILTERING_FE_REPLY; @@ -1009,7 +1203,25 @@ public class MockNetconfSessionEa1000 extends NetconfSessionAdapter { return SAMPLE_REPLY_OK; } else if (sampleXmlRegexGetMseaCfmEssentials.matcher(request).matches()) { - return SAMPLE_MSEACFM_MD_MA_MEP_REPLY2; + return SAMPLE_MSEACFM_MD_MA_MEP_ESSENTIALS_REPLY; + + } else if (sampleXmlRegexGetMseaCfmFull.matcher(request).matches()) { + return SAMPLE_MSEACFM_MD_MA_MEP_FULL_REPLY; + + } else if (sampleXmlRegexDeleteMseaCfmMep.matcher(request).matches()) { + return SAMPLE_REPLY_OK; + + } else if (sampleXmlRegexGetMseaDelay.matcher(request).matches()) { + return SAMPLE_MSEACFM_DELAY_MEASUREMENT_FULL_REPLY; + + } else if (sampleXmlRegexEditConfigDmCreate.matcher(request).matches()) { + return SAMPLE_REPLY_OK; + + } else if (sampleXmlRegexTransmitLoopback.matcher(request).matches()) { + return SAMPLE_REPLY_OK; + + } else if (sampleXmlRegexAbortLoopback.matcher(request).matches()) { + return SAMPLE_REPLY_OK; } else { throw new NetconfException("MocknetconfSession. No sendRequest() case for query: " + diff --git a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MseaCfmManagerTest.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MseaCfmManagerTest.java index 2908d53e1e..fe99bf3d05 100644 --- a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MseaCfmManagerTest.java +++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MseaCfmManagerTest.java @@ -26,18 +26,42 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; import org.onlab.packet.Ip4Address; +import org.onosproject.drivers.microsemi.yang.MseaCfmNetconfService.DmEntryParts; import org.onosproject.drivers.microsemi.yang.impl.MseaCfmManager; +import org.onosproject.drivers.microsemi.yang.utils.MepIdUtil; +import org.onosproject.drivers.microsemi.yang.utils.MepIdUtil2; +import org.onosproject.drivers.microsemi.yang.utils.MepIdUtil3; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; +import org.onosproject.incubator.net.l2monitoring.soam.SoamId; import org.onosproject.netconf.NetconfDeviceInfo; import org.onosproject.netconf.NetconfException; import org.onosproject.netconf.NetconfSession; +import org.onosproject.yang.gen.v1.ietfyangtypes.rev20130715.ietfyangtypes.MacAddress; import org.onosproject.yang.gen.v1.mseacfm.rev20160229.MseaCfm; import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.DefaultMefCfm; import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.MefCfm; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.abortloopback.AbortLoopbackInput; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.abortloopback.DefaultAbortLoopbackInput; import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.DefaultMaintenanceDomain; import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.MaintenanceDomain; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.MaintenanceAssociationEndPoint; import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.DefaultNameCharacterString; import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.NameCharacterString; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.targetaddressgroup.AddressType; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.targetaddressgroup.addresstype.DefaultMacAddress; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.targetaddressgroup.addresstype.DefaultMepId; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitloopback.DefaultTransmitLoopbackInput; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitloopback.TransmitLoopbackInput; +import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitloopback.transmitloopbackinput.DefaultTargetAddress; +import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.augmentedmseacfmmaintenanceassociationendpoint.delaymeasurements.DelayMeasurement; +import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain.maintenanceassociation.maintenanceassociationendpoint.augmentedmseacfmmaintenanceassociationendpoint.lossmeasurements.lossmeasurement.MessagePeriodEnum; +import org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.sessionstatustype.SessionStatusTypeEnum; import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.Identifier45; +import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.MepIdType; +import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.PriorityType; public class MseaCfmManagerTest { @@ -52,7 +76,8 @@ public class MseaCfmManagerTest { } catch (UncheckedIOException e) { fail(e.getMessage()); } - NetconfDeviceInfo deviceInfo = new NetconfDeviceInfo("netconf", "netconf", Ip4Address.valueOf("1.2.3.4"), 830); + NetconfDeviceInfo deviceInfo = new NetconfDeviceInfo("netconf", "netconf", + Ip4Address.valueOf("1.2.3.4"), 830); session = new MockNetconfSessionEa1000(deviceInfo); } @@ -61,13 +86,92 @@ public class MseaCfmManagerTest { } @Test - public void testGetConfigMseaCfmEssentials() throws NetconfException { - MseaCfm mseaCfm = mseaCfmService.getMepEssentials("md-1", "ma-1-1", 1, session); + public void testGetConfigMseaCfmEssentials() + throws NetconfException, CfmConfigException { + MseaCfm mseaCfm = mseaCfmService.getMepEssentials( + MdIdCharStr.asMdId("md-1"), + MaIdCharStr.asMaId("ma-1-1"), + MepId.valueOf((short) 1), session); assertNotNull(mseaCfm); - //See SAMPLE_MSEACFM_MD_MA_MEP_REPLY in MockNetconfSessionEa1000 + //See SAMPLE_MSEACFM_MD_MA_MEP_ESSENTIALS_REPLY in MockNetconfSessionEa1000 assertEquals(1, mseaCfm.mefCfm().maintenanceDomain().size()); - assertEquals(2, mseaCfm.mefCfm().maintenanceDomain().get(0).mdLevel().uint8()); + } + + @Test + public void testGetConfigMseaCfmFull() + throws NetconfException, CfmConfigException { + MseaCfm mseaCfm = mseaCfmService.getMepFull( + MdIdCharStr.asMdId("md-1"), + MaIdCharStr.asMaId("ma-1-1"), + MepId.valueOf((short) 1), session); + assertNotNull(mseaCfm); + + //See SAMPLE_MSEACFM_MD_MA_MEP_FULL_REPLY in MockNetconfSessionEa1000 + assertEquals(1, mseaCfm.mefCfm().maintenanceDomain().size()); + MaintenanceAssociationEndPoint mep = mseaCfm.mefCfm() + .maintenanceDomain().get(0) + .maintenanceAssociation().get(0) + .maintenanceAssociationEndPoint().get(0); + assertTrue(mep.administrativeState()); + assertEquals("00:b0:ae:03:ff:31", mep.macAddress().toString()); + + org.onosproject.yang.gen.v1.mseasoamfm.rev20160229.mseasoamfm.mefcfm.maintenancedomain + .maintenanceassociation.maintenanceassociationendpoint + .AugmentedMseaCfmMaintenanceAssociationEndPoint augmentedMep = + MepIdUtil2.convertFmAugmentedMep(mep); + + assertEquals("partially-active", augmentedMep.connectivityStatus().toString()); + assertEquals("up", augmentedMep.interfaceStatus().enumeration().toString()); + } + + /** + * Driven by SAMPLE_MSEACFM_DELAY_MEASUREMENT_FULL_REPLY. + * @throws NetconfException If there's a problem + */ + @Test + public void testGetSoamDm() throws NetconfException { + MseaCfm mseaCfmWithDm = mseaCfmService.getSoamDm( + MdIdCharStr.asMdId("md-1"), + MaIdCharStr.asMaId("ma-1-1"), + MepId.valueOf((short) 1), + SoamId.valueOf(1), + DmEntryParts.ALL_PARTS, session); + + assertNotNull(mseaCfmWithDm); + MaintenanceAssociationEndPoint mep = mseaCfmWithDm.mefCfm() + .maintenanceDomain().get(0) + .maintenanceAssociation().get(0) + .maintenanceAssociationEndPoint().get(0); + + //Because of a checkstyle problem with typecasts including really long + //package names, this has to be handed off to a different class + org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.mefcfm.maintenancedomain + .maintenanceassociation.maintenanceassociationendpoint + .AugmentedMseaCfmMaintenanceAssociationEndPoint augmentedMep = + MepIdUtil.convertPmAugmentedMep(mep); + + DelayMeasurement dm = augmentedMep.delayMeasurements().delayMeasurement().get(0); + assertEquals(true, dm.administrativeState()); + assertTrue(dm.measurementEnable().get(3)); //frame-delay-two-way-bins + assertTrue(dm.measurementEnable().get(1)); //frame-delay-two-way-max + + assertEquals(MessagePeriodEnum.YANGAUTOPREFIX3MS.name(), dm.messagePeriod().name()); + assertEquals(6, dm.priority().uint8()); + assertEquals(1000, dm.frameSize()); + assertEquals(15, dm.measurementInterval()); + assertEquals(32, dm.numberIntervalsStored()); + assertEquals(SessionStatusTypeEnum.ACTIVE.name(), + dm.sessionStatus().enumeration().name()); + assertEquals(100, dm.frameDelayTwoWay().uint32()); + assertEquals(101, dm.interFrameDelayVariationTwoWay().uint32()); + + //The remoteMep of the DM is a choice, which for mepId is a leafref object + org.onosproject.yang.gen.v1.mseasoampm.rev20160229.mseasoampm.remotemepgroup.remotemep + .DefaultMepId remoteMepId = MepIdUtil3.convertPmRemoteMepToMepId(dm.remoteMep()); + assertNotNull(remoteMepId); + assertEquals(10, ((MepIdType) remoteMepId.mepId()).uint16()); + } /** @@ -91,20 +195,67 @@ public class MseaCfmManagerTest { } @Test - public void testTransmitLoopback() throws NetconfException { + /** + * Using Remote remote MEP ID and all arguments. + */ + public void testTransmitLoopback1() { + TransmitLoopbackInput lbTr1 = new DefaultTransmitLoopbackInput(); + lbTr1.maintenanceDomain(Short.valueOf((short) 1)); + lbTr1.maintenanceAssociation(Short.valueOf((short) 2)); + lbTr1.maintenanceAssociationEndPoint(Short.valueOf((short) 3)); + + DefaultTargetAddress ta = new DefaultTargetAddress(); + DefaultMepId mepId = new DefaultMepId(); + mepId.mepId(MepIdType.of(4)); + ta.addressType((AddressType) mepId); + lbTr1.targetAddress(ta); + +// lbTr1.dataTlv(new byte[]{0x01, 0x02, 0x03}); Not supported in onos-yang-tools just yet + lbTr1.numberOfMessages(10); + lbTr1.vlanDropEligible(true); + lbTr1.vlanPriority(PriorityType.of((short) 1)); try { - mseaCfmService.transmitLoopback(null, session); - } catch (UnsupportedOperationException e) { - assertTrue(e.getMessage().contains("Not yet implemented")); + mseaCfmService.transmitLoopback(lbTr1, session); + } catch (NetconfException e) { + fail("Calling of TransmitLoopback failed: " + e.getMessage()); + } + } + + @Test + /** + * Using Remote Mac address in place of remote MEP ID and fewer arguments. + */ + public void testTransmitLoopback2() { + TransmitLoopbackInput lbTr2 = new DefaultTransmitLoopbackInput(); + + lbTr2.maintenanceDomain(Short.valueOf((short) 63)); + lbTr2.maintenanceAssociation(Short.valueOf((short) 62)); + lbTr2.maintenanceAssociationEndPoint(Short.valueOf((short) 61)); + + DefaultTargetAddress ta = new DefaultTargetAddress(); + DefaultMacAddress macAddr = new DefaultMacAddress(); + macAddr.macAddress(MacAddress.of("FF:EE:DD:CC:BB:AA")); + ta.addressType(macAddr); + lbTr2.targetAddress(ta); + try { + mseaCfmService.transmitLoopback(lbTr2, session); + } catch (NetconfException e) { + fail("Calling of TransmitLoopback failed: " + e.getMessage()); } } @Test public void testAbortLoopback() throws NetconfException { + AbortLoopbackInput lbAbort = new DefaultAbortLoopbackInput(); + + lbAbort.maintenanceDomain((short) 70); + lbAbort.maintenanceAssociation((short) 71); + lbAbort.maintenanceAssociationEndPoint((short) 72); + try { - mseaCfmService.abortLoopback(null, session); - } catch (UnsupportedOperationException e) { - assertTrue(e.getMessage().contains("Not yet implemented")); + mseaCfmService.abortLoopback(lbAbort, session); + } catch (NetconfException e) { + fail("Calling of AbortLoopback failed: " + e.getMessage()); } } diff --git a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MseaSaFilteringManagerTest.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MseaSaFilteringManagerTest.java index 1a3e77961d..29ac4a3c47 100644 --- a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MseaSaFilteringManagerTest.java +++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MseaSaFilteringManagerTest.java @@ -18,6 +18,7 @@ package org.onosproject.drivers.microsemi.yang; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.fail; +import static org.junit.Assert.assertTrue; import java.io.UncheckedIOException; import java.util.List; @@ -85,6 +86,32 @@ public class MseaSaFilteringManagerTest { } } + /** + * See sampleXmlRegexSaFilteringErrorScenario in MockNetconfSessionEa1000. + */ + @Test + public void testGetMseaSaFilteringMseaSaFilteringOpParamNetconfSessionError() { + + SourceAddressRange sar = new DefaultSourceAddressRange(); + sar.rangeId((short) 10); + + InterfaceEth0 eth0 = new DefaultInterfaceEth0(); + eth0.addToSourceAddressRange(sar); + + SourceIpaddressFiltering sip = new DefaultSourceIpaddressFiltering(); + sip.interfaceEth0(eth0); + + MseaSaFilteringOpParam mseaSaFilteringConfig = new MseaSaFilteringOpParam(); + mseaSaFilteringConfig.sourceIpaddressFiltering(sip); + + try { + MseaSaFiltering result = mseaSaSvc.getMseaSaFiltering(mseaSaFilteringConfig, session); + fail("Should have thrown exception"); + } catch (NetconfException ne) { + assertTrue(ne.getMessage().startsWith("NETCONF rpc-error")); + } + } + @Test public void testSetMseaSaFilteringMseaSaFilteringOpParamNetconfSessionNcDsType() { diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/README.md b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/README.md new file mode 100644 index 0000000000..612350934b --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/README.md @@ -0,0 +1,168 @@ +# Layer 2 Monitoring with CFM and SOAM in ONOS + +Connectivity Fault Management (CFM) was first introduced in IEEE 802.1ag, which +has been superseded by IEEE 802.1Q-2011 and subsequently by IEEE 802.1Q-2014 - +the IEEE Standard for Local and metropolitan area networks - Bridges and Bridged +Networks. + +It defines protocols and practices for OAM (Operations, Administration, and +Maintenance) for paths through 802.1 bridges and local area networks (LANs). +It is an amendment to IEEE 802.1Q-2005 and was approved in 2007. + +IEEE 802.1ag is largely identical with ITU-T Recommendation Y.1731, which +additionally addresses performance monitoring. + +In addition the Metro Ethernet Forum (MEF) has defined SOAM (Service Operations +Administration and Management) in MEF-17 on top of these standards to build a +framework for monitoring in conjunction with MEF services. This and other MEF +standards are available in their technical documentation section. + +## Modelling +Working these combined standards into a unified model is a complex task an +inevitably requires some compromises. For instance while 802.1Q talks about +Maintenance Domains and Maintenance Associations the MEF 17 standard uses the +name Maintenance Entity (ME) and Maintenance Entity Group (MEG). MEF 38 and 39 +defines a model that encompasses all of the concepts as a set of YANG modules, +that separate out the Monitoring aspects of MEF 17 from MEF Carrier Ethernet +Services. In this way a loose coupling exists between the CFM and MEF Services +linked together only through VLAN ids. + +MEF 38 defines a root object mef-cfm which represents 802.1Q and Y.1731 CFM +entities, which is augmented by mef-soam-fm which adds on additional attributes +and operations from SOAM related to fault management. + +MEF 39 augments mef-cfm further with the performance management aspects of SOAM +as mef-soam-pm including monitoring of delay, jitter and loss measurements. + +These YANG models act as a unified definition of these standards that it makes +practical sense to reuse in ONOS. + +## Implementation in ONOS +Direct translation of the MEF 38 and MEF 39 YANG models into ONOS does not provide +a completely clean way to define the models in ONOS, because of the complication +brought by the augments. Instead the models have been defined independently in +ONOS as a new structure under reusing common ONOS classes such as DeviceId, +PortNumber, NetworkResource, Identifier, MacAddress etc. + +* onos/incubator/src/main/java/org/onosproject/api/net/l2monitoring/cfm +* onos/incubator/src/main/java/org/onosproject/api/net/l2monitoring/soam + +## Java Model +These immutable objects are defined as Java POJOs with little dependencies on +outside elements, and built the familiar builder pattern. + +As with 802.1Q the model’s top level starts with the Maintenance Domain - an +abstract reference object defining the span of the domain of activity for +maintenance in the network. Maintenance Domains are defined at 8 different levels +to indicate the scope of their span. + +Beneath the Maintenance Domain is the Maintenance Association, another abstract +object specific to a VLAN that contains common parameters for a group of MEPs +(Maintenance Association Endpoints). It is these MEPs that are created on devices +in the network and can be thought of as monitoring points. Devices must support +the CfmMepProgrammable behaviour to support the creation of MEPs. + +The MEP is the key item then that allows specific actions to be taken on devices +such as + +* Continuity Check Messaging (CCM) +* Loopback testing +* Linktrace testing + +In addition these MEPs allow the creation of +* Delay Measurement entities (which run tests for Delay and Jitter on a continuous basis) +* Loss Measurement entities (which run tests for Loss Measurement on a continuous basis) + +The following shows the structure of Java classes defined in ONOS to represent +these entities. + +`Maintenance-Domain*`
+ `|-MdId` (MdIdCharStr or MdIdDomainName or MdIdMacUint or MdIdNone)
+ `|-Maintenance-Association*`
+   `|-MaIdShort` (MaIdCharStr or MaIdPrimaryVid or Ma2Octet + or MaIdRfc2685VpnId or MaIdIccY1731)
+   `|-Component*`
+   `|-Mep*` (Maintenance-Association-EndPoint) and MepEntry*
+   | `|-MepId`
+   | `|-MepLbEntry`
+   | `|-MepLtEntry`
+   | | `|-MepLtTransactionEntry*`
+   | | `|-MepLtReply*`
+   | | `|-SenderIdTlv`
+   | `|-DelayMeasurement*` (SOAM)
+   | | `|-DmId`
+   | | `|-DelayMeasurement-Stat-Current`
+   | | |`-DelayMeasurement-Stat-History*`
+   | |`-LossMeasurement*` (SOAM)
+   | | `|-LmId`
+   | | `|-LossMeasurement-Stat-Current`
+   | | `|-LossMeasurement-Stat-History*`
+   | `|-RemoteMepEntry*`
+   | `|-MepId`
+   `|-RemoteMepId`
+ + +The classes and interfaces can be broken down into 4 main categories: +* Those used as identifiers +* Those for configuring the object +* Those representing both the status attributes of the object and its +configuration (usually ending in Entry) +* Those used in commands called on objects - for Loopback, Linktrace, Delay and +Loss Measurement these are not configured - they are called as a method with +parameters + + +# Java Services +A set of services are defined for managing the object model +* CFM MD Service +* CFM MEP Service +* SOAM Service + +## CFM MD Service +This is an interface that manages only the configuration of Maintenance Domain +and Maintenance Association. It acts as a standalone service in ONOS that manages +only these 2 levels of the model. The Maintenance Domain contains a list of +Maintenance Associations does not contain Meps - these are left to the CfmMepService. + +These objects are persisted in ONOS in a distributed data store by this service. + +There are CLI commands for creating, deleting and modifying these objects. +* cfm-md-list-all - Lists all CFM Maintenance Domains. +* cfm-md-list - Lists a single CFM Maintenance Domain. +* cfm-md-add - Add a CFM Maintenance Domain. +* cfm-md-delete - Delete a CFM Maintenance Domain and its children. +* cfm-ma-add - Add a CFM Maintenance Association to a Maintenance Domain. +* cfm-ma-delete - Delete a CFM Maintenance Association and its children. + +## CFM MEP Service +This is an interface that manages the MEP and objects and commands below it. A +MEP managed under this service has a reference to the Maintenance Domain and +Maintenance Association above it. + +MEPs are identified by a combination of MdId, MaID and MepId. + +The service has the following actions associated with it +* Create MEP +* Delete MEP +* Get all MEPs (for a particular MD and MA) +* Get individual MEP +* Transmit Loopback +* Abort Loopback +* Transmit Linktrace +* Create Test Signal +* Abort Test Signal + +At the moment the MEP object is only maintained in memory and not persisted in +the ONOS data store. The objects Loopback, Linktrace, Test Signal, Loss +Measurement and Delay Measurement are not maintained in ONOS at all as they are +not really configuration objects. They are called on the fly and are passed down +as a collection of method parameters to the device implementing the MEP. This +device will operate on them and their results can be obtained by querying the +responsible MEP on the device. For instance the results of LinkTrace, Loopback +and Test Signal will appear in the MepLbEntry, MepLbEntry and MepTsEntry under +the MepEntry when the “Get Individual Mep” method is called. + +See in +* apps/cfm/src/test/resources/examples + +for some JSON examples that can be used to activate this functionality. \ No newline at end of file diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/Component.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/Component.java new file mode 100644 index 0000000000..9c3e726950 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/Component.java @@ -0,0 +1,177 @@ +/* + * 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.incubator.net.l2monitoring.cfm; + +import com.google.common.annotations.Beta; +import org.onlab.packet.EthType; +import org.onlab.packet.VlanId; + +import java.util.Collection; + +/** + * Components which can be managed in a manner equivalent to an 802.1Q bridge. + * + * Direct child of the {@link org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceAssociation}. + */ +public interface Component { + + int componentId(); + + /** + * The VID(s) monitored by this MA, or 0, if the MA is not attached to any VID. + * + * The first VID returned is the MA's Primary VID + * @return A collection of VIDs + */ + Collection vidList(); + + /** + * Defines how the MA can create MHFs (MIP Half Function) for this VID at this MA. + * @return An enumerated value + */ + MhfCreationType mhfCreationType(); + + /** + * indicates what, if anything, is to be included in the Sender ID TLV. + * The Sender ID TLV is transmitted by MPs configured in this MA. + * @return An enumerated value + */ + IdPermissionType idPermission(); + + /** + * Indicates the tag type for this component. + * @return The type of Tag active on this VLAN + */ + @Beta + TagType tagType(); + + /** + * Builder for {@link org.onosproject.incubator.net.l2monitoring.cfm.Component}. + */ + interface ComponentBuilder { + + ComponentBuilder addToVidList(VlanId vid); + + ComponentBuilder mhfCreationType(MhfCreationType mhfCreationType); + + ComponentBuilder idPermission(IdPermissionType idPermission); + + ComponentBuilder tagType(TagType tagType); + + Component build(); + } + + /** + * An enumerated type defining how MHFs (MIP Half Function) can be created. + */ + public enum MhfCreationType { + /** + * No MHFs can be created for this VID(s). + */ + NONE, + + /** + * MHFs can be created for this VID(s) on any Bridge Port through which the. + * VID(s) can pass where: + * - There are no lower active MD levels; or + * - There is a MEP at the next lower active MD-level on the port + */ + DEFAULT, + + /** + * MHFs can be created for this VID(s) only on Bridge Ports through which. + * this VID(s) can pass, and only if there is a MEP at the next + * lower active MD-level on the port. + */ + EXPLICIT, + + /** + * In the Maintenance Association managed object only, the control of MHF. + * creation is deferred to the corresponding variable in the + * enclosing Maintenance Domain + */ + DEFER + } + + /** + * An enumerated value indicating what, if anything, is to be included in. + * the Sender ID TLV transmitted by maintenance-points configured in the + * default Maintenance Domain + * reference + * [802.1q] 21.5.3, 12.14.3.1.3:e"; + */ + public enum IdPermissionType { + /** + * The Sender ID TLV is not to be sent. + */ + NONE, + + /** + * The Chassis ID Length, Chassis ID Subtype, and Chassis ID fields of the. + * Sender ID TLV are to be sent, but not the Management Address + * Length or Management Address fields. + */ + CHASSIS, + + /** + * The Management Address Length and Management Address of the Sender ID. + * TLV are to be sent, but the Chassis ID Length is to be + * transmitted with a 0 value, and the Chassis ID Subtype and + * Chassis ID fields not sent + */ + MANAGE, + + /** + * The Chassis ID Length, Chassis ID Subtype, Chassis ID, Management. + * Address Length, and Management Address fields are all to be sent + */ + CHASSIS_MANAGE, + + /** + * The contents of the Sender ID TLV are determined by the Maintenance. + * Domain managed object + */ + DEFER + } + + /** + * A choice of VLan tag type. + */ + public enum TagType { + VLAN_NONE(EthType.EtherType.IPV4), + VLAN_CTAG(EthType.EtherType.VLAN), + VLAN_STAG(EthType.EtherType.QINQ); + + private EthType.EtherType type = EthType.EtherType.IPV4; + + TagType(EthType.EtherType type) { + this.type = type; + } + + public EthType.EtherType getType() { + return type; + } + + public static TagType fromEtherType(EthType.EtherType type) { + for (TagType tt:values()) { + if (tt.type.equals(type)) { + return tt; + } + } + throw new IllegalArgumentException("Unsupported EtherType: " + type); + } + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/DefaultComponent.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/DefaultComponent.java new file mode 100644 index 0000000000..e8f43ae5e9 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/DefaultComponent.java @@ -0,0 +1,166 @@ +/* + * 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.incubator.net.l2monitoring.cfm; + +import java.util.ArrayList; +import java.util.Collection; + +import com.google.common.collect.Lists; +import org.onlab.packet.VlanId; + +/** + * The default implementation of {@link org.onosproject.incubator.net.l2monitoring.cfm.Component}. + */ +public final class DefaultComponent implements Component { + + private final int componentId; + private final Collection vidList; + private final MhfCreationType mhfCreationType; + private final IdPermissionType idPermission; + private final TagType tagType; + + private DefaultComponent(DefaultComponentBuilder builder) { + this.componentId = builder.componentId; + this.vidList = builder.vidList; + this.mhfCreationType = builder.mhfCreationType; + this.idPermission = builder.idPermission; + this.tagType = builder.tagType; + } + + @Override + public int componentId() { + return componentId; + } + + @Override + public Collection vidList() { + if (vidList != null) { + return Lists.newArrayList(vidList); + } else { + return null; + } + } + + @Override + public MhfCreationType mhfCreationType() { + return mhfCreationType; + } + + @Override + public IdPermissionType idPermission() { + return idPermission; + } + + @Override + public TagType tagType() { + return tagType; + } + + + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + componentId; + result = prime * result + + ((idPermission == null) ? 0 : idPermission.hashCode()); + result = prime * result + + ((mhfCreationType == null) ? 0 : mhfCreationType.hashCode()); + result = prime * result + ((tagType == null) ? 0 : tagType.hashCode()); + result = prime * result + ((vidList == null) ? 0 : vidList.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + DefaultComponent other = (DefaultComponent) obj; + if (componentId != other.componentId) { + return false; + } + if (idPermission != other.idPermission) { + return false; + } + if (mhfCreationType != other.mhfCreationType) { + return false; + } + if (tagType != other.tagType) { + return false; + } + if (vidList == null) { + if (other.vidList != null) { + return false; + } + } else if (!vidList.equals(other.vidList)) { + return false; + } + return true; + } + + public static ComponentBuilder builder(int componentId) { + return new DefaultComponentBuilder(componentId); + } + + private static final class DefaultComponentBuilder implements ComponentBuilder { + private final int componentId; + private Collection vidList; + private MhfCreationType mhfCreationType; + private IdPermissionType idPermission; + private TagType tagType; + + private DefaultComponentBuilder(int componentId) { + this.componentId = componentId; + vidList = new ArrayList<>(); + } + + @Override + public ComponentBuilder addToVidList(VlanId vid) { + this.vidList.add(vid); + return this; + } + + @Override + public ComponentBuilder mhfCreationType(MhfCreationType mhfCreationType) { + this.mhfCreationType = mhfCreationType; + return this; + } + + @Override + public ComponentBuilder idPermission(IdPermissionType idPermission) { + this.idPermission = idPermission; + return this; + } + + @Override + public ComponentBuilder tagType(TagType tagType) { + this.tagType = tagType; + return this; + } + + public Component build() { + return new DefaultComponent(this); + } + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/DefaultMaintenanceAssociation.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/DefaultMaintenanceAssociation.java new file mode 100644 index 0000000000..5d827f65ac --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/DefaultMaintenanceAssociation.java @@ -0,0 +1,242 @@ +/* + * 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.incubator.net.l2monitoring.cfm; + +import java.util.ArrayList; +import java.util.Collection; + +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; + +import com.google.common.base.MoreObjects; +import com.google.common.collect.Lists; + +/** + * The default implementation of {@link org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceAssociation}. + */ +public final class DefaultMaintenanceAssociation implements MaintenanceAssociation { + + private MaIdShort maId; + private final CcmInterval ccmInterval; + private final Collection componentList; + private final Collection remoteMepIdList; + private final short maNumericId; + + private DefaultMaintenanceAssociation(DefaultMaBuilder builder) + throws CfmConfigException { + this.maId = builder.maId; + this.ccmInterval = builder.ccmInterval; + this.componentList = builder.componentList; + this.remoteMepIdList = builder.remoteMepIdList; + this.maNumericId = builder.maNumericId; + } + + private DefaultMaintenanceAssociation(MaintenanceAssociation ma, + AttributeName attrName, Object attrValue) { + this.maId = ma.maId(); + this.ccmInterval = ma.ccmInterval(); + + if (attrName == AttributeName.COMPONENTLIST) { + this.componentList = (Collection) attrValue; + } else { + this.componentList = ma.componentList(); + } + + if (attrName == AttributeName.REMOTEMEPIDLIST) { + this.remoteMepIdList = (Collection) attrValue; + } else { + this.remoteMepIdList = ma.remoteMepIdList(); + } + + this.maNumericId = ma.maNumericId(); + } + + @Override + public MaIdShort maId() { + return maId; + } + + @Override + public CcmInterval ccmInterval() { + return ccmInterval; + } + + @Override + public Collection componentList() { + if (componentList != null) { + return Lists.newArrayList(componentList); + } + return Lists.newArrayList(); + } + + @Override + public MaintenanceAssociation withComponentList(Collection componentList) { + return new DefaultMaintenanceAssociation(this, AttributeName.COMPONENTLIST, componentList); + } + + @Override + public Collection remoteMepIdList() { + if (remoteMepIdList != null) { + return Lists.newArrayList(remoteMepIdList); + } + return Lists.newArrayList(); + } + + @Override + public MaintenanceAssociation withRemoteMepIdList(Collection remoteMepIdList) { + return new DefaultMaintenanceAssociation(this, AttributeName.REMOTEMEPIDLIST, remoteMepIdList); + } + + @Override + public short maNumericId() { + return maNumericId; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((ccmInterval == null) ? 0 : ccmInterval.hashCode()); + result = prime * result + + ((componentList == null) ? 0 : componentList.hashCode()); + result = prime * result + ((maId == null) ? 0 : maId.hashCode()); + result = prime * result + + ((remoteMepIdList == null) ? 0 : remoteMepIdList.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + DefaultMaintenanceAssociation other = (DefaultMaintenanceAssociation) obj; + if (ccmInterval != other.ccmInterval) { + return false; + } + if (componentList == null) { + if (other.componentList != null) { + return false; + } + } else if (!componentList.equals(other.componentList)) { + return false; + } + if (!maId.equals(other.maId)) { + return false; + } + if (remoteMepIdList == null) { + if (other.remoteMepIdList != null) { + return false; + } + } else if (!remoteMepIdList.equals(other.remoteMepIdList)) { + return false; + } + return true; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()).add("maId", maId).toString(); + } + + public static MaBuilder builder(MaIdShort maId, int mdNameAndTypeLen) + throws CfmConfigException { + return new DefaultMaBuilder(maId, mdNameAndTypeLen); + } + + public static MaBuilder builder(MaintenanceAssociation ma) + throws CfmConfigException { + return new DefaultMaBuilder(ma); + } + + private static final class DefaultMaBuilder implements MaintenanceAssociation.MaBuilder { + + private final MaIdShort maId; + private CcmInterval ccmInterval; + private Collection componentList; + private Collection remoteMepIdList; + private short maNumericId; + + public DefaultMaBuilder(MaIdShort maId, int mdNameAndTypeLen) + throws CfmConfigException { + if (maId.getNameLength() + mdNameAndTypeLen > 48) { + throw new CfmConfigException("Combined length of MD name and " + + "MA name exceeds 48. Cannot create"); + } + this.maId = maId; + this.componentList = new ArrayList<>(); + this.remoteMepIdList = new ArrayList<>(); + } + + public DefaultMaBuilder(MaintenanceAssociation ma) + throws CfmConfigException { + + this.maId = ma.maId(); + this.maNumericId = ma.maNumericId(); + this.componentList = new ArrayList<>(); + ma.componentList().forEach(comp -> this.componentList.add(comp)); + this.remoteMepIdList = new ArrayList<>(); + ma.remoteMepIdList().forEach((rmep -> this.remoteMepIdList.add(rmep))); + } + + @Override + public MaBuilder addToComponentList(Component component) { + this.componentList.add(component); + return this; + } + + @Override + public MaBuilder addToRemoteMepIdList(MepId remoteMep) { + this.remoteMepIdList.add(remoteMep); + return this; + } + + @Override + public MaBuilder ccmInterval(CcmInterval ccmInterval) { + this.ccmInterval = ccmInterval; + return this; + } + + @Override + public MaBuilder maNumericId(short maNumericId) { + if (maNumericId <= 0) { + throw new IllegalArgumentException( + "numericId must be > 0. Rejecting " + maNumericId); + } + this.maNumericId = maNumericId; + return this; + } + + @Override + public MaintenanceAssociation build() throws CfmConfigException { + return new DefaultMaintenanceAssociation(this); + } + } + + private enum AttributeName { + REMOTEMEPIDLIST, + COMPONENTLIST + } + +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/DefaultMaintenanceDomain.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/DefaultMaintenanceDomain.java new file mode 100644 index 0000000000..c6e16b0ebf --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/DefaultMaintenanceDomain.java @@ -0,0 +1,189 @@ +/* + * 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.incubator.net.l2monitoring.cfm; + +import java.util.ArrayList; +import java.util.Collection; + +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; + +import com.google.common.base.MoreObjects; +import com.google.common.collect.Lists; + +/** + * The default implementation of {@link org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain}. + */ +public final class DefaultMaintenanceDomain implements MaintenanceDomain { + + private final MdId mdId; + private final MdLevel mdLevel; + private final Collection maintenanceAssociationList; + private final short mdNumericId; + + private DefaultMaintenanceDomain(DefaultMdBuilder builder) throws CfmConfigException { + this.mdId = builder.mdId; + this.mdLevel = builder.mdLevel; + this.maintenanceAssociationList = builder.maList; + this.mdNumericId = builder.mdNumericId; + } + + private DefaultMaintenanceDomain(DefaultMaintenanceDomain md, Collection maList) { + this.mdId = md.mdId; + this.mdLevel = md.mdLevel; + this.maintenanceAssociationList = maList; + this.mdNumericId = md.mdNumericId; + } + + @Override + public MdId mdId() { + return mdId; + } + + @Override + public MdLevel mdLevel() { + return mdLevel; + } + + @Override + public Collection maintenanceAssociationList() { + if (maintenanceAssociationList != null) { + return Lists.newArrayList(maintenanceAssociationList); + } + return Lists.newArrayList(); + } + + @Override + public MaintenanceDomain withMaintenanceAssociationList( + Collection maintenanceAssociationList) { + return new DefaultMaintenanceDomain(this, maintenanceAssociationList); + } + + @Override + public short mdNumericId() { + return mdNumericId; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((mdId == null) ? 0 : mdId.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + DefaultMaintenanceDomain other = (DefaultMaintenanceDomain) obj; + if (mdId == null) { + if (other.mdId != null) { + return false; + } + } else if (!mdId.equals(other.mdId)) { + return false; + } + return true; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("mdId", mdId.toString()) + .add("level", mdLevel).toString(); + } + + public static MdBuilder builder(MdId mdId) + throws CfmConfigException { + return new DefaultMdBuilder(mdId); + } + + //A method for creating a builder from an existing MD + public static MdBuilder builder(MaintenanceDomain md) + throws CfmConfigException { + return new DefaultMdBuilder(md); + } + + + private static final class DefaultMdBuilder implements MaintenanceDomain.MdBuilder { + private final MdId mdId; + private MdLevel mdLevel = MdLevel.LEVEL0; + private Collection maList; + private short mdNumericId; + + private DefaultMdBuilder(MdId mdId) + throws CfmConfigException, NumberFormatException { + this.mdId = mdId; + this.maList = new ArrayList<>(); + } + + private DefaultMdBuilder(MaintenanceDomain md) + throws CfmConfigException, NumberFormatException { + this.mdId = md.mdId(); + this.mdNumericId = md.mdNumericId(); + this.mdLevel = md.mdLevel(); + this.maList = new ArrayList<>(); + md.maintenanceAssociationList().forEach(ma -> this.maList.add(ma)); + } + + @Override + public MdBuilder mdLevel(MdLevel mdLevel) { + this.mdLevel = mdLevel; + return this; + } + + @Override + public MdBuilder addToMaList(MaintenanceAssociation ma) { + this.maList.add(ma); + return this; + } + + @Override + public MdBuilder deleteFromMaList(MaIdShort maName) { + this.maList.removeIf(ma -> ma.maId().equals(maName)); + return this; + } + + @Override + public boolean checkMaExists(MaIdShort maName) { + return this.maList.stream().anyMatch(ma -> ma.maId().equals(maName)); + } + + @Override + public MdBuilder mdNumericId(short mdNumericId) { + if (mdNumericId <= 0) { + throw new IllegalArgumentException( + "numericId must be > 0. Rejecting " + mdNumericId); + } + this.mdNumericId = mdNumericId; + return this; + } + + @Override + public MaintenanceDomain build() throws CfmConfigException { + return new DefaultMaintenanceDomain(this); + } + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/DefaultMep.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/DefaultMep.java new file mode 100644 index 0000000000..72c976968b --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/DefaultMep.java @@ -0,0 +1,457 @@ +/* + * 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.incubator.net.l2monitoring.cfm; + +import java.time.Duration; + +import org.onlab.packet.VlanId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; +import org.onosproject.net.DeviceId; +import org.onosproject.net.PortNumber; + +/** + * The default implementation of {@link org.onosproject.incubator.net.l2monitoring.cfm.Mep}. + */ +public class DefaultMep implements Mep { + + protected final MepId mepId; + protected final DeviceId deviceId; + protected final PortNumber port; + protected final MepDirection direction; + protected final MdId mdId; + protected final MaIdShort maId; + protected final VlanId primaryVid; + protected final boolean administrativeState; + protected final boolean cciEnabled; + protected final Priority ccmLtmPriority; + protected final FngAddress fngAddress; + protected final LowestFaultDefect lowestFaultPriorityDefect; + protected final Duration defectPresentTime; + protected final Duration defectAbsentTime; + + protected DefaultMep(DefaultMepBuilder mepBuilder) { + this.mepId = mepBuilder.mepId; + this.deviceId = mepBuilder.deviceId; + this.port = mepBuilder.port; + this.direction = mepBuilder.direction; + this.mdId = mepBuilder.mdId; + this.maId = mepBuilder.maId; + this.primaryVid = mepBuilder.primaryVid; + this.administrativeState = mepBuilder.administrativeState; + this.cciEnabled = mepBuilder.cciEnabled; + this.ccmLtmPriority = mepBuilder.ccmLtmPriority; + this.fngAddress = mepBuilder.fngAddress; + this.lowestFaultPriorityDefect = mepBuilder.lowestFaultPriorityDefect; + this.defectPresentTime = mepBuilder.defectPresentTime; + this.defectAbsentTime = mepBuilder.defectAbsentTime; + } + + protected DefaultMep(DefaultMep mep, AttributeName attrName, Object attrValue) { + this.mepId = mep.mepId; + this.deviceId = mep.deviceId; + this.port = mep.port; + this.direction = mep.direction; + this.mdId = mep.mdId; + this.maId = mep.maId; + if (attrName == AttributeName.PRIMARY_VID) { + this.primaryVid = (VlanId) attrValue; + } else { + this.primaryVid = mep.primaryVid; + } + if (attrName == AttributeName.ADMINISTRATIVE_STATE) { + this.administrativeState = (boolean) attrValue; + } else { + this.administrativeState = mep.administrativeState; + } + + if (attrName == AttributeName.CCI_ENABLED) { + this.cciEnabled = (boolean) attrValue; + } else { + this.cciEnabled = mep.cciEnabled; + } + + if (attrName == AttributeName.CCM_LTM_PRIORITY) { + this.ccmLtmPriority = (Priority) attrValue; + } else { + this.ccmLtmPriority = mep.ccmLtmPriority; + } + + if (attrName == AttributeName.FNG_ADDRESS) { + this.fngAddress = (FngAddress) attrValue; + } else { + this.fngAddress = mep.fngAddress; + } + + if (attrName == AttributeName.LOWEST_FAULT_PRIORITY_DEFECT) { + this.lowestFaultPriorityDefect = (LowestFaultDefect) attrValue; + } else { + this.lowestFaultPriorityDefect = mep.lowestFaultPriorityDefect; + } + + if (attrName == AttributeName.DEFECT_PRESENT_TIME) { + this.defectPresentTime = (Duration) attrValue; + } else { + this.defectPresentTime = mep.defectPresentTime; + } + + if (attrName == AttributeName.DEFECT_ABSENT_TIME) { + this.defectAbsentTime = (Duration) attrValue; + } else { + this.defectAbsentTime = mep.defectAbsentTime; + } + } + + @Override + public MepId mepId() { + return mepId; + } + + @Override + public DeviceId deviceId() { + return deviceId; + } + + @Override + public PortNumber port() { + return port; + } + + @Override + public MepDirection direction() { + return direction; + } + + @Override + public MdId mdId() { + return mdId; + } + + @Override + public MaIdShort maId() { + return maId; + } + + @Override + public VlanId primaryVid() { + return primaryVid; + } + + @Override + public Mep withPrimaryVid(VlanId primaryVid) { + return new DefaultMep(this, AttributeName.PRIMARY_VID, primaryVid); + } + + @Override + public boolean administrativeState() { + return administrativeState; + } + + @Override + public Mep withAdministrativeState(boolean adminState) { + return new DefaultMep(this, AttributeName.ADMINISTRATIVE_STATE, adminState); + } + + @Override + public Boolean cciEnabled() { + return cciEnabled; + } + + @Override + public Mep withCciEnabled(boolean cciEnabled) { + return new DefaultMep(this, AttributeName.CCI_ENABLED, cciEnabled); + } + + @Override + public Priority ccmLtmPriority() { + return ccmLtmPriority; + } + + @Override + public Mep withCcmLtmPriority(Priority priority) { + return new DefaultMep(this, AttributeName.CCM_LTM_PRIORITY, priority); + } + + @Override + public Mep withFngAddress(FngAddress fngAddress) { + return new DefaultMep(this, AttributeName.FNG_ADDRESS, fngAddress); + } + + @Override + public FngAddress fngAddress() { + return fngAddress; + } + + @Override + public LowestFaultDefect lowestFaultPriorityDefect() { + return lowestFaultPriorityDefect; + } + + @Override + public Mep withLowestFaultPriorityDefect(LowestFaultDefect lowestFdType) { + return new DefaultMep(this, AttributeName.LOWEST_FAULT_PRIORITY_DEFECT, lowestFdType); + } + + @Override + public Duration defectPresentTime() { + return defectPresentTime; + } + + @Override + public Mep withDefectPresentTime(Duration duration) { + return new DefaultMep(this, AttributeName.DEFECT_PRESENT_TIME, duration); + } + + @Override + public Duration defectAbsentTime() { + return defectAbsentTime; + } + + @Override + public Mep withDefectAbsentTime(Duration duration) { + return new DefaultMep(this, AttributeName.DEFECT_ABSENT_TIME, duration); + } + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + DefaultMep that = (DefaultMep) o; + + if (administrativeState != that.administrativeState) { + return false; + } + if (cciEnabled != that.cciEnabled) { + return false; + } + if (!mepId.equals(that.mepId)) { + return false; + } + if (!deviceId.equals(that.deviceId)) { + return false; + } + if (!port.equals(that.port)) { + return false; + } + if (direction != that.direction) { + return false; + } + if (!mdId.equals(that.mdId)) { + return false; + } + if (!maId.equals(that.maId)) { + return false; + } + if (primaryVid != null ? !primaryVid.equals(that.primaryVid) : that.primaryVid != null) { + return false; + } + if (ccmLtmPriority != that.ccmLtmPriority) { + return false; + } + if (fngAddress != null ? !fngAddress.equals(that.fngAddress) : that.fngAddress != null) { + return false; + } + if (lowestFaultPriorityDefect != that.lowestFaultPriorityDefect) { + return false; + } + if (defectPresentTime != null ? + !defectPresentTime.equals(that.defectPresentTime) : that.defectPresentTime != null) { + return false; + } + return defectAbsentTime != null ? + defectAbsentTime.equals(that.defectAbsentTime) : that.defectAbsentTime == null; + } + + @Override + public int hashCode() { + int result = mepId.hashCode(); + result = 31 * result + deviceId.hashCode(); + result = 31 * result + port.hashCode(); + result = 31 * result + (direction != null ? direction.hashCode() : 0); + result = 31 * result + mdId.hashCode(); + result = 31 * result + maId.hashCode(); + result = 31 * result + (primaryVid != null ? primaryVid.hashCode() : 0); + result = 31 * result + (administrativeState ? 1 : 0); + result = 31 * result + (cciEnabled ? 1 : 0); + result = 31 * result + (ccmLtmPriority != null ? ccmLtmPriority.hashCode() : 0); + result = 31 * result + (fngAddress != null ? fngAddress.hashCode() : 0); + result = 31 * result + (lowestFaultPriorityDefect != null ? lowestFaultPriorityDefect.hashCode() : 0); + result = 31 * result + (defectPresentTime != null ? defectPresentTime.hashCode() : 0); + result = 31 * result + (defectAbsentTime != null ? defectAbsentTime.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return "DefaultMep{" + + "mepId=" + mepId + + ", deviceId=" + deviceId + + ", port=" + port + + ", direction=" + direction + + ", mdId=" + mdId + + ", maId=" + maId + + ", primaryVid=" + primaryVid + + ", administrativeState=" + administrativeState + + ", cciEnabled=" + cciEnabled + + ", ccmLtmPriority=" + ccmLtmPriority + + ", fngAddress=" + fngAddress + + ", lowestFaultPriorityDefect=" + lowestFaultPriorityDefect + + ", defectPresentTime=" + defectPresentTime + + ", defectAbsentTime=" + defectAbsentTime + + '}'; + } + + public static MepBuilder builder( + MepId mepId, + DeviceId deviceId, + PortNumber port, + MepDirection direction, + MdId mdId, + MaIdShort maId) + throws CfmConfigException { + return new DefaultMepBuilder(mepId, deviceId, port, direction, mdId, maId); + } + + /** + * Builder for {@link org.onosproject.incubator.net.l2monitoring.cfm.Mep}. + */ + protected static class DefaultMepBuilder implements Mep.MepBuilder { + protected final MepId mepId; + protected final DeviceId deviceId; + protected final PortNumber port; + protected final MepDirection direction; + protected final MdId mdId; + protected final MaIdShort maId; + protected VlanId primaryVid; + protected boolean administrativeState; + protected boolean cciEnabled; + protected Priority ccmLtmPriority; + protected FngAddress fngAddress; + protected LowestFaultDefect lowestFaultPriorityDefect; + protected Duration defectPresentTime; + protected Duration defectAbsentTime; + + protected DefaultMepBuilder(MepId mepId, DeviceId deviceId, PortNumber port, + MepDirection direction, MdId mdId, MaIdShort maId) + throws CfmConfigException { + if (port.isLogical()) { + throw new CfmConfigException("Port must be physical. Rejecting; " + port.toString()); + } else if (mepId == null) { + throw new CfmConfigException("MepId is null"); + } else if (mdId == null) { + throw new CfmConfigException("MdId is null"); + } else if (maId == null) { + throw new CfmConfigException("MaId is null"); + } + this.mepId = mepId; + this.deviceId = deviceId; + this.port = port; + this.direction = direction; + this.mdId = mdId; + this.maId = maId; + } + + public DefaultMepBuilder(Mep mep) { + this.mepId = mep.mepId(); + this.deviceId = mep.deviceId(); + this.port = mep.port(); + this.direction = mep.direction(); + this.mdId = mep.mdId(); + this.maId = mep.maId(); + this.primaryVid = mep.primaryVid(); + this.administrativeState = mep.administrativeState(); + this.cciEnabled = mep.cciEnabled(); + this.ccmLtmPriority = mep.ccmLtmPriority(); + this.fngAddress = mep.fngAddress(); + this.lowestFaultPriorityDefect = mep.lowestFaultPriorityDefect(); + this.defectPresentTime = mep.defectPresentTime(); + this.defectAbsentTime = mep.defectAbsentTime(); + } + + @Override + public MepBuilder primaryVid(VlanId primaryVid) { + this.primaryVid = primaryVid; + return this; + } + + @Override + public MepBuilder administrativeState(boolean administrativeState) { + this.administrativeState = administrativeState; + return this; + } + + @Override + public MepBuilder cciEnabled(boolean cciEnabled) { + this.cciEnabled = cciEnabled; + return this; + } + + @Override + public MepBuilder ccmLtmPriority(Priority ccmLtmPriority) { + this.ccmLtmPriority = ccmLtmPriority; + return this; + } + + @Override + public MepBuilder fngAddress(FngAddress fngAddress) { + this.fngAddress = fngAddress; + return this; + } + + @Override + public MepBuilder lowestFaultPriorityDefect( + LowestFaultDefect lowestFaultPriorityDefect) { + this.lowestFaultPriorityDefect = lowestFaultPriorityDefect; + return this; + } + + @Override + public MepBuilder defectPresentTime(Duration defectPresentTime) { + this.defectPresentTime = defectPresentTime; + return this; + } + + @Override + public MepBuilder defectAbsentTime(Duration defectAbsentTime) { + this.defectAbsentTime = defectAbsentTime; + return this; + } + + @Override + public Mep build() throws CfmConfigException { + return new DefaultMep(this); + } + } + + private enum AttributeName { + PRIMARY_VID, + ADMINISTRATIVE_STATE, + CCI_ENABLED, + CCM_LTM_PRIORITY, + FNG_ADDRESS, + LOWEST_FAULT_PRIORITY_DEFECT, + DEFECT_PRESENT_TIME, + DEFECT_ABSENT_TIME; + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/DefaultMepEntry.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/DefaultMepEntry.java new file mode 100644 index 0000000000..1fa255e93a --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/DefaultMepEntry.java @@ -0,0 +1,392 @@ +/* + * 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.incubator.net.l2monitoring.cfm; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.onlab.packet.MacAddress; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementEntry; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementEntry; +import org.onosproject.net.DeviceId; +import org.onosproject.net.PortNumber; + +import com.google.common.base.MoreObjects; +import com.google.common.collect.Lists; + +/** + * The default implementation of {@link org.onosproject.incubator.net.l2monitoring.cfm.MepEntry}. + */ +public final class DefaultMepEntry extends DefaultMep implements MepEntry { + + private final MacAddress macAddress; + private final FngState fngState; + private final FaultDefectType highestPriorityDefect; + private final boolean activeRdiCcmDefect; + private final boolean activeMacStatusDefect; + private final boolean activeRemoteCcmDefect; + private final boolean activeErrorCcmDefect; + private final boolean activeXconCcmDefect; + private final byte[] lastErrorCcm; + private final byte[] lastXconCcm; + private final int ccmSequenceErrorCount; + private final int totalCcmsTransmitted; + private final MepLbEntry loopbackAttributes; + private final MepLtEntry linktraceAttributes; + private final Collection activeRemoteMepList; + private final Collection delayMeasurementList; + private final Collection lossMeasurementList; + + private DefaultMepEntry(DefaultMepEntryBuilder mepEntryBuilder) throws CfmConfigException { + super((DefaultMepBuilder) DefaultMep.builder( + mepEntryBuilder.mepId, + mepEntryBuilder.deviceId, + mepEntryBuilder.port, + mepEntryBuilder.direction, + mepEntryBuilder.mdId, + mepEntryBuilder.maId) + .administrativeState(mepEntryBuilder.administrativeState) + .cciEnabled(mepEntryBuilder.cciEnabled) + .ccmLtmPriority(mepEntryBuilder.ccmLtmPriority)); + + this.macAddress = mepEntryBuilder.macAddress; + this.fngState = mepEntryBuilder.fngState; + this.highestPriorityDefect = mepEntryBuilder.highestPriorityDefect; + this.activeRdiCcmDefect = mepEntryBuilder.activeRdiCcmDefect; + this.activeMacStatusDefect = mepEntryBuilder.activeMacStatusDefect; + this.activeRemoteCcmDefect = mepEntryBuilder.activeRemoteCcmDefect; + this.activeErrorCcmDefect = mepEntryBuilder.activeErrorCcmDefect; + this.activeXconCcmDefect = mepEntryBuilder.activeXconCcmDefect; + this.lastErrorCcm = mepEntryBuilder.lastErrorCcm; + this.lastXconCcm = mepEntryBuilder.lastXconCcm; + this.ccmSequenceErrorCount = mepEntryBuilder.ccmSequenceErrorCount; + this.totalCcmsTransmitted = mepEntryBuilder.totalCcmsTransmitted; + this.loopbackAttributes = mepEntryBuilder.loopbackAttributes; + this.linktraceAttributes = mepEntryBuilder.linktraceAttributes; + this.activeRemoteMepList = mepEntryBuilder.activeRemoteMepList; + this.delayMeasurementList = mepEntryBuilder.delayMeasurementList; + this.lossMeasurementList = mepEntryBuilder.lossMeasurementList; + } + + @Override + public MacAddress macAddress() { + return macAddress; + } + + @Override + public FngState fngState() { + return fngState; + } + + @Override + public FaultDefectType getHighestPriorityDefect() { + return highestPriorityDefect; + } + + @Override + public boolean activeRdiCcmDefect() { + return activeRdiCcmDefect; + } + + @Override + public boolean activeMacStatusDefect() { + return activeMacStatusDefect; + } + + @Override + public boolean activeRemoteCcmDefect() { + return activeRemoteCcmDefect; + } + + @Override + public boolean activeErrorCcmDefect() { + return activeErrorCcmDefect; + } + + @Override + public boolean activeXconCcmDefect() { + return activeXconCcmDefect; + } + + @Override + public byte[] lastErrorCcm() { + return lastErrorCcm; + } + + @Override + public byte[] lastXconCcm() { + return lastXconCcm; + } + + @Override + public int ccmSequenceErrorCount() { + return ccmSequenceErrorCount; + } + + @Override + public int totalCcmsTransmitted() { + return totalCcmsTransmitted; + } + + @Override + public MepLbEntry loopbackAttributes() { + return loopbackAttributes; + } + + @Override + public MepLtEntry linktraceAttributes() { + return linktraceAttributes; + } + + @Override + public List activeRemoteMepList() { + if (activeRemoteMepList == null) { + return null; + } else { + return Lists.newArrayList(activeRemoteMepList); + } + } + + @Override + public Collection delayMeasurementList() { + return delayMeasurementList; + } + + @Override + public Collection lossMeasurementList() { + return lossMeasurementList; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + mepId.value(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + DefaultMepEntry other = (DefaultMepEntry) obj; + if (mepId != other.mepId) { + return false; + } + return true; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()).add("id", mepId).toString(); + } + + public static MepEntryBuilder builder( + MepId mepId, + DeviceId deviceId, + PortNumber port, + MepDirection direction, + MdId mdName, + MaIdShort maName) + throws CfmConfigException { + return new DefaultMepEntryBuilder(mepId, deviceId, port, direction, mdName, maName); + } + + public static MepEntryBuilder builder(Mep mep) throws CfmConfigException { + return new DefaultMepEntryBuilder(mep); + } + + private static final class DefaultMepEntryBuilder + extends DefaultMep.DefaultMepBuilder implements MepEntry.MepEntryBuilder { + private MacAddress macAddress; + private FngState fngState; + private FaultDefectType highestPriorityDefect; + private boolean activeRdiCcmDefect; + private boolean activeMacStatusDefect; + private boolean activeRemoteCcmDefect; + private boolean activeErrorCcmDefect; + private boolean activeXconCcmDefect; + private byte[] lastErrorCcm; + private byte[] lastXconCcm; + private int ccmSequenceErrorCount; + private int totalCcmsTransmitted; + private MepLbEntry loopbackAttributes; + private MepLtEntry linktraceAttributes; + private Collection activeRemoteMepList; + private Collection delayMeasurementList; + private Collection lossMeasurementList; + + private DefaultMepEntryBuilder(MepId mepId, DeviceId deviceId, PortNumber port, MepDirection direction, + MdId mdName, MaIdShort maName) + throws CfmConfigException { + super(mepId, deviceId, port, direction, mdName, maName); + + activeRemoteMepList = new ArrayList<>(); + delayMeasurementList = new ArrayList<>(); + lossMeasurementList = new ArrayList<>(); + } + + private DefaultMepEntryBuilder(MepEntry mepEntry) throws CfmConfigException { + super(mepEntry.mepId(), mepEntry.deviceId(), + mepEntry.port(), mepEntry.direction(), mepEntry.mdId(), mepEntry.maId()); + this.macAddress = mepEntry.macAddress(); + this.fngState = mepEntry.fngState(); + this.highestPriorityDefect = mepEntry.getHighestPriorityDefect(); + this.activeRdiCcmDefect = mepEntry.activeRdiCcmDefect(); + this.activeMacStatusDefect = mepEntry.activeMacStatusDefect(); + this.activeRemoteCcmDefect = mepEntry.activeRemoteCcmDefect(); + this.activeErrorCcmDefect = mepEntry.activeErrorCcmDefect(); + this.activeXconCcmDefect = mepEntry.activeXconCcmDefect(); + this.lastErrorCcm = mepEntry.lastErrorCcm(); + this.lastXconCcm = mepEntry.lastXconCcm(); + this.ccmSequenceErrorCount = mepEntry.ccmSequenceErrorCount(); + this.totalCcmsTransmitted = mepEntry.totalCcmsTransmitted(); + this.loopbackAttributes = mepEntry.loopbackAttributes(); + this.linktraceAttributes = mepEntry.linktraceAttributes(); + this.activeRemoteMepList = Lists.newArrayList(mepEntry.activeRemoteMepList()); + this.delayMeasurementList = Lists.newArrayList(mepEntry.delayMeasurementList()); + this.lossMeasurementList = Lists.newArrayList(mepEntry.lossMeasurementList()); + } + + private DefaultMepEntryBuilder(Mep mep) throws CfmConfigException { + super(mep.mepId(), mep.deviceId(), + mep.port(), mep.direction(), + mep.mdId(), mep.maId()); + } + + @Override + public MepEntryBuilder macAddress(MacAddress macAddress) { + this.macAddress = macAddress; + return this; + } + + @Override + public MepEntryBuilder fngState(FngState fngState) { + this.fngState = fngState; + return this; + } + + @Override + public MepEntryBuilder highestPriorityDefect(FaultDefectType highestPriorityDefect) { + this.highestPriorityDefect = highestPriorityDefect; + return this; + } + + @Override + public MepEntryBuilder activeRdiCcmDefect(boolean activeRdiCcmDefect) { + this.activeRdiCcmDefect = activeRdiCcmDefect; + return this; + } + + @Override + public MepEntryBuilder activeMacStatusDefect(boolean activeMacStatusDefect) { + this.activeMacStatusDefect = activeMacStatusDefect; + return this; + } + + @Override + public MepEntryBuilder activeRemoteCcmDefect(boolean activeRemoteCcmDefect) { + this.activeRemoteCcmDefect = activeRemoteCcmDefect; + return this; + } + + @Override + public MepEntryBuilder activeErrorCcmDefect(boolean activeErrorCcmDefect) { + this.activeErrorCcmDefect = activeErrorCcmDefect; + return this; + } + + @Override + public MepEntryBuilder activeXconCcmDefect(boolean activeXconCcmDefect) { + this.activeXconCcmDefect = activeXconCcmDefect; + return this; + } + + @Override + public MepEntryBuilder lastErrorCcm(byte[] lastErrorCcm) { + this.lastErrorCcm = lastErrorCcm; + return this; + } + + @Override + public MepEntryBuilder lastXconCcm(byte[] lastXconCcm) { + this.lastXconCcm = lastXconCcm; + return this; + } + + @Override + public MepEntryBuilder ccmSequenceErrorCount(int ccmSequenceErrorCount) { + this.ccmSequenceErrorCount = ccmSequenceErrorCount; + return this; + } + + @Override + public MepEntryBuilder totalCcmsTransmitted(int totalCcmsTransmitted) { + this.totalCcmsTransmitted = totalCcmsTransmitted; + return this; + } + + @Override + public MepEntryBuilder loopbackAttributes(MepLbEntry loopbackAttributes) { + this.loopbackAttributes = loopbackAttributes; + return this; + } + + @Override + public MepEntryBuilder linktraceAttributes(MepLtEntry linktraceAttributes) { + this.linktraceAttributes = linktraceAttributes; + return this; + } + + @Override + public MepEntryBuilder addToActiveRemoteMepList( + RemoteMepEntry activeRemoteMep) { + this.activeRemoteMepList.add(activeRemoteMep); + return this; + } + + @Override + public MepEntryBuilder addToDelayMeasurementList( + DelayMeasurementEntry delayMeasurement) { + this.delayMeasurementList.add(delayMeasurement); + return this; + } + + @Override + public MepEntryBuilder addToLossMeasurementList( + LossMeasurementEntry lossMeasurement) { + this.lossMeasurementList.add(lossMeasurement); + return this; + } + + @Override + public MepEntry buildEntry() throws CfmConfigException { + return new DefaultMepEntry(this); + } + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/DefaultMepLbCreate.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/DefaultMepLbCreate.java new file mode 100644 index 0000000000..b6eb62abce --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/DefaultMepLbCreate.java @@ -0,0 +1,146 @@ +/* + * 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.incubator.net.l2monitoring.cfm; + +import java.util.Base64; + +import org.onlab.packet.MacAddress; +import org.onlab.util.HexString; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep.Priority; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; + +/** + * The default implementation of {@link org.onosproject.incubator.net.l2monitoring.cfm.MepLbCreate}. + */ +public final class DefaultMepLbCreate implements MepLbCreate { + + private final MacAddress remoteMepAddress; + private final MepId remoteMepId; + private final Integer numberMessages; + private final String dataTlvHex; + private final Priority vlanPriority; + private final Boolean vlanDropEligible; + + private DefaultMepLbCreate(DefaultMepLbCreateBuilder builder) { + this.remoteMepAddress = builder.remoteMepAddress; + this.remoteMepId = builder.remoteMepId; + this.numberMessages = builder.numberMessages; + this.dataTlvHex = builder.dataTlvHex; + this.vlanPriority = builder.vlanPriority; + this.vlanDropEligible = builder.vlanDropEligible; + } + + @Override + public MacAddress remoteMepAddress() { + return remoteMepAddress; + } + + @Override + public MepId remoteMepId() { + return remoteMepId; + } + + @Override + public Integer numberMessages() { + return numberMessages; + } + + @Override + public String dataTlvHex() { + return dataTlvHex; + } + + @Override + public Priority vlanPriority() { + return vlanPriority; + } + + @Override + public Boolean vlanDropEligible() { + return vlanDropEligible; + } + + public static final MepLbCreateBuilder builder(MacAddress remoteMepAddress) { + return new DefaultMepLbCreateBuilder(remoteMepAddress); + } + + public static final MepLbCreateBuilder builder(MepId remoteMepId) { + return new DefaultMepLbCreateBuilder(remoteMepId); + } + + private static final class DefaultMepLbCreateBuilder implements MepLbCreateBuilder { + private final MacAddress remoteMepAddress; + private final MepId remoteMepId; + private Integer numberMessages; + private String dataTlvHex; + private Priority vlanPriority; + private Boolean vlanDropEligible; + + private DefaultMepLbCreateBuilder(MacAddress remoteMepAddress) { + this.remoteMepAddress = remoteMepAddress; + this.remoteMepId = null; + } + + private DefaultMepLbCreateBuilder(MepId remoteMepId) { + this.remoteMepAddress = null; + this.remoteMepId = remoteMepId; + } + + @Override + public MepLbCreateBuilder numberMessages(int numberMessages) { + this.numberMessages = numberMessages; + return this; + } + + @Override + public MepLbCreateBuilder dataTlv(byte[] dataTlv) { + this.dataTlvHex = HexString.toHexString(dataTlv); + return this; + } + + @Override + public MepLbCreateBuilder dataTlvHex(String dataTlvHex) { + this.dataTlvHex = HexString.toHexString( + HexString.fromHexString(dataTlvHex)); + return this; + } + + @Override + public MepLbCreateBuilder dataTlvB64(String dataTlvB64) { + this.dataTlvHex = HexString.toHexString( + Base64.getDecoder().decode(dataTlvB64)); + return this; + } + + @Override + public MepLbCreateBuilder vlanPriority(Priority vlanPriority) { + this.vlanPriority = vlanPriority; + return this; + } + + @Override + public MepLbCreateBuilder vlanDropEligible(boolean vlanDropEligible) { + this.vlanDropEligible = vlanDropEligible; + return this; + } + + @Override + public MepLbCreate build() { + return new DefaultMepLbCreate(this); + } + } + +} \ No newline at end of file diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/DefaultMepLbEntry.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/DefaultMepLbEntry.java new file mode 100644 index 0000000000..0ebe47b9f7 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/DefaultMepLbEntry.java @@ -0,0 +1,127 @@ +/* + * 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.incubator.net.l2monitoring.cfm; + +/** + * The default implementation of {@link org.onosproject.incubator.net.l2monitoring.cfm.MepLbEntry}. + */ +public final class DefaultMepLbEntry implements MepLbEntry { + private final long nextLbmIdentifier; + private final long countLbrTransmitted; + private final long countLbrReceived; + private final long countLbrValidInOrder; + private final long countLbrValidOutOfOrder; + private final long countLbrMacMisMatch; + + private DefaultMepLbEntry(DefaultMepLbEntryBuilder builder) { + this.nextLbmIdentifier = builder.nextLbmIdentifier; + this.countLbrTransmitted = builder.countLbrTransmitted; + this.countLbrReceived = builder.countLbrReceived; + this.countLbrValidInOrder = builder.countLbrValidInOrder; + this.countLbrValidOutOfOrder = builder.countLbrValidOutOfOrder; + this.countLbrMacMisMatch = builder.countLbrMacMisMatch; + } + + @Override + public long nextLbmIdentifier() { + return nextLbmIdentifier; + } + + @Override + public long countLbrTransmitted() { + return countLbrTransmitted; + } + + @Override + public long countLbrReceived() { + return countLbrReceived; + } + + @Override + public long countLbrValidInOrder() { + return countLbrValidInOrder; + } + + @Override + public long countLbrValidOutOfOrder() { + return countLbrValidOutOfOrder; + } + + @Override + public long countLbrMacMisMatch() { + return countLbrMacMisMatch; + } + + public static final MepLbEntryBuilder builder() { + return new DefaultMepLbEntryBuilder(); + } + + private static final class DefaultMepLbEntryBuilder implements MepLbEntryBuilder { + private long nextLbmIdentifier; + private long countLbrTransmitted; + private long countLbrReceived; + private long countLbrValidInOrder; + private long countLbrValidOutOfOrder; + private long countLbrMacMisMatch; + + private DefaultMepLbEntryBuilder() { + //Hidden + } + + @Override + public MepLbEntryBuilder nextLbmIdentifier(long nextLbmIdentifier) { + this.nextLbmIdentifier = nextLbmIdentifier; + return this; + } + + @Override + public MepLbEntryBuilder countLbrTransmitted(long countLbrTransmitted) { + this.countLbrTransmitted = countLbrTransmitted; + return this; + } + + @Override + public MepLbEntryBuilder countLbrReceived(long countLbrReceived) { + this.countLbrReceived = countLbrReceived; + return this; + } + + @Override + public MepLbEntryBuilder countLbrValidInOrder( + long countLbrValidInOrder) { + this.countLbrValidInOrder = countLbrValidInOrder; + return this; + } + + @Override + public MepLbEntryBuilder countLbrValidOutOfOrder( + long countLbrValidOutOfOrder) { + this.countLbrValidOutOfOrder = countLbrValidOutOfOrder; + return this; + } + + @Override + public MepLbEntryBuilder countLbrMacMisMatch(long countLbrMacMisMatch) { + this.countLbrMacMisMatch = countLbrMacMisMatch; + return this; + } + + @Override + public MepLbEntry build() { + return new DefaultMepLbEntry(this); + } + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/DefaultMepLtCreate.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/DefaultMepLtCreate.java new file mode 100644 index 0000000000..790278a6a0 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/DefaultMepLtCreate.java @@ -0,0 +1,100 @@ +/* + * 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.incubator.net.l2monitoring.cfm; + +import org.onlab.packet.MacAddress; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; + +import java.util.BitSet; + +/** + * The default implementation of {@link org.onosproject.incubator.net.l2monitoring.cfm.MepLtCreate}. + */ +public final class DefaultMepLtCreate implements MepLtCreate { + private final MacAddress remoteMepAddress; + private final MepId remoteMepId; + private BitSet transmitLtmFlags; + private Short defaultTtl; + + private DefaultMepLtCreate(DefaultMepLtCreateBuilder builder) { + this.remoteMepAddress = builder.remoteMepAddress; + this.remoteMepId = builder.remoteMepId; + this.defaultTtl = builder.defaultTtl; + this.transmitLtmFlags = builder.transmitLtmFlags; + } + + @Override + public MacAddress remoteMepAddress() { + return remoteMepAddress; + } + + @Override + public MepId remoteMepId() { + return remoteMepId; + } + + @Override + public BitSet transmitLtmFlags() { + return transmitLtmFlags; + } + + @Override + public Short defaultTtl() { + return defaultTtl; + } + + public static final MepLtCreate.MepLtCreateBuilder builder(MacAddress remoteMepAddress) { + return new DefaultMepLtCreate.DefaultMepLtCreateBuilder(remoteMepAddress); + } + + public static final MepLtCreate.MepLtCreateBuilder builder(MepId remoteMepId) { + return new DefaultMepLtCreate.DefaultMepLtCreateBuilder(remoteMepId); + } + + private static final class DefaultMepLtCreateBuilder implements MepLtCreate.MepLtCreateBuilder { + private final MacAddress remoteMepAddress; + private final MepId remoteMepId; + private BitSet transmitLtmFlags; + private Short defaultTtl; + + private DefaultMepLtCreateBuilder(MacAddress remoteMepAddress) { + this.remoteMepId = null; + this.remoteMepAddress = remoteMepAddress; + } + + private DefaultMepLtCreateBuilder(MepId remoteMepId) { + this.remoteMepId = remoteMepId; + this.remoteMepAddress = null; + } + + @Override + public MepLtCreateBuilder transmitLtmFlags(BitSet transmitLtmFlags) { + this.transmitLtmFlags = transmitLtmFlags; + return this; + } + + @Override + public MepLtCreateBuilder defaultTtl(Short defaultTtl) { + this.defaultTtl = defaultTtl; + return this; + } + + @Override + public MepLtCreate build() { + return new DefaultMepLtCreate(this); + } + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/DefaultRemoteMepEntry.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/DefaultRemoteMepEntry.java new file mode 100644 index 0000000000..377dddec84 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/DefaultRemoteMepEntry.java @@ -0,0 +1,159 @@ +/* + * 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.incubator.net.l2monitoring.cfm; + +import java.time.Duration; + +import org.onlab.packet.MacAddress; +import org.onosproject.incubator.net.l2monitoring.cfm.SenderIdTlv.SenderIdTlvType; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; + +/** + * The default implementation of {@link org.onosproject.incubator.net.l2monitoring.cfm.RemoteMepEntry}. + */ +public class DefaultRemoteMepEntry implements RemoteMepEntry { + + private final MepId remoteMepId; + private final RemoteMepState state; + private final Duration failedOrOkTime; + private final MacAddress macAddress; + private final boolean rdi; + private final PortStatusTlvType portStatusTlvType; + private final InterfaceStatusTlvType interfaceStatusTlvType; + private final SenderIdTlvType senderIdTlvType; + + protected DefaultRemoteMepEntry(DefaultRemoteMepEntryBuilder rmepBuilder) { + this.remoteMepId = rmepBuilder.remoteMepId; + this.state = rmepBuilder.state; + this.failedOrOkTime = rmepBuilder.failedOrOkTime; + this.macAddress = rmepBuilder.macAddress; + this.rdi = rmepBuilder.rdi; + this.portStatusTlvType = rmepBuilder.portStatusTlvType; + this.interfaceStatusTlvType = rmepBuilder.interfaceStatusTlvType; + this.senderIdTlvType = rmepBuilder.senderIdTlvType; + } + + @Override + public MepId remoteMepId() { + return this.remoteMepId; + } + + @Override + public RemoteMepState state() { + return this.state; + } + + @Override + public Duration failedOrOkTime() { + return failedOrOkTime; + } + + @Override + public MacAddress macAddress() { + return macAddress; + } + + @Override + public boolean rdi() { + return rdi; + } + + @Override + public PortStatusTlvType portStatusTlvType() { + return portStatusTlvType; + } + + @Override + public InterfaceStatusTlvType interfaceStatusTlvType() { + return interfaceStatusTlvType; + } + + @Override + public SenderIdTlvType senderIdTlvType() { + return senderIdTlvType; + } + + public static RemoteMepEntryBuilder builder( + MepId remoteMepId, RemoteMepState state) throws CfmConfigException { + return new DefaultRemoteMepEntryBuilder(remoteMepId, state); + } + + private static class DefaultRemoteMepEntryBuilder implements RemoteMepEntryBuilder { + private final MepId remoteMepId; + private final RemoteMepState state; + private Duration failedOrOkTime; + private MacAddress macAddress; + private boolean rdi; + private PortStatusTlvType portStatusTlvType; + private InterfaceStatusTlvType interfaceStatusTlvType; + private SenderIdTlvType senderIdTlvType; + + protected DefaultRemoteMepEntryBuilder(MepId remoteMepId, + RemoteMepState state) throws CfmConfigException { + if (remoteMepId == null) { + throw new CfmConfigException("remoteMepId is null"); + } else if (state == null) { + throw new CfmConfigException("state is null"); + } + this.remoteMepId = remoteMepId; + this.state = state; + } + + @Override + public RemoteMepEntryBuilder failedOrOkTime(Duration failedOrOkTime) { + this.failedOrOkTime = failedOrOkTime; + return this; + } + + @Override + public RemoteMepEntryBuilder macAddress(MacAddress macAddress) { + this.macAddress = macAddress; + return this; + } + + @Override + public RemoteMepEntryBuilder rdi(boolean rdi) { + this.rdi = rdi; + return this; + } + + @Override + public RemoteMepEntryBuilder portStatusTlvType(PortStatusTlvType portStatusTlvType) { + this.portStatusTlvType = portStatusTlvType; + return this; + } + + @Override + public RemoteMepEntryBuilder interfaceStatusTlvType( + InterfaceStatusTlvType interfaceStatusTlvType) { + this.interfaceStatusTlvType = interfaceStatusTlvType; + return this; + } + + @Override + public RemoteMepEntryBuilder senderIdTlvType( + SenderIdTlvType senderIdTlvType) { + this.senderIdTlvType = senderIdTlvType; + return this; + } + + @Override + public RemoteMepEntry build() { + return new DefaultRemoteMepEntry(this); + } + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/MaintenanceAssociation.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/MaintenanceAssociation.java new file mode 100644 index 0000000000..b3c24dee8d --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/MaintenanceAssociation.java @@ -0,0 +1,122 @@ +/* + * 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.incubator.net.l2monitoring.cfm; + +import java.time.Duration; +import java.util.Collection; + +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; +import org.onosproject.net.NetworkResource; + +/** + * A model of the Maintenance Association. + * + * See IEEE 802.1Q Section 12.14 CFM entities + * Direct child of {@link org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain} + */ +public interface MaintenanceAssociation extends NetworkResource { + /** + * Get the ID of the Maintenance Association. + * @return The id object + */ + MaIdShort maId(); + + /** + * Get the CCM interval for the Maintenance Association. + * @return An enumerated value + */ + CcmInterval ccmInterval(); + + /** + * A list of components each of which can be managed in a manner essentially equivalent to an 802.1Q bridge. + * @return A collection of Components + */ + Collection componentList(); + + /** + * Create a new component collection. + * @param componentList A collection of component objects + * @return A new Maintenance Association + */ + MaintenanceAssociation withComponentList(Collection componentList); + + /** + * Get the list of the Remote Mep Ids. + * @return A list of Remote Mep Ids + */ + Collection remoteMepIdList(); + + /** + * Create a new Maintenance Association from the current with the specified RemoteMepId list. + * @param remoteMepIdList A list of RemoteMepIds + * @return A new Maintenance Association + */ + MaintenanceAssociation withRemoteMepIdList(Collection remoteMepIdList); + + /** + * Numeric identifier. + * Some systems require to have a placeholder for a numeric identifier in + * addition to the MaId + * @return A short numeric id that's been assigned to the MA + */ + short maNumericId(); + + /** + * Enumerated values from IEEE 802.1Q Table 21-16—CCM Interval field encoding. + */ + public enum CcmInterval { + INVALID(0), + INTERVAL_3MS(3), + INVERVAL_10MS(10), + INVERVAL_100MS(100), + INTERVAL_1S(1000), + INTERVAL_10S(10000), + INTERVAL_1MIN(60000), + INTERVAL_10MIN(600000); + + private final int millis; + + CcmInterval(int millis) { + this.millis = millis; + } + + public int millis() { + return millis; + } + + public Duration duration() { + return Duration.ofMillis(millis); + } + } + + /** + * Builder for {@link org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceAssociation}. + */ + interface MaBuilder { + + MaBuilder ccmInterval(CcmInterval ccmInterval); + + MaBuilder addToRemoteMepIdList(MepId remoteMep); + + MaBuilder addToComponentList(Component component); + + MaBuilder maNumericId(short maNumericId); + + MaintenanceAssociation build() throws CfmConfigException; + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/MaintenanceDomain.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/MaintenanceDomain.java new file mode 100644 index 0000000000..f98b76b456 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/MaintenanceDomain.java @@ -0,0 +1,125 @@ +/* + * Copyright 2017-present Open Networking Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.incubator.net.l2monitoring.cfm; + +import java.util.Collection; + +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; +import org.onosproject.net.NetworkResource; + +/** + * A model of the Maintenance Domain. + * + * See IEEE 802.1Q Section 12.14.5.1.3 CFM entities.
+ * This is the root of the L2 Monitoring hierarchy
+ * |-Maintenance-Domain*
+ * |-{@link org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId} + * (MdIdCharStr or MdIdDomainName or MdIdMacUint or MdIdNone)
+ * |-{@link org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceAssociation Maintenance-Association}*
+ * |-{@link org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort} + * ({@link org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr} + * or {@link org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdPrimaryVid} + * or {@link org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaId2Octet} + * or {@link org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdRfc2685VpnId} + * or {@link org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdIccY1731})
+ * |-{@link org.onosproject.incubator.net.l2monitoring.cfm.Component}*
+ * |-{@link org.onosproject.incubator.net.l2monitoring.cfm.Mep}* (Maintenance-Association-EndPoint) + * and {@link org.onosproject.incubator.net.l2monitoring.cfm.MepEntry}*
+ * | |-{@link org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId}
+ * | |-{@link org.onosproject.incubator.net.l2monitoring.cfm.MepLbEntry}
+ * | |-{@link org.onosproject.incubator.net.l2monitoring.cfm.MepLtEntry}
+ * | | |-{@link org.onosproject.incubator.net.l2monitoring.cfm.MepLtTransactionEntry}*
+ * | | |-{@link org.onosproject.incubator.net.l2monitoring.cfm.MepLtReply}*
+ * | | |-{@link org.onosproject.incubator.net.l2monitoring.cfm.SenderIdTlv}
+ * | |-{@link org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate} (SOAM)* + * and {@link org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementEntry}
+ * | | |-{@link org.onosproject.incubator.net.l2monitoring.soam.SoamId DmId}
+ * | | |-{@link org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStatCurrent}
+ * | | |-{@link org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStatHistory}*
+ * | |-{@link org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementCreate} (SOAM)* + * and {@link org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementEntry}
+ * | | |-{@link org.onosproject.incubator.net.l2monitoring.soam.SoamId LmId}
+ * | | |-{@link org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementStatCurrent}
+ * | | |-{@link org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementStatHistory}*
+ * | |-{@link org.onosproject.incubator.net.l2monitoring.cfm.RemoteMepEntry}*
+ * | | |-{@link org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId RemoteMepId}
+ * |-{@link org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId RemoteMepId}*
+ *
+ * *above indicates 0-many can be created + * -Create suffix means the Object is part of a request + * -Entry suffix means the Object is part of a reply + */ +public interface MaintenanceDomain extends NetworkResource { + /** + * Retrieve the id of the Maintenance Domain. + * @return The id object + */ + MdId mdId(); + + /** + * Retrieve the level of the MD. + * @return An enumerated value for the level + */ + MdLevel mdLevel(); + + /** + * Retrieve the MA list of the MD. + * @return The collection of Maintenance Associations + */ + Collection maintenanceAssociationList(); + + /** + * Replace the MA list of the MD. + * @param maintenanceAssociationList A list of MAs to replace the existing one + * @return A new version of the MD with the given MA list + */ + MaintenanceDomain withMaintenanceAssociationList( + Collection maintenanceAssociationList); + + /** + * Numeric identifier. + * Some systems require to have a placeholder for a numeric identifier in + * addition to the MdId + * @return A short numeric id that's been assigned to the MD + */ + short mdNumericId(); + + /** + * An enumerated set of values to represent MD Level. + */ + public enum MdLevel { + LEVEL0, LEVEL1, LEVEL2, LEVEL3, LEVEL4, LEVEL5, LEVEL6, LEVEL7 + } + + /** + * Builder for {@link org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain}. + */ + interface MdBuilder { + MdBuilder mdLevel(MdLevel mdLevel); + + MdBuilder mdNumericId(short mdNumericId); + + MdBuilder addToMaList(MaintenanceAssociation ma); + + MdBuilder deleteFromMaList(MaIdShort maName); + + boolean checkMaExists(MaIdShort maName); + + MaintenanceDomain build() throws CfmConfigException; + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/Mep.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/Mep.java new file mode 100644 index 0000000000..ff06932734 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/Mep.java @@ -0,0 +1,369 @@ +/* + * 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.incubator.net.l2monitoring.cfm; + +import java.time.Duration; +import java.util.HashSet; +import java.util.Set; + +import org.onlab.packet.IpAddress; +import org.onlab.packet.VlanId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; +import org.onosproject.net.DeviceId; +import org.onosproject.net.NetworkResource; +import org.onosproject.net.PortNumber; + +/** + * A model of the Maintenance Association Endpoint. + * + * See IEE 802.1Q Section 12.14.7.1.3 for reference + */ +public interface Mep extends NetworkResource { + + /** + * Get the ID of the MEP. + * + * @return The MEPID is an integer in the range 1–8191 + */ + MepId mepId(); + + /** + * Get the Device ID which the MEP is realized on. + * + * @return The DeviceID to which this Mep is associated + */ + DeviceId deviceId(); + + /** + * Get the port to which the MEP is attached. + * + * @return An port to which the MEP is attached + */ + PortNumber port(); + + /** + * Get the MEP direction. + * + * @return A value indicating the direction in which the MEP faces on the interface + */ + MepDirection direction(); + + /** + * Get the Maintenance Domain reference. + * + * @return The name of the containing Maintenance Domain + */ + MdId mdId(); + + /** + * Get the Maintenance Association reference. + * + * @return The name of the containing Maintenance Association + */ + MaIdShort maId(); + + /** + * Get the Primary VID of the MEP. + * The value 0 indicates that either the Primary VID is that + * of the MEP's MA or that the MEP's MA is associated with no VID. + * + * @return An integer in the range 0-4094 + */ + VlanId primaryVid(); + + /** + * Set the Primary VID of the MEP. + * + * @param primaryVid An integer between 0 and 4094 + * @return A new MEP with this value set + */ + Mep withPrimaryVid(VlanId primaryVid); + + /** + * Get the administrative state of the MEP. + * + * @return The administrative state of the MEP + */ + boolean administrativeState(); + + /** + * Set the administrative state of the MEP. + * + * @param adminState The administrative state of the MEP + * @return A new MEP with this value set + */ + Mep withAdministrativeState(boolean adminState); + + /** + * Get whether the MEP is or is not to generate CCMs. + * + * CCMs are Continuity Check Messages + * + * @return boolean value indicating whether the MEP is or is not to generate CCMs + */ + Boolean cciEnabled(); + + /** + * Enable or disable the generation of CCMs by the MEP. + * + * @param cciEnabled boolean value dictating whether CCMs are sent or not + * @return A new MEP with this value set + */ + Mep withCciEnabled(boolean cciEnabled); + + /** + * Get the priority parameter for CCMs and LTMs transmitted by the MEP. + * + * @return The priority parameter for CCMs and LTMs transmitted by the MEP + */ + Priority ccmLtmPriority(); + + /** + * Set the priority parameter for CCMs and LTMs transmitted by the MEP. + * + * @param priority An integer value between 0 and 7 inclusive + * @return A new MEP with this value set + */ + Mep withCcmLtmPriority(Priority priority); + + /** + * Get the network address to which Fault Alarms are to be transmitted. + * + * @return The IP address to which Fault Alarms are to be transmitted + */ + FngAddress fngAddress(); + + /** + * Set the network address to which Fault Alarms are to be transmitted. + * + * If “not specified,” the address used is that from the Maintenance Association managed object + * + * @param address Address type or indicator that address is not specified or alarms are not to be transmitted + * @return A new MEP with this value set + */ + Mep withFngAddress(FngAddress address); + + /** + * Get the lowest priority defect that is allowed to generate a Fault Alarm. + * @return The lowest priority defect that is allowed to generate a Fault Alarm + */ + LowestFaultDefect lowestFaultPriorityDefect(); + + /** + * Set the lowest priority defect that is allowed to generate a Fault Alarm. + * @param lowestFdType The lowest priority defect that is allowed to generate a Fault Alarm + * @return A new MEP with this value set + */ + Mep withLowestFaultPriorityDefect(LowestFaultDefect lowestFdType); + + /** + * Get the time that the Fault must be present before it is issued. + * @return The time that the Fault must be present before it is issued + */ + Duration defectPresentTime(); + + /** + * Set the time that the Fault must be present before it is issued. + * + * The default is 2500ms (2.5 seconds) if not specified + * @param duration The time that the Fault must be present before it is issued + * @return A new MEP with this value set + */ + Mep withDefectPresentTime(Duration duration); + + /** + * Get the time that the Fault must be absent before it is reset. + * @return The time that the Fault must be absent before it is reset + */ + Duration defectAbsentTime(); + + /** + * Set the time that the Fault must be absent before it is reset. + * + * The default is 10000ms (10 seconds) if not specified + * @param duration The time that the Fault must be absent before it is reset + * @return A new MEP with this value set + */ + Mep withDefectAbsentTime(Duration duration); + + /** + * Enumerated options for MEP Directions. + */ + public enum MepDirection { + UP_MEP, + DOWN_MEP + } + + /** + * Supported FNG Address Types. + * See {@link org.onosproject.incubator.net.l2monitoring.cfm.Mep.FngAddress} + */ + public enum FngAddressType { + IPV4, + IPV6, + NOT_SPECIFIED, + NOT_TRANSMITTED; + } + + /** + * Supported Fault Defect Types. + */ + public enum FaultDefectType { + DEF_NONE, + DEF_RDI_CCM, + DEF_MAC_STATUS, + DEF_REMOTE_CCM, + DEF_ERROR_CCM, + DEF_XCON_CCM + } + + /** + * Options for setting the lowest fault defect. + * Each comprises a set of {@link org.onosproject.incubator.net.l2monitoring.cfm.Mep.FaultDefectType} + */ + public enum LowestFaultDefect { + ALL_DEFECTS(FaultDefectType.DEF_RDI_CCM, + FaultDefectType.DEF_MAC_STATUS, + FaultDefectType.DEF_REMOTE_CCM, + FaultDefectType.DEF_ERROR_CCM, + FaultDefectType.DEF_XCON_CCM), + MAC_FD_PLUS(FaultDefectType.DEF_MAC_STATUS, + FaultDefectType.DEF_REMOTE_CCM, + FaultDefectType.DEF_ERROR_CCM, + FaultDefectType.DEF_XCON_CCM), + REMOTE_FD_PLUS(FaultDefectType.DEF_REMOTE_CCM, + FaultDefectType.DEF_ERROR_CCM, + FaultDefectType.DEF_XCON_CCM), + ERROR_FD_PLUS(FaultDefectType.DEF_ERROR_CCM, + FaultDefectType.DEF_XCON_CCM), + XCON_FD_ONLY(FaultDefectType.DEF_XCON_CCM); + + private Set defectTypes = new HashSet<>(); + + private LowestFaultDefect(FaultDefectType... defectTypes) { + for (FaultDefectType defectType:defectTypes) { + this.defectTypes.add(defectType); + } + } + + public Set getDefectTypes() { + return defectTypes; + } + } + + /** + * An enumerated set of values to represent Priority. + */ + public enum Priority { + PRIO0, PRIO1, PRIO2, PRIO3, PRIO4, PRIO5, PRIO6, PRIO7 + } + + /** + * A simple class to join an FngAddressType and an IpAddress. + */ + public final class FngAddress { + private final FngAddressType addressType; + private final IpAddress ipAddress; + + private FngAddress(FngAddressType addressType, IpAddress ipAddress) { + this.addressType = addressType; + this.ipAddress = ipAddress; + } + + public FngAddressType addressType() { + return addressType; + } + + public IpAddress ipAddress() { + return ipAddress; + } + + public static FngAddress ipV4Address(IpAddress ipAddress) { + return new FngAddress(FngAddressType.IPV4, ipAddress); + } + + public static FngAddress ipV6Address(IpAddress ipAddress) { + return new FngAddress(FngAddressType.IPV6, ipAddress); + } + + public static FngAddress notSpecified() { + return new FngAddress(FngAddressType.NOT_SPECIFIED, null); + } + + public static FngAddress notTransmitted(IpAddress ipAddress) { + return new FngAddress(FngAddressType.NOT_TRANSMITTED, ipAddress); + } + + @Override + public String toString() { + return "FngAddress{" + + "addressType=" + addressType + + ", ipAddress=" + ipAddress + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + FngAddress that = (FngAddress) o; + + if (addressType != that.addressType) { + return false; + } + return ipAddress != null ? ipAddress.equals(that.ipAddress) : that.ipAddress == null; + } + + @Override + public int hashCode() { + int result = addressType.hashCode(); + result = 31 * result + (ipAddress != null ? ipAddress.hashCode() : 0); + return result; + } + } + + /** + * Builder for {@link org.onosproject.incubator.net.l2monitoring.cfm.Mep}. + */ + interface MepBuilder { + + MepBuilder primaryVid(VlanId primaryVid); + + MepBuilder administrativeState(boolean administrativeState); + + MepBuilder cciEnabled(boolean cciEnabled); + + MepBuilder ccmLtmPriority(Priority ccmLtmPriority); + + MepBuilder fngAddress(FngAddress fngAddress); + + MepBuilder lowestFaultPriorityDefect(LowestFaultDefect lowestFaultPriorityDefect); + + MepBuilder defectPresentTime(Duration defectPresentTime); + + MepBuilder defectAbsentTime(Duration defectAbsentTime); + + Mep build() throws CfmConfigException; + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/MepEntry.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/MepEntry.java new file mode 100644 index 0000000000..5259ec6139 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/MepEntry.java @@ -0,0 +1,187 @@ +/* + * 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.incubator.net.l2monitoring.cfm; + +import java.util.Collection; + +import org.onlab.packet.MacAddress; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementEntry; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementEntry; + +/** + * An extension of the Mep interface to represent the state attributes. + * + */ +public interface MepEntry extends Mep { + /** + * Get the MAC address of the MEP. + * + * @return The MAC address of the MEP + */ + MacAddress macAddress(); + + /** + * Get the state of the MEPs Fault Notification Generator. + * + * @return The state of the MEPs Fault Notification Generator + */ + FngState fngState(); + + /** + * Get the highest-priority defect that has been present since last FNG reset. + * @return The highest-priority defect + */ + FaultDefectType getHighestPriorityDefect(); + + /** + * Get flag indicating that some other MEP in this MEP’s MA is transmitting the RDI bit. + * @return true or false + */ + boolean activeRdiCcmDefect(); + + /** + * Get flag indicating that a Port Status or Interface Status TLV is indicating an error condition. + * @return true or false + */ + boolean activeMacStatusDefect(); + + /** + * Get flag indicating that CCMs are not being received from at least one of the configured remote MEPs. + * @return true or false + */ + boolean activeRemoteCcmDefect(); + + /** + * Get flag indicating that erroneous CCMs are being received from some MEP in this MEP’s MA. + * @return true or false + */ + boolean activeErrorCcmDefect(); + + /** + * Get flag indicating indicating that CCMs are being received from a MEP that could be in some other MA. + * @return true or false + */ + boolean activeXconCcmDefect(); + + /** + * The last-received CCM that triggered a DEF_ERROR_CCM fault. + * + * @return An array of bytes (length 1-1522) containing the CCM + */ + byte[] lastErrorCcm(); + + /** + * The last-received CCM that triggered a DEF_XCON_CCM fault. + * + * @return An array of bytes (length 1-1522) containing the CCM + */ + byte[] lastXconCcm(); + + /** + * Get the total number of out-of-sequence CCMs received. + * @return The total number of out-of-sequence CCMs received + */ + int ccmSequenceErrorCount(); + + /** + * Get the total number of CCMs transmitted. + * @return The total number of CCMs transmitted + */ + int totalCcmsTransmitted(); + + /** + * Get the collection of attributes related to loopback. + * @return An object with loopback attributes + */ + MepLbEntry loopbackAttributes(); + + /** + * Get the collection of attributes related to linktrace. + * @return An object with linktrace attributes + */ + MepLtEntry linktraceAttributes(); + + /** + * Get the list of active Remote MEPs. + * @return A list of remote MEPs including their states + */ + Collection activeRemoteMepList(); + + /** + * Get the list of Delay Measurements for this MEP. + * @return A list of the Delay Measurements including their states + */ + Collection delayMeasurementList(); + + /** + * Get the list of Loss Measurements for this MEP. + * @return A list of the Loss Measurements including their states + */ + Collection lossMeasurementList(); + + /** + * States of Fault Notification Generator. + */ + public enum FngState { + FNG_RESET, + FNG_DEFECT, + FNG_REPORT_DEFECT, + FNG_DEFECT_REPORTED, + FNG_DEFECT_CLEARING + } + + /** + * Builder for {@link org.onosproject.incubator.net.l2monitoring.cfm.MepEntry}. + */ + interface MepEntryBuilder extends MepBuilder { + MepEntryBuilder macAddress(MacAddress macAddress); + + MepEntryBuilder fngState(FngState fngState); + + MepEntryBuilder highestPriorityDefect(FaultDefectType highestPriorityDefect); + + MepEntryBuilder activeRdiCcmDefect(boolean activeRdiCcmDefect); + + MepEntryBuilder activeMacStatusDefect(boolean activeMacStatusDefect); + + MepEntryBuilder activeRemoteCcmDefect(boolean activeRemoteCcmDefect); + + MepEntryBuilder activeErrorCcmDefect(boolean activeErrorCcmDefect); + + MepEntryBuilder activeXconCcmDefect(boolean activeXconCcmDefect); + + MepEntryBuilder lastErrorCcm(byte[] lastErrorCcm); + + MepEntryBuilder lastXconCcm(byte[] lastXconCcm); + + MepEntryBuilder ccmSequenceErrorCount(int ccmSequenceErrorCount); + + MepEntryBuilder totalCcmsTransmitted(int totalCcmsTransmitted); + + MepEntryBuilder loopbackAttributes(MepLbEntry loopbackAttributes); + + MepEntryBuilder linktraceAttributes(MepLtEntry linktraceAttributes); + + MepEntryBuilder addToActiveRemoteMepList(RemoteMepEntry activeRemoteMep); + + MepEntryBuilder addToDelayMeasurementList(DelayMeasurementEntry delayMeasurement); + + MepEntryBuilder addToLossMeasurementList(LossMeasurementEntry lossMeasurement); + + MepEntry buildEntry() throws CfmConfigException; + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/MepLbCreate.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/MepLbCreate.java new file mode 100644 index 0000000000..cdb02ca7ff --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/MepLbCreate.java @@ -0,0 +1,98 @@ +/* + * 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.incubator.net.l2monitoring.cfm; + +import org.onlab.packet.MacAddress; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep.Priority; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; + +/** + * Grouping of parameters used to create a loopback test on a MEP. + */ +public interface MepLbCreate { + /** + * The remote Mep will be identified by either a MacAddress or a MEPId. + * @return The MAC address of the remoteMep + */ + MacAddress remoteMepAddress(); + + /** + * The remote Mep will be identified by either a MacAddress or a MEPId. + * @return The id of the remoteMep + */ + MepId remoteMepId(); + + /** + * The number of LBM transmissions in a session. + * [802.1q] 12.14.7.3.2:c, [MEF30] R39 + * @return The number of messages to send + */ + Integer numberMessages(); + + /** + * An arbitrary amount of data to be included in a Data TLV. + * [802.1q] 12.14.7.3.d, IEEE8021-CFM-MIB.dot1agCfmMepTransmitLbmDataTlv + * @return The data that will be sent encoded as hexadecimal (lower case, colon separated bytes) + */ + String dataTlvHex(); + + /** + * The priority parameter to be used in the transmitted LBMs. + * [802.1q] 12.14.7.3.2:e + * @return The priority to be used + */ + Priority vlanPriority(); + + /** + * The drop eligible parameter to be used in the transmitted LBMs. + * @return True or False + */ + Boolean vlanDropEligible(); + + /** + * Builder for {@link org.onosproject.incubator.net.l2monitoring.cfm.MepLbCreate}. + */ + interface MepLbCreateBuilder { + MepLbCreateBuilder numberMessages(int numberMessages); + + /** + * Define the dataTlv straight from a byte array. + * @param dataTlv String of hex pairs separated by : e.g. AA:BB:CC + * @return The builder + */ + MepLbCreateBuilder dataTlv(byte[] dataTlv); + + /** + * Define the dataTlv byte array from a Hex string. + * @param dataTlv String of hex pairs separated by : e.g. AA:BB:CC + * @return The builder + */ + MepLbCreateBuilder dataTlvHex(String dataTlv); + + /** + * Define the dataTlv byte array from a Base64 string. + * @param dataTlv A string in base64 encoding + * @return The builder + */ + MepLbCreateBuilder dataTlvB64(String dataTlv); + + MepLbCreateBuilder vlanPriority(Priority vlanPriority); + + MepLbCreateBuilder vlanDropEligible(boolean vlanDropEligible); + + MepLbCreate build(); + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/MepLbEntry.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/MepLbEntry.java new file mode 100644 index 0000000000..fe72023ddf --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/MepLbEntry.java @@ -0,0 +1,78 @@ +/* + * Copyright 2017-present Open Networking Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.incubator.net.l2monitoring.cfm; + +/** + * An extension of the MepEntry for Loopback state attributes. + * + */ +public interface MepLbEntry { + /** + * Get the next Loopback Transaction Identifier to be sent in an LBM. + * LBM = LoopBack Message + * @return The next Loopback Transaction Identifier to be sent in an LBM + */ + long nextLbmIdentifier(); + + /** + * Get the total number of LBRs transmitted by this Mep. + * @return The total number of LBRs transmitted + */ + long countLbrTransmitted(); + + /** + * Get the total number of LBRs received by this Mep. + * @return The total number of LBRs received + */ + long countLbrReceived(); + + /** + * Get the total number of valid, in-order LBRs received. + * @return The total number of valid, in-order LBRs received + */ + long countLbrValidInOrder(); + + /** + * Get the total number of valid, out-of-order LBRs received. + * @return The total number of valid, out-of-order LBRs received + */ + long countLbrValidOutOfOrder(); + + /** + * Get the total number of LBRs received whose mac_service_data_unit did not match LBM. + * @return the total number of LBRs received whose mac_service_data_unit did not match LBM + */ + long countLbrMacMisMatch(); + + /** + * Builder for {@link org.onosproject.incubator.net.l2monitoring.cfm.MepLbEntry}. + */ + interface MepLbEntryBuilder { + MepLbEntryBuilder nextLbmIdentifier(long nextLbmIdentifier); + + MepLbEntryBuilder countLbrTransmitted(long countLbrTransmitted); + + MepLbEntryBuilder countLbrReceived(long countLbrRecieved); + + MepLbEntryBuilder countLbrValidInOrder(long countLbrValidInOrder); + + MepLbEntryBuilder countLbrValidOutOfOrder(long countLbrValidOutOfOrder); + + MepLbEntryBuilder countLbrMacMisMatch(long countLbrMacMisMatch); + + MepLbEntry build(); + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/MepLtCreate.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/MepLtCreate.java new file mode 100644 index 0000000000..adf472b267 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/MepLtCreate.java @@ -0,0 +1,65 @@ +/* + * 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.incubator.net.l2monitoring.cfm; + +import org.onlab.packet.MacAddress; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; + +import java.util.BitSet; + +/** + * Object representing Linktrace create parameters. + */ +public interface MepLtCreate { + /** + * The remote Mep will be identified by either a MacAddress or a MEPId. + * @return The MAC address of the remoteMep + */ + MacAddress remoteMepAddress(); + + /** + * The remote Mep will be identified by either a MacAddress or a MEPId. + * @return The id of the remoteMep + */ + MepId remoteMepId(); + + /** + * The Flags field for LTMs transmitted by the MEP. + * [802.1q] 12.14.7.4.2:b + * Bit 0 is use-fdb-only + * @return A bit set of flags + */ + BitSet transmitLtmFlags(); + + /** + * An initial value for the LTM TTL field. 64 if not specified. + * [802.1q] 12.14.7.4.2:d + * @return The default number of hops + */ + Short defaultTtl(); + + + /** + * Builder for {@link org.onosproject.incubator.net.l2monitoring.cfm.MepLtCreate}. + */ + interface MepLtCreateBuilder { + MepLtCreateBuilder transmitLtmFlags(BitSet transmitLtmFlags); + + MepLtCreateBuilder defaultTtl(Short defaultTtl); + + public MepLtCreate build(); + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/MepLtEntry.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/MepLtEntry.java new file mode 100644 index 0000000000..310b58a0fa --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/MepLtEntry.java @@ -0,0 +1,65 @@ +/* + * 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.incubator.net.l2monitoring.cfm; + +import java.util.Collection; + +/** + * An extension of the MepEntry for LinkTrace state attributes. + * + */ +public interface MepLtEntry { + /** + * Get the next LTM Transaction Identifier to be sent in an LTM. + * LTM = Link Trace Message + * @return The next LTM Transaction Identifier to be sent in an LTM + */ + int nextLtmIdentifier(); + + /** + * Get the total number of unexpected LTRs received. + * @return The total number of unexpected LTRs received + */ + int countLtrUnexpected(); + + /** + * Get the total number of LBRs transmitted. + * LBR = LoopBack Response + * @return The total number of LBRs transmitted + */ + int countLbrTransmitted(); + + /** + * Get the linktrace database of results. + * @return A collection of Linktrace transaction details + */ + Collection linktraceDatabase(); + + /** + * Builder for {@link org.onosproject.incubator.net.l2monitoring.cfm.MepLtEntry}. + */ + interface MepLtEntryBuilder { + MepLtEntryBuilder nextLtmIdentifier(int nextLtmIdentifier); + + MepLtEntryBuilder countLtrUnexpected(int countLtrUnexpected); + + MepLtEntryBuilder countLbrTransmitted(int countLbrTransmitted); + + MepLtEntryBuilder addToLinktraceDatabase(MepLtTransactionEntry linktrace); + + MepLtEntryBuilder build(); + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/MepLtReply.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/MepLtReply.java new file mode 100644 index 0000000000..4fa00048e2 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/MepLtReply.java @@ -0,0 +1,104 @@ +/* + * 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.incubator.net.l2monitoring.cfm; + +/** + * The list of LTRs associated with a specific Linktrace transaction. + */ +public interface MepLtReply { + /** + * An index to distinguish among multiple LTRs with the same LTR transaction-id field value. + * reply-order are assigned sequentially from 1, in the order that the Linktrace Initiator received the LTR + * @return The index + */ + int replyOrder(); + + /** + * The integer Reply TTL field value returned in the LTR. + * @return the Reply TTL field value + */ + int replyTtl(); + + /** + * A Boolean value stating whether an LTM was forwarded by the responding MP. + * @return true when the LTM was forwarded + */ + boolean forwarded(); + + /** + * A Boolean value stating whether the forwarded LTM reached a MEP for its MA. + * @return true when the forwarded LTM reached a MEP + */ + boolean terminalMep(); + + /** + * An octet string holding the Last Egress Identifier field returned in the LTR Egress Identifier TLV of the LTR. + * @return the Last Egress Identifier + */ + byte[] lastEgressIdentifier(); + + /** + * An octet string holding the Next Egress Identifier field returned in the LTR Egress Identifier TLV of the LTR. + * @return the Next Egress Identifier + */ + byte[] nextEgressIdentifier(); + + /** + * An enumerated value indicating the value returned in the Relay Action field. + * @return the Relay Action + */ + LtrReply ltrRelay(); + + /** + * Builder for {@link org.onosproject.incubator.net.l2monitoring.cfm.MepLtReply}. + */ + public interface MepLtReplyBuilder { + MepLtReplyBuilder replyOrder(int replyOrder); + + MepLtReplyBuilder replyTtl(int replyTtl); + + MepLtReplyBuilder forwarded(boolean forwarded); + + MepLtReplyBuilder terminalMep(boolean terminalMep); + + MepLtReplyBuilder lastEgressIdentifier(byte[] lastEgressIdentifier); + + MepLtReplyBuilder nextEgressIdentifier(byte[] nextEgressIdentifier); + + MepLtReplyBuilder ltrRelay(LtrReply ltrRelay); + + MepLtReplyBuilder build(); + } + + /** + * An enumerated value indicating the value returned in the Relay Action field. + * reference [802.1q] 12.14.7.5.3:g, Table 21-27 IEEE8021-CFM-MIB.Dot1agCfmRelayActionFieldValue + */ + public enum LtrReply { + /** + * Indicates the LTM reached an MP whose MAC address matches the target MAC address. + */ + RELAY_HIT, + /** + * Indicates the Egress Port was determined by consulting the Filtering Database. + */ + RELAY_FILTERING_DATABASE, + /** + * Indicates the Egress Port was determined by consulting the MIP CCM Database. + */ + RELAY_MIP_CCM_DATABASE; + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/MepLtTransactionEntry.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/MepLtTransactionEntry.java new file mode 100644 index 0000000000..82ddfe143f --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/MepLtTransactionEntry.java @@ -0,0 +1,87 @@ +/* + * 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.incubator.net.l2monitoring.cfm; + +import java.util.BitSet; +import java.util.Collection; + +import org.onlab.packet.MacAddress; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; + +/** + * The LTM entry for a previously transmitted LTM. + * An LTM entry consists of a list of LTR entries, each + * corresponding to a Linktrace Reply (LTR) PDU received in response to that LTM. + * + * See IEEE 802.1Q 12.14.7.5.3 + */ +public interface MepLtTransactionEntry { + /** + * The LTM Transaction Identifier to which the LTR entries will be attached. + * @return The id + */ + int transactionId(); + + /** + * The remote Mep will be identified by either a MacAddress or a MEPId. + * @return The MAC address of the remoteMep + */ + MacAddress macAddress(); + + /** + * The remote Mep will be identified by either a MacAddress or a MEPId. + * @return The id of the remoteMep + */ + MepId mepId(); + + /** + * The Flags field for LTMs transmitted by the MEP. + * [802.1q] 12.14.7.4.2:b + * Bit 0 is use-fdb-only + * @return A bit set of flags + */ + BitSet transmitLtmUseFdbOnly(); + + /** + * An initial value for the LTM TTL field. 64 if not specified. + * [802.1q] 12.14.7.4.2:d + * @return The default number of hops + */ + int defaultTtl(); + + /** + * The list of LTRs associated with a specific Linktrace transaction. + * @return A collection of Replies + */ + Collection ltrReplies(); + + /** + * Builder for {@link org.onosproject.incubator.net.l2monitoring.cfm.MepLtTransactionEntry}. + */ + interface MepLtEntryBuilder { + MepLtEntryBuilder macAddress(MacAddress macAddress); + + MepLtEntryBuilder mepId(MepId mepId); + + MepLtEntryBuilder transmitLtmUseFdbOnly(boolean transmitLtmUseFdbOnly); + + MepLtEntryBuilder defaultTtl(int defaultTtl); + + MepLtEntryBuilder addToLtrReplies(MepLtReply ltrReply); + + MepLtEntryBuilder build(); + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/MepTsCreate.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/MepTsCreate.java new file mode 100644 index 0000000000..fce75aada5 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/MepTsCreate.java @@ -0,0 +1,90 @@ +/* + * 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.incubator.net.l2monitoring.cfm; + +import org.onlab.packet.MacAddress; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; + +import java.util.Optional; + +/** + * Grouping of parameters used to create a Test Signal test on a MEP. + */ +public interface MepTsCreate { + /** + * The remote Mep will be identified by either a MacAddress or a MEPId. + * @return The MAC address of the remoteMep + */ + MacAddress remoteMepAddress(); + + /** + * The remote Mep will be identified by either a MacAddress or a MEPId. + * @return The id of the remoteMep + */ + MepId remoteMepId(); + + /** + * Indicates the MEP is acting in the role of a receiver. + * True by default + * @return true if MEP is acting as a receiver + */ + Optional isReceiver(); + + /** + * Indicates the MEP is acting in the role of a generator. + * False by default + * @return true if MEP is acting as a generator + */ + Optional isGenerator(); + + /** + * This attribute specifies the type of ETH-Test to perform whether it is service interrupting or not. + * An 'in-service' value indicates that the ETH-Test is in service and normal + * client service traffic is not interrupted. A 'out-of-service' value + * indicates that the ETH-Test is out of service and normal client service + * traffic is disrupted. + * The test-type parameter is only relevant for the generator side + * @return test type enumeration + */ + Optional testType(); + + /** + * Builder for {@link org.onosproject.incubator.net.l2monitoring.cfm.MepTsCreate}. + */ + interface MepTsCreateBuilder { + MepTsCreateBuilder isReceiver(Optional isReceiver); + + MepTsCreateBuilder isGenerator(Optional isGenerator); + + MepTsCreateBuilder testType(Optional testType); + + MepTsCreateBuilder build(); + } + + /** + * Types of Test Signal test. + */ + public enum TestType { + /** + * Indicates the ETH-Test is in-service and normal client service traffic is not interrupted. + */ + INSERVICE, + /** + * Indicates the ETH-Test is out-of-service and normal client service traffic is disrupted. + */ + OUTOFSERVICE + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/RemoteMepEntry.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/RemoteMepEntry.java new file mode 100644 index 0000000000..91d45d85b0 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/RemoteMepEntry.java @@ -0,0 +1,126 @@ +/* + * 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.incubator.net.l2monitoring.cfm; + +import java.time.Duration; + +import org.onlab.packet.MacAddress; +import org.onosproject.incubator.net.l2monitoring.cfm.SenderIdTlv.SenderIdTlvType; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; + +/** + * Defined in IEEE 802.1Q Section 12.14.7.6.3 Read MEP Database - Outputs. + * + */ +public interface RemoteMepEntry { + + MepId remoteMepId(); + + /** + * Get the operational state of a Remote MEP state machine for a remote MEP. + * @return An enumerated value + */ + RemoteMepState state(); + + /** + * Get the time since Remote MEP last entered either RMEP_FAILED or RMEP_OK state. + * @return Duration + */ + Duration failedOrOkTime(); + + /** + * Get the MAC address of the remote MEP or 0 if no CCM has been received. + * @return A MAC address + */ + MacAddress macAddress(); + + /** + * A Boolean value indicating the state of the RDI bit in the last received CCM. + * + * @return (TRUE for RDI = 1), or FALSE, if none has been received + */ + boolean rdi(); + + /** + * Get the Port Status TLV from the last CCM received from the remote MEP. + * @return An enumerated value + */ + PortStatusTlvType portStatusTlvType(); + + /** + * Get the Interface Status TLV from the last CCM received from the remote MEP. + * @return An enumerated value + */ + InterfaceStatusTlvType interfaceStatusTlvType(); + + /** + * Get the Sender ID TLV type from the last CCM received from the remote MEP or default. + * @return An enumerated value + */ + SenderIdTlvType senderIdTlvType(); + + /** + * Builder for {@link org.onosproject.incubator.net.l2monitoring.cfm.RemoteMepEntry}. + */ + public interface RemoteMepEntryBuilder { + RemoteMepEntryBuilder failedOrOkTime(Duration failedOrOkTime); + + RemoteMepEntryBuilder macAddress(MacAddress macAddress); + + RemoteMepEntryBuilder rdi(boolean rdi); + + RemoteMepEntryBuilder portStatusTlvType(PortStatusTlvType portStatusTlvType); + + RemoteMepEntryBuilder interfaceStatusTlvType(InterfaceStatusTlvType interfaceStatusTlvType); + + RemoteMepEntryBuilder senderIdTlvType(SenderIdTlvType senderIdTlvType); + + RemoteMepEntry build(); + } + + /** + * Remote MEP States. + */ + public enum RemoteMepState { + RMEP_IDLE, + RMEP_START, + RMEP_FAILED, + RMEP_OK + } + + /** + * Port Status TLV types. + */ + public enum PortStatusTlvType { + PS_NO_STATUS_TLV, + PS_BLOCKED, + PS_UP; + } + + /** + * Interface Status TLV types. + */ + public enum InterfaceStatusTlvType { + IS_NO_STATUS_TLV, + IS_UP, + IS_DOWN, + IS_TESTING, + IS_UNKNOWN, + IS_DORMANT, + IS_NOTPRESENT, + IS_LOWERLAYERDOWN; + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/SenderIdTlv.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/SenderIdTlv.java new file mode 100644 index 0000000000..12cd23b98a --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/SenderIdTlv.java @@ -0,0 +1,36 @@ +/* + * 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.incubator.net.l2monitoring.cfm; + +/** + * Object for representing Sender ID TLV. + */ +public interface SenderIdTlv { + + /** + * Type of Sender ID TLV. + */ + public enum SenderIdTlvType { + SI_NO_SENDER_ID_TLV, + SI_CHASSIS_COMPONENT, + SI_INTERFACE_ALIAS, + SI_PORT_COMPONENT, + SI_MAC_ADDRESS, + SI_NETWORK_ADDRESS, + SI_INTERFACE_NAME, + SI_LOCALLY_ASSIGNED; + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MaId2Octet.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MaId2Octet.java new file mode 100644 index 0000000000..d18fb6f8f9 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MaId2Octet.java @@ -0,0 +1,52 @@ +/* + * Copyright 2017-present Open Networking Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.incubator.net.l2monitoring.cfm.identifier; + +/** + * The 2 octet format of MA Short Name. + * This is similar to primaryVid except range is 0 to 65535 + */ +public final class MaId2Octet extends MaIdPrimaryVid { + protected static int uintUpperLimit = 65535; + + protected MaId2Octet(int id2octet) { + super(id2octet); + } + + public static MaIdShort asMaId(int id) { + if (id <= lowerLimit || id > uintUpperLimit) { + throw new IllegalArgumentException("MA Id must be between " + + lowerLimit + " and " + uintUpperLimit + ". Rejecting: " + id); + } + return new MaId2Octet(id); + } + + public static MaIdShort asMaId(String maName) { + int id = 0; + try { + id = Integer.parseInt(maName); + return asMaId(id); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("MA Name must be numeric. Rejecting: " + + maName + " " + e.getMessage()); + } + } + + @Override + public MaIdType nameType() { + return MaIdType.TWOOCTET; + } +} \ No newline at end of file diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MaIdCharStr.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MaIdCharStr.java new file mode 100644 index 0000000000..5fee714807 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MaIdCharStr.java @@ -0,0 +1,52 @@ +/* + * Copyright 2017-present Open Networking Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.incubator.net.l2monitoring.cfm.identifier; + +import org.onlab.util.Identifier; + +/** + * A representation of a string identifier as an MA identifier. + */ +public final class MaIdCharStr extends Identifier implements MaIdShort { + private static final String MANAME_PATTERN = "[a-zA-Z0-9\\-:]{1,48}"; + + protected MaIdCharStr(String mdName) { + super(mdName); + } + + @Override + public String maName() { + return identifier; + } + + @Override + public int getNameLength() { + return identifier.length(); + } + + @Override + public MaIdType nameType() { + return MaIdType.CHARACTERSTRING; + } + + public static MaIdShort asMaId(String maName) { + if (maName == null || !maName.matches(MANAME_PATTERN)) { + throw new IllegalArgumentException("MA Name must follow pattern " + + MANAME_PATTERN + " Rejecting: " + maName); + } + return new MaIdCharStr(maName); + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MaIdIccY1731.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MaIdIccY1731.java new file mode 100644 index 0000000000..27b3d03af4 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MaIdIccY1731.java @@ -0,0 +1,80 @@ +/* + * 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.incubator.net.l2monitoring.cfm.identifier; + +import org.onlab.util.Identifier; + +/** + * ICC-based MEG ID Format, thirteen octet field. + * + * It consists of two subfields: the ITU Carrier Code (ICC) followed by a unique + * MEG ID code (UMC). The ITU Carrier Code consists of 1-6 + * left-justified characters, alphabetic, or leading alphabetic + * with trailing numeric. The UMC code immediately follows the ICC + * and shall consist of 7-12 characters, with trailing NULLs, + * completing the 13-character MEG ID Value. + * reference + * [Y.1731] Annex A; + */ +public final class MaIdIccY1731 extends Identifier implements MaIdShort { + private static final String ICC_PATTERN = "[a-z|A-Z|0-9]{1,6}"; + private static final String UMC_PATTERN = "[a-z|A-Z|0-9]{7,12}"; + private int iccLength = 0; + + protected MaIdIccY1731(String icc, String umc) { + super(icc + umc); + iccLength = icc.length(); + } + + @Override + public String toString() { + return identifier.substring(0, iccLength) + ":" + identifier.substring(iccLength); + } + + @Override + public String maName() { + return identifier; + } + + @Override + public int getNameLength() { + return identifier.length(); + } + + @Override + public MaIdType nameType() { + return MaIdType.ICCY1731; + } + + public static MaIdShort asMaId(String icc, String umc) { + if (icc == null || !icc.matches(ICC_PATTERN)) { + throw new IllegalArgumentException("ICC part must follow pattern " + + ICC_PATTERN + " Rejecting: " + icc); + } else if (umc == null || !umc.matches(UMC_PATTERN)) { + throw new IllegalArgumentException("UMC part must follow pattern " + + UMC_PATTERN + " Rejecting: " + umc); + } + return new MaIdIccY1731(icc, umc); + } + + public static MaIdShort asMaId(String iccAndUmc) { + String[] nameParts = iccAndUmc.split(":"); + if (nameParts.length != 2) { + throw new IllegalArgumentException("Expecting format like ICC:UMC"); + } + return asMaId(nameParts[0], nameParts[1]); + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MaIdPrimaryVid.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MaIdPrimaryVid.java new file mode 100644 index 0000000000..f82efc4b56 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MaIdPrimaryVid.java @@ -0,0 +1,69 @@ +/* + * 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.incubator.net.l2monitoring.cfm.identifier; + +import org.onlab.util.Identifier; + +/** + * A representation of a Vid identifier as an int as an MA identifier. + */ +public class MaIdPrimaryVid extends Identifier implements MaIdShort { + private static final int PRIMARY_VID_BYTES = 2; + protected static int lowerLimit = 0; + protected static int upperLimit = 4095; + + protected MaIdPrimaryVid(int primaryVid) { + super(primaryVid); + } + + @Override + public String maName() { + return identifier.toString(); + } + + /** + * Vid length of 12 bits will be rounded up to 2 bytes (16 bits). + * @return 2 bytes + */ + @Override + public int getNameLength() { + return PRIMARY_VID_BYTES; + } + + @Override + public MaIdType nameType() { + return MaIdType.PRIMARYVID; + } + + public static MaIdShort asMaId(String maName) { + int id = 0; + try { + id = Integer.parseInt(maName); + return asMaId(id); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("MA Name must be numeric. Rejecting: " + + maName + " " + e.getMessage()); + } + } + + public static MaIdShort asMaId(int id) { + if (id <= lowerLimit || id > upperLimit) { + throw new IllegalArgumentException("MA Id must be between " + + lowerLimit + " and " + upperLimit + ". Rejecting: " + id); + } + return new MaIdPrimaryVid(id); + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MaIdRfc2685VpnId.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MaIdRfc2685VpnId.java new file mode 100644 index 0000000000..d4e623cc03 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MaIdRfc2685VpnId.java @@ -0,0 +1,58 @@ +/* + * 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.incubator.net.l2monitoring.cfm.identifier; + +import org.onlab.util.Identifier; + +/** + * A representation of a Rfc2685VpnId identifier in Hexadecimal as an MA identifier. + */ +public final class MaIdRfc2685VpnId extends Identifier implements MaIdShort { + private static final String VPNID_HEX_PATTERN = "([a-f|A-F|0-9]{2}:){6}[a-f|A-F|0-9]{2}"; + + protected MaIdRfc2685VpnId(String maNameHex) { + super(maNameHex); + } + + @Override + public String maName() { + return identifier; + } + + /** + * Identifier will be in the format aa:bb:cc:dd:ee:ff:11. + * Each pair of hex chars (and one colon) is one byte + * To get the length in bytes add 1 (extra colon) and divide by 3 + * @return name length in bytes + */ + @Override + public int getNameLength() { + return (identifier.length() + 1) / 3; + } + + @Override + public MaIdType nameType() { + return MaIdType.RFC2685VPNID; + } + + public static MaIdShort asMaIdHex(String hexString) { + if (hexString == null || !hexString.matches(VPNID_HEX_PATTERN)) { + throw new IllegalArgumentException("MA Name must follow pattern " + + VPNID_HEX_PATTERN + " Rejecting: " + hexString); + } + return new MaIdRfc2685VpnId(hexString.toLowerCase()); + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MaIdShort.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MaIdShort.java new file mode 100644 index 0000000000..6e1d6fb0d0 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MaIdShort.java @@ -0,0 +1,73 @@ +/* + * 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.incubator.net.l2monitoring.cfm.identifier; + +/** + * Representation of a Maintenance Association ID. + * + * The MA Id consists of a name and a name type. + * In certain applications the MA name and type together with the MD Name and + * name type are embedded in to a TLV and passed between systems, and so it is + * important that all combinations of the name and name type can be represented here. + * + * IEEE 802.1Q Table 21-20—Short MA Name Format. + */ +public interface MaIdShort { + + /** + * Get the MA name as a string. + * @return A string representation of the name + */ + String maName(); + + /** + * Get the length of the MD name. + * @return The length of the name in bytes + */ + int getNameLength(); + + /** + * The type of the name. + * @return An enumerated value + */ + MaIdType nameType(); + + /** + * Supported types of MD identifier. + */ + enum MaIdType { + /** + * Implemented as {@link org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr}. + */ + CHARACTERSTRING, + /** + * Implemented as {@link org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaId2Octet}. + */ + TWOOCTET, + /** + * Implemented as {@link org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdIccY1731}. + */ + ICCY1731, + /** + * Implemented as {@link org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdPrimaryVid}. + */ + PRIMARYVID, + /** + * Implemented as {@link org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdRfc2685VpnId}. + */ + RFC2685VPNID + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MdId.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MdId.java new file mode 100644 index 0000000000..4d82f5189d --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MdId.java @@ -0,0 +1,75 @@ +/* + * Copyright 2017-present Open Networking Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.incubator.net.l2monitoring.cfm.identifier; + +/** + * Representation of a Maintenance Domain ID. + * + * The MD Id consists of a name and a name type. + * In certain applications the MD name and type are embedded in to a TLV and + * passed between systems, and so it is important that all combinations of the + * name and name type can be represented here. + * + * For example the name "test1.domain.tld" could be a valid with either a + * CharacterString name type and a DomainName name type. Both could be present + * on the same system concurrently and must be distinguished by the name type + * + * IEEE 802.1Q Table 21-19—Maintenance Domain Name Format. + */ +public interface MdId { + public static final int MD_NAME_MAX_LEN = 45; + public static final int MD_NAME_MIN_LEN = 1; + + /** + * Get the MD name as a string. + * @return A string representation of the name + */ + String mdName(); + + /** + * Get the length of the MD name. + * @return The length of the name in bytes + */ + int getNameLength(); + + /** + * The type of the name. + * @return An enumerated value + */ + MdNameType nameType(); + + /** + * Supported types of MA identifier. + */ + enum MdNameType { + /** + * Implemented as {@link org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr}. + */ + CHARACTERSTRING, + /** + * Implemented as {@link org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdDomainName}. + */ + DOMAINNAME, + /** + * Implemented as {@link org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdMacUint}. + */ + MACANDUINT, + /** + * Implemented as {@link org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdNone}. + */ + NONE + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MdIdCharStr.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MdIdCharStr.java new file mode 100644 index 0000000000..5fea05ad91 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MdIdCharStr.java @@ -0,0 +1,53 @@ +/* + * 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.incubator.net.l2monitoring.cfm.identifier; + +import org.onlab.util.Identifier; + +/** + * A representation of a string identifier as an MD identifier. + */ +public final class MdIdCharStr extends Identifier implements MdId { + private static final String MDNAME_PATTERN = + "[a-zA-Z0-9\\-:\\.]{" + MD_NAME_MIN_LEN + "," + MD_NAME_MAX_LEN + "}"; + + protected MdIdCharStr(String mdName) { + super(mdName); + } + + @Override + public String mdName() { + return identifier; + } + + @Override + public int getNameLength() { + return identifier.length(); + } + + @Override + public MdNameType nameType() { + return MdNameType.CHARACTERSTRING; + } + + public static MdId asMdId(String mdName) { + if (mdName == null || !mdName.matches(MDNAME_PATTERN)) { + throw new IllegalArgumentException("MD Name must follow pattern " + + MDNAME_PATTERN + " Rejecting: " + mdName); + } + return new MdIdCharStr(mdName); + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MdIdDomainName.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MdIdDomainName.java new file mode 100644 index 0000000000..c015fd1283 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MdIdDomainName.java @@ -0,0 +1,64 @@ +/* + * Copyright 2017-present Open Networking Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.incubator.net.l2monitoring.cfm.identifier; + +import org.onlab.util.Identifier; + +import com.google.common.net.InternetDomainName; + +/** + * A representation of a domain name as an MD identifier. + */ +public class MdIdDomainName extends Identifier implements MdId { + + protected MdIdDomainName(InternetDomainName mdDomainName) { + super(mdDomainName); + } + + @Override + public String mdName() { + return identifier.toString(); + } + + @Override + public int getNameLength() { + return identifier.toString().length(); + } + + public static MdId asMdId(String mdName) { + if (mdName == null || !InternetDomainName.isValid(mdName)) { + throw new IllegalArgumentException("MD Name must follow internet domain name pattern " + + " Rejecting: " + mdName); + } + return asMdId(InternetDomainName.from(mdName)); + } + + @Override + public MdNameType nameType() { + return MdNameType.DOMAINNAME; + } + + + public static MdId asMdId(InternetDomainName mdName) { + if (mdName == null || mdName.toString().length() < MD_NAME_MIN_LEN || + mdName.toString().length() > MD_NAME_MAX_LEN) { + throw new IllegalArgumentException("MD Domain Name must be between " + + MD_NAME_MIN_LEN + " and " + MD_NAME_MAX_LEN + " chars long" + + " Rejecting: " + mdName); + } + return new MdIdDomainName(mdName); + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MdIdMacUint.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MdIdMacUint.java new file mode 100644 index 0000000000..b790f0e790 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MdIdMacUint.java @@ -0,0 +1,73 @@ +/* + * 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.incubator.net.l2monitoring.cfm.identifier; + +import org.apache.commons.lang3.tuple.Pair; +import org.onlab.packet.MacAddress; +import org.onlab.util.Identifier; + +/** + * A representation of a Mac Address and Unsigned Integer as an MD identifier. + */ +public class MdIdMacUint extends Identifier> implements MdId { + private static final String MACUINT_PATTERN = "([a-fA-F0-9]{2}[\\-:]){6}[0-9]{1,5}"; + private static final int MAC_UINT_LENGTH_BYTES = 8; + private static final int UINT_MIN = 0; + private static final int UINT_MAX = 65535; + + protected MdIdMacUint(Pair macAndUint) { + super(macAndUint); + } + + @Override + public String mdName() { + return identifier.getLeft().toString() + ":" + identifier.getRight(); + } + + @Override + public String toString() { + return mdName(); + } + + @Override + public int getNameLength() { + return MAC_UINT_LENGTH_BYTES; + } + + public static MdId asMdId(String mdName) { + if (mdName == null || !mdName.matches(MACUINT_PATTERN)) { + throw new IllegalArgumentException("MD Name must follow pattern " + + MACUINT_PATTERN + " Rejecting: " + mdName); + } + MacAddress macAddress = MacAddress.valueOf(mdName.substring(0, 17)); + int uInt = Integer.parseInt(mdName.substring(18)); + + return asMdId(macAddress, uInt); + } + + @Override + public MdNameType nameType() { + return MdNameType.MACANDUINT; + } + + public static MdId asMdId(MacAddress macAddress, int uInt) { + if (uInt < UINT_MIN || uInt > UINT_MAX) { + throw new IllegalArgumentException("uInt must be between " + + UINT_MIN + " and " + UINT_MAX + ". Rejecting: " + uInt); + } + return new MdIdMacUint(Pair.of(macAddress, uInt)); + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MdIdNone.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MdIdNone.java new file mode 100644 index 0000000000..0e9eaa8081 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MdIdNone.java @@ -0,0 +1,59 @@ +/* + * 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.incubator.net.l2monitoring.cfm.identifier; + +/** + * A representation of NONE as an MA identifier. + */ +public class MdIdNone implements MdId { + + @Override + public String mdName() { + return null; + } + + @Override + public String toString() { + return ""; + } + + @Override + public int getNameLength() { + return 0; + } + + @Override + public MdNameType nameType() { + return MdNameType.NONE; + } + + public static MdId asMdId() { + return new MdIdNone(); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof MdIdNone) { + return true; + } + return false; + } + + @Override + public int hashCode() { + return super.hashCode(); + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MepId.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MepId.java new file mode 100644 index 0000000000..dde3da3665 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MepId.java @@ -0,0 +1,46 @@ +/* + * 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.incubator.net.l2monitoring.cfm.identifier; + +import org.onlab.util.Identifier; + +/** + * Representation of a Mep Id. + */ +public final class MepId extends Identifier { + + private MepId(short id) { + super(id); + } + + public static MepId valueOf(short id) { + if (id < 1 || id > 8191) { + throw new IllegalArgumentException( + "Invalid value for Mep Id - must be between 1-8191 inclusive. " + + "Rejecting " + id); + } + return new MepId(id); + } + + public short value() { + return this.identifier; + } + + @Override + public String toString() { + return String.valueOf(identifier); + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/package-info.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/package-info.java new file mode 100644 index 0000000000..7d5a4ebd29 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/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. + */ + +/** + * Identifiers related to Connectivity Fault Management functionality from IEEE 802.1Q Chapter 18. + */ +package org.onosproject.incubator.net.l2monitoring.cfm.identifier; diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/package-info.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/package-info.java new file mode 100644 index 0000000000..41bf1b97be --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/package-info.java @@ -0,0 +1,22 @@ +/* + * 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. + */ + +/** + * Object model for Connectivity Fault Management functionality from IEEE 802.1Q Chapter 18. + * + * See {@link org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain} for the hierarchy. + */ +package org.onosproject.incubator.net.l2monitoring.cfm; diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/CfmConfigException.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/CfmConfigException.java new file mode 100644 index 0000000000..6d0d057b23 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/CfmConfigException.java @@ -0,0 +1,36 @@ +/* + * Copyright 2016-present Open Networking Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.incubator.net.l2monitoring.cfm.service; + +/** + * Exception for configuration related to Connectivity Fault Management. + */ +public class CfmConfigException extends Throwable { + + private static final long serialVersionUID = 1L; + + public CfmConfigException(String message) { + super(message); + } + + public CfmConfigException(Throwable t) { + super(t); + } + + public CfmConfigException(String message, Throwable t) { + super(message, t); + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/CfmMdService.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/CfmMdService.java new file mode 100644 index 0000000000..9c9aa46732 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/CfmMdService.java @@ -0,0 +1,97 @@ +/* + * 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.incubator.net.l2monitoring.cfm.service; + +import java.util.Collection; +import java.util.Optional; + +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceAssociation; +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; + +/** + * For the management of Maintenance Domains and Maintenance Associations. + */ +public interface CfmMdService { + + /** + * Get a list of all of the Maintenance Domains on the system. + * @return A collection Maintenance domains from the Distributed MD Store. + */ + Collection getAllMaintenanceDomain(); + + /** + * Get a specific Maintenance Domain by its identifier. + * @param mdName An identifier for the Maintenance Domain + * @return A Maintenance Domain from the Distributed MD Store. Empty if not found. + */ + Optional getMaintenanceDomain(MdId mdName); + + /** + * Delete a specific Maintenance Domain by its identifier. + * @param mdName An identifier for the Maintenance Domain to be deleted + * @return True if the MD was found and deleted + * @exception CfmConfigException If there were any Meps dependent on the MD or its MAs + */ + boolean deleteMaintenanceDomain(MdId mdName) throws CfmConfigException; + + /** + * Create or replace a Maintenance Domain. + * @param md The Maintenance Domain to create or replace + * @return true if an MD of this name already existed + * @throws CfmConfigException If it is a replacement and there were any + * Meps dependent on the MD or its MAs + */ + boolean createMaintenanceDomain(MaintenanceDomain md) throws CfmConfigException; + + /** + * Get all of the Maintenance Associations for a Maintenance Domain. + * @param mdName The identifier of the Maintenance Domain + * @return A collection of Maintenance Associations + */ + Collection getAllMaintenanceAssociation(MdId mdName); + + /** + * Get a specific Maintenance Association of a specific Maintenance Domain. + * @param mdName The identifier of the Maintenance Domain + * @param maName The identifier of the Maintenance Association + * @return A Maintenance Association from the Distributed MD Store. Empty if not found. + * @throws IllegalArgumentException if MD is not found + */ + Optional getMaintenanceAssociation(MdId mdName, MaIdShort maName); + + /** + * Delete a specific Maintenance Association of a specific Maintenance Domain. + * @param mdName The identifier of the Maintenance Domain + * @param maName The identifier of the Maintenance Association + * @return true if deleted + * @throws CfmConfigException If there were any Meps dependent on the MD or its MAs + * @throws IllegalArgumentException if MD is not found + */ + boolean deleteMaintenanceAssociation(MdId mdName, MaIdShort maName) throws CfmConfigException; + + /** + * Create or replace a Maintenance Domain of a specific Maintenance Domain. + * @param mdName The identifier of the Maintenance Domain + * @param ma A Maintenance Association + * @return true if an MA of this name already existed in the MD + * @throws CfmConfigException If it is a replacement and there were any + * Meps dependent on the MD or its MAs + * @throws IllegalArgumentException if MD is not found + */ + boolean createMaintenanceAssociation(MdId mdName, MaintenanceAssociation ma) throws CfmConfigException; +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/CfmMepEvent.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/CfmMepEvent.java new file mode 100644 index 0000000000..26abc45446 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/CfmMepEvent.java @@ -0,0 +1,61 @@ +/* + * 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.incubator.net.l2monitoring.cfm.service; + +import org.onosproject.event.AbstractEvent; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep; + +/** + * Event related to the maintenance of CFM MEPs. + */ +public class CfmMepEvent extends AbstractEvent { + + /** + * Type of Mep events. + */ + public enum Type { + /** + * Signifies that a new Mep has been detected. + */ + MEP_ADDED, + + /** + * Signifies that a Mep has been removed. + */ + MEP_REMOVED, + + /** + * Signifies that a Mep has been updated. + */ + MEP_UPDATED, + + /** + * Signifies that the MEP has raised a fault alarm. + */ + MEP_FAULT_ALARM + } + + /** + * Creates an event of a given type and for the specified Mep and the current time. + * + * @param type Mep event type + * @param mep event Mep subject + */ + protected CfmMepEvent(Type type, Mep mep) { + super(type, mep); + // TODO Auto-generated constructor stub + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/CfmMepListener.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/CfmMepListener.java new file mode 100644 index 0000000000..655823f54b --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/CfmMepListener.java @@ -0,0 +1,24 @@ +/* + * 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.incubator.net.l2monitoring.cfm.service; + +import org.onosproject.event.EventListener; + +/** + * Entity capable of receiving {@link org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepEvent} events. + */ +public interface CfmMepListener extends EventListener { +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/CfmMepProgrammable.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/CfmMepProgrammable.java new file mode 100644 index 0000000000..b92777b2d8 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/CfmMepProgrammable.java @@ -0,0 +1,28 @@ +/* + * 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.incubator.net.l2monitoring.cfm.service; + +import org.onosproject.net.driver.HandlerBehaviour; + +/** + * Behaviour that allows Layer 2 Monitoring as defined in IEEE 802.1Q be implemented by devices. + * + * Has all of the same methods as + * {@link org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepService} so reuse that + */ +public interface CfmMepProgrammable extends HandlerBehaviour, CfmMepService { + +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/CfmMepService.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/CfmMepService.java new file mode 100644 index 0000000000..c0c2f92548 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/CfmMepService.java @@ -0,0 +1,109 @@ +/* + * 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.incubator.net.l2monitoring.cfm.service; + +import java.util.Collection; + +import org.onosproject.incubator.net.l2monitoring.cfm.Mep; +import org.onosproject.incubator.net.l2monitoring.cfm.MepEntry; +import org.onosproject.incubator.net.l2monitoring.cfm.MepLbCreate; +import org.onosproject.incubator.net.l2monitoring.cfm.MepLtCreate; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; + +/** + * For the management of Maintenance Association Endpoints. + * + * These are dependent on the Maintenance Domain service which maintains the + * Maintenance Domain and Maintenance Associations + */ +public interface CfmMepService { + /** + * Retrieve all {@link org.onosproject.incubator.net.l2monitoring.cfm.MepEntry}(s) belonging to an MA. + * @param mdName A Maintenance Domain + * @param maName A Maintetance Association in the MD + * @return A collection of MEP Entries + * @throws CfmConfigException If there a problem with the MD or MA + */ + Collection getAllMeps(MdId mdName, MaIdShort maName) + throws CfmConfigException; + + /** + * Retrieve a named {@link org.onosproject.incubator.net.l2monitoring.cfm.MepEntry} belonging to an MA. + * @param mdName A Maintenance Domain + * @param maName A Maintetance Association in the MD + * @param mepId A Mep Id + * @return A MEP Entry or null if none found + * @throws CfmConfigException If there a problem with the MD, MA or MEP + */ + MepEntry getMep(MdId mdName, MaIdShort maName, MepId mepId) + throws CfmConfigException; + + /** + * Delete a named {@link org.onosproject.incubator.net.l2monitoring.cfm.Mep} belonging to an MA. + * @param mdName A Maintenance Domain + * @param maName A Maintetance Association in the MD + * @param mepId A Mep Id + * @return true if the MEP was deleted successfully. false if it was not found + * @throws CfmConfigException If there a problem with the MD or MA + */ + boolean deleteMep(MdId mdName, MaIdShort maName, MepId mepId) + throws CfmConfigException; + + /** + * Create a named {@link org.onosproject.incubator.net.l2monitoring.cfm.Mep} on an MA. + * @param mdName A Maintenance Domain + * @param maName A Maintetance Association in the MD + * @param mep A Mep object + * @return False if it was created successfully. True if the object already exists. + * @throws CfmConfigException If there a problem with the MD, MA or MEP + */ + boolean createMep(MdId mdName, MaIdShort maName, Mep mep) + throws CfmConfigException; + + /** + * Create a {@link org.onosproject.incubator.net.l2monitoring.cfm.MepLbEntry Loopback} session on the named Mep. + * @param mdName A Maintenance Domain + * @param maName A Maintetance Association in the MD + * @param mepId A Mep Id + * @param lbCreate The Loopback session details + * @throws CfmConfigException If there a problem with the MD, MA or MEP + */ + void transmitLoopback(MdId mdName, MaIdShort maName, MepId mepId, + MepLbCreate lbCreate) throws CfmConfigException; + + /** + * Abort a {@link org.onosproject.incubator.net.l2monitoring.cfm.MepLbEntry Loopback} session on the named Mep. + * @param mdName A Maintenance Domain + * @param maName A Maintetance Association in the MD + * @param mepId A Mep Id + * @throws CfmConfigException If there a problem with the MD, MA or MEP + */ + void abortLoopback(MdId mdName, MaIdShort maName, MepId mepId) + throws CfmConfigException; + + /** + * Create a {@link org.onosproject.incubator.net.l2monitoring.cfm.MepLtEntry Linktrace} session on the named Mep. + * @param mdName A Maintenance Domain + * @param maName A Maintetance Association in the MD + * @param mepId A Mep Id + * @param ltCreate The Linktrace session details + * @throws CfmConfigException If there a problem with the MD, MA or MEP + */ + void transmitLinktrace(MdId mdName, MaIdShort maName, MepId mepId, + MepLtCreate ltCreate) throws CfmConfigException; +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/MdEvent.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/MdEvent.java new file mode 100644 index 0000000000..e3090f7b90 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/MdEvent.java @@ -0,0 +1,38 @@ +/* + * 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.incubator.net.l2monitoring.cfm.service; + +import org.onosproject.event.AbstractEvent; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; + +/** + * Event related to the maintenance of CFM MDs. + */ +public class MdEvent extends AbstractEvent { + + /** + * MD Event types supported. + */ + public enum Type { + MD_ADDED, + MD_REMOVED, + MD_UPDATED + } + + public MdEvent(Type type, MdId mdId) { + super(type, mdId); + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/MdListener.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/MdListener.java new file mode 100644 index 0000000000..ca840d8c41 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/MdListener.java @@ -0,0 +1,24 @@ +/* + * 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.incubator.net.l2monitoring.cfm.service; + +import org.onosproject.event.EventListener; + +/** + * Listener interface for MD Store. + */ +public interface MdListener extends EventListener { +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/MdStore.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/MdStore.java new file mode 100644 index 0000000000..26a39331a4 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/MdStore.java @@ -0,0 +1,58 @@ +/* + * 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.incubator.net.l2monitoring.cfm.service; + +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; +import org.onosproject.store.Store; + +import java.util.Collection; +import java.util.Optional; + +/** + * {@link org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain Maintenance Domain's} storage interface. + * Note: because the MaintenanceDomain is immutable if anything needs to be + * changed in it, then it must be replaced in the store. This includes adding + * and deleting Maintenance Associations from an MD. + */ +public interface MdStore extends Store { + /** + * Get a list of all of the Maintenance Domains on the system. + * @return A collection Maintenance domains from the MD Store. + */ + Collection getAllMaintenanceDomain(); + + /** + * Get a specific Maintenance Domain by its identifier. + * @param mdName An identifier for the Maintenance Domain + * @return A Maintenance Domain from the MD Store. Empty if not found. + */ + Optional getMaintenanceDomain(MdId mdName); + + /** + * Delete a specific Maintenance Domain by its identifier. + * @param mdName An identifier for the Maintenance Domain to be deleted + * @return True if the MD was found and deleted + */ + boolean deleteMaintenanceDomain(MdId mdName); + + /** + * Create or replace a Maintenance Domain. + * @param md The Maintenance Domain to create or replace + * @return true if an MD of this name already existed + */ + boolean createUpdateMaintenanceDomain(MaintenanceDomain md); +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/MdStoreDelegate.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/MdStoreDelegate.java new file mode 100644 index 0000000000..91a626060c --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/MdStoreDelegate.java @@ -0,0 +1,24 @@ +/* + * 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.incubator.net.l2monitoring.cfm.service; + +import org.onosproject.store.StoreDelegate; + +/** + * Delegate for MD Store. + */ +public interface MdStoreDelegate extends StoreDelegate { +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/package-info.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/package-info.java new file mode 100644 index 0000000000..79ca82909d --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/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. + */ + +/** + * Interfaces related to the Service for Connectivity Fault Management. + */ +package org.onosproject.incubator.net.l2monitoring.cfm.service; diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/DefaultMeasurementCreateBase.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/DefaultMeasurementCreateBase.java new file mode 100644 index 0000000000..62b9e3a607 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/DefaultMeasurementCreateBase.java @@ -0,0 +1,287 @@ +/* + * 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.incubator.net.l2monitoring.soam; + +import java.time.Duration; +import java.time.Instant; + +import org.onosproject.incubator.net.l2monitoring.cfm.Mep.Priority; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.soam.StartTime.StartTimeOption; +import org.onosproject.incubator.net.l2monitoring.soam.StopTime.StopTimeOption; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.DataPattern; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.TestTlvPattern; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.Version; + +/** + * Abstract implementation of {@link org.onosproject.incubator.net.l2monitoring.soam.MeasurementCreateBase}. + */ +public abstract class DefaultMeasurementCreateBase + implements MeasurementCreateBase { + protected final Version version; + + protected final MepId remoteMepId; + protected final Duration messagePeriod; + protected final Priority priority; + protected final Short frameSize; + protected final DataPattern dataPattern; + protected final boolean testTlvIncluded; + protected final TestTlvPattern testTlvPattern; + protected final Duration measurementInterval; + protected final Short numberIntervalsStored; + protected final boolean alignMeasurementIntervals; + protected final Duration alignMeasurementOffset; + protected final SessionType sessionType; + protected final StartTime startTime; + protected final StopTime stopTime; + + protected DefaultMeasurementCreateBase(DefaultMeasCreateBaseBuilder builder) { + this.version = builder.version; + + this.remoteMepId = builder.remoteMepId; + this.messagePeriod = builder.messagePeriod; + this.priority = builder.priority; + this.frameSize = builder.frameSize; + this.dataPattern = builder.dataPattern; + this.testTlvIncluded = builder.testTlvIncluded; + this.testTlvPattern = builder.testTlvPattern; + this.measurementInterval = builder.measurementInterval; + this.numberIntervalsStored = builder.numberIntervalsStored; + this.alignMeasurementIntervals = builder.alignMeasurementIntervals; + this.alignMeasurementOffset = builder.alignMeasurementOffset; + this.sessionType = builder.sessionType; + this.startTime = builder.startTime; + this.stopTime = builder.stopTime; + } + + @Override + public Version version() { + return version; + } + + @Override + public MepId remoteMepId() { + return remoteMepId; + } + + @Override + public Duration messagePeriod() { + return messagePeriod; + } + + @Override + public Priority priority() { + return priority; + } + + @Override + public Short frameSize() { + return frameSize; + } + + @Override + public DataPattern dataPattern() { + return dataPattern; + } + + @Override + public boolean testTlvIncluded() { + return testTlvIncluded; + } + + @Override + public TestTlvPattern testTlvPattern() { + return testTlvPattern; + } + + @Override + public Duration measurementInterval() { + return measurementInterval; + } + + @Override + public Short numberIntervalsStored() { + return numberIntervalsStored; + } + + @Override + public boolean alignMeasurementIntervals() { + return alignMeasurementIntervals; + } + + @Override + public Duration alignMeasurementOffset() { + return alignMeasurementOffset; + } + + @Override + public SessionType sessionType() { + return sessionType; + } + + @Override + public StartTime startTime() { + return startTime; + } + + @Override + public StopTime stopTime() { + return stopTime; + } + + /** + * Abstract Builder class for building. + * {@link org.onosproject.incubator.net.l2monitoring.soam.MeasurementCreateBase}. + */ + protected abstract static class DefaultMeasCreateBaseBuilder implements MeasCreateBaseBuilder { + protected final Version version; + protected final MepId remoteMepId; + protected final Priority priority; + + protected Duration messagePeriod; + protected Short frameSize; + protected DataPattern dataPattern; + protected boolean testTlvIncluded; + protected TestTlvPattern testTlvPattern; + protected Duration measurementInterval; + protected Short numberIntervalsStored; + protected boolean alignMeasurementIntervals; + protected Duration alignMeasurementOffset; + protected SessionType sessionType; + protected StartTime startTime; + protected StopTime stopTime; + + protected DefaultMeasCreateBaseBuilder(Version version, + MepId remoteMepId, Priority priority) + throws SoamConfigException { + super(); + if (remoteMepId == null) { + throw new SoamConfigException("RemoteMepId is null"); + } + this.remoteMepId = remoteMepId; + this.version = version; + this.priority = priority; + } + + @Override + public MeasCreateBaseBuilder messagePeriod(Duration messagePeriod) throws SoamConfigException { + if (messagePeriod.toMillis() < 3 || messagePeriod.toMillis() > 3600000) { + throw new SoamConfigException("Message Period must be between 3-3600000ms. Rejecting: " + + messagePeriod); + } + this.messagePeriod = messagePeriod; + return this; + } + + @Override + public MeasCreateBaseBuilder frameSize(Short frameSize) throws SoamConfigException { + if (frameSize < 64 || frameSize > 9600) { + throw new SoamConfigException("Frame Size must be between 64-9600 bytes." + + " Rejecting: " + frameSize); + } + this.frameSize = frameSize; + return this; + } + + @Override + public MeasCreateBaseBuilder dataPattern(DataPattern dataPattern) { + this.dataPattern = dataPattern; + return this; + } + + @Override + public MeasCreateBaseBuilder testTlvIncluded(boolean testTlvIncluded) { + this.testTlvIncluded = testTlvIncluded; + return this; + } + + @Override + public MeasCreateBaseBuilder testTlvPattern(TestTlvPattern testTlvPattern) { + this.testTlvPattern = testTlvPattern; + return this; + } + + @Override + public MeasCreateBaseBuilder measurementInterval(Duration measurementInterval) throws SoamConfigException { + if (measurementInterval.toMinutes() < 1 || measurementInterval.toMinutes() > 525600) { + throw new SoamConfigException( + "Measurement Interval must be between 1..525600 minutes. Rejecting: " + measurementInterval); + } + this.measurementInterval = measurementInterval; + return this; + } + + @Override + public MeasCreateBaseBuilder numberIntervalsStored(Short numberIntervalsStored) + throws SoamConfigException { + if (numberIntervalsStored < 2 || numberIntervalsStored > 1000) { + throw new SoamConfigException( + "Number Intervals Stored must be between 2-1000. " + + "Rejecting: " + numberIntervalsStored); + } + this.numberIntervalsStored = numberIntervalsStored; + return this; + } + + @Override + public MeasCreateBaseBuilder alignMeasurementIntervals(boolean alignMeasurementIntervals) { + this.alignMeasurementIntervals = alignMeasurementIntervals; + return this; + } + + @Override + public MeasCreateBaseBuilder alignMeasurementOffset( + Duration alignMeasurementOffset) throws SoamConfigException { + if (alignMeasurementOffset.toMinutes() < 0 || alignMeasurementOffset.toMinutes() > 525600) { + throw new SoamConfigException( + "Align Measurement Offset must be between 0..525600 minutes. Rejecting: " + + alignMeasurementOffset); + } + this.alignMeasurementOffset = alignMeasurementOffset; + return this; + } + + @Override + public MeasCreateBaseBuilder sessionType(SessionType sessionType) { + this.sessionType = sessionType; + return this; + } + + @Override + public MeasCreateBaseBuilder startTime(StartTime startTime) throws SoamConfigException { + if (startTime.option() == StartTimeOption.ABSOLUTE && + startTime.absoluteTime().isBefore(Instant.now())) { + throw new SoamConfigException( + "Start Time must be not be in the past. Rejecting: " + startTime); + } + this.startTime = startTime; + return this; + } + + @Override + public MeasCreateBaseBuilder stopTime(StopTime stopTime) throws SoamConfigException { + if (stopTime.option() == StopTimeOption.ABSOLUTE && + stopTime.absoluteTime().isBefore(Instant.now())) { + throw new SoamConfigException( + "Stop Time must be not be in the past. Rejecting: " + stopTime); + } + this.stopTime = stopTime; + return this; + } + + + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/MeasurementCreateBase.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/MeasurementCreateBase.java new file mode 100644 index 0000000000..89428b0b16 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/MeasurementCreateBase.java @@ -0,0 +1,208 @@ +/* + * 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.incubator.net.l2monitoring.soam; + +import java.time.Duration; + +import org.onosproject.incubator.net.l2monitoring.cfm.Mep.Priority; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.DataPattern; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.TestTlvPattern; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.Version; + +/** + * A base interface with attributes that are common to both Delay and Loss Measurements. + */ +public interface MeasurementCreateBase { + /** + * The version of the PDUs used to perform Loss or Delay Measurement. + * The exact PDUs to use are specified by this object in combination with measurement-type + * @return The version of the PDUs + */ + Version version(); + + /** + * The remote MEP to perform the tests against. + * @return An ID of a MEP + */ + MepId remoteMepId(); + + /** + * The interval between Loss or Delay Measurement OAM message transmission. + * For Loss Measurement monitoring applications the default value is 1 sec. + * This object is not applicable if measurement-type is set to 'ccm' and is ignored for that Loss Measurement Type + * @return A java Duration + */ + Duration messagePeriod(); + + /** + * The priority of frames with Performance Monitoring OAM message information. + * @return A priority enumerated value 0-7 + */ + Priority priority(); + + /** + * The Loss Measurement frame size between 64 bytes and the maximum transmission unit of the EVC. + * The range of frame sizes from 64 through 2000 octets need to be supported, + * and the range of frame sizes from 2001 through 9600 octets is suggested be supported. + * The adjustment to the frame size of the standard frame size is accomplished + * by the addition of a Data or Test TLV. A Data or Test TLV is only added to + * the frame if the frame size is greater than 64 bytes + * @return frame size in bytes + */ + Short frameSize(); + + /** + * The LM data pattern included in a Data TLV. + * when the size of the LM frame is determined by the frame-size object and test-tlv-included is 'false'. + * If the frame size object does not define the LM frame size or + * test-tlv-included is 'true' the value of this object is ignored + * @return The data pattern - ones or zeroes + */ + DataPattern dataPattern(); + + /** + * Whether a Test TLV or Data TLV is included when the size of the LM frame is determined by the frame-size object. + * If the frame-size object does not define the LM frame size the value of + * this object is ignored. + * @return true indicates that the Test TLV is to be included, false indicates it is not + */ + boolean testTlvIncluded(); + + /** + * The type of test pattern to be sent in the LM frame Test TLV. + * when the size of LM PDU is determined by the frame-size object and + * test-tlv-included is 'true'. + * If the frame size object does not define the LM frame size or + * test-tlv-included is 'false' the value of this object is ignored + * @return A TLV pattern enum + */ + TestTlvPattern testTlvPattern(); + + /** + * The Measurement Interval for FLR statistics. + * A Measurement Interval of 15 minutes needs to be supported, other + * intervals may be supported. + * @return A java Duration + */ + Duration measurementInterval(); + + /** + * The number of completed measurement intervals to store in the history statistic table. + * At least 32 completed measurement intervals are to be stored. + * 96 measurement intervals are recommended to be stored + * @return The number to be stored. + */ + Short numberIntervalsStored(); + + /** + * Whether the measurement intervals for the Loss Measurement session are aligned with a zero offset to real time. + * The value 'true' indicates that each Measurement Interval starts at a time + * which is aligned to NE time source hour if the interval is a factor of an + * hour, i.e. 60min/15min = 4. For instance, a measurement time interval of + * 15 minutes would stop/start the measurement interval at 0, 15, 30, and 45 + * minutes of an hour. A measurement interval of 7 minutes would not align to + * the hour since 7 minutes is NOT a factor of an hour, i.e. 60min/7min = 8.6, + * and the behavior is the same as if the object is set to 'false'. + * The value 'false' indicates that each Measurement Interval starts at a time + * which is indicated by repetition-period. + * One side effect of the usage of this parameter is that if the value is true + * and the repetition-period is not a factor of an hour then the start of the + * next Measurement Interval will be delayed until the next factor of an hour. + * @return See above for the meaning of true and false + */ + boolean alignMeasurementIntervals(); + + /** + * The offset in minutes from the time of day value. + * if align-measurement-intervals is 'true' and the repetition time is a factor + * of 60 minutes. If not, the value of this object is ignored. + * If the Measurement Interval is 15 minutes and align-measurement-intervals + * is true and if this object was set to 5 minutes, the Measurement Intervals + * would start at 5, 20, 35, 50 minutes past each hour + * @return A java Duration + */ + Duration alignMeasurementOffset(); + + /** + * Defines the session start time. + * @return An object with the start time type and optionally an instant + */ + StartTime startTime(); + + /** + * Defines the session stop time. + * @return An object with the stop time type and optionally an instant + */ + StopTime stopTime(); + + /** + * Indicates whether the current session is defined to be 'proactive' or 'on-demand. + * @return An enumerated value + */ + SessionType sessionType(); + + /** + * Builder for {@link org.onosproject.incubator.net.l2monitoring.soam.MeasurementCreateBase}. + */ + public interface MeasCreateBaseBuilder { + MeasCreateBaseBuilder messagePeriod( + Duration messagePeriod) throws SoamConfigException; + + MeasCreateBaseBuilder frameSize(Short frameSize) throws SoamConfigException; + + MeasCreateBaseBuilder dataPattern(DataPattern dataPattern); + + MeasCreateBaseBuilder testTlvIncluded(boolean testTlvIncluded); + + MeasCreateBaseBuilder testTlvPattern(TestTlvPattern testTlvPattern); + + MeasCreateBaseBuilder measurementInterval( + Duration measurementInterval) throws SoamConfigException; + + MeasCreateBaseBuilder numberIntervalsStored( + Short numberIntervalsStored) throws SoamConfigException; + + MeasCreateBaseBuilder alignMeasurementIntervals( + boolean alignMeasurementIntervals); + + MeasCreateBaseBuilder alignMeasurementOffset( + Duration alignMeasurementOffset) throws SoamConfigException; + + MeasCreateBaseBuilder startTime(StartTime startTime) throws SoamConfigException; + + MeasCreateBaseBuilder stopTime(StopTime stopTime) throws SoamConfigException; + + MeasCreateBaseBuilder sessionType(SessionType sessionType); + + } + + /** + * Supported session types. + * reference [MEF SOAM IA] R3 + */ + public enum SessionType { + /** + * The current session is 'proactive'. + */ + PROACTIVE, + /** + * The current session is 'on-demand'. + */ + ONDEMAND; + } + +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/MilliPct.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/MilliPct.java new file mode 100644 index 0000000000..0c6dd88201 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/MilliPct.java @@ -0,0 +1,80 @@ +/* + * 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.incubator.net.l2monitoring.soam; + +import java.text.DecimalFormat; +import java.text.NumberFormat; + +/** + * A representation of a ratio in milli-percent. + */ +public final class MilliPct extends Number { + + private static final long serialVersionUID = 1476288484705687568L; + private static NumberFormat pf = DecimalFormat.getPercentInstance(); + + private int value; + + private MilliPct(int value) { + this.value = value; + pf.setMaximumFractionDigits(3); + } + + public static MilliPct ofMilliPct(int value) { + return new MilliPct(value); + } + + public static MilliPct ofPercent(float value) { + return new MilliPct(Float.valueOf(value * 1000f).intValue()); + } + + public static MilliPct ofRatio(float value) { + return new MilliPct(Float.valueOf(value * 100000f).intValue()); + } + + @Override + public int intValue() { + return value; + } + + @Override + public long longValue() { + return value; + } + + @Override + public float floatValue() { + return value; + } + + @Override + public double doubleValue() { + return value; + } + + public float percentValue() { + return value / 1000f; + } + + public float ratioValue() { + return value / 100000f; + } + + @Override + public String toString() { + return pf.format(ratioValue()); + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/SoamConfigException.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/SoamConfigException.java new file mode 100644 index 0000000000..6ca9994d01 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/SoamConfigException.java @@ -0,0 +1,36 @@ +/* + * Copyright 2016-present Open Networking Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.incubator.net.l2monitoring.soam; + +/** + * Exception for configuration related to Service OAM. + */ +public class SoamConfigException extends Throwable { + + private static final long serialVersionUID = 1L; + + public SoamConfigException(String message) { + super(message); + } + + public SoamConfigException(Throwable t) { + super(t); + } + + public SoamConfigException(String message, Throwable t) { + super(message, t); + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/SoamDmProgrammable.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/SoamDmProgrammable.java new file mode 100644 index 0000000000..77582e9e64 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/SoamDmProgrammable.java @@ -0,0 +1,27 @@ +/* + * 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.incubator.net.l2monitoring.soam; + +import org.onosproject.net.driver.HandlerBehaviour; + +/** + * Behaviour that allows Layer 2 SOAM PM in the form of Delay Measurement to be implemented by devices. + * + * Has all of the same methods as {@link org.onosproject.incubator.net.l2monitoring.soam.SoamService}, + * so we don't repeat them here + */ +public interface SoamDmProgrammable extends HandlerBehaviour, SoamService { +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/SoamId.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/SoamId.java new file mode 100644 index 0000000000..a4434d99f8 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/SoamId.java @@ -0,0 +1,55 @@ +/* + * 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.incubator.net.l2monitoring.soam; + +import org.onlab.util.Identifier; + +/** + * Identifier for SOAM objects. + */ +public class SoamId extends Identifier { + protected SoamId(int id) { + super(id); + } + + /** + * Creates a dm ID from a int value. + * + * @param id int value + * @return dm ID + */ + public static SoamId valueOf(int id) { + if (id < 0) { + throw new IllegalArgumentException("SOAM Value must be unsigned." + + "Rejecting: " + id); + } + return new SoamId(id); + } + + /** + * Gets the dm ID value. + * + * @return dm ID value as int + */ + public int value() { + return this.identifier; + } + + @Override + public String toString() { + return String.valueOf(identifier); + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/SoamService.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/SoamService.java new file mode 100644 index 0000000000..fc777cb97a --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/SoamService.java @@ -0,0 +1,334 @@ +/* + * 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.incubator.net.l2monitoring.soam; + +import java.util.Collection; +import java.util.Optional; + +import org.onosproject.incubator.net.l2monitoring.cfm.MepTsCreate; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementEntry; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStatCurrent; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStatHistory; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementCreate; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementEntry; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementStatCurrent; + +/** + * Methods callable on MEPs to implement SOAM functionality. + * Most of the methods have been derived from the MEF 38 and MEF 39 standards + * + */ +public interface SoamService { + /** + * Get all of the Delay Measurements on a particular MEP. + * + * @param mdName The Maintenance Domain of the MEP + * @param maName The Maintenance Association of the MEP + * @param mepId The id of the MEP itself + * @return A collection of Delay Measurements and their children + * @throws CfmConfigException If there's a problem with Cfm attributes + * @throws SoamConfigException If there's a problem with Soam attributes + */ + Collection getAllDms(MdId mdName, MaIdShort maName, MepId mepId) + throws CfmConfigException, SoamConfigException; + + /** + * Get a named Delay Measurements on a particular MEP. + * While devices are not required to have named delay measurement objects + * so do. The getAllDms() method may have produced a list of DM Ids that can + * be used here to retrieve one DM at a time + * + * @param mdName The Maintenance Domain of the MEP + * @param maName The Maintenance Association of the MEP + * @param mepId The id of the MEP itself + * @param dmId The id of the Delay Measurement + * @return A collection of Delay Measurements and their children + * @throws CfmConfigException If there's a problem with Cfm attributes + * @throws SoamConfigException If there's a problem with Soam attributes + */ + DelayMeasurementEntry getDm(MdId mdName, MaIdShort maName, MepId mepId, SoamId dmId) + throws CfmConfigException, SoamConfigException; + + /** + * Get only the current stats of a named Delay Measurements on a particular MEP. + * It may be useful to retrieve the current stats on their own to retrieve + * values between Delay Measurement intervals + * + * @param mdName The Maintenance Domain of the MEP + * @param maName The Maintenance Association of the MEP + * @param mepId The id of the MEP itself + * @param dmId The id of the Delay Measurement + * @throws CfmConfigException If there's a problem with Cfm attributes + * @throws SoamConfigException If there's a problem with Soam attributes + * @return A collection of Delay Measurements and their children + */ + DelayMeasurementStatCurrent getDmCurrentStat( + MdId mdName, MaIdShort maName, MepId mepId, SoamId dmId) + throws CfmConfigException, SoamConfigException; + + /** + * Get only the history stats of a named Delay Measurements on a particular MEP. + * It may be useful to retrieve the history stats on their own to retrieve + * values before they have been overwritten + * + * @param mdName The Maintenance Domain of the MEP + * @param maName The Maintenance Association of the MEP + * @param mepId The id of the MEP itself + * @param dmId The id of the Delay Measurement + * @throws CfmConfigException If there's a problem with Cfm attributes + * @throws SoamConfigException If there's a problem with Soam attributes + * @return A collection of Delay Measurements and their children + */ + Collection getDmHistoricalStats( + MdId mdName, MaIdShort maName, MepId mepId, SoamId dmId) + throws CfmConfigException, SoamConfigException; + + /** + * Create a Delay Measurement on a particular MEP. + * MEF 39 defines a delay measurement as an ephemeral object and does not + * require the supporting device to persist it. It runs as an action until + * stopped with the corresponding abort action below. + * + * @param mdName The Maintenance Domain of the MEP + * @param maName The Maintenance Association of the MEP + * @param mepId The id of the MEP itself + * @param dm The parameters of the Delay Measurement + * @return The id of the newly created DM if available + * @throws CfmConfigException If there's a problem with Cfm attributes + * @throws SoamConfigException If there's a problem with Soam attributes + */ + Optional createDm(MdId mdName, MaIdShort maName, MepId mepId, + DelayMeasurementCreate dm) throws CfmConfigException, SoamConfigException; + + /** + * Stop all Delay Measurements on a particular MEP. + * This stops the Delay Measurement activity started through the + * createDm action above. It is up to the individual device how to implement + * it. It does not necessarily mean delete the DM. + * + * @param mdName The Maintenance Domain of the MEP + * @param maName The Maintenance Association of the MEP + * @param mepId The id of the MEP itself + * @throws CfmConfigException When the command cannot be completed + */ + void abortDm(MdId mdName, MaIdShort maName, MepId mepId) + throws CfmConfigException; + + /** + * Stop a particular named Delay Measurement on a particular MEP. + * This stops the Delay Measurement activity started through the + * createDm action above. It is up to the individual device how to implement + * it. It does not necessarily mean delete the DM. + * + * @param mdName The Maintenance Domain of the MEP + * @param maName The Maintenance Association of the MEP + * @param mepId The id of the MEP itself + * @param dmId The id of the DM + * @throws CfmConfigException When the command cannot be completed + */ + void abortDm(MdId mdName, MaIdShort maName, MepId mepId, SoamId dmId) + throws CfmConfigException; + + /** + * Clear the history stats on all Delay Measurements on a particular MEP. + * This removes any historical stats stored on a device for one MEP + * It does NOT require that the Delay Measurement test is aborted. + * + * @param mdName The Maintenance Domain of the MEP + * @param maName The Maintenance Association of the MEP + * @param mepId The id of the MEP itself + * @throws CfmConfigException When the command cannot be completed + */ + void clearDelayHistoryStats(MdId mdName, MaIdShort maName, MepId mepId) + throws CfmConfigException; + + /** + * Clear the history stats on a named Delay Measurement on a particular MEP. + * This removes any historical stats stored on a device for one DM on one MEP + * It does NOT require that the Delay Measurement test is aborted. + * + * @param mdName The Maintenance Domain of the MEP + * @param maName The Maintenance Association of the MEP + * @param mepId The id of the MEP itself + * @param dmId The id of the DM + * @throws CfmConfigException When the command cannot be completed + */ + void clearDelayHistoryStats(MdId mdName, MaIdShort maName, MepId mepId, + SoamId dmId) throws CfmConfigException; + + /** + * Get all of the Loss Measurements on a particular MEP. + * + * @param mdName The Maintenance Domain of the MEP + * @param maName The Maintenance Association of the MEP + * @param mepId The id of the MEP itself + * @return A collection of Loss Measurements and their children + * @throws CfmConfigException When the command cannot be completed + * @throws SoamConfigException When the command cannot be completed + */ + Collection getAllLms(MdId mdName, MaIdShort maName, MepId mepId) + throws CfmConfigException, SoamConfigException; + + /** + * Get a named Loss Measurements on a particular MEP. + * While devices are not required to have named Loss measurement objects + * some do. The getAllLms() method may have produced a list of LM Ids that + * can be used here to retrieve one LM at a time + * + * @param mdName The Maintenance Domain of the MEP + * @param maName The Maintenance Association of the MEP + * @param mepId The id of the MEP itself + * @param lmId The id of the Loss Measurement + * @return A collection of Loss Measurements and their children + * @throws CfmConfigException When the command cannot be completed + * @throws SoamConfigException When the command cannot be completed + */ + LossMeasurementEntry getLm(MdId mdName, MaIdShort maName, MepId mepId, + SoamId lmId) throws CfmConfigException, SoamConfigException; + + /** + * Get only the current stats of a named Loss Measurements on a particular MEP. + * It may be useful to retrieve the current stats on their own to retrieve + * values between Loss Measurement intervals + * + * @param mdName The Maintenance Domain of the MEP + * @param maName The Maintenance Association of the MEP + * @param mepId The id of the MEP itself + * @param lmId The id of the Loss Measurement + * @return A collection of Loss Measurements and their children + */ + LossMeasurementStatCurrent getLmCurrentStat( + MdId mdName, MaIdShort maName, MepId mepId, SoamId lmId); + + /** + * Get only the history stats of a named Loss Measurements on a particular MEP. + * It may be useful to retrieve the history stats on their own to retrieve + * values before they have been overwritten + * + * @param mdName The Maintenance Domain of the MEP + * @param maName The Maintenance Association of the MEP + * @param mepId The id of the MEP itself + * @param lmId The id of the Loss Measurement + * @return A collection of Loss Measurements and their children + */ + Collection getLmHistoricalStats( + MdId mdName, MaIdShort maName, MepId mepId, SoamId lmId); + + /** + * Create a Loss Measurement on a particular MEP. + * MEF 39 defines a Loss measurement as an ephemeral object and does not + * require the supporting device to persist it. It runs as an action until + * stopped with the corresponding abort action below. + * + * @param mdName The Maintenance Domain of the MEP + * @param maName The Maintenance Association of the MEP + * @param mepId The id of the MEP itself + * @param lm The parameters of the Loss Measurement + * @return The id of the newly created LM if available + * @throws CfmConfigException When the command cannot be completed + * @throws SoamConfigException When the command cannot be completed + */ + Optional createLm(MdId mdName, MaIdShort maName, MepId mepId, + LossMeasurementCreate lm) throws CfmConfigException, SoamConfigException; + + /** + * Stop all Loss Measurements on a particular MEP. + * This stops the Loss Measurement activity started through the + * createLm action above. It is up to the individual device how to implement + * it. It does not necessarily mean delete the LM. + * + * @param mdName The Maintenance Domain of the MEP + * @param maName The Maintenance Association of the MEP + * @param mepId The id of the MEP itself + * @throws CfmConfigException When the command cannot be completed + */ + void abortLm(MdId mdName, MaIdShort maName, MepId mepId) + throws CfmConfigException; + + /** + * Stop a particular named Loss Measurement on a particular MEP. + * This stops the Loss Measurement activity started through the + * createLm action above. It is up to the individual device how to implement + * it. It does not necessarily mean delete the LM. + * + * @param mdName The Maintenance Domain of the MEP + * @param maName The Maintenance Association of the MEP + * @param mepId The id of the MEP itself + * @param lmId The id of the LM + * @throws CfmConfigException When the command cannot be completed + */ + void abortLm(MdId mdName, MaIdShort maName, MepId mepId, SoamId lmId) + throws CfmConfigException; + + /** + * Clear the history stats on all Loss Measurements on a particular MEP. + * This removes any historical stats stored on a device for one MEP + * It does NOT require that the Loss Measurement test is aborted. + * + * @param mdName The Maintenance Domain of the MEP + * @param maName The Maintenance Association of the MEP + * @param mepId The id of the MEP itself + * @throws CfmConfigException When the command cannot be completed + */ + void clearLossHistoryStats(MdId mdName, MaIdShort maName, MepId mepId) + throws CfmConfigException; + + /** + * Clear the history stats on a named Loss Measurement on a particular MEP. + * This removes any historical stats stored on a device for one LM on one MEP + * It does NOT require that the Loss Measurement test is aborted. + * + * @param mdName The Maintenance Domain of the MEP + * @param maName The Maintenance Association of the MEP + * @param mepId The id of the MEP itself + * @param lmId The id of the LM + * @throws CfmConfigException When the command cannot be completed + */ + void clearLossHistoryStats(MdId mdName, MaIdShort maName, MepId mepId, + SoamId lmId) throws CfmConfigException; + + /** + * Create a Test Signal operation on a particular MEP. + * MEF39 defines the Test Signal as an ephemeral operation that is not + * required to be persisted by a device. Only one Test Signal is active + * on a MEP at a time + * + * @param mdName The Maintenance Domain of the MEP + * @param maName The Maintenance Association of the MEP + * @param mepId The id of the MEP itself + * @param tsCreate The parameters the Test Signal is created with + * @throws CfmConfigException When the command cannot be completed + */ + void createTestSignal(MdId mdName, MaIdShort maName, MepId mepId, + MepTsCreate tsCreate) throws CfmConfigException; + + /** + * Abort a Test Signal operation on a particular MEP. + * Abort a Test Signal operation on a Mep + * + * @param mdName The Maintenance Domain of the MEP + * @param maName The Maintenance Association of the MEP + * @param mepId The id of the MEP itself + * @throws CfmConfigException When the command cannot be completed + */ + void abortTestSignal(MdId mdName, MaIdShort maName, MepId mepId) + throws CfmConfigException; +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/SoamTime.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/SoamTime.java new file mode 100644 index 0000000000..d8e5924d9c --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/SoamTime.java @@ -0,0 +1,52 @@ +/* + * Copyright 2017-present Open Networking Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.incubator.net.l2monitoring.soam; + +import java.time.Duration; +import java.time.Instant; + +/** + * A base class with common attributes of StartTime and StopTime. + */ +public abstract class SoamTime { + protected final TimeOption option; + protected final Duration relativeTime; + protected final Instant absoluteTime; + + public TimeOption option() { + return option; + } + + public Duration relativeTime() { + return relativeTime; + } + + public Instant absoluteTime() { + return absoluteTime; + } + + protected SoamTime(TimeOption option, Duration relativeStart, Instant absoluteStart) { + this.option = option; + this.relativeTime = relativeStart; + this.absoluteTime = absoluteStart; + } + + /** + * Abstract interface for TimeOptions on SoamTime concrete classes. + */ + public interface TimeOption { + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/StartTime.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/StartTime.java new file mode 100644 index 0000000000..02fa765a29 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/StartTime.java @@ -0,0 +1,64 @@ +/* + * Copyright 2017-present Open Networking Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.incubator.net.l2monitoring.soam; + +import java.time.Duration; +import java.time.Instant; + +import com.google.common.base.MoreObjects; + +/** + * A utility class for specifying a Start Time for Delay and Loss Measurements. + */ +public final class StartTime extends SoamTime { + + protected StartTime(TimeOption option, Duration relativeStart, Instant absoluteStart) { + super(option, relativeStart, absoluteStart); + } + + public static final StartTime immediate() { + return new StartTime(StartTimeOption.IMMEDIATE, null, null); + } + + public static final StartTime relative(Duration relativeStart) { + return new StartTime(StartTimeOption.RELATIVE, relativeStart, null); + } + + public static final StartTime absolute(Instant absoluteStart) { + return new StartTime(StartTimeOption.ABSOLUTE, null, absoluteStart); + } + + @Override + public String toString() { + if (option == StartTimeOption.IMMEDIATE) { + return "immediate"; + } else if (option == StartTimeOption.ABSOLUTE) { + return MoreObjects.toStringHelper(getClass()).add("absolute", absoluteTime).toString(); + } else if (option == StartTimeOption.RELATIVE) { + return MoreObjects.toStringHelper(getClass()).add("relative", relativeTime).toString(); + } + return "unknown"; + } + + /** + * Options for Start Time. + */ + public enum StartTimeOption implements TimeOption { + IMMEDIATE, + RELATIVE, + ABSOLUTE; + } +} \ No newline at end of file diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/StopTime.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/StopTime.java new file mode 100644 index 0000000000..b58103648e --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/StopTime.java @@ -0,0 +1,64 @@ +/* + * Copyright 2017-present Open Networking Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.incubator.net.l2monitoring.soam; + +import java.time.Duration; +import java.time.Instant; + +import com.google.common.base.MoreObjects; + +/** + * A utility class for specifying a Stop Time for Delay and Loss Measurements. + */ +public final class StopTime extends SoamTime { + + private StopTime(TimeOption option, Duration relativeStart, Instant absoluteStart) { + super(option, relativeStart, absoluteStart); + } + + public static final StopTime none() { + return new StopTime(StopTimeOption.NONE, null, null); + } + + public static final StopTime relative(Duration relativeStop) { + return new StopTime(StopTimeOption.RELATIVE, relativeStop, null); + } + + public static final StopTime absolute(Instant absoluteStop) { + return new StopTime(StopTimeOption.ABSOLUTE, null, absoluteStop); + } + + @Override + public String toString() { + if (option == StopTimeOption.NONE) { + return "none"; + } else if (option == StopTimeOption.ABSOLUTE) { + return MoreObjects.toStringHelper(getClass()).add("absolute", absoluteTime).toString(); + } else if (option == StopTimeOption.RELATIVE) { + return MoreObjects.toStringHelper(getClass()).add("relative", relativeTime).toString(); + } + return "unknown"; + } + + /** + * Options for Stop Time. + */ + public enum StopTimeOption implements TimeOption { + NONE, + RELATIVE, + ABSOLUTE; + } +} \ No newline at end of file diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DefaultDelayMeasurementCreate.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DefaultDelayMeasurementCreate.java new file mode 100644 index 0000000000..f74ff040d8 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DefaultDelayMeasurementCreate.java @@ -0,0 +1,182 @@ +/* + * 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.incubator.net.l2monitoring.soam.delay; + +import java.util.ArrayList; +import java.util.Collection; + +import org.onosproject.incubator.net.l2monitoring.cfm.Mep.Priority; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.soam.DefaultMeasurementCreateBase; +import org.onosproject.incubator.net.l2monitoring.soam.SoamConfigException; + +/** + * The default implementation of {@link org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate}. + */ +public class DefaultDelayMeasurementCreate extends DefaultMeasurementCreateBase + implements DelayMeasurementCreate { + + protected final DmType dmCfgType; + protected final Collection measurementsEnabled; + protected final Short binsPerFdInterval; + protected final Short binsPerIfdvInterval; + protected final Short ifdvSelectionOffset; + protected final Short binsPerFdrInterval; + protected final Collection thresholds; + + protected DefaultDelayMeasurementCreate(DefaultDmCreateBuilder builder) { + super(builder); + this.dmCfgType = builder.dmCfgType; + this.measurementsEnabled = builder.measurementsEnabled; + this.binsPerFdInterval = builder.binsPerFdInterval; + this.binsPerIfdvInterval = builder.binsPerIfdvInterval; + this.ifdvSelectionOffset = builder.ifdvSelectionOffset; + this.binsPerFdrInterval = builder.binsPerFdrInterval; + this.thresholds = builder.thresholds; + } + + @Override + public DmType dmCfgType() { + return dmCfgType; + } + + @Override + public Collection measurementsEnabled() { + return measurementsEnabled; + } + + @Override + public Short binsPerFdInterval() { + return binsPerFdInterval; + } + + @Override + public Short binsPerIfdvInterval() { + return binsPerIfdvInterval; + } + + @Override + public Short ifdvSelectionOffset() { + return ifdvSelectionOffset; + } + + @Override + public Short binsPerFdrInterval() { + return binsPerFdrInterval; + } + + @Override + public Collection thresholds() { + return thresholds; + } + + public static DmCreateBuilder builder(DmType dmCfgType, + Version version, MepId remoteMepId, Priority priority) + throws SoamConfigException { + return new DefaultDmCreateBuilder(dmCfgType, version, remoteMepId, priority); + } + + /** + * Builder for {@link org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate}. + */ + protected static class DefaultDmCreateBuilder extends DefaultMeasCreateBaseBuilder + implements DmCreateBuilder { + protected final DmType dmCfgType; + + protected Collection measurementsEnabled; + protected Short binsPerFdInterval; + protected Short binsPerIfdvInterval; + protected Short ifdvSelectionOffset; + protected Short binsPerFdrInterval; + protected Collection thresholds; + + protected DefaultDmCreateBuilder(DmType dmCfgType, Version version, + MepId remoteMepId, Priority priority) + throws SoamConfigException { + super(version, remoteMepId, priority); + this.dmCfgType = dmCfgType; + measurementsEnabled = new ArrayList<>(); + thresholds = new ArrayList<>(); + } + + @Override + public DmCreateBuilder addToMeasurementsEnabled( + MeasurementOption measurementEnabled) { + this.measurementsEnabled.add(measurementEnabled); + return this; + } + + @Override + public DmCreateBuilder binsPerFdInterval(Short binsPerFdInterval) + throws SoamConfigException { + if (binsPerFdInterval < 2 || binsPerFdInterval > 100) { + throw new SoamConfigException( + "Bins Per Fd Interval must be between 2..100. Rejecting: " + + binsPerFdInterval); + } + this.binsPerFdInterval = binsPerFdInterval; + return this; + } + + @Override + public DmCreateBuilder binsPerIfdvInterval(Short binsPerIfdvInterval) + throws SoamConfigException { + if (binsPerIfdvInterval < 2 || binsPerIfdvInterval > 100) { + throw new SoamConfigException( + "Bins Per Ifdv Interval must be between 2..100. Rejecting: " + + binsPerIfdvInterval); + } + this.binsPerIfdvInterval = binsPerIfdvInterval; + return this; + } + + @Override + public DmCreateBuilder ifdvSelectionOffset(Short ifdvSelectionOffset) + throws SoamConfigException { + if (ifdvSelectionOffset < 2 || ifdvSelectionOffset > 100) { + throw new SoamConfigException( + "IFDV Selection Offset must be between 2..100. Rejecting: " + + ifdvSelectionOffset); + } + this.ifdvSelectionOffset = ifdvSelectionOffset; + return this; + } + + @Override + public DmCreateBuilder binsPerFdrInterval(Short binsPerFdrInterval) + throws SoamConfigException { + if (binsPerFdrInterval < 2 || binsPerFdrInterval > 100) { + throw new SoamConfigException( + "Bins Per Fd Interval must be between 2..100. Rejecting: " + + binsPerFdrInterval); + } + this.binsPerFdrInterval = binsPerFdrInterval; + return this; + } + + @Override + public DmCreateBuilder addToThresholds( + DelayMeasurementThreshold threshold) { + this.thresholds.add(threshold); + return this; + } + + @Override + public DelayMeasurementCreate build() { + return new DefaultDelayMeasurementCreate(this); + } + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DefaultDelayMeasurementEntry.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DefaultDelayMeasurementEntry.java new file mode 100644 index 0000000000..c53c63bc74 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DefaultDelayMeasurementEntry.java @@ -0,0 +1,211 @@ +/* + * 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.incubator.net.l2monitoring.soam.delay; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.Collection; + +import org.onosproject.incubator.net.l2monitoring.cfm.Mep.Priority; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.soam.SoamConfigException; +import org.onosproject.incubator.net.l2monitoring.soam.SoamId; + +import com.google.common.collect.Lists; + +/** + * The default implementation of {@link org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementEntry}. + */ +public final class DefaultDelayMeasurementEntry + extends DefaultDelayMeasurementCreate implements DelayMeasurementEntry { + + private final SoamId dmId; + private final SessionStatus sessionStatus; + private final Duration frameDelayTwoWay; + private final Duration frameDelayForward; + private final Duration frameDelayBackward; + private final Duration interFrameDelayVariationTwoWay; + private final Duration interFrameDelayVariationForward; + private final Duration interFrameDelayVariationBackward; + private final DelayMeasurementStatCurrent currentResult; + private final Collection historicalResults; + + private DefaultDelayMeasurementEntry(DefaultDmEntryBuilder builder) { + super(builder); + this.dmId = builder.dmId; + this.currentResult = builder.currentResult; + this.historicalResults = builder.historicalResults; + + this.sessionStatus = builder.sessionStatus; + this.frameDelayTwoWay = builder.frameDelayTwoWay; + this.frameDelayForward = builder.frameDelayForward; + this.frameDelayBackward = builder.frameDelayBackward; + this.interFrameDelayVariationTwoWay = builder.interFrameDelayVariationTwoWay; + this.interFrameDelayVariationForward = builder.interFrameDelayVariationForward; + this.interFrameDelayVariationBackward = builder.interFrameDelayVariationBackward; + } + + @Override + public SoamId dmId() { + return dmId; + } + + @Override + public SessionStatus sessionStatus() { + return sessionStatus; + } + + @Override + public Duration frameDelayTwoWay() { + return frameDelayTwoWay; + } + + @Override + public Duration frameDelayForward() { + return frameDelayForward; + } + + @Override + public Duration frameDelayBackward() { + return frameDelayBackward; + } + + @Override + public Duration interFrameDelayVariationTwoWay() { + return interFrameDelayVariationTwoWay; + } + + @Override + public Duration interFrameDelayVariationForward() { + return interFrameDelayVariationForward; + } + + @Override + public Duration interFrameDelayVariationBackward() { + return interFrameDelayVariationBackward; + } + + @Override + public DelayMeasurementStatCurrent currentResult() { + return currentResult; + } + + @Override + public Collection historicalResults() { + if (historicalResults != null) { + return Lists.newArrayList(historicalResults); + } + return null; + } + + public static DmEntryBuilder builder(SoamId dmId, DmType dmCfgType, + Version version, MepId remoteMepId, Priority priority) + throws SoamConfigException { + return new DefaultDmEntryBuilder(dmId, dmCfgType, version, + remoteMepId, priority); + } + + /** + * Builder for {@link org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementEntry}. + */ + private static final class DefaultDmEntryBuilder extends DefaultDmCreateBuilder + implements DmEntryBuilder { + private final SoamId dmId; + private SessionStatus sessionStatus; + private Duration frameDelayTwoWay; + private Duration frameDelayForward; + private Duration frameDelayBackward; + private Duration interFrameDelayVariationTwoWay; + private Duration interFrameDelayVariationForward; + private Duration interFrameDelayVariationBackward; + private DelayMeasurementStatCurrent currentResult; + private Collection historicalResults; + + private DefaultDmEntryBuilder(SoamId dmId, DmType dmCfgType, + Version version, MepId remoteMepId, Priority priority) + throws SoamConfigException { + super(dmCfgType, version, remoteMepId, priority); + if (dmId == null) { + throw new SoamConfigException("DmId is null"); + } + this.dmId = dmId; + historicalResults = new ArrayList<>(); + } + + @Override + public DmEntryBuilder sessionStatus(SessionStatus sessionStatus) { + this.sessionStatus = sessionStatus; + return this; + } + + @Override + public DmEntryBuilder frameDelayTwoWay(Duration frameDelayTwoWay) { + this.frameDelayTwoWay = frameDelayTwoWay; + return this; + } + + @Override + public DmEntryBuilder frameDelayForward(Duration frameDelayForward) { + this.frameDelayForward = frameDelayForward; + return this; + } + + @Override + public DmEntryBuilder frameDelayBackward(Duration frameDelayBackward) { + this.frameDelayBackward = frameDelayBackward; + return this; + } + + @Override + public DmEntryBuilder interFrameDelayVariationTwoWay( + Duration interFrameDelayVariationTwoWay) { + this.interFrameDelayVariationTwoWay = interFrameDelayVariationTwoWay; + return this; + } + + @Override + public DmEntryBuilder interFrameDelayVariationForward( + Duration interFrameDelayVariationForward) { + this.interFrameDelayVariationForward = interFrameDelayVariationForward; + return this; + } + + @Override + public DmEntryBuilder interFrameDelayVariationBackward( + Duration interFrameDelayVariationBackward) { + this.interFrameDelayVariationBackward = interFrameDelayVariationBackward; + return this; + } + + @Override + public DmEntryBuilder currentResult(DelayMeasurementStatCurrent currentResult) { + this.currentResult = currentResult; + return this; + } + + @Override + public DmEntryBuilder addToHistoricalResults( + DelayMeasurementStatHistory historicalResult) { + this.historicalResults.add(historicalResult); + return this; + } + + @Override + public DelayMeasurementEntry build() { + return new DefaultDelayMeasurementEntry(this); + } + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DefaultDelayMeasurementStat.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DefaultDelayMeasurementStat.java new file mode 100644 index 0000000000..01f0bc4695 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DefaultDelayMeasurementStat.java @@ -0,0 +1,589 @@ +/* + * 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.incubator.net.l2monitoring.soam.delay; + +import java.time.Duration; +import java.util.Map; + +import com.google.common.collect.Maps; + +/** + * Abstract default implementation of DelayMeasurementStat. + * {@link org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStat}. + */ +public abstract class DefaultDelayMeasurementStat implements DelayMeasurementStat { + + private final Duration elapsedTime; + private final boolean suspectStatus; + private final Duration frameDelayTwoWayMin; + private final Duration frameDelayTwoWayMax; + private final Duration frameDelayTwoWayAvg; + private final Duration frameDelayForwardMin; + private final Duration frameDelayForwardMax; + private final Duration frameDelayForwardAvg; + private final Duration frameDelayBackwardMin; + private final Duration frameDelayBackwardMax; + private final Duration frameDelayBackwardAvg; + private final Duration interFrameDelayVariationTwoWayMin; + private final Duration interFrameDelayVariationTwoWayMax; + private final Duration interFrameDelayVariationTwoWayAvg; + private final Duration interFrameDelayVariationForwardMin; + private final Duration interFrameDelayVariationForwardMax; + private final Duration interFrameDelayVariationForwardAvg; + private final Duration interFrameDelayVariationBackwardMin; + private final Duration interFrameDelayVariationBackwardMax; + private final Duration interFrameDelayVariationBackwardAvg; + private final Duration frameDelayRangeTwoWayMax; + private final Duration frameDelayRangeTwoWayAvg; + private final Duration frameDelayRangeForwardMax; + private final Duration frameDelayRangeForwardAvg; + private final Duration frameDelayRangeBackwardMax; + private final Duration frameDelayRangeBackwardAvg; + private final Integer soamPdusSent; + private final Integer soamPdusReceived; + private final Map frameDelayTwoWayBins; + private final Map frameDelayForwardBins; + private final Map frameDelayBackwardBins; + private final Map interFrameDelayVariationTwoWayBins; + private final Map interFrameDelayVariationForwardBins; + private final Map interFrameDelayVariationBackwardBins; + private final Map frameDelayRangeTwoWayBins; + private final Map frameDelayRangeForwardBins; + private final Map frameDelayRangeBackwardBins; + + protected DefaultDelayMeasurementStat(DefaultDmStatBuilder builder) { + this.elapsedTime = builder.elapsedTime; + this.suspectStatus = builder.suspectStatus; + this.frameDelayTwoWayMin = builder.frameDelayTwoWayMin; + this.frameDelayTwoWayMax = builder.frameDelayTwoWayMax; + this.frameDelayTwoWayAvg = builder.frameDelayTwoWayAvg; + this.frameDelayForwardMin = builder.frameDelayForwardMin; + this.frameDelayForwardMax = builder.frameDelayForwardMax; + this.frameDelayForwardAvg = builder.frameDelayForwardAvg; + this.frameDelayBackwardMin = builder.frameDelayBackwardMin; + this.frameDelayBackwardMax = builder.frameDelayBackwardMax; + this.frameDelayBackwardAvg = builder.frameDelayBackwardAvg; + this.interFrameDelayVariationTwoWayMin = builder.interFrameDelayVariationTwoWayMin; + this.interFrameDelayVariationTwoWayMax = builder.interFrameDelayVariationTwoWayMax; + this.interFrameDelayVariationTwoWayAvg = builder.interFrameDelayVariationTwoWayAvg; + this.interFrameDelayVariationForwardMin = builder.interFrameDelayVariationForwardMin; + this.interFrameDelayVariationForwardMax = builder.interFrameDelayVariationForwardMax; + this.interFrameDelayVariationForwardAvg = builder.interFrameDelayVariationForwardAvg; + this.interFrameDelayVariationBackwardMin = builder.interFrameDelayVariationBackwardMin; + this.interFrameDelayVariationBackwardMax = builder.interFrameDelayVariationBackwardMax; + this.interFrameDelayVariationBackwardAvg = builder.interFrameDelayVariationBackwardAvg; + this.frameDelayRangeTwoWayMax = builder.frameDelayRangeTwoWayMax; + this.frameDelayRangeTwoWayAvg = builder.frameDelayRangeTwoWayAvg; + this.frameDelayRangeForwardMax = builder.frameDelayRangeForwardMax; + this.frameDelayRangeForwardAvg = builder.frameDelayRangeForwardAvg; + this.frameDelayRangeBackwardMax = builder.frameDelayRangeBackwardMax; + this.frameDelayRangeBackwardAvg = builder.frameDelayRangeBackwardAvg; + this.soamPdusSent = builder.soamPdusSent; + this.soamPdusReceived = builder.soamPdusReceived; + this.frameDelayTwoWayBins = builder.frameDelayTwoWayBins; + this.frameDelayForwardBins = builder.frameDelayForwardBins; + this.frameDelayBackwardBins = builder.frameDelayBackwardBins; + this.interFrameDelayVariationTwoWayBins = builder.interFrameDelayVariationTwoWayBins; + this.interFrameDelayVariationForwardBins = builder.interFrameDelayVariationForwardBins; + this.interFrameDelayVariationBackwardBins = builder.interFrameDelayVariationBackwardBins; + this.frameDelayRangeTwoWayBins = builder.frameDelayRangeTwoWayBins; + this.frameDelayRangeForwardBins = builder.frameDelayRangeForwardBins; + this.frameDelayRangeBackwardBins = builder.frameDelayRangeBackwardBins; + } + + @Override + public Duration elapsedTime() { + return elapsedTime; + } + + @Override + public boolean suspectStatus() { + return suspectStatus; + } + + @Override + public Duration frameDelayTwoWayMin() { + return frameDelayTwoWayMin; + } + + @Override + public Duration frameDelayTwoWayMax() { + return frameDelayTwoWayMax; + } + + @Override + public Duration frameDelayTwoWayAvg() { + return frameDelayTwoWayAvg; + } + + @Override + public Duration frameDelayForwardMin() { + return frameDelayForwardMin; + } + + @Override + public Duration frameDelayForwardMax() { + return frameDelayForwardMax; + } + + @Override + public Duration frameDelayForwardAvg() { + return frameDelayForwardAvg; + } + + @Override + public Duration frameDelayBackwardMin() { + return frameDelayBackwardMin; + } + + @Override + public Duration frameDelayBackwardMax() { + return frameDelayBackwardMax; + } + + @Override + public Duration frameDelayBackwardAvg() { + return frameDelayBackwardAvg; + } + + @Override + public Duration interFrameDelayVariationTwoWayMin() { + return interFrameDelayVariationTwoWayMin; + } + + @Override + public Duration interFrameDelayVariationTwoWayMax() { + return interFrameDelayVariationTwoWayMax; + } + + @Override + public Duration interFrameDelayVariationTwoWayAvg() { + return interFrameDelayVariationTwoWayAvg; + } + + @Override + public Duration interFrameDelayVariationForwardMin() { + return interFrameDelayVariationForwardMin; + } + + @Override + public Duration interFrameDelayVariationForwardMax() { + return interFrameDelayVariationForwardMax; + } + + @Override + public Duration interFrameDelayVariationForwardAvg() { + return interFrameDelayVariationForwardAvg; + } + + @Override + public Duration interFrameDelayVariationBackwardMin() { + return interFrameDelayVariationBackwardMin; + } + + @Override + public Duration interFrameDelayVariationBackwardMax() { + return interFrameDelayVariationBackwardMax; + } + + @Override + public Duration interFrameDelayVariationBackwardAvg() { + return interFrameDelayVariationBackwardAvg; + } + + @Override + public Duration frameDelayRangeTwoWayMax() { + return frameDelayRangeTwoWayMax; + } + + @Override + public Duration frameDelayRangeTwoWayAvg() { + return frameDelayRangeTwoWayAvg; + } + + @Override + public Duration frameDelayRangeForwardMax() { + return frameDelayRangeForwardMax; + } + + @Override + public Duration frameDelayRangeForwardAvg() { + return frameDelayRangeForwardAvg; + } + + @Override + public Duration frameDelayRangeBackwardMax() { + return frameDelayRangeBackwardMax; + } + + @Override + public Duration frameDelayRangeBackwardAvg() { + return frameDelayRangeBackwardAvg; + } + + @Override + public Integer soamPdusSent() { + return soamPdusSent; + } + + @Override + public Integer soamPdusReceived() { + return soamPdusReceived; + } + + @Override + public Map frameDelayTwoWayBins() { + if (frameDelayTwoWayBins != null) { + return Maps.newHashMap(frameDelayTwoWayBins); + } else { + return null; + } + } + + @Override + public Map frameDelayForwardBins() { + if (frameDelayForwardBins != null) { + return Maps.newHashMap(frameDelayForwardBins); + } else { + return null; + } + } + + @Override + public Map frameDelayBackwardBins() { + if (frameDelayBackwardBins != null) { + return Maps.newHashMap(frameDelayBackwardBins); + } else { + return null; + } + } + + @Override + public Map interFrameDelayVariationTwoWayBins() { + if (interFrameDelayVariationTwoWayBins != null) { + return Maps.newHashMap(interFrameDelayVariationTwoWayBins); + } else { + return null; + } + } + + @Override + public Map interFrameDelayVariationForwardBins() { + if (interFrameDelayVariationForwardBins != null) { + return Maps.newHashMap(interFrameDelayVariationForwardBins); + } else { + return null; + } + } + + @Override + public Map interFrameDelayVariationBackwardBins() { + if (interFrameDelayVariationBackwardBins != null) { + return Maps.newHashMap(interFrameDelayVariationBackwardBins); + } else { + return null; + } + } + + @Override + public Map frameDelayRangeTwoWayBins() { + if (frameDelayRangeTwoWayBins != null) { + return Maps.newHashMap(frameDelayRangeTwoWayBins); + } else { + return null; + } + } + + @Override + public Map frameDelayRangeForwardBins() { + if (frameDelayRangeForwardBins != null) { + return Maps.newHashMap(frameDelayRangeForwardBins); + } else { + return null; + } + } + + @Override + public Map frameDelayRangeBackwardBins() { + if (frameDelayRangeBackwardBins != null) { + return Maps.newHashMap(frameDelayRangeBackwardBins); + } else { + return null; + } + } + + /** + * Abstract builder for {@link org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStat}. + */ + protected abstract static class DefaultDmStatBuilder implements DmStatBuilder { + + private final Duration elapsedTime; + private final boolean suspectStatus; + private Duration frameDelayTwoWayMin; + private Duration frameDelayTwoWayMax; + private Duration frameDelayTwoWayAvg; + private Duration frameDelayForwardMin; + private Duration frameDelayForwardMax; + private Duration frameDelayForwardAvg; + private Duration frameDelayBackwardMin; + private Duration frameDelayBackwardMax; + private Duration frameDelayBackwardAvg; + private Duration interFrameDelayVariationTwoWayMin; + private Duration interFrameDelayVariationTwoWayMax; + private Duration interFrameDelayVariationTwoWayAvg; + private Duration interFrameDelayVariationForwardMin; + private Duration interFrameDelayVariationForwardMax; + private Duration interFrameDelayVariationForwardAvg; + private Duration interFrameDelayVariationBackwardMin; + private Duration interFrameDelayVariationBackwardMax; + private Duration interFrameDelayVariationBackwardAvg; + private Duration frameDelayRangeTwoWayMax; + private Duration frameDelayRangeTwoWayAvg; + private Duration frameDelayRangeForwardMax; + private Duration frameDelayRangeForwardAvg; + private Duration frameDelayRangeBackwardMax; + private Duration frameDelayRangeBackwardAvg; + private Integer soamPdusSent; + private Integer soamPdusReceived; + private Map frameDelayTwoWayBins; + private Map frameDelayForwardBins; + private Map frameDelayBackwardBins; + private Map interFrameDelayVariationTwoWayBins; + private Map interFrameDelayVariationForwardBins; + private Map interFrameDelayVariationBackwardBins; + private Map frameDelayRangeTwoWayBins; + private Map frameDelayRangeForwardBins; + private Map frameDelayRangeBackwardBins; + + protected DefaultDmStatBuilder(Duration elapsedTime, boolean suspectStatus) { + this.elapsedTime = elapsedTime; + this.suspectStatus = suspectStatus; + } + + @Override + public DmStatBuilder frameDelayTwoWayMin(Duration frameDelayTwoWayMin) { + this.frameDelayTwoWayMin = frameDelayTwoWayMin; + return this; + } + + @Override + public DmStatBuilder frameDelayTwoWayMax(Duration frameDelayTwoWayMax) { + this.frameDelayTwoWayMax = frameDelayTwoWayMax; + return this; + } + + @Override + public DmStatBuilder frameDelayTwoWayAvg(Duration frameDelayTwoWayAvg) { + this.frameDelayTwoWayAvg = frameDelayTwoWayAvg; + return this; + } + + @Override + public DmStatBuilder frameDelayForwardMin(Duration frameDelayForwardMin) { + this.frameDelayForwardMin = frameDelayForwardMin; + return this; + } + + @Override + public DmStatBuilder frameDelayForwardMax(Duration frameDelayForwardMax) { + this.frameDelayForwardMax = frameDelayForwardMax; + return this; + } + + @Override + public DmStatBuilder frameDelayForwardAvg(Duration frameDelayForwardAvg) { + this.frameDelayForwardAvg = frameDelayForwardAvg; + return this; + } + + @Override + public DmStatBuilder frameDelayBackwardMin(Duration frameDelayBackwardMin) { + this.frameDelayBackwardMin = frameDelayBackwardMin; + return this; + } + + @Override + public DmStatBuilder frameDelayBackwardMax(Duration frameDelayBackwardMax) { + this.frameDelayBackwardMax = frameDelayBackwardMax; + return this; + } + + @Override + public DmStatBuilder frameDelayBackwardAvg(Duration frameDelayBackwardAvg) { + this.frameDelayBackwardAvg = frameDelayBackwardAvg; + return this; + } + + @Override + public DmStatBuilder interFrameDelayVariationTwoWayMin(Duration interFrameDelayVariationTwoWayMin) { + this.interFrameDelayVariationTwoWayMin = interFrameDelayVariationTwoWayMin; + return this; + } + + @Override + public DmStatBuilder interFrameDelayVariationTwoWayMax(Duration interFrameDelayVariationTwoWayMax) { + this.interFrameDelayVariationTwoWayMax = interFrameDelayVariationTwoWayMax; + return this; + } + + @Override + public DmStatBuilder interFrameDelayVariationTwoWayAvg(Duration interFrameDelayVariationTwoWayAvg) { + this.interFrameDelayVariationTwoWayAvg = interFrameDelayVariationTwoWayAvg; + return this; + } + + @Override + public DmStatBuilder interFrameDelayVariationForwardMin(Duration interFrameDelayVariationForwardMin) { + this.interFrameDelayVariationForwardMin = interFrameDelayVariationForwardMin; + return this; + } + + @Override + public DmStatBuilder interFrameDelayVariationForwardMax(Duration interFrameDelayVariationForwardMax) { + this.interFrameDelayVariationForwardMax = interFrameDelayVariationForwardMax; + return this; + } + + @Override + public DmStatBuilder interFrameDelayVariationForwardAvg(Duration interFrameDelayVariationForwardAvg) { + this.interFrameDelayVariationForwardAvg = interFrameDelayVariationForwardAvg; + return this; + } + + @Override + public DmStatBuilder interFrameDelayVariationBackwardMin(Duration interFrameDelayVariationBackwardMin) { + this.interFrameDelayVariationBackwardMin = interFrameDelayVariationBackwardMin; + return this; + } + + @Override + public DmStatBuilder interFrameDelayVariationBackwardMax(Duration interFrameDelayVariationBackwardMax) { + this.interFrameDelayVariationBackwardMax = interFrameDelayVariationBackwardMax; + return this; + } + + @Override + public DmStatBuilder interFrameDelayVariationBackwardAvg(Duration interFrameDelayVariationBackwardAvg) { + this.interFrameDelayVariationBackwardAvg = interFrameDelayVariationBackwardAvg; + return this; + } + + @Override + public DmStatBuilder frameDelayRangeTwoWayMax(Duration frameDelayRangeTwoWayMax) { + this.frameDelayRangeTwoWayMax = frameDelayRangeTwoWayMax; + return this; + } + + @Override + public DmStatBuilder frameDelayRangeTwoWayAvg(Duration frameDelayRangeTwoWayAvg) { + this.frameDelayRangeTwoWayAvg = frameDelayRangeTwoWayAvg; + return this; + } + + @Override + public DmStatBuilder frameDelayRangeForwardMax(Duration frameDelayRangeForwardMax) { + this.frameDelayRangeForwardMax = frameDelayRangeForwardMax; + return this; + } + + @Override + public DmStatBuilder frameDelayRangeForwardAvg(Duration frameDelayRangeForwardAvg) { + this.frameDelayRangeForwardAvg = frameDelayRangeForwardAvg; + return this; + } + + @Override + public DmStatBuilder frameDelayRangeBackwardMax(Duration frameDelayRangeBackwardMax) { + this.frameDelayRangeBackwardMax = frameDelayRangeBackwardMax; + return this; + } + + @Override + public DmStatBuilder frameDelayRangeBackwardAvg(Duration frameDelayRangeBackwardAvg) { + this.frameDelayRangeBackwardAvg = frameDelayRangeBackwardAvg; + return this; + } + + @Override + public DmStatBuilder soamPdusSent(Integer soamPdusSent) { + this.soamPdusSent = soamPdusSent; + return this; + } + + @Override + public DmStatBuilder soamPdusReceived(Integer soamPdusReceived) { + this.soamPdusReceived = soamPdusReceived; + return this; + } + + @Override + public DmStatBuilder frameDelayTwoWayBins(Map frameDelayTwoWayBins) { + this.frameDelayTwoWayBins = frameDelayTwoWayBins; + return this; + } + + @Override + public DmStatBuilder frameDelayForwardBins(Map frameDelayForwardBins) { + this.frameDelayForwardBins = frameDelayForwardBins; + return this; + } + + @Override + public DmStatBuilder frameDelayBackwardBins(Map frameDelayBackwardBins) { + this.frameDelayBackwardBins = frameDelayBackwardBins; + return this; + } + + @Override + public DmStatBuilder interFrameDelayVariationTwoWayBins( + Map interFrameDelayVariationTwoWayBins) { + this.interFrameDelayVariationTwoWayBins = interFrameDelayVariationTwoWayBins; + return this; + } + + @Override + public DmStatBuilder interFrameDelayVariationForwardBins( + Map interFrameDelayVariationForwardBins) { + this.interFrameDelayVariationForwardBins = interFrameDelayVariationForwardBins; + return this; + } + + @Override + public DmStatBuilder interFrameDelayVariationBackwardBins( + Map interFrameDelayVariationBackwardBins) { + this.interFrameDelayVariationBackwardBins = interFrameDelayVariationBackwardBins; + return this; + } + + @Override + public DmStatBuilder frameDelayRangeTwoWayBins(Map frameDelayRangeTwoWayBins) { + this.frameDelayRangeTwoWayBins = frameDelayRangeTwoWayBins; + return this; + } + + @Override + public DmStatBuilder frameDelayRangeForwardBins(Map frameDelayRangeForwardBins) { + this.frameDelayRangeForwardBins = frameDelayRangeForwardBins; + return this; + } + + @Override + public DmStatBuilder frameDelayRangeBackwardBins(Map frameDelayRangeBackwardBins) { + this.frameDelayRangeBackwardBins = frameDelayRangeBackwardBins; + return this; + } + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DefaultDelayMeasurementStatCurrent.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DefaultDelayMeasurementStatCurrent.java new file mode 100644 index 0000000000..7263134c5b --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DefaultDelayMeasurementStatCurrent.java @@ -0,0 +1,68 @@ +/* + * 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.incubator.net.l2monitoring.soam.delay; + +import java.time.Duration; +import java.time.Instant; + +/** + * The default implementation of DelayMeasurementStatCurrent. + * {@link org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStatCurrent}. + */ +public final class DefaultDelayMeasurementStatCurrent + extends DefaultDelayMeasurementStat + implements DelayMeasurementStatCurrent { + + private final Instant startTime; + + protected DefaultDelayMeasurementStatCurrent(DefaultDmStatCurrentBuilder builder) { + super(builder); + this.startTime = builder.startTime; + } + + @Override + public Instant startTime() { + return startTime; + } + + public static DmStatCurrentBuilder builder(Duration elapsedTime, boolean suspectStatus) { + return new DefaultDmStatCurrentBuilder(elapsedTime, suspectStatus); + } + + /** + * Builder for {@link org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStatCurrent}. + */ + private static final class DefaultDmStatCurrentBuilder extends DefaultDmStatBuilder + implements DmStatCurrentBuilder { + + private Instant startTime; + + private DefaultDmStatCurrentBuilder(Duration elapsedTime, boolean suspectStatus) { + super(elapsedTime, suspectStatus); + } + + @Override + public DmStatCurrentBuilder startTime(Instant startTime) { + this.startTime = startTime; + return this; + } + + @Override + public DelayMeasurementStat build() { + return new DefaultDelayMeasurementStatCurrent(this); + } + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DefaultDelayMeasurementStatHistory.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DefaultDelayMeasurementStatHistory.java new file mode 100644 index 0000000000..4db368360f --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DefaultDelayMeasurementStatHistory.java @@ -0,0 +1,80 @@ +/* + * 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.incubator.net.l2monitoring.soam.delay; + +import java.time.Duration; +import java.time.Instant; + +import org.onosproject.incubator.net.l2monitoring.soam.SoamId; + +/** + * The default implementation of DelayMeasurementStatHistory. + * {@link org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStatHistory}. + */ +public class DefaultDelayMeasurementStatHistory extends DefaultDelayMeasurementStat + implements DelayMeasurementStatHistory { + + private final SoamId historyStatsId; + private final Instant endTime; + + protected DefaultDelayMeasurementStatHistory(DefaultDmStatHistoryBuilder builder) { + super(builder); + this.historyStatsId = builder.historyStatsId; + this.endTime = builder.endTime; + } + + @Override + public SoamId historyStatsId() { + return historyStatsId; + } + + @Override + public Instant endTime() { + return endTime; + } + + public static DmStatHistoryBuilder builder(SoamId historyStatsId, + Duration elapsedTime, boolean suspectStatus) { + return new DefaultDmStatHistoryBuilder( + historyStatsId, elapsedTime, suspectStatus); + } + + /** + * Builder for {@link org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStatHistory}. + */ + private static final class DefaultDmStatHistoryBuilder + extends DefaultDmStatBuilder implements DmStatHistoryBuilder { + private final SoamId historyStatsId; + private Instant endTime; + + private DefaultDmStatHistoryBuilder(SoamId historyStatsId, + Duration elapsedTime, boolean suspectStatus) { + super(elapsedTime, suspectStatus); + this.historyStatsId = historyStatsId; + } + + @Override + public DmStatHistoryBuilder endTime(Instant endTime) { + this.endTime = endTime; + return this; + } + + @Override + public DelayMeasurementStat build() { + return new DefaultDelayMeasurementStatHistory(this); + } + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DefaultDelayMeasurementThreshold.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DefaultDelayMeasurementThreshold.java new file mode 100644 index 0000000000..90a8c25c19 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DefaultDelayMeasurementThreshold.java @@ -0,0 +1,458 @@ +/* + * 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.incubator.net.l2monitoring.soam.delay; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.Collection; + +import org.onosproject.incubator.net.l2monitoring.soam.SoamId; + +/** + * The default implementation of DelayMeasurementThreshold. + * {@link org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementThreshold}. + */ +public final class DefaultDelayMeasurementThreshold + implements DelayMeasurementThreshold { + + private final SoamId threshId; + private final Collection thresholdsEnabled; + private final Duration measuredFrameDelayTwoWay; + private final Duration maxFrameDelayTwoWay; + private final Duration averageFrameDelayTwoWay; + private final Duration measuredInterFrameDelayVariationTwoWay; + private final Duration maxInterFrameDelayVariationTwoWay; + private final Duration averageInterFrameDelayVariationTwoWay; + private final Duration maxFrameDelayRangeTwoWay; + private final Duration averageFrameDelayRangeTwoWay; + private final Duration measuredFrameDelayForward; + private final Duration maxFrameDelayForward; + private final Duration averageFrameDelayForward; + private final Duration measuredInterFrameDelayVariationForward; + private final Duration maxInterFrameDelayVariationForward; + private final Duration averageInterFrameDelayVariationForward; + private final Duration maxFrameDelayRangeForward; + private final Duration averageFrameDelayRangeForward; + private final Duration measuredFrameDelayBackward; + private final Duration maxFrameDelayBackward; + private final Duration averageFrameDelayBackward; + private final Duration measuredInterFrameDelayVariationBackward; + private final Duration maxInterFrameDelayVariationBackward; + private final Duration averageInterFrameDelayVariationBackward; + private final Duration maxFrameDelayRangeBackward; + private final Duration averageFrameDelayRangeBackward; + + private DefaultDelayMeasurementThreshold(DefaultDmThresholdBuilder builder) { + this.threshId = builder.threshId; + this.thresholdsEnabled = builder.thresholdsEnabled; + this.measuredFrameDelayTwoWay = builder.measuredFrameDelayTwoWay; + this.maxFrameDelayTwoWay = builder.maxFrameDelayTwoWay; + this.averageFrameDelayTwoWay = builder.averageFrameDelayTwoWay; + this.measuredInterFrameDelayVariationTwoWay = + builder.measuredInterFrameDelayVariationTwoWay; + this.maxInterFrameDelayVariationTwoWay = + builder.maxInterFrameDelayVariationTwoWay; + this.averageInterFrameDelayVariationTwoWay = + builder.averageInterFrameDelayVariationTwoWay; + this.maxFrameDelayRangeTwoWay = builder.maxFrameDelayRangeTwoWay; + this.averageFrameDelayRangeTwoWay = builder.averageFrameDelayRangeTwoWay; + this.measuredFrameDelayForward = builder.measuredFrameDelayForward; + this.maxFrameDelayForward = builder.maxFrameDelayForward; + this.averageFrameDelayForward = builder.averageFrameDelayForward; + this.measuredInterFrameDelayVariationForward = + builder.measuredInterFrameDelayVariationForward; + this.maxInterFrameDelayVariationForward = + builder.maxInterFrameDelayVariationForward; + this.averageInterFrameDelayVariationForward = + builder.averageInterFrameDelayVariationForward; + this.maxFrameDelayRangeForward = builder.maxFrameDelayRangeForward; + this.averageFrameDelayRangeForward = builder.averageFrameDelayRangeForward; + this.measuredFrameDelayBackward = builder.measuredFrameDelayBackward; + this.maxFrameDelayBackward = builder.maxFrameDelayBackward; + this.averageFrameDelayBackward = builder.averageFrameDelayBackward; + this.measuredInterFrameDelayVariationBackward = + builder.measuredInterFrameDelayVariationBackward; + this.maxInterFrameDelayVariationBackward = + builder.maxInterFrameDelayVariationBackward; + this.averageInterFrameDelayVariationBackward = + builder.averageInterFrameDelayVariationBackward; + this.maxFrameDelayRangeBackward = + builder.maxFrameDelayRangeBackward; + this.averageFrameDelayRangeBackward = + builder.averageFrameDelayRangeBackward; + } + + @Override + public SoamId threshId() { + return threshId; + } + + @Override + public Collection thresholdsEnabled() { + return thresholdsEnabled; + } + + @Override + public Duration measuredFrameDelayTwoWay() { + return measuredFrameDelayTwoWay; + } + + @Override + public Duration maxFrameDelayTwoWay() { + return maxFrameDelayTwoWay; + } + + @Override + public Duration averageFrameDelayTwoWay() { + return averageFrameDelayTwoWay; + } + + @Override + public Duration measuredInterFrameDelayVariationTwoWay() { + return measuredInterFrameDelayVariationTwoWay; + } + + @Override + public Duration maxInterFrameDelayVariationTwoWay() { + return maxInterFrameDelayVariationTwoWay; + } + + @Override + public Duration averageInterFrameDelayVariationTwoWay() { + return averageInterFrameDelayVariationTwoWay; + } + + @Override + public Duration maxFrameDelayRangeTwoWay() { + return maxFrameDelayRangeTwoWay; + } + + @Override + public Duration averageFrameDelayRangeTwoWay() { + return averageFrameDelayRangeTwoWay; + } + + @Override + public Duration measuredFrameDelayForward() { + return measuredFrameDelayForward; + } + + @Override + public Duration maxFrameDelayForward() { + return maxFrameDelayForward; + } + + @Override + public Duration averageFrameDelayForward() { + return averageFrameDelayForward; + } + + @Override + public Duration measuredInterFrameDelayVariationForward() { + return measuredInterFrameDelayVariationForward; + } + + @Override + public Duration maxInterFrameDelayVariationForward() { + return maxInterFrameDelayVariationForward; + } + + @Override + public Duration averageInterFrameDelayVariationForward() { + return averageInterFrameDelayVariationForward; + } + + @Override + public Duration maxFrameDelayRangeForward() { + return maxFrameDelayRangeForward; + } + + @Override + public Duration averageFrameDelayRangeForward() { + return averageFrameDelayRangeForward; + } + + @Override + public Duration measuredFrameDelayBackward() { + return measuredFrameDelayBackward; + } + + @Override + public Duration maxFrameDelayBackward() { + return maxFrameDelayBackward; + } + + @Override + public Duration averageFrameDelayBackward() { + return averageFrameDelayBackward; + } + + @Override + public Duration measuredInterFrameDelayVariationBackward() { + return measuredInterFrameDelayVariationBackward; + } + + @Override + public Duration maxInterFrameDelayVariationBackward() { + return maxInterFrameDelayVariationBackward; + } + + @Override + public Duration averageInterFrameDelayVariationBackward() { + return averageInterFrameDelayVariationBackward; + } + + @Override + public Duration maxFrameDelayRangeBackward() { + return maxFrameDelayRangeBackward; + } + + @Override + public Duration averageFrameDelayRangeBackward() { + return averageFrameDelayRangeBackward; + } + + public static DmThresholdBuilder builder(SoamId threshId) { + return new DefaultDmThresholdBuilder(threshId); + } + + /** + * Builder for {@link org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementThreshold}. + */ + private static final class DefaultDmThresholdBuilder implements DmThresholdBuilder { + private final SoamId threshId; + private Collection thresholdsEnabled; + private Duration measuredFrameDelayTwoWay; + private Duration maxFrameDelayTwoWay; + private Duration averageFrameDelayTwoWay; + private Duration measuredInterFrameDelayVariationTwoWay; + private Duration maxInterFrameDelayVariationTwoWay; + private Duration averageInterFrameDelayVariationTwoWay; + private Duration maxFrameDelayRangeTwoWay; + private Duration averageFrameDelayRangeTwoWay; + private Duration measuredFrameDelayForward; + private Duration maxFrameDelayForward; + private Duration averageFrameDelayForward; + private Duration measuredInterFrameDelayVariationForward; + private Duration maxInterFrameDelayVariationForward; + private Duration averageInterFrameDelayVariationForward; + private Duration maxFrameDelayRangeForward; + private Duration averageFrameDelayRangeForward; + private Duration measuredFrameDelayBackward; + private Duration maxFrameDelayBackward; + private Duration averageFrameDelayBackward; + private Duration measuredInterFrameDelayVariationBackward; + private Duration maxInterFrameDelayVariationBackward; + private Duration averageInterFrameDelayVariationBackward; + private Duration maxFrameDelayRangeBackward; + private Duration averageFrameDelayRangeBackward; + + protected DefaultDmThresholdBuilder(SoamId threshId) { + this.threshId = threshId; + this.thresholdsEnabled = new ArrayList<>(); + } + + @Override + public DmThresholdBuilder addToThresholdsEnabled( + ThresholdOption thresholdEnabled) { + this.thresholdsEnabled.add(thresholdEnabled); + return this; + } + + @Override + public DmThresholdBuilder measuredFrameDelayTwoWay( + Duration measuredFrameDelayTwoWay) { + this.measuredFrameDelayTwoWay = measuredFrameDelayTwoWay; + return this; + } + + @Override + public DmThresholdBuilder maxFrameDelayTwoWay( + Duration maxFrameDelayTwoWay) { + this.maxFrameDelayTwoWay = maxFrameDelayTwoWay; + return this; + } + + @Override + public DmThresholdBuilder averageFrameDelayTwoWay( + Duration averageFrameDelayTwoWay) { + this.averageFrameDelayTwoWay = averageFrameDelayTwoWay; + return this; + } + + @Override + public DmThresholdBuilder measuredInterFrameDelayVariationTwoWay( + Duration measuredInterFrameDelayVariationTwoWay) { + this.measuredInterFrameDelayVariationTwoWay = + measuredInterFrameDelayVariationTwoWay; + return this; + } + + @Override + public DmThresholdBuilder maxInterFrameDelayVariationTwoWay( + Duration maxInterFrameDelayVariationTwoWay) { + this.maxInterFrameDelayVariationTwoWay = + maxInterFrameDelayVariationTwoWay; + return this; + } + + @Override + public DmThresholdBuilder averageInterFrameDelayVariationTwoWay( + Duration averageInterFrameDelayVariationTwoWay) { + this.averageInterFrameDelayVariationTwoWay = + averageInterFrameDelayVariationTwoWay; + return this; + } + + @Override + public DmThresholdBuilder maxFrameDelayRangeTwoWay( + Duration maxFrameDelayRangeTwoWay) { + this.maxFrameDelayRangeTwoWay = maxFrameDelayRangeTwoWay; + return this; + } + + @Override + public DmThresholdBuilder averageFrameDelayRangeTwoWay( + Duration averageFrameDelayRangeTwoWay) { + this.averageFrameDelayRangeTwoWay = averageFrameDelayRangeTwoWay; + return this; + } + + @Override + public DmThresholdBuilder measuredFrameDelayForward( + Duration measuredFrameDelayForward) { + this.measuredFrameDelayForward = measuredFrameDelayForward; + return this; + } + + @Override + public DmThresholdBuilder maxFrameDelayForward( + Duration maxFrameDelayForward) { + this.maxFrameDelayForward = maxFrameDelayForward; + return this; + } + + @Override + public DmThresholdBuilder averageFrameDelayForward( + Duration averageFrameDelayForward) { + this.averageFrameDelayForward = averageFrameDelayForward; + return this; + } + + @Override + public DmThresholdBuilder measuredInterFrameDelayVariationForward( + Duration measuredInterFrameDelayVariationForward) { + this.measuredInterFrameDelayVariationForward = + measuredInterFrameDelayVariationForward; + return this; + } + + @Override + public DmThresholdBuilder maxInterFrameDelayVariationForward( + Duration maxInterFrameDelayVariationForward) { + this.maxInterFrameDelayVariationForward = + maxInterFrameDelayVariationForward; + return this; + } + + @Override + public DmThresholdBuilder averageInterFrameDelayVariationForward( + Duration averageInterFrameDelayVariationForward) { + this.averageInterFrameDelayVariationForward = + averageInterFrameDelayVariationForward; + return this; + } + + @Override + public DmThresholdBuilder maxFrameDelayRangeForward( + Duration maxFrameDelayRangeForward) { + this.maxFrameDelayRangeForward = maxFrameDelayRangeForward; + return this; + } + + @Override + public DmThresholdBuilder averageFrameDelayRangeForward( + Duration averageFrameDelayRangeForward) { + this.averageFrameDelayRangeForward = averageFrameDelayRangeForward; + return this; + } + + @Override + public DmThresholdBuilder measuredFrameDelayBackward( + Duration measuredFrameDelayBackward) { + this.measuredFrameDelayBackward = measuredFrameDelayBackward; + return this; + } + + @Override + public DmThresholdBuilder maxFrameDelayBackward( + Duration maxFrameDelayBackward) { + this.maxFrameDelayBackward = maxFrameDelayBackward; + return this; + } + + @Override + public DmThresholdBuilder averageFrameDelayBackward( + Duration averageFrameDelayBackward) { + this.averageFrameDelayBackward = averageFrameDelayBackward; + return this; + } + + @Override + public DmThresholdBuilder measuredInterFrameDelayVariationBackward( + Duration measuredInterFrameDelayVariationBackward) { + this.measuredInterFrameDelayVariationBackward = + measuredInterFrameDelayVariationBackward; + return this; + } + + @Override + public DmThresholdBuilder maxInterFrameDelayVariationBackward( + Duration maxInterFrameDelayVariationBackward) { + this.maxInterFrameDelayVariationBackward = + maxInterFrameDelayVariationBackward; + return this; + } + + @Override + public DmThresholdBuilder averageInterFrameDelayVariationBackward( + Duration averageInterFrameDelayVariationBackward) { + this.averageInterFrameDelayVariationBackward = + averageInterFrameDelayVariationBackward; + return this; + } + + @Override + public DmThresholdBuilder maxFrameDelayRangeBackward( + Duration maxFrameDelayRangeBackward) { + this.maxFrameDelayRangeBackward = maxFrameDelayRangeBackward; + return this; + } + + @Override + public DmThresholdBuilder averageFrameDelayRangeBackward( + Duration averageFrameDelayRangeBackward) { + this.averageFrameDelayRangeBackward = averageFrameDelayRangeBackward; + return this; + } + + @Override + public DelayMeasurementThreshold build() { + return new DefaultDelayMeasurementThreshold(this); + } + } + +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DelayMeasurementCreate.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DelayMeasurementCreate.java new file mode 100644 index 0000000000..4934146a83 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DelayMeasurementCreate.java @@ -0,0 +1,226 @@ +/* + * 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.incubator.net.l2monitoring.soam.delay; + +import java.util.Collection; + +import org.onosproject.incubator.net.l2monitoring.soam.MeasurementCreateBase; +import org.onosproject.incubator.net.l2monitoring.soam.SoamConfigException; + +/** + * A model of Delay Measurement from ITU Y.1731 Chapter 8.2, MEF 17, MEF 36.1 and MEF 39. + * + * In this model delay measurements entries are returned as a collection in the + * MepEntry. In this way Delay Measurements are created by calling on the + * Create Delay Measurement function, passing this DelayMeasurementCreate object + * and any other arguments needed. + * The Delay Measurement Entry is a result and not configured or + * persisted in ONOS, but instead is is passed on to some analytics system + */ +public interface DelayMeasurementCreate extends MeasurementCreateBase { + /** + * The type of Delay Measurement is to be performed. + * The exact PDUs to use are specified by this object in combination with version + * @return enumerated type + */ + DmType dmCfgType(); + + /** + * A vector of bits that indicates the type of SOAM DM counters that are enabled. + * A present bit enables the specific SOAM DM counter. + * A not present bit disables the SOAM DM counter. + * If a particular SOAM DM counter is not supported the BIT value is not present. + * Not all SOAM DM counters are supported for all SOAM DM types. + * @return A collection of options + */ + Collection measurementsEnabled(); + + /** + * The number of measurement bins per Measurement Interval for Frame Delay measurements. + * At least 3 bins are to be supported; at least 10 bins are recommended to be supported + * @return the number of bins + */ + Short binsPerFdInterval(); + + /** + * The number of measurement bins per Measurement Interval for Inter-Frame Delay Variation measurements. + * The minimum number of measurement bins to be supported is 2. The desired + * number of measurements bins to be supported is 10 + * @return the number of bins + */ + Short binsPerIfdvInterval(); + + /** + * The selection offset for Inter-Frame Delay Variation measurements. + * If this value is set to n, then the IFDV is calculated by taking the + * difference in frame delay between frame F and frame (F+n). + * reference: MEF-SOAM-PM-MIB.mefSoamDmCfgInterFrameDelayVariationSelectionOffset + * @return The selection offset + */ + Short ifdvSelectionOffset(); + + /** + * The number of measurement bins per Measurement Interval for Frame Delay Range measurements. + * @return the number of bins + */ + Short binsPerFdrInterval(); + + /** + * The Delay Measurement threshold configuration values for DM Performance Monitoring. + * The main purpose of the threshold configuration list is to configure + * threshold alarm notifications indicating that a specific performance metric + * is not being met + * @return a collection of Thresholds + */ + Collection thresholds(); + + /** + * Builder for {@link org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate}. + */ + public interface DmCreateBuilder extends MeasCreateBaseBuilder { + + DmCreateBuilder addToMeasurementsEnabled( + MeasurementOption measurementEnabled); + + DmCreateBuilder binsPerFdInterval(Short binsPerFdInterval) + throws SoamConfigException; + + DmCreateBuilder binsPerIfdvInterval(Short binsPerIfdvInterval) + throws SoamConfigException; + + DmCreateBuilder ifdvSelectionOffset(Short ifdvSelectionOffset) + throws SoamConfigException; + + DmCreateBuilder binsPerFdrInterval(Short binsPerFdrInterval) + throws SoamConfigException; + + DmCreateBuilder addToThresholds(DelayMeasurementThreshold threshold); + + DelayMeasurementCreate build(); + } + + /** + * Enumerated options for Delay Measurement Types. + */ + public enum DmType { + /** + * DMM SOAM PDU generated, DMR responses received (one-way or two-way measurements). + */ + DMDMM, + /** + * 1DM SOAM PDU generated (one-way measurements are made by the receiver). + */ + DM1DMTX, + /** + * 1DM SOAM PDU received and tracked (one-way measurements). + */ + DM1DMRX + } + + /** + * Supported Versions of Y.1731. + */ + public enum Version { + Y17312008("Y.1731-2008"), + Y17312011("Y.1731-2011"); + + private String literal; + private Version(String literal) { + this.literal = literal; + } + + public String literal() { + return literal; + } + } + + /** + * Selection of Measurement types. + */ + public enum MeasurementOption { + SOAM_PDUS_SENT, + SOAM_PDUS_RECEIVED, + FRAME_DELAY_TWO_WAY_BINS, + FRAME_DELAY_TWO_WAY_MIN, + FRAME_DELAY_TWO_WAY_MAX, + FRAME_DELAY_TWO_WAY_AVERAGE, + FRAME_DELAY_FORWARD_BINS, + FRAME_DELAY_FORWARD_MIN, + FRAME_DELAY_FORWARD_MAX, + FRAME_DELAY_FORWARD_AVERAGE, + FRAME_DELAY_BACKWARD_BINS, + FRAME_DELAY_BACKWARD_MIN, + FRAME_DELAY_BACKWARD_MAX, + FRAME_DELAY_BACKWARD_AVERAGE, + INTER_FRAME_DELAY_VARIATION_FORWARD_BINS, + INTER_FRAME_DELAY_VARIATION_FORWARD_MIN, + INTER_FRAME_DELAY_VARIATION_FORWARD_MAX, + INTER_FRAME_DELAY_VARIATION_FORWARD_AVERAGE, + INTER_FRAME_DELAY_VARIATION_BACKWARD_BINS, + INTER_FRAME_DELAY_VARIATION_BACKWARD_MIN, + INTER_FRAME_DELAY_VARIATION_BACKWARD_MAX, + INTER_FRAME_DELAY_VARIATION_BACKWARD_AVERAGE, + INTER_FRAME_DELAY_VARIATION_TWO_WAY_BINS, + INTER_FRAME_DELAY_VARIATION_TWO_WAY_MIN, + INTER_FRAME_DELAY_VARIATION_TWO_WAY_MAX, + INTER_FRAME_DELAY_VARIATION_TWO_WAY_AVERAGE, + FRAME_DELAY_RANGE_FORWARD_BINS, + FRAME_DELAY_RANGE_FORWARD_MAX, + FRAME_DELAY_RANGE_FORWARD_AVERAGE, + FRAME_DELAY_RANGE_BACKWARD_BINS, + FRAME_DELAY_RANGE_BACKWARD_MAX, + FRAME_DELAY_RANGE_BACKWARD_AVERAGE, + FRAME_DELAY_RANGE_TWO_WAY_BINS, + FRAME_DELAY_RANGE_TWO_WAY_MAX, + FRAME_DELAY_RANGE_TWO_WAY_AVERAGE, + MEASURED_STATS_FRAME_DELAY_TWO_WAY, + MEASURED_STATS_FRAME_DELAY_FORWARD, + MEASURED_STATS_FRAME_DELAY_BACKWARD, + MEASURED_STATS_INTER_FRAME_DELAY_VARIATION_TWO_WAY, + MEASURED_STATS_INTER_FRAME_DELAY_VARIATION_FORWARD, + MEASURED_STATS_INTER_FRAME_DELAY_VARIATION_BACKWARD; + } + + /** + * Selection of Data Patterns. + */ + public enum DataPattern { + ZEROES, + ONES; + } + + /** + * Selection of Test TLV Patterns. + */ + public enum TestTlvPattern { + /** + * This test pattern is a Null signal without CRC-32. + */ + NULL_SIGNAL_WITHOUT_CRC_32, + /** + * This test pattern is a Null signal with CRC-32. + */ + NULL_SIGNAL_WITH_CRC_32, + /** + * This test pattern is a PRBS 2^31-1 without CRC-32. + */ + PRBS_2311_WITHOUT_CRC_32, + /** + * This test pattern is a PRBS 2^31-1 with CRC-32. + */ + PRBS_2311_WITH_CRC_32; + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DelayMeasurementEntry.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DelayMeasurementEntry.java new file mode 100644 index 0000000000..3571922903 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DelayMeasurementEntry.java @@ -0,0 +1,141 @@ +/* + * 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.incubator.net.l2monitoring.soam.delay; + +import java.time.Duration; +import java.util.Collection; + +import org.onosproject.incubator.net.l2monitoring.soam.SoamId; + +/** + * Delay Measurement from ITU Y.1731 Chapter 8.2, MEF 17, MEF 36.1 and MEF 39. + * + * This represents the result returned and includes the parameters used to + * configure the DM when it was created + */ +public interface DelayMeasurementEntry extends DelayMeasurementCreate { + /** + * This uniquely identifies a scheduled measurement. + * It is automatically generated by the server on creation of a new measurement + * @return the id + */ + SoamId dmId(); + + /** + * The current status of the DM session. + * A value of 'active' indicates the current DM session is active, + * i.e. the current time lies between the start time and the stop time, and + * enabled is true. A value of 'not-active' indicates the current DM session + * is not active, i.e. it has not started yet, has stopped upon reaching the + * stop time, or is disabled + * @return the status + */ + SessionStatus sessionStatus(); + + /** + * The two-way frame delay calculated by this MEP from the last received SOAM PDU. + * This object is undefined is measurement-type is dm1-transmitted or dm1-received + * @return The delay as a java duration + */ + Duration frameDelayTwoWay(); + + /** + * The frame delay in the forward direction calculated by this MEP from the last received SOAM PDU. + * The value of this object may not be accurate in the absence of sufficiently + * precise clock synchronization. + * This object is undefined is measurement-type is dm1-transmitted + * @return The delay as a java duration + */ + Duration frameDelayForward(); + + /** + * The frame delay in the backward direction calculated by this MEP from the last received SOAM PDU. + * The value of this object may not be accurate in the absence of sufficiently + * precise clock synchronization. + * This object is undefined is measurement-type is dm1-transmitted or dm1-received + * @return The delay as a java duration + */ + Duration frameDelayBackward(); + + /** + * The last two-way inter-frame delay interval calculated by this MEP. + * The value of this object is undefined when measurement-type is dm1-transmitted or dm1-received + * @return The delay as a java duration + */ + Duration interFrameDelayVariationTwoWay(); + + /** + * The last one-way inter-frame delay interval in the forward direction calculated by this MEP. + * The value of this object is undefined when measurement-type is dm1-transmitted + * @return The delay as a java duration + */ + Duration interFrameDelayVariationForward(); + + /** + * The last one-way inter-frame delay interval in the backward direction calculated by this MEP. + * The value of this object is undefined when measurement-type is + * dm1-transmitted or dm1-received + * @return The delay as a java duration + */ + Duration interFrameDelayVariationBackward(); + + /** + * The results for the current Measurement Interval in a SOAM Delay Measurement session. + * gathered during the interval indicated by measurement-interval. + * @return The current set of results + */ + DelayMeasurementStatCurrent currentResult(); + + /** + * The results for history Measurement Intervals in a SOAM Delay Measurement session. + * @return A collection of history results + */ + Collection historicalResults(); + + /** + * Builder for {@link org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementEntry}. + */ + public interface DmEntryBuilder extends DmCreateBuilder { + DmEntryBuilder sessionStatus(SessionStatus sessionStatus); + + DmEntryBuilder frameDelayTwoWay(Duration frameDelayTwoWay); + + DmEntryBuilder frameDelayForward(Duration frameDelayForward); + + DmEntryBuilder frameDelayBackward(Duration frameDelayBackward); + + DmEntryBuilder interFrameDelayVariationTwoWay(Duration interFrameDelayVariationTwoWay); + + DmEntryBuilder interFrameDelayVariationForward(Duration interFrameDelayVariationForward); + + DmEntryBuilder interFrameDelayVariationBackward(Duration interFrameDelayVariationBackward); + + DmEntryBuilder currentResult(DelayMeasurementStatCurrent currentResult); + + DmEntryBuilder addToHistoricalResults( + DelayMeasurementStatHistory historicalResult); + + DelayMeasurementEntry build(); + } + + /** + * Session Status options. + */ + public enum SessionStatus { + ACTIVE, + NOT_ACTIVE; + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DelayMeasurementStat.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DelayMeasurementStat.java new file mode 100644 index 0000000000..c218c06ad3 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DelayMeasurementStat.java @@ -0,0 +1,356 @@ +/* + * 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.incubator.net.l2monitoring.soam.delay; + +import java.time.Duration; +import java.util.Map; + +/** + * Abstract object as a base for DelayMeasurementStatCurrent and DelayMeasurementStatHistory interfaces. + */ +public interface DelayMeasurementStat { + /** + * The time that the current Measurement Interval has been running. + * @return A java duration + */ + Duration elapsedTime(); + + /** + * The suspect flag for the current measurement interval in which the notification was generated. + * reference MEF-SOAM-PM-MIB.mefSoamPmNotificationObjSuspect"; + * @return true if the measurement might include an error + */ + boolean suspectStatus(); + + /** + * The minimum two-way frame delay calculated by this MEP for this Measurement Interval. + * @return A java duration + */ + Duration frameDelayTwoWayMin(); + + /** + * The maximum two-way frame delay calculated by this MEP for this Measurement Interval. + * @return A java duration + */ + Duration frameDelayTwoWayMax(); + + /** + * The average two-way frame delay calculated by this MEP for this Measurement Interval. + * @return A java duration + */ + Duration frameDelayTwoWayAvg(); + + /** + * The minimum foward frame delay calculated by this MEP for this Measurement Interval. + * @return A java duration + */ + Duration frameDelayForwardMin(); + + /** + * The maximum forward frame delay calculated by this MEP for this Measurement Interval. + * @return A java duration + */ + Duration frameDelayForwardMax(); + + /** + * The average forward frame delay calculated by this MEP for this Measurement Interval. + * @return A java duration + */ + Duration frameDelayForwardAvg(); + + /** + * The minimum backward frame delay calculated by this MEP for this Measurement Interval. + * @return A java duration + */ + Duration frameDelayBackwardMin(); + + /** + * The maximum backward frame delay calculated by this MEP for this Measurement Interval. + * @return A java duration + */ + Duration frameDelayBackwardMax(); + + /** + * The average backward frame delay calculated by this MEP for this Measurement Interval. + * @return A java duration + */ + Duration frameDelayBackwardAvg(); + + /** + * The minimum two-way inter-frame delay interval calculated by this MEP for this Measurement Interval. + * @return A java duration + */ + Duration interFrameDelayVariationTwoWayMin(); + + /** + * The maximum two-way inter-frame delay interval calculated by this MEP for this Measurement Interval. + * @return A java duration + */ + Duration interFrameDelayVariationTwoWayMax(); + + /** + * The average two-way inter-frame delay interval calculated by this MEP for this Measurement Interval. + * @return A java duration + */ + Duration interFrameDelayVariationTwoWayAvg(); + + /** + * The minimum one-way inter-frame delay interval in the forward direction. + * calculated by this MEP for this Measurement Interval. + * @return A java duration + */ + Duration interFrameDelayVariationForwardMin(); + + /** + * The maximum one-way inter-frame delay interval in the forward direction. + * calculated by this MEP for this Measurement Interval. + * @return A java duration + */ + Duration interFrameDelayVariationForwardMax(); + + /** + * The average one-way inter-frame delay interval in the forward direction. + * calculated by this MEP for this Measurement Interval. + * @return A java duration + */ + Duration interFrameDelayVariationForwardAvg(); + + /** + * The minimum one-way inter-frame delay interval in the backward direction. + * calculated by this MEP for this Measurement Interval. + * @return A java duration + */ + Duration interFrameDelayVariationBackwardMin(); + + /** + * The maximum one-way inter-frame delay interval in the backward direction. + * calculated by this MEP for this Measurement Interval. + * @return A java duration + */ + Duration interFrameDelayVariationBackwardMax(); + + /** + * The average one-way inter-frame delay interval in the backward direction. + * calculated by this MEP for this Measurement Interval. + * @return A java duration + */ + Duration interFrameDelayVariationBackwardAvg(); + + /** + * The maximum two-way Frame Delay Range calculated by this MEP for this Measurement Interval. + * @return A java duration + */ + Duration frameDelayRangeTwoWayMax(); + + /** + * The average two-way Frame Delay Range calculated by this MEP for this Measurement Interval. + * @return A java duration + */ + Duration frameDelayRangeTwoWayAvg(); + + /** + * The maximum one-way Frame Delay Range in the forward direction. + * calculated by this MEP for this Measurement Interval + * @return A java duration + */ + Duration frameDelayRangeForwardMax(); + + /** + * The average one-way Frame Delay Range in the forward direction. + * calculated by this MEP for this Measurement Interval + * @return A java duration + */ + Duration frameDelayRangeForwardAvg(); + + /** + * The maximum one-way Frame Delay Range in the backward direction. + * calculated by this MEP for this Measurement Interval + * @return A java duration + */ + Duration frameDelayRangeBackwardMax(); + + /** + * The average one-way Frame Delay Range in the backward direction. + * calculated by this MEP for this Measurement Interval + * @return A java duration + */ + Duration frameDelayRangeBackwardAvg(); + + /** + * The count of the number of SOAM PDUs sent during this Measurement Interval. + * @return the count as an integer + */ + Integer soamPdusSent(); + + /** + * The count of the number of SOAM PDUs received during this Measurement Interval. + * @return the count as an integer + */ + Integer soamPdusReceived(); + + /** + * Bins calculated for two-way Frame Delay measurements. + * calculated by this MEP for this Measurement interval. + * + * The reply contains a set of counts of packets per bin + * The bin is defined by the durations given as the lower limit and the next + * size being the upper limit. For the largest duration, the count is of packets + * of that size up to infinity + * + * For example, if there are 4 elements in the result + * PT0.000S 4 - This means there are 4 packets in the 0-20ms bin + * PT0.020S 6 - This means there are 6 packets in the 20-30ms bin + * PT0.030S 8 - This means there are 8 packets in the 30-50ms bin + * PT0.050S 10 - This means there are 10 packets in the 50ms-infinity bin + * + * @return A map of counts per time periods + */ + Map frameDelayTwoWayBins(); + + /** + * Bins calculated for one-way Frame Delay measurements in the Forward direction. + * calculated by this MEP for this Measurement interval. + * @return A map of counts per time periods + */ + Map frameDelayForwardBins(); + + /** + * Bins calculated for one-way Frame Delay measurements in the Backward direction. + * calculated by this MEP for this Measurement interval. + * @return A map of counts per time periods + */ + Map frameDelayBackwardBins(); + + /** + * Bins calculated for two-way Inter Frame Delay Variation measurements. + * calculated by this MEP for this Measurement interval. + * @return A map of counts per time periods + */ + Map interFrameDelayVariationTwoWayBins(); + + /** + * Bins calculated for one-way Inter Frame Delay Variation measurements in the Forward direction. + * calculated by this MEP for this Measurement interval. + * @return A map of counts per time periods + */ + Map interFrameDelayVariationForwardBins(); + + /** + * Bins calculated for one-way Inter Frame Delay Variation measurements in the Backward direction. + * calculated by this MEP for this Measurement interval. + * @return A map of counts per time periods + */ + Map interFrameDelayVariationBackwardBins(); + + /** + * Bins calculated for two-way Frame Delay Range measurements. + * calculated by this MEP for this Measurement interval. + * @return A map of counts per time periods + */ + Map frameDelayRangeTwoWayBins(); + + /** + * Bins calculated for one-way Frame Delay Range measurements in the Forward direction. + * calculated by this MEP for this Measurement interval. + * @return A map of counts per time periods + */ + Map frameDelayRangeForwardBins(); + + /** + * Bins calculated for one-way Frame Delay Range measurements in the Backward direction. + * calculated by this MEP for this Measurement interval. + * @return A map of counts per time periods + */ + Map frameDelayRangeBackwardBins(); + + /** + * Abstract Builder interface for DelayMeasurementStat. + * {@link org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStat}. + */ + interface DmStatBuilder { + DmStatBuilder frameDelayTwoWayMin(Duration frameDelayTwoWayMin); + + DmStatBuilder frameDelayTwoWayMax(Duration frameDelayTwoWayMax); + + DmStatBuilder frameDelayTwoWayAvg(Duration frameDelayTwoWayAvg); + + DmStatBuilder frameDelayForwardMin(Duration frameDelayForwardMin); + + DmStatBuilder frameDelayForwardMax(Duration frameDelayForwardMax); + + DmStatBuilder frameDelayForwardAvg(Duration frameDelayForwardAvg); + + DmStatBuilder frameDelayBackwardMin(Duration frameDelayBackwardMin); + + DmStatBuilder frameDelayBackwardMax(Duration frameDelayBackwardMax); + + DmStatBuilder frameDelayBackwardAvg(Duration frameDelayBackwardAvg); + + DmStatBuilder interFrameDelayVariationTwoWayMin(Duration interFrameDelayVariationTwoWayMin); + + DmStatBuilder interFrameDelayVariationTwoWayMax(Duration interFrameDelayVariationTwoWayMax); + + DmStatBuilder interFrameDelayVariationTwoWayAvg(Duration interFrameDelayVariationTwoWayAvg); + + DmStatBuilder interFrameDelayVariationForwardMin(Duration interFrameDelayVariationForwardMin); + + DmStatBuilder interFrameDelayVariationForwardMax(Duration interFrameDelayVariationForwardMax); + + DmStatBuilder interFrameDelayVariationForwardAvg(Duration interFrameDelayVariationForwardAvg); + + DmStatBuilder interFrameDelayVariationBackwardMin(Duration interFrameDelayVariationBackwardMin); + + DmStatBuilder interFrameDelayVariationBackwardMax(Duration interFrameDelayVariationBackwardMax); + + DmStatBuilder interFrameDelayVariationBackwardAvg(Duration interFrameDelayVariationBackwardAvg); + + DmStatBuilder frameDelayRangeTwoWayMax(Duration frameDelayRangeTwoWayMax); + + DmStatBuilder frameDelayRangeTwoWayAvg(Duration frameDelayRangeTwoWayAvg); + + DmStatBuilder frameDelayRangeForwardMax(Duration frameDelayRangeForwardMax); + + DmStatBuilder frameDelayRangeForwardAvg(Duration frameDelayRangeForwardAvg); + + DmStatBuilder frameDelayRangeBackwardMax(Duration frameDelayRangeBackwardMax); + + DmStatBuilder frameDelayRangeBackwardAvg(Duration frameDelayRangeBackwardAvg); + + DmStatBuilder soamPdusSent(Integer soamPdusSent); + + DmStatBuilder soamPdusReceived(Integer soamPdusReceived); + + DmStatBuilder frameDelayTwoWayBins(Map frameDelayTwoWayBins); + + DmStatBuilder frameDelayForwardBins(Map frameDelayForwardBins); + + DmStatBuilder frameDelayBackwardBins(Map frameDelayBackwardBins); + + DmStatBuilder interFrameDelayVariationTwoWayBins(Map interFrameDelayVariationTwoWayBins); + + DmStatBuilder interFrameDelayVariationForwardBins(Map interFrameDelayVariationForwardBins); + + DmStatBuilder interFrameDelayVariationBackwardBins(Map interFrameDelayVariationBackwardBins); + + DmStatBuilder frameDelayRangeTwoWayBins(Map frameDelayRangeTwoWayBins); + + DmStatBuilder frameDelayRangeForwardBins(Map frameDelayRangeForwardBins); + + DmStatBuilder frameDelayRangeBackwardBins(Map frameDelayRangeBackwardBins); + + DelayMeasurementStat build(); + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DelayMeasurementStatCurrent.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DelayMeasurementStatCurrent.java new file mode 100644 index 0000000000..f9bb25ffdd --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DelayMeasurementStatCurrent.java @@ -0,0 +1,36 @@ +/* + * 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.incubator.net.l2monitoring.soam.delay; + +import java.time.Instant; + +/** + * Object for representing Delay Measurement Current Stats. + */ +public interface DelayMeasurementStatCurrent extends DelayMeasurementStat { + /** + * The time that the current Measurement Interval started. + * @return The start time as a java Instant + */ + Instant startTime(); + + /** + * Builder for {@link org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStatCurrent}. + */ + public interface DmStatCurrentBuilder extends DmStatBuilder { + DmStatCurrentBuilder startTime(Instant startTime); + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DelayMeasurementStatHistory.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DelayMeasurementStatHistory.java new file mode 100644 index 0000000000..c55c66a5fe --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DelayMeasurementStatHistory.java @@ -0,0 +1,44 @@ +/* + * 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.incubator.net.l2monitoring.soam.delay; + +import java.time.Instant; + +import org.onosproject.incubator.net.l2monitoring.soam.SoamId; + +/** + * Object for representing Delay Measurement History Stats. + */ +public interface DelayMeasurementStatHistory extends DelayMeasurementStat { + /** + * The identifier of the historic measurement. + * @return The id + */ + SoamId historyStatsId(); + + /** + * The time that the historic Measurement Interval ended. + * @return A java Instant + */ + Instant endTime(); + + /** + * Builder for {@link org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStatHistory}. + */ + public interface DmStatHistoryBuilder extends DmStatBuilder { + DmStatHistoryBuilder endTime(Instant endTime); + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DelayMeasurementThreshold.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DelayMeasurementThreshold.java new file mode 100644 index 0000000000..78ae5d4f32 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DelayMeasurementThreshold.java @@ -0,0 +1,298 @@ +/* + * 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.incubator.net.l2monitoring.soam.delay; + +import java.time.Duration; +import java.util.Collection; + +import org.onosproject.incubator.net.l2monitoring.soam.SoamId; + +/** + * Object to represent a Delay Measurement Threshold. + */ +public interface DelayMeasurementThreshold { + /** + * The identifier or the scheduled measurement. + * @return The id + */ + SoamId threshId(); + + /** + * A vector of bits that indicates the type of SOAM LM thresholds notifications that are enabled. + * A present bit enables the specific SOAM LM threshold notification and + * when the specific counter is enabled and the threshold is crossed a + * notification is generated. + * A not present bit disables the specific SOAM LM threshold notification. If + * a particular SOAM LM threshold is not supported the BIT value is not present. + * @return A collection of bit options + */ + Collection thresholdsEnabled(); + + /** + * The measurement two-way delay threshold used to determine if a threshold notification is generated. + * @return A java duration + */ + Duration measuredFrameDelayTwoWay(); + + /** + * The maximum two-way delay threshold used to determine if a threshold notification is generated. + * @return A java duration + */ + Duration maxFrameDelayTwoWay(); + + /** + * The average two-way delay threshold used to determine if a threshold notification is generated. + * @return A java duration + */ + Duration averageFrameDelayTwoWay(); + + /** + * The measurement two-way IFDV threshold used to determine if a threshold notification is generated. + * @return A java duration + */ + Duration measuredInterFrameDelayVariationTwoWay(); + + /** + * The maximum two-way IFDV threshold used to determine if a threshold notification is generated. + * @return A java duration + */ + Duration maxInterFrameDelayVariationTwoWay(); + + /** + * The average two-way IFDV threshold used to determine if a threshold notification is generated. + * @return A java duration + */ + Duration averageInterFrameDelayVariationTwoWay(); + + /** + * The maximum two-way Frame Delay Range threshold used to determine if a threshold notification is generated. + * @return A java duration + */ + Duration maxFrameDelayRangeTwoWay(); + + /** + * The average two-way Frame Delay Range threshold used to determine if a threshold notification is generated. + * @return A java duration + */ + Duration averageFrameDelayRangeTwoWay(); + + /** + * The measurement forward delay threshold used to determine if a threshold notification is generated. + * @return A java duration + */ + Duration measuredFrameDelayForward(); + + /** + * The maximum forward delay threshold used to determine if a threshold notification is generated. + * @return A java duration + */ + Duration maxFrameDelayForward(); + + /** + * The average forward delay threshold used to determine if a threshold notification is generated. + * @return A java duration + */ + Duration averageFrameDelayForward(); + + /** + * The measurement IFDV threshold used to determine if a threshold notification is generated. + * @return A java duration + */ + Duration measuredInterFrameDelayVariationForward(); + + /** + * The maximum IFDV threshold used to determine if a threshold notification is generated. + * @return A java duration + */ + Duration maxInterFrameDelayVariationForward(); + + /** + * The average IFDV threshold used to determine if a threshold notification is generated. + * @return A java duration + */ + Duration averageInterFrameDelayVariationForward(); + + /** + * The maximum Frame Delay Range threshold used to determine if a threshold notification is generated. + * @return A java duration + */ + Duration maxFrameDelayRangeForward(); + + /** + * The average Frame Delay Range threshold used to determine if a threshold notification is generated. + * @return A java duration + */ + Duration averageFrameDelayRangeForward(); + + /** + * The measurement backward delay threshold used to determine if a threshold notification is generated. + * @return A java duration + */ + Duration measuredFrameDelayBackward(); + + /** + * The maximum backward delay threshold used to determine if a threshold notification is generated. + * @return A java duration + */ + Duration maxFrameDelayBackward(); + + /** + * The average backward delay threshold used to determine if a threshold notification is generated. + * @return A java duration + */ + Duration averageFrameDelayBackward(); + + /** + * The measurement backward IFDV threshold used to determine if a threshold notification is generated. + * @return A java duration + */ + Duration measuredInterFrameDelayVariationBackward(); + + /** + * The maximum backward IFDV threshold used to determine if a threshold notification is generated. + * @return A java duration + */ + Duration maxInterFrameDelayVariationBackward(); + + /** + * The average backward IFDV threshold used to determine if a threshold notification is generated. + * @return A java duration + */ + Duration averageInterFrameDelayVariationBackward(); + + /** + * The maximum backward Frame Delay Range threshold used to determine if a threshold notification is generated. + * @return A java duration + */ + Duration maxFrameDelayRangeBackward(); + + /** + * The average backward Frame Delay Range threshold used to determine if a threshold notification is generated. + * @return A java duration + */ + Duration averageFrameDelayRangeBackward(); + + /** + * Builder for {@link org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementThreshold}. + */ + public interface DmThresholdBuilder { + DmThresholdBuilder addToThresholdsEnabled( + ThresholdOption thresholdEnabled); + + DmThresholdBuilder measuredFrameDelayTwoWay( + Duration measuredFrameDelayTwoWay); + + DmThresholdBuilder maxFrameDelayTwoWay(Duration maxFrameDelayTwoWay); + + DmThresholdBuilder averageFrameDelayTwoWay(Duration averageFrameDelayTwoWay); + + DmThresholdBuilder measuredInterFrameDelayVariationTwoWay( + Duration measuredInterFrameDelayVariationTwoWay); + + DmThresholdBuilder maxInterFrameDelayVariationTwoWay( + Duration maxInterFrameDelayVariationTwoWay); + + DmThresholdBuilder averageInterFrameDelayVariationTwoWay( + Duration averageInterFrameDelayVariationTwoWay); + + DmThresholdBuilder maxFrameDelayRangeTwoWay( + Duration maxFrameDelayRangeTwoWay); + + DmThresholdBuilder averageFrameDelayRangeTwoWay( + Duration averageFrameDelayRangeTwoWay); + + DmThresholdBuilder measuredFrameDelayForward( + Duration averageFrameDelayRangeTwoWay); + + DmThresholdBuilder maxFrameDelayForward( + Duration maxFrameDelayForward); + + DmThresholdBuilder averageFrameDelayForward( + Duration averageFrameDelayForward); + + DmThresholdBuilder measuredInterFrameDelayVariationForward( + Duration measuredInterFrameDelayVariationForward); + + DmThresholdBuilder maxInterFrameDelayVariationForward( + Duration maxInterFrameDelayVariationForward); + + DmThresholdBuilder averageInterFrameDelayVariationForward( + Duration averageInterFrameDelayVariationForward); + + DmThresholdBuilder maxFrameDelayRangeForward( + Duration maxFrameDelayRangeForward); + + DmThresholdBuilder averageFrameDelayRangeForward( + Duration averageFrameDelayRangeForward); + + DmThresholdBuilder measuredFrameDelayBackward( + Duration measuredFrameDelayBackward); + + DmThresholdBuilder maxFrameDelayBackward( + Duration maxFrameDelayBackward); + + DmThresholdBuilder averageFrameDelayBackward( + Duration averageFrameDelayBackward); + + DmThresholdBuilder measuredInterFrameDelayVariationBackward( + Duration measuredInterFrameDelayVariationBackward); + + DmThresholdBuilder maxInterFrameDelayVariationBackward( + Duration maxInterFrameDelayVariationBackward); + + DmThresholdBuilder averageInterFrameDelayVariationBackward( + Duration averageInterFrameDelayVariationBackward); + + DmThresholdBuilder maxFrameDelayRangeBackward( + Duration maxFrameDelayRangeBackward); + + DmThresholdBuilder averageFrameDelayRangeBackward( + Duration averageFrameDelayRangeBackward); + + public DelayMeasurementThreshold build(); + + } + + /** + * Selection of Threshold choices. + */ + public enum ThresholdOption { + MEASURED_FRAME_DELAY_TWO_WAY, + MAX_FRAME_DELAY_TWO_WAY, + AVERAGE_FRAME_DELAY_TWO_WAY, + MEASURED_INTER_FRAME_DELAY_VARIATION_TWO_WAY, + MAX_INTER_FRAME_DELAY_VARIATION_TWO_WAY, + AVERAGE_INTER_FRAME_DELAY_VARIATION_TWO_WAY, + MAX_FRAME_DELAY_RANGE_TWO_WAY, + AVERAGE_FRAME_DELAY_RANGE_TWO_WAY, + MEASURED_FRAME_DELAY_FORWARD, + MAX_FRAME_DELAY_FORWARD, + AVERAGE_FRAME_DELAY_FORWARD, + MEASURED_INTER_FRAME_DELAY_VARIATION_FORWARD, + MAX_INTER_FRAME_DELAY_VARIATION_FORWARD, + AVERAGE_INTER_FRAME_DELAY_VARIATION_FORWARD, + MAX_FRAME_DELAY_RANGE_FORWARD, + AVERAGE_FRAME_DELAY_RANGE_FORWARD, + MEASURED_FRAME_DELAY_BACKWARD, + MAX_FRAME_DELAY_BACKWARD, + AVERAGE_FRAME_DELAY_BACKWARD, + MEASURED_INTER_FRAME_DELAY_VARIATION_BACKWARD, + MAX_INTER_FRAME_DELAY_VARIATION_BACKWARD, + AVERAGE_INTER_FRAME_DELAY_VARIATION_BACKWARD, + MAX_FRAME_DELAY_RANGE_BACKWARD, + AVERAGE_FRAME_DELAY_RANGE_BACKWARD; + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/delay/package-info.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/delay/package-info.java new file mode 100644 index 0000000000..310eb12a7c --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/delay/package-info.java @@ -0,0 +1,23 @@ +/* + * 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. + */ + +/** + * Implementation of Service Operation and Maintenance related to Frame delay measurement. + * + * From ITU Y.1731 (ETH-DM) and MEF 17 Frame Delay Performance and Frame Delay Variation Performance + * MEF 36.1 Service OAM SNMP MIB for Performance Monitoring, MEF 39 Service OAM Performance Monitoring YANG Module + */ +package org.onosproject.incubator.net.l2monitoring.soam.delay; \ No newline at end of file diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/DefaultLaStat.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/DefaultLaStat.java new file mode 100644 index 0000000000..0616a5523a --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/DefaultLaStat.java @@ -0,0 +1,262 @@ +/* + * 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.incubator.net.l2monitoring.soam.loss; + +import java.time.Duration; + +import org.onosproject.incubator.net.l2monitoring.soam.MilliPct; + +/** + * The default implementation of {@link org.onosproject.incubator.net.l2monitoring.soam.loss.LossAvailabilityStat}. + */ +public abstract class DefaultLaStat implements LossAvailabilityStat { + private final Duration elapsedTime; + private final boolean suspectStatus; + private final Long forwardHighLoss; + private final Long backwardHighLoss; + private final Long forwardConsecutiveHighLoss; + private final Long backwardConsecutiveHighLoss; + private final Long forwardAvailable; + private final Long backwardAvailable; + private final Long forwardUnavailable; + private final Long backwardUnavailable; + private final MilliPct forwardMinFrameLossRatio; + private final MilliPct forwardMaxFrameLossRatio; + private final MilliPct forwardAverageFrameLossRatio; + private final MilliPct backwardMinFrameLossRatio; + private final MilliPct backwardMaxFrameLossRatio; + private final MilliPct backwardAverageFrameLossRatio; + + protected DefaultLaStat(DefaultLaStatBuilder builder) { + this.elapsedTime = builder.elapsedTime; + this.suspectStatus = builder.suspectStatus; + this.forwardHighLoss = builder.forwardHighLoss; + this.backwardHighLoss = builder.backwardHighLoss; + this.forwardConsecutiveHighLoss = builder.forwardConsecutiveHighLoss; + this.backwardConsecutiveHighLoss = builder.backwardConsecutiveHighLoss; + this.forwardAvailable = builder.forwardAvailable; + this.backwardAvailable = builder.backwardAvailable; + this.forwardUnavailable = builder.forwardUnavailable; + this.backwardUnavailable = builder.backwardUnavailable; + this.forwardMinFrameLossRatio = builder.forwardMinFrameLossRatio; + this.forwardMaxFrameLossRatio = builder.forwardMaxFrameLossRatio; + this.forwardAverageFrameLossRatio = builder.forwardAverageFrameLossRatio; + this.backwardMinFrameLossRatio = builder.backwardMinFrameLossRatio; + this.backwardMaxFrameLossRatio = builder.backwardMaxFrameLossRatio; + this.backwardAverageFrameLossRatio = builder.backwardAverageFrameLossRatio; + } + + @Override + public Duration elapsedTime() { + return elapsedTime; + } + + @Override + public boolean suspectStatus() { + return suspectStatus; + } + + @Override + public Long forwardHighLoss() { + return forwardHighLoss; + } + + @Override + public Long backwardHighLoss() { + return backwardHighLoss; + } + + @Override + public Long forwardConsecutiveHighLoss() { + return forwardConsecutiveHighLoss; + } + + @Override + public Long backwardConsecutiveHighLoss() { + return backwardConsecutiveHighLoss; + } + + @Override + public Long forwardAvailable() { + return forwardAvailable; + } + + @Override + public Long backwardAvailable() { + return backwardAvailable; + } + + @Override + public Long forwardUnavailable() { + return forwardUnavailable; + } + + @Override + public Long backwardUnavailable() { + return backwardUnavailable; + } + + @Override + public MilliPct forwardMinFrameLossRatio() { + return forwardMinFrameLossRatio; + } + + @Override + public MilliPct forwardMaxFrameLossRatio() { + return forwardMaxFrameLossRatio; + } + + @Override + public MilliPct forwardAverageFrameLossRatio() { + return forwardAverageFrameLossRatio; + } + + @Override + public MilliPct backwardMinFrameLossRatio() { + return backwardMinFrameLossRatio; + } + + @Override + public MilliPct backwardMaxFrameLossRatio() { + return backwardMaxFrameLossRatio; + } + + @Override + public MilliPct backwardAverageFrameLossRatio() { + return backwardAverageFrameLossRatio; + } + + /** + * Abstract base class for builders of. + * {@link org.onosproject.incubator.net.l2monitoring.soam.loss.LossAvailabilityStat}. + */ + protected abstract static class DefaultLaStatBuilder implements LaStatBuilder { + private final Duration elapsedTime; + private final boolean suspectStatus; + private Long forwardHighLoss; + private Long backwardHighLoss; + private Long forwardConsecutiveHighLoss; + private Long backwardConsecutiveHighLoss; + private Long forwardAvailable; + private Long backwardAvailable; + private Long forwardUnavailable; + private Long backwardUnavailable; + private MilliPct forwardMinFrameLossRatio; + private MilliPct forwardMaxFrameLossRatio; + private MilliPct forwardAverageFrameLossRatio; + private MilliPct backwardMinFrameLossRatio; + private MilliPct backwardMaxFrameLossRatio; + private MilliPct backwardAverageFrameLossRatio; + + protected DefaultLaStatBuilder(Duration elapsedTime, boolean suspectStatus) { + this.elapsedTime = elapsedTime; + this.suspectStatus = suspectStatus; + } + + @Override + public LaStatBuilder forwardHighLoss(Long forwardHighLoss) { + this.forwardHighLoss = forwardHighLoss; + return this; + } + + @Override + public LaStatBuilder backwardHighLoss(Long backwardHighLoss) { + this.backwardHighLoss = backwardHighLoss; + return this; + } + + @Override + public LaStatBuilder forwardConsecutiveHighLoss( + Long forwardConsecutiveHighLoss) { + this.forwardConsecutiveHighLoss = forwardConsecutiveHighLoss; + return this; + } + + @Override + public LaStatBuilder backwardConsecutiveHighLoss( + Long backwardConsecutiveHighLoss) { + this.backwardConsecutiveHighLoss = backwardConsecutiveHighLoss; + return this; + } + + @Override + public LaStatBuilder forwardAvailable(Long forwardAvailable) { + this.forwardAvailable = forwardAvailable; + return this; + } + + @Override + public LaStatBuilder backwardAvailable(Long backwardAvailable) { + this.backwardAvailable = backwardAvailable; + return this; + } + + @Override + public LaStatBuilder forwardUnavailable(Long forwardUnavailable) { + this.forwardUnavailable = forwardUnavailable; + return this; + } + + @Override + public LaStatBuilder backwardUnavailable(Long backwardUnavailable) { + this.backwardUnavailable = backwardUnavailable; + return this; + } + + @Override + public LaStatBuilder forwardMinFrameLossRatio( + MilliPct forwardMinFrameLossRatio) { + this.forwardMinFrameLossRatio = forwardMinFrameLossRatio; + return this; + } + + @Override + public LaStatBuilder forwardMaxFrameLossRatio( + MilliPct forwardMaxFrameLossRatio) { + this.forwardMaxFrameLossRatio = forwardMaxFrameLossRatio; + return this; + } + + @Override + public LaStatBuilder forwardAverageFrameLossRatio( + MilliPct forwardAverageFrameLossRatio) { + this.forwardAverageFrameLossRatio = forwardAverageFrameLossRatio; + return this; + } + + @Override + public LaStatBuilder backwardMinFrameLossRatio( + MilliPct backwardMinFrameLossRatio) { + this.backwardMinFrameLossRatio = backwardMinFrameLossRatio; + return this; + } + + @Override + public LaStatBuilder backwardMaxFrameLossRatio( + MilliPct backwardMaxFrameLossRatio) { + this.backwardMaxFrameLossRatio = backwardMaxFrameLossRatio; + return this; + } + + @Override + public LaStatBuilder backwardAverageFrameLossRatio( + MilliPct backwardAverageFrameLossRatio) { + this.backwardAverageFrameLossRatio = backwardAverageFrameLossRatio; + return this; + } + } + +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/DefaultLaStatCurrent.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/DefaultLaStatCurrent.java new file mode 100644 index 0000000000..9564ef0641 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/DefaultLaStatCurrent.java @@ -0,0 +1,60 @@ +/* + * 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.incubator.net.l2monitoring.soam.loss; + +import java.time.Duration; +import java.time.Instant; + +/** + * The default implementation of LossAvailabilityStatCurrent. + * {@link org.onosproject.incubator.net.l2monitoring.soam.loss.LossAvailabilityStatCurrent}. + */ +public final class DefaultLaStatCurrent extends DefaultLaStat + implements LossAvailabilityStatCurrent { + private final Instant startTime; + + private DefaultLaStatCurrent(DefaultLaStatCurrentBuilder builder) { + super(builder); + this.startTime = builder.startTime; + } + + @Override + public Instant startTime() { + return startTime; + } + + public static LaStatCurrentBuilder builder(Duration elapsedTime, + boolean suspectStatus, Instant startTime) { + return new DefaultLaStatCurrentBuilder(elapsedTime, suspectStatus, + startTime); + } + + private static final class DefaultLaStatCurrentBuilder + extends DefaultLaStatBuilder implements LaStatCurrentBuilder { + private Instant startTime; + + protected DefaultLaStatCurrentBuilder(Duration elapsedTime, + boolean suspectStatus, Instant startTime) { + super(elapsedTime, suspectStatus); + this.startTime = startTime; + } + + @Override + public LossAvailabilityStatCurrent build() { + return new DefaultLaStatCurrent(this); + } + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/DefaultLaStatHistory.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/DefaultLaStatHistory.java new file mode 100644 index 0000000000..6203bbd566 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/DefaultLaStatHistory.java @@ -0,0 +1,71 @@ +/* + * 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.incubator.net.l2monitoring.soam.loss; + +import java.time.Duration; +import java.time.Instant; + +import org.onosproject.incubator.net.l2monitoring.soam.SoamId; + +/** + * The default implementation of LossAvailabilityStatHistory. + * {@link org.onosproject.incubator.net.l2monitoring.soam.loss.LossAvailabilityStatHistory}. + */ +public final class DefaultLaStatHistory extends DefaultLaStat + implements LossAvailabilityStatHistory { + private final Instant endTime; + private final SoamId historyStatsId; + + private DefaultLaStatHistory(DefaultLaStatHistoryBuilder builder) { + super(builder); + this.endTime = builder.endTime; + this.historyStatsId = builder.historyStatsId; + } + + @Override + public Instant endTime() { + return endTime; + } + + @Override + public SoamId historyStatsId() { + return historyStatsId; + } + + public static LaStatHistoryBuilder builder(Duration elapsedTime, + boolean suspectStatus, SoamId historyStatsId, Instant endTime) { + return new DefaultLaStatHistoryBuilder(elapsedTime, suspectStatus, + historyStatsId, endTime); + } + + private static final class DefaultLaStatHistoryBuilder + extends DefaultLaStatBuilder implements LaStatHistoryBuilder { + private Instant endTime; + private SoamId historyStatsId; + + protected DefaultLaStatHistoryBuilder(Duration elapsedTime, + boolean suspectStatus, SoamId historyStatsId, Instant endTime) { + super(elapsedTime, suspectStatus); + this.historyStatsId = historyStatsId; + this.endTime = endTime; + } + + @Override + public LossAvailabilityStatHistory build() { + return new DefaultLaStatHistory(this); + } + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/DefaultLmCreate.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/DefaultLmCreate.java new file mode 100644 index 0000000000..c735994cd0 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/DefaultLmCreate.java @@ -0,0 +1,182 @@ +/* + * 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.incubator.net.l2monitoring.soam.loss; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.Collection; + +import org.onosproject.incubator.net.l2monitoring.cfm.Mep.Priority; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.soam.DefaultMeasurementCreateBase; +import org.onosproject.incubator.net.l2monitoring.soam.MilliPct; +import org.onosproject.incubator.net.l2monitoring.soam.SoamConfigException; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.Version; + +/** + * The default implementation of {@link org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementCreate}. + */ +public class DefaultLmCreate extends DefaultMeasurementCreateBase + implements LossMeasurementCreate { + + private final LmType lmCfgType; + private final Collection countersEnabled; + private final Duration availabilityMeasurementInterval; + private final Integer availabilityNumberConsecutiveFlrMeasurements; + private final MilliPct availabilityFlrThreshold; + private final Short availabilityNumberConsecutiveIntervals; + private final Short availabilityNumberConsecutiveHighFlr; + private final Collection lossMeasurementThresholds; + + protected DefaultLmCreate(DefaultLmCreateBuilder builder) { + super(builder); + this.lmCfgType = builder.lmCfgType; + this.countersEnabled = builder.countersEnabled; + this.availabilityMeasurementInterval = builder.availabilityMeasurementInterval; + this.availabilityNumberConsecutiveFlrMeasurements = builder.availabilityNumberConsecutiveFlrMeasurements; + this.availabilityFlrThreshold = builder.availabilityFlrThreshold; + this.availabilityNumberConsecutiveIntervals = builder.availabilityNumberConsecutiveIntervals; + this.availabilityNumberConsecutiveHighFlr = builder.availabilityNumberConsecutiveHighFlr; + this.lossMeasurementThresholds = builder.lossMeasurementThresholds; + } + + @Override + public LmType lmCfgType() { + return this.lmCfgType; + } + + @Override + public Collection countersEnabled() { + return this.countersEnabled; + } + + @Override + public Duration availabilityMeasurementInterval() { + return this.availabilityMeasurementInterval; + } + + @Override + public Integer availabilityNumberConsecutiveFlrMeasurements() { + return this.availabilityNumberConsecutiveFlrMeasurements; + } + + @Override + public MilliPct availabilityFlrThreshold() { + return this.availabilityFlrThreshold; + } + + @Override + public Short availabilityNumberConsecutiveIntervals() { + return this.availabilityNumberConsecutiveIntervals; + } + + @Override + public Short availabilityNumberConsecutiveHighFlr() { + return this.availabilityNumberConsecutiveHighFlr; + } + + @Override + public Collection lossMeasurementThreshold() { + return this.lossMeasurementThresholds; + } + + public static LmCreateBuilder builder(Version version, MepId remoteMepId, + Priority priority, LmType lmCfgType) throws SoamConfigException { + return new DefaultLmCreateBuilder(version, remoteMepId, + priority, lmCfgType); + } + + /** + * Implementation of LmCreateBuilder. + * {@link org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementCreate.LmCreateBuilder} + */ + protected static class DefaultLmCreateBuilder extends DefaultMeasCreateBaseBuilder + implements LmCreateBuilder { + private final LmType lmCfgType; + private Collection countersEnabled; + private Duration availabilityMeasurementInterval; + private Integer availabilityNumberConsecutiveFlrMeasurements; + private MilliPct availabilityFlrThreshold; + private Short availabilityNumberConsecutiveIntervals; + private Short availabilityNumberConsecutiveHighFlr; + private Collection lossMeasurementThresholds; + + protected DefaultLmCreateBuilder(Version version, MepId remoteMepId, + Priority priority, LmType lmCfgType) throws SoamConfigException { + super(version, remoteMepId, priority); + this.lmCfgType = lmCfgType; + countersEnabled = new ArrayList<>(); + lossMeasurementThresholds = new ArrayList<>(); + } + + @Override + public LmCreateBuilder addToCountersEnabled( + CounterOption counterOption) { + this.countersEnabled.add(counterOption); + return this; + } + + @Override + public LmCreateBuilder availabilityMeasurementInterval( + Duration availabilityMeasurementInterval) { + this.availabilityMeasurementInterval = availabilityMeasurementInterval; + return this; + } + + @Override + public LmCreateBuilder availabilityNumberConsecutiveFlrMeasurements( + Integer availabilityNumberConsecutiveFlrMeasurements) { + this.availabilityNumberConsecutiveFlrMeasurements = + availabilityNumberConsecutiveFlrMeasurements; + return this; + } + + @Override + public LmCreateBuilder availabilityFlrThreshold( + MilliPct availabilityFlrThreshold) { + this.availabilityFlrThreshold = availabilityFlrThreshold; + return this; + } + + @Override + public LmCreateBuilder availabilityNumberConsecutiveIntervals( + Short availabilityNumberConsecutiveIntervals) + throws SoamConfigException { + this.availabilityNumberConsecutiveIntervals = availabilityNumberConsecutiveIntervals; + return this; + } + + @Override + public LmCreateBuilder availabilityNumberConsecutiveHighFlr( + Short availabilityNumberConsecutiveHighFlr) + throws SoamConfigException { + this.availabilityNumberConsecutiveHighFlr = availabilityNumberConsecutiveHighFlr; + return this; + } + + @Override + public LmCreateBuilder addToLossMeasurementThreshold( + LossMeasurementThreshold lossMeasurementThreshold) { + this.lossMeasurementThresholds.add(lossMeasurementThreshold); + return this; + } + + @Override + public LossMeasurementCreate build() { + return new DefaultLmCreate(this); + } + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/DefaultLmEntry.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/DefaultLmEntry.java new file mode 100644 index 0000000000..3e45303965 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/DefaultLmEntry.java @@ -0,0 +1,220 @@ +/* + * 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.incubator.net.l2monitoring.soam.loss; + +import java.time.Instant; +import java.util.ArrayList; +import java.util.Collection; + +import org.onosproject.incubator.net.l2monitoring.cfm.Mep.Priority; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.soam.MilliPct; +import org.onosproject.incubator.net.l2monitoring.soam.SoamConfigException; +import org.onosproject.incubator.net.l2monitoring.soam.SoamId; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.Version; + +/** + * The default implementation of {@link org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementEntry}. + */ +public final class DefaultLmEntry extends DefaultLmCreate + implements LossMeasurementEntry { + private final SoamId lmId; + private final MilliPct measuredForwardFlr; + private final MilliPct measuredBackwardFlr; + private final AvailabilityType measuredAvailabilityForwardStatus; + private final AvailabilityType measuredAvailabilityBackwardStatus; + private final Instant measuredForwardLastTransitionTime; + private final Instant measuredBackwardLastTransitionTime; + private final LossMeasurementStatCurrent measurementCurrent; + private final Collection measurementHistories; + private final LossAvailabilityStatCurrent availabilityCurrent; + private final Collection availabilityHistories; + + protected DefaultLmEntry(DefaultLmEntryBuilder builder) { + super(builder); + this.lmId = builder.lmId; + this.measuredForwardFlr = builder.measuredForwardFlr; + this.measuredBackwardFlr = builder.measuredBackwardFlr; + this.measuredAvailabilityForwardStatus = builder.measuredAvailabilityForwardStatus; + this.measuredAvailabilityBackwardStatus = builder.measuredAvailabilityBackwardStatus; + this.measuredForwardLastTransitionTime = builder.measuredForwardLastTransitionTime; + this.measuredBackwardLastTransitionTime = builder.measuredBackwardLastTransitionTime; + this.measurementCurrent = builder.measurementCurrent; + this.measurementHistories = builder.measurementHistories; + this.availabilityCurrent = builder.availabilityCurrent; + this.availabilityHistories = builder.availabilityHistories; + } + + @Override + public SoamId lmId() { + return lmId; + } + + @Override + public MilliPct measuredForwardFlr() { + return measuredForwardFlr; + } + + @Override + public MilliPct measuredBackwardFlr() { + return measuredBackwardFlr; + } + + @Override + public AvailabilityType measuredAvailabilityForwardStatus() { + return measuredAvailabilityForwardStatus; + } + + @Override + public AvailabilityType measuredAvailabilityBackwardStatus() { + return measuredAvailabilityBackwardStatus; + } + + @Override + public Instant measuredForwardLastTransitionTime() { + return measuredForwardLastTransitionTime; + } + + @Override + public Instant measuredBackwardLastTransitionTime() { + return measuredBackwardLastTransitionTime; + } + + @Override + public LossMeasurementStatCurrent measurementCurrent() { + return measurementCurrent; + } + + @Override + public Collection measurementHistories() { + return measurementHistories; + } + + @Override + public LossAvailabilityStatCurrent availabilityCurrent() { + return availabilityCurrent; + } + + @Override + public Collection availabilityHistories() { + return availabilityHistories; + } + + public static LmEntryBuilder builder(Version version, MepId remoteMepId, + Priority priority, LmType lmCfgType, SoamId lmId) + throws SoamConfigException { + return new DefaultLmEntryBuilder(version, remoteMepId, + priority, lmCfgType, lmId); + } + + private static final class DefaultLmEntryBuilder extends DefaultLmCreateBuilder + implements LmEntryBuilder { + private final SoamId lmId; + private MilliPct measuredForwardFlr; + private MilliPct measuredBackwardFlr; + private AvailabilityType measuredAvailabilityForwardStatus; + private AvailabilityType measuredAvailabilityBackwardStatus; + private Instant measuredForwardLastTransitionTime; + private Instant measuredBackwardLastTransitionTime; + private LossMeasurementStatCurrent measurementCurrent; + private Collection measurementHistories; + private LossAvailabilityStatCurrent availabilityCurrent; + private Collection availabilityHistories; + + protected DefaultLmEntryBuilder(Version version, MepId remoteMepId, + Priority priority, LmType lmCfgType, SoamId lmId) + throws SoamConfigException { + super(version, remoteMepId, priority, lmCfgType); + this.lmId = lmId; + measurementHistories = new ArrayList<>(); + availabilityHistories = new ArrayList<>(); + } + + @Override + public LmEntryBuilder measuredForwardFlr(MilliPct measuredForwardFlr) { + this.measuredForwardFlr = measuredForwardFlr; + return this; + } + + @Override + public LmEntryBuilder measuredBackwardFlr( + MilliPct measuredBackwardFlr) { + this.measuredBackwardFlr = measuredBackwardFlr; + return this; + } + + @Override + public LmEntryBuilder measuredAvailabilityForwardStatus( + AvailabilityType measuredAvailabilityForwardStatus) { + this.measuredAvailabilityForwardStatus = measuredAvailabilityForwardStatus; + return this; + } + + @Override + public LmEntryBuilder measuredAvailabilityBackwardStatus( + AvailabilityType measuredAvailabilityBackwardStatus) { + this.measuredAvailabilityBackwardStatus = measuredAvailabilityBackwardStatus; + return this; + } + + @Override + public LmEntryBuilder measuredForwardLastTransitionTime( + Instant measuredForwardLastTransitionTime) { + this.measuredForwardLastTransitionTime = measuredForwardLastTransitionTime; + return this; + } + + @Override + public LmEntryBuilder measuredBackwardLastTransitionTime( + Instant measuredBackwardLastTransitionTime) { + this.measuredBackwardLastTransitionTime = measuredBackwardLastTransitionTime; + return this; + } + + @Override + public LmEntryBuilder measurementCurrent( + LossMeasurementStatCurrent measurementCurrent) { + this.measurementCurrent = measurementCurrent; + return this; + } + + @Override + public LmEntryBuilder addToMeasurementHistories( + LossMeasurementStatHistory history) { + this.measurementHistories.add(history); + return this; + } + + @Override + public LmEntryBuilder availabilityCurrent( + LossAvailabilityStatCurrent availabilityCurrent) { + this.availabilityCurrent = availabilityCurrent; + return this; + } + + @Override + public LmEntryBuilder addToAvailabilityHistories( + LossAvailabilityStatHistory history) { + this.availabilityHistories.add(history); + return this; + } + + @Override + public LossMeasurementEntry build() { + return new DefaultLmEntry(this); + } + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/DefaultLmStat.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/DefaultLmStat.java new file mode 100644 index 0000000000..0410e471ef --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/DefaultLmStat.java @@ -0,0 +1,235 @@ +/* + * 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.incubator.net.l2monitoring.soam.loss; + +import java.time.Duration; + +import org.onosproject.incubator.net.l2monitoring.soam.MilliPct; + +/** + * The default implementation of {@link org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementStat}. + */ +public abstract class DefaultLmStat implements LossMeasurementStat { + private final Duration elapsedTime; + private final boolean suspectStatus; + private final Long forwardTransmittedFrames; + private final Long forwardReceivedFrames; + private final MilliPct forwardMinFrameLossRatio; + private final MilliPct forwardMaxFrameLossRatio; + private final MilliPct forwardAverageFrameLossRatio; + private final Long backwardTransmittedFrames; + private final Long backwardReceivedFrames; + private final MilliPct backwardMinFrameLossRatio; + private final MilliPct backwardMaxFrameLossRatio; + private final MilliPct backwardAverageFrameLossRatio; + private final Long soamPdusSent; + private final Long soamPdusReceived; + + protected DefaultLmStat(DefaultLmStatBuilder builder) { + this.elapsedTime = builder.elapsedTime; + this.suspectStatus = builder.suspectStatus; + this.forwardTransmittedFrames = builder.forwardTransmittedFrames; + this.forwardReceivedFrames = builder.forwardReceivedFrames; + this.forwardMinFrameLossRatio = builder.forwardMinFrameLossRatio; + this.forwardMaxFrameLossRatio = builder.forwardMaxFrameLossRatio; + this.forwardAverageFrameLossRatio = builder.forwardAverageFrameLossRatio; + this.backwardTransmittedFrames = builder.backwardTransmittedFrames; + this.backwardReceivedFrames = builder.backwardReceivedFrames; + this.backwardMinFrameLossRatio = builder.backwardMinFrameLossRatio; + this.backwardMaxFrameLossRatio = builder.backwardMaxFrameLossRatio; + this.backwardAverageFrameLossRatio = builder.backwardAverageFrameLossRatio; + this.soamPdusSent = builder.soamPdusSent; + this.soamPdusReceived = builder.soamPdusReceived; + } + + @Override + public Duration elapsedTime() { + return this.elapsedTime; + } + + @Override + public boolean suspectStatus() { + return this.suspectStatus; + } + + @Override + public Long forwardTransmittedFrames() { + return this.forwardTransmittedFrames; + } + + @Override + public Long forwardReceivedFrames() { + return this.forwardReceivedFrames; + } + + @Override + public MilliPct forwardMinFrameLossRatio() { + return this.forwardMinFrameLossRatio; + } + + @Override + public MilliPct forwardMaxFrameLossRatio() { + return this.forwardMaxFrameLossRatio; + } + + @Override + public MilliPct forwardAverageFrameLossRatio() { + return this.forwardAverageFrameLossRatio; + } + + @Override + public Long backwardTransmittedFrames() { + return this.backwardTransmittedFrames; + } + + @Override + public Long backwardReceivedFrames() { + return this.backwardReceivedFrames; + } + + @Override + public MilliPct backwardMinFrameLossRatio() { + return this.backwardMinFrameLossRatio; + } + + @Override + public MilliPct backwardMaxFrameLossRatio() { + return this.backwardMaxFrameLossRatio; + } + + @Override + public MilliPct backwardAverageFrameLossRatio() { + return this.backwardAverageFrameLossRatio; + } + + @Override + public Long soamPdusSent() { + return this.soamPdusSent; + } + + @Override + public Long soamPdusReceived() { + return this.soamPdusReceived; + } + + /** + * Abstract implementation of LmStatBuilder. + * {@link org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementStat.LmStatBuilder} + */ + protected abstract static class DefaultLmStatBuilder implements LmStatBuilder { + private final Duration elapsedTime; + private final boolean suspectStatus; + private Long forwardTransmittedFrames; + private Long forwardReceivedFrames; + private MilliPct forwardMinFrameLossRatio; + private MilliPct forwardMaxFrameLossRatio; + private MilliPct forwardAverageFrameLossRatio; + private Long backwardTransmittedFrames; + private Long backwardReceivedFrames; + private MilliPct backwardMinFrameLossRatio; + private MilliPct backwardMaxFrameLossRatio; + private MilliPct backwardAverageFrameLossRatio; + private Long soamPdusSent; + private Long soamPdusReceived; + + protected DefaultLmStatBuilder(Duration elapsedTime, boolean suspectStatus) { + this.elapsedTime = elapsedTime; + this.suspectStatus = suspectStatus; + } + + @Override + public LmStatBuilder forwardTransmittedFrames( + Long forwardTransmittedFrames) { + this.forwardTransmittedFrames = forwardTransmittedFrames; + return this; + } + + @Override + public LmStatBuilder forwardReceivedFrames(Long forwardReceivedFrames) { + this.forwardReceivedFrames = forwardReceivedFrames; + return this; + } + + @Override + public LmStatBuilder forwardMinFrameLossRatio( + MilliPct forwardMinFrameLossRatio) { + this.forwardMinFrameLossRatio = forwardMinFrameLossRatio; + return this; + } + + @Override + public LmStatBuilder forwardMaxFrameLossRatio( + MilliPct forwardMaxFrameLossRatio) { + this.forwardMaxFrameLossRatio = forwardMaxFrameLossRatio; + return this; + } + + @Override + public LmStatBuilder forwardAverageFrameLossRatio( + MilliPct forwardAverageFrameLossRatio) { + this.forwardAverageFrameLossRatio = forwardAverageFrameLossRatio; + return this; + } + + @Override + public LmStatBuilder backwardTransmittedFrames( + Long backwardTransmittedFrames) { + this.backwardTransmittedFrames = backwardTransmittedFrames; + return this; + } + + @Override + public LmStatBuilder backwardReceivedFrames( + Long backwardReceivedFrames) { + this.backwardReceivedFrames = backwardReceivedFrames; + return this; + } + + @Override + public LmStatBuilder backwardMinFrameLossRatio( + MilliPct backwardMinFrameLossRatio) { + this.backwardMinFrameLossRatio = backwardMinFrameLossRatio; + return this; + } + + @Override + public LmStatBuilder backwardMaxFrameLossRatio( + MilliPct backwardMaxFrameLossRatio) { + this.backwardMaxFrameLossRatio = backwardMaxFrameLossRatio; + return this; + } + + @Override + public LmStatBuilder backwardAverageFrameLossRatio( + MilliPct backwardAverageFrameLossRatio) { + this.backwardAverageFrameLossRatio = backwardAverageFrameLossRatio; + return this; + } + + @Override + public LmStatBuilder soamPdusSent(Long soamPdusSent) { + this.soamPdusSent = soamPdusSent; + return this; + } + + @Override + public LmStatBuilder soamPdusReceived(Long soamPdusReceived) { + this.soamPdusReceived = soamPdusReceived; + return this; + } + } + +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/DefaultLmStatCurrent.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/DefaultLmStatCurrent.java new file mode 100644 index 0000000000..1920845dec --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/DefaultLmStatCurrent.java @@ -0,0 +1,60 @@ +/* + * 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.incubator.net.l2monitoring.soam.loss; + +import java.time.Duration; +import java.time.Instant; + +/** + * The default implementation of LossMeasurementStatCurrent. + * {@link org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementStatCurrent} + */ +public final class DefaultLmStatCurrent extends DefaultLmStat + implements LossMeasurementStatCurrent { + private final Instant startTime; + + protected DefaultLmStatCurrent(DefaultLmStatCurrentBuilder builder) { + super(builder); + this.startTime = builder.startTime; + } + + @Override + public Instant startTime() { + return startTime; + } + + public static LmStatCurrentBuilder builder(Duration elapsedTime, + boolean suspectStatus, Instant startTime) { + return new DefaultLmStatCurrentBuilder(elapsedTime, + suspectStatus, startTime); + } + + private static class DefaultLmStatCurrentBuilder extends DefaultLmStatBuilder + implements LmStatCurrentBuilder { + private final Instant startTime; + + protected DefaultLmStatCurrentBuilder(Duration elapsedTime, + boolean suspectStatus, Instant startTime) { + super(elapsedTime, suspectStatus); + this.startTime = startTime; + } + + @Override + public LossMeasurementStatCurrent build() { + return new DefaultLmStatCurrent(this); + } + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/DefaultLmStatHistory.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/DefaultLmStatHistory.java new file mode 100644 index 0000000000..1109e9221b --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/DefaultLmStatHistory.java @@ -0,0 +1,74 @@ +/* + * 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.incubator.net.l2monitoring.soam.loss; + +import java.time.Duration; +import java.time.Instant; + +import org.onosproject.incubator.net.l2monitoring.soam.SoamId; + +/** + * The default implementation of LossMeasurementStatHistory. + * {@link org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementStatHistory} + */ +public final class DefaultLmStatHistory extends DefaultLmStat + implements LossMeasurementStatHistory { + private final SoamId historyStatsId; + private final Instant endTime; + + protected DefaultLmStatHistory(DefaultLmStatHistoryBuilder builder) { + super(builder); + this.historyStatsId = builder.historyStatsId; + this.endTime = builder.endTime; + } + + @Override + public SoamId historyStatsId() { + return historyStatsId; + } + + + @Override + public Instant endTime() { + return endTime; + } + + public static LmStatHistoryBuilder builder(Duration elapsedTime, + boolean suspectStatus, SoamId historyStatsId, Instant endTime) { + return new DefaultLmStatHistoryBuilder(elapsedTime, + suspectStatus, historyStatsId, endTime); + } + + private static class DefaultLmStatHistoryBuilder extends DefaultLmStatBuilder + implements LmStatHistoryBuilder { + private final SoamId historyStatsId; + private final Instant endTime; + + protected DefaultLmStatHistoryBuilder(Duration elapsedTime, + boolean suspectStatus, SoamId historyStatsId, Instant endTime) { + super(elapsedTime, suspectStatus); + this.historyStatsId = historyStatsId; + this.endTime = endTime; + } + + @Override + public LossMeasurementStatHistory build() { + return new DefaultLmStatHistory(this); + } + } + + +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/DefaultLmThreshold.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/DefaultLmThreshold.java new file mode 100644 index 0000000000..048751625f --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/DefaultLmThreshold.java @@ -0,0 +1,274 @@ +/* + * 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.incubator.net.l2monitoring.soam.loss; + +import java.util.ArrayList; +import java.util.Collection; + +import org.onosproject.incubator.net.l2monitoring.soam.MilliPct; +import org.onosproject.incubator.net.l2monitoring.soam.SoamId; + +/** + * The default implementation of {@link org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementThreshold}. + */ +public final class DefaultLmThreshold implements LossMeasurementThreshold { + + private final SoamId thresholdId; + private final Collection threshold; + private final MilliPct measuredFlrForward; + private final MilliPct maxFlrForward; + private final MilliPct averageFlrForward; + private final MilliPct measuredFlrBackward; + private final MilliPct maxFlrBackward; + private final MilliPct averageFlrBackward; + private final Long forwardHighLoss; + private final Long forwardConsecutiveHighLoss; + private final Long backwardHighLoss; + private final Long backwardConsecutiveHighLoss; + private final Long forwardUnavailableCount; + private final MilliPct forwardAvailableRatio; + private final Long backwardUnavailableCount; + private final MilliPct backwardAvailableRatio; + + private DefaultLmThreshold(DefaultLmThresholdBuilder builder) { + this.thresholdId = builder.thresholdId; + this.threshold = builder.threshold; + this.measuredFlrForward = builder.measuredFlrForward; + this.maxFlrForward = builder.maxFlrForward; + this.averageFlrForward = builder.averageFlrForward; + this.measuredFlrBackward = builder.measuredFlrBackward; + this.maxFlrBackward = builder.maxFlrBackward; + this.averageFlrBackward = builder.averageFlrBackward; + this.forwardHighLoss = builder.forwardHighLoss; + this.forwardConsecutiveHighLoss = builder.forwardConsecutiveHighLoss; + this.backwardHighLoss = builder.backwardHighLoss; + this.backwardConsecutiveHighLoss = builder.backwardConsecutiveHighLoss; + this.forwardUnavailableCount = builder.forwardUnavailableCount; + this.forwardAvailableRatio = builder.forwardAvailableRatio; + this.backwardUnavailableCount = builder.backwardUnavailableCount; + this.backwardAvailableRatio = builder.backwardAvailableRatio; + } + + @Override + public SoamId thresholdId() { + return thresholdId; + } + + @Override + public Collection thresholds() { + return threshold; + } + + @Override + public MilliPct measuredFlrForward() { + return measuredFlrForward; + } + + @Override + public MilliPct maxFlrForward() { + return maxFlrForward; + } + + @Override + public MilliPct averageFlrForward() { + return averageFlrForward; + } + + @Override + public MilliPct measuredFlrBackward() { + return measuredFlrBackward; + } + + @Override + public MilliPct maxFlrBackward() { + return maxFlrBackward; + } + + @Override + public MilliPct averageFlrBackward() { + return averageFlrBackward; + } + + @Override + public Long forwardHighLoss() { + return forwardHighLoss; + } + + @Override + public Long forwardConsecutiveHighLoss() { + return forwardConsecutiveHighLoss; + } + + @Override + public Long backwardHighLoss() { + return backwardHighLoss; + } + + @Override + public Long backwardConsecutiveHighLoss() { + return backwardConsecutiveHighLoss; + } + + @Override + public Long forwardUnavailableCount() { + return forwardUnavailableCount; + } + + @Override + public MilliPct forwardAvailableRatio() { + return forwardAvailableRatio; + } + + @Override + public Long backwardUnavailableCount() { + return backwardUnavailableCount; + } + + @Override + public MilliPct backwardAvailableRatio() { + return backwardAvailableRatio; + } + + public static LmThresholdBuilder builder(SoamId thresholdId) { + return new DefaultLmThresholdBuilder(thresholdId); + } + + private static final class DefaultLmThresholdBuilder implements LmThresholdBuilder { + private final SoamId thresholdId; + private Collection threshold; + private MilliPct measuredFlrForward; + private MilliPct maxFlrForward; + private MilliPct averageFlrForward; + private MilliPct measuredFlrBackward; + private MilliPct maxFlrBackward; + private MilliPct averageFlrBackward; + private Long forwardHighLoss; + private Long forwardConsecutiveHighLoss; + private Long backwardHighLoss; + private Long backwardConsecutiveHighLoss; + private Long forwardUnavailableCount; + private MilliPct forwardAvailableRatio; + private Long backwardUnavailableCount; + private MilliPct backwardAvailableRatio; + + protected DefaultLmThresholdBuilder(SoamId thresholdId) { + this.thresholdId = thresholdId; + threshold = new ArrayList<>(); + } + + @Override + public LmThresholdBuilder addToThreshold(ThresholdOption threshold) { + this.threshold.add(threshold); + return this; + } + + @Override + public LmThresholdBuilder measuredFlrForward(MilliPct measuredFlrForward) { + this.measuredFlrForward = measuredFlrForward; + return this; + } + + @Override + public LmThresholdBuilder maxFlrForward(MilliPct maxFlrForward) { + this.maxFlrForward = maxFlrForward; + return this; + } + + @Override + public LmThresholdBuilder averageFlrForward(MilliPct averageFlrForward) { + this.averageFlrForward = averageFlrForward; + return this; + } + + @Override + public LmThresholdBuilder measuredFlrBackward( + MilliPct measuredFlrBackward) { + this.measuredFlrBackward = measuredFlrBackward; + return this; + } + + @Override + public LmThresholdBuilder maxFlrBackward(MilliPct maxFlrBackward) { + this.maxFlrBackward = maxFlrBackward; + return this; + } + + @Override + public LmThresholdBuilder averageFlrBackward(MilliPct averageFlrBackward) { + this.averageFlrBackward = averageFlrBackward; + return this; + } + + @Override + public LmThresholdBuilder forwardHighLoss(Long forwardHighLoss) { + this.forwardHighLoss = forwardHighLoss; + return this; + } + + @Override + public LmThresholdBuilder forwardConsecutiveHighLoss( + Long forwardConsecutiveHighLoss) { + this.forwardConsecutiveHighLoss = forwardConsecutiveHighLoss; + return this; + } + + @Override + public LmThresholdBuilder backwardHighLoss(Long backwardHighLoss) { + this.backwardHighLoss = backwardHighLoss; + return this; + } + + @Override + public LmThresholdBuilder backwardConsecutiveHighLoss( + Long backwardConsecutiveHighLoss) { + this.backwardConsecutiveHighLoss = backwardConsecutiveHighLoss; + return this; + } + + @Override + public LmThresholdBuilder forwardUnavailableCount( + Long forwardUnavailableCount) { + this.forwardUnavailableCount = forwardUnavailableCount; + return this; + } + + @Override + public LmThresholdBuilder forwardAvailableRatio( + MilliPct forwardAvailableRatio) { + this.forwardAvailableRatio = forwardAvailableRatio; + return this; + } + + @Override + public LmThresholdBuilder backwardUnavailableCount( + Long backwardUnavailableCount) { + this.backwardUnavailableCount = backwardUnavailableCount; + return this; + } + + @Override + public LmThresholdBuilder backwardAvailableRatio( + MilliPct backwardAvailableRatio) { + this.backwardAvailableRatio = backwardAvailableRatio; + return this; + } + + @Override + public LossMeasurementThreshold build() { + return new DefaultLmThreshold(this); + } + } +} \ No newline at end of file diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossAvailabilityStat.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossAvailabilityStat.java new file mode 100644 index 0000000000..09b6e0efda --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossAvailabilityStat.java @@ -0,0 +1,204 @@ +/* + * 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.incubator.net.l2monitoring.soam.loss; + +import java.time.Duration; + +import org.onosproject.incubator.net.l2monitoring.soam.MilliPct; + +/** + * Abstract base interface to represent Loss Availability Stats. + */ +public interface LossAvailabilityStat { + + Duration elapsedTime(); + + /** + * Indicates whether the Measurement Interval has been marked as suspect. + * The object is set to false at the start of a measurement interval. + * Conditions for a discontinuity include, but are not limited to the following: + * 1 - The local time-of-day clock is adjusted by at least 10 seconds + * 2 - The conducting of a performance measurement is halted before the + * current Measurement Interval is completed + * 3 - A local test, failure, or reconfiguration that disrupts service + * @return true when there is a discontinuity in the performance measurements during the Measurement Interval + */ + boolean suspectStatus(); + + /** + * The number of high loss intervals (HLI) over time in the forward direction. + * The value starts at 0 and increments for every HLI that occurs. + * This parameter is equivalent to 'L Sub T' found in MEF 10.2.1 + * @return the number of intervals + */ + Long forwardHighLoss(); + + /** + * The number of high loss intervals (HLI) over time in the backward direction. + * The value starts at 0 and increments for every HLI that occurs. + * This parameter is equivalent to 'L Sub T' found in MEF 10.2.1 + * @return the number of intervals + */ + Long backwardHighLoss(); + + /** + * The number of consecutive high loss intervals (CHLI) over time in the forward direction. + * The value starts at 0 and increments for every HLI that occurs. + * This parameter is equivalent to 'B Sub T' found in MEF 10.2.1 + * @return the number of intervals + */ + Long forwardConsecutiveHighLoss(); + + /** + * The number of consecutive high loss intervals (CHLI) over time in the backward direction. + * The value starts at 0 and increments for every HLI that occurs. + * This parameter is equivalent to 'B Sub T' found in MEF 10.2.1 + * @return the number of intervals + */ + Long backwardConsecutiveHighLoss(); + + /** + * The number of availability indicators during a small time interval. + * evaluated as available (low frame loss) in the forward direction by this + * MEP during this measurement interval. + * @return The number of availability indicators + */ + Long forwardAvailable(); + + /** + * The number of availability indicators during a small time interval. + * evaluated as available (low frame loss) in the backward direction by + * this MEP during this measurement interval. + * @return The number of availability indicators + */ + Long backwardAvailable(); + + /** + * The number of availability indicators during a small time interval. + * evaluated as unavailable (high frame loss) in the forward direction by + * this MEP during this measurement interval + * @return The number of availability indicators + */ + Long forwardUnavailable(); + + /** + * The number of availability indicators during a small time interval. + * evaluated as unavailable (high frame loss) in the backward direction by + * this MEP during this measurement interval + * @return The number of availability indicators + */ + Long backwardUnavailable(); + + /** + * The minimum one-way availability flr in the forward direction,. + * from among the set of availability flr values calculated by the MEP in this Measurement Interval. + * There is one availability flr value for each 'delta_t' time period within + * the Measurement Interval, as specified in MEF 10.2.1. + * The flr value is a ratio that is expressed as a percent with a value of 0 + * (ratio 0.00) through 100000 (ratio 1.00). + * @return The ratio as 1/1000th of a percent, where 1 indicates 0.001 percent + */ + MilliPct forwardMinFrameLossRatio(); + + /** + * The maximum one-way availability flr in the forward direction,. + * from among the set of availability flr values calculated by the MEP in this Measurement Interval. + * There is one availability flr value for each 'delta_t' time period within + * the Measurement Interval, as specified in MEF 10.2.1. + * The flr value is a ratio that is expressed as a percent with a value of 0 + * (ratio 0.00) through 100000 (ratio 1.00). + * @return The ratio as 1/1000th of a percent, where 1 indicates 0.001 percent + */ + MilliPct forwardMaxFrameLossRatio(); + + /** + * The average one-way availability flr in the forward direction,. + * from among the set of availability flr values calculated by the MEP in this Measurement Interval. + * There is one availability flr value for each 'delta_t' time period within + * the Measurement Interval, as specified in MEF 10.2.1. + * The flr value is a ratio that is expressed as a percent with a value of 0 + * (ratio 0.00) through 100000 (ratio 1.00). + * @return The ratio as 1/1000th of a percent, where 1 indicates 0.001 percent + */ + MilliPct forwardAverageFrameLossRatio(); + + /** + * The minimum one-way availability flr in the backward direction,. + * from among the set of availability flr values calculated by the MEP in this Measurement Interval. + * There is one availability flr value for each 'delta_t' time period within + * the Measurement Interval, as specified in MEF 10.2.1. + * The flr value is a ratio that is expressed as a percent with a value of 0 + * (ratio 0.00) through 100000 (ratio 1.00). + * @return The ratio as 1/1000th of a percent, where 1 indicates 0.001 percent + */ + MilliPct backwardMinFrameLossRatio(); + + /** + * The maximum one-way availability flr in the backward direction,. + * from among the set of availability flr values calculated by the MEP in this Measurement Interval. + * There is one availability flr value for each 'delta_t' time period within + * the Measurement Interval, as specified in MEF 10.2.1. + * The flr value is a ratio that is expressed as a percent with a value of 0 + * (ratio 0.00) through 100000 (ratio 1.00). + * @return The ratio as 1/1000th of a percent, where 1 indicates 0.001 percent + */ + MilliPct backwardMaxFrameLossRatio(); + + /** + * The average one-way availability flr in the backward direction,. + * from among the set of availability flr values calculated by the MEP in this Measurement Interval. + * There is one availability flr value for each 'delta_t' time period within + * the Measurement Interval, as specified in MEF 10.2.1. + * The flr value is a ratio that is expressed as a percent with a value of 0 + * (ratio 0.00) through 100000 (ratio 1.00). + * @return The ratio as 1/1000th of a percent, where 1 indicates 0.001 percent + */ + MilliPct backwardAverageFrameLossRatio(); + + /** + * Abstract builder for classes derived from LossAvailabilityStat. + * {@link org.onosproject.incubator.net.l2monitoring.soam.loss.LossAvailabilityStat}. + */ + public interface LaStatBuilder { + LaStatBuilder forwardHighLoss(Long forwardHighLoss); + + LaStatBuilder backwardHighLoss(Long backwardHighLoss); + + LaStatBuilder forwardConsecutiveHighLoss(Long forwardConsecutiveHighLoss); + + LaStatBuilder backwardConsecutiveHighLoss(Long backwardConsecutiveHighLoss); + + LaStatBuilder forwardAvailable(Long forwardAvailable); + + LaStatBuilder backwardAvailable(Long backwardAvailable); + + LaStatBuilder forwardUnavailable(Long forwardUnavailable); + + LaStatBuilder backwardUnavailable(Long backwardUnavailable); + + LaStatBuilder forwardMinFrameLossRatio(MilliPct forwardMinFrameLossRatio); + + LaStatBuilder forwardMaxFrameLossRatio(MilliPct forwardMaxFrameLossRatio); + + LaStatBuilder forwardAverageFrameLossRatio(MilliPct forwardAverageFrameLossRatio); + + LaStatBuilder backwardMinFrameLossRatio(MilliPct backwardMinFrameLossRatio); + + LaStatBuilder backwardMaxFrameLossRatio(MilliPct backwardMaxFrameLossRatio); + + LaStatBuilder backwardAverageFrameLossRatio(MilliPct backwardAverageFrameLossRatio); + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossAvailabilityStatCurrent.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossAvailabilityStatCurrent.java new file mode 100644 index 0000000000..9c1465a264 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossAvailabilityStatCurrent.java @@ -0,0 +1,37 @@ +/* + * 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.incubator.net.l2monitoring.soam.loss; + +import java.time.Instant; + +/** + * Object for representing Loss Availability Stats Current. + * Extends {@link org.onosproject.incubator.net.l2monitoring.soam.loss.LossAvailabilityStat} + */ +public interface LossAvailabilityStatCurrent extends LossAvailabilityStat { + /** + * The time that the current Measurement Interval started. + * @return The start time as a java Instant + */ + Instant startTime(); + + /** + * Builder for {@link org.onosproject.incubator.net.l2monitoring.soam.loss.LossAvailabilityStatCurrent}. + */ + public interface LaStatCurrentBuilder extends LaStatBuilder { + LossAvailabilityStatCurrent build(); + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossAvailabilityStatHistory.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossAvailabilityStatHistory.java new file mode 100644 index 0000000000..49beef5644 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossAvailabilityStatHistory.java @@ -0,0 +1,45 @@ +/* + * 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.incubator.net.l2monitoring.soam.loss; + +import java.time.Instant; + +import org.onosproject.incubator.net.l2monitoring.soam.SoamId; + +/** + * Object for representing Loss Availability Stats History. + * Extends {@link org.onosproject.incubator.net.l2monitoring.soam.loss.LossAvailabilityStat} + */ +public interface LossAvailabilityStatHistory extends LossAvailabilityStat { + /** + * The identifier of the historic measurement. + * @return The id + */ + SoamId historyStatsId(); + + /** + * The time that the historic Measurement Interval ended. + * @return A java Instant + */ + Instant endTime(); + + /** + * Builder for {@link org.onosproject.incubator.net.l2monitoring.soam.loss.LossAvailabilityStatHistory}. + */ + public interface LaStatHistoryBuilder extends LaStatBuilder { + LossAvailabilityStatHistory build(); + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossMeasurementCreate.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossMeasurementCreate.java new file mode 100644 index 0000000000..6dcb3bb69a --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossMeasurementCreate.java @@ -0,0 +1,207 @@ +/* + * 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.incubator.net.l2monitoring.soam.loss; + +import java.time.Duration; +import java.util.Collection; + +import org.onosproject.incubator.net.l2monitoring.soam.MeasurementCreateBase; +import org.onosproject.incubator.net.l2monitoring.soam.MilliPct; +import org.onosproject.incubator.net.l2monitoring.soam.SoamConfigException; + +/** + * Object to support creation of Loss Measurement tests. + */ +public interface LossMeasurementCreate extends MeasurementCreateBase { + /** + * The type of Loss Measurement that will be performed. + * @return A loss Measurement type + */ + LmType lmCfgType(); + + /** + * A vector of bits that indicates the type of SOAM LM counters found. + * in the current-stats and history-stats that are enabled. + * A present bit enables the specific SOAM LM counter. A not present bit disables the SOAM LM counter. + * If a particular SOAM LM counter is not supported the BIT value is not present. + * Not all SOAM LM counters are supported for all SOAM LM types. + * @return A collection of bit options + */ + Collection countersEnabled(); + + /** + * This object specifies the availability measurement interval in minutes. + * A measurement interval of 15 minutes is to be supported, other intervals can be supported + * @return A java Duration + */ + Duration availabilityMeasurementInterval(); + + /** + * Specifies a configurable number of consecutive loss measurement PDUs. + * to be used in evaluating the availability/unavailability status of each + * availability indicator per MEF 10.2.1. + * Loss Measurement PDUs (LMMs, CCMs or SLMs) are sent regularly with a + * period defined by message-period. Therefore, this object, when multiplied + * by message-period, is equivalent to the Availability parameter of 'delta_t' + * as specified by MEF 10.2.1. + * + * If the measurement-type is lmm or ccm, this object defines the number of + * LMM or CCM PDUs transmitted during each 'delta_t' period. The Availability + * flr for a given 'delta_t' can be calculated based on the counters in the + * last LMM/R or CCM during this 'delta_t' and the last LMM/R or CCM in the + * previous 'delta_t'. + * + * If the measurement-type is slm, this object defines the number of SLM PDUs + * transmitted during each 'delta_t' period. The Availability flr for a + * given 'delta_t' is calculated based on the number of those SLM PDUs that are lost. + * + * If the measurement-type is lmm or ccm, the number range of 1 through 10 + * must be supported. The number range of 10 through 1000000 may be supported, + * but is not mandatory. + * + * If the measurement-type is slm, the number range of 10 through 100 must be + * supported. The number range of 100 through 1000000 may be supported, + * but is not mandatory + * @return number of consecutive loss measurement PDUs + */ + Integer availabilityNumberConsecutiveFlrMeasurements(); + + /** + * Specifies a configurable availability threshold to be used in evaluating + * the availability/unavailability status of an availability indicator per + * MEF 10.2.1. The availability threshold range of 0.00 (0) through 1.00 (100000) + * is supported. This parameter is equivalent to the Availability parameter + * of 'C' as specified by MEF 10.2.1. + * @return Units are in milli-percent, where 1 indicates 0.001 percent + */ + MilliPct availabilityFlrThreshold(); + + /** + * Specifies a configurable number of consecutive availability indicators to + * be used to determine a change in the availability status as indicated by + * MEF 10.2.1. This parameter is equivalent to the Availability parameter of + * 'n' as specified by MEF 10.2.1. + * The number range of 1 through 10 must be supported. + * The number range of 1 through 1000 may be supported, but is not mandatory + * @return number of consecutive availability indicators + */ + Short availabilityNumberConsecutiveIntervals(); + + /** + * Specifies a configurable number of consecutive availability indicators. + * to be used for assessing CHLI. This parameter is equivalent to the + * Resilency parameter of 'p' as specified by MEF 10.2.1. + * + * Availability-consecutive-high-flr must be strictly less than + * availability-number-consecutive-intervals. If not, the count of high loss + * intervals over time, and the count of consecutive high loss levels, is disabled. + * + * The number range of 1 through 10 must be supported. The number range of 1 + * through 1000 may be supported, but is not mandatory + * @return number of consecutive availability indicators + */ + Short availabilityNumberConsecutiveHighFlr(); + + /** + * The list of Loss Measurement configuration threshold values for LM Performance Monitoring. + * The main purpose of the threshold configuration list is to configure + * threshold alarm notifications indicating that a specific performance metric + * is not being met + * @return A collection of Loss Measurement Thresholds + */ + Collection lossMeasurementThreshold(); + + /** + * Builder for {@link org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementCreate}. + */ + public interface LmCreateBuilder extends MeasCreateBaseBuilder { + + LmCreateBuilder addToCountersEnabled(CounterOption counterOption); + + LmCreateBuilder availabilityMeasurementInterval( + Duration availabilityMeasurementInterval); + + LmCreateBuilder availabilityNumberConsecutiveFlrMeasurements( + Integer availabilityNumberConsecutiveFlrMeasurements); + + LmCreateBuilder availabilityFlrThreshold(MilliPct availabilityFlrThreshold); + + LmCreateBuilder availabilityNumberConsecutiveIntervals( + Short availabilityNumberConsecutiveIntervals) throws SoamConfigException; + + LmCreateBuilder availabilityNumberConsecutiveHighFlr( + Short availabilityNumberConsecutiveHighFlr) throws SoamConfigException; + + LmCreateBuilder addToLossMeasurementThreshold( + LossMeasurementThreshold lossMeasurementThreshold); + + LossMeasurementCreate build(); + } + + /** + * Enumerated set of Loss Measurement types. + */ + public enum LmType { + /** + * LMM SOAM PDU generated and received LMR responses tracked. + */ + LMLMM, + /** + * SLM SOAM PDU generated and received SLR responses tracked. + */ + LMSLM, + /** + * CCM SOAM PDU generated and received CCM PDUs tracked. + */ + LMCCM; + } + + /** + * Options for Counters that may be enabled. + */ + public enum CounterOption { + FORWARD_TRANSMITTED_FRAMES, + FORWARD_RECEIVED_FRAMES, + FORWARD_MIN_FLR, + FORWARD_MAX_FLR, + FORWARD_AVERAGE_FLR, + BACKWARD_TRANSMITTED_FRAMES, + BACKWARD_RECEIVED_FRAMES, + BACKWARD_MIN_FLR, + BACKWARD_MAX_FLR, + BACKWARD_AVERAGE_FLR, + SOAM_PDUS_SENT, + SOAM_PDUS_RECEIVED, + AVAILABILITY_FORWARD_HIGH_LOSS, + AVAILABILITY_FORWARD_CONSECUTIVE_HIGH_LOSS, + AVAILABILITY_FORWARD_AVAILABLE, + AVAILABILITY_FORWARD_UNAVAILABLE, + AVAILABILILITY_FORWARD_MIN_FLR, + AVAILABILITY_FORWARD_MAX_FLR, + AVAILABILITY_FORWARD_AVERAGE_FLR, + AVAILABILITY_BACKWARD_HIGH_LOSS, + AVAILABILITY_BACKWARD_CONSECUTIVE_HIGH_LOSS, + AVAILABILITY_BACKWARD_AVAILABLE, + AVAILABLE_BACKWARD_UNAVAILABLE, + AVAILABLE_BACKWARD_MIN_FLR, + AVAILABLE_BACKWARD_MAX_FLR, + AVAILABLE_BACKWARD_AVERAGE_FLR, + MEASURED_STATS_FORWARD_MEASURED_FLR, + MEASURED_STATS_BACKWARD_MEASURED_FLR, + MEASURED_STATS_AVAILABILITY_FORWARD_STATUS, + MEASURED_STATS_AVAILABILITY_BACKWARD_STATUS; + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossMeasurementEntry.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossMeasurementEntry.java new file mode 100644 index 0000000000..fb0cecb906 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossMeasurementEntry.java @@ -0,0 +1,157 @@ +/* + * 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.incubator.net.l2monitoring.soam.loss; + +import java.time.Instant; +import java.util.Collection; + +import org.onosproject.incubator.net.l2monitoring.soam.MilliPct; +import org.onosproject.incubator.net.l2monitoring.soam.SoamId; + +/** + * A model of Loss Measurement from ITU Y.1731 Chapter 8.2, MEF 17, MEF 36.1 and MEF 39. + * + * In this model Loss Measurements entries are returned as a collection in the + * MepEntry. In this way Loss Measurements are created by calling on the + * Create Loss Measurement function, passing in any arguments needed to + * configure it. The Loss Measurement is a result and not configured or + * persisted in ONOS, but instead is is passed on to some analytics system. + */ +public interface LossMeasurementEntry extends LossMeasurementCreate { + /** + * Ian id that uniquely identifies a scheduled measurement. + * It is automatically generated by the server on creation of a new measurement + * @return An LM id + */ + SoamId lmId(); + + /** + * Contains the Frame Loss Ratio in the forward direction calculated by this MEP. + * from the last received SOAM PDU. + * The FLR value is a ratio that is expressed as a percent with a value of + * 0 (ratio 0.00) through 100000 (ratio 1.00). + * @return Units are in milli-percent, where 1 indicates 0.001 per-cent + */ + MilliPct measuredForwardFlr(); + + /** + * Contains the Frame Loss Ratio in the backward direction calculated by this MEP. + * from the last received SOAM PDU. + * The FLR value is a ratio that is expressed as a percent with a value of + * 0 (ratio 0.00) through 100000 (ratio 1.00). + * @return Units are in milli-percent, where 1 indicates 0.001 per-cent + */ + MilliPct measuredBackwardFlr(); + + /** + * The availability status (the outcome of the last availability indicator) in the forward direction. + * based upon the last received SOAM PDU + * @return enumerated availability value + */ + AvailabilityType measuredAvailabilityForwardStatus(); + + /** + * The availability status (the outcome of the last availability indicator) in the backward direction. + * based upon the last received SOAM PDU + * @return enumerated availability value + */ + AvailabilityType measuredAvailabilityBackwardStatus(); + + /** + * The time of the last transition between available and unavailable in the forward direction. + * If there have been no transitions since the Loss Measurement Session was + * started, this is set to 0 + * @return The transition time + */ + Instant measuredForwardLastTransitionTime(); + + /** + * The time of the last transition between available and unavailable in the backward direction. + * If there have been no transitions since the Loss Measurement Session was + * started, this is set to 0 + * @return The transition time + */ + Instant measuredBackwardLastTransitionTime(); + + /** + * The results for the current Measurement Interval in a SOAM Loss Measurement session. + * gathered during the interval indicated by measurement-interval + * @return An object with current measurements + */ + LossMeasurementStatCurrent measurementCurrent(); + + /** + * The results for history Measurement Intervals in a SOAM Loss Measurement session. + * @return An object with historic measurements + */ + Collection measurementHistories(); + + /** + * The current results for a SOAM Loss Measurement session for availability statistics. + * gathered during the interval indicated by availability-measurement-interval + * @return An object with current availability + */ + LossAvailabilityStatCurrent availabilityCurrent(); + + /** + * The results for availability history Measurement Intervals in a SOAM Loss Measurement session. + * @return An object with historic availability + */ + Collection availabilityHistories(); + + /** + * Builder for {@link org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementEntry}. + */ + public interface LmEntryBuilder extends LmCreateBuilder { + LmEntryBuilder measuredForwardFlr(MilliPct measuredForwardFlr); + + LmEntryBuilder measuredBackwardFlr(MilliPct measuredBackwardFlr); + + LmEntryBuilder measuredAvailabilityForwardStatus( + AvailabilityType measuredAvailabilityForwardStatus); + + LmEntryBuilder measuredAvailabilityBackwardStatus( + AvailabilityType measuredAvailabilityBackwardStatus); + + LmEntryBuilder measuredForwardLastTransitionTime( + Instant measuredForwardLastTransitionTime); + + LmEntryBuilder measuredBackwardLastTransitionTime( + Instant measuredBackwardLastTransitionTime); + + LmEntryBuilder measurementCurrent( + LossMeasurementStatCurrent measurementCurrent); + + LmEntryBuilder addToMeasurementHistories( + LossMeasurementStatHistory history); + + LmEntryBuilder availabilityCurrent( + LossAvailabilityStatCurrent availabilityCurrent); + + LmEntryBuilder addToAvailabilityHistories(LossAvailabilityStatHistory history); + + LossMeasurementEntry build(); + } + + /** + * Options for Availability test types. + */ + public enum AvailabilityType { + AVAILABLE, + UNAVAILABLE, + UNKNOWN; + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossMeasurementStat.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossMeasurementStat.java new file mode 100644 index 0000000000..f61aab58b8 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossMeasurementStat.java @@ -0,0 +1,172 @@ +/* + * 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.incubator.net.l2monitoring.soam.loss; + +import java.time.Duration; + +import org.onosproject.incubator.net.l2monitoring.soam.MilliPct; + +/** + * Abstract base interface for the creation of Loss Measurement Stat. + * This is the base for {@link org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementStatHistory} + * and {@link org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementStatCurrent} + */ +public interface LossMeasurementStat { + /** + * The time that the current Measurement Interval has been running. + * @return A java Duration + */ + Duration elapsedTime(); + + /** + * The suspect flag for the current measurement interval in which the notification was generated. + * reference MEF-SOAM-PM-MIB.mefSoamPmNotificationObjSuspect"; + * @return true if the measurement might include an error + */ + boolean suspectStatus(); + + /** + * The number of frames transmitted in the forward direction by this MEP. + * For a PM Session of types lmm or ccm this includes Ethernet Service Frames + * and SOAM PDUs that are in a higher MEG level only. + * For a PM Session of type slm this includes the count of SOAM ETH-SLM frames only + * @return The number of frames + */ + Long forwardTransmittedFrames(); + + /** + * The number of frames received in the forward direction by this MEP. + * For a PM Session of types lmm or ccm this includes Ethernet + * Service Frames and SOAM PDUs that are in a higher MEG level only. + * For a PM Session of type slm this includes the count of SOAM ETH-SLM frames only + * @return The number of frames received + */ + Long forwardReceivedFrames(); + + /** + * The minimum one-way frame loss ratio in the forward direction calculated by this MEP for this Interval. + * The FLR value is a ratio that is expressed as a percent with a value of + * 0 (ratio 0.00) through 100000 (ratio 1.00). + * @return Units are in milli-percent, where 1 indicates 0.001 percent + */ + MilliPct forwardMinFrameLossRatio(); + + /** + * The maximum one-way frame loss ratio in the forward direction calculated by this MEP for this Interval. + * The FLR value is a ratio that is expressed as a percent with a value of + * 0 (ratio 0.00) through 100000 (ratio 1.00). + * @return Units are in milli-percent, where 1 indicates 0.001 percent + */ + MilliPct forwardMaxFrameLossRatio(); + + /** + * The average one-way frame loss ratio in the forward direction calculated by this MEP for this Interval. + * The FLR value is a ratio that is expressed as a percent with a value of + * 0 (ratio 0.00) through 100000 (ratio 1.00). + * @return Units are in milli-percent, where 1 indicates 0.001 percent + */ + MilliPct forwardAverageFrameLossRatio(); + + /** + * The number of frames transmitted in the backward direction by this MEP. + * For a PM Session of type lmm or ccm this includes Ethernet Service Frames + * and SOAM PDUs that are in a higher MEG level only. + * For a PM Session of type slm this includes the count of SOAM ETH-SLM frames only + * @return The number of frames + */ + Long backwardTransmittedFrames(); + + /** + * The number of frames received in the backward direction by this MEP. + * For a PM Session of type lmm this includes Ethernet Service Frames and + * SOAM PDUs that are in a higher MEG level only. + * For a PM Session of type slm this includes the count of SOAM ETH-SLM frames only + * @return The number of frames + */ + Long backwardReceivedFrames(); + + /** + * The minimum one-way frame loss ratio in the backward direction. + * calculated by this MEP for this Measurement Interval. The FLR value is a + * ratio that is expressed as a percent with a value of 0 (ratio 0.00) + * through 100000 (ratio 1.00). + * @return Units are in milli-percent, where 1 indicates 0.001 percent + */ + MilliPct backwardMinFrameLossRatio(); + + /** + * The maximum one-way frame loss ratio in the backward direction. + * calculated by this MEP for this Measurement Interval. The FLR value is a + * ratio that is expressed as a percent with a value of 0 (ratio 0.00) + * through 100000 (ratio 1.00). + * @return Units are in milli-percent, where 1 indicates 0.001 percent + */ + MilliPct backwardMaxFrameLossRatio(); + + /** + * The average one-way frame loss ratio in the backward direction. + * calculated by this MEP for this Measurement Interval. The FLR value is a + * ratio that is expressed as a percent with a value of 0 (ratio 0.00) + * through 100000 (ratio 1.00). + * @return Units are in milli-percent, where 1 indicates 0.001 percent + */ + MilliPct backwardAverageFrameLossRatio(); + + /** + * The count of the number of SOAM PDUs sent during this Measurement Interval. + * This object applies when type is lmm, slm or ccm. It indicates the number + * of LMM, CCM, or SLM SOAM frames transmitted + * @return the number of SOAM PDUs sent + */ + Long soamPdusSent(); + + /** + * The count of the number of SOAM PDUs PDUs received in this Measurement Interval. + * This object applies when type is lmm, slm, or ccm. This object indicates + * the number of LMR, CCM, or SLR SOAM frames received + * @return the number of SOAM PDUs PDUs received + */ + Long soamPdusReceived(); + + /** + * Base interface for builders of {@link org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementStat}. + */ + interface LmStatBuilder { + LmStatBuilder forwardTransmittedFrames(Long forwardTransmittedFrames); + + LmStatBuilder forwardReceivedFrames(Long forwardReceivedFrames); + + LmStatBuilder forwardMinFrameLossRatio(MilliPct forwardMinFrameLossRatio); + + LmStatBuilder forwardMaxFrameLossRatio(MilliPct forwardMaxFrameLossRatio); + + LmStatBuilder forwardAverageFrameLossRatio(MilliPct forwardAverageFrameLossRatio); + + LmStatBuilder backwardTransmittedFrames(Long backwardTransmittedFrames); + + LmStatBuilder backwardReceivedFrames(Long backwardReceivedFrames); + + LmStatBuilder backwardMinFrameLossRatio(MilliPct backwardMinFrameLossRatio); + + LmStatBuilder backwardMaxFrameLossRatio(MilliPct backwardMaxFrameLossRatio); + + LmStatBuilder backwardAverageFrameLossRatio(MilliPct backwardAverageFrameLossRatio); + + LmStatBuilder soamPdusSent(Long soamPdusSent); + + LmStatBuilder soamPdusReceived(Long soamPdusReceived); + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossMeasurementStatCurrent.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossMeasurementStatCurrent.java new file mode 100644 index 0000000000..c5b2423c63 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossMeasurementStatCurrent.java @@ -0,0 +1,37 @@ +/* + * 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.incubator.net.l2monitoring.soam.loss; + +import java.time.Instant; + +/** + * Object for representing Loss Availability Stats Current. + * Extends {@link org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementStat} + */ +public interface LossMeasurementStatCurrent extends LossMeasurementStat { + /** + * The time that the current Measurement Interval started. + * @return The start time as a java Instant + */ + Instant startTime(); + + /** + * Builder for {@link org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementStatCurrent}. + */ + public interface LmStatCurrentBuilder extends LmStatBuilder { + LossMeasurementStatCurrent build(); + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossMeasurementStatHistory.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossMeasurementStatHistory.java new file mode 100644 index 0000000000..90c7a5fe3d --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossMeasurementStatHistory.java @@ -0,0 +1,45 @@ +/* + * 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.incubator.net.l2monitoring.soam.loss; + +import java.time.Instant; + +import org.onosproject.incubator.net.l2monitoring.soam.SoamId; + +/** + * Object for representing Loss Measurement Stats History. + * Extends {@link org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementStat} + */ +public interface LossMeasurementStatHistory extends LossMeasurementStat { + /** + * The identifier of the historic measurement. + * @return The id + */ + SoamId historyStatsId(); + + /** + * The time that the historic Measurement Interval ended. + * @return A java Instant + */ + Instant endTime(); + + /** + * Builder for {@link org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementStatHistory}. + */ + public interface LmStatHistoryBuilder extends LmStatBuilder { + LossMeasurementStatHistory build(); + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossMeasurementThreshold.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossMeasurementThreshold.java new file mode 100644 index 0000000000..16242040e6 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossMeasurementThreshold.java @@ -0,0 +1,209 @@ +/* + * 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.incubator.net.l2monitoring.soam.loss; + +import java.util.Collection; + +import org.onosproject.incubator.net.l2monitoring.soam.MilliPct; +import org.onosproject.incubator.net.l2monitoring.soam.SoamId; + +/** + * Object to support the setting of Loss Measurement Thresholds. + * + * The main purpose of the threshold configuration is to configure threshold + * alarm notifications indicating that a specific performance metric is not being met + */ +public interface LossMeasurementThreshold { + /** + * The index of the threshold number for the specific LM threshold entry. + * An index value of '1' needs to be supported. Other index values can also be supported + * @return The threshold Id + */ + SoamId thresholdId(); + + /** + * A vector of bits that indicates the type of SOAM LM thresholds notifications that are enabled. + * A present but enables the specific SOAM LM threshold notification and + * when the specific counter is enabled and the threshold is crossed a + * notification is generated. + * A not present bit disables the specific SOAM LM threshold notification. + * If a particular SOAM LM threshold is not supported the BIT value is not present + * @return A collection of bit options + */ + Collection thresholds(); + + /** + * The measured forward frame loss ratio threshold value. + * that will be used to determine if a threshold notification is generated + * @return Units are in milli-percent, where 1 indicates 0.001 percent + */ + MilliPct measuredFlrForward(); + + /** + * The maximum forward frame loss ratio threshold value. + * that will be used to determine if a threshold notification is generated + * @return Units are in milli-percent, where 1 indicates 0.001 percent + */ + MilliPct maxFlrForward(); + + /** + * The average forward frame loss ratio threshold value. + * that will be used to determine if a threshold notification is generated + * @return Units are in milli-percent, where 1 indicates 0.001 percent + */ + MilliPct averageFlrForward(); + + /** + * The measured backward frame loss ratio threshold value. + * that will be used to determine if a threshold notification is generated + * @return Units are in milli-percent, where 1 indicates 0.001 percent + */ + MilliPct measuredFlrBackward(); + + /** + * The maximum backward frame loss ratio threshold value. + * that will be used to determine if a threshold notification is generated + * @return Units are in milli-percent, where 1 indicates 0.001 percent + */ + MilliPct maxFlrBackward(); + + /** + * The average backward frame loss ratio threshold value. + * that will be used to determine if a threshold notification is generated + * @return Units are in milli-percent, where 1 indicates 0.001 percent + */ + MilliPct averageFlrBackward(); + + /** + * The forward high loss threshold value. + * that will be used to determine if a threshold notification is generated. + * @return The threshold value + */ + Long forwardHighLoss(); + + /** + * The consecutive forward high loss threshold value. + * that will be used to determine if a threshold notification is generated + * @return The threshold value + */ + Long forwardConsecutiveHighLoss(); + + /** + * The backward high loss threshold value. + * that will be used to determine if a threshold notification is generated. + * @return The threshold value + */ + Long backwardHighLoss(); + + /** + * The consecutive backward high loss threshold value. + * that will be used to determine if a threshold notification is generated + * @return The threshold value + */ + Long backwardConsecutiveHighLoss(); + + /** + * The forward unavailability threshold value. + * that will be used to determine if a threshold notification is generated + * @return The threshold value + */ + Long forwardUnavailableCount(); + + /** + * The forward availability/total time ratio threshold value. + * that will be used to determine if a threshold notification is generated + * if the ratio drops below the configured value. + * The ratio value is expressed as a percent with a value of 0 (ratio 0.00) + * through 100000 (ratio 1.00) + * @return Units are in milli-percent, where 1 indicates 0.001 percent + */ + MilliPct forwardAvailableRatio(); + + /** + * The backward unavailability threshold value. + * that will be used to determine if a threshold notification is generated + * @return The threshold value + */ + Long backwardUnavailableCount(); + + /** + * The backward availability/total time ratio threshold value. + * that will be used to determine if a threshold notification is generated + * if the ratio drops below the configured value. + * The ratio value is expressed as a percent with a value of 0 (ratio 0.00) + * through 100000 (ratio 1.00) + * @return Units are in milli-percent, where 1 indicates 0.001 percent + */ + MilliPct backwardAvailableRatio(); + + /** + * Builder for {@link org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementThreshold}. + */ + public interface LmThresholdBuilder { + + LmThresholdBuilder addToThreshold(ThresholdOption threshold); + + LmThresholdBuilder measuredFlrForward(MilliPct measuredFlrForward); + + LmThresholdBuilder maxFlrForward(MilliPct maxFlrForward); + + LmThresholdBuilder averageFlrForward(MilliPct averageFlrForward); + + LmThresholdBuilder measuredFlrBackward(MilliPct measuredFlrBackward); + + LmThresholdBuilder maxFlrBackward(MilliPct maxFlrBackward); + + LmThresholdBuilder averageFlrBackward(MilliPct averageFlrBackward); + + LmThresholdBuilder forwardHighLoss(Long forwardHighLoss); + + LmThresholdBuilder forwardConsecutiveHighLoss(Long forwardConsecutiveHighLoss); + + LmThresholdBuilder backwardHighLoss(Long backwardHighLoss); + + LmThresholdBuilder backwardConsecutiveHighLoss(Long backwardConsecutiveHighLoss); + + LmThresholdBuilder forwardUnavailableCount(Long forwardUnavailableCount); + + LmThresholdBuilder forwardAvailableRatio(MilliPct forwardAvailableRatio); + + LmThresholdBuilder backwardUnavailableCount(Long backwardUnavailableCount); + + LmThresholdBuilder backwardAvailableRatio(MilliPct backwardAvailableRatio); + + LossMeasurementThreshold build(); + } + + /** + * Set of enumerated threshold options. + */ + public enum ThresholdOption { + MEASURED_FLR_FORWARD, + MAX_FLR_FORWARD, + AVERAGE_FLR_FORWARD, + MEASURED_FLR_BACKWARD, + MAX_FLR_BACKWARD, + AVERAGE_FLR_BACKWARD, + FORWARD_HIGH_LOSS, + FORWARD_CONSECUTIVE_HIGH_LOSS, + BACKWARD_HIGH_LOSS, + BACKWARD_CONSECUTIVE_HIGH_LOSS, + FORWARD_UNAVAILABLE_COUNT, + FORWARD_AVAILABLE_RATIO, + BACKWARD_UNAVAILABLE_COUNT, + BACKWARD_AVAILABLE_RATIO; + } +} diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/package-info.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/package-info.java new file mode 100644 index 0000000000..909113a455 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/loss/package-info.java @@ -0,0 +1,23 @@ +/* + * 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. + */ + +/** + * Implementation of Service Operation and Maintenance related to Frame loss measurement. + * + * From ITU Y.1731 (ETH-DM) and MEF 17 Frame Delay Performance and Frame Delay Variation Performance + * MEF 36.1 Service OAM SNMP MIB for Performance Monitoring, MEF 39 Service OAM Performance Monitoring YANG Module + */ +package org.onosproject.incubator.net.l2monitoring.soam.loss; \ No newline at end of file diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/package-info.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/package-info.java new file mode 100644 index 0000000000..a718c8b9d6 --- /dev/null +++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/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. + */ + +/** + * Implementation of MEF Service Operation and Maintenance. + */ +package org.onosproject.incubator.net.l2monitoring.soam; \ No newline at end of file diff --git a/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/ComponentTest.java b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/ComponentTest.java new file mode 100644 index 0000000000..cd71911b34 --- /dev/null +++ b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/ComponentTest.java @@ -0,0 +1,65 @@ +/* + * 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.incubator.net.l2monitoring.cfm; + +import static org.junit.Assert.assertEquals; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.onlab.packet.VlanId; +import org.onosproject.incubator.net.l2monitoring.cfm.Component.IdPermissionType; +import org.onosproject.incubator.net.l2monitoring.cfm.Component.MhfCreationType; + +public class ComponentTest { + Component c1; + + @Before + public void setUp() throws Exception { + c1 = DefaultComponent.builder(1) + .idPermission(IdPermissionType.MANAGE) + .mhfCreationType(MhfCreationType.EXPLICIT) + .addToVidList(VlanId.vlanId((short) 1)) + .addToVidList(VlanId.vlanId((short) 2)) + .addToVidList(VlanId.vlanId((short) 3)) + .build(); + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testComponentId() { + assertEquals(1, c1.componentId()); + } + + @Test + public void testVidList() { + assertEquals(3, c1.vidList().size()); + } + + @Test + public void testMhfCreationType() { + assertEquals(MhfCreationType.EXPLICIT, c1.mhfCreationType()); + } + + @Test + public void testIdPermission() { + assertEquals(IdPermissionType.MANAGE, c1.idPermission()); + } + +} diff --git a/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/MaintenanceAssociationTest.java b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/MaintenanceAssociationTest.java new file mode 100644 index 0000000000..68716dd622 --- /dev/null +++ b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/MaintenanceAssociationTest.java @@ -0,0 +1,136 @@ +/* + * 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.incubator.net.l2monitoring.cfm; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.Collection; + +import org.junit.Before; +import org.junit.Test; +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceAssociation.CcmInterval; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaId2Octet; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdPrimaryVid; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdRfc2685VpnId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; + +public class MaintenanceAssociationTest { + + MaintenanceAssociation ma1; + MaintenanceAssociation ma2; + MaintenanceAssociation ma3; + MaintenanceAssociation ma4; + MaintenanceAssociation ma5; + + @Before + public void setUp() throws Exception { + try { + ma1 = DefaultMaintenanceAssociation.builder(MaIdCharStr.asMaId("ma-1"), 10) + .ccmInterval(CcmInterval.INTERVAL_1MIN) + .maNumericId((short) 1) + .build(); + + ma2 = DefaultMaintenanceAssociation.builder(MaIdPrimaryVid.asMaId("1024"), 10) + .build(); + + ma3 = DefaultMaintenanceAssociation.builder(MaId2Octet.asMaId("33333"), 10) + .build(); + + ma4 = DefaultMaintenanceAssociation.builder(MaIdRfc2685VpnId + .asMaIdHex("0A:0B:0C:0D:0E:0F:00"), 10).build(); + + } catch (CfmConfigException e) { + throw new Exception(e); + } + } + + @Test + public void testMaName() { + assertEquals("ma-1", ma1.maId().maName()); + + assertEquals("1024", ma2.maId().maName()); + + assertEquals("33333", ma3.maId().maName()); + + assertEquals("0A:0B:0C:0D:0E:0F:00".toLowerCase(), ma4.maId().maName()); + } + + @Test + public void testCcmInterval() { + assertEquals(CcmInterval.INTERVAL_1MIN, ma1.ccmInterval()); + } + + @Test + public void testComponentList() { + assertNotNull(ma1.componentList()); + } + + @Test + public void testWithComponentList() { + Collection componentList2 = new ArrayList<>(); + MaintenanceAssociation ma2 = ma1.withComponentList(componentList2); + assertNotNull(ma2.componentList()); + } + + @Test + public void testRemoteMepIdList() { + assertNotNull(ma1.remoteMepIdList()); + } + + @Test + public void testWithRemoteMepIdList() throws CfmConfigException { + Collection remoteMepIdList2 = new ArrayList<>(); + remoteMepIdList2.add(MepId.valueOf((short) 450)); + remoteMepIdList2.add(MepId.valueOf((short) 451)); + remoteMepIdList2.add(MepId.valueOf((short) 452)); + MaintenanceAssociation ma2 = ma1.withRemoteMepIdList(remoteMepIdList2); + assertEquals(3, ma2.remoteMepIdList().size()); + } + + @Test + public void testMaNumericId() { + assertEquals(1, ma1.maNumericId()); + } + + @Test + public void testCopyThroughBuilder() throws CfmConfigException { + MaintenanceAssociation maCopy = + DefaultMaintenanceAssociation.builder(ma3).build(); + assertEquals(ma3, maCopy); + } + + @Test + public void testEquals() { + //For char string + assertFalse(ma1.equals(null)); + assertFalse(ma1.equals(new String("test"))); + + assertTrue(ma1.equals(ma1)); + assertFalse(ma1.equals(ma2)); + } + + @Test + public void testHashCode() { + assertEquals(ma1.hashCode(), ma1.hashCode()); + } + +} diff --git a/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/MaintenanceDomainTest.java b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/MaintenanceDomainTest.java new file mode 100644 index 0000000000..74e076ca64 --- /dev/null +++ b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/MaintenanceDomainTest.java @@ -0,0 +1,153 @@ +/* + * 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.incubator.net.l2monitoring.cfm; + +import java.util.Collection; + +import org.junit.Before; +import org.junit.Test; +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain.MdLevel; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdDomainName; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdMacUint; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdNone; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; + +import static org.junit.Assert.*; + +public class MaintenanceDomainTest { + + MaintenanceDomain md1; + MaintenanceDomain md2; + MaintenanceDomain md3; + MaintenanceDomain md4; + + @Before + public void setUp() { + + try { + MaintenanceAssociation ma1 = + DefaultMaintenanceAssociation + .builder(MaIdCharStr.asMaId("ma-1-1"), 4) + .build(); + + md1 = DefaultMaintenanceDomain.builder(MdIdCharStr.asMdId("md-1")) + .mdLevel(MdLevel.LEVEL3) + .addToMaList(ma1) + .mdNumericId((short) 1) + .build(); + + md2 = DefaultMaintenanceDomain.builder(MdIdDomainName.asMdId("test1.onosproject.org")) + .mdLevel(MdLevel.LEVEL4) + .build(); + + md3 = DefaultMaintenanceDomain.builder(MdIdMacUint.asMdId("00:11:22:33:44:55:8191")) + .mdLevel(MdLevel.LEVEL5) + .build(); + + md4 = DefaultMaintenanceDomain.builder(MdIdNone.asMdId()) + .build(); + + } catch (CfmConfigException e) { + fail("Unexpected exception " + e.getMessage()); + } + } + + @Test + public void testMdNameType() { + assertEquals("md-1", md1.mdId().mdName()); + assertEquals(MdIdCharStr.class, md1.mdId().getClass()); + assertEquals(4, md1.mdId().getNameLength()); + + assertEquals("test1.onosproject.org", md2.mdId().mdName()); + assertEquals(MdIdDomainName.class, md2.mdId().getClass()); + assertEquals(21, md2.mdId().getNameLength()); + + assertEquals("00:11:22:33:44:55:8191", md3.mdId().mdName()); + assertEquals(MdIdMacUint.class, md3.mdId().getClass()); + assertEquals(8, md3.mdId().getNameLength()); + + assertEquals(null, md4.mdId().mdName()); + assertEquals(MdIdNone.class, md4.mdId().getClass()); + assertEquals(0, md4.mdId().getNameLength()); + } + + @Test + public void testMdLevel() { + assertEquals(MdLevel.LEVEL3, md1.mdLevel()); + assertEquals(MdLevel.LEVEL4, md2.mdLevel()); + assertEquals(MdLevel.LEVEL5, md3.mdLevel()); + assertEquals(MdLevel.LEVEL0, md4.mdLevel()); + } + + @Test + public void testMaintenanceAssociationList() { + assertEquals(1, md1.maintenanceAssociationList().size()); + + assertEquals(0, md2.maintenanceAssociationList().size()); + } + + @Test + public void testWithMaintenanceAssociationList() throws CfmConfigException { + Collection maList = md1.maintenanceAssociationList(); + maList.add(DefaultMaintenanceAssociation + .builder(MaIdCharStr.asMaId("ma-1-2"), 4) + .build()); + + md1 = md1.withMaintenanceAssociationList(maList); + assertEquals(2, md1.maintenanceAssociationList().size()); + } + + @Test + public void testMdNumericid() throws CfmConfigException { + assertEquals(1, md1.mdNumericId()); + } + + @Test + public void testEquals() throws CfmConfigException { + assertFalse(md1.equals(md2)); + + assertFalse(md1.equals(null)); + + assertFalse(md1.equals(new String("test"))); + } + + @Test + public void testHashCode() throws CfmConfigException { + assertFalse(md1.hashCode() == md2.hashCode()); + + assertTrue(md1.hashCode() == md1.hashCode()); + } + + @Test + public void testCopyToBuilder() throws CfmConfigException { + MaintenanceDomain mdCopy = DefaultMaintenanceDomain.builder(md1).build(); + + assertEquals(md1, mdCopy); + } + + @Test + public void testToString() { + assertEquals("DefaultMaintenanceDomain{mdId=md-1, level=LEVEL3}", + md1.toString()); + assertEquals("DefaultMaintenanceDomain{mdId=test1.onosproject.org, level=LEVEL4}", + md2.toString()); + assertEquals("DefaultMaintenanceDomain{mdId=00:11:22:33:44:55:8191, level=LEVEL5}", + md3.toString()); + assertEquals("DefaultMaintenanceDomain{mdId=, level=LEVEL0}", md4.toString()); + } +} diff --git a/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/MepLbCreateTest.java b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/MepLbCreateTest.java new file mode 100644 index 0000000000..e415a84380 --- /dev/null +++ b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/MepLbCreateTest.java @@ -0,0 +1,80 @@ +/* + * 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.incubator.net.l2monitoring.cfm; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import org.junit.Before; +import org.junit.Test; +import org.onlab.packet.MacAddress; +import org.onlab.util.HexString; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep.Priority; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; + +public class MepLbCreateTest { + + MepLbCreate lb1; + MepLbCreate lb2; + + @Before + public void setUp() throws Exception { + lb1 = DefaultMepLbCreate + .builder(MacAddress.valueOf("aa:bb:cc:dd:ee:ff")) + .numberMessages(5) + .dataTlv(new byte[]{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}) + .vlanPriority(Priority.PRIO3) + .vlanDropEligible(true) + .build(); + lb2 = DefaultMepLbCreate + .builder(MepId.valueOf((short) 12)) + .build(); + + } + + @Test + public void testRemoteMepAddress() { + assertEquals("aa:bb:cc:dd:ee:ff".toUpperCase(), + lb1.remoteMepAddress().toString()); + assertNull(lb1.remoteMepId()); + } + + @Test + public void testRemoteMepId() { + assertEquals(12, lb2.remoteMepId().id().intValue()); + assertNull(lb2.remoteMepAddress()); + } + + @Test + public void testNumberMessages() { + assertEquals(5, lb1.numberMessages().intValue()); + } + + @Test + public void testDataTlv() { + assertEquals(0x06, HexString.fromHexString(lb1.dataTlvHex())[5]); + } + + @Test + public void testVlanPriority() { + assertEquals(3, lb1.vlanPriority().ordinal()); + } + + @Test + public void testVlanDropElegible() { + assertEquals(true, lb1.vlanDropEligible()); + } +} diff --git a/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/MepLbEntryTest.java b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/MepLbEntryTest.java new file mode 100644 index 0000000000..47ef5b3bd2 --- /dev/null +++ b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/MepLbEntryTest.java @@ -0,0 +1,69 @@ +/* + * 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.incubator.net.l2monitoring.cfm; + +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.Test; + +public class MepLbEntryTest { + + MepLbEntry lbResult; + + @Before + public void setUp() throws Exception { + lbResult = DefaultMepLbEntry.builder() + .countLbrMacMisMatch(987654321L) + .countLbrReceived(987654322L) + .countLbrTransmitted(987654323L) + .countLbrValidInOrder(987654324L) + .countLbrValidOutOfOrder(987654325L) + .nextLbmIdentifier(987654326L) + .build(); + } + + @Test + public void testNextLbmIdentifier() { + assertEquals(987654326L, lbResult.nextLbmIdentifier()); + } + + @Test + public void testCountLbrTransmitted() { + assertEquals(987654323L, lbResult.countLbrTransmitted()); + } + + @Test + public void testCountLbrReceived() { + assertEquals(987654322L, lbResult.countLbrReceived()); + } + + @Test + public void testCountLbrValidInOrder() { + assertEquals(987654324L, lbResult.countLbrValidInOrder()); + } + + @Test + public void testCountLbrValidOutOfOrder() { + assertEquals(987654325L, lbResult.countLbrValidOutOfOrder()); + } + + @Test + public void testCountLbrMacMisMatch() { + assertEquals(987654321L, lbResult.countLbrMacMisMatch()); + } + +} diff --git a/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/MepTest.java b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/MepTest.java new file mode 100644 index 0000000000..eee1f979ce --- /dev/null +++ b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/MepTest.java @@ -0,0 +1,275 @@ +/* + * 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.incubator.net.l2monitoring.cfm; + +import java.time.Duration; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.onlab.packet.IpAddress; +import org.onlab.packet.VlanId; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMep.DefaultMepBuilder; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep.FngAddress; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep.FngAddressType; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep.LowestFaultDefect; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep.MepDirection; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep.Priority; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; +import org.onosproject.net.DeviceId; +import org.onosproject.net.PortNumber; + +import static org.junit.Assert.*; + +public class MepTest { + private Mep mep1; + + @Before + public void setUp() throws Exception { + try { + mep1 = DefaultMep.builder(MepId.valueOf((short) 1), + DeviceId.deviceId("of:12345678"), + PortNumber.portNumber(0), + MepDirection.UP_MEP, + MdIdCharStr.asMdId("md-1"), + MaIdCharStr.asMaId("ma-1-1")) + .primaryVid(VlanId.vlanId((short) 1000)) + .administrativeState(true) + .cciEnabled(true) + .ccmLtmPriority(Priority.PRIO6) + .fngAddress(FngAddress.ipV4Address(IpAddress.valueOf("10.2.3.1"))) + .lowestFaultPriorityDefect(LowestFaultDefect.ERROR_FD_PLUS) + .defectPresentTime(Duration.ofSeconds(1)) + .defectAbsentTime(Duration.ofSeconds(2)) + .build(); + } catch (CfmConfigException e) { + throw new Exception(e); + } + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void testPortError() { + try { + DefaultMep.builder(MepId.valueOf((short) 1), + DeviceId.deviceId("of:12345678"), + PortNumber.FLOOD, + MepDirection.UP_MEP, + MdIdCharStr.asMdId("md-1"), + MaIdCharStr.asMaId("ma-1-1")) + .build(); + fail("Port = FLOOD should throw exception"); + } catch (CfmConfigException e) { + assertTrue(e.getMessage().contains("Port must be physical")); + } + } + + @Test + public void testMdNameErrorNull() { + try { + DefaultMep.builder(MepId.valueOf((short) 1), + DeviceId.deviceId("of:12345678"), + PortNumber.portNumber(0), + MepDirection.UP_MEP, + null, + MaIdCharStr.asMaId("ma-1-1")) + .build(); + fail("Null md Name should throw exception"); + } catch (CfmConfigException e) { + assertTrue(e.getMessage().contains("MdId is null")); + } + } + + @Test + public void testMaNameErrorNull() { + try { + DefaultMep.builder(MepId.valueOf((short) 1), + DeviceId.deviceId("of:12345678"), + PortNumber.portNumber(0), + MepDirection.UP_MEP, + MdIdCharStr.asMdId("md-1"), + null) + .build(); + fail("Null ma Name should throw exception"); + } catch (CfmConfigException e) { + assertTrue(e.getMessage().contains("MaId is null")); + } + } + + @Test + public void testMepCopyConstructor() throws CfmConfigException { + Mep mep2 = (new DefaultMepBuilder(mep1)).build(); + assertEquals(1, mep2.mepId().value()); + assertEquals("md-1", mep2.mdId().mdName()); + } + + @Test + public void testMepId() { + assertEquals(1, mep1.mepId().value()); + } + + @Test + public void testDeviceId() { + assertEquals("of:12345678", mep1.deviceId().toString()); + } + + @Test + public void testPort() { + assertEquals(0, mep1.port().toLong()); + } + + @Test + public void testDirection() { + assertEquals(MepDirection.UP_MEP, mep1.direction()); + } + + @Test + public void testPrimaryVid() { + assertEquals(1000, mep1.primaryVid().id().intValue()); + } + + @Test + public void testAdministrativeState() { + assertTrue(mep1.administrativeState()); + } + + @Test + public void testWithAdministrativeState() { + Mep mep2 = mep1.withAdministrativeState(false); + assertFalse(mep2.administrativeState()); + assertEquals(1, mep2.mepId().value()); + } + + @Test + public void testCciEnabled() { + assertTrue(mep1.cciEnabled()); + } + + @Test + public void testWithCciEnabled() { + Mep mep2 = mep1.withCciEnabled(false); + assertFalse(mep2.cciEnabled()); + } + + @Test + public void testCcmLtmPriority() { + assertEquals(6, mep1.ccmLtmPriority().ordinal()); + } + + @Test + public void testWithCcmLtmPriority() throws CfmConfigException { + Mep mep2 = mep1.withCcmLtmPriority(Priority.PRIO5); + assertEquals(5, mep2.ccmLtmPriority().ordinal()); + assertEquals(1, mep2.mepId().value()); + } + + @Test + public void testWithFngAddress() { + Mep mep2 = mep1.withFngAddress(FngAddress.ipV4Address(IpAddress.valueOf("10.2.3.2"))); + assertEquals(FngAddressType.IPV4, mep2.fngAddress().addressType()); + assertEquals(IpAddress.valueOf("10.2.3.2"), mep2.fngAddress().ipAddress()); + } + + @Test + public void testFngAddress() { + assertEquals(FngAddressType.IPV4, mep1.fngAddress().addressType()); + assertEquals(IpAddress.valueOf("10.2.3.1"), mep1.fngAddress().ipAddress()); + } + + @Test + public void testLowestFaultPriorityDefect() { + assertEquals(LowestFaultDefect.ERROR_FD_PLUS, mep1.lowestFaultPriorityDefect()); + } + + @Test + public void testWithLowestFaultPriorityDefect() { + Mep mep2 = mep1.withLowestFaultPriorityDefect(LowestFaultDefect.XCON_FD_ONLY); + assertEquals(LowestFaultDefect.XCON_FD_ONLY, mep2.lowestFaultPriorityDefect()); + } + + @Test + public void testDefectPresetTime() { + assertEquals(1000, mep1.defectPresentTime().toMillis()); + } + + @Test + public void testWithDefectPresentTime() { + Mep mep2 = mep1.withDefectPresentTime(Duration.ofMillis(1500L)); + assertEquals(1500, mep2.defectPresentTime().toMillis()); + } + + @Test + public void testDefectAbsentTime() { + assertEquals(2000, mep1.defectAbsentTime().toMillis()); + } + + @Test + public void testWithDefectAbsentTime() { + Mep mep2 = mep1.withDefectAbsentTime(Duration.ofMillis(2500L)); + assertEquals(2500, mep2.defectAbsentTime().toMillis()); + } + + @Test + public void testEqualsObject() throws CfmConfigException { + Mep mep2 = mep1.withPrimaryVid(VlanId.vlanId((short) 5)); + assertNotEquals(mep1, mep2); + } + + @Test + public void testMepToString() { + assertEquals(mep1.toString(), "DefaultMep{" + + "mepId=1, " + + "deviceId=of:12345678, " + + "port=0, " + + "direction=UP_MEP, " + + "mdId=md-1, " + + "maId=ma-1-1, " + + "primaryVid=1000, " + + "administrativeState=true, " + + "cciEnabled=true, " + + "ccmLtmPriority=PRIO6, " + + "fngAddress=FngAddress{addressType=IPV4, ipAddress=10.2.3.1}, " + + "lowestFaultPriorityDefect=ERROR_FD_PLUS, " + + "defectPresentTime=PT1S, " + + "defectAbsentTime=PT2S}"); + } + + @Test + public void testEquality() throws CfmConfigException { + assertFalse(mep1.equals(null)); + assertTrue(mep1.equals(mep1)); + assertFalse(mep1.equals(new String("test"))); + + Mep mep2 = new DefaultMepBuilder(mep1).build(); + assertTrue(mep1.equals(mep2)); + assertEquals(mep1.hashCode(), mep2.hashCode()); + + Mep mep3 = DefaultMep.builder(MepId.valueOf((short) 2), + DeviceId.deviceId("of:12345680"), + PortNumber.portNumber(0), + MepDirection.UP_MEP, + MdIdCharStr.asMdId("md-3"), + MaIdCharStr.asMaId("ma-3-3")) + .build(); + assertFalse(mep1.equals(mep3)); + } +} diff --git a/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/RemoteMepEntryTest.java b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/RemoteMepEntryTest.java new file mode 100644 index 0000000000..9ec1029776 --- /dev/null +++ b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/RemoteMepEntryTest.java @@ -0,0 +1,89 @@ +/* + * 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.incubator.net.l2monitoring.cfm; + +import static org.junit.Assert.assertEquals; + +import java.time.Duration; + +import org.junit.Before; +import org.junit.Test; +import org.onlab.packet.MacAddress; +import org.onosproject.incubator.net.l2monitoring.cfm.RemoteMepEntry.InterfaceStatusTlvType; +import org.onosproject.incubator.net.l2monitoring.cfm.RemoteMepEntry.PortStatusTlvType; +import org.onosproject.incubator.net.l2monitoring.cfm.RemoteMepEntry.RemoteMepState; +import org.onosproject.incubator.net.l2monitoring.cfm.SenderIdTlv.SenderIdTlvType; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; + +public class RemoteMepEntryTest { + + RemoteMepEntry rmep1; + + @Before + public void setUp() throws Exception, CfmConfigException { + rmep1 = DefaultRemoteMepEntry + .builder(MepId.valueOf((short) 1), RemoteMepState.RMEP_IDLE) + .failedOrOkTime(Duration.ofSeconds(5)) + .macAddress(MacAddress.valueOf("AA:BB:CC:DD:EE:FF")) + .rdi(true) + .portStatusTlvType(PortStatusTlvType.PS_UP) + .interfaceStatusTlvType(InterfaceStatusTlvType.IS_UP) + .senderIdTlvType(SenderIdTlvType.SI_MAC_ADDRESS) + .build(); + } + + @Test + public void testRemoteMepId() { + assertEquals(1, rmep1.remoteMepId().value()); + } + + @Test + public void testState() { + assertEquals(RemoteMepState.RMEP_IDLE, rmep1.state()); + } + + @Test + public void testFailedOrOkTime() { + assertEquals(5, rmep1.failedOrOkTime().getSeconds()); + } + + @Test + public void testMacAddress() { + assertEquals("AA:BB:CC:DD:EE:FF", rmep1.macAddress().toString()); + } + + @Test + public void testRdi() { + assertEquals(true, rmep1.rdi()); + } + + @Test + public void testPortStatusTlvType() { + assertEquals(PortStatusTlvType.PS_UP, rmep1.portStatusTlvType()); + } + + @Test + public void testInterfaceStatusTlvType() { + assertEquals(InterfaceStatusTlvType.IS_UP, rmep1.interfaceStatusTlvType()); + } + + @Test + public void testSenderIdTlvType() { + assertEquals(SenderIdTlvType.SI_MAC_ADDRESS, rmep1.senderIdTlvType()); + } + +} diff --git a/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MaIdShortTest.java b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MaIdShortTest.java new file mode 100644 index 0000000000..970e6a0dcc --- /dev/null +++ b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MaIdShortTest.java @@ -0,0 +1,207 @@ +/* + * 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.incubator.net.l2monitoring.cfm.identifier; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import org.junit.Before; +import org.junit.Test; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; + +public class MaIdShortTest { + + MaIdShort maId1; + MaIdShort maId2; + MaIdShort maId3; + MaIdShort maId4; + MaIdShort maId5; + + @Before + public void setUp() throws Exception, CfmConfigException { + maId1 = MaIdCharStr.asMaId("ma-1-1"); + maId2 = MaIdPrimaryVid.asMaId((short) 1234); + maId3 = MaId2Octet.asMaId(33333); + maId4 = MaIdRfc2685VpnId.asMaIdHex("aa:BB:cc:DD:ee:ff:11"); + maId5 = MaIdIccY1731.asMaId("ABC", "DEFGHIJK"); + } + + @Test + public void testMaName() { + assertEquals("ma-1-1", maId1.maName()); + assertEquals("1234", maId2.maName()); + assertEquals("33333", maId3.maName()); + assertEquals("aa:BB:cc:DD:ee:ff:11".toLowerCase(), maId4.maName()); + assertEquals("ABCDEFGHIJK", maId5.maName()); + } + + @Test + public void testGetNameLength() { + assertEquals(6, maId1.getNameLength()); + assertEquals(2, maId2.getNameLength()); + assertEquals(2, maId3.getNameLength()); + assertEquals(7, maId4.getNameLength()); + assertEquals(11, maId5.getNameLength()); + } + + @Test + public void testMaNameWrong() { + try { + MaIdCharStr.asMaId(null); + fail("Expected exception"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().contains("MA Name must follow pattern")); + } + + try { + MaIdCharStr.asMaId(""); + fail("Expected exception"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().contains("MA Name must follow pattern")); + } + + try { + MaIdCharStr.asMaId("This is a name with spaces - not allowed"); + fail("Expected exception"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().contains("MA Name must follow pattern")); + } + + try { + MaIdCharStr.asMaId("This-name-is-too-long-at-forty-eight-characters-in-total"); + fail("Expected exception"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().contains("MA Name must follow pattern")); + } + + + try { + MaIdPrimaryVid.asMaId("abcdef"); + fail("Expected exception"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().contains("MA Name must be numeric")); + } + + try { + MaIdPrimaryVid.asMaId("-20"); + fail("Expected exception"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().contains("MA Id must be between 0 and 4095")); + } + + try { + MaIdPrimaryVid.asMaId("5000"); + fail("Expected exception"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().contains("MA Id must be between 0 and 4095")); + } + + + try { + MaId2Octet.asMaId("abcdef"); + fail("Expected exception"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().contains("MA Name must be numeric")); + } + + try { + MaId2Octet.asMaId("-20"); + fail("Expected exception"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().contains("MA Id must be between 0 and 65535")); + } + + try { + MaId2Octet.asMaId("70000"); + fail("Expected exception"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().contains("MA Id must be between 0 and 65535")); + } + + + try { + MaIdRfc2685VpnId.asMaIdHex("aa:bb:cc:dd:ee:ff"); //Need 7 + fail("Expected exception"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().contains("MA Name must follow pattern")); + } + + try { + MaIdIccY1731.asMaId("ABCDEFG", "HIJKL"); //7 too long for ICC + fail("Expected exception"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().contains("ICC part must follow pattern")); + } + + try { + MaIdIccY1731.asMaId("A", "BCDEFGHIJKLMNO"); //14 too long for UMC + fail("Expected exception"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().contains("UMC part must follow pattern")); + } + + } + + @Test + public void testEquals() { + //For char string + assertFalse(maId1.equals(null)); + assertFalse(maId1.equals(new String("test"))); + + assertTrue(maId1.equals(maId1)); + assertFalse(maId1.equals(maId2)); + + //For primary vid + assertFalse(maId2.equals(null)); + assertFalse(maId2.equals(new String("test"))); + + assertTrue(maId2.equals(maId2)); + assertFalse(maId2.equals(maId1)); + + //For 2 octet + assertFalse(maId3.equals(null)); + assertFalse(maId3.equals(new String("test"))); + + assertTrue(maId3.equals(maId3)); + assertFalse(maId3.equals(maId1)); + + //rfc2685vpn + assertFalse(maId4.equals(null)); + assertFalse(maId4.equals(new String("test"))); + + assertTrue(maId4.equals(maId4)); + assertFalse(maId4.equals(maId1)); + + + //ICC-Y1731 + assertFalse(maId5.equals(null)); + assertFalse(maId5.equals(new String("test"))); + + assertTrue(maId5.equals(maId5)); + assertFalse(maId5.equals(maId1)); +} + + @Test + public void testHashCode() { + assertEquals(maId1.hashCode(), maId1.hashCode()); + assertEquals(maId2.hashCode(), maId2.hashCode()); + assertEquals(maId3.hashCode(), maId3.hashCode()); + assertEquals(maId4.hashCode(), maId4.hashCode()); + assertEquals(maId5.hashCode(), maId5.hashCode()); + } +} diff --git a/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MdIdTest.java b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MdIdTest.java new file mode 100644 index 0000000000..18af6b6ff9 --- /dev/null +++ b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MdIdTest.java @@ -0,0 +1,170 @@ +/* + * 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.incubator.net.l2monitoring.cfm.identifier; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import org.junit.Before; +import org.junit.Test; +import org.onlab.packet.MacAddress; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; + +import com.google.common.net.InternetDomainName; + +public class MdIdTest { + + MdId mdId1; + MdId mdId2; + MdId mdId3; + MdId mdId4; + + @Before + public void setUp() throws Exception, CfmConfigException { + mdId1 = MdIdCharStr.asMdId("md-1"); + mdId2 = MdIdDomainName.asMdId("md.domain.tld"); + mdId3 = MdIdMacUint.asMdId(MacAddress.valueOf("AA:BB:cc:dd:ee:ff"), 54321); + mdId4 = MdIdNone.asMdId(); + } + + @Test + public void testMdNameWrong() { + + try { + MdIdCharStr.asMdId(""); + fail("Expected an exception"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().contains("MD Name must follow pattern")); + } + + try { + MdIdCharStr.asMdId("name with spaces and other stuff"); + fail("Expected an exception"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().contains("MD Name must follow pattern")); + } + + try { + MdIdCharStr.asMdId("NameIsTooLongItShouldNotExceedFortyFiveCharacters"); + fail("Expected an exception"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().contains("MD Name must follow pattern")); + } + + try { + MdIdCharStr.asMdId(null); + fail("Expected an exception"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().contains("MD Name must follow pattern")); + } + + + try { + MdIdDomainName.asMdId((String) null); + fail("Expected an exception"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().contains("MD Name must follow internet domain")); + } + + try { + MdIdDomainName.asMdId("name with spaces"); + fail("Expected an exception"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().contains("MD Name must follow internet domain")); + } + + try { + MdIdDomainName.asMdId(InternetDomainName + .from("a.really.long.domain.name.which.is.more.than.45.chars.long")); + fail("Expected an exception"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().contains("MD Domain Name must be between 1 and 45 chars long")); + } + + try { + MdIdMacUint.asMdId("AA:BB:cc:dd:ee:ff:70000"); + fail("Expected an exception"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().contains("uInt must be between 0 and 65535")); + } + + try { + MdIdMacUint.asMdId("something:12345"); + fail("Expected an exception"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().contains("MD Name must follow pattern")); + } +} + + @Test + public void testMdName() { + assertEquals("md-1", mdId1.mdName()); + assertEquals("md.domain.tld", mdId2.mdName()); + assertEquals("AA:BB:cc:dd:ee:ff:54321".toUpperCase(), mdId3.mdName()); + assertNull(mdId4.mdName()); + } + + @Test + public void testGetNameLength() { + assertEquals(4, mdId1.getNameLength()); + assertEquals(13, mdId2.getNameLength()); + assertEquals(8, mdId3.getNameLength()); + assertEquals(0, mdId4.getNameLength()); + } + + @Test + public void testEquals() { + //For char string + assertFalse(mdId1.equals(null)); + assertFalse(mdId1.equals(new String("test"))); + + assertTrue(mdId1.equals(mdId1)); + assertFalse(mdId1.equals(mdId2)); + + //For DomainName + assertFalse(mdId2.equals(null)); + assertFalse(mdId2.equals(new String("test"))); + + assertTrue(mdId2.equals(mdId2)); + assertFalse(mdId2.equals(mdId1)); + + //For MacUint + assertFalse(mdId3.equals(null)); + assertFalse(mdId3.equals(new String("test"))); + + assertTrue(mdId3.equals(mdId3)); + assertFalse(mdId3.equals(mdId1)); + + //For None + assertFalse(mdId4.equals(null)); + assertFalse(mdId4.equals(new String("test"))); + + assertTrue(mdId4.equals(mdId4)); + assertFalse(mdId4.equals(mdId1)); + + } + + @Test + public void testHashCode() { + assertEquals(mdId1.hashCode(), mdId1.hashCode()); + assertEquals(mdId2.hashCode(), mdId2.hashCode()); + assertEquals(mdId3.hashCode(), mdId3.hashCode()); + assertEquals(mdId4.hashCode(), mdId4.hashCode()); + } +} diff --git a/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MepIdTest.java b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MepIdTest.java new file mode 100644 index 0000000000..ed11e3903b --- /dev/null +++ b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MepIdTest.java @@ -0,0 +1,58 @@ +/* + * 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.incubator.net.l2monitoring.cfm.identifier; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import org.junit.Test; + +public class MepIdTest { + @Test + public void testLowRange() { + try { + MepId.valueOf((short) -1); + fail("Exception expected for MepId = -1"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().contains("Invalid value for Mep Id")); + } + + try { + MepId.valueOf((short) 0); + fail("Exception expected for MepId = 0"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().contains("Invalid value for Mep Id")); + } + } + + @Test + public void testHighRange() { + try { + MepId.valueOf((short) 8192); + fail("Exception expected for MepId = 8192"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().contains("Invalid value for Mep Id")); + } + + try { + MepId.valueOf((short) 33333); //Above the range of short + fail("Exception expected for MepId = 33333"); + } catch (IllegalArgumentException e) { + assertTrue(e.getMessage().contains("Invalid value for Mep Id")); + } + } + +} diff --git a/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/MilliPctTest.java b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/MilliPctTest.java new file mode 100644 index 0000000000..e51a761400 --- /dev/null +++ b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/MilliPctTest.java @@ -0,0 +1,83 @@ +/* + * 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.incubator.net.l2monitoring.soam; + +import static org.junit.Assert.assertEquals; + +import java.text.DecimalFormat; +import java.text.NumberFormat; + +import org.junit.Test; + +public class MilliPctTest { + + @Test + public void testIntValue() { + assertEquals(100, MilliPct.ofMilliPct(100).intValue()); + assertEquals(-100, MilliPct.ofMilliPct(-100).intValue()); + } + + @Test + public void testLongValue() { + assertEquals(100, MilliPct.ofMilliPct(100).longValue()); + assertEquals(-100, MilliPct.ofMilliPct(-100).longValue()); + } + + @Test + public void testFloatValue() { + assertEquals(100f, MilliPct.ofMilliPct(100).floatValue(), 0.0001f); + assertEquals(-100f, MilliPct.ofMilliPct(-100).floatValue(), 0.0001f); + } + + @Test + public void testDoubleValue() { + assertEquals(100f, MilliPct.ofMilliPct(100).doubleValue(), 0.0001f); + assertEquals(-100f, MilliPct.ofMilliPct(-100).doubleValue(), 0.0001f); + } + + @Test + public void testOfPercent() { + assertEquals(63563, MilliPct.ofPercent(63.563f).intValue()); + assertEquals(-63563, MilliPct.ofPercent(-63.563f).intValue()); + } + + @Test + public void testOfRatio() { + assertEquals(43211, MilliPct.ofRatio(0.43211f).intValue()); + assertEquals(-43211, MilliPct.ofRatio(-0.43211f).intValue()); + } + + @Test + public void testPercentValue() { + assertEquals(0.1f, MilliPct.ofMilliPct(100).percentValue(), 0.0001f); + assertEquals(-0.1f, MilliPct.ofMilliPct(-100).percentValue(), 0.0001f); + } + + @Test + public void testRatioValue() { + assertEquals(0.002f, MilliPct.ofMilliPct(200).ratioValue(), 0.0001f); + assertEquals(-0.002f, MilliPct.ofMilliPct(-200).ratioValue(), 0.0001f); + } + + @Test + public void testToString() { + NumberFormat pf = DecimalFormat.getPercentInstance(); //Varies by machine + pf.setMaximumFractionDigits(3); + assertEquals(pf.format(0.12345f), MilliPct.ofMilliPct(12345).toString()); + assertEquals(pf.format(-0.12345f), MilliPct.ofMilliPct(-12345).toString()); + } + +} diff --git a/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/StartTimeTest.java b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/StartTimeTest.java new file mode 100644 index 0000000000..4d7c6c071b --- /dev/null +++ b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/StartTimeTest.java @@ -0,0 +1,90 @@ +/* + * 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.incubator.net.l2monitoring.soam; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import java.time.Duration; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; + +import org.junit.Test; +import org.onosproject.incubator.net.l2monitoring.soam.StartTime.StartTimeOption; +import org.onosproject.incubator.net.l2monitoring.soam.StopTime.StopTimeOption; + +public class StartTimeTest { + + @Test + public void testStartImmediate() { + StartTime st = StartTime.immediate(); + assertEquals(StartTimeOption.IMMEDIATE, st.option()); + assertNull(st.relativeTime()); + assertNull(st.absoluteTime()); + } + + @Test + public void testStartRelative() { + StartTime st = StartTime.relative(Duration.ofMinutes(20)); + assertEquals(StartTimeOption.RELATIVE, st.option()); + assertEquals(20 * 60, st.relativeTime().getSeconds()); + assertNull(st.absoluteTime()); + } + + @Test + public void testStartAbsolute() { + StartTime st = StartTime.absolute(OffsetDateTime + .of(2017, 3, 20, 11, 43, 11, 0, ZoneOffset.ofHours(-7)) + .toInstant()); + assertEquals(StartTimeOption.ABSOLUTE, st.option()); + assertNull(st.relativeTime()); + assertEquals("2017-03-20T11:43:11-07:00", st + .absoluteTime() + .atOffset(ZoneOffset.ofHours(-7)) + .format(DateTimeFormatter.ISO_OFFSET_DATE_TIME)); + } + + @Test + public void testStopImmediate() { + StopTime st = StopTime.none(); + assertEquals(StopTimeOption.NONE, st.option()); + assertNull(st.relativeTime()); + assertNull(st.absoluteTime()); + } + + @Test + public void testStopRelative() { + StopTime st = StopTime.relative(Duration.ofMinutes(20)); + assertEquals(StopTimeOption.RELATIVE, st.option()); + assertEquals(20 * 60, st.relativeTime().getSeconds()); + assertNull(st.absoluteTime()); + } + + @Test + public void testStopAbsolute() { + StopTime st = StopTime.absolute(OffsetDateTime + .of(2017, 3, 20, 11, 43, 11, 0, ZoneOffset.ofHours(-7)) + .toInstant()); + assertEquals(StopTimeOption.ABSOLUTE, st.option()); + assertNull(st.relativeTime()); + assertEquals("2017-03-20T11:43:11-07:00", st + .absoluteTime() + .atOffset(ZoneOffset.ofHours(-7)) + .format(DateTimeFormatter.ISO_OFFSET_DATE_TIME)); + } + +} diff --git a/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DelayMeasurementCreateTest.java b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DelayMeasurementCreateTest.java new file mode 100644 index 0000000000..d24effcf3e --- /dev/null +++ b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DelayMeasurementCreateTest.java @@ -0,0 +1,304 @@ +/* + * 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.incubator.net.l2monitoring.soam.delay; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.time.Duration; +import java.time.OffsetDateTime; + +import org.junit.Before; +import org.junit.Test; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep.Priority; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; +import org.onosproject.incubator.net.l2monitoring.soam.MeasurementCreateBase.SessionType; +import org.onosproject.incubator.net.l2monitoring.soam.SoamConfigException; +import org.onosproject.incubator.net.l2monitoring.soam.SoamId; +import org.onosproject.incubator.net.l2monitoring.soam.StartTime; +import org.onosproject.incubator.net.l2monitoring.soam.StartTime.StartTimeOption; +import org.onosproject.incubator.net.l2monitoring.soam.StopTime; +import org.onosproject.incubator.net.l2monitoring.soam.StopTime.StopTimeOption; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DefaultDelayMeasurementCreate.DefaultDmCreateBuilder; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.DataPattern; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.DmType; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.MeasurementOption; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.TestTlvPattern; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.Version; + +public class DelayMeasurementCreateTest { + + DelayMeasurementCreate dm1; + + @Before + public void setUp() throws Exception, CfmConfigException, SoamConfigException { + + DelayMeasurementThreshold dmT1 = DefaultDelayMeasurementThreshold + .builder(SoamId.valueOf(1)) + .averageFrameDelayBackward(Duration.ofMillis(123)) + .averageInterFrameDelayVariationForward(Duration.ofMillis(321)) + .build(); + + DelayMeasurementThreshold dmT2 = DefaultDelayMeasurementThreshold + .builder(SoamId.valueOf(2)) + .averageFrameDelayBackward(Duration.ofMillis(456)) + .averageInterFrameDelayVariationForward(Duration.ofMillis(654)) + .build(); + + try { + DefaultDmCreateBuilder builder = (DefaultDmCreateBuilder) + DefaultDelayMeasurementCreate.builder( + DmType.DMDMM, Version.Y17312011, MepId.valueOf((short) 12), Priority.PRIO6) + .addToMeasurementsEnabled(MeasurementOption.FRAME_DELAY_FORWARD_MIN) + .addToMeasurementsEnabled(MeasurementOption.FRAME_DELAY_FORWARD_AVERAGE) + .addToMeasurementsEnabled(MeasurementOption.FRAME_DELAY_FORWARD_MAX) + .addToMeasurementsEnabled(MeasurementOption.FRAME_DELAY_FORWARD_BINS) + .binsPerFdInterval((short) 8) + .binsPerIfdvInterval((short) 9) + .ifdvSelectionOffset((short) 10) + .binsPerFdrInterval((short) 12) + .addToThresholds(dmT1) + .addToThresholds(dmT2) + .messagePeriod(Duration.ofMillis(100L)) + .frameSize((short) 64) + .dataPattern(DataPattern.ONES) + .testTlvIncluded(true) + .testTlvPattern(TestTlvPattern.NULL_SIGNAL_WITHOUT_CRC_32) + .measurementInterval(Duration.ofMinutes(15)) + .numberIntervalsStored((short) 32) + .alignMeasurementIntervals(true) + .alignMeasurementOffset(Duration.ofMinutes(4)) + .sessionType(SessionType.ONDEMAND) + .startTime(StartTime.relative(Duration.ofMinutes(7))) + .stopTime(StopTime.relative(Duration.ofMinutes(8))); + dm1 = builder.build(); + } catch (SoamConfigException e) { + throw new Exception(e); + } + } + + @Test + public void testInvalidMessagePeriod() throws CfmConfigException { + try { + DefaultDelayMeasurementCreate.builder( + DmType.DMDMM, Version.Y17312011, MepId.valueOf((short) 20), + Priority.PRIO6) + .messagePeriod(Duration.ofMinutes(61)); + fail("Expected an exception to be thrown for invalid messagePeriod: " + 3660000); + } catch (SoamConfigException e) { + assertEquals(SoamConfigException.class, e.getClass()); + } + } + + @Test + public void testInvalidFrameSize() throws CfmConfigException { + try { + DefaultDelayMeasurementCreate.builder( + DmType.DMDMM, Version.Y17312011, MepId.valueOf((short) 20), + Priority.PRIO6) + .frameSize((short) 11111); + fail("Expected an exception to be thrown for frame size: " + 11111); + } catch (SoamConfigException e) { + assertEquals(SoamConfigException.class, e.getClass()); + } + } + + @Test + public void testInvalidMeasurementInterval() throws CfmConfigException { + try { + DefaultDelayMeasurementCreate.builder( + DmType.DMDMM, Version.Y17312011, MepId.valueOf((short) 20), + Priority.PRIO6) + .measurementInterval(Duration.ofMinutes(0)); + fail("Expected an exception to be thrown for invalid measurementInterval: " + 0); + } catch (SoamConfigException e) { + assertEquals(SoamConfigException.class, e.getClass()); + } + } + + @Test + public void testInvalidNumberIntervalsStored() throws CfmConfigException { + try { + DefaultDelayMeasurementCreate.builder( + DmType.DMDMM, Version.Y17312011, MepId.valueOf((short) 20), + Priority.PRIO6) + .numberIntervalsStored((short) 1001); + fail("Expected an exception to be thrown for number intervals stored: " + 1001); + } catch (SoamConfigException e) { + assertEquals(SoamConfigException.class, e.getClass()); + } + } + + @Test + public void testInvalidAlignMeasurementOffset() throws CfmConfigException { + try { + DefaultDelayMeasurementCreate.builder( + DmType.DMDMM, Version.Y17312011, MepId.valueOf((short) 20), + Priority.PRIO6) + .alignMeasurementOffset(Duration.ofMinutes(525601)); + fail("Expected an exception to be thrown for align Measurement Offset: " + 525601); + } catch (SoamConfigException e) { + assertEquals(SoamConfigException.class, e.getClass()); + } + } + + @Test + public void testInvalidStartTime() throws CfmConfigException { + OffsetDateTime oneMinuteAgo = OffsetDateTime.now().minusMinutes(1); + try { + DefaultDelayMeasurementCreate.builder( + DmType.DMDMM, Version.Y17312011, MepId.valueOf((short) 20), + Priority.PRIO6) + .startTime(StartTime.absolute(oneMinuteAgo.toInstant())); + fail("Expected an exception to be thrown for align Start Time: " + oneMinuteAgo); + } catch (SoamConfigException e) { + assertEquals(SoamConfigException.class, e.getClass()); + } + } + + @Test + public void testInvalidStopTime() throws CfmConfigException { + OffsetDateTime oneMinuteAgo = OffsetDateTime.now().minusMinutes(1); + try { + DefaultDelayMeasurementCreate.builder( + DmType.DMDMM, Version.Y17312011, MepId.valueOf((short) 20), + Priority.PRIO6) + .stopTime(StopTime.absolute(oneMinuteAgo.toInstant())); + fail("Expected an exception to be thrown for align Stop Time: " + oneMinuteAgo); + } catch (SoamConfigException e) { + assertEquals(SoamConfigException.class, e.getClass()); + } + } + + @Test + public void testDmCfgType() { + assertEquals(DmType.DMDMM, dm1.dmCfgType()); + } + + @Test + public void testVersion() { + assertEquals(Version.Y17312011, dm1.version()); + } + + @Test + public void testRemoteMepId() { + assertEquals(12, dm1.remoteMepId().value()); + } + + @Test + public void testMeasurementsEnabled() { + assertEquals(4, dm1.measurementsEnabled().size()); + } + + @Test + public void testMessagePeriod() { + assertEquals(100, dm1.messagePeriod().toMillis()); + } + + @Test + public void testPriority() { + assertEquals(Priority.PRIO6.name(), dm1.priority().name()); + } + + @Test + public void testFrameSize() { + assertEquals(64, dm1.frameSize().shortValue()); + } + + @Test + public void testDataPattern() { + assertEquals(DataPattern.ONES, dm1.dataPattern()); + } + + @Test + public void testTestTlvIncluded() { + assertTrue(dm1.testTlvIncluded()); + } + + @Test + public void testTestTlvPattern() { + assertEquals(TestTlvPattern.NULL_SIGNAL_WITHOUT_CRC_32, dm1.testTlvPattern()); + } + + @Test + public void testMeasurementInterval() { + assertEquals(15, dm1.measurementInterval().toMinutes()); + } + + @Test + public void testNumberIntervalsStored() { + assertEquals(32, dm1.numberIntervalsStored().shortValue()); + } + + @Test + public void testAlignMeasurementIntervals() { + assertTrue(dm1.alignMeasurementIntervals()); + } + + @Test + public void testAlignMeasurementOffset() { + assertEquals(4, dm1.alignMeasurementOffset().toMinutes()); + } + + @Test + public void testBinsPerFdInterval() { + assertEquals(8, dm1.binsPerFdInterval().shortValue()); + } + + @Test + public void testBinsPerIfdvInterval() { + assertEquals(9, dm1.binsPerIfdvInterval().shortValue()); + } + + @Test + public void testIfdvSelectionOffset() { + assertEquals(10, dm1.ifdvSelectionOffset().shortValue()); + } + + @Test + public void testBinsPerFdrInterval() { + assertEquals(12, dm1.binsPerFdrInterval().shortValue()); + } + + @Test + public void testSessionType() { + assertEquals(SessionType.ONDEMAND, dm1.sessionType()); + } + + @Test + public void testStartTime() { + assertEquals(StartTimeOption.RELATIVE, dm1.startTime().option()); + assertEquals(7, dm1.startTime().relativeTime().toMinutes()); + } + + @Test + public void testStopTime() { + assertEquals(StopTimeOption.RELATIVE, dm1.stopTime().option()); + assertEquals(8, dm1.stopTime().relativeTime().toMinutes()); + } + + @Test + public void testThresholds() { + DelayMeasurementThreshold[] thresholds = + dm1.thresholds().toArray( + new DelayMeasurementThreshold[dm1.thresholds().size()]); + + assertEquals(1, thresholds[0].threshId().id().intValue()); + assertEquals(123, thresholds[0].averageFrameDelayBackward().toMillis()); + } +} diff --git a/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DelayMeasurementEntryTest.java b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DelayMeasurementEntryTest.java new file mode 100644 index 0000000000..ad2439a1d8 --- /dev/null +++ b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DelayMeasurementEntryTest.java @@ -0,0 +1,125 @@ +/* + * Copyright 2017-present Open Networking Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onosproject.incubator.net.l2monitoring.soam.delay; + +import static org.junit.Assert.*; + +import java.time.Duration; + +import org.junit.Before; +import org.junit.Test; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep.Priority; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; +import org.onosproject.incubator.net.l2monitoring.soam.SoamConfigException; +import org.onosproject.incubator.net.l2monitoring.soam.SoamId; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.DmType; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.Version; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementEntry.SessionStatus; + +public class DelayMeasurementEntryTest { + + DelayMeasurementEntry dmE1; + + @Before + public void setUp() throws Exception, SoamConfigException, CfmConfigException { + + DelayMeasurementStatCurrent dmE1c = (DelayMeasurementStatCurrent) + DefaultDelayMeasurementStatCurrent.builder( + Duration.ofMinutes(6), false) + .build(); + + DelayMeasurementStatHistory dmE1h1 = (DelayMeasurementStatHistory) + DefaultDelayMeasurementStatHistory.builder( + SoamId.valueOf(1), Duration.ofMinutes(15), false) + .build(); + + DelayMeasurementStatHistory dmE1h2 = (DelayMeasurementStatHistory) + DefaultDelayMeasurementStatHistory.builder( + SoamId.valueOf(2), Duration.ofMinutes(15), false) + .build(); + + dmE1 = DefaultDelayMeasurementEntry.builder( + SoamId.valueOf(1), + DmType.DMDMM, + Version.Y17312011, + MepId.valueOf((short) 10), + Priority.PRIO3) + .sessionStatus(SessionStatus.NOT_ACTIVE) + .frameDelayTwoWay(Duration.ofMillis(1)) + .frameDelayForward(Duration.ofMillis(2)) + .frameDelayBackward(Duration.ofMillis(3)) + .interFrameDelayVariationTwoWay(Duration.ofMillis(4)) + .interFrameDelayVariationForward(Duration.ofMillis(5)) + .interFrameDelayVariationBackward(Duration.ofMillis(6)) + .currentResult(dmE1c) + .addToHistoricalResults(dmE1h1) + .addToHistoricalResults(dmE1h2) + .build(); + } + + @Test + public void testDmId() { + assertEquals(1, dmE1.dmId().id().shortValue()); + } + + @Test + public void testSessionStatus() { + assertEquals(SessionStatus.NOT_ACTIVE.name(), + dmE1.sessionStatus().name()); + } + + @Test + public void testFrameDelayTwoWay() { + assertEquals(1, dmE1.frameDelayTwoWay().toMillis()); + } + + @Test + public void testFrameDelayForward() { + assertEquals(2, dmE1.frameDelayForward().toMillis()); + } + + @Test + public void testFrameDelayBackward() { + assertEquals(3, dmE1.frameDelayBackward().toMillis()); + } + + @Test + public void testInterFrameDelayVariationTwoWay() { + assertEquals(4, dmE1.interFrameDelayVariationTwoWay().toMillis()); + } + + @Test + public void testInterFrameDelayVariationForward() { + assertEquals(5, dmE1.interFrameDelayVariationForward().toMillis()); + } + + @Test + public void testInterFrameDelayVariationBackward() { + assertEquals(6, dmE1.interFrameDelayVariationBackward().toMillis()); + } + + @Test + public void testCurrentResult() { + assertEquals(360, dmE1.currentResult().elapsedTime().getSeconds()); + } + + @Test + public void testHistoricalResults() { + assertEquals(2, dmE1.historicalResults().size()); + } + +} diff --git a/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DelayMeasurementStatCurrentAndHistoryTest.java b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DelayMeasurementStatCurrentAndHistoryTest.java new file mode 100644 index 0000000000..0bde63a54c --- /dev/null +++ b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DelayMeasurementStatCurrentAndHistoryTest.java @@ -0,0 +1,385 @@ +/* + * 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.incubator.net.l2monitoring.soam.delay; + +import static junit.framework.TestCase.fail; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.time.Duration; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; + +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Test; +import org.onosproject.incubator.net.l2monitoring.soam.SoamConfigException; +import org.onosproject.incubator.net.l2monitoring.soam.SoamId; + +public class DelayMeasurementStatCurrentAndHistoryTest { + + private DelayMeasurementStatCurrent dmStCurr1; + private DelayMeasurementStatHistory dmStHist1; + + @Before + public void setUp() throws Exception, SoamConfigException { + dmStCurr1 = (DelayMeasurementStatCurrent) + DefaultDelayMeasurementStatCurrent.builder( + Duration.ofMinutes(9), false) + .startTime(OffsetDateTime.of(2017, 3, 20, 23, 22, 7, 0, + ZoneOffset.ofHours(-7)).toInstant()) + .frameDelayTwoWayMin(Duration.ofMillis(101)) + .frameDelayTwoWayMax(Duration.ofMillis(102)) + .frameDelayTwoWayAvg(Duration.ofMillis(103)) + .frameDelayForwardMin(Duration.ofMillis(104)) + .frameDelayForwardMax(Duration.ofMillis(105)) + .frameDelayForwardAvg(Duration.ofMillis(106)) + .frameDelayBackwardMin(Duration.ofMillis(107)) + .frameDelayBackwardMax(Duration.ofMillis(108)) + .frameDelayBackwardAvg(Duration.ofMillis(109)) + .interFrameDelayVariationTwoWayMin(Duration.ofMillis(110)) + .interFrameDelayVariationTwoWayMax(Duration.ofMillis(111)) + .interFrameDelayVariationTwoWayAvg(Duration.ofMillis(112)) + .interFrameDelayVariationForwardMin(Duration.ofMillis(113)) + .interFrameDelayVariationForwardMax(Duration.ofMillis(114)) + .interFrameDelayVariationForwardAvg(Duration.ofMillis(115)) + .interFrameDelayVariationBackwardMin(Duration.ofMillis(116)) + .interFrameDelayVariationBackwardMax(Duration.ofMillis(117)) + .interFrameDelayVariationBackwardAvg(Duration.ofMillis(118)) + .frameDelayRangeTwoWayMax(Duration.ofMillis(119)) + .frameDelayRangeTwoWayAvg(Duration.ofMillis(120)) + .frameDelayRangeForwardMax(Duration.ofMillis(121)) + .frameDelayRangeForwardAvg(Duration.ofMillis(122)) + .frameDelayRangeBackwardMax(Duration.ofMillis(123)) + .frameDelayRangeBackwardAvg(Duration.ofMillis(124)) + .soamPdusSent(125) + .soamPdusReceived(126) + .build(); + + dmStHist1 = (DelayMeasurementStatHistory) + DefaultDelayMeasurementStatHistory.builder( + SoamId.valueOf(11), Duration.ofMinutes(15), true) + .endTime(OffsetDateTime.of(2017, 3, 20, 23, 22, 8, 0, + ZoneOffset.ofHours(-7)).toInstant()) + .frameDelayTwoWayMin(Duration.ofMillis(201)) + .frameDelayTwoWayMax(Duration.ofMillis(202)) + .frameDelayTwoWayAvg(Duration.ofMillis(203)) + .frameDelayForwardMin(Duration.ofMillis(204)) + .frameDelayForwardMax(Duration.ofMillis(205)) + .frameDelayForwardAvg(Duration.ofMillis(206)) + .frameDelayBackwardMin(Duration.ofMillis(207)) + .frameDelayBackwardMax(Duration.ofMillis(208)) + .frameDelayBackwardAvg(Duration.ofMillis(209)) + .interFrameDelayVariationTwoWayMin(Duration.ofMillis(210)) + .interFrameDelayVariationTwoWayMax(Duration.ofMillis(211)) + .interFrameDelayVariationTwoWayAvg(Duration.ofMillis(212)) + .interFrameDelayVariationForwardMin(Duration.ofMillis(213)) + .interFrameDelayVariationForwardMax(Duration.ofMillis(214)) + .interFrameDelayVariationForwardAvg(Duration.ofMillis(215)) + .interFrameDelayVariationBackwardMin(Duration.ofMillis(216)) + .interFrameDelayVariationBackwardMax(Duration.ofMillis(217)) + .interFrameDelayVariationBackwardAvg(Duration.ofMillis(218)) + .frameDelayRangeTwoWayMax(Duration.ofMillis(219)) + .frameDelayRangeTwoWayAvg(Duration.ofMillis(220)) + .frameDelayRangeForwardMax(Duration.ofMillis(221)) + .frameDelayRangeForwardAvg(Duration.ofMillis(222)) + .frameDelayRangeBackwardMax(Duration.ofMillis(223)) + .frameDelayRangeBackwardAvg(Duration.ofMillis(224)) + .soamPdusSent(225) + .soamPdusReceived(226) + .build(); + } + + @Test + public void testStartTime() { + assertEquals("2017-03-20T23:22:07-07:00", + dmStCurr1.startTime().atOffset(ZoneOffset.ofHours(-7)) + .format(DateTimeFormatter.ISO_OFFSET_DATE_TIME)); + } + + @Test + public void testEndTime() { + assertEquals("2017-03-20T23:22:08-07:00", + dmStHist1.endTime().atOffset(ZoneOffset.ofHours(-7)) + .format(DateTimeFormatter.ISO_OFFSET_DATE_TIME)); + } + + @Test + public void testHistoryStatsId() { + assertEquals(11, dmStHist1.historyStatsId().id().intValue()); + } + + @Test + public void testElapsedTime() { + assertEquals(9, dmStCurr1.elapsedTime().toMinutes()); + + assertEquals(15, dmStHist1.elapsedTime().toMinutes()); + } + + @Test + public void testSuspectStatus() { + assertFalse(dmStCurr1.suspectStatus()); + + assertTrue(dmStHist1.suspectStatus()); + } + + @Test + public void testFrameDelayTwoWayMin() { + assertEquals(101, dmStCurr1.frameDelayTwoWayMin().toMillis()); + + assertEquals(201, dmStHist1.frameDelayTwoWayMin().toMillis()); + } + + @Test + public void testFrameDelayTwoWayMax() { + assertEquals(102, dmStCurr1.frameDelayTwoWayMax().toMillis()); + + assertEquals(202, dmStHist1.frameDelayTwoWayMax().toMillis()); + } + + @Test + public void testFrameDelayTwoWayAvg() { + assertEquals(103, dmStCurr1.frameDelayTwoWayAvg().toMillis()); + + assertEquals(203, dmStHist1.frameDelayTwoWayAvg().toMillis()); + } + + @Test + public void testFrameDelayForwardMin() { + assertEquals(104, dmStCurr1.frameDelayForwardMin().toMillis()); + + assertEquals(204, dmStHist1.frameDelayForwardMin().toMillis()); + } + + @Test + public void testFrameDelayForwardMax() { + assertEquals(105, dmStCurr1.frameDelayForwardMax().toMillis()); + + assertEquals(205, dmStHist1.frameDelayForwardMax().toMillis()); + } + + @Test + public void testFrameDelayForwardAvg() { + assertEquals(106, dmStCurr1.frameDelayForwardAvg().toMillis()); + + assertEquals(206, dmStHist1.frameDelayForwardAvg().toMillis()); + } + + @Test + public void testFrameDelayBackwardMin() { + assertEquals(107, dmStCurr1.frameDelayBackwardMin().toMillis()); + + assertEquals(207, dmStHist1.frameDelayBackwardMin().toMillis()); + } + + @Test + public void testFrameDelayBackwardMax() { + assertEquals(108, dmStCurr1.frameDelayBackwardMax().toMillis()); + + assertEquals(208, dmStHist1.frameDelayBackwardMax().toMillis()); + } + + @Test + public void testFrameDelayBackwardAvg() { + assertEquals(109, dmStCurr1.frameDelayBackwardAvg().toMillis()); + + assertEquals(209, dmStHist1.frameDelayBackwardAvg().toMillis()); + } + + @Test + public void testInterFrameDelayVariationTwoWayMin() { + assertEquals(110, dmStCurr1.interFrameDelayVariationTwoWayMin().toMillis()); + + assertEquals(210, dmStHist1.interFrameDelayVariationTwoWayMin().toMillis()); + } + + @Test + public void testInterFrameDelayVariationTwoWayMax() { + assertEquals(111, dmStCurr1.interFrameDelayVariationTwoWayMax().toMillis()); + + assertEquals(211, dmStHist1.interFrameDelayVariationTwoWayMax().toMillis()); + } + + @Test + public void testInterFrameDelayVariationTwoWayAvg() { + assertEquals(112, dmStCurr1.interFrameDelayVariationTwoWayAvg().toMillis()); + + assertEquals(212, dmStHist1.interFrameDelayVariationTwoWayAvg().toMillis()); + } + + @Test + public void testInterFrameDelayVariationForwardMin() { + assertEquals(113, dmStCurr1.interFrameDelayVariationForwardMin().toMillis()); + + assertEquals(213, dmStHist1.interFrameDelayVariationForwardMin().toMillis()); + } + + @Test + public void testInterFrameDelayVariationForwardMax() { + assertEquals(114, dmStCurr1.interFrameDelayVariationForwardMax().toMillis()); + + assertEquals(214, dmStHist1.interFrameDelayVariationForwardMax().toMillis()); + } + + @Test + public void testInterFrameDelayVariationForwardAvg() { + assertEquals(115, dmStCurr1.interFrameDelayVariationForwardAvg().toMillis()); + + assertEquals(215, dmStHist1.interFrameDelayVariationForwardAvg().toMillis()); + } + + @Test + public void testInterFrameDelayVariationBackwardMin() { + assertEquals(116, dmStCurr1.interFrameDelayVariationBackwardMin().toMillis()); + + assertEquals(216, dmStHist1.interFrameDelayVariationBackwardMin().toMillis()); + } + + @Test + public void testInterFrameDelayVariationBackwardMax() { + assertEquals(117, dmStCurr1.interFrameDelayVariationBackwardMax().toMillis()); + + assertEquals(217, dmStHist1.interFrameDelayVariationBackwardMax().toMillis()); + } + + @Test + public void testInterFrameDelayVariationBackwardAvg() { + assertEquals(118, dmStCurr1.interFrameDelayVariationBackwardAvg().toMillis()); + + assertEquals(218, dmStHist1.interFrameDelayVariationBackwardAvg().toMillis()); + } + + @Test + public void testFrameDelayRangeTwoWayMax() { + assertEquals(119, dmStCurr1.frameDelayRangeTwoWayMax().toMillis()); + + assertEquals(219, dmStHist1.frameDelayRangeTwoWayMax().toMillis()); + } + + @Test + public void testFrameDelayRangeTwoWayAvg() { + assertEquals(120, dmStCurr1.frameDelayRangeTwoWayAvg().toMillis()); + + assertEquals(220, dmStHist1.frameDelayRangeTwoWayAvg().toMillis()); + } + + @Test + public void testFrameDelayRangeForwardMax() { + assertEquals(121, dmStCurr1.frameDelayRangeForwardMax().toMillis()); + + assertEquals(221, dmStHist1.frameDelayRangeForwardMax().toMillis()); + } + + @Test + public void testFrameDelayRangeForwardAvg() { + assertEquals(122, dmStCurr1.frameDelayRangeForwardAvg().toMillis()); + + assertEquals(222, dmStHist1.frameDelayRangeForwardAvg().toMillis()); + } + + @Test + public void testFrameDelayRangeBackwardMax() { + assertEquals(123, dmStCurr1.frameDelayRangeBackwardMax().toMillis()); + + assertEquals(223, dmStHist1.frameDelayRangeBackwardMax().toMillis()); + } + + @Test + public void testFrameDelayRangeBackwardAvg() { + assertEquals(124, dmStCurr1.frameDelayRangeBackwardAvg().toMillis()); + + assertEquals(224, dmStHist1.frameDelayRangeBackwardAvg().toMillis()); + } + + @Test + public void testSoamPdusSent() { + assertEquals(125, dmStCurr1.soamPdusSent().intValue()); + + assertEquals(225, dmStHist1.soamPdusSent().intValue()); + } + + @Test + public void testSoamPdusReceived() { + assertEquals(126, dmStCurr1.soamPdusReceived().intValue()); + + assertEquals(226, dmStHist1.soamPdusReceived().intValue()); + } + + @Ignore + @Test + public void testFrameDelayTwoWayBins() { + //TODO Add in test + fail("Not yet implemented"); + } + + @Ignore + @Test + public void testFrameDelayForwardBins() { + //TODO Add in test + fail("Not yet implemented"); + } + + @Ignore + @Test + public void testFrameDelayBackwardBins() { + //TODO Add in test + fail("Not yet implemented"); + } + + @Ignore + @Test + public void testInterFrameDelayVariationTwoWayBins() { + //TODO Add in test + fail("Not yet implemented"); + } + + @Ignore + @Test + public void testInterFrameDelayVariationForwardBins() { + //TODO Add in test + fail("Not yet implemented"); + } + + @Ignore + @Test + public void testInterFrameDelayVariationBackwardBins() { + //TODO Add in test + fail("Not yet implemented"); + } + + @Ignore + @Test + public void testFrameDelayRangeTwoWayBins() { + //TODO Add in test + fail("Not yet implemented"); + } + + @Ignore + @Test + public void testFrameDelayRangeForwardBins() { + //TODO Add in test + fail("Not yet implemented"); + } + + @Ignore + @Test + public void testFrameDelayRangeBackwardBins() { + //TODO Add in test + fail("Not yet implemented"); + } +} diff --git a/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DelayMeasurementThresholdOptionTest.java b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DelayMeasurementThresholdOptionTest.java new file mode 100644 index 0000000000..f83814319f --- /dev/null +++ b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/delay/DelayMeasurementThresholdOptionTest.java @@ -0,0 +1,216 @@ +/* + * 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.incubator.net.l2monitoring.soam.delay; + +import static org.junit.Assert.*; + +import java.time.Duration; + +import org.junit.Before; +import org.junit.Test; +import org.onosproject.incubator.net.l2monitoring.soam.SoamConfigException; +import org.onosproject.incubator.net.l2monitoring.soam.SoamId; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementThreshold.ThresholdOption; + +public class DelayMeasurementThresholdOptionTest { + + DelayMeasurementThreshold dmT1; + + @Before + public void setUp() throws Exception, SoamConfigException { + dmT1 = DefaultDelayMeasurementThreshold.builder(SoamId.valueOf(1)) + .averageFrameDelayBackward(Duration.ofMillis(101)) + .averageFrameDelayForward(Duration.ofMillis(102)) + .averageFrameDelayTwoWay(Duration.ofMillis(103)) + .averageFrameDelayRangeBackward(Duration.ofMillis(201)) + .averageFrameDelayRangeForward(Duration.ofMillis(202)) + .averageFrameDelayRangeTwoWay(Duration.ofMillis(203)) + .averageInterFrameDelayVariationBackward(Duration.ofMillis(301)) + .averageInterFrameDelayVariationForward(Duration.ofMillis(302)) + .averageInterFrameDelayVariationTwoWay(Duration.ofMillis(303)) + .maxFrameDelayBackward(Duration.ofMillis(401)) + .maxFrameDelayForward(Duration.ofMillis(402)) + .maxFrameDelayTwoWay(Duration.ofMillis(403)) + .maxFrameDelayRangeBackward(Duration.ofMillis(501)) + .maxFrameDelayRangeForward(Duration.ofMillis(502)) + .maxFrameDelayRangeTwoWay(Duration.ofMillis(503)) + .maxInterFrameDelayVariationBackward(Duration.ofMillis(601)) + .maxInterFrameDelayVariationForward(Duration.ofMillis(602)) + .maxInterFrameDelayVariationTwoWay(Duration.ofMillis(603)) + .measuredFrameDelayBackward(Duration.ofMillis(701)) + .measuredFrameDelayForward(Duration.ofMillis(702)) + .measuredFrameDelayTwoWay(Duration.ofMillis(703)) + .measuredInterFrameDelayVariationBackward(Duration.ofMillis(801)) + .measuredInterFrameDelayVariationForward(Duration.ofMillis(802)) + .measuredInterFrameDelayVariationTwoWay(Duration.ofMillis(803)) + .addToThresholdsEnabled(ThresholdOption.MEASURED_FRAME_DELAY_TWO_WAY) + .addToThresholdsEnabled(ThresholdOption.MAX_FRAME_DELAY_TWO_WAY) + .addToThresholdsEnabled(ThresholdOption.AVERAGE_FRAME_DELAY_TWO_WAY) + .addToThresholdsEnabled(ThresholdOption.MEASURED_INTER_FRAME_DELAY_VARIATION_TWO_WAY) + .addToThresholdsEnabled(ThresholdOption.MAX_INTER_FRAME_DELAY_VARIATION_TWO_WAY) + .addToThresholdsEnabled(ThresholdOption.AVERAGE_INTER_FRAME_DELAY_VARIATION_TWO_WAY) + .addToThresholdsEnabled(ThresholdOption.MAX_FRAME_DELAY_RANGE_TWO_WAY) + .addToThresholdsEnabled(ThresholdOption.AVERAGE_FRAME_DELAY_RANGE_TWO_WAY) + .addToThresholdsEnabled(ThresholdOption.MEASURED_FRAME_DELAY_FORWARD) + .addToThresholdsEnabled(ThresholdOption.MAX_FRAME_DELAY_FORWARD) + .addToThresholdsEnabled(ThresholdOption.AVERAGE_FRAME_DELAY_FORWARD) + .addToThresholdsEnabled(ThresholdOption.MEASURED_INTER_FRAME_DELAY_VARIATION_FORWARD) + .addToThresholdsEnabled(ThresholdOption.MAX_INTER_FRAME_DELAY_VARIATION_FORWARD) + .addToThresholdsEnabled(ThresholdOption.AVERAGE_INTER_FRAME_DELAY_VARIATION_FORWARD) + .addToThresholdsEnabled(ThresholdOption.MAX_FRAME_DELAY_RANGE_FORWARD) + .addToThresholdsEnabled(ThresholdOption.AVERAGE_FRAME_DELAY_RANGE_FORWARD) + .addToThresholdsEnabled(ThresholdOption.MEASURED_FRAME_DELAY_BACKWARD) + .addToThresholdsEnabled(ThresholdOption.MAX_FRAME_DELAY_BACKWARD) + .addToThresholdsEnabled(ThresholdOption.AVERAGE_FRAME_DELAY_BACKWARD) + .addToThresholdsEnabled(ThresholdOption.MEASURED_INTER_FRAME_DELAY_VARIATION_BACKWARD) + .addToThresholdsEnabled(ThresholdOption.MAX_INTER_FRAME_DELAY_VARIATION_BACKWARD) + .addToThresholdsEnabled(ThresholdOption.AVERAGE_INTER_FRAME_DELAY_VARIATION_BACKWARD) + .addToThresholdsEnabled(ThresholdOption.MAX_FRAME_DELAY_RANGE_BACKWARD) + .addToThresholdsEnabled(ThresholdOption.AVERAGE_FRAME_DELAY_RANGE_BACKWARD) + .build(); + } + + @Test + public void testThreshId() { + assertEquals(1, dmT1.threshId().id().intValue()); + } + + @Test + public void testThresholdsEnabled() { + assertEquals(24, dmT1.thresholdsEnabled().size()); + } + + @Test + public void testMeasuredFrameDelayTwoWay() { + assertEquals(703, dmT1.measuredFrameDelayTwoWay().toMillis()); + } + + @Test + public void testMaxFrameDelayTwoWay() { + assertEquals(403, dmT1.maxFrameDelayTwoWay().toMillis()); + } + + @Test + public void testAverageFrameDelayTwoWay() { + assertEquals(103, dmT1.averageFrameDelayTwoWay().toMillis()); + } + + @Test + public void testMeasuredInterFrameDelayVariationTwoWay() { + assertEquals(803, dmT1.measuredInterFrameDelayVariationTwoWay().toMillis()); + } + + @Test + public void testMaxInterFrameDelayVariationTwoWay() { + assertEquals(603, dmT1.maxInterFrameDelayVariationTwoWay().toMillis()); + } + + @Test + public void testAverageInterFrameDelayVariationTwoWay() { + assertEquals(303, dmT1.averageInterFrameDelayVariationTwoWay().toMillis()); + } + + @Test + public void testMaxFrameDelayRangeTwoWay() { + assertEquals(503, dmT1.maxFrameDelayRangeTwoWay().toMillis()); + } + + @Test + public void testAverageFrameDelayRangeTwoWay() { + assertEquals(203, dmT1.averageFrameDelayRangeTwoWay().toMillis()); + } + + @Test + public void testMeasuredFrameDelayForward() { + assertEquals(702, dmT1.measuredFrameDelayForward().toMillis()); + } + + @Test + public void testMaxFrameDelayForward() { + assertEquals(402, dmT1.maxFrameDelayForward().toMillis()); + } + + @Test + public void testAverageFrameDelayForward() { + assertEquals(102, dmT1.averageFrameDelayForward().toMillis()); + } + + @Test + public void testMeasuredInterFrameDelayVariationForward() { + assertEquals(802, dmT1.measuredInterFrameDelayVariationForward().toMillis()); + } + + @Test + public void testMaxInterFrameDelayVariationForward() { + assertEquals(602, dmT1.maxInterFrameDelayVariationForward().toMillis()); + } + + @Test + public void testAverageInterFrameDelayVariationForward() { + assertEquals(302, dmT1.averageInterFrameDelayVariationForward().toMillis()); + } + + @Test + public void testMaxFrameDelayRangeForward() { + assertEquals(502, dmT1.maxFrameDelayRangeForward().toMillis()); + } + + @Test + public void testAverageFrameDelayRangeForward() { + assertEquals(202, dmT1.averageFrameDelayRangeForward().toMillis()); + } + + @Test + public void testMeasuredFrameDelayBackward() { + assertEquals(701, dmT1.measuredFrameDelayBackward().toMillis()); + } + + @Test + public void testMaxFrameDelayBackward() { + assertEquals(401, dmT1.maxFrameDelayBackward().toMillis()); + } + + @Test + public void testAverageFrameDelayBackward() { + assertEquals(101, dmT1.averageFrameDelayBackward().toMillis()); + } + + @Test + public void testMeasuredInterFrameDelayVariationBackward() { + assertEquals(801, dmT1.measuredInterFrameDelayVariationBackward().toMillis()); + } + + @Test + public void testMaxInterFrameDelayVariationBackward() { + assertEquals(601, dmT1.maxInterFrameDelayVariationBackward().toMillis()); + } + + @Test + public void testAverageInterFrameDelayVariationBackward() { + assertEquals(301, dmT1.averageInterFrameDelayVariationBackward().toMillis()); + } + + @Test + public void testMaxFrameDelayRangeBackward() { + assertEquals(501, dmT1.maxFrameDelayRangeBackward().toMillis()); + } + + @Test + public void testAverageFrameDelayRangeBackward() { + assertEquals(201, dmT1.averageFrameDelayRangeBackward().toMillis()); + } + +} diff --git a/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossAvailabilityStatCurrentTest.java b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossAvailabilityStatCurrentTest.java new file mode 100644 index 0000000000..d65c307e99 --- /dev/null +++ b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossAvailabilityStatCurrentTest.java @@ -0,0 +1,141 @@ +/* + * 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.incubator.net.l2monitoring.soam.loss; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.time.Duration; +import java.time.Instant; + +import org.junit.Before; +import org.junit.Test; +import org.onosproject.incubator.net.l2monitoring.soam.MilliPct; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossAvailabilityStatCurrent.LaStatCurrentBuilder; + +public class LossAvailabilityStatCurrentTest { + + LossAvailabilityStatCurrent lasc1; + + @Before + public void setUp() { + LaStatCurrentBuilder builder = DefaultLaStatCurrent.builder( + Duration.ofMinutes(13), true, Instant.ofEpochSecond(123456789L)); + builder = (LaStatCurrentBuilder) builder + .backwardAvailable(123456780L) + .backwardAverageFrameLossRatio(MilliPct.ofMilliPct(12345)) + .backwardConsecutiveHighLoss(123456781L) + .backwardHighLoss(123456782L) + .backwardMaxFrameLossRatio(MilliPct.ofMilliPct(12346)) + .backwardMinFrameLossRatio(MilliPct.ofMilliPct(12347)) + .backwardUnavailable(123456783L) + .forwardAvailable(123456784L) + .forwardAverageFrameLossRatio(MilliPct.ofMilliPct(12348)) + .forwardConsecutiveHighLoss(123456785L) + .forwardHighLoss(123456786L) + .forwardMaxFrameLossRatio(MilliPct.ofMilliPct(12349)) + .forwardMinFrameLossRatio(MilliPct.ofMilliPct(12350)) + .forwardUnavailable(123456787L); + + lasc1 = builder.build(); + } + + @Test + public void testStartTime() { + assertEquals(123456789L, lasc1.startTime().getEpochSecond()); + } + + @Test + public void testElapsedTime() { + assertEquals(13, lasc1.elapsedTime().toMinutes()); + } + + @Test + public void testSuspectStatus() { + assertTrue(lasc1.suspectStatus()); + } + + @Test + public void testForwardHighLoss() { + assertEquals(123456786L, lasc1.forwardHighLoss().longValue()); + } + + @Test + public void testBackwardHighLoss() { + assertEquals(123456782L, lasc1.backwardHighLoss().longValue()); + } + + @Test + public void testForwardConsecutiveHighLoss() { + assertEquals(123456785L, lasc1.forwardConsecutiveHighLoss().longValue()); + } + + @Test + public void testBackwardConsecutiveHighLoss() { + assertEquals(123456781L, lasc1.backwardConsecutiveHighLoss().longValue()); + } + + @Test + public void testForwardAvailable() { + assertEquals(123456784L, lasc1.forwardAvailable().longValue()); + } + + @Test + public void testBackwardAvailable() { + assertEquals(123456780L, lasc1.backwardAvailable().longValue()); + } + + @Test + public void testForwardUnavailable() { + assertEquals(123456787L, lasc1.forwardUnavailable().longValue()); + } + + @Test + public void testBackwardUnavailable() { + assertEquals(123456783L, lasc1.backwardUnavailable().longValue()); + } + + @Test + public void testForwardMinFrameLossRatio() { + assertEquals(12350, lasc1.forwardMinFrameLossRatio().intValue()); + } + + @Test + public void testForwardMaxFrameLossRatio() { + assertEquals(12349, lasc1.forwardMaxFrameLossRatio().intValue()); + } + + @Test + public void testForwardAverageFrameLossRatio() { + assertEquals(12348, lasc1.forwardAverageFrameLossRatio().intValue()); + } + + @Test + public void testBackwardMinFrameLossRatio() { + assertEquals(12347, lasc1.backwardMinFrameLossRatio().intValue()); + } + + @Test + public void testBackwardMaxFrameLossRatio() { + assertEquals(12346, lasc1.backwardMaxFrameLossRatio().intValue()); + } + + @Test + public void testBackwardAverageFrameLossRatio() { + assertEquals(12345, lasc1.backwardAverageFrameLossRatio().intValue()); + } + +} diff --git a/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossAvailabilityStatHistoryTest.java b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossAvailabilityStatHistoryTest.java new file mode 100644 index 0000000000..1b68b6e88d --- /dev/null +++ b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossAvailabilityStatHistoryTest.java @@ -0,0 +1,61 @@ +/* + * 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.incubator.net.l2monitoring.soam.loss; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.time.Duration; +import java.time.Instant; + +import org.junit.Before; +import org.junit.Test; +import org.onosproject.incubator.net.l2monitoring.soam.SoamId; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossAvailabilityStatHistory.LaStatHistoryBuilder; + +public class LossAvailabilityStatHistoryTest { + LossAvailabilityStatHistory lash1; + + @Before + public void setUp() { + LaStatHistoryBuilder builder = DefaultLaStatHistory.builder( + Duration.ofMinutes(12), true, SoamId.valueOf(5), + Instant.ofEpochSecond(123456789L)); + + lash1 = builder.build(); + } + + @Test + public void testHistoryStatsId() { + assertEquals(5, lash1.historyStatsId().id().intValue()); + } + + @Test + public void testEndTime() { + assertEquals(123456789L, lash1.endTime().getEpochSecond()); + } + + @Test + public void testElapsedTime() { + assertEquals(12, lash1.elapsedTime().toMinutes()); + } + + @Test + public void testSuspectStatus() { + assertTrue(lash1.suspectStatus()); + } + +} diff --git a/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossMeasurementCreateTest.java b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossMeasurementCreateTest.java new file mode 100644 index 0000000000..c7d1264ded --- /dev/null +++ b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossMeasurementCreateTest.java @@ -0,0 +1,194 @@ +/* + * 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.incubator.net.l2monitoring.soam.loss; + +import static org.junit.Assert.*; + +import java.time.Duration; + +import org.junit.Before; +import org.junit.Test; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep.Priority; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.soam.MeasurementCreateBase.SessionType; +import org.onosproject.incubator.net.l2monitoring.soam.MilliPct; +import org.onosproject.incubator.net.l2monitoring.soam.SoamConfigException; +import org.onosproject.incubator.net.l2monitoring.soam.SoamId; +import org.onosproject.incubator.net.l2monitoring.soam.StartTime; +import org.onosproject.incubator.net.l2monitoring.soam.StopTime; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.DataPattern; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.TestTlvPattern; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.Version; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementCreate.CounterOption; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementCreate.LmCreateBuilder; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementCreate.LmType; + +public class LossMeasurementCreateTest { + + LossMeasurementCreate lmc1; + + @Before + public void setUp() throws SoamConfigException { + + LossMeasurementThreshold lmt1 = DefaultLmThreshold + .builder(SoamId.valueOf(4)).build(); + + + LmCreateBuilder builder = (LmCreateBuilder) DefaultLmCreate + .builder(Version.Y17312008, MepId.valueOf((short) 10), + Priority.PRIO3, LmType.LMLMM) + .addToCountersEnabled(CounterOption.AVAILABILITY_FORWARD_AVERAGE_FLR) + .addToCountersEnabled(CounterOption.AVAILABILITY_FORWARD_CONSECUTIVE_HIGH_LOSS) + .availabilityFlrThreshold(MilliPct.ofRatio(0.201f)) + .availabilityMeasurementInterval(Duration.ofSeconds(5)) + .availabilityNumberConsecutiveFlrMeasurements(6) + .availabilityNumberConsecutiveHighFlr((short) 7) + .availabilityNumberConsecutiveIntervals((short) 8) + .addToLossMeasurementThreshold(lmt1) + .frameSize((short) 100) + .dataPattern(DataPattern.ZEROES) + .testTlvIncluded(true) + .testTlvPattern(TestTlvPattern.NULL_SIGNAL_WITHOUT_CRC_32) + .messagePeriod(Duration.ofMinutes(9)) + .measurementInterval(Duration.ofMinutes(10)) + .numberIntervalsStored((short) 11) + .alignMeasurementIntervals(true) + .alignMeasurementOffset(Duration.ofSeconds(12)) + .startTime(StartTime.immediate()) + .stopTime(StopTime.none()) + .sessionType(SessionType.PROACTIVE); + + lmc1 = builder.build(); + } + + @Test + public void testLmCfgType() { + assertEquals(LmType.LMLMM, lmc1.lmCfgType()); + } + + @Test + public void testCountersEnabled() { + assertEquals(2, lmc1.countersEnabled().size()); + } + + @Test + public void testAvailabilityMeasurementInterval() { + assertEquals(5, lmc1.availabilityMeasurementInterval().getSeconds()); + } + + @Test + public void testAvailabilityNumberConsecutiveFlrMeasurements() { + assertEquals(6, lmc1.availabilityNumberConsecutiveFlrMeasurements().intValue()); + } + + @Test + public void testAvailabilityFlrThreshold() { + assertEquals(0.201f, lmc1.availabilityFlrThreshold().ratioValue(), 0.0001f); + } + + @Test + public void testAvailabilityNumberConsecutiveIntervals() { + assertEquals(8, lmc1.availabilityNumberConsecutiveIntervals().shortValue()); + } + + @Test + public void testAvailabilityNumberConsecutiveHighFlr() { + assertEquals(7, lmc1.availabilityNumberConsecutiveHighFlr().shortValue()); + } + + @Test + public void testLossMeasurementThreshold() { + assertEquals(1, lmc1.lossMeasurementThreshold().size()); + } + + @Test + public void testVersion() { + assertEquals(Version.Y17312008, lmc1.version()); + } + + @Test + public void testRemoteMepId() { + assertEquals(10, lmc1.remoteMepId().id().shortValue()); + } + + @Test + public void testMessagePeriod() { + assertEquals(9, lmc1.messagePeriod().toMinutes()); + } + + @Test + public void testPriority() { + assertEquals(Priority.PRIO3, lmc1.priority()); + } + + @Test + public void testFrameSize() { + assertEquals(100, lmc1.frameSize().shortValue()); + } + + @Test + public void testDataPattern() { + assertEquals(DataPattern.ZEROES, lmc1.dataPattern()); + } + + @Test + public void testTestTlvIncluded() { + assertEquals(true, lmc1.testTlvIncluded()); + } + + @Test + public void testTestTlvPattern() { + assertEquals(TestTlvPattern.NULL_SIGNAL_WITHOUT_CRC_32, lmc1.testTlvPattern()); + } + + @Test + public void testMeasurementInterval() { + assertEquals(10, lmc1.measurementInterval().toMinutes()); + } + + @Test + public void testNumberIntervalsStored() { + assertEquals(11, lmc1.numberIntervalsStored().shortValue()); + } + + @Test + public void testAlignMeasurementIntervals() { + assertEquals(true, lmc1.alignMeasurementIntervals()); + } + + @Test + public void testAlignMeasurementOffset() { + assertEquals(12, lmc1.alignMeasurementOffset().getSeconds()); + } + + @Test + public void testStartTime() { + assertEquals(StartTime.immediate().option(), + lmc1.startTime().option()); + } + + @Test + public void testStopTime() { + assertEquals(StopTime.none().option(), + lmc1.stopTime().option()); + } + + @Test + public void testSessionType() { + assertEquals(SessionType.PROACTIVE, lmc1.sessionType()); + } + +} diff --git a/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossMeasurementEntryTest.java b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossMeasurementEntryTest.java new file mode 100644 index 0000000000..30b637a40d --- /dev/null +++ b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossMeasurementEntryTest.java @@ -0,0 +1,158 @@ +/* + * 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.incubator.net.l2monitoring.soam.loss; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.time.Duration; +import java.time.Instant; +import java.util.ArrayList; + +import org.junit.Before; +import org.junit.Test; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep.Priority; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.soam.MilliPct; +import org.onosproject.incubator.net.l2monitoring.soam.SoamConfigException; +import org.onosproject.incubator.net.l2monitoring.soam.SoamId; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate.Version; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementCreate.CounterOption; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementCreate.LmType; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementEntry.AvailabilityType; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementEntry.LmEntryBuilder; + +public class LossMeasurementEntryTest { + + LossMeasurementEntry lme1; + + @Before + public void setUp() throws SoamConfigException { + LmEntryBuilder builder = DefaultLmEntry.builder( + Version.Y17312008, MepId.valueOf((short) 10), + Priority.PRIO3, LmType.LMLMM, SoamId.valueOf(1)) + .measuredAvailabilityBackwardStatus(AvailabilityType.UNAVAILABLE) + .measuredAvailabilityForwardStatus(AvailabilityType.UNKNOWN) + .measuredBackwardFlr(MilliPct.ofMilliPct(1600)) + .measuredBackwardLastTransitionTime(Instant.ofEpochSecond(123456L)) + .measuredForwardFlr(MilliPct.ofMilliPct(1601)) + .measuredForwardLastTransitionTime(Instant.ofEpochSecond(123457L)) + + .availabilityCurrent(DefaultLaStatCurrent.builder( + Duration.ofMinutes(9), false, Instant.ofEpochSecond(9876543)) + .build()) + .measurementCurrent(DefaultLmStatCurrent.builder( + Duration.ofMinutes(10), true, Instant.ofEpochSecond(9876544)) + .build()) + + .addToAvailabilityHistories(DefaultLaStatHistory.builder( + Duration.ofMinutes(11), true, SoamId.valueOf(10), + Instant.ofEpochSecond(9876545)) + .build()) + .addToAvailabilityHistories(DefaultLaStatHistory.builder( + Duration.ofMinutes(12), true, SoamId.valueOf(11), + Instant.ofEpochSecond(9876546)) + .build()) + + .addToMeasurementHistories(DefaultLmStatHistory.builder( + Duration.ofMinutes(13), true, SoamId.valueOf(12), + Instant.ofEpochSecond(9876547)) + .build()) + .addToMeasurementHistories(DefaultLmStatHistory.builder( + Duration.ofMinutes(14), true, SoamId.valueOf(13), + Instant.ofEpochSecond(9876548)) + .build()); + + builder = (LmEntryBuilder) builder + .addToCountersEnabled(CounterOption.AVAILABILITY_BACKWARD_CONSECUTIVE_HIGH_LOSS) + .addToCountersEnabled(CounterOption.AVAILABILITY_FORWARD_MAX_FLR) + .alignMeasurementIntervals(true) + .frameSize((short) 100); + + lme1 = builder.build(); + } + + @Test + public void testLmId() { + assertEquals(1, lme1.lmId().id().intValue()); + } + + @Test + public void testMeasuredForwardFlr() { + assertEquals(1601, lme1.measuredForwardFlr().intValue()); + } + + @Test + public void testMeasuredBackwardFlr() { + assertEquals(1600, lme1.measuredBackwardFlr().intValue()); + } + + @Test + public void testMeasuredAvailabilityForwardStatus() { + assertEquals(AvailabilityType.UNKNOWN, lme1.measuredAvailabilityForwardStatus()); + } + + @Test + public void testMeasuredAvailabilityBackwardStatus() { + assertEquals(AvailabilityType.UNAVAILABLE, lme1.measuredAvailabilityBackwardStatus()); + } + + @Test + public void testMeasuredForwardLastTransitionTime() { + assertEquals(123457L, lme1.measuredForwardLastTransitionTime().getEpochSecond()); + } + + @Test + public void testMeasuredBackwardLastTransitionTime() { + assertEquals(123456L, lme1.measuredBackwardLastTransitionTime().getEpochSecond()); + } + + @Test + public void testMeasurementCurrent() { + assertEquals(10, lme1.measurementCurrent().elapsedTime().toMinutes()); + } + + @Test + public void testMeasurementHistories() { + assertEquals(2, lme1.measurementHistories().size()); + ArrayList histories = new ArrayList<>(); + lme1.measurementHistories().forEach(histories::add); + assertEquals(14, histories.get(1).elapsedTime().toMinutes()); + } + + @Test + public void testAvailabilityCurrent() { + assertEquals(9, lme1.availabilityCurrent().elapsedTime().toMinutes()); + } + + @Test + public void testAvailabilityHistories() { + assertEquals(2, lme1.measurementHistories().size()); + ArrayList histories = new ArrayList<>(); + lme1.availabilityHistories().forEach(histories::add); + assertEquals(11, histories.get(0).elapsedTime().toMinutes()); + } + + @Test + public void testLmCfgType() { + assertEquals(LmType.LMLMM, lme1.lmCfgType()); + } + + @Test + public void testAlignMeasurementIntervals() { + assertTrue(lme1.alignMeasurementIntervals()); + } +} diff --git a/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossMeasurementStatCurrentTest.java b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossMeasurementStatCurrentTest.java new file mode 100644 index 0000000000..76e82469ba --- /dev/null +++ b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossMeasurementStatCurrentTest.java @@ -0,0 +1,129 @@ +/* + * 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.incubator.net.l2monitoring.soam.loss; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.time.Duration; +import java.time.Instant; + +import org.junit.Before; +import org.junit.Test; +import org.onosproject.incubator.net.l2monitoring.soam.MilliPct; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementStatCurrent.LmStatCurrentBuilder; + +public class LossMeasurementStatCurrentTest { + LossMeasurementStatCurrent lmsc1; + + @Before + public void setUp() { + LmStatCurrentBuilder builder = DefaultLmStatCurrent + .builder(Duration.ofMinutes(14), + true, Instant.ofEpochSecond(12345678L)); + builder = (LmStatCurrentBuilder) builder + .backwardAverageFrameLossRatio(MilliPct.ofMilliPct(301)) + .backwardMaxFrameLossRatio(MilliPct.ofMilliPct(302)) + .backwardMinFrameLossRatio(MilliPct.ofMilliPct(303)) + .backwardReceivedFrames(123456780L) + .backwardTransmittedFrames(123456781L) + .forwardAverageFrameLossRatio(MilliPct.ofMilliPct(304)) + .forwardMaxFrameLossRatio(MilliPct.ofMilliPct(305)) + .forwardMinFrameLossRatio(MilliPct.ofMilliPct(306)) + .forwardReceivedFrames(123456782L) + .forwardTransmittedFrames(123456783L) + .soamPdusReceived(123456784L) + .soamPdusSent(123456785L); + + lmsc1 = builder.build(); + } + + @Test + public void testStartTime() { + assertEquals(12345678L, lmsc1.startTime().getEpochSecond()); + } + + @Test + public void testElapsedTime() { + assertEquals(14, lmsc1.elapsedTime().toMinutes()); + } + + @Test + public void testSuspectStatus() { + assertTrue(lmsc1.suspectStatus()); + } + + @Test + public void testForwardTransmittedFrames() { + assertEquals(123456783L, lmsc1.forwardTransmittedFrames().longValue()); + } + + @Test + public void testForwardReceivedFrames() { + assertEquals(123456782L, lmsc1.forwardReceivedFrames().longValue()); + } + + @Test + public void testForwardMinFrameLossRatio() { + assertEquals(306, lmsc1.forwardMinFrameLossRatio().intValue()); + } + + @Test + public void testForwardMaxFrameLossRatio() { + assertEquals(305, lmsc1.forwardMaxFrameLossRatio().intValue()); + } + + @Test + public void testForwardAverageFrameLossRatio() { + assertEquals(304, lmsc1.forwardAverageFrameLossRatio().intValue()); + } + + @Test + public void testBackwardTransmittedFrames() { + assertEquals(123456781L, lmsc1.backwardTransmittedFrames().longValue()); + } + + @Test + public void testBackwardReceivedFrames() { + assertEquals(123456780L, lmsc1.backwardReceivedFrames().longValue()); + } + + @Test + public void testBackwardMinFrameLossRatio() { + assertEquals(303, lmsc1.backwardMinFrameLossRatio().intValue()); + } + + @Test + public void testBackwardMaxFrameLossRatio() { + assertEquals(302, lmsc1.backwardMaxFrameLossRatio().intValue()); + } + + @Test + public void testBackwardAverageFrameLossRatio() { + assertEquals(301, lmsc1.backwardAverageFrameLossRatio().intValue()); + } + + @Test + public void testSoamPdusSent() { + assertEquals(123456785L, lmsc1.soamPdusSent().longValue()); + } + + @Test + public void testSoamPdusReceived() { + assertEquals(123456784L, lmsc1.soamPdusReceived().longValue()); + } + +} diff --git a/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossMeasurementStatHistoryTest.java b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossMeasurementStatHistoryTest.java new file mode 100644 index 0000000000..46de87c71d --- /dev/null +++ b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossMeasurementStatHistoryTest.java @@ -0,0 +1,61 @@ +/* + * 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.incubator.net.l2monitoring.soam.loss; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.time.Duration; +import java.time.Instant; + +import org.junit.Before; +import org.junit.Test; +import org.onosproject.incubator.net.l2monitoring.soam.SoamId; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementStatHistory.LmStatHistoryBuilder; + +public class LossMeasurementStatHistoryTest { + LossMeasurementStatHistory lmsh1; + + @Before + public void setUp() { + LmStatHistoryBuilder builder = DefaultLmStatHistory.builder( + Duration.ofMinutes(11), true, SoamId.valueOf(6), + Instant.ofEpochSecond(123456789L)); + + lmsh1 = builder.build(); + } + + @Test + public void testHistoryStatsId() { + assertEquals(6, lmsh1.historyStatsId().id().intValue()); + } + + @Test + public void testEndTime() { + assertEquals(123456789L, lmsh1.endTime().getEpochSecond()); + } + + @Test + public void testElapsedTime() { + assertEquals(11, lmsh1.elapsedTime().toMinutes()); + } + + @Test + public void testSuspectStatus() { + assertTrue(lmsh1.suspectStatus()); + } + +} diff --git a/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossMeasurementThresholdOptionTest.java b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossMeasurementThresholdOptionTest.java new file mode 100644 index 0000000000..0882268560 --- /dev/null +++ b/incubator/api/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/loss/LossMeasurementThresholdOptionTest.java @@ -0,0 +1,138 @@ +/* + * 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.incubator.net.l2monitoring.soam.loss; + +import static org.junit.Assert.assertEquals; + +import java.util.ArrayList; + +import org.junit.Before; +import org.junit.Test; +import org.onosproject.incubator.net.l2monitoring.soam.MilliPct; +import org.onosproject.incubator.net.l2monitoring.soam.SoamId; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementThreshold.ThresholdOption; + +public class LossMeasurementThresholdOptionTest { + + LossMeasurementThreshold lmt1; + + @Before + public void setUp() throws Exception { + lmt1 = DefaultLmThreshold + .builder(SoamId.valueOf(4)) + .addToThreshold(ThresholdOption.BACKWARD_CONSECUTIVE_HIGH_LOSS) + .addToThreshold(ThresholdOption.MAX_FLR_BACKWARD) + .averageFlrBackward(MilliPct.ofMilliPct(301)) + .averageFlrForward(MilliPct.ofMilliPct(302)) + .backwardAvailableRatio(MilliPct.ofMilliPct(303)) + .backwardConsecutiveHighLoss(123451L) + .backwardHighLoss(123452L) + .backwardUnavailableCount(123453L) + .forwardAvailableRatio(MilliPct.ofMilliPct(304)) + .forwardConsecutiveHighLoss(123454L) + .forwardHighLoss(123455L) + .forwardUnavailableCount(123456L) + .maxFlrBackward(MilliPct.ofMilliPct(305)) + .maxFlrForward(MilliPct.ofMilliPct(306)) + .measuredFlrBackward(MilliPct.ofMilliPct(307)) + .measuredFlrForward(MilliPct.ofMilliPct(308)) + .build(); + } + + @Test + public void testThresholdId() { + assertEquals(4, lmt1.thresholdId().id().intValue()); + } + + @Test + public void testThreshold() { + assertEquals(2, lmt1.thresholds().size()); + ArrayList list = new ArrayList<>(); + lmt1.thresholds().forEach(list::add); + assertEquals(ThresholdOption.BACKWARD_CONSECUTIVE_HIGH_LOSS, list.get(0)); + assertEquals(ThresholdOption.MAX_FLR_BACKWARD, list.get(1)); + } + + @Test + public void testMeasuredFlrForward() { + assertEquals(308, lmt1.measuredFlrForward().intValue()); + } + + @Test + public void testMaxFlrForward() { + assertEquals(306, lmt1.maxFlrForward().intValue()); + } + + @Test + public void testAverageFlrForward() { + assertEquals(302, lmt1.averageFlrForward().intValue()); + } + + @Test + public void testMeasuredFlrBackward() { + assertEquals(307, lmt1.measuredFlrBackward().intValue()); + } + + @Test + public void testMaxFlrBackward() { + assertEquals(305, lmt1.maxFlrBackward().intValue()); + } + + @Test + public void testAverageFlrBackward() { + assertEquals(301, lmt1.averageFlrBackward().intValue()); + } + + @Test + public void testForwardHighLoss() { + assertEquals(123455L, lmt1.forwardHighLoss().longValue()); + } + + @Test + public void testForwardConsecutiveHighLoss() { + assertEquals(123454L, lmt1.forwardConsecutiveHighLoss().longValue()); + } + + @Test + public void testBackwardHighLoss() { + assertEquals(123452L, lmt1.backwardHighLoss().longValue()); + } + + @Test + public void testBackwardConsecutiveHighLoss() { + assertEquals(123451L, lmt1.backwardConsecutiveHighLoss().longValue()); + } + + @Test + public void testForwardUnavailableCount() { + assertEquals(123456L, lmt1.forwardUnavailableCount().longValue()); + } + + @Test + public void testForwardAvailableRatio() { + assertEquals(304, lmt1.forwardAvailableRatio().intValue()); + } + + @Test + public void testBackwardUnavailableCount() { + assertEquals(123453L, lmt1.backwardUnavailableCount().longValue()); + } + + @Test + public void testBackwardAvailableRatio() { + assertEquals(303, lmt1.backwardAvailableRatio().intValue()); + } +} diff --git a/incubator/net/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/impl/CfmMdManager.java b/incubator/net/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/impl/CfmMdManager.java new file mode 100644 index 0000000000..5a125f5b4c --- /dev/null +++ b/incubator/net/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/impl/CfmMdManager.java @@ -0,0 +1,171 @@ +/* + * 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.incubator.net.l2monitoring.cfm.impl; + +import java.util.Collection; +import java.util.Optional; + +import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Deactivate; +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.ReferenceCardinality; +import org.apache.felix.scr.annotations.Service; +import org.onosproject.core.ApplicationId; +import org.onosproject.core.CoreService; +import org.onosproject.event.AbstractListenerManager; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMaintenanceDomain; +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceAssociation; +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMdService; +import org.onosproject.incubator.net.l2monitoring.cfm.service.MdEvent; +import org.onosproject.incubator.net.l2monitoring.cfm.service.MdListener; +import org.onosproject.incubator.net.l2monitoring.cfm.service.MdStore; +import org.onosproject.incubator.net.l2monitoring.cfm.service.MdStoreDelegate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Manager of Cfm Md Service - persists Maintenance Domain in distributed store. + */ +@Component(immediate = true) +@Service +public class CfmMdManager extends AbstractListenerManager + implements CfmMdService { + + private final Logger log = LoggerFactory.getLogger(getClass()); + private static final String APP_ID = "org.onosproject.app.cfm"; + + protected ApplicationId appId; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected CoreService coreService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected MdStore store; + + protected final MdStoreDelegate delegate = new InternalStoreDelegate(); + + @Activate + public void activate() { + appId = coreService.registerApplication(APP_ID); + + eventDispatcher.addSink(MdEvent.class, listenerRegistry); + store.setDelegate(delegate); + + log.info("CFM Service Started"); + } + + @Deactivate + public void deactivate() { + eventDispatcher.removeSink(MdEvent.class); + store.unsetDelegate(delegate); + log.info("CFM Service Stopped"); + } + + @Override + public Collection getAllMaintenanceDomain() { + log.debug("Retrieving all MDs from distributed store"); + return store.getAllMaintenanceDomain(); + } + + @Override + public Optional getMaintenanceDomain(MdId mdName) { + log.debug("Retrieving MD {} from distributed store", mdName); + return store.getMaintenanceDomain(mdName); + } + + @Override + public boolean deleteMaintenanceDomain(MdId mdName) throws CfmConfigException { + log.info("Deleting MD {} from distributed store", mdName); + return store.deleteMaintenanceDomain(mdName); + } + + @Override + public Collection getAllMaintenanceAssociation(MdId mdName) { + log.debug("Retrieving all MA of MD {} from distributed store", mdName); + return store.getMaintenanceDomain(mdName) + .orElseThrow(() -> new IllegalArgumentException("Unknown MD " + mdName)) + .maintenanceAssociationList(); + } + + @Override + public Optional getMaintenanceAssociation( + MdId mdName, MaIdShort maName) { + log.debug("Retrieving MA {} of MD {} from distributed store", maName, mdName); + return store.getMaintenanceDomain(mdName) + .orElseThrow(() -> new IllegalArgumentException("Unknown MD " + mdName)) + .maintenanceAssociationList() + .stream().filter(ma -> ma.maId().equals(maName)) + .findFirst(); + } + + @Override + public boolean deleteMaintenanceAssociation(MdId mdName, MaIdShort maName) throws CfmConfigException { + log.info("Deleting MA {} of MD {} from distributed store", maName, mdName); + MaintenanceDomain.MdBuilder builder = DefaultMaintenanceDomain + .builder(store.getMaintenanceDomain(mdName) + .orElseThrow(() -> new IllegalArgumentException("Unknown MD: " + mdName))); + + //Check the MA is present + if (!builder.checkMaExists(maName)) { + return false; + } + + builder = builder.deleteFromMaList(maName); + + store.createUpdateMaintenanceDomain(builder.build()); + return true; + } + + @Override + public boolean createMaintenanceDomain(MaintenanceDomain newMd) throws CfmConfigException { + log.info("Creating/Updating MD {} in distributed store", newMd.mdId()); + return store.createUpdateMaintenanceDomain(newMd); + } + + @Override + public boolean createMaintenanceAssociation(MdId mdName, MaintenanceAssociation newMa) + throws CfmConfigException { + log.info("Updating MD {} in distributed store by adding new MA {}", mdName, newMa.maId()); + MaintenanceDomain.MdBuilder builder = DefaultMaintenanceDomain + .builder(store.getMaintenanceDomain(mdName) + .orElseThrow(() -> new IllegalArgumentException("Unknown MD: " + mdName))); + + boolean replaced = false; + //Check the MA is present + if (builder.checkMaExists(newMa.maId())) { + builder = builder.deleteFromMaList(newMa.maId()); + replaced = true; + } + + builder.addToMaList(newMa); + store.createUpdateMaintenanceDomain(builder.build()); + return replaced; + } + + private class InternalStoreDelegate implements MdStoreDelegate { + @Override + public void notify(MdEvent event) { + log.debug("New MD event: {}", event.subject()); + eventDispatcher.post(event); + } + } + +} diff --git a/incubator/net/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/impl/CfmMepManager.java b/incubator/net/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/impl/CfmMepManager.java new file mode 100644 index 0000000000..5723466b0e --- /dev/null +++ b/incubator/net/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/impl/CfmMepManager.java @@ -0,0 +1,292 @@ +/* + * 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.incubator.net.l2monitoring.cfm.impl; + +import static org.slf4j.LoggerFactory.getLogger; + +import java.util.ArrayList; +import java.util.Collection; + +import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Deactivate; +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.ReferenceCardinality; +import org.apache.felix.scr.annotations.Service; +import org.onosproject.core.CoreService; +import org.onosproject.core.IdGenerator; +import org.onosproject.event.AbstractListenerManager; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep; +import org.onosproject.incubator.net.l2monitoring.cfm.MepEntry; +import org.onosproject.incubator.net.l2monitoring.cfm.MepLbCreate; +import org.onosproject.incubator.net.l2monitoring.cfm.MepLtCreate; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMdService; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepEvent; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepListener; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepProgrammable; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepService; +import org.onosproject.mastership.MastershipService; +import org.onosproject.net.Device; +import org.onosproject.net.DeviceId; +import org.onosproject.net.device.DeviceEvent; +import org.onosproject.net.device.DeviceListener; +import org.onosproject.net.device.DeviceService; +import org.slf4j.Logger; + +/** + * Provides implementation of the CFM North and South Bound Interfaces. + */ +@Component(immediate = true) +@Service +public class CfmMepManager + extends AbstractListenerManager + implements CfmMepService { + + private final Logger log = getLogger(getClass()); + + private final DeviceListener deviceListener = new InternalDeviceListener(); + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected DeviceService deviceService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected CoreService coreService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected MastershipService mastershipService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected CfmMdService cfmMdService; + + private static final int DEFAULT_POLL_FREQUENCY = 30; + private int fallbackMepPollFrequency = DEFAULT_POLL_FREQUENCY; + + private IdGenerator idGenerator; + + //FIXME Get rid of this hack - we will use this in memory to emulate + // a store for the short term. + //Note: This is not distributed and will not work in a clustered system + //TODO Create a MepStore for this + private Collection mepCollection; + + + @Activate + public void activate() { + //FIXME Get rid of this local list + mepCollection = new ArrayList<>(); + + eventDispatcher.addSink(CfmMepEvent.class, listenerRegistry); + deviceService.addListener(deviceListener); + idGenerator = coreService.getIdGenerator("mep-ids"); + log.info("CFM MEP Manager Started"); + } + + @Deactivate + public void deactivate() { + deviceService.removeListener(deviceListener); + eventDispatcher.removeSink(CfmMepEvent.class); + log.info("CFM MEP Manager Stopped"); + mepCollection.clear(); + } + + @Override + public Collection getAllMeps(MdId mdName, MaIdShort maName) + throws CfmConfigException { + //Will throw IllegalArgumentException if ma does not exist + cfmMdService.getMaintenanceAssociation(mdName, maName); + + Collection mepEntryCollection = new ArrayList<>(); + + for (Mep mep:mepCollection) { + if (mep.mdId().equals(mdName) && mep.maId().equals(maName)) { + DeviceId mepDeviceId = mep.deviceId(); + if (deviceService.getDevice(mepDeviceId) == null) { + log.warn("Device not found/available " + mepDeviceId + + " for MEP: " + mdName + "/" + maName + "/" + mep.mepId()); + continue; + } else if (!deviceService.getDevice(mepDeviceId) + .is(CfmMepProgrammable.class)) { + throw new CfmConfigException("Device " + mepDeviceId + + " does not support CfmMepProgrammable behaviour."); + } + + log.debug("Retrieving MEP results for Mep {} in MD {}, MA {} " + + "on Device {}", mep.mepId(), mdName, maName, mepDeviceId); + mepEntryCollection.add(deviceService + .getDevice(mepDeviceId) + .as(CfmMepProgrammable.class) + .getMep(mdName, maName, mep.mepId())); + } + } + + return mepEntryCollection; + } + + @Override + public MepEntry getMep(MdId mdName, MaIdShort maName, MepId mepId) throws CfmConfigException { + //Will throw IllegalArgumentException if ma does not exist + cfmMdService.getMaintenanceAssociation(mdName, maName); + + for (Mep mep : mepCollection) { + if (mep.mdId().equals(mdName) && mep.maId().equals(maName) + && mep.mepId().equals(mepId)) { + + DeviceId mepDeviceId = mep.deviceId(); + if (deviceService.getDevice(mepDeviceId) == null) { + throw new CfmConfigException("Device not found " + mepDeviceId); + } else if (!deviceService.getDevice(mepDeviceId).is(CfmMepProgrammable.class)) { + throw new CfmConfigException("Device " + mepDeviceId + + " does not support CfmMepProgrammable behaviour."); + } + + log.debug("Retrieving MEP reults for Mep {} in MD {}, MA {} on Device {}", + mep.mepId(), mdName, maName, mepDeviceId); + + return deviceService.getDevice(mepDeviceId) + .as(CfmMepProgrammable.class).getMep(mdName, maName, mepId); + } + } + return null; + } + + @Override + public boolean deleteMep(MdId mdName, MaIdShort maName, MepId mepId) throws CfmConfigException { + //Will throw IllegalArgumentException if ma does not exist + cfmMdService.getMaintenanceAssociation(mdName, maName); + + for (Mep mep : mepCollection) { + if (mep.mdId().equals(mdName) && mep.maId().equals(maName) + && mep.mepId().equals(mepId)) { + Device mepDevice = deviceService.getDevice(mep.deviceId()); + if (mepDevice == null || !mepDevice.is(CfmMepProgrammable.class)) { + throw new CfmConfigException("Unexpeced fault on device drier for " + + mep.deviceId()); + } + boolean deleted = false; + try { + deleted = mepDevice.as(CfmMepProgrammable.class) + .deleteMep(mdName, maName, mepId); + } catch (CfmConfigException e) { + log.warn("MEP could not be deleted on device - perhaps it " + + "does not exist. Continuing"); + mepCollection.remove(mep); + return false; + } + if (deleted) { + mepCollection.remove(mep); + return true; + } else { + return false; + } + } + } + return false; + } + + @Override + public boolean createMep(MdId mdName, MaIdShort maName, Mep newMep) throws CfmConfigException { + log.debug("Creating MEP " + newMep.mepId() + " on MD {}, MA {} on Device {}", + mdName, maName, newMep.deviceId().toString()); + for (Mep mep : mepCollection) { + if (mep.mdId().equals(mdName) && mep.maId().equals(maName) + && mep.mepId().equals(newMep.mepId())) { + return false; + } + } + + //Will throw IllegalArgumentException if ma does not exist + cfmMdService.getMaintenanceAssociation(mdName, maName); + + DeviceId mepDeviceId = newMep.deviceId(); + if (deviceService.getDevice(mepDeviceId) == null) { + throw new CfmConfigException("Device not found " + mepDeviceId); + } else if (!deviceService.getDevice(mepDeviceId).is(CfmMepProgrammable.class)) { + throw new CfmConfigException("Device " + mepDeviceId + " does not support CfmMepProgrammable behaviour."); + } + + boolean deviceResult = + deviceService.getDevice(mepDeviceId).as(CfmMepProgrammable.class).createMep(mdName, maName, newMep); + log.debug("MEP created on {}", mepDeviceId); + if (deviceResult) { + return mepCollection.add(newMep); + } else { + return deviceResult; + } + } + + @Override + public void transmitLoopback(MdId mdName, MaIdShort maName, + MepId mepId, MepLbCreate lbCreate) throws CfmConfigException { + for (Mep mep : mepCollection) { + if (mep.mdId().equals(mdName) && mep.maId().equals(maName) + && mep.mepId().equals(mepId)) { + log.debug("Transmitting Loopback on MEP {}/{}/{} on Device {}", + mdName, maName, mepId, mep.deviceId()); + deviceService.getDevice(mep.deviceId()) + .as(CfmMepProgrammable.class) + .transmitLoopback(mdName, maName, mepId, lbCreate); + return; + } + } + throw new CfmConfigException("Mep " + mdName + "/" + maName + "/" + + mepId + " not found when calling Transmit Loopback"); + } + + @Override + public void abortLoopback(MdId mdName, MaIdShort maName, MepId mepId) + throws CfmConfigException { + for (Mep mep : mepCollection) { + if (mep.mdId().equals(mdName) && mep.maId().equals(maName) + && mep.mepId().equals(mepId)) { + log.debug("Aborting Loopback on MEP {}/{}/{} on Device {}", + mdName, maName, mepId, mep.deviceId()); + deviceService.getDevice(mep.deviceId()) + .as(CfmMepProgrammable.class) + .abortLoopback(mdName, maName, mepId); + return; + } + } + throw new CfmConfigException("Mep " + mdName + "/" + maName + "/" + + mepId + " not found when calling Transmit Loopback"); + } + + @Override + public void transmitLinktrace(MdId mdName, MaIdShort maName, MepId mepId, + MepLtCreate ltCreate) { + throw new UnsupportedOperationException("Not yet implemented"); + } + + private class InternalDeviceListener implements DeviceListener { + @Override + public void event(DeviceEvent event) { + switch (event.type()) { + case DEVICE_REMOVED: + case DEVICE_AVAILABILITY_CHANGED: + DeviceId deviceId = event.subject().id(); + if (!deviceService.isAvailable(deviceId)) { + log.warn("Device {} has been removed or changed", deviceId); + } + break; + default: + break; + } + } + } +} diff --git a/incubator/net/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/impl/DistributedMdStore.java b/incubator/net/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/impl/DistributedMdStore.java new file mode 100644 index 0000000000..964a56a12d --- /dev/null +++ b/incubator/net/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/impl/DistributedMdStore.java @@ -0,0 +1,159 @@ +/* + * 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.incubator.net.l2monitoring.cfm.impl; + +import com.google.common.net.InternetDomainName; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.ReferenceCardinality; +import org.apache.felix.scr.annotations.Service; +import org.onlab.packet.MacAddress; +import org.onlab.util.Identifier; +import org.onlab.util.KryoNamespace; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultComponent; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMaintenanceAssociation; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMaintenanceDomain; +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceAssociation; +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaId2Octet; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdIccY1731; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdPrimaryVid; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdRfc2685VpnId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdDomainName; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdMacUint; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdNone; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.cfm.service.MdEvent; +import org.onosproject.incubator.net.l2monitoring.cfm.service.MdStore; +import org.onosproject.incubator.net.l2monitoring.cfm.service.MdStoreDelegate; +import org.onosproject.store.serializers.KryoNamespaces; +import org.onosproject.store.AbstractStore; +import org.onosproject.store.service.ConsistentMap; +import org.onosproject.store.service.MapEvent; +import org.onosproject.store.service.MapEventListener; +import org.onosproject.store.service.Serializer; +import org.onosproject.store.service.StorageService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Collection; +import java.util.Map; +import java.util.Optional; + +/** + * Maintenance Domain Store implementation backed by consistent map. + */ +@Component(immediate = true) +@Service +public class DistributedMdStore extends AbstractStore + implements MdStore { + + private final Logger log = LoggerFactory.getLogger(getClass()); + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected StorageService storageService; + + private ConsistentMap maintenanceDomainConsistentMap; + private Map maintenanceDomainMap; + + private final InternalMdListener listener = new InternalMdListener(); + + @Activate + public void activate() { + maintenanceDomainConsistentMap = storageService + .consistentMapBuilder() + .withName("onos-cfm-ma-map") + .withSerializer(Serializer.using(new KryoNamespace.Builder() + .register(KryoNamespaces.API) + .register(DefaultMaintenanceDomain.class) + .register(MdIdCharStr.class) + .register(MdIdDomainName.class) + .register(MdIdMacUint.class) + .register(MdIdNone.class) + .register(MaintenanceDomain.MdLevel.class) + .register(DefaultMaintenanceAssociation.class) + .register(MaIdCharStr.class) + .register(MaIdShort.class) + .register(MaId2Octet.class) + .register(MaIdIccY1731.class) + .register(MaIdPrimaryVid.class) + .register(MaIdRfc2685VpnId.class) + .register(MaintenanceAssociation.CcmInterval.class) + .register(DefaultComponent.class) + .register(MepId.class) + .register(Identifier.class) + .register(InternetDomainName.class) + .register(MacAddress.class) + .register(ImmutablePair.class) + .register(org.onosproject.incubator.net.l2monitoring + .cfm.Component.MhfCreationType.class) + .register(org.onosproject.incubator.net.l2monitoring + .cfm.Component.IdPermissionType.class) + .register(org.onosproject.incubator.net.l2monitoring + .cfm.Component.TagType.class) + .build("md"))) + .build(); + + maintenanceDomainMap = maintenanceDomainConsistentMap.asJavaMap(); + } + + @Override + public Collection getAllMaintenanceDomain() { + return maintenanceDomainMap.values(); + } + + @Override + public Optional getMaintenanceDomain(MdId mdName) { + return Optional.ofNullable( + maintenanceDomainMap.get(mdName)); + } + + @Override + public boolean deleteMaintenanceDomain(MdId mdName) { + return maintenanceDomainMap.remove(mdName) == null ? false : true; + } + + @Override + public boolean createUpdateMaintenanceDomain(MaintenanceDomain md) { + return maintenanceDomainMap.put(md.mdId(), md) == null ? false : true; + } + + private class InternalMdListener implements MapEventListener { + @Override + public void event(MapEvent mapEvent) { + final MdEvent.Type type; + switch (mapEvent.type()) { + case INSERT: + type = MdEvent.Type.MD_ADDED; + break; + case UPDATE: + type = MdEvent.Type.MD_UPDATED; + break; + case REMOVE: + default: + type = MdEvent.Type.MD_REMOVED; + break; + } + notifyDelegate(new MdEvent(type, mapEvent.key())); + } + } +} diff --git a/incubator/net/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/impl/package-info.java b/incubator/net/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/impl/package-info.java new file mode 100644 index 0000000000..3542f07490 --- /dev/null +++ b/incubator/net/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/impl/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2015-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. + */ + +/** + * An implementation of Layer 2 CFM (Connectivity Fault Management). + */ +package org.onosproject.incubator.net.l2monitoring.cfm.impl; \ No newline at end of file diff --git a/incubator/net/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/impl/SoamManager.java b/incubator/net/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/impl/SoamManager.java new file mode 100644 index 0000000000..9a351cac28 --- /dev/null +++ b/incubator/net/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/impl/SoamManager.java @@ -0,0 +1,271 @@ +/* + * 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.incubator.net.l2monitoring.soam.impl; + +import java.util.Collection; +import java.util.Optional; + +import org.apache.felix.scr.annotations.Activate; +import org.apache.felix.scr.annotations.Component; +import org.apache.felix.scr.annotations.Deactivate; +import org.apache.felix.scr.annotations.Reference; +import org.apache.felix.scr.annotations.ReferenceCardinality; +import org.apache.felix.scr.annotations.Service; +import org.onosproject.core.ApplicationId; +import org.onosproject.core.CoreService; +import org.onosproject.incubator.net.l2monitoring.cfm.MepEntry; +import org.onosproject.incubator.net.l2monitoring.cfm.MepTsCreate; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepService; +import org.onosproject.incubator.net.l2monitoring.soam.SoamConfigException; +import org.onosproject.incubator.net.l2monitoring.soam.SoamDmProgrammable; +import org.onosproject.incubator.net.l2monitoring.soam.SoamId; +import org.onosproject.incubator.net.l2monitoring.soam.SoamService; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementEntry; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStatCurrent; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStatHistory; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementCreate; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementEntry; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementStatCurrent; +import org.onosproject.net.DeviceId; +import org.onosproject.net.device.DeviceService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * ONOS application component. + */ +@Component(immediate = true) +@Service +public class SoamManager implements SoamService { + + private final Logger log = LoggerFactory.getLogger(getClass()); + private static final String APP_ID = "org.onosproject.app.soam"; + + private ApplicationId appId; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected DeviceService deviceService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected CoreService coreService; + + @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) + protected CfmMepService cfmMepService; + + @Activate + protected void activate() { + appId = coreService.registerApplication(APP_ID); + + log.info("SOAM Service Started"); + } + + @Deactivate + protected void deactivate() { + log.info("SOAM Service Stopped"); + } + + @Override + public Collection getAllDms( + MdId mdName, MaIdShort maName, MepId mepId) + throws CfmConfigException, SoamConfigException { + MepEntry mep = cfmMepService.getMep(mdName, maName, mepId); + log.debug("Retrieving DMs for MD {}, MA {}, MEP {} on Device {}", + mdName, maName, mepId, mep.deviceId()); + return mep.delayMeasurementList(); + }; + + @Override + public DelayMeasurementEntry getDm(MdId mdName, MaIdShort maName, MepId mepId, SoamId dmId) + throws CfmConfigException, SoamConfigException { + MepEntry mep = cfmMepService.getMep(mdName, maName, mepId); + if (mep == null || mep.deviceId() == null) { + throw new CfmConfigException("MEP :" + + mdName + "/" + maName + "/" + mepId + " does not exist"); + } else if (deviceService.getDevice(mep.deviceId()) == null) { + throw new CfmConfigException("Device " + mep.deviceId() + " from MEP :" + + mdName + "/" + maName + "/" + mepId + " does not exist"); + } else if (!deviceService.getDevice(mep.deviceId()).is(SoamDmProgrammable.class)) { + throw new CfmConfigException("Device " + mep.deviceId() + " from MEP :" + + mdName + "/" + maName + "/" + mepId + + " does not implement SoamDmProgrammable"); + } + log.debug("Retrieving DM for DM {} in MD {}, MA {}, MEP {} on Device {}", + dmId, mdName, maName, mepId, mep.deviceId()); + return deviceService.getDevice(mep.deviceId()) + .as(SoamDmProgrammable.class).getDm(mdName, maName, mepId, dmId); + } + + @Override + public DelayMeasurementStatCurrent getDmCurrentStat(MdId mdName, + MaIdShort maName, MepId mepId, SoamId dmId) + throws CfmConfigException, SoamConfigException { + MepEntry mep = cfmMepService.getMep(mdName, maName, mepId); + if (mep == null || mep.deviceId() == null) { + throw new CfmConfigException("MEP :" + + mdName + "/" + maName + "/" + mepId + " does not exist"); + } else if (deviceService.getDevice(mep.deviceId()) == null) { + throw new CfmConfigException("Device " + mep.deviceId() + " from MEP :" + + mdName + "/" + maName + "/" + mepId + " does not exist"); + } else if (!deviceService.getDevice(mep.deviceId()).is(SoamDmProgrammable.class)) { + throw new CfmConfigException("Device " + mep.deviceId() + " from MEP :" + + mdName + "/" + maName + "/" + mepId + + " does not implement SoamDmProgrammable"); + } + log.debug("Retrieving Current Stats for DM {} in MD {}, MA {}, MEP {} " + + "on Device {}", dmId, mdName, maName, mepId, mep.deviceId()); + return deviceService.getDevice(mep.deviceId()) + .as(SoamDmProgrammable.class).getDmCurrentStat(mdName, maName, mepId, dmId); + } + + @Override + public Collection getDmHistoricalStats( + MdId mdName, MaIdShort maName, MepId mepId, SoamId dmId) + throws SoamConfigException, CfmConfigException { + MepEntry mep = cfmMepService.getMep(mdName, maName, mepId); + if (mep == null || mep.deviceId() == null) { + throw new CfmConfigException("MEP :" + + mdName + "/" + maName + "/" + mepId + " does not exist"); + } else if (deviceService.getDevice(mep.deviceId()) == null) { + throw new CfmConfigException("Device " + mep.deviceId() + " from MEP :" + + mdName + "/" + maName + "/" + mepId + " does not exist"); + } else if (!deviceService.getDevice(mep.deviceId()).is(SoamDmProgrammable.class)) { + throw new CfmConfigException("Device " + mep.deviceId() + " from MEP :" + + mdName + "/" + maName + "/" + mepId + + " does not implement SoamDmProgrammable"); + } + log.debug("Retrieving History Stats for DM {} in MD {}, MA {}, MEP {} " + + "on Device {}", dmId, mdName, maName, mepId, mep.deviceId()); + return deviceService.getDevice(mep.deviceId()) + .as(SoamDmProgrammable.class).getDmHistoricalStats(mdName, maName, mepId, dmId); + } + + @Override + public Optional createDm(MdId mdName, MaIdShort maName, MepId mepId, + DelayMeasurementCreate dmNew) + throws CfmConfigException, SoamConfigException { + DeviceId mepDeviceId = cfmMepService.getMep(mdName, maName, mepId).deviceId(); + if (mepDeviceId == null) { + throw new CfmConfigException("Unable to create DM. MEP :" + + mdName + "/" + maName + "/" + mepId + " does not exist"); + } else if (deviceService.getDevice(mepDeviceId) == null) { + throw new CfmConfigException("Device " + mepDeviceId + " from MEP :" + + mdName + "/" + maName + "/" + mepId + " does not exist"); + } else if (!deviceService.getDevice(mepDeviceId).is(SoamDmProgrammable.class)) { + throw new CfmConfigException("Device " + mepDeviceId + " from MEP :" + + mdName + "/" + maName + "/" + mepId + + " does not implement SoamDmProgrammable"); + } + log.debug("Creating new DM in MD {}, MA {}, MEP {} on Device {}", + mdName, maName, mepId, mepDeviceId); + return deviceService.getDevice(mepDeviceId) + .as(SoamDmProgrammable.class).createDm(mdName, maName, mepId, dmNew); + } + + @Override + public void abortDm(MdId mdName, MaIdShort maName, MepId mepId) + throws CfmConfigException { + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public void abortDm(MdId mdName, MaIdShort maName, MepId mepId, SoamId dmId) + throws CfmConfigException { + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public void clearDelayHistoryStats(MdId mdName, MaIdShort maName, + MepId mepId) throws CfmConfigException { + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public void clearDelayHistoryStats(MdId mdName, MaIdShort maName, + MepId mepId, SoamId dmId) throws CfmConfigException { + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public Collection getAllLms(MdId mdName, + MaIdShort maName, MepId mepId) throws CfmConfigException { + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public LossMeasurementEntry getLm(MdId mdName, MaIdShort maName, + MepId mepId, SoamId lmId) throws CfmConfigException { + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public LossMeasurementStatCurrent getLmCurrentStat(MdId mdName, + MaIdShort maName, MepId mepId, SoamId lmId) { + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public Collection getLmHistoricalStats( + MdId mdName, MaIdShort maName, MepId mepId, SoamId lmId) { + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public Optional createLm(MdId mdName, MaIdShort maName, MepId mepId, + LossMeasurementCreate lm) throws CfmConfigException { + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public void abortLm(MdId mdName, MaIdShort maName, MepId mepId) + throws CfmConfigException { + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public void abortLm(MdId mdName, MaIdShort maName, MepId mepId, SoamId lmId) + throws CfmConfigException { + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public void clearLossHistoryStats(MdId mdName, MaIdShort maName, + MepId mepId) throws CfmConfigException { + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public void clearLossHistoryStats(MdId mdName, MaIdShort maName, + MepId mepId, SoamId lmId) throws CfmConfigException { + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public void createTestSignal(MdId mdName, MaIdShort maName, MepId mepId, + MepTsCreate tsCreate) throws CfmConfigException { + throw new UnsupportedOperationException("Not yet implemented"); + } + + @Override + public void abortTestSignal(MdId mdName, MaIdShort maName, MepId mepId) + throws CfmConfigException { + throw new UnsupportedOperationException("Not yet implemented"); + } +} diff --git a/incubator/net/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/impl/package-info.java b/incubator/net/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/impl/package-info.java new file mode 100644 index 0000000000..fd932e0ec7 --- /dev/null +++ b/incubator/net/src/main/java/org/onosproject/incubator/net/l2monitoring/soam/impl/package-info.java @@ -0,0 +1,20 @@ +/* + * Copyright 2015-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. + */ + +/** + * An implementation of Layer 2 CFM Service Operations and Maintenance (SOAM). + */ +package org.onosproject.incubator.net.l2monitoring.soam.impl; \ No newline at end of file diff --git a/incubator/net/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/impl/CfmMdManagerTest.java b/incubator/net/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/impl/CfmMdManagerTest.java new file mode 100644 index 0000000000..a0de513ff8 --- /dev/null +++ b/incubator/net/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/impl/CfmMdManagerTest.java @@ -0,0 +1,386 @@ +/* + * 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.incubator.net.l2monitoring.cfm.impl; + +import com.google.common.collect.Sets; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.onlab.junit.TestUtils; +import org.onlab.packet.IpAddress; +import org.onosproject.cluster.ClusterServiceAdapter; +import org.onosproject.cluster.ControllerNode; +import org.onosproject.cluster.DefaultControllerNode; +import org.onosproject.cluster.NodeId; +import org.onosproject.common.event.impl.TestEventDispatcher; +import org.onosproject.core.CoreServiceAdapter; +import org.onosproject.core.DefaultApplicationId; +import org.onosproject.core.IdGenerator; +import org.onosproject.incubator.net.l2monitoring.cfm.Component; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultComponent; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMaintenanceAssociation; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMaintenanceDomain; +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceAssociation; +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceDomain; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMdService; +import org.onosproject.mastership.MastershipServiceAdapter; +import org.onosproject.net.DeviceId; +import org.onosproject.store.service.TestStorageService; + +import java.util.Collection; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.atomic.AtomicLong; + +import static junit.framework.TestCase.assertFalse; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.onosproject.net.NetTestTools.injectEventDispatcher; + +/** + * CFM MD Manager test. + */ +public class CfmMdManagerTest { + private static final NodeId NID_LOCAL = new NodeId("local"); + private static final IpAddress LOCALHOST = IpAddress.valueOf("127.0.0.1"); + + private DistributedMdStore mdStore; + private CfmMdService service; + private CfmMdManager manager; + + @Before + public void setup() throws Exception, CfmConfigException { + mdStore = new DistributedMdStore(); + + MaintenanceAssociation maTest11 = DefaultMaintenanceAssociation + .builder(MaIdCharStr.asMaId("test-ma-1-1"), 9) + .ccmInterval(MaintenanceAssociation.CcmInterval.INTERVAL_10MIN) + .maNumericId((short) 1) + .addToRemoteMepIdList(MepId.valueOf((short) 101)) + .addToRemoteMepIdList(MepId.valueOf((short) 102)) + .addToComponentList( + DefaultComponent.builder(1) + .tagType(Component.TagType.VLAN_CTAG) + .build()) + .build(); + + MaintenanceAssociation maTest12 = DefaultMaintenanceAssociation + .builder(MaIdCharStr.asMaId("test-ma-1-2"), 9) + .ccmInterval(MaintenanceAssociation.CcmInterval.INTERVAL_10MIN) + .maNumericId((short) 2) + .addToRemoteMepIdList(MepId.valueOf((short) 201)) + .addToRemoteMepIdList(MepId.valueOf((short) 202)) + .addToComponentList( + DefaultComponent.builder(2) + .tagType(Component.TagType.VLAN_CTAG) + .build()) + .build(); + + MaintenanceDomain mdTest1 = DefaultMaintenanceDomain + .builder(MdIdCharStr.asMdId("test-md-1")) + .mdLevel(MaintenanceDomain.MdLevel.LEVEL1) + .mdNumericId((short) 1) + .addToMaList(maTest11) + .addToMaList(maTest12) + .build(); + + TestUtils.setField(mdStore, "storageService", new TestStorageService()); + TestUtils.setField(mdStore, "clusterService", new CfmMdManagerTest.TestClusterService()); + TestUtils.setField(mdStore, "mastershipService", new CfmMdManagerTest.TestMastershipService()); + mdStore.activate(); + mdStore.createUpdateMaintenanceDomain(mdTest1); + + manager = new CfmMdManager(); + manager.store = mdStore; + service = manager; + TestUtils.setField(manager, "storageService", new TestStorageService()); + TestUtils.setField(manager, "coreService", new TestCoreService()); + injectEventDispatcher(manager, new TestEventDispatcher()); + + manager.appId = new CfmMdManagerTest.TestApplicationId(0, "CfmMdManagerTest"); + manager.activate(); + } + + @After + public void tearDown() { + + manager.deactivate(); + injectEventDispatcher(manager, null); + + } + + @Test + public void testGetAllMaintenanceDomain() { + Collection mdList = service.getAllMaintenanceDomain(); + assertEquals(1, mdList.size()); + + MaintenanceDomain md = mdList.iterator().next(); + assertEquals(1, md.mdNumericId()); + + assertEquals(2, md.maintenanceAssociationList().size()); + + md.maintenanceAssociationList().iterator().forEachRemaining(ma -> + assertTrue(ma.maId().maName().endsWith(String.valueOf(ma.maNumericId()))) + ); + } + + @Test + public void testGetMaintenanceDomain() { + Optional md = + service.getMaintenanceDomain(MdIdCharStr.asMdId("test-md-1")); + assertTrue(md.isPresent()); + + assertEquals(1, md.get().mdNumericId()); + + assertEquals(2, md.get().maintenanceAssociationList().size()); + + + + //Now try an invalid name + Optional mdInvalid = + service.getMaintenanceDomain(MdIdCharStr.asMdId("test-md-3")); + assertFalse(mdInvalid.isPresent()); + } + + @Test + public void testDeleteMaintenanceDomain() { + try { + assertTrue(service.deleteMaintenanceDomain( + MdIdCharStr.asMdId("test-md-1"))); + } catch (CfmConfigException e) { + fail("Should not have thrown exception: " + e.getMessage()); + } + + //Now try an invalid name + try { + assertFalse(service.deleteMaintenanceDomain( + MdIdCharStr.asMdId("test-md-3"))); + } catch (CfmConfigException e) { + fail("Should not have thrown exception: " + e.getMessage()); + } + } + + @Test + public void testCreateMaintenanceDomain() throws CfmConfigException { + + MaintenanceAssociation maTest21 = DefaultMaintenanceAssociation + .builder(MaIdCharStr.asMaId("test-ma-2-1"), 9) + .ccmInterval(MaintenanceAssociation.CcmInterval.INTERVAL_1S) + .maNumericId((short) 1) + .addToRemoteMepIdList(MepId.valueOf((short) 101)) + .addToRemoteMepIdList(MepId.valueOf((short) 102)) + .addToComponentList( + DefaultComponent.builder(1) + .tagType(Component.TagType.VLAN_STAG) + .build()) + .build(); + + MaintenanceDomain mdTest2 = DefaultMaintenanceDomain + .builder(MdIdCharStr.asMdId("test-md-2")) + .mdLevel(MaintenanceDomain.MdLevel.LEVEL2) + .mdNumericId((short) 2) + .addToMaList(maTest21) + .build(); + + + //We expect false here because there should have been no previous value + //with that ID in the store + assertFalse(service.createMaintenanceDomain(mdTest2)); + } + + @Test + public void testGetAllMaintenanceAssociation() { + Collection maListMd1 = + service.getAllMaintenanceAssociation( + MdIdCharStr.asMdId("test-md-1")); + + assertEquals(2, maListMd1.size()); + + maListMd1.iterator().forEachRemaining(ma -> + assertTrue(ma.maId().maName().endsWith(String.valueOf(ma.maNumericId()))) + ); + + //Now try with an invalid name + try { + service.getAllMaintenanceAssociation( + MdIdCharStr.asMdId("test-md-2")); + } catch (IllegalArgumentException e) { + assertEquals("Unknown MD test-md-2", e.getMessage()); + } + } + + @Test + public void testGetMaintenanceAssociation() { + Optional ma = + service.getMaintenanceAssociation( + MdIdCharStr.asMdId("test-md-1"), + MaIdCharStr.asMaId("test-ma-1-2")); + + assertTrue(ma.isPresent()); + + //Now try an invalid MD Name + try { + service.getMaintenanceAssociation( + MdIdCharStr.asMdId("test-md-2"), + MaIdCharStr.asMaId("test-ma-1-2")); + } catch (IllegalArgumentException e) { + assertEquals("Unknown MD test-md-2", e.getMessage()); + } + + //Now try an invalid MA Name with a valid MD Name + try { + Optional maInvalid = + service.getMaintenanceAssociation( + MdIdCharStr.asMdId("test-md-1"), + MaIdCharStr.asMaId("test-ma-1-3")); + assertFalse(maInvalid.isPresent()); + } catch (IllegalArgumentException e) { + fail("Should not throw exception: " + e.getMessage()); + } + } + + @Test + public void testDeleteMaintenanceAssociation() throws CfmConfigException { + assertTrue(service.deleteMaintenanceAssociation( + MdIdCharStr.asMdId("test-md-1"), + MaIdCharStr.asMaId("test-ma-1-2"))); + + //Now check it has actually been removed + Collection maListUpdated = + service.getAllMaintenanceAssociation( + MdIdCharStr.asMdId("test-md-1")); + assertEquals(1, maListUpdated.size()); + maListUpdated.stream().findFirst().ifPresent(ma -> + assertEquals("test-ma-1-1", ma.maId().maName()) + ); + + //Now try with an invalid mdName + try { + service.deleteMaintenanceAssociation( + MdIdCharStr.asMdId("test-md-2"), + MaIdCharStr.asMaId("test-ma-1-2")); + } catch (IllegalArgumentException e) { + assertEquals("Unknown MD: test-md-2", e.getMessage()); + } + + //Now try with an invalid maName + try { + assertFalse(service.deleteMaintenanceAssociation( + MdIdCharStr.asMdId("test-md-1"), + MaIdCharStr.asMaId("test-ma-1-3"))); + } catch (IllegalArgumentException e) { + fail("Should not throw exception: " + e.getMessage()); + } + } + + @Test + public void testCreateMaintenanceAssociation() throws CfmConfigException { + MaintenanceAssociation maTest41 = DefaultMaintenanceAssociation + .builder(MaIdCharStr.asMaId("test-ma-1-4"), 9) + .ccmInterval(MaintenanceAssociation.CcmInterval.INTERVAL_1S) + .maNumericId((short) 4) + .addToRemoteMepIdList(MepId.valueOf((short) 401)) + .addToRemoteMepIdList(MepId.valueOf((short) 402)) + .addToComponentList( + DefaultComponent.builder(4) + .tagType(Component.TagType.VLAN_STAG) + .build()) + .build(); + + //Should return false, as this MA did not exist before + assertFalse(service.createMaintenanceAssociation( + MdIdCharStr.asMdId("test-md-1"), maTest41)); + assertEquals(3, service.getAllMaintenanceAssociation( + MdIdCharStr.asMdId("test-md-1")).size()); + + //Now try with an invalid mdName + try { + service.createMaintenanceAssociation( + MdIdCharStr.asMdId("test-md-2"), maTest41); + } catch (IllegalArgumentException e) { + assertEquals("Unknown MD: test-md-2", e.getMessage()); + } + + //Now try replacing an MA with some new values or Remote MEP + MaintenanceAssociation maTest11 = DefaultMaintenanceAssociation + .builder(MaIdCharStr.asMaId("test-ma-1-1"), 9) + .ccmInterval(MaintenanceAssociation.CcmInterval.INTERVAL_10MIN) + .maNumericId((short) 1) + .addToRemoteMepIdList(MepId.valueOf((short) 111)) //Changed + .addToRemoteMepIdList(MepId.valueOf((short) 112)) //Changed + .addToComponentList( + DefaultComponent.builder(1) + .tagType(Component.TagType.VLAN_CTAG) + .build()) + .build(); + + //Should return true, as this MA did exist before + assertTrue(service.createMaintenanceAssociation( + MdIdCharStr.asMdId("test-md-1"), maTest11)); + assertEquals(3, service.getAllMaintenanceAssociation( + MdIdCharStr.asMdId("test-md-1")).size()); + } + + + public class TestApplicationId extends DefaultApplicationId { + public TestApplicationId(int id, String name) { + super(id, name); + } + } + + private final class TestClusterService extends ClusterServiceAdapter { + + ControllerNode local = new DefaultControllerNode(NID_LOCAL, LOCALHOST); + + @Override + public ControllerNode getLocalNode() { + return local; + } + + @Override + public Set getNodes() { + return Sets.newHashSet(); + } + + } + + private class TestMastershipService extends MastershipServiceAdapter { + @Override + public NodeId getMasterFor(DeviceId deviceId) { + return NID_LOCAL; + } + } + + private class TestCoreService extends CoreServiceAdapter { + + @Override + public IdGenerator getIdGenerator(String topic) { + return new IdGenerator() { + private AtomicLong counter = new AtomicLong(0); + + @Override + public long getNewId() { + return counter.getAndIncrement(); + } + }; + } + } +} diff --git a/incubator/net/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/impl/CfmMepManagerTest.java b/incubator/net/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/impl/CfmMepManagerTest.java new file mode 100644 index 0000000000..a82585872b --- /dev/null +++ b/incubator/net/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/impl/CfmMepManagerTest.java @@ -0,0 +1,381 @@ +/* + * 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.incubator.net.l2monitoring.cfm.impl; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.onlab.junit.TestUtils; +import org.onlab.packet.ChassisId; +import org.onosproject.common.event.impl.TestEventDispatcher; +import org.onosproject.core.CoreServiceAdapter; +import org.onosproject.core.IdGenerator; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMaintenanceAssociation; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMep; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMepLbCreate; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMepLtCreate; +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceAssociation; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep; +import org.onosproject.incubator.net.l2monitoring.cfm.MepEntry; +import org.onosproject.incubator.net.l2monitoring.cfm.MepLbCreate; +import org.onosproject.incubator.net.l2monitoring.cfm.MepLtCreate; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMdService; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepProgrammable; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepService; +import org.onosproject.incubator.net.l2monitoring.soam.SoamDmProgrammable; +import org.onosproject.incubator.net.l2monitoring.soam.impl.TestSoamDmProgrammable; +import org.onosproject.net.AbstractProjectableModel; +import org.onosproject.net.AnnotationKeys; +import org.onosproject.net.DefaultAnnotations; +import org.onosproject.net.DefaultDevice; +import org.onosproject.net.Device; +import org.onosproject.net.DeviceId; +import org.onosproject.net.PortNumber; +import org.onosproject.net.device.DeviceDescriptionDiscovery; +import org.onosproject.net.device.DeviceService; +import org.onosproject.net.driver.Behaviour; +import org.onosproject.net.driver.DefaultDriver; +import org.onosproject.net.driver.Driver; +import org.onosproject.net.driver.DriverService; +import org.onosproject.net.provider.ProviderId; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.atomic.AtomicLong; + +import static junit.framework.TestCase.fail; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.onosproject.net.NetTestTools.injectEventDispatcher; + +/** + * CFM MEP Manager test. + */ +public class CfmMepManagerTest { + private static final String TEST_MFR = "testMfr"; + private static final String TEST_HW_VERSION = "testHwVersion"; + private static final String TEST_SW_VERSION = "testSwVersion"; + private static final String TEST_SN = "testSn"; + private static final String TEST_DRIVER = "testDriver"; + public static final String TEST_DRIVER_3 = "testDriver3"; + public static final String TEST_SW_3 = "testSw3"; + private final CfmMdService mdService = createMock(CfmMdService.class); + private final DeviceService deviceService = createMock(DeviceService.class); + private final DriverService driverService = createMock(DriverService.class); + + private CfmMepService mepService; + private CfmMepManager mepManager; + + protected static final MdId MDNAME1 = MdIdCharStr.asMdId("md-1"); + protected static final MaIdShort MANAME1 = MaIdCharStr.asMaId("ma-1-1"); + + private MaintenanceAssociation ma1; + protected static final MepId MEPID1 = MepId.valueOf((short) 10); + protected static final MepId MEPID2 = MepId.valueOf((short) 20); + protected static final DeviceId DEVICE_ID1 = DeviceId.deviceId("netconf:1.2.3.4:830"); + protected static final DeviceId DEVICE_ID2 = DeviceId.deviceId("netconf:2.2.3.4:830"); + + private Mep mep1; + private Mep mep2; + + private Device device1; + private Device device2; + + private Driver testDriver; + + @Before + public void setup() throws CfmConfigException { + mepManager = new CfmMepManager(); + + ma1 = DefaultMaintenanceAssociation.builder(MANAME1, MDNAME1.getNameLength()).build(); + + TestUtils.setField(mepManager, "coreService", new TestCoreService()); + TestUtils.setField(mepManager, "deviceService", deviceService); + TestUtils.setField(mepManager, "cfmMdService", mdService); + injectEventDispatcher(mepManager, new TestEventDispatcher()); + + mepService = mepManager; + mepManager.activate(); + + mep1 = DefaultMep.builder(MEPID1, DEVICE_ID1, PortNumber.P0, + Mep.MepDirection.UP_MEP, MDNAME1, MANAME1).build(); + mep2 = DefaultMep.builder(MEPID2, DEVICE_ID2, PortNumber.portNumber(2), + Mep.MepDirection.UP_MEP, MDNAME1, MANAME1).build(); + List mepList = new ArrayList<>(); + mepList.add(mep1); + mepList.add(mep2); + TestUtils.setField(mepManager, "mepCollection", mepList); + + device1 = new DefaultDevice( + ProviderId.NONE, DEVICE_ID1, Device.Type.SWITCH, + TEST_MFR, TEST_HW_VERSION, TEST_SW_VERSION, TEST_SN, + new ChassisId(1), + DefaultAnnotations.builder().set(AnnotationKeys.DRIVER, TEST_DRIVER).build()); + + device2 = new DefaultDevice( + ProviderId.NONE, DEVICE_ID2, Device.Type.SWITCH, + TEST_MFR, TEST_HW_VERSION, TEST_SW_VERSION, TEST_SN, + new ChassisId(2), + DefaultAnnotations.builder().set(AnnotationKeys.DRIVER, TEST_DRIVER).build()); + + AbstractProjectableModel.setDriverService(null, driverService); + + Map, Class> behaviours = new HashMap<>(); + behaviours.put(DeviceDescriptionDiscovery.class, TestDeviceDiscoveryBehavior.class); + behaviours.put(CfmMepProgrammable.class, TestCfmMepProgrammable.class); + behaviours.put(SoamDmProgrammable.class, TestSoamDmProgrammable.class); + + testDriver = new DefaultDriver( + TEST_DRIVER, new ArrayList(), + TEST_MFR, TEST_HW_VERSION, TEST_SW_VERSION, + behaviours, new HashMap<>()); + } + + + @After + public void tearDown() { +// mepManager.deactivate(); + } + + @Test + public void testGetAllMeps() throws CfmConfigException { + + expect(mdService.getMaintenanceAssociation(MDNAME1, MANAME1)) + .andReturn(Optional.ofNullable(ma1)) + .anyTimes(); + replay(mdService); + + expect(deviceService.getDevice(DEVICE_ID1)).andReturn(device1).anyTimes(); + expect(deviceService.getDevice(DEVICE_ID2)).andReturn(device2).anyTimes(); + replay(deviceService); + + expect(driverService.getDriver(TEST_DRIVER)).andReturn(testDriver).anyTimes(); + replay(driverService); + + Collection mepEntries = mepManager.getAllMeps(MDNAME1, MANAME1); + + assertEquals(2, mepEntries.size()); + } + + @Test + public void testGetMep() throws CfmConfigException { + + expect(mdService.getMaintenanceAssociation(MDNAME1, MANAME1)) + .andReturn(Optional.ofNullable(ma1)) + .anyTimes(); + replay(mdService); + + expect(deviceService.getDevice(DEVICE_ID1)).andReturn(device1).anyTimes(); + replay(deviceService); + + expect(driverService.getDriver(TEST_DRIVER)).andReturn(testDriver).anyTimes(); + replay(driverService); + + MepEntry mepEntry = mepManager.getMep(MDNAME1, MANAME1, MEPID1); + + assertEquals(MEPID1.value(), mepEntry.mepId().value()); + } + + @Test + public void testGetMepMissing() { + + expect(mdService.getMaintenanceAssociation(MDNAME1, MANAME1)) + .andReturn(Optional.ofNullable(ma1)) + .anyTimes(); + replay(mdService); + + expect(deviceService.getDevice(DEVICE_ID1)).andReturn(null).anyTimes(); + replay(deviceService); + + expect(driverService.getDriver(TEST_DRIVER)).andReturn(testDriver).anyTimes(); + replay(driverService); + + try { + mepManager.getMep(MDNAME1, MANAME1, MEPID1); + fail("Expecting CfmConfigException because device does not exist"); + } catch (CfmConfigException e) { + assertEquals("Device not found netconf:1.2.3.4:830", e.getMessage()); + } + } + + @Test + public void testDeleteMep() throws CfmConfigException { + expect(mdService.getMaintenanceAssociation(MDNAME1, MANAME1)) + .andReturn(Optional.ofNullable(ma1)) + .anyTimes(); + replay(mdService); + + expect(deviceService.getDevice(DEVICE_ID1)).andReturn(device1).anyTimes(); + replay(deviceService); + + expect(driverService.getDriver(TEST_DRIVER)).andReturn(testDriver).anyTimes(); + replay(driverService); + + assertTrue(mepManager.deleteMep(MDNAME1, MANAME1, MEPID1)); + } + + @Test + public void testCreateMep() throws CfmConfigException { + expect(mdService.getMaintenanceAssociation(MDNAME1, MANAME1)) + .andReturn(Optional.ofNullable(ma1)) + .anyTimes(); + replay(mdService); + + expect(deviceService.getDevice(DEVICE_ID1)).andReturn(device1).anyTimes(); + replay(deviceService); + + expect(driverService.getDriver(TEST_DRIVER)).andReturn(testDriver).anyTimes(); + replay(driverService); + + MepId mepId3 = MepId.valueOf((short) 3); + Mep mep3 = DefaultMep.builder(mepId3, DEVICE_ID1, PortNumber.portNumber(1), + Mep.MepDirection.UP_MEP, MDNAME1, MANAME1).build(); + + assertTrue(mepManager.createMep(MDNAME1, MANAME1, mep3)); + } + + @Test + public void testCreateMepBehaviorNotSupported() throws CfmConfigException { + final DeviceId deviceId3 = DeviceId.deviceId("netconf:3.2.3.4:830"); + + Map, Class> behaviours = new HashMap<>(); + behaviours.put(DeviceDescriptionDiscovery.class, TestDeviceDiscoveryBehavior.class); + + Driver testDriver3 = new DefaultDriver( + TEST_DRIVER_3, new ArrayList(), + TEST_MFR, TEST_HW_VERSION, TEST_SW_3, + behaviours, new HashMap<>()); + + Device device3 = new DefaultDevice( + ProviderId.NONE, deviceId3, Device.Type.SWITCH, + TEST_MFR, TEST_HW_VERSION, TEST_SW_3, TEST_SN, + new ChassisId(2), + DefaultAnnotations.builder().set(AnnotationKeys.DRIVER, TEST_DRIVER_3).build()); + + expect(mdService.getMaintenanceAssociation(MDNAME1, MANAME1)) + .andReturn(Optional.ofNullable(ma1)) + .anyTimes(); + replay(mdService); + + expect(deviceService.getDevice(deviceId3)).andReturn(device3).anyTimes(); + replay(deviceService); + + expect(driverService.getDriver(TEST_DRIVER_3)).andReturn(testDriver3).anyTimes(); + replay(driverService); + + MepId mepId3 = MepId.valueOf((short) 3); + Mep mep3 = DefaultMep.builder(mepId3, deviceId3, PortNumber.portNumber(1), + Mep.MepDirection.UP_MEP, MDNAME1, MANAME1).build(); + + try { + mepManager.createMep(MDNAME1, MANAME1, mep3); + fail("Expecting CfmConfigException because driver does not support behavior"); + } catch (CfmConfigException e) { + assertEquals("Device netconf:3.2.3.4:830 does not support " + + "CfmMepProgrammable behaviour.", e.getMessage()); + } + } + + @Test + public void testTransmitLoopback() { + expect(mdService.getMaintenanceAssociation(MDNAME1, MANAME1)) + .andReturn(Optional.ofNullable(ma1)) + .anyTimes(); + replay(mdService); + + expect(deviceService.getDevice(DEVICE_ID1)).andReturn(device1).anyTimes(); + replay(deviceService); + + expect(driverService.getDriver(TEST_DRIVER)).andReturn(testDriver).anyTimes(); + replay(driverService); + + MepLbCreate lbCreate = DefaultMepLbCreate.builder(MepId.valueOf((short) 11)).build(); + try { + mepService.transmitLoopback(MDNAME1, MANAME1, MEPID1, lbCreate); + } catch (CfmConfigException e) { + fail("Not expecting an exception"); + } + } + + @Test + public void testAbortLoopback() { + expect(mdService.getMaintenanceAssociation(MDNAME1, MANAME1)) + .andReturn(Optional.ofNullable(ma1)) + .anyTimes(); + replay(mdService); + + expect(deviceService.getDevice(DEVICE_ID1)).andReturn(device1).anyTimes(); + replay(deviceService); + + expect(driverService.getDriver(TEST_DRIVER)).andReturn(testDriver).anyTimes(); + replay(driverService); + + try { + mepService.abortLoopback(MDNAME1, MANAME1, MEPID1); + } catch (CfmConfigException e) { + fail("Not expecting an exception"); + } + } + + @Test + public void testTransmitLinktrace() throws CfmConfigException { + expect(mdService.getMaintenanceAssociation(MDNAME1, MANAME1)) + .andReturn(Optional.ofNullable(ma1)) + .anyTimes(); + replay(mdService); + + expect(deviceService.getDevice(DEVICE_ID1)).andReturn(device1).anyTimes(); + replay(deviceService); + + expect(driverService.getDriver(TEST_DRIVER)).andReturn(testDriver).anyTimes(); + replay(driverService); + + MepLtCreate ltCreate = DefaultMepLtCreate.builder(MepId.valueOf((short) 11)).build(); + try { + mepService.transmitLinktrace(MDNAME1, MANAME1, MEPID1, ltCreate); + } catch (UnsupportedOperationException e) { + assertEquals("Not yet implemented", e.getMessage()); + } + } + + private class TestCoreService extends CoreServiceAdapter { + + @Override + public IdGenerator getIdGenerator(String topic) { + return new IdGenerator() { + private AtomicLong counter = new AtomicLong(0); + + @Override + public long getNewId() { + return counter.getAndIncrement(); + } + }; + } + } +} diff --git a/incubator/net/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/impl/TestCfmMepProgrammable.java b/incubator/net/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/impl/TestCfmMepProgrammable.java new file mode 100644 index 0000000000..8d0f7659bd --- /dev/null +++ b/incubator/net/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/impl/TestCfmMepProgrammable.java @@ -0,0 +1,95 @@ +/* + * 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.incubator.net.l2monitoring.cfm.impl; + +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMep; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMepEntry; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep; +import org.onosproject.incubator.net.l2monitoring.cfm.MepEntry; +import org.onosproject.incubator.net.l2monitoring.cfm.MepLbCreate; +import org.onosproject.incubator.net.l2monitoring.cfm.MepLtCreate; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepProgrammable; +import org.onosproject.net.PortNumber; +import org.onosproject.net.driver.AbstractHandlerBehaviour; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import static org.onosproject.incubator.net.l2monitoring.cfm.impl.CfmMepManagerTest.*; + +/** + * A dummy implementation of the CfmMepProgrammable for test purposes. + */ +public class TestCfmMepProgrammable extends AbstractHandlerBehaviour implements CfmMepProgrammable { + + private List deviceMepList; + + public TestCfmMepProgrammable() throws CfmConfigException { + deviceMepList = new ArrayList<>(); + + deviceMepList.add(DefaultMep.builder(MEPID1, DEVICE_ID1, PortNumber.P0, + Mep.MepDirection.UP_MEP, MDNAME1, MANAME1).build()); + deviceMepList.add(DefaultMep.builder(MEPID2, DEVICE_ID2, PortNumber.portNumber(2), + Mep.MepDirection.UP_MEP, MDNAME1, MANAME1).build()); + } + + @Override + public Collection getAllMeps(MdId mdName, MaIdShort maName) throws CfmConfigException { + return null; + } + + @Override + public MepEntry getMep(MdId mdName, MaIdShort maName, MepId mepId) throws CfmConfigException { + for (Mep mep:deviceMepList) { + if (mep.mdId().equals(mdName) && mep.maId().equals(maName) && mep.mepId().equals(mepId)) { + return DefaultMepEntry.builder(mep).buildEntry(); + } + } + return null; + } + + @Override + public boolean deleteMep(MdId mdName, MaIdShort maName, MepId mepId) throws CfmConfigException { + return true; + } + + @Override + public boolean createMep(MdId mdName, MaIdShort maName, Mep mep) throws CfmConfigException { + return true; + } + + @Override + public void transmitLoopback(MdId mdName, MaIdShort maName, MepId mepId, MepLbCreate lbCreate) + throws CfmConfigException { + + } + + @Override + public void abortLoopback(MdId mdName, MaIdShort maName, MepId mepId) throws CfmConfigException { + + } + + @Override + public void transmitLinktrace(MdId mdName, MaIdShort maName, MepId mepId, MepLtCreate ltCreate) + throws CfmConfigException { + + } +} diff --git a/incubator/net/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/impl/TestDeviceDiscoveryBehavior.java b/incubator/net/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/impl/TestDeviceDiscoveryBehavior.java new file mode 100644 index 0000000000..01d3d013a6 --- /dev/null +++ b/incubator/net/src/test/java/org/onosproject/incubator/net/l2monitoring/cfm/impl/TestDeviceDiscoveryBehavior.java @@ -0,0 +1,37 @@ +/* + * 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.incubator.net.l2monitoring.cfm.impl; + +import org.onosproject.net.device.DeviceDescription; +import org.onosproject.net.device.DeviceDescriptionDiscovery; +import org.onosproject.net.device.PortDescription; +import org.onosproject.net.driver.AbstractHandlerBehaviour; + +import java.util.List; + +public class TestDeviceDiscoveryBehavior extends AbstractHandlerBehaviour + implements DeviceDescriptionDiscovery { + + @Override + public DeviceDescription discoverDeviceDetails() { + return null; + } + + @Override + public List discoverPortDetails() { + return null; + } +} diff --git a/incubator/net/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/impl/SoamManagerTest.java b/incubator/net/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/impl/SoamManagerTest.java new file mode 100644 index 0000000000..251cc71e61 --- /dev/null +++ b/incubator/net/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/impl/SoamManagerTest.java @@ -0,0 +1,470 @@ +/* + * 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.incubator.net.l2monitoring.soam.impl; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.onlab.junit.TestUtils; +import org.onlab.packet.ChassisId; +import org.onosproject.common.event.impl.TestEventDispatcher; +import org.onosproject.core.CoreServiceAdapter; +import org.onosproject.core.IdGenerator; +import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMepEntry; +import org.onosproject.incubator.net.l2monitoring.cfm.MaintenanceAssociation; +import org.onosproject.incubator.net.l2monitoring.cfm.Mep; +import org.onosproject.incubator.net.l2monitoring.cfm.MepEntry; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdIdCharStr; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.cfm.impl.TestCfmMepProgrammable; +import org.onosproject.incubator.net.l2monitoring.cfm.impl.TestDeviceDiscoveryBehavior; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMdService; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepProgrammable; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepService; +import org.onosproject.incubator.net.l2monitoring.soam.SoamConfigException; +import org.onosproject.incubator.net.l2monitoring.soam.SoamDmProgrammable; +import org.onosproject.incubator.net.l2monitoring.soam.SoamId; +import org.onosproject.incubator.net.l2monitoring.soam.SoamService; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DefaultDelayMeasurementCreate; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DefaultDelayMeasurementEntry; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementEntry; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStatCurrent; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStatHistory; +import org.onosproject.net.AbstractProjectableModel; +import org.onosproject.net.AnnotationKeys; +import org.onosproject.net.DefaultAnnotations; +import org.onosproject.net.DefaultDevice; +import org.onosproject.net.Device; +import org.onosproject.net.DeviceId; +import org.onosproject.net.PortNumber; +import org.onosproject.net.device.DeviceDescriptionDiscovery; +import org.onosproject.net.device.DeviceService; +import org.onosproject.net.driver.Behaviour; +import org.onosproject.net.driver.DefaultDriver; +import org.onosproject.net.driver.Driver; +import org.onosproject.net.driver.DriverService; +import org.onosproject.net.provider.ProviderId; + +import java.time.Instant; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; + +import static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.assertNotNull; +import static junit.framework.TestCase.fail; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.junit.Assert.assertTrue; +import static org.onosproject.net.NetTestTools.injectEventDispatcher; + +/** + * Services OAM Manager test. + */ +public class SoamManagerTest { + private static final String TEST_MFR = "testMfr"; + private static final String TEST_HW_VERSION = "testHwVersion"; + private static final String TEST_SW_VERSION = "testSwVersion"; + private static final String TEST_SN = "testSn"; + private static final String TEST_DRIVER = "testDriver"; + public static final String TEST_DRIVER_3 = "testDriver3"; + public static final String TEST_SW_3 = "testSw3"; + + + protected static final MdId MDNAME1 = MdIdCharStr.asMdId("md-1"); + protected static final MaIdShort MANAME1 = MaIdCharStr.asMaId("ma-1-1"); + protected static final MepId MEPID1 = MepId.valueOf((short) 10); + protected static final DeviceId DEVICE_ID1 = DeviceId.deviceId("netconf:1.2.3.4:830"); + protected static final SoamId DMID101 = SoamId.valueOf(101); + protected static final SoamId DMID102 = SoamId.valueOf(102); + protected static final SoamId LMID101 = SoamId.valueOf(201); + + private MaintenanceAssociation ma1; + private MepEntry mep1; + + private SoamManager soamManager; + private SoamService soamService; + + private final CfmMdService mdService = createMock(CfmMdService.class); + private CfmMepService mepService = createMock(CfmMepService.class); + private final DeviceService deviceService = createMock(DeviceService.class); + private final DriverService driverService = createMock(DriverService.class); + private Device device1; + private Driver testDriver; + + @Before + public void setup() throws CfmConfigException, SoamConfigException { + soamManager = new SoamManager(); + TestUtils.setField(soamManager, "coreService", new TestCoreService()); + TestUtils.setField(soamManager, "cfmMepService", mepService); + TestUtils.setField(soamManager, "deviceService", deviceService); + + injectEventDispatcher(soamManager, new TestEventDispatcher()); + soamService = soamManager; + soamManager.activate(); + + DelayMeasurementEntry dmEntry1 = DefaultDelayMeasurementEntry + .builder(DMID101, DelayMeasurementCreate.DmType.DM1DMTX, + DelayMeasurementCreate.Version.Y17312011, + MepId.valueOf((short) 11), Mep.Priority.PRIO5).build(); + DelayMeasurementEntry dmEntry2 = DefaultDelayMeasurementEntry + .builder(DMID102, DelayMeasurementCreate.DmType.DM1DMTX, + DelayMeasurementCreate.Version.Y17312011, + MepId.valueOf((short) 11), Mep.Priority.PRIO6).build(); + + mep1 = DefaultMepEntry.builder(MEPID1, DEVICE_ID1, PortNumber.P0, + Mep.MepDirection.UP_MEP, MDNAME1, MANAME1) + .addToDelayMeasurementList(dmEntry1) + .addToDelayMeasurementList(dmEntry2) + .buildEntry(); + + device1 = new DefaultDevice( + ProviderId.NONE, DEVICE_ID1, Device.Type.SWITCH, + TEST_MFR, TEST_HW_VERSION, TEST_SW_VERSION, TEST_SN, + new ChassisId(1), + DefaultAnnotations.builder().set(AnnotationKeys.DRIVER, TEST_DRIVER).build()); + + AbstractProjectableModel.setDriverService(null, driverService); + + Map, Class> behaviours = new HashMap<>(); + behaviours.put(DeviceDescriptionDiscovery.class, TestDeviceDiscoveryBehavior.class); + behaviours.put(CfmMepProgrammable.class, TestCfmMepProgrammable.class); + behaviours.put(SoamDmProgrammable.class, TestSoamDmProgrammable.class); + + testDriver = new DefaultDriver( + TEST_DRIVER, new ArrayList(), + TEST_MFR, TEST_HW_VERSION, TEST_SW_VERSION, + behaviours, new HashMap<>()); + + } + + @After + public void tearDown() { +// soamManager.deactivate(); + } + + @Test + public void testGetAllDms() throws CfmConfigException, SoamConfigException { + + expect(mepService.getMep(MDNAME1, MANAME1, MEPID1)).andReturn(mep1).anyTimes(); + replay(mepService); + + Collection dmEntries = + soamManager.getAllDms(MDNAME1, MANAME1, MEPID1); + assertEquals(2, dmEntries.size()); + } + + @Test + public void testGetDm() throws CfmConfigException, SoamConfigException { + expect(deviceService.getDevice(DEVICE_ID1)).andReturn(device1).anyTimes(); + replay(deviceService); + + expect(mepService.getMep(MDNAME1, MANAME1, MEPID1)).andReturn(mep1).anyTimes(); + replay(mepService); + + expect(driverService.getDriver(TEST_DRIVER)).andReturn(testDriver).anyTimes(); + replay(driverService); + + DelayMeasurementEntry dmEntry = + soamManager.getDm(MDNAME1, MANAME1, MEPID1, DMID101); + + assertNotNull(dmEntry); + assertEquals(DMID101, dmEntry.dmId()); + } + + @Test + public void testGetDmCurrentStat() throws CfmConfigException, SoamConfigException { + expect(deviceService.getDevice(DEVICE_ID1)).andReturn(device1).anyTimes(); + replay(deviceService); + + expect(mepService.getMep(MDNAME1, MANAME1, MEPID1)).andReturn(mep1).anyTimes(); + replay(mepService); + + expect(driverService.getDriver(TEST_DRIVER)).andReturn(testDriver).anyTimes(); + replay(driverService); + + DelayMeasurementStatCurrent dmCurrentStat = + soamManager.getDmCurrentStat(MDNAME1, MANAME1, MEPID1, DMID101); + + assertNotNull(dmCurrentStat); + assertTrue(dmCurrentStat.startTime().isBefore(Instant.now())); + } + + @Test + public void testGetDmHistoryStats() throws CfmConfigException, SoamConfigException { + expect(deviceService.getDevice(DEVICE_ID1)).andReturn(device1).anyTimes(); + replay(deviceService); + + expect(mepService.getMep(MDNAME1, MANAME1, MEPID1)).andReturn(mep1).anyTimes(); + replay(mepService); + + expect(driverService.getDriver(TEST_DRIVER)).andReturn(testDriver).anyTimes(); + replay(driverService); + + Collection dmHistoricalStats = + soamManager.getDmHistoricalStats(MDNAME1, MANAME1, MEPID1, DMID101); + + assertNotNull(dmHistoricalStats); + assertEquals(2, dmHistoricalStats.size()); + } + + @Test + public void testCreateDm() throws CfmConfigException, SoamConfigException { + expect(deviceService.getDevice(DEVICE_ID1)).andReturn(device1).anyTimes(); + replay(deviceService); + + expect(mepService.getMep(MDNAME1, MANAME1, MEPID1)).andReturn(mep1).anyTimes(); + replay(mepService); + + expect(driverService.getDriver(TEST_DRIVER)).andReturn(testDriver).anyTimes(); + replay(driverService); + + DelayMeasurementCreate dmCreate1 = DefaultDelayMeasurementCreate + .builder(DelayMeasurementCreate.DmType.DM1DMTX, + DelayMeasurementCreate.Version.Y17312011, + MepId.valueOf((short) 11), Mep.Priority.PRIO3) + .binsPerFdInterval((short) 4) + .binsPerFdrInterval((short) 5) + .binsPerIfdvInterval((short) 6) + .build(); + + assertEquals(1000, soamManager.createDm( + MDNAME1, MANAME1, MEPID1, dmCreate1).get().value()); + } + + @Test + public void testCreateDmNoBehavior() throws CfmConfigException, SoamConfigException { + final DeviceId deviceId3 = DeviceId.deviceId("netconf:3.2.3.4:830"); + final MepId mepId3 = MepId.valueOf((short) 3); + + Map, Class> behaviours = new HashMap<>(); + behaviours.put(DeviceDescriptionDiscovery.class, TestDeviceDiscoveryBehavior.class); + + Driver testDriver3 = new DefaultDriver( + TEST_DRIVER_3, new ArrayList(), + TEST_MFR, TEST_HW_VERSION, TEST_SW_3, + behaviours, new HashMap<>()); + + Device device3 = new DefaultDevice( + ProviderId.NONE, deviceId3, Device.Type.SWITCH, + TEST_MFR, TEST_HW_VERSION, TEST_SW_3, TEST_SN, + new ChassisId(2), + DefaultAnnotations.builder().set(AnnotationKeys.DRIVER, TEST_DRIVER_3).build()); + + expect(deviceService.getDevice(deviceId3)).andReturn(device3).anyTimes(); + replay(deviceService); + + MepEntry mep3 = DefaultMepEntry.builder(mepId3, deviceId3, PortNumber.P0, + Mep.MepDirection.UP_MEP, MDNAME1, MANAME1) + .buildEntry(); + + expect(mepService.getMep(MDNAME1, MANAME1, mepId3)).andReturn(mep3).anyTimes(); + replay(mepService); + + expect(driverService.getDriver(TEST_DRIVER_3)).andReturn(testDriver3).anyTimes(); + replay(driverService); + + DelayMeasurementCreate dmCreate1 = DefaultDelayMeasurementCreate + .builder(DelayMeasurementCreate.DmType.DM1DMTX, + DelayMeasurementCreate.Version.Y17312011, + MepId.valueOf((short) 11), Mep.Priority.PRIO3) + .binsPerFdInterval((short) 4) + .binsPerFdrInterval((short) 5) + .binsPerIfdvInterval((short) 6) + .build(); + + try { + soamManager.createDm(MDNAME1, MANAME1, mepId3, dmCreate1); + fail("Expecting exception since device does not support behavior"); + } catch (CfmConfigException e) { + assertEquals("Device netconf:3.2.3.4:830 from MEP :md-1/" + + "ma-1-1/3 does not implement SoamDmProgrammable", e.getMessage()); + } + } + + @Test + public void testAbortAllDmOnMep() throws CfmConfigException { + //TODO: Implement underlying method + try { + soamManager.abortDm(MDNAME1, MANAME1, MEPID1); + fail("Expecting UnsupportedOperationException"); + } catch (UnsupportedOperationException e) { + } + } + + @Test + public void testAbortOneDm() throws CfmConfigException { + //TODO: Implement underlying method + try { + soamManager.abortDm(MDNAME1, MANAME1, MEPID1, DMID101); + fail("Expecting UnsupportedOperationException"); + } catch (UnsupportedOperationException e) { + } + } + + @Test + public void testClearAllDmHistoriesOnMep() throws CfmConfigException { + //TODO: Implement underlying method + try { + soamManager.clearDelayHistoryStats(MDNAME1, MANAME1, MEPID1); + fail("Expecting UnsupportedOperationException"); + } catch (UnsupportedOperationException e) { + } + } + + @Test + public void testClearOneDmHistories() throws CfmConfigException { + //TODO: Implement underlying method + try { + soamManager.clearDelayHistoryStats(MDNAME1, MANAME1, MEPID1, DMID101); + fail("Expecting UnsupportedOperationException"); + } catch (UnsupportedOperationException e) { + } + } + + @Test + public void testGetAllLmsOnMep() throws CfmConfigException { + //TODO: Implement underlying method + try { + soamManager.getAllLms(MDNAME1, MANAME1, MEPID1); + fail("Expecting UnsupportedOperationException"); + } catch (UnsupportedOperationException e) { + } + } + + @Test + public void testGetLm() throws CfmConfigException { + //TODO: Implement underlying method + try { + soamManager.getLm(MDNAME1, MANAME1, MEPID1, LMID101); + fail("Expecting UnsupportedOperationException"); + } catch (UnsupportedOperationException e) { + } + } + + @Test + public void testGetLmCurrentStat() { + //TODO: Implement underlying method + try { + soamManager.getLmCurrentStat(MDNAME1, MANAME1, MEPID1, LMID101); + fail("Expecting UnsupportedOperationException"); + } catch (UnsupportedOperationException e) { + } + } + + @Test + public void testGetLmhistoricalStats() { + //TODO: Implement underlying method + try { + soamManager.getLmHistoricalStats(MDNAME1, MANAME1, MEPID1, LMID101); + fail("Expecting UnsupportedOperationException"); + } catch (UnsupportedOperationException e) { + } + } + + @Test + public void testCreateLm() throws CfmConfigException { + //TODO: Implement underlying method + try { + soamManager.createLm(MDNAME1, MANAME1, MEPID1, null); + fail("Expecting UnsupportedOperationException"); + } catch (UnsupportedOperationException e) { + } + } + + @Test + public void testAbortAllLmOnMep() throws CfmConfigException { + //TODO: Implement underlying method + try { + soamManager.abortLm(MDNAME1, MANAME1, MEPID1); + fail("Expecting UnsupportedOperationException"); + } catch (UnsupportedOperationException e) { + } + } + + @Test + public void testAbortOneLm() throws CfmConfigException { + //TODO: Implement underlying method + try { + soamManager.abortLm(MDNAME1, MANAME1, MEPID1, LMID101); + fail("Expecting UnsupportedOperationException"); + } catch (UnsupportedOperationException e) { + } + } + + @Test + public void testClearAllLossHistoryStatsOnMep() throws CfmConfigException { + //TODO: Implement underlying method + try { + soamManager.clearLossHistoryStats(MDNAME1, MANAME1, MEPID1); + fail("Expecting UnsupportedOperationException"); + } catch (UnsupportedOperationException e) { + } + } + + @Test + public void testClearLossHistoryStatsOnLm() throws CfmConfigException { + //TODO: Implement underlying method + try { + soamManager.clearLossHistoryStats(MDNAME1, MANAME1, MEPID1, LMID101); + fail("Expecting UnsupportedOperationException"); + } catch (UnsupportedOperationException e) { + } + } + + @Test + public void testCreateTestSignal() throws CfmConfigException { + //TODO: Implement underlying method + try { + soamManager.createTestSignal(MDNAME1, MANAME1, MEPID1, null); + fail("Expecting UnsupportedOperationException"); + } catch (UnsupportedOperationException e) { + } + } + + @Test + public void testAbortTestSignal() throws CfmConfigException { + //TODO: Implement underlying method + try { + soamManager.abortTestSignal(MDNAME1, MANAME1, MEPID1); + fail("Expecting UnsupportedOperationException"); + } catch (UnsupportedOperationException e) { + } + } + + protected class TestCoreService extends CoreServiceAdapter { + + @Override + public IdGenerator getIdGenerator(String topic) { + return new IdGenerator() { + private AtomicLong counter = new AtomicLong(0); + + @Override + public long getNewId() { + return counter.getAndIncrement(); + } + }; + } + } +} diff --git a/incubator/net/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/impl/TestSoamDmProgrammable.java b/incubator/net/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/impl/TestSoamDmProgrammable.java new file mode 100644 index 0000000000..8d010de5b9 --- /dev/null +++ b/incubator/net/src/test/java/org/onosproject/incubator/net/l2monitoring/soam/impl/TestSoamDmProgrammable.java @@ -0,0 +1,238 @@ +/* + * 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.incubator.net.l2monitoring.soam.impl; + +import org.onosproject.incubator.net.l2monitoring.cfm.Mep; +import org.onosproject.incubator.net.l2monitoring.cfm.MepTsCreate; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MaIdShort; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId; +import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId; +import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException; +import org.onosproject.incubator.net.l2monitoring.soam.SoamConfigException; +import org.onosproject.incubator.net.l2monitoring.soam.SoamDmProgrammable; +import org.onosproject.incubator.net.l2monitoring.soam.SoamId; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DefaultDelayMeasurementEntry; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DefaultDelayMeasurementStatCurrent; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DefaultDelayMeasurementStatHistory; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementCreate; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementEntry; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStatCurrent; +import org.onosproject.incubator.net.l2monitoring.soam.delay.DelayMeasurementStatHistory; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementCreate; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementEntry; +import org.onosproject.incubator.net.l2monitoring.soam.loss.LossMeasurementStatCurrent; +import org.onosproject.net.driver.AbstractHandlerBehaviour; + +import java.time.Duration; +import java.time.Instant; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Optional; + +import static org.onosproject.incubator.net.l2monitoring.soam.impl.SoamManagerTest.*; + +/** + * A dummy implementation of the SoamDmProgrammable for test purposes. + */ +public class TestSoamDmProgrammable extends AbstractHandlerBehaviour implements SoamDmProgrammable { + private DelayMeasurementEntry dmEntry1; + + public TestSoamDmProgrammable() throws SoamConfigException { + long nowMs = System.currentTimeMillis(); + long lastSecond = nowMs - nowMs % 1000; + DelayMeasurementStatCurrent current = + (DelayMeasurementStatCurrent) DefaultDelayMeasurementStatCurrent + .builder(Duration.ofSeconds(37), false) + .startTime(Instant.ofEpochMilli(lastSecond)) + .build(); + + long lastMinute = nowMs - nowMs % (60 * 1000); + DelayMeasurementStatHistory history1 = + (DelayMeasurementStatHistory) DefaultDelayMeasurementStatHistory + .builder(SoamId.valueOf(67), Duration.ofSeconds(60), false) + .endTime(Instant.ofEpochMilli(lastMinute)) + .frameDelayForwardMin(Duration.ofMillis(107)) + .frameDelayForwardMax(Duration.ofMillis(109)) + .frameDelayForwardAvg(Duration.ofMillis(108)) + .build(); + + long lastMinute2 = lastMinute - (60 * 1000); + DelayMeasurementStatHistory history2 = + (DelayMeasurementStatHistory) DefaultDelayMeasurementStatHistory + .builder(SoamId.valueOf(66), Duration.ofSeconds(60), false) + .endTime(Instant.ofEpochMilli(lastMinute2)) + .frameDelayForwardMin(Duration.ofMillis(117)) + .frameDelayForwardMax(Duration.ofMillis(119)) + .frameDelayForwardAvg(Duration.ofMillis(118)) + .build(); + + dmEntry1 = DefaultDelayMeasurementEntry + .builder(DMID101, DelayMeasurementCreate.DmType.DM1DMTX, + DelayMeasurementCreate.Version.Y17312011, + MepId.valueOf((short) 11), Mep.Priority.PRIO5) + .currentResult(current) + .addToHistoricalResults(history1) + .addToHistoricalResults(history2) + .build(); + } + + @Override + public Collection getAllDms( + MdId mdName, MaIdShort maName, MepId mepId) + throws CfmConfigException, SoamConfigException { + return null; + } + + @Override + public DelayMeasurementEntry getDm( + MdId mdName, MaIdShort maName, MepId mepId, SoamId dmId) + throws CfmConfigException, SoamConfigException { + if (mdName.equals(MDNAME1) && maName.equals(MANAME1) && mepId.equals(MEPID1)) { + return dmEntry1; + } + return null; + } + + @Override + public DelayMeasurementStatCurrent getDmCurrentStat( + MdId mdName, MaIdShort maName, MepId mepId, SoamId dmId) + throws CfmConfigException, SoamConfigException { + if (mdName.equals(MDNAME1) && maName.equals(MANAME1) && mepId.equals(MEPID1)) { + return dmEntry1.currentResult(); + } + return null; + } + + @Override + public Collection getDmHistoricalStats( + MdId mdName, MaIdShort maName, MepId mepId, SoamId dmId) + throws CfmConfigException, SoamConfigException { + if (mdName.equals(MDNAME1) && maName.equals(MANAME1) && mepId.equals(MEPID1)) { + return dmEntry1.historicalResults(); + } + return null; + } + + @Override + public Optional createDm( + MdId mdName, MaIdShort maName, MepId mepId, DelayMeasurementCreate dm) + throws CfmConfigException, SoamConfigException { + return Optional.ofNullable(SoamId.valueOf(1000)); + } + + @Override + public void abortDm( + MdId mdName, MaIdShort maName, MepId mepId) + throws CfmConfigException { + + } + + @Override + public void abortDm( + MdId mdName, MaIdShort maName, MepId mepId, SoamId dmId) + throws CfmConfigException { + + } + + @Override + public void clearDelayHistoryStats( + MdId mdName, MaIdShort maName, MepId mepId) + throws CfmConfigException { + + } + + @Override + public void clearDelayHistoryStats( + MdId mdName, MaIdShort maName, MepId mepId, SoamId dmId) + throws CfmConfigException { + + } + + @Override + public Collection getAllLms( + MdId mdName, MaIdShort maName, MepId mepId) + throws CfmConfigException, SoamConfigException { + return null; + } + + @Override + public LossMeasurementEntry getLm( + MdId mdName, MaIdShort maName, MepId mepId, SoamId lmId) + throws CfmConfigException, SoamConfigException { + return null; + } + + @Override + public LossMeasurementStatCurrent getLmCurrentStat( + MdId mdName, MaIdShort maName, MepId mepId, SoamId lmId) { + return null; + } + + @Override + public Collection getLmHistoricalStats( + MdId mdName, MaIdShort maName, MepId mepId, SoamId lmId) { + return new ArrayList(); + } + + @Override + public Optional createLm( + MdId mdName, MaIdShort maName, MepId mepId, LossMeasurementCreate lm) + throws CfmConfigException, SoamConfigException { + return Optional.empty(); + } + + @Override + public void abortLm( + MdId mdName, MaIdShort maName, MepId mepId) + throws CfmConfigException { + + } + + @Override + public void abortLm( + MdId mdName, MaIdShort maName, MepId mepId, SoamId lmId) + throws CfmConfigException { + + } + + @Override + public void clearLossHistoryStats( + MdId mdName, MaIdShort maName, MepId mepId) + throws CfmConfigException { + + } + + @Override + public void clearLossHistoryStats( + MdId mdName, MaIdShort maName, MepId mepId, SoamId lmId) + throws CfmConfigException { + + } + + @Override + public void createTestSignal( + MdId mdName, MaIdShort maName, MepId mepId, MepTsCreate tsCreate) + throws CfmConfigException { + + } + + @Override + public void abortTestSignal( + MdId mdName, MaIdShort maName, MepId mepId) + throws CfmConfigException { + + } +} \ No newline at end of file diff --git a/incubator/pom.xml b/incubator/pom.xml index 54312936b7..713bed2a29 100644 --- a/incubator/pom.xml +++ b/incubator/pom.xml @@ -57,10 +57,10 @@ tests test - - com.google.guava - guava - + + + + org.onosproject onlab-misc diff --git a/modules.defs b/modules.defs index 8d495b6f85..e917053570 100644 --- a/modules.defs +++ b/modules.defs @@ -221,6 +221,7 @@ ONOS_APPS = [ '//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', ] PROTOCOL_APPS = [