Merge branch 'master' into dev/auklet
Change-Id: I2d4ce97786694a9032c87a41dfca8ee72786efab
diff --git a/apps/acl/src/main/java/org/onosproject/acl/AclRule.java b/apps/acl/src/main/java/org/onosproject/acl/AclRule.java
index a5cc297..ff01aa4 100644
--- a/apps/acl/src/main/java/org/onosproject/acl/AclRule.java
+++ b/apps/acl/src/main/java/org/onosproject/acl/AclRule.java
@@ -43,7 +43,7 @@
private final short dstTpPort;
private final Action action;
- private static IdGenerator idGenerator;
+ protected static IdGenerator idGenerator;
/**
* Enum type for ACL rule's action.
diff --git a/apps/acl/src/test/java/org/onosproject/acl/AclWebResourceTest.java b/apps/acl/src/test/java/org/onosproject/acl/AclWebResourceTest.java
index 13c8201..003cf8c 100644
--- a/apps/acl/src/test/java/org/onosproject/acl/AclWebResourceTest.java
+++ b/apps/acl/src/test/java/org/onosproject/acl/AclWebResourceTest.java
@@ -27,6 +27,7 @@
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
+import org.onlab.junit.TestUtils;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.TestServiceDirectory;
import org.onlab.rest.BaseResource;
@@ -65,10 +66,9 @@
ServiceDirectory testDirectory = new TestServiceDirectory()
.add(AclService.class, mockAclService)
.add(AclStore.class, mockAclStore);
- BaseResource.setServiceDirectory(testDirectory);
+ TestUtils.setField(BaseResource.class, "services", testDirectory);
- IdGenerator idGenerator = new MockIdGenerator();
- AclRule.bindIdGenerator(idGenerator);
+ AclRule.idGenerator = new MockIdGenerator();
}
@After
diff --git a/apps/actn-mdsc/tetunnel-pce/src/main/java/org/onosproject/actn/mdsc/pce/impl/TeTunnelPceManager.java b/apps/actn-mdsc/tetunnel-pce/src/main/java/org/onosproject/actn/mdsc/pce/impl/TeTunnelPceManager.java
index 890c7ba..b0efe80 100644
--- a/apps/actn-mdsc/tetunnel-pce/src/main/java/org/onosproject/actn/mdsc/pce/impl/TeTunnelPceManager.java
+++ b/apps/actn-mdsc/tetunnel-pce/src/main/java/org/onosproject/actn/mdsc/pce/impl/TeTunnelPceManager.java
@@ -16,6 +16,7 @@
package org.onosproject.actn.mdsc.pce.impl;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
@@ -63,7 +64,11 @@
}
}
}
- return pce.computePaths(teTunnel);
+ if (pce != null) {
+ return pce.computePaths(teTunnel);
+ } else {
+ return ImmutableList.of();
+ }
}
@Override
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
index 341bd7d..f3c5b6e 100644
--- a/apps/cfm/src/main/java/org/onosproject/cfm/cli/CfmMdListMdCommand.java
+++ b/apps/cfm/src/main/java/org/onosproject/cfm/cli/CfmMdListMdCommand.java
@@ -20,6 +20,12 @@
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.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;
@@ -45,29 +51,7 @@
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 <identifier(name-type)>");
- }
-
- 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]);
- }
-
+ MdId mdId = parseMdName(name);
print("Maintenance Domain:");
Optional<MaintenanceDomain> md = service.getMaintenanceDomain(mdId);
print(printMd(md));
@@ -131,4 +115,59 @@
return sb.toString();
}
+
+ public static MdId parseMdName(String mdStr) {
+ String[] nameParts = mdStr.split("[()]");
+ if (nameParts.length != 2) {
+ throw new IllegalArgumentException("Invalid name format. " +
+ "Must be in the format of <identifier(name-type)>");
+ }
+
+ 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]);
+ }
+ return mdId;
+ }
+
+ public static MaIdShort parseMaName(String maStr) {
+ String[] nameParts = maStr.split("[()]");
+ if (nameParts.length != 2) {
+ throw new IllegalArgumentException("Invalid name format. " +
+ "Must be in the format of <identifier(name-type)>");
+ }
+
+ MaIdShort maId = null;
+ MaIdShort.MaIdType nameTypeEnum = MaIdShort.MaIdType.valueOf(nameParts[1]);
+ switch (nameTypeEnum) {
+ case ICCY1731:
+ maId = MaIdIccY1731.asMaId(nameParts[0]);
+ break;
+ case PRIMARYVID:
+ maId = MaIdPrimaryVid.asMaId(nameParts[0]);
+ break;
+ case RFC2685VPNID:
+ maId = MaIdRfc2685VpnId.asMaIdHex(nameParts[0]);
+ break;
+ case TWOOCTET:
+ maId = MaId2Octet.asMaId(nameParts[0]);
+ case CHARACTERSTRING:
+ default:
+ maId = MaIdCharStr.asMaId(nameParts[0]);
+ }
+ return maId;
+ }
+
}
diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/cli/CfmMepListCommand.java b/apps/cfm/src/main/java/org/onosproject/cfm/cli/CfmMepListCommand.java
new file mode 100644
index 0000000..b406947
--- /dev/null
+++ b/apps/cfm/src/main/java/org/onosproject/cfm/cli/CfmMepListCommand.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright 2018-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.MepEntry;
+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.identifier.MepKeyId;
+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.slf4j.Logger;
+
+import static org.onosproject.cfm.cli.CfmMdListMdCommand.parseMaName;
+import static org.onosproject.cfm.cli.CfmMdListMdCommand.parseMdName;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Lists a particular Maintenance Domain.
+ */
+@Command(scope = "onos", name = "cfm-mep-list",
+ description = "Lists a filtered set of MEPs or all if no parameters specified.")
+public class CfmMepListCommand extends AbstractShellCommand {
+ private final Logger log = getLogger(getClass());
+ @Argument(index = 0, name = "md",
+ description = "Maintenance Domain name and type (in brackets) - will use all MDs if not specified",
+ required = false, multiValued = false)
+ String mdStr = null;
+ @Argument(index = 1, name = "ma",
+ description = "Maintenance Association name and type (in brackets) - requires MD",
+ required = false, multiValued = false)
+ String maStr = null;
+ @Argument(index = 2, name = "mep",
+ description = "MEP identifier - requires MD and MA",
+ required = false, multiValued = false)
+ String mepStr = null;
+
+ @Override
+ protected void execute() {
+ CfmMepService mepService = get(CfmMepService.class);
+ CfmMdService mdService = get(CfmMdService.class);
+
+ if (mdStr != null && !mdStr.isEmpty()) {
+
+
+ MdId mdId = parseMdName(mdStr);
+ print(printMdId(mdId));
+
+ if (maStr != null && !maStr.isEmpty()) {
+ MaIdShort maId = parseMaName(maStr);
+ print(printMaId(maId));
+
+ if (mepStr != null && !mepStr.isEmpty()) {
+ MepId mepId = MepId.valueOf(Short.parseShort(mepStr));
+ try {
+ MepEntry mep = mepService.getMep(mdId, maId, mepId);
+ if (mep != null) {
+ print(printMepEntry(mep));
+ }
+ } catch (CfmConfigException e) {
+ log.error("Error retrieving Mep details {}",
+ new MepKeyId(mdId, maId, mepId), e);
+ }
+
+ //MD, MA and MEP given
+ } else {
+ //MD and MA given but no MEP given
+ try {
+ mepService.getAllMeps(mdId, maId).forEach(mep -> {
+ print(printMepEntry(mep));
+ });
+ } catch (CfmConfigException e) {
+ log.error("Error retrieving Meps for {}/{}",
+ mdId.mdName(), maId.maName(), e);
+ }
+ }
+ } else {
+ //MD given but no MA given
+ mdService.getAllMaintenanceAssociation(mdId).forEach(ma -> {
+ print(printMaId(ma.maId()));
+ try {
+ mepService.getAllMeps(mdId, ma.maId()).forEach(mep -> {
+ print(printMepEntry(mep));
+ });
+ } catch (CfmConfigException e) {
+ log.error("Error retrieving Meps for {}/{}",
+ mdId.mdName(), ma.maId().maName(), e);
+ }
+ });
+
+ }
+ } else {
+ mdService.getAllMaintenanceDomain().forEach(md -> {
+ print(printMdId(md.mdId()));
+
+ mdService.getAllMaintenanceAssociation(md.mdId()).forEach(ma -> {
+ print(printMaId(ma.maId()));
+ try {
+ mepService.getAllMeps(md.mdId(), ma.maId()).forEach(mep -> {
+ print(printMepEntry(mep));
+ });
+ } catch (CfmConfigException e) {
+ log.error("Error retrieving Meps for {}/{}",
+ md.mdId().mdName(), ma.maId().maName(), e);
+ }
+ });
+ });
+ }
+ }
+
+ /**
+ * Print the whole MEP Entry (config and status).
+ * @param mep The MEPEntry to print
+ * @return A string with MepEntry details
+ */
+ public static String printMepEntry(MepEntry mep) {
+ StringBuffer sb = new StringBuffer("MEP: ");
+ sb.append(mep.mepId());
+ sb.append(" Device:" + mep.deviceId());
+ sb.append(", Port: " + mep.port());
+ sb.append(", Vlan: " + mep.primaryVid());
+ sb.append(", AdminSt: " + mep.administrativeState());
+ sb.append(", CciEnabled: " + mep.cciEnabled());
+ sb.append(", Priority: " + mep.ccmLtmPriority());
+ sb.append("\n"); //The following are state
+ sb.append(", Total CCMs: " + mep.totalCcmsTransmitted());
+ sb.append(", MAC: " + mep.macAddress());
+ sb.append(", Fault: " + mep.fngState());
+
+ mep.activeRemoteMepList().forEach(rmep -> {
+ sb.append("\n\tRmep: " + rmep.remoteMepId());
+ sb.append(", Mac: " + rmep.macAddress());
+ sb.append(", State: " + rmep.state());
+ sb.append(", Failed Time: " + rmep.failedOrOkTime());
+
+ });
+
+
+ return sb.toString();
+ }
+
+ public static String printMdId(MdId mdId) {
+ StringBuffer sb = new StringBuffer("MD: ");
+ sb.append(mdId.mdName());
+ sb.append("(" + mdId.nameType() + ")");
+ return sb.toString();
+ }
+
+ public static String printMaId(MaIdShort maId) {
+ StringBuffer sb = new StringBuffer("MA: ");
+ sb.append(maId.maName());
+ sb.append("(" + maId.nameType() + ")");
+ return sb.toString();
+ }
+
+}
diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/cli/CfmMepListDeviceCommand.java b/apps/cfm/src/main/java/org/onosproject/cfm/cli/CfmMepListDeviceCommand.java
new file mode 100644
index 0000000..c99399a
--- /dev/null
+++ b/apps/cfm/src/main/java/org/onosproject/cfm/cli/CfmMepListDeviceCommand.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2018-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.Mep;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepService;
+import org.onosproject.net.DeviceId;
+import org.slf4j.Logger;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Lists all the MEPs on a particular device.
+ */
+@Command(scope = "onos", name = "cfm-mep-device-list",
+ description = "Lists a set of MEPs filtered by device.")
+public class CfmMepListDeviceCommand extends AbstractShellCommand {
+ private final Logger log = getLogger(getClass());
+ @Argument(index = 0, name = "device",
+ description = "Device Id",
+ required = true, multiValued = false)
+ String deviceStr = null;
+
+ @Override
+ protected void execute() {
+ CfmMepService mepService = get(CfmMepService.class);
+ if (deviceStr != null) {
+ DeviceId deviceId = DeviceId.deviceId(deviceStr);
+ try {
+ mepService.getAllMepsByDevice(deviceId).forEach(mep -> {
+ print(printMep(mep));
+ });
+ } catch (CfmConfigException e) {
+ log.error("Error retrieving Meps for Device {}",
+ deviceId, e);
+ }
+ }
+ }
+
+ /**
+ * Print only the config part of the MEP.
+ * @param mep The MEP to print
+ * @return A string with MD name, MA name and Mep details
+ */
+ public static String printMep(Mep mep) {
+ StringBuffer sb = new StringBuffer("MEP: ");
+ sb.append(mep.mdId().mdName() + "/");
+ sb.append(mep.maId().maName() + "/");
+ sb.append(mep.mepId());
+ sb.append(" Device:" + mep.deviceId());
+ sb.append(", Port: " + mep.port());
+ sb.append(", Vlan: " + mep.primaryVid());
+ sb.append(", AdminSt: " + mep.administrativeState());
+ sb.append(", CciEnabled: " + mep.cciEnabled());
+ sb.append(", Priority: " + mep.ccmLtmPriority());
+
+ return sb.toString();
+ }
+
+}
diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/cli/completer/CfmDeviceIdCompleter.java b/apps/cfm/src/main/java/org/onosproject/cfm/cli/completer/CfmDeviceIdCompleter.java
new file mode 100644
index 0000000..6e2e29f
--- /dev/null
+++ b/apps/cfm/src/main/java/org/onosproject/cfm/cli/completer/CfmDeviceIdCompleter.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2018-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.cli.AbstractShellCommand;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepProgrammable;
+import org.onosproject.net.Device;
+import org.onosproject.net.device.DeviceService;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.SortedSet;
+
+/**
+ * CLI completer for Devices that support Meps.
+ */
+public class CfmDeviceIdCompleter implements Completer {
+ @Override
+ public int complete(String buffer, int cursor, List<String> candidates) {
+ // Delegate string completer
+ StringsCompleter delegate = new StringsCompleter();
+
+ // Fetch our service and feed it's offerings to the string completer
+ DeviceService service = AbstractShellCommand.get(DeviceService.class);
+ Iterator<Device> it = service.getDevices().iterator();
+ SortedSet<String> strings = delegate.getStrings();
+ while (it.hasNext()) {
+ Device device = it.next();
+ if (device.is(CfmMepProgrammable.class)) {
+ strings.add(device.id().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/CfmMepIdCompleter.java b/apps/cfm/src/main/java/org/onosproject/cfm/cli/completer/CfmMepIdCompleter.java
new file mode 100644
index 0000000..6019916
--- /dev/null
+++ b/apps/cfm/src/main/java/org/onosproject/cfm/cli/completer/CfmMepIdCompleter.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2018-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.CfmConfigException;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMdService;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepService;
+import org.slf4j.Logger;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.onosproject.cli.AbstractShellCommand.get;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * CLI completer for Mep Id creation.
+ */
+public class CfmMepIdCompleter extends AbstractChoicesCompleter {
+ private final Logger log = getLogger(getClass());
+
+ @Override
+ public List<String> choices() {
+ List<String> choices = new ArrayList<>();
+
+ CfmMdService mdService = get(CfmMdService.class);
+ CfmMepService mepService = get(CfmMepService.class);
+
+ mdService.getAllMaintenanceDomain().forEach(md -> {
+ choices.add(new StringBuilder(md.mdId().mdName())
+ .append("(")
+ .append(md.mdId().nameType())
+ .append(")").toString());
+
+ 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());
+
+ try {
+ mepService.getAllMeps(md.mdId(), ma.maId()).forEach(mep ->
+ choices.add(new StringBuilder(md.mdId().mdName())
+ .append("(")
+ .append(md.mdId().nameType())
+ .append(") ")
+ .append(ma.maId().maName())
+ .append("(")
+ .append(ma.maId().nameType())
+ .append(") ")
+ .append(mep.mepId()).toString())
+ );
+ } catch (CfmConfigException e) {
+ log.warn("Unable to retrieve mep details", e);
+ }
+ }
+ );
+ });
+
+ return choices;
+ }
+
+}
diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/rest/CfmWebApplication.java b/apps/cfm/src/main/java/org/onosproject/cfm/rest/CfmWebApplication.java
index 13157f2..b32174e 100644
--- a/apps/cfm/src/main/java/org/onosproject/cfm/rest/CfmWebApplication.java
+++ b/apps/cfm/src/main/java/org/onosproject/cfm/rest/CfmWebApplication.java
@@ -32,6 +32,7 @@
MdWebResource.class,
MaWebResource.class,
MepWebResource.class,
+ DeviceMepWebResource.class,
DmWebResource.class,
LmWebResource.class);
}
diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/rest/DeviceMepWebResource.java b/apps/cfm/src/main/java/org/onosproject/cfm/rest/DeviceMepWebResource.java
new file mode 100644
index 0000000..5fbed6d
--- /dev/null
+++ b/apps/cfm/src/main/java/org/onosproject/cfm/rest/DeviceMepWebResource.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.rest;
+
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import org.onosproject.incubator.net.l2monitoring.cfm.Mep;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepService;
+import org.onosproject.net.DeviceId;
+import org.onosproject.rest.AbstractWebResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+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.util.Collection;
+
+/**
+ * Layer 2 CFM Maintenance Association Endpoint (MEP) by Device web resource.
+ */
+@Path("device")
+public class DeviceMepWebResource extends AbstractWebResource {
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ /**
+ * Get all MEPs by Device Id. The device should support Meps
+ *
+ * @param deviceId The id of a device.
+ * @return 200 OK with a list of MEPS or 500 on error
+ */
+ @GET
+ @Path("{device_id}")
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ public Response getAllMepsForDevice(@PathParam("device_id") String deviceId) {
+ DeviceId deviceIdObj = DeviceId.deviceId(deviceId);
+ log.debug("GET all Meps called for Device {}", deviceIdObj);
+ try {
+ Collection<Mep> mepCollection = get(CfmMepService.class)
+ .getAllMepsByDevice(deviceIdObj);
+ ArrayNode an = mapper().createArrayNode();
+ an.add(codec(Mep.class).encode(mepCollection, this));
+ return ok(mapper().createObjectNode().set("meps", an)).build();
+ } catch (CfmConfigException e) {
+ log.error("Get all Meps on device {} failed because of exception",
+ deviceIdObj, e);
+ return Response.serverError().entity("{ \"failure\":\"" + e.toString() + "\" }").build();
+ }
+ }
+}
diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/rest/MdWebResource.java b/apps/cfm/src/main/java/org/onosproject/cfm/rest/MdWebResource.java
index c642f4a..0e523a7 100644
--- a/apps/cfm/src/main/java/org/onosproject/cfm/rest/MdWebResource.java
+++ b/apps/cfm/src/main/java/org/onosproject/cfm/rest/MdWebResource.java
@@ -82,6 +82,7 @@
log.debug("GET called for MD {}", mdName);
try {
MaintenanceDomain md = get(CfmMdService.class)
+ //FIXME Handle other types of name constructs e.g. DomainName
.getMaintenanceDomain(MdIdCharStr.asMdId(mdName))
.orElseThrow(() -> new IllegalArgumentException(
"MD " + mdName + " not Found"));
diff --git a/apps/cfm/src/main/java/org/onosproject/cfm/rest/MepWebResource.java b/apps/cfm/src/main/java/org/onosproject/cfm/rest/MepWebResource.java
index fa8c728..52d4150 100644
--- a/apps/cfm/src/main/java/org/onosproject/cfm/rest/MepWebResource.java
+++ b/apps/cfm/src/main/java/org/onosproject/cfm/rest/MepWebResource.java
@@ -18,6 +18,7 @@
import java.io.InputStream;
import java.net.URI;
import java.util.Collection;
+import java.util.Optional;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
@@ -145,7 +146,7 @@
MdId mdId = MdIdCharStr.asMdId(mdName);
MaIdShort maId = MaIdCharStr.asMaId(maName);
boolean deleted = get(CfmMepService.class)
- .deleteMep(mdId, maId, MepId.valueOf(mepIdShort));
+ .deleteMep(mdId, maId, MepId.valueOf(mepIdShort), Optional.empty());
if (!deleted) {
return Response.notModified(mdName + "/" + maName + "/" +
mepIdShort + " did not exist").build();
@@ -187,8 +188,8 @@
Mep mep = ((MepCodec) mepCodec).decode((ObjectNode) cfg, this, mdName, maName);
- Boolean issuccess = get(CfmMepService.class).createMep(mdId, maId, mep);
- if (!issuccess) {
+ Boolean didNotExist = get(CfmMepService.class).createMep(mdId, maId, mep);
+ if (!didNotExist) {
return Response.notModified(mdName + "/" + ma.maId() + "/" + mep.mepId() +
" already exists").build();
}
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
index 62be35d..6c3829f 100644
--- a/apps/cfm/src/main/java/org/onosproject/cfm/web/MaintenanceAssociationCodec.java
+++ b/apps/cfm/src/main/java/org/onosproject/cfm/web/MaintenanceAssociationCodec.java
@@ -124,10 +124,13 @@
builder = builder.addToComponentList(component);
}
- List<MepId> remoteMeps = (new RMepCodec()).decode(
- (ArrayNode) nullIsIllegal(maNode.get(RMEP_LIST), "rmep-list is required"), context);
- for (MepId remoteMep:remoteMeps) {
- builder = builder.addToRemoteMepIdList(remoteMep);
+ JsonNode rmepListJson = maNode.get(RMEP_LIST);
+ if (rmepListJson != null) {
+ List<MepId> remoteMeps = (new RMepCodec()).decode(
+ (ArrayNode) rmepListJson, context);
+ for (MepId remoteMep:remoteMeps) {
+ builder = builder.addToRemoteMepIdList(remoteMep);
+ }
}
return builder.build();
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
index 5f53eba..fcd66a0 100644
--- a/apps/cfm/src/main/resources/OSGI-INF/blueprint/shell-config.xml
+++ b/apps/cfm/src/main/resources/OSGI-INF/blueprint/shell-config.xml
@@ -57,6 +57,18 @@
<ref component-id="maNameCompleter"/>
</completers>
</command>
+ <command>
+ <action class="org.onosproject.cfm.cli.CfmMepListCommand"/>
+ <completers>
+ <ref component-id="mepIdCompleter"/>
+ </completers>
+ </command>
+ <command>
+ <action class="org.onosproject.cfm.cli.CfmMepListDeviceCommand"/>
+ <completers>
+ <ref component-id="mepDeviceIdCompleter"/>
+ </completers>
+ </command>
</command-bundle>
<bean id="placeholderCompleter" class="org.onosproject.cli.PlaceholderCompleter"/>
@@ -68,6 +80,8 @@
<bean id="maCcmIntervalCompleter" class="org.onosproject.cfm.cli.completer.CfmMaCcmIntervalCompleter"/>
<bean id="compTagTypeCompleter" class="org.onosproject.cfm.cli.completer.CfmCompTagTypeCompleter"/>
<bean id="compMhfCompleter" class="org.onosproject.cfm.cli.completer.CfmCompMhfCompleter"/>
+ <bean id="mepIdCompleter" class="org.onosproject.cfm.cli.completer.CfmMepIdCompleter"/>
+ <bean id="mepDeviceIdCompleter" class="org.onosproject.cfm.cli.completer.CfmDeviceIdCompleter"/>
</blueprint>
diff --git a/apps/cfm/src/main/resources/definitions/MaCreate.json b/apps/cfm/src/main/resources/definitions/MaCreate.json
index fea36db..5b6be27 100644
--- a/apps/cfm/src/main/resources/definitions/MaCreate.json
+++ b/apps/cfm/src/main/resources/definitions/MaCreate.json
@@ -133,7 +133,8 @@
}
}
},
- "example": [{"rmep": 10}, {"rmep": 20}]
+ "example": [{"rmep": 10}, {"rmep": 20}],
+ "description": "An optional set of Mep IDs that might be on equipment not managed by ONOS"
}
}
}
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
index 6378ea9..8216dde 100644
--- a/apps/cfm/src/test/java/org/onosproject/cfm/impl/MaWebResourceTest.java
+++ b/apps/cfm/src/test/java/org/onosproject/cfm/impl/MaWebResourceTest.java
@@ -22,7 +22,6 @@
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;
@@ -43,7 +42,6 @@
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;
@@ -72,7 +70,7 @@
ServiceDirectory testDirectory = new TestServiceDirectory()
.add(CfmMdService.class, mdService)
.add(CodecService.class, context.codecManager());
- BaseResource.setServiceDirectory(testDirectory);
+ setServiceDirectory(testDirectory);
ma1 = DefaultMaintenanceAssociation
.builder(MANAME1, MDNAME1.getNameLength())
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
index f4c9b5a..3c65176 100644
--- a/apps/cfm/src/test/java/org/onosproject/cfm/impl/MdWebResourceTest.java
+++ b/apps/cfm/src/test/java/org/onosproject/cfm/impl/MdWebResourceTest.java
@@ -21,7 +21,6 @@
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;
@@ -65,7 +64,7 @@
ServiceDirectory testDirectory = new TestServiceDirectory()
.add(CfmMdService.class, mdService)
.add(CodecService.class, context.codecManager());
- BaseResource.setServiceDirectory(testDirectory);
+ setServiceDirectory(testDirectory);
mdList = new ArrayList<>();
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
index 4dd83db..6a5dbca 100644
--- a/apps/cfm/src/test/java/org/onosproject/cfm/impl/MepWebResourceTest.java
+++ b/apps/cfm/src/test/java/org/onosproject/cfm/impl/MepWebResourceTest.java
@@ -22,7 +22,6 @@
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;
@@ -86,7 +85,7 @@
.add(CfmMepService.class, mepService)
.add(CfmMdService.class, mdService)
.add(CodecService.class, context.codecManager());
- BaseResource.setServiceDirectory(testDirectory);
+ setServiceDirectory(testDirectory);
mepEntry1 = DefaultMepEntry.builder(
MEPID1,
@@ -186,7 +185,7 @@
@Test
public void testDeleteMepValid() throws CfmConfigException {
- expect(mepService.deleteMep(MDNAME1, MANAME1, MepId.valueOf((short) 1)))
+ expect(mepService.deleteMep(MDNAME1, MANAME1, MepId.valueOf((short) 1), Optional.empty()))
.andReturn(true).anyTimes();
replay(mepService);
@@ -200,7 +199,7 @@
@Test
public void testDeleteMepNotFound() throws CfmConfigException {
- expect(mepService.deleteMep(MDNAME1, MANAME1, MepId.valueOf((short) 2)))
+ expect(mepService.deleteMep(MDNAME1, MANAME1, MepId.valueOf((short) 2), Optional.empty()))
.andReturn(false).anyTimes();
replay(mepService);
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
index 702bc09..6fac3a3 100644
--- a/apps/cfm/src/test/java/org/onosproject/soam/impl/DmWebResourceTest.java
+++ b/apps/cfm/src/test/java/org/onosproject/soam/impl/DmWebResourceTest.java
@@ -21,7 +21,6 @@
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;
@@ -50,7 +49,6 @@
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;
@@ -61,7 +59,9 @@
import java.util.List;
import static junit.framework.TestCase.fail;
-import static org.easymock.EasyMock.*;
+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;
@@ -88,7 +88,7 @@
.add(CfmMepService.class, mepService)
.add(SoamService.class, soamService)
.add(CodecService.class, context.codecManager());
- BaseResource.setServiceDirectory(testDirectory);
+ setServiceDirectory(testDirectory);
DelayMeasurementStatCurrent.DmStatCurrentBuilder dmCurrBuilder1 =
(DelayMeasurementStatCurrent.DmStatCurrentBuilder)
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
index 9dd70e6..44b4960 100644
--- a/apps/cfm/src/test/java/org/onosproject/soam/impl/LmWebResourceTest.java
+++ b/apps/cfm/src/test/java/org/onosproject/soam/impl/LmWebResourceTest.java
@@ -21,7 +21,6 @@
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;
@@ -87,7 +86,7 @@
.add(CfmMepService.class, mepService)
.add(SoamService.class, soamService)
.add(CodecService.class, context.codecManager());
- BaseResource.setServiceDirectory(testDirectory);
+ setServiceDirectory(testDirectory);
lm1 = DefaultLmEntry.builder(
DelayMeasurementCreate.Version.Y17312008,
diff --git a/apps/config/src/main/java/org/onosproject/config/impl/DistributedDynamicConfigStore.java b/apps/config/src/main/java/org/onosproject/config/impl/DistributedDynamicConfigStore.java
index 3923173..8f1662c 100644
--- a/apps/config/src/main/java/org/onosproject/config/impl/DistributedDynamicConfigStore.java
+++ b/apps/config/src/main/java/org/onosproject/config/impl/DistributedDynamicConfigStore.java
@@ -300,7 +300,7 @@
entries = complete(ret);
log.trace(" keystore.getChildren({})", spath);
log.trace(" entries keys:{}", entries.keySet());
- if ((entries != null) && (!entries.isEmpty())) {
+ if (!entries.isEmpty()) {
entries.forEach((k, v) -> {
String[] names = k.split(ResourceIdParser.NM_CHK);
String name = names[0];
diff --git a/apps/configsync-netconf/pom.xml b/apps/configsync-netconf/pom.xml
index 4f832bc..7a23711 100644
--- a/apps/configsync-netconf/pom.xml
+++ b/apps/configsync-netconf/pom.xml
@@ -124,18 +124,6 @@
</dependencies>
<build>
- <pluginManagement>
- <plugins>
-
- <plugin>
- <groupId>org.apache.karaf.tooling</groupId>
- <artifactId>karaf-maven-plugin</artifactId>
- <version>3.0.5</version>
- <extensions>true</extensions>
- </plugin>
-
- </plugins>
- </pluginManagement>
<plugins>
<plugin>
diff --git a/apps/configsync/pom.xml b/apps/configsync/pom.xml
index 270dda3..1376461 100644
--- a/apps/configsync/pom.xml
+++ b/apps/configsync/pom.xml
@@ -124,18 +124,6 @@
</dependencies>
<build>
- <pluginManagement>
- <plugins>
-
- <plugin>
- <groupId>org.apache.karaf.tooling</groupId>
- <artifactId>karaf-maven-plugin</artifactId>
- <version>3.0.5</version>
- <extensions>true</extensions>
- </plugin>
-
- </plugins>
- </pluginManagement>
<plugins>
<plugin>
diff --git a/apps/cpman/api/src/main/java/org/onosproject/cpman/ControlLoadSnapshot.java b/apps/cpman/api/src/main/java/org/onosproject/cpman/ControlLoadSnapshot.java
index b3f34ea..532297d 100644
--- a/apps/cpman/api/src/main/java/org/onosproject/cpman/ControlLoadSnapshot.java
+++ b/apps/cpman/api/src/main/java/org/onosproject/cpman/ControlLoadSnapshot.java
@@ -99,7 +99,7 @@
@Override
public int hashCode() {
- return Objects.hash(latest, average, time, recent);
+ return Objects.hash(latest, average, time, Arrays.hashCode(recent));
}
@Override
diff --git a/apps/cpman/app/src/main/java/org/onosproject/cpman/rest/SystemMetricsCollectorWebResource.java b/apps/cpman/app/src/main/java/org/onosproject/cpman/rest/SystemMetricsCollectorWebResource.java
index ca10f86..dc7ea22 100644
--- a/apps/cpman/app/src/main/java/org/onosproject/cpman/rest/SystemMetricsCollectorWebResource.java
+++ b/apps/cpman/app/src/main/java/org/onosproject/cpman/rest/SystemMetricsCollectorWebResource.java
@@ -93,7 +93,7 @@
ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
if (jsonTree == null || !checkFields(jsonTree, CPU_FIELD_SET)) {
- ok(root).build();
+ return ok(root).build();
}
long cpuLoad = nullIsIllegal((long) (jsonTree.get("cpuLoad").asDouble()
@@ -154,7 +154,7 @@
ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
if (jsonTree == null || !checkFields(jsonTree, MEMORY_FIELD_SET)) {
- ok(root).build();
+ return ok(root).build();
}
long memUsed = nullIsIllegal(jsonTree.get("memoryUsed").asLong(), INVALID_REQUEST);
diff --git a/apps/cpman/app/src/test/java/org/onosproject/cpman/rest/ControlMetricsCollectorResourceTest.java b/apps/cpman/app/src/test/java/org/onosproject/cpman/rest/ControlMetricsCollectorResourceTest.java
index b505cd5..a225113 100644
--- a/apps/cpman/app/src/test/java/org/onosproject/cpman/rest/ControlMetricsCollectorResourceTest.java
+++ b/apps/cpman/app/src/test/java/org/onosproject/cpman/rest/ControlMetricsCollectorResourceTest.java
@@ -32,7 +32,6 @@
import org.onlab.metrics.MetricsService;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.TestServiceDirectory;
-import org.onlab.rest.BaseResource;
import org.onosproject.cpman.ControlPlaneMonitorService;
import org.onosproject.cpman.SystemInfo;
import org.onosproject.cpman.impl.SystemInfoFactory;
@@ -86,7 +85,7 @@
new TestServiceDirectory()
.add(ControlPlaneMonitorService.class, mockControlPlaneMonitorService)
.add(MetricsService.class, mockMetricsService);
- BaseResource.setServiceDirectory(testDirectory);
+ setServiceDirectory(testDirectory);
}
/**
diff --git a/apps/cpman/app/src/test/java/org/onosproject/cpman/rest/ControlMetricsResourceTest.java b/apps/cpman/app/src/test/java/org/onosproject/cpman/rest/ControlMetricsResourceTest.java
index 8549167..7c48680 100644
--- a/apps/cpman/app/src/test/java/org/onosproject/cpman/rest/ControlMetricsResourceTest.java
+++ b/apps/cpman/app/src/test/java/org/onosproject/cpman/rest/ControlMetricsResourceTest.java
@@ -22,7 +22,6 @@
import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.TestServiceDirectory;
import org.onlab.packet.IpAddress;
-import org.onlab.rest.BaseResource;
import org.onosproject.cluster.ClusterService;
import org.onosproject.cluster.ControllerNode;
import org.onosproject.cluster.NodeId;
@@ -151,7 +150,7 @@
mockControlPlaneMonitorService)
.add(ClusterService.class, mockClusterService)
.add(CodecService.class, codecService);
- BaseResource.setServiceDirectory(testDirectory);
+ setServiceDirectory(testDirectory);
nodeId = new NodeId("1");
mockControlLoad = new MockControlLoad();
diff --git a/apps/dhcp/api/src/main/java/org/onosproject/dhcp/IpAssignment.java b/apps/dhcp/api/src/main/java/org/onosproject/dhcp/IpAssignment.java
index d4beda2..7b83f0c 100644
--- a/apps/dhcp/api/src/main/java/org/onosproject/dhcp/IpAssignment.java
+++ b/apps/dhcp/api/src/main/java/org/onosproject/dhcp/IpAssignment.java
@@ -310,7 +310,6 @@
private void validateInputs() {
checkNotNull(ipAddress, "IP Address must be specified");
checkNotNull(assignmentStatus, "Assignment Status must be specified");
- checkNotNull(leasePeriod, "Lease Period must be specified");
checkNotNull(timeStamp, "Timestamp must be specified");
switch (assignmentStatus) {
diff --git a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/Dhcp4HandlerImpl.java b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/Dhcp4HandlerImpl.java
index b45433f..5b255ab 100644
--- a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/Dhcp4HandlerImpl.java
+++ b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/Dhcp4HandlerImpl.java
@@ -792,9 +792,6 @@
}
}
- // Remove broadcast flag
- dhcpPacket.setFlags((short) 0);
-
udpPacket.setPayload(dhcpPacket);
// As a DHCP relay, the source port should be server port( instead
// of client port.
@@ -1017,14 +1014,18 @@
// if client is indirectly connected, try use next hop mac address
MacAddress macAddress = MacAddress.valueOf(dhcpPayload.getClientHardwareAddress());
HostId hostId = HostId.hostId(macAddress, vlanId);
- DhcpRecord record = dhcpRelayStore.getDhcpRecord(hostId).orElse(null);
- if (record != null) {
- // if next hop can be found, use mac address of next hop
- record.nextHop().ifPresent(etherReply::setDestinationMACAddress);
+ if (((int) dhcpPayload.getFlags() & 0x8000) == 0x0000) {
+ DhcpRecord record = dhcpRelayStore.getDhcpRecord(hostId).orElse(null);
+ if (record != null) {
+ // if next hop can be found, use mac address of next hop
+ record.nextHop().ifPresent(etherReply::setDestinationMACAddress);
+ } else {
+ // otherwise, discard the packet
+ log.warn("Can't find record for host id {}, discard packet", hostId);
+ return null;
+ }
} else {
- // otherwise, discard the packet
- log.warn("Can't find record for host id {}, discard packet", hostId);
- return null;
+ etherReply.setDestinationMACAddress(MacAddress.BROADCAST);
}
} else {
etherReply.setDestinationMACAddress(dhcpPayload.getClientHardwareAddress());
@@ -1043,7 +1044,11 @@
// SRC_IP: relay agent IP
// DST_IP: offered IP
ipv4Packet.setSourceAddress(ipFacingClient.toInt());
- ipv4Packet.setDestinationAddress(dhcpPayload.getYourIPAddress());
+ if (((int) dhcpPayload.getFlags() & 0x8000) == 0x0000) {
+ ipv4Packet.setDestinationAddress(dhcpPayload.getYourIPAddress());
+ } else {
+ ipv4Packet.setDestinationAddress(BROADCAST_IP);
+ }
udpPacket.setSourcePort(UDP.DHCP_SERVER_PORT);
if (directlyConnected(dhcpPayload)) {
udpPacket.setDestinationPort(UDP.DHCP_CLIENT_PORT);
diff --git a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/Dhcp6HandlerImpl.java b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/Dhcp6HandlerImpl.java
index 9a8b3e0..0cb3468 100644
--- a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/Dhcp6HandlerImpl.java
+++ b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/Dhcp6HandlerImpl.java
@@ -14,7 +14,6 @@
* limitations under the License.
*
*/
-
package org.onosproject.dhcprelay;
import com.google.common.collect.HashMultimap;
@@ -42,12 +41,14 @@
import org.onlab.packet.VlanId;
import org.onlab.packet.dhcp.Dhcp6RelayOption;
import org.onlab.packet.dhcp.Dhcp6InterfaceIdOption;
-import org.onlab.packet.dhcp.Dhcp6Option;
import org.onlab.packet.dhcp.Dhcp6IaNaOption;
import org.onlab.packet.dhcp.Dhcp6IaTaOption;
import org.onlab.packet.dhcp.Dhcp6IaPdOption;
import org.onlab.packet.dhcp.Dhcp6IaAddressOption;
import org.onlab.packet.dhcp.Dhcp6IaPrefixOption;
+import org.onlab.packet.dhcp.Dhcp6ClientIdOption;
+import org.onlab.packet.dhcp.Dhcp6Duid;
+import org.onlab.packet.DHCP6.MsgType;
import org.onlab.util.HexString;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
@@ -55,7 +56,10 @@
import org.onosproject.dhcprelay.api.DhcpServerInfo;
import org.onosproject.dhcprelay.config.IgnoreDhcpConfig;
import org.onosproject.dhcprelay.store.DhcpRelayStore;
+import org.onosproject.dhcprelay.store.DhcpRecord;
import org.onosproject.dhcprelay.store.DhcpFpmPrefixStore;
+import org.onosproject.dhcprelay.store.DhcpRelayCounters;
+import org.onosproject.dhcprelay.store.DhcpRelayCountersStore;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.routing.fpm.api.FpmRecord;
@@ -97,6 +101,7 @@
import org.slf4j.LoggerFactory;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.dhcprelay.Dhcp6HandlerUtil.InternalPacket;
import java.nio.ByteBuffer;
@@ -106,12 +111,11 @@
import java.util.Set;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicInteger;
-
-
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static org.onosproject.net.flowobjective.Objective.Operation.ADD;
import static org.onosproject.net.flowobjective.Objective.Operation.REMOVE;
+import java.util.concurrent.Semaphore;
@Component
@Service
@@ -120,7 +124,7 @@
public static final String DHCP_V6_RELAY_APP = "org.onosproject.Dhcp6HandlerImpl";
public static final ProviderId PROVIDER_ID = new ProviderId("dhcp6", DHCP_V6_RELAY_APP);
private static final int IGNORE_CONTROL_PRIORITY = PacketPriority.CONTROL.priorityValue() + 1000;
-
+ private String gCount = "global";
private static final TrafficSelector CLIENT_SERVER_SELECTOR = DefaultTrafficSelector.builder()
.matchEthType(Ethernet.TYPE_IPV6)
.matchIPProtocol(IPv6.PROTOCOL_UDP)
@@ -145,6 +149,9 @@
protected DhcpRelayStore dhcpRelayStore;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DhcpRelayCountersStore dhcpRelayCountersStore;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected PacketService packetService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
@@ -178,9 +185,22 @@
private Boolean dhcpFpmEnabled = false;
+ private Dhcp6HandlerUtil dhcp6HandlerUtil = new Dhcp6HandlerUtil();
+
private List<DhcpServerInfo> defaultServerInfoList = Lists.newArrayList();
private List<DhcpServerInfo> indirectServerInfoList = Lists.newArrayList();
+ private class IpAddressInfo {
+ Ip6Address ip6Address;
+ long prefTime;
+ }
+ private class PdPrefixInfo {
+ IpPrefix pdPrefix;
+ long prefTime;
+ }
+ protected int dhcp6PollInterval = 24 * 3600; // 24 hr period
+ // max 1 thread
+ static Semaphore recordSemaphore = new Semaphore(1);
// CLIENT message types
public static final Set<Byte> MSG_TYPE_FROM_CLIENT =
@@ -275,16 +295,18 @@
Ethernet receivedPacket = context.inPacket().parsed();
if (!configured()) {
- log.warn("Missing DHCP6 relay server config. Abort packet processing");
- log.trace("dhcp6 payload {}", dhcp6Payload);
-
+ log.warn("Missing DHCP6 relay server config. Abort packet processing dhcp6 payload {}", dhcp6Payload);
return;
}
-
- byte msgType = dhcp6Payload.getMsgType();
+ byte msgTypeVal = dhcp6Payload.getMsgType();
+ MsgType msgType = DHCP6.MsgType.getType(msgTypeVal);
+ log.debug("msgType is {}", msgType);
ConnectPoint inPort = context.inPacket().receivedFrom();
+ if (inPort == null) {
+ log.warn("incomming ConnectPoint is null");
+ }
Set<Interface> receivingInterfaces = interfaceService.getInterfacesByPort(inPort);
//ignore the packets if dhcp client interface is not configured on onos.
if (receivingInterfaces.isEmpty()) {
@@ -292,27 +314,25 @@
return;
}
+ if (MSG_TYPE_FROM_CLIENT.contains(msgTypeVal)) {
- if (MSG_TYPE_FROM_CLIENT.contains(msgType)) {
- InternalPacket ethernetClientPacket =
+ List<InternalPacket> ethernetClientPacket =
processDhcp6PacketFromClient(context, receivedPacket, receivingInterfaces);
- if (ethernetClientPacket != null) {
- forwardPacket(ethernetClientPacket);
+ for (InternalPacket internalPacket : ethernetClientPacket) {
+ forwardPacket(internalPacket);
}
-
- } else if (MSG_TYPE_FROM_SERVER.contains(msgType)) {
- log.debug("calling processDhcp6PacketFromServer with RELAY_REPL", msgType);
+ } else if (MSG_TYPE_FROM_SERVER.contains(msgTypeVal)) {
+ log.debug("calling processDhcp6PacketFromServer with RELAY_REPL {}", msgTypeVal);
InternalPacket ethernetPacketReply =
processDhcp6PacketFromServer(context, receivedPacket, receivingInterfaces);
if (ethernetPacketReply != null) {
forwardPacket(ethernetPacketReply);
}
} else {
- log.warn("DHCP type {} not supported yet", msgType);
+ log.warn("Not so fast, packet type {} not supported yet", msgTypeVal);
}
}
-
/**
* Checks if this app has been configured.
*
@@ -332,19 +352,7 @@
// Do nothing here
}
- // the new class the contains Ethernet packet and destination port, kind of like adding
- // internal header to the packet
- private class InternalPacket {
- Ethernet packet;
- ConnectPoint destLocation;
- public InternalPacket(Ethernet newPacket, ConnectPoint newLocation) {
- packet = newPacket;
- destLocation = newLocation;
- }
- void setLocation(ConnectPoint newLocation) {
- destLocation = newLocation;
- }
- }
+
//forward the packet to ConnectPoint where the DHCP server is attached.
private void forwardPacket(InternalPacket packet) {
@@ -361,168 +369,17 @@
} // if
}
- /**
- * Check if the host is directly connected to the network or not.
- *
- * @param dhcp6Payload the dhcp6 payload
- * @return true if the host is directly connected to the network; false otherwise
- */
- private boolean directlyConnected(DHCP6 dhcp6Payload) {
- log.debug("directlyConnected enters");
-
- if (dhcp6Payload.getMsgType() != DHCP6.MsgType.RELAY_FORW.value() &&
- dhcp6Payload.getMsgType() != DHCP6.MsgType.RELAY_REPL.value()) {
- log.debug("directlyConnected true. MsgType {}", dhcp6Payload.getMsgType());
-
- return true;
- }
-
- // Regardless of relay-forward or relay-replay, check if we see another relay message
- DHCP6 dhcp6Payload2 = dhcp6PacketFromRelayPacket(dhcp6Payload);
- if (dhcp6Payload2 != null) {
- if (dhcp6Payload.getMsgType() == DHCP6.MsgType.RELAY_FORW.value()) {
- log.debug("directlyConnected false. 1st realy-foward, 2nd MsgType {}", dhcp6Payload2.getMsgType());
- return false;
- } else {
- // relay-reply
- if (dhcp6Payload2.getMsgType() != DHCP6.MsgType.RELAY_REPL.value()) {
- log.debug("directlyConnected true. 2nd MsgType {}", dhcp6Payload2.getMsgType());
- return true; // must be directly connected
- } else {
- log.debug("directlyConnected false. 1st relay-reply, 2nd relay-reply MsgType {}",
- dhcp6Payload2.getMsgType());
- return false; // must be indirectly connected
- }
- }
- } else {
- log.debug("directlyConnected true.");
- return true;
- }
- }
-
- /**
- * extract DHCP6 payload from dhcp6 relay message within relay-forwrd/reply.
- *
- * @param dhcp6 dhcp6 relay-reply or relay-foward
- * @return dhcp6Packet dhcp6 packet extracted from relay-message
- */
- private DHCP6 dhcp6PacketFromRelayPacket(DHCP6 dhcp6) {
- log.debug("dhcp6PacketFromRelayPacket enters. dhcp6 {}", dhcp6);
-
- // extract the relay message if exist
- DHCP6 dhcp6Payload = dhcp6.getOptions().stream()
- .filter(opt -> opt instanceof Dhcp6RelayOption)
- .map(BasePacket::getPayload)
- .map(pld -> (DHCP6) pld)
- .findFirst()
- .orElse(null);
- if (dhcp6Payload == null) {
- // Can't find dhcp payload
- log.debug("Can't find dhcp6 payload from relay message");
- } else {
- log.debug("dhcp6 payload found from relay message {}", dhcp6Payload);
- }
-
- return dhcp6Payload;
- }
-
- /**
- * find the leaf DHCP6 packet from multi-level relay packet.
- *
- * @param relayPacket dhcp6 relay packet
- * @return leafPacket non-relay dhcp6 packet
- */
- private DHCP6 getDhcp6Leaf(DHCP6 relayPacket) {
- DHCP6 dhcp6Parent = relayPacket;
- DHCP6 dhcp6Child = null;
-
- log.debug("getDhcp6Leaf entered.");
- while (dhcp6Parent != null) {
- dhcp6Child = dhcp6PacketFromRelayPacket(dhcp6Parent);
-
- if (dhcp6Child != null) {
- if (dhcp6Child.getMsgType() != DHCP6.MsgType.RELAY_FORW.value() &&
- dhcp6Child.getMsgType() != DHCP6.MsgType.RELAY_REPL.value()) {
- log.debug("leaf dhcp6 packet found.");
- break;
- } else {
- // found another relay
- // go for another loop
- dhcp6Parent = dhcp6Child;
- }
- } else {
- log.warn("Expected dhcp6 within relay pkt, but no dhcp6 leaf found.");
- break;
- }
- }
- return dhcp6Child;
- }
-
- /**
- * check if DHCP6 relay-reply is reply.
- *
- * @param relayPacket dhcp6 relay-reply
- * @return boolean relay-reply contains ack
- */
- private boolean isDhcp6Reply(DHCP6 relayPacket) {
- log.debug("isDhcp6Reply entered.");
-
- DHCP6 leafDhcp6 = getDhcp6Leaf(relayPacket);
-
- if (leafDhcp6 != null) {
- if (leafDhcp6.getMsgType() == DHCP6.MsgType.REPLY.value()) {
- log.debug("isDhcp6Reply true.");
- return true; // must be directly connected
- } else {
- log.debug("isDhcp6Reply false. leaf dhcp6 is not replay. MsgType {}", leafDhcp6.getMsgType());
- }
- } else {
- log.debug("isDhcp6Reply false. Expected dhcp6 within relay pkt but not found.");
- }
- log.debug("isDhcp6Reply false.");
- return false;
- }
-
- /**
- * check if DHCP6 is release or relay-forward contains release.
- *
- * @param dhcp6Payload dhcp6 packet
- * @return boolean dhcp6 contains release
- */
- private boolean isDhcp6Release(DHCP6 dhcp6Payload) {
-
- log.debug("isDhcp6Release entered.");
-
- if (dhcp6Payload.getMsgType() == DHCP6.MsgType.RELEASE.value()) {
- log.debug("isDhcp6Release true.");
- return true; // must be directly connected
- } else {
- DHCP6 dhcp6Leaf = getDhcp6Leaf(dhcp6Payload);
- if (dhcp6Leaf != null) {
- if (dhcp6Leaf.getMsgType() == DHCP6.MsgType.RELEASE.value()) {
- log.debug("isDhcp6Release true. indirectlry connected");
- return true;
- } else {
- log.debug("leaf dhcp6 is not release. MsgType {}", dhcp6Leaf.getMsgType());
- return false;
- }
- } else {
- log.debug("isDhcp6Release false. dhcp6 is niether relay nor release.");
- return false;
- }
- }
- }
/**
* extract from dhcp6 packet client ipv6 address of given by dhcp server.
*
* @param dhcp6 the dhcp6 packet
- * @return Ip6Address Ip6Address given by dhcp server, or null if not exists
+ * @return IpAddressInfo IpAddressInfo given by dhcp server, or null if not exists
*/
- private Ip6Address extractIpAddress(DHCP6 dhcp6) {
- Ip6Address ip = null;
+ private IpAddressInfo extractIpAddress(DHCP6 dhcp6) {
+ IpAddressInfo ipInfo = new IpAddressInfo();
log.debug("extractIpAddress enters dhcp6 {}.", dhcp6);
// Extract IPv6 address from IA NA ot IA TA option
@@ -552,18 +409,18 @@
.map(opt -> (Dhcp6IaAddressOption) opt)
.findFirst();
} else {
+ log.info("No IPv6 address found from iaTaOption {}", iaTaOption);
iaAddressOption = Optional.empty();
}
if (iaAddressOption.isPresent()) {
- ip = iaAddressOption.get().getIp6Address();
+ ipInfo.ip6Address = iaAddressOption.get().getIp6Address();
+ ipInfo.prefTime = iaAddressOption.get().getPreferredLifetime();
log.debug("Found IPv6 address from iaAddressOption {}", iaAddressOption);
-
-
} else {
log.debug("Can't find IPv6 address from DHCPv6 {}", dhcp6);
+ return null;
}
-
- return ip;
+ return ipInfo;
}
/**
* extract from dhcp6 packet Prefix prefix provided by dhcp server.
@@ -571,11 +428,11 @@
* @param dhcp6 the dhcp6 payload
* @return IpPrefix Prefix Delegation prefix, or null if not exists.
*/
- private IpPrefix extractPrefix(DHCP6 dhcp6) {
- log.trace("extractPrefix enters {}", dhcp6);
+ private PdPrefixInfo extractPrefix(DHCP6 dhcp6) {
+ log.debug("extractPrefix enters {}", dhcp6);
// extract prefix
- IpPrefix prefixPrefix = null;
+ PdPrefixInfo pdPrefixInfo = new PdPrefixInfo();
Ip6Address prefixAddress = null;
@@ -588,485 +445,507 @@
Optional<Dhcp6IaPrefixOption> iaPrefixOption;
if (iaPdOption.isPresent()) {
- log.trace("IA_PD option found {}", iaPdOption);
+ log.debug("IA_PD option found {}", iaPdOption);
iaPrefixOption = iaPdOption.get().getOptions().stream()
.filter(opt -> opt instanceof Dhcp6IaPrefixOption)
.map(opt -> (Dhcp6IaPrefixOption) opt)
.findFirst();
} else {
- log.trace("IA_PD option NOT found");
+ log.debug("IA_PD option NOT found");
iaPrefixOption = Optional.empty();
}
if (iaPrefixOption.isPresent()) {
- log.trace("IAPrefix Option within IA_PD option found {}", iaPrefixOption);
+ log.debug("IAPrefix Option within IA_PD option found {}", iaPrefixOption);
prefixAddress = iaPrefixOption.get().getIp6Prefix();
int prefixLen = (int) iaPrefixOption.get().getPrefixLength();
- log.trace("Prefix length is {} bits", prefixLen);
- prefixPrefix = IpPrefix.valueOf(prefixAddress, prefixLen);
+ log.debug("Prefix length is {} bits", prefixLen);
+ pdPrefixInfo.pdPrefix = IpPrefix.valueOf(prefixAddress, prefixLen);
+ pdPrefixInfo.prefTime = iaPrefixOption.get().getPreferredLifetime();
} else {
- log.trace("Can't find IPv6 prefix from DHCPv6 {}", dhcp6);
+ log.debug("Can't find IPv6 prefix from DHCPv6 {}", dhcp6);
+ return null;
}
-
- return prefixPrefix;
+ return pdPrefixInfo;
}
/**
- * remove host or route.
+ * extract from dhcp6 packet ClientIdOption.
+ *
+ * @param directConnFlag directly connected host
+ * @param dhcp6Payload the dhcp6 payload
+ * @return Dhcp6ClientIdOption clientIdOption, or null if not exists.
+ */
+ private Dhcp6ClientIdOption extractClinedId(Boolean directConnFlag, DHCP6 dhcp6Payload) {
+ Dhcp6ClientIdOption clientIdOption;
+
+ if (directConnFlag) {
+ clientIdOption = dhcp6Payload.getOptions()
+ .stream()
+ .filter(opt -> opt instanceof Dhcp6ClientIdOption)
+ .map(opt -> (Dhcp6ClientIdOption) opt)
+ .findFirst()
+ .orElse(null);
+ } else {
+ DHCP6 leafDhcp = dhcp6HandlerUtil.getDhcp6Leaf(dhcp6Payload);
+ clientIdOption = leafDhcp.getOptions()
+ .stream()
+ .filter(opt -> opt instanceof Dhcp6ClientIdOption)
+ .map(opt -> (Dhcp6ClientIdOption) opt)
+ .findFirst()
+ .orElse(null);
+ }
+
+ return clientIdOption;
+ }
+ /**
+ * remove host or route and update dhcp relay record attributes.
*
* @param directConnFlag flag to show that packet is from directly connected client
+ * @param location client side connect point
* @param dhcp6Packet the dhcp6 payload
* @param clientPacket client's ethernet packet
* @param clientIpv6 client's Ipv6 packet
* @param clientInterface client interfaces
*/
- private void removeHostOrRoute(boolean directConnFlag, DHCP6 dhcp6Packet,
+ private void removeHostOrRoute(boolean directConnFlag, ConnectPoint location,
+ DHCP6 dhcp6Packet,
Ethernet clientPacket, IPv6 clientIpv6,
Interface clientInterface) {
- log.debug("extractPrefix enters {}", dhcp6Packet);
+ log.debug("removeHostOrRoute enters {}", dhcp6Packet);
VlanId vlanId = clientInterface.vlan();
- MacAddress clientMac = clientPacket.getSourceMAC();
- log.debug("client mac {} client vlan {}", HexString.toHexString(clientMac.toBytes(), ":"), vlanId);
+ MacAddress srcMac = clientPacket.getSourceMAC(); // could be gw or host
+ MacAddress leafClientMac;
+ byte leafMsgType;
+ log.debug("client mac {} client vlan {}", HexString.toHexString(srcMac.toBytes(), ":"), vlanId);
- // add host or route
- if (isDhcp6Release(dhcp6Packet)) {
- IpAddress ip = null;
- if (directConnFlag) {
- // Add to host store if it is connected to network directly
- ip = extractIpAddress(dhcp6Packet);
- if (ip != null) {
+ Dhcp6ClientIdOption clientIdOption = extractClinedId(directConnFlag, dhcp6Packet);
+ if (clientIdOption != null) {
+ if ((clientIdOption.getDuid().getDuidType() == Dhcp6Duid.DuidType.DUID_LLT) ||
+ (clientIdOption.getDuid().getDuidType() == Dhcp6Duid.DuidType.DUID_LL)) {
+ leafClientMac = MacAddress.valueOf(clientIdOption.getDuid().getLinkLayerAddress());
+ } else {
+ log.warn("Link-Layer Address not supported in CLIENTID option. No DhcpRelay Record created.");
+ dhcpRelayCountersStore.incrementCounter(gCount, DhcpRelayCounters.NO_LINKLOCAL_FAIL);
+ return;
+ }
+ } else {
+ log.warn("CLIENTID option NOT found. Don't create DhcpRelay Record.");
+ dhcpRelayCountersStore.incrementCounter(gCount, DhcpRelayCounters.NO_CLIENTID_FAIL);
+ return;
+ }
- HostId hostId = HostId.hostId(clientMac, vlanId);
+ HostId leafHostId = HostId.hostId(leafClientMac, vlanId);
+ DhcpRecord record = dhcpRelayStore.getDhcpRecord(leafHostId).orElse(null);
+ if (record == null) {
+ record = new DhcpRecord(leafHostId);
+ } else {
+ record = record.clone();
+ }
+
+ Boolean isMsgRelease = dhcp6HandlerUtil.isDhcp6Release(dhcp6Packet);
+ IpAddressInfo ipInfo;
+ PdPrefixInfo pdInfo = null;
+ if (directConnFlag) {
+ // Add to host store if it is connected to network directly
+ ipInfo = extractIpAddress(dhcp6Packet);
+ if (ipInfo != null) {
+ if (isMsgRelease) {
+ HostId hostId = HostId.hostId(srcMac, vlanId);
log.debug("remove Host {} ip for directly connected.", hostId.toString());
- // Remove host's ip of when dhcp release msg is received
- providerService.removeIpFromHost(hostId, ip);
- } else {
- log.debug("ipAddress not found. Do not add Host for directly connected.");
+ providerService.removeIpFromHost(hostId, ipInfo.ip6Address);
}
} else {
- // Remove from route store if it is not connected to network directly
- // pick out the first link-local ip address
- IpAddress nextHopIp = getFirstIpByHost(clientMac, vlanId);
- if (nextHopIp == null) {
- log.warn("Can't find link-local IP address of gateway mac {} vlanId {}",
- clientMac, vlanId);
- return;
- }
+ log.debug("ipAddress not found. Do not remove Host {} for directly connected.",
+ HostId.hostId(srcMac, vlanId).toString());
+ }
+ leafMsgType = dhcp6Packet.getMsgType();
+ } else {
+ // Remove from route store if it is not connected to network directly
+ // pick out the first link-local ip address
+ IpAddress nextHopIp = getFirstIpByHost(directConnFlag, srcMac, vlanId);
+ if (nextHopIp == null) {
+ log.warn("Can't find link-local IP address of gateway mac {} vlanId {}", srcMac, vlanId);
+ dhcpRelayCountersStore.incrementCounter(gCount, DhcpRelayCounters.NO_LINKLOCAL_GW);
+ return;
+ }
- DHCP6 leafDhcp = getDhcp6Leaf(dhcp6Packet);
- ip = extractIpAddress(leafDhcp);
- if (ip == null) {
- log.debug("ip is null");
- } else {
- Route routeForIP = new Route(Route.Source.STATIC, ip.toIpPrefix(), nextHopIp);
+ DHCP6 leafDhcp = dhcp6HandlerUtil.getDhcp6Leaf(dhcp6Packet);
+ ipInfo = extractIpAddress(leafDhcp);
+ if (ipInfo == null) {
+ log.debug("ip is null");
+ } else {
+ if (isMsgRelease) {
+ Route routeForIP = new Route(Route.Source.STATIC, ipInfo.ip6Address.toIpPrefix(), nextHopIp);
log.debug("removing route of 128 address for indirectly connected.");
- log.debug("128 ip {}, nexthop {}", HexString.toHexString(ip.toOctets(), ":"),
+ log.debug("128 ip {}, nexthop {}",
+ HexString.toHexString(ipInfo.ip6Address.toOctets(), ":"),
HexString.toHexString(nextHopIp.toOctets(), ":"));
routeStore.removeRoute(routeForIP);
}
+ }
- IpPrefix ipPrefix = extractPrefix(leafDhcp);
- if (ipPrefix == null) {
- log.debug("ipPrefix is null ");
- } else {
- Route routeForPrefix = new Route(Route.Source.STATIC, ipPrefix, nextHopIp);
+ pdInfo = extractPrefix(leafDhcp);
+ if (pdInfo == null) {
+ log.debug("ipPrefix is null ");
+ } else {
+ if (isMsgRelease) {
+ Route routeForPrefix = new Route(Route.Source.STATIC, pdInfo.pdPrefix, nextHopIp);
log.debug("removing route of PD for indirectly connected.");
- log.debug("pd ip {}, nexthop {}", HexString.toHexString(ipPrefix.address().toOctets(), ":"),
+ log.debug("pd ip {}, nexthop {}",
+ HexString.toHexString(pdInfo.pdPrefix.address().toOctets(), ":"),
HexString.toHexString(nextHopIp.toOctets(), ":"));
routeStore.removeRoute(routeForPrefix);
if (this.dhcpFpmEnabled) {
- dhcpFpmPrefixStore.removeFpmRecord(ipPrefix);
+ dhcpFpmPrefixStore.removeFpmRecord(pdInfo.pdPrefix);
}
}
}
+ leafMsgType = leafDhcp.getMsgType();
+ }
+
+ if (isMsgRelease) {
+ log.debug("DHCP6 RELEASE msg.");
+ if (record != null) {
+ if (ipInfo != null) {
+ log.debug("DhcpRelay Record ip6Address is set to null.");
+ record.ip6Address(null);
+ }
+ if (pdInfo != null) {
+ log.debug("DhcpRelay Record pdPrefix is set to null.");
+ }
+
+ if (!record.ip6Address().isPresent() && !record.pdPrefix().isPresent()) {
+ log.warn("IP6 address and IP6 PD both are null. Remove record.");
+ // do not remove a record. Let timer task handler it.
+ //dhcpRelayStore.removeDhcpRecord(HostId.hostId(leafClientMac, vlanId));
+ }
+ }
+ }
+
+ if (record != null) {
+ record.getV6Counters().incrementCounter(dhcp6HandlerUtil.getMsgTypeStr(leafMsgType));
+ record.addLocation(new HostLocation(location, System.currentTimeMillis()));
+ record.ip6Status(DHCP6.MsgType.getType(leafMsgType));
+ record.setDirectlyConnected(directConnFlag);
+ if (!directConnFlag) {
+ // Update gateway mac address if the host is not directly connected
+ record.nextHop(srcMac);
+ }
+ record.updateLastSeen();
+ }
+ dhcpRelayStore.updateDhcpRecord(leafHostId, record);
+ // TODO Use AtomicInteger for the counters
+ try {
+ recordSemaphore.acquire();
+ try {
+ dhcpRelayCountersStore.incrementCounter(gCount, dhcp6HandlerUtil.getMsgTypeStr(leafMsgType));
+ } finally {
+ // calling release() after a successful acquire()
+ recordSemaphore.release();
+ }
+ } catch (InterruptedException e) {
+ e.printStackTrace();
}
}
/**
- * add host or route.
+ * add host or route and update dhcp relay record.
*
* @param directConnFlag flag to show that packet is from directly connected client
+ * @param location client side connect point
* @param dhcp6Relay the dhcp6 payload
- * @param embeddedDhcp6 client's ethernet packetthe dhcp6 payload within relay
- * @param clientMac client macAddress
+ * @param embeddedDhcp6 the dhcp6 payload within relay
+ * @param srcMac client gw/host macAddress
* @param clientInterface client interface
*/
- private void addHostOrRoute(boolean directConnFlag, DHCP6 dhcp6Relay,
- DHCP6 embeddedDhcp6,
- MacAddress clientMac,
- Interface clientInterface) {
+ private void addHostOrRoute(boolean directConnFlag, ConnectPoint location, DHCP6 dhcp6Relay,
+ DHCP6 embeddedDhcp6, MacAddress srcMac, Interface clientInterface) {
log.debug("addHostOrRoute entered.");
VlanId vlanId = clientInterface.vlan();
- // add host or route
- if (isDhcp6Reply(dhcp6Relay)) {
- IpAddress ip = null;
- if (directConnFlag) {
- // Add to host store if it connect to network directly
- ip = extractIpAddress(embeddedDhcp6);
- if (ip != null) {
- Set<IpAddress> ips = Sets.newHashSet(ip);
+ Boolean isMsgReply = dhcp6HandlerUtil.isDhcp6Reply(dhcp6Relay);
+ MacAddress leafClientMac;
+ Byte leafMsgType;
- // FIXME: we should use vlan id from original packet (solicit, request)
- HostId hostId = HostId.hostId(clientMac, vlanId);
+ Dhcp6ClientIdOption clientIdOption = extractClinedId(directConnFlag, embeddedDhcp6);
+ if (clientIdOption != null) {
+ log.debug("CLIENTID option found {}", clientIdOption);
+ if ((clientIdOption.getDuid().getDuidType() == Dhcp6Duid.DuidType.DUID_LLT) ||
+ (clientIdOption.getDuid().getDuidType() == Dhcp6Duid.DuidType.DUID_LL)) {
+ leafClientMac = MacAddress.valueOf(clientIdOption.getDuid().getLinkLayerAddress());
+ } else {
+ log.warn("Link-Layer Address not supported in CLIENTID option. No DhcpRelay Record created.");
+ dhcpRelayCountersStore.incrementCounter(gCount, DhcpRelayCounters.NO_LINKLOCAL_FAIL);
+ return;
+ }
+ } else {
+ log.warn("CLIENTID option NOT found. No DhcpRelay Record created.");
+ dhcpRelayCountersStore.incrementCounter(gCount, DhcpRelayCounters.NO_CLIENTID_FAIL);
+ return;
+ }
+ HostId leafHostId = HostId.hostId(leafClientMac, vlanId);
+ DhcpRecord record = dhcpRelayStore.getDhcpRecord(leafHostId).orElse(null);
+ if (record == null) {
+ record = new DhcpRecord(HostId.hostId(leafClientMac, vlanId));
+ } else {
+ record = record.clone();
+ }
+
+ IpAddressInfo ipInfo;
+ PdPrefixInfo pdInfo = null;
+ if (directConnFlag) {
+ // Add to host store if it connect to network directly
+ ipInfo = extractIpAddress(embeddedDhcp6);
+ if (ipInfo != null) {
+ if (isMsgReply) {
+ Set<IpAddress> ips = Sets.newHashSet(ipInfo.ip6Address);
+ HostId hostId = HostId.hostId(srcMac, vlanId);
Host host = hostService.getHost(hostId);
HostLocation hostLocation = new HostLocation(clientInterface.connectPoint(),
- System.currentTimeMillis());
+ System.currentTimeMillis());
Set<HostLocation> hostLocations = Sets.newHashSet(hostLocation);
-
if (host != null) {
// Dual homing support:
// if host exists, use old locations and new location
hostLocations.addAll(host.locations());
}
- HostDescription desc = new DefaultHostDescription(clientMac, vlanId,
- hostLocations, ips,
- false);
+ HostDescription desc = new DefaultHostDescription(srcMac, vlanId, hostLocations, ips,
+ false);
log.debug("adding Host for directly connected.");
log.debug("client mac {} client vlan {} hostlocation {}",
- HexString.toHexString(clientMac.toBytes(), ":"),
- vlanId, hostLocation.toString());
-
+ HexString.toHexString(srcMac.toBytes(), ":"), vlanId, hostLocation.toString());
// Replace the ip when dhcp server give the host new ip address
providerService.hostDetected(hostId, desc, false);
- } else {
- log.debug("ipAddress not found. Do not add Host for directly connected.");
}
} else {
- // Add to route store if it does not connect to network directly
- // pick out the first link-local ip address
- IpAddress nextHopIp = getFirstIpByHost(clientMac, vlanId);
- if (nextHopIp == null) {
- log.warn("Can't find link-local IP address of gateway mac {} vlanId {}",
- clientMac, vlanId);
- return;
- }
+ log.warn("ipAddress not found. Do not add Host {} for directly connected.",
+ HostId.hostId(srcMac, vlanId).toString());
+ }
+ leafMsgType = embeddedDhcp6.getMsgType();
+ } else {
+ // Add to route store if it does not connect to network directly
+ // pick out the first link-local ip address
+ IpAddress nextHopIp = getFirstIpByHost(directConnFlag, srcMac, vlanId);
+ if (nextHopIp == null) {
+ log.warn("Can't find link-local IP address of gateway mac {} vlanId {}", srcMac, vlanId);
+ dhcpRelayCountersStore.incrementCounter(gCount, DhcpRelayCounters.NO_LINKLOCAL_GW);
+ return;
+ }
- DHCP6 leafDhcp = getDhcp6Leaf(embeddedDhcp6);
- ip = extractIpAddress(leafDhcp);
- if (ip == null) {
- log.debug("ip is null");
- } else {
- Route routeForIP = new Route(Route.Source.STATIC, ip.toIpPrefix(), nextHopIp);
+ DHCP6 leafDhcp = dhcp6HandlerUtil.getDhcp6Leaf(embeddedDhcp6);
+ ipInfo = extractIpAddress(leafDhcp);
+ if (ipInfo == null) {
+ log.debug("ip is null");
+ } else {
+ if (isMsgReply) {
+ Route routeForIP = new Route(Route.Source.STATIC, ipInfo.ip6Address.toIpPrefix(), nextHopIp);
log.debug("adding Route of 128 address for indirectly connected.");
routeStore.updateRoute(routeForIP);
}
+ }
- IpPrefix ipPrefix = extractPrefix(leafDhcp);
- if (ipPrefix == null) {
- log.debug("ipPrefix is null ");
- } else {
- Route routeForPrefix = new Route(Route.Source.STATIC, ipPrefix, nextHopIp);
+ pdInfo = extractPrefix(leafDhcp);
+ if (pdInfo == null) {
+ log.debug("ipPrefix is null ");
+ } else {
+ if (isMsgReply) {
+ Route routeForPrefix = new Route(Route.Source.STATIC, pdInfo.pdPrefix, nextHopIp);
log.debug("adding Route of PD for indirectly connected.");
routeStore.updateRoute(routeForPrefix);
if (this.dhcpFpmEnabled) {
- FpmRecord record = new FpmRecord(ipPrefix, nextHopIp, FpmRecord.Type.DHCP_RELAY);
- dhcpFpmPrefixStore.addFpmRecord(ipPrefix, record);
+ FpmRecord fpmRecord = new FpmRecord(pdInfo.pdPrefix, nextHopIp, FpmRecord.Type.DHCP_RELAY);
+ dhcpFpmPrefixStore.addFpmRecord(pdInfo.pdPrefix, fpmRecord);
}
}
}
+ leafMsgType = leafDhcp.getMsgType();
+ }
+ if (leafMsgType == DHCP6.MsgType.RELEASE.value() ||
+ (leafMsgType == DHCP6.MsgType.REPLY.value()) && ipInfo == null) {
+ log.warn("DHCP6 RELEASE/REPLY(null ip) from Server. MsgType {}", leafMsgType);
+ //return;
+ }
+
+ record.addLocation(new HostLocation(location, System.currentTimeMillis()));
+
+ if (leafMsgType == DHCP6.MsgType.REPLY.value()) {
+ if (ipInfo != null) {
+ log.debug("IP6 address is being stored into dhcp-relay store.");
+ log.debug("IP6 address {}", HexString.toHexString(ipInfo.ip6Address.toOctets(), ":"));
+ record.ip6Address(ipInfo.ip6Address);
+ record.updateAddrPrefTime(ipInfo.prefTime);
+ record.updateLastIp6Update();
+ } else {
+ log.debug("IP6 address is not returned from server. Maybe only PD is returned.");
+ }
+ if (pdInfo != null) {
+ log.debug("IP6 PD address {}",
+ HexString.toHexString(pdInfo.pdPrefix.address().toOctets(), ":"));
+ record.pdPrefix(pdInfo.pdPrefix);
+ record.updatePdPrefTime(pdInfo.prefTime);
+ record.updateLastPdUpdate();
+ } else {
+ log.debug("IP6 PD address is not returned from server. Maybe only IPAddress is returned.");
+ }
+ }
+
+ record.getV6Counters().incrementCounter(dhcp6HandlerUtil.getMsgTypeStr(leafMsgType));
+ record.ip6Status(DHCP6.MsgType.getType(leafMsgType));
+ record.setDirectlyConnected(directConnFlag);
+ record.updateLastSeen();
+ dhcpRelayStore.updateDhcpRecord(leafHostId, record);
+ // TODO Use AtomicInteger for the counters
+ try {
+ recordSemaphore.acquire();
+ try {
+ dhcpRelayCountersStore.incrementCounter(gCount, dhcp6HandlerUtil.getMsgTypeStr(leafMsgType));
+ } finally {
+ // calling release() after a successful acquire()
+ recordSemaphore.release();
+ }
+ } catch (InterruptedException e) {
+ e.printStackTrace();
}
}
/**
- * Build the DHCP6 solicit/request packet with gatewayip.
- * TODO: method too long, need to be refactored.
+ * build the DHCP6 solicit/request packet with gatewayip.
*
* @param context packet context
* @param clientPacket client ethernet packet
* @param clientInterfaces set of client side interfaces
*/
- private InternalPacket processDhcp6PacketFromClient(PacketContext context,
- Ethernet clientPacket, Set<Interface> clientInterfaces) {
+ private List<InternalPacket> processDhcp6PacketFromClient(PacketContext context,
+ Ethernet clientPacket,
+ Set<Interface> clientInterfaces) {
ConnectPoint receivedFrom = context.inPacket().receivedFrom();
DeviceId receivedFromDevice = receivedFrom.deviceId();
- DhcpServerInfo serverInfo;
- Ip6Address dhcpServerIp = null;
- ConnectPoint dhcpServerConnectPoint = null;
- MacAddress dhcpConnectMac = null;
- VlanId dhcpConnectVlan = null;
- Ip6Address dhcpGatewayIp = null;
- Ip6Address indirectDhcpServerIp = null;
- ConnectPoint indirectDhcpServerConnectPoint = null;
- MacAddress indirectDhcpConnectMac = null;
- VlanId indirectDhcpConnectVlan = null;
- Ip6Address indirectDhcpGatewayIp = null;
- Ip6Address indirectRelayAgentIpFromCfg = null;
- if (!defaultServerInfoList.isEmpty()) {
- serverInfo = defaultServerInfoList.get(0);
- dhcpConnectMac = serverInfo.getDhcpConnectMac().orElse(null);
- dhcpGatewayIp = serverInfo.getDhcpGatewayIp6().orElse(null);
- dhcpServerIp = serverInfo.getDhcpServerIp6().orElse(null);
- dhcpServerConnectPoint = serverInfo.getDhcpServerConnectPoint().orElse(null);
- dhcpConnectVlan = serverInfo.getDhcpConnectVlan().orElse(null);
- }
- if (!indirectServerInfoList.isEmpty()) {
- serverInfo = indirectServerInfoList.get(0);
- indirectDhcpConnectMac = serverInfo.getDhcpConnectMac().orElse(null);
- indirectDhcpGatewayIp = serverInfo.getDhcpGatewayIp6().orElse(null);
- indirectDhcpServerIp = serverInfo.getDhcpServerIp6().orElse(null);
- indirectDhcpServerConnectPoint = serverInfo.getDhcpServerConnectPoint().orElse(null);
- indirectDhcpConnectVlan = serverInfo.getDhcpConnectVlan().orElse(null);
- indirectRelayAgentIpFromCfg = serverInfo.getRelayAgentIp6(receivedFromDevice).orElse(null);
- }
- Ip6Address relayAgentIp = getRelayAgentIPv6Address(clientInterfaces);
+ Ip6Address relayAgentIp = dhcp6HandlerUtil.getRelayAgentIPv6Address(clientInterfaces);
MacAddress relayAgentMac = clientInterfaces.iterator().next().mac();
if (relayAgentIp == null || relayAgentMac == null) {
log.warn("Missing DHCP relay agent interface Ipv6 addr config for "
- + "packet from client on port: {}. Aborting packet processing",
- clientInterfaces.iterator().next().connectPoint());
- return null;
+ + "packet from client on port: {}. Aborting packet processing",
+ clientInterfaces.iterator().next().connectPoint());
+ dhcpRelayCountersStore.incrementCounter(gCount, DhcpRelayCounters.NO_CLIENT_INTF_MAC);
+ return Lists.newArrayList();
}
- // get dhcp6 header.
+
IPv6 clientIpv6 = (IPv6) clientPacket.getPayload();
UDP clientUdp = (UDP) clientIpv6.getPayload();
DHCP6 clientDhcp6 = (DHCP6) clientUdp.getPayload();
- boolean directConnFlag = directlyConnected(clientDhcp6);
- Interface serverInterface;
- if (directConnFlag) {
- serverInterface = getServerInterface();
- } else {
- serverInterface = getIndirectServerInterface();
- if (serverInterface == null) {
- // Indirect server interface not found, use default server interface
- serverInterface = getServerInterface();
- }
- }
- if (serverInterface == null) {
- log.warn("Can't get {} server interface, ignore", directConnFlag ? "direct" : "indirect");
- return null;
- }
- Ip6Address ipFacingServer = getFirstIpFromInterface(serverInterface);
- MacAddress macFacingServer = serverInterface.mac();
- if (ipFacingServer == null || macFacingServer == null) {
- log.warn("No IP v6 address for server Interface {}", serverInterface);
- return null;
- }
- Ethernet etherReply = clientPacket.duplicate();
- etherReply.setSourceMACAddress(macFacingServer);
- if ((directConnFlag && dhcpConnectMac == null) ||
- !directConnFlag && indirectDhcpConnectMac == null && dhcpConnectMac == null) {
- log.trace("Packet received from {} connected client.", directConnFlag ? "directly" : "indirectly");
- log.debug("DHCP6 {} not yet resolved .. Aborting DHCP packet processing from client on port: {}",
- (dhcpGatewayIp == null) ? "server IP " + dhcpServerIp
- : "gateway IP " + dhcpGatewayIp,
- clientInterfaces.iterator().next().connectPoint());
- return null;
- }
- if (dhcpServerConnectPoint == null) {
- log.warn("DHCP6 server connection point direct {} directConn {} indirectConn {} is not set up yet",
- directConnFlag, dhcpServerConnectPoint, indirectDhcpServerConnectPoint);
- return null;
- }
- etherReply.setDestinationMACAddress(dhcpConnectMac);
- etherReply.setVlanID(dhcpConnectVlan.toShort());
- IPv6 ipv6Packet = (IPv6) etherReply.getPayload();
- byte[] peerAddress = clientIpv6.getSourceAddress();
- ipv6Packet.setSourceAddress(ipFacingServer.toOctets());
- ipv6Packet.setDestinationAddress(dhcpServerIp.toOctets());
- UDP udpPacket = (UDP) ipv6Packet.getPayload();
- udpPacket.setSourcePort(UDP.DHCP_V6_SERVER_PORT);
- DHCP6 dhcp6Packet = (DHCP6) udpPacket.getPayload();
- byte[] dhcp6PacketByte = dhcp6Packet.serialize();
+ boolean directConnFlag = dhcp6HandlerUtil.directlyConnected(clientDhcp6);
ConnectPoint clientConnectionPoint = context.inPacket().receivedFrom();
VlanId vlanIdInUse = VlanId.vlanId(clientPacket.getVlanID());
Interface clientInterface = interfaceService.getInterfacesByPort(clientConnectionPoint)
- .stream().filter(iface -> interfaceContainsVlan(iface, vlanIdInUse))
- .findFirst().orElse(null);
+ .stream().filter(iface -> dhcp6HandlerUtil.interfaceContainsVlan(iface, vlanIdInUse))
+ .findFirst()
+ .orElse(null);
- removeHostOrRoute(directConnFlag, dhcp6Packet, clientPacket, clientIpv6, clientInterface);
+ List<InternalPacket> internalPackets = new ArrayList<>();
+ List<DhcpServerInfo> serverInfoList = findValidServerInfo(directConnFlag);
+ List<DhcpServerInfo> copyServerInfoList = new ArrayList<DhcpServerInfo>(serverInfoList);
- DHCP6 dhcp6Relay = new DHCP6();
- dhcp6Relay.setMsgType(DHCP6.MsgType.RELAY_FORW.value());
- if (directConnFlag) {
- dhcp6Relay.setLinkAddress(relayAgentIp.toOctets());
- log.debug("direct connection: relayAgentIp obtained dynamically {}",
- HexString.toHexString(relayAgentIp.toOctets(), ":"));
+ for (DhcpServerInfo serverInfo : copyServerInfoList) {
+ if (!dhcp6HandlerUtil.checkDhcpServerConnPt(directConnFlag, serverInfo)) {
+ log.warn("Can't get server connect point, ignore");
+ continue;
+ }
+ DhcpServerInfo newServerInfo = getHostInfoForServerInfo(serverInfo, serverInfoList);
+ if (newServerInfo == null) {
+ log.warn("Can't get server interface with host info resolved, ignore");
+ continue;
+ }
- } else {
- if (indirectDhcpServerIp == null) {
- log.debug("indirect DhcpServerIp not available, use default DhcpServerIp {}",
- HexString.toHexString(dhcpServerIp.toOctets()));
- } else {
- // Indirect case, replace destination to indirect dhcp server if exist
- // Check if mac is obtained for valid server ip
- if (indirectDhcpConnectMac == null) {
- log.warn("DHCP6 {} not yet resolved .. Aborting DHCP "
- + "packet processing from client on port: {}",
- (indirectDhcpGatewayIp == null) ? "server IP " + indirectDhcpServerIp
- : "gateway IP " + indirectDhcpGatewayIp,
- clientInterfaces.iterator().next().connectPoint());
- return null;
- }
- etherReply.setDestinationMACAddress(indirectDhcpConnectMac);
- etherReply.setVlanID(indirectDhcpConnectVlan.toShort());
- ipv6Packet.setDestinationAddress(indirectDhcpServerIp.toOctets());
- }
- if (indirectRelayAgentIpFromCfg == null) {
- dhcp6Relay.setLinkAddress(relayAgentIp.toOctets());
- log.trace("indirect connection: relayAgentIp NOT availale from config file! Use dynamic. {}",
- HexString.toHexString(relayAgentIp.toOctets(), ":"));
- } else {
- dhcp6Relay.setLinkAddress(indirectRelayAgentIpFromCfg.toOctets());
- log.trace("indirect connection: relayAgentIp from config file is available! {}",
- HexString.toHexString(indirectRelayAgentIpFromCfg.toOctets(), ":"));
- }
- }
- // peer address: address of the client or relay agent from which
- // the message to be relayed was received.
- dhcp6Relay.setPeerAddress(peerAddress);
- List<Dhcp6Option> options = new ArrayList<>();
- // directly connected case, hop count is zero; otherwise, hop count + 1
- if (directConnFlag) {
- dhcp6Relay.setHopCount((byte) 0);
- } else {
- dhcp6Relay.setHopCount((byte) (dhcp6Packet.getHopCount() + 1));
- }
- // create relay message option
- Dhcp6Option relayMessage = new Dhcp6Option();
- relayMessage.setCode(DHCP6.OptionCode.RELAY_MSG.value());
- relayMessage.setLength((short) dhcp6PacketByte.length);
- relayMessage.setData(dhcp6PacketByte);
- options.add(relayMessage);
- // create interfaceId option
- String inPortString = "-" + context.inPacket().receivedFrom().toString() + ":";
- Dhcp6Option interfaceId = new Dhcp6Option();
- interfaceId.setCode(DHCP6.OptionCode.INTERFACE_ID.value());
- byte[] clientSoureMacBytes = clientPacket.getSourceMACAddress();
- byte[] inPortStringBytes = inPortString.getBytes();
- byte[] vlanIdBytes = new byte[2];
- vlanIdBytes[0] = (byte) (clientPacket.getVlanID() & 0xff);
- vlanIdBytes[1] = (byte) ((clientPacket.getVlanID() >> 8) & 0xff);
- byte[] interfaceIdBytes = new byte[clientSoureMacBytes.length +
- inPortStringBytes.length + vlanIdBytes.length];
- log.trace("Length: interfaceIdBytes {} clientSoureMacBytes {} inPortStringBytes {} vlan {}",
- interfaceIdBytes.length, clientSoureMacBytes.length, inPortStringBytes.length,
- vlanIdBytes.length);
- System.arraycopy(clientSoureMacBytes, 0, interfaceIdBytes, 0, clientSoureMacBytes.length);
- System.arraycopy(inPortStringBytes, 0, interfaceIdBytes, clientSoureMacBytes.length, inPortStringBytes.length);
- System.arraycopy(vlanIdBytes, 0, interfaceIdBytes, clientSoureMacBytes.length + inPortStringBytes.length,
- vlanIdBytes.length);
- interfaceId.setData(interfaceIdBytes);
- interfaceId.setLength((short) interfaceIdBytes.length);
- options.add(interfaceId);
- log.debug("interfaceId write srcMac {} portString {}",
- HexString.toHexString(clientSoureMacBytes, ":"), inPortString);
- dhcp6Relay.setOptions(options);
- udpPacket.setPayload(dhcp6Relay);
- udpPacket.resetChecksum();
- ipv6Packet.setPayload(udpPacket);
- ipv6Packet.setHopLimit((byte) 64);
- etherReply.setPayload(ipv6Packet);
- if (directConnFlag || indirectDhcpServerIp == null) {
- return new InternalPacket(etherReply, dhcpServerConnectPoint);
- } else {
- return new InternalPacket(etherReply, indirectDhcpServerConnectPoint);
- }
- }
+ Interface serverInterface = getServerInterface(newServerInfo);
+ if (serverInterface == null) {
+ log.warn("Can't get server interface, ignore");
+ continue;
+ }
+
+ Ethernet etherReply = dhcp6HandlerUtil.buildDhcp6PacketFromClient(context, clientPacket,
+ clientInterfaces, newServerInfo, serverInterface);
+ removeHostOrRoute(directConnFlag, clientConnectionPoint, clientDhcp6, clientPacket,
+ clientIpv6, clientInterface);
+
+ InternalPacket internalPacket = new Dhcp6HandlerUtil().new InternalPacket(etherReply,
+ serverInfo.getDhcpServerConnectPoint().get());
+ internalPackets.add(internalPacket);
+ }
+ log.debug("num of client packets to send is{}", internalPackets.size());
+
+ return internalPackets;
+ }
/**
- *
* process the DHCP6 relay-reply packet from dhcp server.
*
* @param context packet context
* @param receivedPacket server ethernet packet
* @param recevingInterfaces set of server side interfaces
+ * @return internalPacket toward client
*/
private InternalPacket processDhcp6PacketFromServer(PacketContext context,
Ethernet receivedPacket, Set<Interface> recevingInterfaces) {
-
- ConnectPoint receivedFrom = context.inPacket().receivedFrom();
- DeviceId receivedFromDevice = receivedFrom.deviceId();
-
- // TODO: refactor
- DhcpServerInfo serverInfo;
- Ip6Address dhcpServerIp = null;
- ConnectPoint dhcpServerConnectPoint = null;
- MacAddress dhcpConnectMac = null;
- VlanId dhcpConnectVlan = null;
- Ip6Address dhcpGatewayIp = null;
-
- Ip6Address indirectDhcpServerIp = null;
- ConnectPoint indirectDhcpServerConnectPoint = null;
- MacAddress indirectDhcpConnectMac = null;
- VlanId indirectDhcpConnectVlan = null;
- Ip6Address indirectDhcpGatewayIp = null;
- Ip6Address indirectRelayAgentIpFromCfg = null;
-
- if (!defaultServerInfoList.isEmpty()) {
- serverInfo = defaultServerInfoList.get(0);
- dhcpConnectMac = serverInfo.getDhcpConnectMac().orElse(null);
- dhcpGatewayIp = serverInfo.getDhcpGatewayIp6().orElse(null);
- dhcpServerIp = serverInfo.getDhcpServerIp6().orElse(null);
- dhcpServerConnectPoint = serverInfo.getDhcpServerConnectPoint().orElse(null);
- dhcpConnectVlan = serverInfo.getDhcpConnectVlan().orElse(null);
- }
-
- if (!indirectServerInfoList.isEmpty()) {
- serverInfo = indirectServerInfoList.get(0);
- indirectDhcpConnectMac = serverInfo.getDhcpConnectMac().orElse(null);
- indirectDhcpGatewayIp = serverInfo.getDhcpGatewayIp6().orElse(null);
- indirectDhcpServerIp = serverInfo.getDhcpServerIp6().orElse(null);
- indirectDhcpServerConnectPoint = serverInfo.getDhcpServerConnectPoint().orElse(null);
- indirectDhcpConnectVlan = serverInfo.getDhcpConnectVlan().orElse(null);
- indirectRelayAgentIpFromCfg = serverInfo.getRelayAgentIp6(receivedFromDevice).orElse(null);
- }
-
// get dhcp6 header.
Ethernet etherReply = receivedPacket.duplicate();
IPv6 ipv6Packet = (IPv6) etherReply.getPayload();
UDP udpPacket = (UDP) ipv6Packet.getPayload();
DHCP6 dhcp6Relay = (DHCP6) udpPacket.getPayload();
+ Boolean directConnFlag = dhcp6HandlerUtil.directlyConnected(dhcp6Relay);
- Boolean directConnFlag = directlyConnected(dhcp6Relay);
+ DHCP6 embeddedDhcp6 = dhcp6Relay.getOptions().stream()
+ .filter(opt -> opt instanceof Dhcp6RelayOption)
+ .map(BasePacket::getPayload)
+ .map(pld -> (DHCP6) pld)
+ .findFirst()
+ .orElse(null);
ConnectPoint inPort = context.inPacket().receivedFrom();
- if ((directConnFlag || (!directConnFlag && indirectDhcpServerIp == null))
- && !inPort.equals(dhcpServerConnectPoint)) {
- log.warn("Receiving port {} is not the same as server connect point {} for direct or indirect-null",
- inPort, dhcpServerConnectPoint);
- return null;
- }
+ DhcpServerInfo foundServerInfo = findServerInfoFromServer(directConnFlag, inPort);
- if (!directConnFlag && indirectDhcpServerIp != null &&
- !inPort.equals(indirectDhcpServerConnectPoint)) {
- log.warn("Receiving port {} is not the same as server connect point {} for indirect",
- inPort, indirectDhcpServerConnectPoint);
+ if (foundServerInfo == null) {
+ log.warn("Cannot find server info");
+ dhcpRelayCountersStore.incrementCounter(gCount, DhcpRelayCounters.NO_SERVER_INFO);
return null;
+ } else {
+ if (dhcp6HandlerUtil.isServerIpEmpty(foundServerInfo)) {
+ log.warn("Cannot find server info's ipaddress");
+ dhcpRelayCountersStore.incrementCounter(gCount, DhcpRelayCounters.NO_SERVER_IP6ADDR);
+ return null;
+ }
}
-
Dhcp6InterfaceIdOption interfaceIdOption = dhcp6Relay.getOptions().stream()
.filter(opt -> opt instanceof Dhcp6InterfaceIdOption)
.map(opt -> (Dhcp6InterfaceIdOption) opt)
.findFirst()
.orElse(null);
-
if (interfaceIdOption == null) {
log.warn("Interface Id option is not present, abort packet...");
+ dhcpRelayCountersStore.incrementCounter(gCount, DhcpRelayCounters.OPTION_MISSING_FAIL);
return null;
}
MacAddress peerMac = interfaceIdOption.getMacAddress();
String clientConnectionPointStr = new String(interfaceIdOption.getInPort());
-
ConnectPoint clientConnectionPoint = ConnectPoint.deviceConnectPoint(clientConnectionPointStr);
VlanId vlanIdInUse = VlanId.vlanId(interfaceIdOption.getVlanId());
Interface clientInterface = interfaceService.getInterfacesByPort(clientConnectionPoint)
- .stream()
- .filter(iface -> interfaceContainsVlan(iface, vlanIdInUse))
- .findFirst()
- .orElse(null);
+ .stream().filter(iface -> dhcp6HandlerUtil.interfaceContainsVlan(iface, vlanIdInUse))
+ .findFirst().orElse(null);
if (clientInterface == null) {
log.warn("Cannot get client interface for from packet, abort... vlan {}", vlanIdInUse.toString());
+ dhcpRelayCountersStore.incrementCounter(gCount, DhcpRelayCounters.NO_MATCHING_INTF);
return null;
}
MacAddress relayAgentMac = clientInterface.mac();
if (relayAgentMac == null) {
log.warn("Can not get client interface mac, abort packet..");
+ dhcpRelayCountersStore.incrementCounter(gCount, DhcpRelayCounters.NO_CLIENT_INTF_MAC);
return null;
}
etherReply.setSourceMACAddress(relayAgentMac);
@@ -1084,13 +963,12 @@
clientMac = clients.iterator().next().mac();
if (clientMac == null) {
log.warn("No client mac address found, abort packet...");
+ dhcpRelayCountersStore.incrementCounter(gCount, DhcpRelayCounters.NO_CLIENT_INTF_MAC);
return null;
}
log.trace("Client mac address found from getHostByIp");
-
}
etherReply.setDestinationMACAddress(clientMac);
-
// ip header
ipv6Packet.setSourceAddress(dhcp6Relay.getLinkAddress());
ipv6Packet.setDestinationAddress(dhcp6Relay.getPeerAddress());
@@ -1101,39 +979,16 @@
} else {
udpPacket.setDestinationPort(UDP.DHCP_V6_SERVER_PORT);
}
-
- DHCP6 embeddedDhcp6 = dhcp6Relay.getOptions().stream()
- .filter(opt -> opt instanceof Dhcp6RelayOption)
- .map(BasePacket::getPayload)
- .map(pld -> (DHCP6) pld)
- .findFirst()
- .orElse(null);
-
-
// add host or route
- addHostOrRoute(directConnFlag, dhcp6Relay, embeddedDhcp6, clientMac, clientInterface);
+ addHostOrRoute(directConnFlag, clientConnectionPoint, dhcp6Relay, embeddedDhcp6, clientMac, clientInterface);
udpPacket.setPayload(embeddedDhcp6);
udpPacket.resetChecksum();
ipv6Packet.setPayload(udpPacket);
etherReply.setPayload(ipv6Packet);
-
- return new InternalPacket(etherReply, clientConnectionPoint);
+ return new Dhcp6HandlerUtil().new InternalPacket(etherReply, clientConnectionPoint);
}
- // Returns the first v6 interface ip out of a set of interfaces or null.
- // Checks all interfaces, and ignores v6 interface ips
- private Ip6Address getRelayAgentIPv6Address(Set<Interface> intfs) {
- for (Interface intf : intfs) {
- for (InterfaceIpAddress ip : intf.ipAddressesList()) {
- Ip6Address relayAgentIp = ip.ipAddress().getIp6Address();
- if (relayAgentIp != null) {
- return relayAgentIp;
- }
- }
- }
- return null;
- }
@Override
public void setDhcpFpmEnabled(Boolean enabled) {
@@ -1142,33 +997,37 @@
@Override
public void setDefaultDhcpServerConfigs(Collection<DhcpServerConfig> configs) {
+ log.debug("setDefaultDhcpServerConfigs is called.");
setDhcpServerConfigs(configs, defaultServerInfoList);
}
@Override
public void setIndirectDhcpServerConfigs(Collection<DhcpServerConfig> configs) {
+ log.debug("setIndirectDhcpServerConfigs is called.");
setDhcpServerConfigs(configs, indirectServerInfoList);
}
public void setDhcpServerConfigs(Collection<DhcpServerConfig> configs, List<DhcpServerInfo> serverInfoList) {
+ log.debug("config size {}.", configs.size());
+
if (configs.size() == 0) {
// no config to update
return;
}
-
// TODO: currently we pick up first DHCP server config.
// Will use other server configs in the future for HA.
- DhcpServerConfig serverConfig = configs.iterator().next();
-
- if (!serverConfig.getDhcpServerIp6().isPresent()) {
- // not a DHCPv6 config
- return;
+ Boolean isConfigValid = false;
+ for (DhcpServerConfig serverConfig : configs) {
+ if (serverConfig.getDhcpServerIp6().isPresent()) {
+ isConfigValid = true;
+ break;
+ }
}
-
- if (!serverInfoList.isEmpty()) {
- // remove old server info
- DhcpServerInfo oldServerInfo = serverInfoList.remove(0);
-
+ if (!isConfigValid) {
+ log.warn("No IP V6 server address found.");
+ return; // No IP V6 address found
+ }
+ for (DhcpServerInfo oldServerInfo : serverInfoList) {
// stop monitoring gateway or server
oldServerInfo.getDhcpGatewayIp6().ifPresent(gatewayIp -> {
hostService.stopMonitoringIp(gatewayIp);
@@ -1178,43 +1037,50 @@
cancelDhcpPacket(serverIp);
});
}
+ serverInfoList.clear();
+ for (DhcpServerConfig serverConfig : configs) {
+ // Create new server info according to the config
+ DhcpServerInfo newServerInfo = new DhcpServerInfo(serverConfig,
+ DhcpServerInfo.Version.DHCP_V6);
+ checkState(newServerInfo.getDhcpServerConnectPoint().isPresent(),
+ "Connect point not exists");
+ checkState(newServerInfo.getDhcpServerIp6().isPresent(),
+ "IP of DHCP server not exists");
- // Create new server info according to the config
- DhcpServerInfo newServerInfo = new DhcpServerInfo(serverConfig,
- DhcpServerInfo.Version.DHCP_V6);
- checkState(newServerInfo.getDhcpServerConnectPoint().isPresent(),
- "Connect point not exists");
- checkState(newServerInfo.getDhcpServerIp6().isPresent(),
- "IP of DHCP server not exists");
+ log.debug("DHCP server connect point: {}", newServerInfo.getDhcpServerConnectPoint().orElse(null));
+ log.debug("DHCP server IP: {}", newServerInfo.getDhcpServerIp6().orElse(null));
- log.debug("DHCP server connect point: {}", newServerInfo.getDhcpServerConnectPoint().orElse(null));
- log.debug("DHCP server IP: {}", newServerInfo.getDhcpServerIp6().orElse(null));
+ Ip6Address serverIp = newServerInfo.getDhcpServerIp6().get();
+ Ip6Address ipToProbe;
+ if (newServerInfo.getDhcpGatewayIp6().isPresent()) {
+ ipToProbe = newServerInfo.getDhcpGatewayIp6().get();
+ } else {
+ ipToProbe = newServerInfo.getDhcpServerIp6().orElse(null);
+ }
+ String hostToProbe = newServerInfo.getDhcpGatewayIp6()
+ .map(ip -> "gateway").orElse("server");
- Ip6Address serverIp = newServerInfo.getDhcpServerIp6().get();
- Ip6Address ipToProbe;
- if (newServerInfo.getDhcpGatewayIp6().isPresent()) {
- ipToProbe = newServerInfo.getDhcpGatewayIp6().get();
- } else {
- ipToProbe = newServerInfo.getDhcpServerIp6().orElse(null);
+ log.warn("Probing to resolve {} IP {}", hostToProbe, ipToProbe);
+ hostService.startMonitoringIp(ipToProbe);
+
+ Set<Host> hosts = hostService.getHostsByIp(ipToProbe);
+ if (!hosts.isEmpty()) {
+ Host host = hosts.iterator().next();
+ newServerInfo.setDhcpConnectVlan(host.vlan());
+ newServerInfo.setDhcpConnectMac(host.mac());
+ log.warn("Host found host {}", host);
+
+ } else {
+ log.warn("No host found host ip {}", ipToProbe);
+ }
+ // Add new server info
+ synchronized (this) {
+ serverInfoList.add(newServerInfo);
+ }
+ if (!hosts.isEmpty()) {
+ requestDhcpPacket(serverIp);
+ }
}
- String hostToProbe = newServerInfo.getDhcpGatewayIp6()
- .map(ip -> "gateway").orElse("server");
-
- log.debug("Probing to resolve {} IP {}", hostToProbe, ipToProbe);
- hostService.startMonitoringIp(ipToProbe);
-
- Set<Host> hosts = hostService.getHostsByIp(ipToProbe);
- if (!hosts.isEmpty()) {
- Host host = hosts.iterator().next();
- newServerInfo.setDhcpConnectVlan(host.vlan());
- newServerInfo.setDhcpConnectMac(host.mac());
- }
- // Add new server info
- synchronized (this) {
- serverInfoList.clear();
- serverInfoList.add(0, newServerInfo);
- }
- requestDhcpPacket(serverIp);
}
class InternalHostListener implements HostListener {
@@ -1256,7 +1122,6 @@
if (targetIp == null) {
targetIp = serverIp;
}
-
if (targetIp != null) {
if (host.ipAddresses().contains(targetIp)) {
serverInfo.setDhcpConnectMac(host.mac());
@@ -1290,7 +1155,6 @@
if (targetIp == null) {
targetIp = serverIp;
}
-
if (targetIp != null) {
if (host.ipAddresses().contains(targetIp)) {
serverInfo.setDhcpConnectVlan(null);
@@ -1317,81 +1181,81 @@
.findFirst()
.orElse(null);
}
+ /**
+ * Checks if serverInfo's host info (mac and vlan) is filled in; if not, fills in.
+ *
+ * @param serverInfo server information
+ * @return newServerInfo if host info can be either found or filled in.
+ */
+ private DhcpServerInfo getHostInfoForServerInfo(DhcpServerInfo serverInfo, List<DhcpServerInfo> sererInfoList) {
+ DhcpServerInfo newServerInfo = null;
+ MacAddress dhcpServerConnectMac = serverInfo.getDhcpConnectMac().orElse(null);
+ VlanId dhcpConnectVlan = serverInfo.getDhcpConnectVlan().orElse(null);
+ ConnectPoint dhcpServerConnectPoint = serverInfo.getDhcpServerConnectPoint().orElse(null);
+
+ if (dhcpServerConnectMac != null && dhcpConnectVlan != null) {
+ newServerInfo = serverInfo;
+ log.info("DHCP server {} host info found. ConnectPt{} Mac {} vlan {}", serverInfo.getDhcpServerIp6(),
+ dhcpServerConnectPoint, dhcpServerConnectMac, dhcpConnectVlan);
+ } else {
+ log.warn("DHCP server {} not resolve yet connectPt {} mac {} vlan {}", serverInfo.getDhcpServerIp6(),
+ dhcpServerConnectPoint, dhcpServerConnectMac, dhcpConnectVlan);
+
+ Ip6Address ipToProbe;
+ if (serverInfo.getDhcpGatewayIp6().isPresent()) {
+ ipToProbe = serverInfo.getDhcpGatewayIp6().get();
+ } else {
+ ipToProbe = serverInfo.getDhcpServerIp6().orElse(null);
+ }
+ String hostToProbe = serverInfo.getDhcpGatewayIp6()
+ .map(ip -> "gateway").orElse("server");
+
+ log.info("Dynamically probing to resolve {} IP {}", hostToProbe, ipToProbe);
+ hostService.startMonitoringIp(ipToProbe);
+
+ Set<Host> hosts = hostService.getHostsByIp(ipToProbe);
+ if (!hosts.isEmpty()) {
+ int serverInfoIndex = sererInfoList.indexOf(serverInfo);
+ Host host = hosts.iterator().next();
+ serverInfo.setDhcpConnectVlan(host.vlan());
+ serverInfo.setDhcpConnectMac(host.mac());
+ // replace the serverInfo in the list
+ sererInfoList.set(serverInfoIndex, serverInfo);
+ newServerInfo = serverInfo;
+ log.warn("Dynamically host found host {}", host);
+ } else {
+ log.warn("No host found host ip {} dynamically", ipToProbe);
+ }
+ }
+ return newServerInfo;
+ }
/**
* Gets Interface facing to the server for default host.
*
+ * @param serverInfo server information
* @return the Interface facing to the server; null if not found
*/
- private Interface getServerInterface() {
- DhcpServerInfo serverInfo;
- ConnectPoint dhcpServerConnectPoint;
- VlanId dhcpConnectVlan;
+ private Interface getServerInterface(DhcpServerInfo serverInfo) {
+ Interface serverInterface = null;
- if (!defaultServerInfoList.isEmpty()) {
- serverInfo = defaultServerInfoList.get(0);
- dhcpServerConnectPoint = serverInfo.getDhcpServerConnectPoint().orElse(null);
- dhcpConnectVlan = serverInfo.getDhcpConnectVlan().orElse(null);
+ ConnectPoint dhcpServerConnectPoint = serverInfo.getDhcpServerConnectPoint().orElse(null);
+ VlanId dhcpConnectVlan = serverInfo.getDhcpConnectVlan().orElse(null);
+
+ if (dhcpServerConnectPoint != null && dhcpConnectVlan != null) {
+ serverInterface = interfaceService.getInterfacesByPort(dhcpServerConnectPoint)
+ .stream()
+ .filter(iface -> dhcp6HandlerUtil.interfaceContainsVlan(iface, dhcpConnectVlan))
+ .findFirst()
+ .orElse(null);
} else {
- return null;
+ log.warn("DHCP server {} not resolve yet connectPoint {} vlan {}", serverInfo.getDhcpServerIp6(),
+ dhcpServerConnectPoint, dhcpConnectVlan);
}
- if (dhcpServerConnectPoint == null || dhcpConnectVlan == null) {
- log.info("Default DHCP server {} not resolve yet", serverInfo.getDhcpGatewayIp6());
- return null;
- }
- return interfaceService.getInterfacesByPort(dhcpServerConnectPoint)
- .stream()
- .filter(iface -> interfaceContainsVlan(iface, dhcpConnectVlan))
- .findFirst()
- .orElse(null);
+
+ return serverInterface;
}
- /**
- * Gets Interface facing to the server for indirect hosts.
- * Use default server Interface if indirect server not configured.
- *
- * @return the Interface facing to the server; null if not found
- */
- private Interface getIndirectServerInterface() {
- DhcpServerInfo serverInfo;
-
- ConnectPoint indirectDhcpServerConnectPoint;
- VlanId indirectDhcpConnectVlan;
-
- if (!indirectServerInfoList.isEmpty()) {
- serverInfo = indirectServerInfoList.get(0);
- indirectDhcpServerConnectPoint = serverInfo.getDhcpServerConnectPoint().orElse(null);
- indirectDhcpConnectVlan = serverInfo.getDhcpConnectVlan().orElse(null);
- } else {
- return getServerInterface();
- }
- if (indirectDhcpServerConnectPoint == null || indirectDhcpConnectVlan == null) {
- log.info("Indirect DHCP server {} not resolve yet", serverInfo.getDhcpGatewayIp6());
- return null;
- }
- return interfaceService.getInterfacesByPort(indirectDhcpServerConnectPoint)
- .stream()
- .filter(iface -> interfaceContainsVlan(iface, indirectDhcpConnectVlan))
- .findFirst()
- .orElse(null);
- }
-
- /**
- * Determind if an Interface contains a vlan id.
- *
- * @param iface the Interface
- * @param vlanId the vlan id
- * @return true if the Interface contains the vlan id
- */
- private boolean interfaceContainsVlan(Interface iface, VlanId vlanId) {
- if (vlanId.equals(VlanId.NONE)) {
- // untagged packet, check if vlan untagged or vlan native is not NONE
- return !iface.vlanUntagged().equals(VlanId.NONE) ||
- !iface.vlanNative().equals(VlanId.NONE);
- }
- // tagged packet, check if the interface contains the vlan
- return iface.vlanTagged().contains(vlanId);
- }
private void requestDhcpPacket(Ip6Address serverIp) {
requestServerDhcpPacket(serverIp);
@@ -1555,7 +1419,6 @@
flowObjectiveService.apply(deviceId, fwd);
});
}
-
/**
* Find first ipaddress for a given Host info i.e. mac and vlan.
*
@@ -1563,7 +1426,7 @@
* @param vlanId packet's vlan
* @return next-hop link-local ipaddress for a given host
*/
- private IpAddress getFirstIpByHost(MacAddress clientMac, VlanId vlanId) {
+ private IpAddress getFirstIpByHost(Boolean directConnFlag, MacAddress clientMac, VlanId vlanId) {
IpAddress nextHopIp;
// pick out the first link-local ip address
HostId gwHostId = HostId.hostId(clientMac, vlanId);
@@ -1572,13 +1435,157 @@
log.warn("Can't find gateway host for hostId {}", gwHostId);
return null;
}
- nextHopIp = gwHost.ipAddresses()
- .stream()
- .filter(IpAddress::isIp6)
- .filter(IpAddress::isLinkLocal)
- .map(IpAddress::getIp6Address)
- .findFirst()
- .orElse(null);
+ if (directConnFlag) {
+ nextHopIp = gwHost.ipAddresses()
+ .stream()
+ .filter(IpAddress::isIp6)
+ .map(IpAddress::getIp6Address)
+ .findFirst()
+ .orElse(null);
+ } else {
+ nextHopIp = gwHost.ipAddresses()
+ .stream()
+ .filter(IpAddress::isIp6)
+ .filter(ip6 -> ip6.isLinkLocal())
+ .map(IpAddress::getIp6Address)
+ .findFirst()
+ .orElse(null);
+ }
return nextHopIp;
}
+
+ private List<DhcpServerInfo> findValidServerInfo(boolean directConnFlag) {
+ List<DhcpServerInfo> validServerInfo;
+
+ if (directConnFlag || indirectServerInfoList.isEmpty()) {
+ validServerInfo = new ArrayList<DhcpServerInfo>(defaultServerInfoList);
+ } else {
+ validServerInfo = new ArrayList<DhcpServerInfo>(indirectServerInfoList);
+ }
+ return validServerInfo;
+ }
+
+ private DhcpServerInfo findServerInfoFromServer(boolean directConnFlag, ConnectPoint inPort) {
+ List<DhcpServerInfo> validServerInfoList = findValidServerInfo(directConnFlag);
+ DhcpServerInfo foundServerInfo = null;
+ for (DhcpServerInfo serverInfo : validServerInfoList) {
+ if (inPort.equals(serverInfo.getDhcpServerConnectPoint().get())) {
+ foundServerInfo = serverInfo;
+ log.warn("ServerInfo found for Rcv port {} Server Connect Point {} for {}",
+ inPort, serverInfo.getDhcpServerConnectPoint(), directConnFlag ? "direct" : "indirect");
+ break;
+ } else {
+ log.warn("Rcv port {} not the same as Server Connect Point {} for {}",
+ inPort, serverInfo.getDhcpServerConnectPoint(), directConnFlag ? "direct" : "indirect");
+ }
+ }
+ return foundServerInfo;
+ }
+ /**
+ * Set the dhcp6 lease expiry poll interval value.
+ *
+ * @param val poll interval value in seconds
+ */
+ @Override
+ public void setDhcp6PollInterval(int val) {
+ dhcp6PollInterval = val;
+ }
+
+ /**
+ * get the dhcp6 lease expiry poll interval value.
+ * This is a private function
+ * @return poll interval value in seconds
+ */
+ private int getDhcp6PollInterval() {
+ return dhcp6PollInterval;
+ }
+
+ /**
+ * Find lease-expired ipaddresses and pd prefixes.
+ * Removing host/route/fpm entries.
+ */
+ public void timeTick() {
+ long currentTime = System.currentTimeMillis();
+ Collection<DhcpRecord> records = dhcpRelayStore.getDhcpRecords();
+
+ log.debug("timeTick called currenttime {} records num {} ", currentTime, records.size());
+
+ records.forEach(record -> {
+ boolean addrOrPdRemoved = false;
+ DHCP6.MsgType ip6Status = record.ip6Status().orElse(null);
+ if (ip6Status == null) {
+ log.debug("record is not valid v6 record.");
+ return;
+ }
+
+ if ((currentTime - record.getLastIp6Update()) >
+ ((record.addrPrefTime() + getDhcp6PollInterval() / 2) * 1000)) {
+ // remove ipaddress from host/route table
+ IpAddress ip = record.ip6Address().orElse(null);
+ if (ip != null) {
+ if (record.directlyConnected()) {
+ providerService.removeIpFromHost(HostId.hostId(record.macAddress(),
+ record.vlanId()), ip);
+ } else {
+ MacAddress gwMac = record.nextHop().orElse(null);
+ if (gwMac == null) {
+ log.warn("Can't find gateway mac address from record {} for ip6Addr", record);
+ return;
+ }
+ IpAddress nextHopIp = getFirstIpByHost(record.directlyConnected(),
+ gwMac,
+ record.vlanId());
+ Route route = new Route(Route.Source.STATIC, ip.toIpPrefix(), nextHopIp);
+ routeStore.removeRoute(route);
+ }
+ record.updateAddrPrefTime(0);
+ record.ip6Address(null);
+ addrOrPdRemoved = true;
+ dhcpRelayStore.updateDhcpRecord(HostId.hostId(record.macAddress(),
+ record.vlanId()), record);
+ log.warn("IP6 address is set to null. delta {} lastUpdate {} addrPrefTime {}",
+ (currentTime - record.getLastIp6Update()), record.getLastIp6Update(),
+ record.addrPrefTime());
+ }
+ }
+ if ((currentTime - record.getLastPdUpdate()) >
+ ((record.pdPrefTime() + getDhcp6PollInterval() / 2) * 1000)) {
+ // remove PD from route/fpm table
+ IpPrefix pdIpPrefix = record.pdPrefix().orElse(null);
+ if (pdIpPrefix != null) {
+ if (record.directlyConnected()) {
+ providerService.removeIpFromHost(HostId.hostId(record.macAddress(), record.vlanId()),
+ pdIpPrefix.address().getIp6Address());
+ } else {
+ MacAddress gwMac = record.nextHop().orElse(null);
+ if (gwMac == null) {
+ log.warn("Can't find gateway mac address from record {} for PD prefix", record);
+ return;
+ }
+ IpAddress nextHopIp = getFirstIpByHost(record.directlyConnected(),
+ gwMac,
+ record.vlanId());
+ Route route = new Route(Route.Source.STATIC, pdIpPrefix, nextHopIp);
+ routeStore.removeRoute(route);
+ if (this.dhcpFpmEnabled) {
+ dhcpFpmPrefixStore.removeFpmRecord(pdIpPrefix);
+ }
+ }
+ record.updatePdPrefTime(0);
+ record.pdPrefix(null);
+ addrOrPdRemoved = true;
+ dhcpRelayStore.updateDhcpRecord(HostId.hostId(record.macAddress(),
+ record.vlanId()), record);
+ log.warn("PD prefix is set to null.delta {} pdPrefTime {}",
+ (currentTime - record.getLastPdUpdate()), record.pdPrefTime());
+ }
+ }
+ if (addrOrPdRemoved &&
+ !record.ip6Address().isPresent() && !record.pdPrefix().isPresent()) {
+ log.warn("ip6Status {} IP6 address and IP6 PD both are null. Remove record.", ip6Status);
+ dhcpRelayStore.removeDhcpRecord(HostId.hostId(record.macAddress(), record.vlanId()));
+ }
+ }
+ );
+ }
}
diff --git a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/Dhcp6HandlerUtil.java b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/Dhcp6HandlerUtil.java
new file mode 100644
index 0000000..6e47a0d
--- /dev/null
+++ b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/Dhcp6HandlerUtil.java
@@ -0,0 +1,485 @@
+/*
+ * 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.dhcprelay;
+
+import org.onlab.packet.BasePacket;
+import org.onlab.packet.DHCP6;
+import org.onlab.packet.DHCP6.MsgType;
+import org.onlab.packet.Ip6Address;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.VlanId;
+import org.onlab.packet.dhcp.Dhcp6RelayOption;
+import org.onlab.packet.dhcp.Dhcp6Option;
+
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.IPv6;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.UDP;
+
+import org.onlab.util.HexString;
+import org.onosproject.dhcprelay.api.DhcpServerInfo;
+import org.onosproject.dhcprelay.store.DhcpRelayCounters;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.host.InterfaceIpAddress;
+import org.onosproject.net.intf.Interface;
+import org.onosproject.net.packet.PacketContext;
+import org.onosproject.net.DeviceId;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.util.Set;
+import java.util.List;
+import java.util.ArrayList;
+
+
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+
+
+public class Dhcp6HandlerUtil {
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+ // Returns the first v6 interface ip out of a set of interfaces or null.
+ // Checks all interfaces, and ignores v6 interface ips
+ public Ip6Address getRelayAgentIPv6Address(Set<Interface> intfs) {
+ for (Interface intf : intfs) {
+ for (InterfaceIpAddress ip : intf.ipAddressesList()) {
+ Ip6Address relayAgentIp = ip.ipAddress().getIp6Address();
+ if (relayAgentIp != null) {
+ return relayAgentIp;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the first interface ip from interface.
+ *
+ * @param iface interface of one connect point
+ * @return the first interface IP; null if not exists an IP address in
+ * these interfaces
+ */
+ public Ip6Address getFirstIpFromInterface(Interface iface) {
+ checkNotNull(iface, "Interface can't be null");
+ return iface.ipAddressesList().stream()
+ .map(InterfaceIpAddress::ipAddress)
+ .filter(IpAddress::isIp6)
+ .map(IpAddress::getIp6Address)
+ .findFirst()
+ .orElse(null);
+ }
+
+ /**
+ * extract DHCP6 payload from dhcp6 relay message within relay-forwrd/reply.
+ *
+ * @param dhcp6 dhcp6 relay-reply or relay-foward
+ * @return dhcp6Packet dhcp6 packet extracted from relay-message
+ */
+ public DHCP6 dhcp6PacketFromRelayPacket(DHCP6 dhcp6) {
+
+ // extract the relay message if exist
+ DHCP6 dhcp6Payload = dhcp6.getOptions().stream()
+ .filter(opt -> opt instanceof Dhcp6RelayOption)
+ .map(BasePacket::getPayload)
+ .map(pld -> (DHCP6) pld)
+ .findFirst()
+ .orElse(null);
+ if (dhcp6Payload == null) {
+ // Can't find dhcp payload
+ log.debug("Can't find dhcp6 payload from relay message");
+ } else {
+ log.debug("dhcp6 payload found from relay message {}", dhcp6Payload);
+ }
+ return dhcp6Payload;
+ }
+
+ /**
+ * find the leaf DHCP6 packet from multi-level relay packet.
+ *
+ * @param relayPacket dhcp6 relay packet
+ * @return leafPacket non-relay dhcp6 packet
+ */
+ public DHCP6 getDhcp6Leaf(DHCP6 relayPacket) {
+ DHCP6 dhcp6Parent = relayPacket;
+ DHCP6 dhcp6Child = null;
+
+ log.debug("getDhcp6Leaf entered.");
+ while (dhcp6Parent != null) {
+ dhcp6Child = dhcp6PacketFromRelayPacket(dhcp6Parent);
+ if (dhcp6Child != null) {
+ if (dhcp6Child.getMsgType() != DHCP6.MsgType.RELAY_FORW.value() &&
+ dhcp6Child.getMsgType() != DHCP6.MsgType.RELAY_REPL.value()) {
+ log.debug("leaf dhcp6 packet found.");
+ break;
+ } else {
+ // found another relay, go for another loop
+ dhcp6Parent = dhcp6Child;
+ }
+ } else {
+ log.debug("Expected dhcp6 within relay pkt, but no dhcp6 leaf found.");
+ break;
+ }
+ }
+ return dhcp6Child;
+ }
+
+ /**
+ * check if DHCP6 relay-reply is reply.
+ *
+ * @param relayPacket dhcp6 relay-reply
+ * @return boolean relay-reply contains ack
+ */
+ public boolean isDhcp6Reply(DHCP6 relayPacket) {
+ DHCP6 leafDhcp6 = getDhcp6Leaf(relayPacket);
+ if (leafDhcp6 != null) {
+ if (leafDhcp6.getMsgType() == DHCP6.MsgType.REPLY.value()) {
+ log.debug("isDhcp6Reply true.");
+ return true; // must be directly connected
+ } else {
+ log.debug("isDhcp6Reply false. leaf dhcp6 is not replay. MsgType {}", leafDhcp6.getMsgType());
+ }
+ } else {
+ log.debug("isDhcp6Reply false. Expected dhcp6 within relay pkt but not found.");
+ }
+ log.debug("isDhcp6Reply false.");
+ return false;
+ }
+
+ /**
+ * check if DHCP6 is release or relay-forward contains release.
+ *
+ * @param dhcp6Payload dhcp6 packet
+ * @return boolean dhcp6 contains release
+ */
+ public boolean isDhcp6Release(DHCP6 dhcp6Payload) {
+ if (dhcp6Payload.getMsgType() == DHCP6.MsgType.RELEASE.value()) {
+ log.debug("isDhcp6Release true.");
+ return true; // must be directly connected
+ } else {
+ DHCP6 dhcp6Leaf = getDhcp6Leaf(dhcp6Payload);
+ if (dhcp6Leaf != null) {
+ if (dhcp6Leaf.getMsgType() == DHCP6.MsgType.RELEASE.value()) {
+ log.debug("isDhcp6Release true. indirectlry connected");
+ return true;
+ } else {
+ log.debug("leaf dhcp6 is not release. MsgType {}", dhcp6Leaf.getMsgType());
+ return false;
+ }
+ } else {
+ log.debug("isDhcp6Release false. dhcp6 is niether relay nor release.");
+ return false;
+ }
+ }
+ }
+
+
+ /**
+ * convert dhcp6 msgType to String.
+ *
+ * @param msgTypeVal msgType byte of dhcp6 packet
+ * @return String string value of dhcp6 msg type
+ */
+ public String getMsgTypeStr(byte msgTypeVal) {
+ MsgType msgType = DHCP6.MsgType.getType(msgTypeVal);
+ return DHCP6.MsgType.getMsgTypeStr(msgType);
+ }
+
+ /**
+ * find the string of dhcp6 leaf packets's msg type.
+ *
+ * @param directConnFlag boolean value indicating direct/indirect connection
+ * @param dhcp6Packet dhcp6 packet
+ * @return String string value of dhcp6 leaf packet msg type
+ */
+ public String findLeafMsgType(boolean directConnFlag, DHCP6 dhcp6Packet) {
+ if (directConnFlag) {
+ return getMsgTypeStr(dhcp6Packet.getMsgType());
+ } else {
+ DHCP6 leafDhcp = getDhcp6Leaf(dhcp6Packet);
+ if (leafDhcp != null) {
+ return getMsgTypeStr(leafDhcp.getMsgType());
+ } else {
+ return DhcpRelayCounters.INVALID_PACKET;
+ }
+ }
+ }
+
+ /**
+ * Determind if an Interface contains a vlan id.
+ *
+ * @param iface the Interface
+ * @param vlanId the vlan id
+ * @return true if the Interface contains the vlan id
+ */
+ public boolean interfaceContainsVlan(Interface iface, VlanId vlanId) {
+ if (vlanId.equals(VlanId.NONE)) {
+ // untagged packet, check if vlan untagged or vlan native is not NONE
+ return !iface.vlanUntagged().equals(VlanId.NONE) ||
+ !iface.vlanNative().equals(VlanId.NONE);
+ }
+ // tagged packet, check if the interface contains the vlan
+ return iface.vlanTagged().contains(vlanId);
+ }
+
+ /**
+ * the new class the contains Ethernet packet and destination port.
+ */
+ public class InternalPacket {
+ Ethernet packet;
+ ConnectPoint destLocation;
+ public InternalPacket(Ethernet newPacket, ConnectPoint newLocation) {
+ packet = newPacket;
+ destLocation = newLocation;
+ }
+ void setLocation(ConnectPoint newLocation) {
+ destLocation = newLocation;
+ }
+ }
+ /**
+ * Check if the host is directly connected to the network or not.
+ *
+ * @param dhcp6Payload the dhcp6 payload
+ * @return true if the host is directly connected to the network; false otherwise
+ */
+ public boolean directlyConnected(DHCP6 dhcp6Payload) {
+ log.debug("directlyConnected enters");
+
+ if (dhcp6Payload.getMsgType() != DHCP6.MsgType.RELAY_FORW.value() &&
+ dhcp6Payload.getMsgType() != DHCP6.MsgType.RELAY_REPL.value()) {
+ log.debug("directlyConnected true. MsgType {}", dhcp6Payload.getMsgType());
+
+ return true;
+ }
+ // Regardless of relay-forward or relay-replay, check if we see another relay message
+ DHCP6 dhcp6Payload2 = dhcp6PacketFromRelayPacket(dhcp6Payload);
+ if (dhcp6Payload2 != null) {
+ if (dhcp6Payload.getMsgType() == DHCP6.MsgType.RELAY_FORW.value()) {
+ log.debug("directlyConnected false. 1st realy-foward, 2nd MsgType {}", dhcp6Payload2.getMsgType());
+ return false;
+ } else {
+ // relay-reply
+ if (dhcp6Payload2.getMsgType() != DHCP6.MsgType.RELAY_REPL.value()) {
+ log.debug("directlyConnected true. 2nd MsgType {}", dhcp6Payload2.getMsgType());
+ return true; // must be directly connected
+ } else {
+ log.debug("directlyConnected false. 1st relay-reply, 2nd relay-reply MsgType {}",
+ dhcp6Payload2.getMsgType());
+ return false; // must be indirectly connected
+ }
+ }
+ } else {
+ log.debug("directlyConnected true.");
+ return true;
+ }
+ }
+ /**
+ * Check if a given server info has v6 ipaddress.
+ *
+ * @param serverInfo server info to check
+ * @return true if server info has v6 ip address; false otherwise
+ */
+ public boolean isServerIpEmpty(DhcpServerInfo serverInfo) {
+ if (!serverInfo.getDhcpServerIp6().isPresent()) {
+ log.warn("DhcpServerIp not available, use default DhcpServerIp {}",
+ HexString.toHexString(serverInfo.getDhcpServerIp6().get().toOctets()));
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isConnectMacEmpty(DhcpServerInfo serverInfo, Set<Interface> clientInterfaces) {
+ if (!serverInfo.getDhcpConnectMac().isPresent()) {
+ log.warn("DHCP6 {} not yet resolved .. Aborting DHCP "
+ + "packet processing from client on port: {}",
+ !serverInfo.getDhcpGatewayIp6().isPresent() ? "server IP " + serverInfo.getDhcpServerIp6()
+ : "gateway IP " + serverInfo.getDhcpGatewayIp6(),
+ clientInterfaces.iterator().next().connectPoint());
+ return true;
+ }
+ return false;
+ }
+
+ private boolean isRelayAgentIpFromCfgEmpty(DhcpServerInfo serverInfo, DeviceId receivedFromDevice) {
+ if (!serverInfo.getRelayAgentIp6(receivedFromDevice).isPresent()) {
+ log.warn("indirect connection: relayAgentIp NOT availale from config file! Use dynamic.");
+ return true;
+ }
+ return false;
+ }
+
+ private Dhcp6Option getInterfaceIdIdOption(PacketContext context, Ethernet clientPacket) {
+ String inPortString = "-" + context.inPacket().receivedFrom().toString() + ":";
+ Dhcp6Option interfaceId = new Dhcp6Option();
+ interfaceId.setCode(DHCP6.OptionCode.INTERFACE_ID.value());
+ byte[] clientSoureMacBytes = clientPacket.getSourceMACAddress();
+ byte[] inPortStringBytes = inPortString.getBytes();
+ byte[] vlanIdBytes = new byte[2];
+ vlanIdBytes[0] = (byte) (clientPacket.getVlanID() & 0xff);
+ vlanIdBytes[1] = (byte) ((clientPacket.getVlanID() >> 8) & 0xff);
+ byte[] interfaceIdBytes = new byte[clientSoureMacBytes.length +
+ inPortStringBytes.length + vlanIdBytes.length];
+ log.debug("Length: interfaceIdBytes {} clientSoureMacBytes {} inPortStringBytes {} vlan {}",
+ interfaceIdBytes.length, clientSoureMacBytes.length, inPortStringBytes.length,
+ vlanIdBytes.length);
+
+ System.arraycopy(clientSoureMacBytes, 0, interfaceIdBytes, 0, clientSoureMacBytes.length);
+ System.arraycopy(inPortStringBytes, 0, interfaceIdBytes, clientSoureMacBytes.length,
+ inPortStringBytes.length);
+ System.arraycopy(vlanIdBytes, 0, interfaceIdBytes,
+ clientSoureMacBytes.length + inPortStringBytes.length,
+ vlanIdBytes.length);
+ interfaceId.setData(interfaceIdBytes);
+ interfaceId.setLength((short) interfaceIdBytes.length);
+ log.debug("interfaceId write srcMac {} portString {}",
+ HexString.toHexString(clientSoureMacBytes, ":"), inPortString);
+ return interfaceId;
+ }
+
+ private void addDhcp6OptionsFromClient(List<Dhcp6Option> options, byte[] dhcp6PacketByte,
+ PacketContext context, Ethernet clientPacket) {
+ Dhcp6Option relayMessage = new Dhcp6Option();
+ relayMessage.setCode(DHCP6.OptionCode.RELAY_MSG.value());
+ relayMessage.setLength((short) dhcp6PacketByte.length);
+ relayMessage.setData(dhcp6PacketByte);
+ options.add(relayMessage);
+ // create interfaceId option
+ Dhcp6Option interfaceId = getInterfaceIdIdOption(context, clientPacket);
+ options.add(interfaceId);
+ }
+
+ /**
+ * build the DHCP6 solicit/request packet with gatewayip.
+ *
+ * @param context packet context
+ * @param clientPacket client ethernet packet
+ * @param clientInterfaces set of client side interfaces
+ * @param serverInfo target server which a packet is generated for
+ * @param serverInterface target server interface
+ * @return ethernet packet with dhcp6 packet info
+ */
+ public Ethernet buildDhcp6PacketFromClient(PacketContext context, Ethernet clientPacket,
+ Set<Interface> clientInterfaces, DhcpServerInfo serverInfo,
+ Interface serverInterface) {
+ ConnectPoint receivedFrom = context.inPacket().receivedFrom();
+ DeviceId receivedFromDevice = receivedFrom.deviceId();
+
+ Ip6Address relayAgentIp = getRelayAgentIPv6Address(clientInterfaces);
+ MacAddress relayAgentMac = clientInterfaces.iterator().next().mac();
+ if (relayAgentIp == null || relayAgentMac == null) {
+ log.warn("Missing DHCP relay agent interface Ipv6 addr config for "
+ + "packet from client on port: {}. Aborting packet processing",
+ clientInterfaces.iterator().next().connectPoint());
+ return null;
+ }
+ IPv6 clientIpv6 = (IPv6) clientPacket.getPayload();
+ UDP clientUdp = (UDP) clientIpv6.getPayload();
+ DHCP6 clientDhcp6 = (DHCP6) clientUdp.getPayload();
+ boolean directConnFlag = directlyConnected(clientDhcp6);
+
+ Ip6Address serverIpFacing = getFirstIpFromInterface(serverInterface);
+ if (serverIpFacing == null || serverInterface.mac() == null) {
+ log.warn("No IP v6 address for server Interface {}", serverInterface);
+ return null;
+ }
+
+ Ethernet etherReply = clientPacket.duplicate();
+ etherReply.setSourceMACAddress(serverInterface.mac());
+
+ // set default info and replace with indirect if available later on.
+ if (serverInfo.getDhcpConnectMac().isPresent()) {
+ etherReply.setDestinationMACAddress(serverInfo.getDhcpConnectMac().get());
+ }
+ if (serverInfo.getDhcpConnectVlan().isPresent()) {
+ etherReply.setVlanID(serverInfo.getDhcpConnectVlan().get().toShort());
+ }
+ IPv6 ipv6Packet = (IPv6) etherReply.getPayload();
+ byte[] peerAddress = clientIpv6.getSourceAddress();
+ ipv6Packet.setSourceAddress(serverIpFacing.toOctets());
+ ipv6Packet.setDestinationAddress(serverInfo.getDhcpServerIp6().get().toOctets());
+ UDP udpPacket = (UDP) ipv6Packet.getPayload();
+ udpPacket.setSourcePort(UDP.DHCP_V6_SERVER_PORT);
+ DHCP6 dhcp6Packet = (DHCP6) udpPacket.getPayload();
+ byte[] dhcp6PacketByte = dhcp6Packet.serialize();
+
+ DHCP6 dhcp6Relay = new DHCP6();
+
+ dhcp6Relay.setMsgType(DHCP6.MsgType.RELAY_FORW.value());
+
+ if (directConnFlag) {
+ dhcp6Relay.setLinkAddress(relayAgentIp.toOctets());
+ } else {
+ if (isServerIpEmpty(serverInfo)) {
+ log.warn("indirect DhcpServerIp empty... use default server ");
+ } else {
+ // Indirect case, replace destination to indirect dhcp server if exist
+ // Check if mac is obtained for valid server ip
+ if (isConnectMacEmpty(serverInfo, clientInterfaces)) {
+ log.warn("indirect Dhcp ConnectMac empty ...");
+ return null;
+ }
+ etherReply.setDestinationMACAddress(serverInfo.getDhcpConnectMac().get());
+ etherReply.setVlanID(serverInfo.getDhcpConnectVlan().get().toShort());
+ ipv6Packet.setDestinationAddress(serverInfo.getDhcpServerIp6().get().toOctets());
+ }
+ if (isRelayAgentIpFromCfgEmpty(serverInfo, receivedFromDevice)) {
+ dhcp6Relay.setLinkAddress(relayAgentIp.toOctets());
+ log.debug("indirect connection: relayAgentIp NOT availale from config file! Use dynamic. {}",
+ HexString.toHexString(relayAgentIp.toOctets(), ":"));
+ } else {
+ dhcp6Relay.setLinkAddress(serverInfo.getRelayAgentIp6(receivedFromDevice).get().toOctets());
+ }
+ }
+ // peer address: address of the client or relay agent from which the message to be relayed was received.
+ dhcp6Relay.setPeerAddress(peerAddress);
+ // directly connected case, hop count is zero; otherwise, hop count + 1
+ if (directConnFlag) {
+ dhcp6Relay.setHopCount((byte) 0);
+ } else {
+ dhcp6Relay.setHopCount((byte) (dhcp6Packet.getHopCount() + 1));
+ }
+
+ List<Dhcp6Option> options = new ArrayList<>();
+ addDhcp6OptionsFromClient(options, dhcp6PacketByte, context, clientPacket);
+ dhcp6Relay.setOptions(options);
+ udpPacket.setPayload(dhcp6Relay);
+ udpPacket.resetChecksum();
+ ipv6Packet.setPayload(udpPacket);
+ ipv6Packet.setHopLimit((byte) 64);
+ etherReply.setPayload(ipv6Packet);
+
+ return etherReply;
+ }
+
+ /**
+ * build the DHCP6 solicit/request packet with gatewayip.
+ *
+ * @param directConnFlag flag indicating if packet is from direct client or not
+ * @param serverInfo server to check its connect point
+ * @return boolean true if serverInfo is found; false otherwise
+ */
+ public boolean checkDhcpServerConnPt(boolean directConnFlag,
+ DhcpServerInfo serverInfo) {
+ if (serverInfo.getDhcpServerConnectPoint() == null) {
+ log.warn("DHCP6 server connect point for {} connPt {}",
+ directConnFlag ? "direct" : "indirect", serverInfo.getDhcpServerConnectPoint());
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/DhcpRelayManager.java b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/DhcpRelayManager.java
index 07e5cd9..39123ac 100644
--- a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/DhcpRelayManager.java
+++ b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/DhcpRelayManager.java
@@ -93,6 +93,11 @@
import org.osgi.service.component.ComponentContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import static org.onlab.util.Tools.groupedThreads;
+
import com.google.common.collect.ImmutableSet;
@@ -153,6 +158,7 @@
}
);
+
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected NetworkConfigRegistry cfgService;
@@ -192,14 +198,30 @@
label = "Enable Address resolution protocol")
protected boolean arpEnabled = true;
+ @Property(name = "dhcpPollInterval", intValue = 24 * 3600,
+ label = "dhcp relay poll interval")
+ protected int dhcpPollInterval = 24 * 3600;
+
@Property(name = "dhcpFpmEnabled", boolValue = false,
label = "Enable DhcpRelay Fpm")
protected boolean dhcpFpmEnabled = false;
+
+ private ScheduledExecutorService timerExecutor;
+
protected DeviceListener deviceListener = new InternalDeviceListener();
private DhcpRelayPacketProcessor dhcpRelayPacketProcessor = new DhcpRelayPacketProcessor();
private ApplicationId appId;
+ /**
+ * One second timer.
+ */
+ class Dhcp6Timer implements Runnable {
+ @Override
+ public void run() {
+ v6Handler.timeTick();
+ }
+ };
@Activate
protected void activate(ComponentContext context) {
@@ -214,6 +236,14 @@
//add the packet processor
packetService.addProcessor(dhcpRelayPacketProcessor, PacketProcessor.director(0));
+ timerExecutor = Executors.newScheduledThreadPool(1,
+ groupedThreads("dhcpRelay",
+ "config-reloader-%d", log));
+ timerExecutor.scheduleAtFixedRate(new Dhcp6Timer(),
+ 0,
+ dhcpPollInterval,
+ TimeUnit.SECONDS);
+
modified(context);
// Enable distribute route store
@@ -222,6 +252,9 @@
compCfgService.registerProperties(getClass());
deviceService.addListener(deviceListener);
+
+
+
log.info("DHCP-RELAY Started");
}
@@ -233,6 +266,8 @@
cancelArpPackets();
compCfgService.unregisterProperties(getClass(), false);
deviceService.removeListener(deviceListener);
+ timerExecutor.shutdown();
+
log.info("DHCP-RELAY Stopped");
}
@@ -254,6 +289,21 @@
cancelArpPackets();
}
+ int intervalVal = Tools.getIntegerProperty(properties, "dhcpPollInterval");
+ log.info("DhcpRelay poll interval new {} old {}", intervalVal, dhcpPollInterval);
+ if (intervalVal != dhcpPollInterval) {
+ timerExecutor.shutdown();
+ dhcpPollInterval = intervalVal;
+ timerExecutor = Executors.newScheduledThreadPool(1,
+ groupedThreads("dhcpRelay",
+ "config-reloader-%d", log));
+ timerExecutor.scheduleAtFixedRate(new Dhcp6Timer(),
+ 0,
+ dhcpPollInterval > 1 ? dhcpPollInterval : 1,
+ TimeUnit.SECONDS);
+ v6Handler.setDhcp6PollInterval(dhcpPollInterval);
+ }
+
flag = Tools.isPropertyEnabled(properties, "dhcpFpmEnabled");
if (flag != null) {
boolean oldValue = dhcpFpmEnabled;
@@ -368,7 +418,10 @@
public Collection<DhcpRecord> getDhcpRecords() {
return dhcpRelayStore.getDhcpRecords();
}
-
+ @Override
+ public void updateDhcpRecord(HostId hostId, DhcpRecord dhcpRecord) {
+ dhcpRelayStore.updateDhcpRecord(hostId, dhcpRecord);
+ }
@Override
public Optional<MacAddress> getDhcpServerMacAddress() {
// TODO: depreated it
@@ -617,4 +670,6 @@
public Optional<FpmRecord> removeFpmRecord(IpPrefix prefix) {
return dhcpFpmPrefixStore.removeFpmRecord(prefix);
}
+
+
}
diff --git a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/api/DhcpHandler.java b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/api/DhcpHandler.java
index 49b88e8..3de3ced 100644
--- a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/api/DhcpHandler.java
+++ b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/api/DhcpHandler.java
@@ -178,10 +178,22 @@
void removeIgnoreVlanState(IgnoreDhcpConfig config);
/**
+ * Hander for Dhcp expiration poll timer.
+ *
+ */
+ default void timeTick() { }
+
+ /**
+ * Update Dhcp expiration poll timer value.
+ *
+ * @param val the timer interval value
+ */
+ default void setDhcp6PollInterval(int val) { }
+
+ /**
* Sets DHCP FPM Enable state.
*
* @param dhcpFpmFlag flag indicating dhcpFpmEnable state
*/
default void setDhcpFpmEnabled(Boolean dhcpFpmFlag) { }
-
}
diff --git a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/api/DhcpRelayService.java b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/api/DhcpRelayService.java
index ef700d4..5eb8d9e 100644
--- a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/api/DhcpRelayService.java
+++ b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/api/DhcpRelayService.java
@@ -43,6 +43,14 @@
Collection<DhcpRecord> getDhcpRecords();
/**
+ * Updates DHCP record for specific host id (mac + vlan).
+ *
+ * @param hostId the id of host
+ * @param dhcpRecord the DHCP record of the host
+ */
+ void updateDhcpRecord(HostId hostId, DhcpRecord dhcpRecord);
+
+ /**
* Gets mac address of DHCP server.
*
* @return the mac address of DHCP server; empty if not exist
@@ -102,4 +110,5 @@
* @return boolean value
*/
public boolean isDhcpFpmEnabled();
+
}
diff --git a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/cli/DhcpRelayAggCountersCommand.java b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/cli/DhcpRelayAggCountersCommand.java
new file mode 100644
index 0000000..a91a53a
--- /dev/null
+++ b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/cli/DhcpRelayAggCountersCommand.java
@@ -0,0 +1,82 @@
+/*
+ * 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.dhcprelay.cli;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.dhcprelay.api.DhcpRelayService;
+import org.onosproject.dhcprelay.store.DhcpRelayCounters;
+import org.onosproject.dhcprelay.store.DhcpRelayCountersStore;
+
+
+import java.util.Map;
+import java.util.Optional;
+
+/**
+ * Prints Dhcp FPM Routes information.
+ */
+@Command(scope = "onos", name = "dhcp-relay-agg-counters",
+ description = "DHCP Relay Aggregate Counters cli.")
+public class DhcpRelayAggCountersCommand extends AbstractShellCommand {
+ @Argument(index = 0, name = "reset",
+ description = "reset counters or not",
+ required = false, multiValued = false)
+ String reset = null;
+
+ private static final String HEADER = "DHCP Relay Aggregate Counters :";
+ private static final String GCOUNT = "global";
+ private static final DhcpRelayService DHCP_RELAY_SERVICE = get(DhcpRelayService.class);
+
+ @Override
+ protected void execute() {
+ boolean toResetFlag;
+
+ if (reset != null) {
+ if (reset.equals("reset") || reset.equals("[reset]")) {
+ toResetFlag = true;
+ } else {
+ print("Last parameter is [reset]");
+ return;
+ }
+ } else {
+ toResetFlag = false;
+ }
+
+ print(HEADER);
+
+ DhcpRelayCountersStore counterStore = AbstractShellCommand.get(DhcpRelayCountersStore.class);
+
+ Optional<DhcpRelayCounters> perClassCounters = counterStore.getCounters(GCOUNT);
+
+ if (perClassCounters.isPresent()) {
+ Map<String, Integer> counters = perClassCounters.get().getCounters();
+ if (counters.size() > 0) {
+ counters.forEach((name, value) -> {
+ print("%-30s ............................ %-4d packets", name, value);
+ });
+ } else {
+ print("No counter for {}", GCOUNT);
+ }
+
+ if (toResetFlag) {
+ counterStore.resetCounters(GCOUNT);
+
+ }
+ }
+ }
+}
diff --git a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/cli/DhcpRelayCommand.java b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/cli/DhcpRelayCommand.java
index bd41ecf..6bf46b8 100644
--- a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/cli/DhcpRelayCommand.java
+++ b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/cli/DhcpRelayCommand.java
@@ -16,12 +16,15 @@
package org.onosproject.dhcprelay.cli;
+
+import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.commands.Command;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onlab.util.Tools;
import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.dhcprelay.store.DhcpRelayCounters;
import org.onosproject.dhcprelay.api.DhcpServerInfo;
import org.onosproject.dhcprelay.api.DhcpRelayService;
import org.onosproject.dhcprelay.store.DhcpRecord;
@@ -32,12 +35,30 @@
import java.util.Collection;
import java.util.List;
import java.util.function.Predicate;
+import java.util.Map;
+
/**
* Prints DHCP server and DHCP relay status.
*/
@Command(scope = "onos", name = "dhcp-relay", description = "DHCP relay app cli.")
public class DhcpRelayCommand extends AbstractShellCommand {
+ @Argument(index = 0, name = "counter",
+ description = "shows counter values",
+ required = false, multiValued = false)
+ String counter = null;
+
+ @Argument(index = 1, name = "reset",
+ description = "reset counters or not",
+ required = false, multiValued = false)
+ String reset = null;
+
+
+
+ private static final String CONUTER_HEADER = "DHCP Relay Counters :";
+ private static final String COUNTER_HOST = "Counters for id=%s/%s, locations=%s%s";
+
+
private static final String HEADER = "DHCP relay records ([D]: Directly connected):";
private static final String NO_RECORDS = "No DHCP relay record found";
private static final String HOST = "id=%s/%s, locations=%s%s, last-seen=%s, IPv4=%s, IPv6=%s";
@@ -49,12 +70,15 @@
private static final String NA = "N/A";
private static final String STATUS_FMT = "[%s, %s]";
private static final String STATUS_FMT_NH = "[%s via %s, %s]";
+ private static final String STATUS_FMT_V6 = "[%s %d, %d ms %s %d %d ms, %s]";
+ private static final String STATUS_FMT_V6_NH = "[%s %d %d ms, %s %d %d ms via %s, %s]";
private static final String DEFAULT_SERVERS = "Default DHCP servers:";
private static final String INDIRECT_SERVERS = "Indirect DHCP servers:";
private static final DhcpRelayService DHCP_RELAY_SERVICE = get(DhcpRelayService.class);
private static final HostService HOST_SERVICE = get(HostService.class);
+
@Override
protected void execute() {
List<DhcpServerInfo> defaultDhcpServerInfoList = DHCP_RELAY_SERVICE.getDefaultDhcpServerInfoList();
@@ -80,6 +104,52 @@
print(NO_RECORDS);
return;
}
+
+ // Handle display of counters
+ boolean toResetFlag;
+
+ if (counter != null) {
+ if (counter.equals("counter") || reset.equals("[counter]")) {
+ print(CONUTER_HEADER);
+ } else {
+ print("first parameter is [counter]");
+ return;
+ }
+ if (reset != null) {
+ if (reset.equals("reset") || reset.equals("[reset]")) {
+ toResetFlag = true;
+ } else {
+ print("Last parameter is [reset]");
+ return;
+ }
+ } else {
+ toResetFlag = false;
+ }
+
+ records.forEach(record -> {
+ print(COUNTER_HOST, record.macAddress(),
+ record.vlanId(),
+ record.locations(),
+ record.directlyConnected() ? DIRECTLY : EMPTY);
+ DhcpRelayCounters v6Counters = record.getV6Counters();
+ Map<String, Integer> countersMap = v6Counters.getCounters();
+ countersMap.forEach((name, value) -> {
+ print("%-30s ............................ %-4d packets", name, value);
+ });
+ if (toResetFlag) {
+ v6Counters.resetCounters();
+ record.updateLastSeen();
+ DHCP_RELAY_SERVICE.updateDhcpRecord(HostId.hostId(record.macAddress(), record.vlanId()), record);
+ }
+ });
+
+
+ return;
+ }
+
+
+ // Handle display of records
+
print(HEADER);
records.forEach(record -> print(HOST,
record.macAddress(),
@@ -135,13 +205,30 @@
}
private String ip6State(DhcpRecord record) {
- String nextHopIp = findNextHopIp(IpAddress::isIp6,
+ String nextHopIp = findNextHopIp6(IpAddress::isIp6,
record.nextHop().orElse(null),
record.vlanId());
- return ipState(record.ip6Address().map(Object::toString).orElse(NA),
- record.ip6Status().map(Object::toString).orElse(NA),
- record.directlyConnected(),
- nextHopIp);
+
+ if (record.directlyConnected()) {
+ return String.format(STATUS_FMT_V6,
+ record.ip6Address().map(Object::toString).orElse(NA),
+ record.addrPrefTime(),
+ record.getLastIp6Update(),
+ record.pdPrefix().map(Object::toString).orElse(NA),
+ record.pdPrefTime(),
+ record.getLastPdUpdate(),
+ record.ip6Status().map(Object::toString).orElse(NA));
+ } else {
+ return String.format(STATUS_FMT_V6_NH,
+ record.ip6Address().map(Object::toString).orElse(NA),
+ record.addrPrefTime(),
+ record.getLastIp6Update(),
+ record.pdPrefix().map(Object::toString).orElse(NA),
+ record.pdPrefTime(),
+ record.getLastPdUpdate(),
+ nextHopIp,
+ record.ip6Status().map(Object::toString).orElse(NA));
+ }
}
private String ipState(String ipAddress, String status,
@@ -158,6 +245,7 @@
if (ipFilter == null || nextHopMac == null || vlanId == null) {
return NA;
}
+
Host host = HOST_SERVICE.getHost(HostId.hostId(nextHopMac, vlanId));
if (host == null) {
return NA;
@@ -169,4 +257,21 @@
.findFirst()
.orElse(NA);
}
+
+ private String findNextHopIp6(Predicate<IpAddress> ipFilter, MacAddress nextHopMac, VlanId vlanId) {
+ if (ipFilter == null || nextHopMac == null || vlanId == null) {
+ return NA;
+ }
+
+ Host host = HOST_SERVICE.getHost(HostId.hostId(nextHopMac, vlanId));
+ if (host == null) {
+ return NA;
+ }
+ return host.ipAddresses().stream()
+ .filter(ipFilter)
+ .filter(ip -> ip.isLinkLocal())
+ .map(Object::toString)
+ .findFirst()
+ .orElse(NA);
+ }
}
diff --git a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/cli/DhcpRelayCounterCompleter.java b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/cli/DhcpRelayCounterCompleter.java
new file mode 100644
index 0000000..8b024a5
--- /dev/null
+++ b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/cli/DhcpRelayCounterCompleter.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.dhcprelay.cli;
+
+import org.apache.karaf.shell.console.Completer;
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+
+import java.util.List;
+import java.util.SortedSet;
+
+/**
+ * Dhcp Relay counter completer.
+ */
+public class DhcpRelayCounterCompleter implements Completer {
+
+ @Override
+ public int complete(String buffer, int cursor, List<String> candidates) {
+ // Delegate string completer
+ StringsCompleter delegate = new StringsCompleter();
+ SortedSet<String> strings = delegate.getStrings();
+ strings.add("counter");
+
+ // Now let the completer do the work for figuring out what to offer.
+ return delegate.complete(buffer, cursor, candidates);
+ }
+}
diff --git a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/cli/DhcpRelayResetCompleter.java b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/cli/DhcpRelayResetCompleter.java
new file mode 100644
index 0000000..3eb4404
--- /dev/null
+++ b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/cli/DhcpRelayResetCompleter.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.dhcprelay.cli;
+
+import org.apache.karaf.shell.console.Completer;
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+
+import java.util.List;
+import java.util.SortedSet;
+
+/**
+ * Dhcp Relay reset completer.
+ */
+public class DhcpRelayResetCompleter implements Completer {
+
+ @Override
+ public int complete(String buffer, int cursor, List<String> candidates) {
+ // Delegate string completer
+ StringsCompleter delegate = new StringsCompleter();
+ SortedSet<String> strings = delegate.getStrings();
+ strings.add("reset");
+
+ // Now let the completer do the work for figuring out what to offer.
+ return delegate.complete(buffer, cursor, candidates);
+ }
+}
diff --git a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/store/DhcpRecord.java b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/store/DhcpRecord.java
index e133f03..44c6c3c 100644
--- a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/store/DhcpRecord.java
+++ b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/store/DhcpRecord.java
@@ -22,6 +22,7 @@
import org.onlab.packet.DHCP6;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip6Address;
+import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.net.HostId;
@@ -49,10 +50,19 @@
private DHCP.MsgType ip4Status;
private Ip6Address ip6Address;
+ private IpPrefix pdPrefix;
private DHCP6.MsgType ip6Status;
+
private long lastSeen;
+ private long lastIp6Update;
+ private long lastPdUpdate;
+
private boolean directlyConnected;
+ private long addrPrefTime;
+ private long pdPrefTime;
+ private DhcpRelayCounters v6Counters;
+
/**
* Creates a DHCP record for a host (mac + vlan).
@@ -67,6 +77,7 @@
this.vlanId = hostId.vlanId();
this.lastSeen = System.currentTimeMillis();
this.directlyConnected = false;
+ this.v6Counters = new DhcpRelayCounters();
}
/**
@@ -159,6 +170,26 @@
}
/**
+ * Gets IPv6 PD address which assigned to the host.
+ *
+ * @return the PD IP address assigned to the host
+ */
+ public Optional<IpPrefix> pdPrefix() {
+ return Optional.ofNullable(pdPrefix);
+ }
+
+ /**
+ * Sets IPv6 PD address.
+ *
+ * @param pdPrefix the IPv6 PD address
+ * @return the DHCP record
+ */
+ public DhcpRecord pdPrefix(IpPrefix pdPrefix) {
+ this.pdPrefix = pdPrefix;
+ return this;
+ }
+
+ /**
* Gets the latest time this record updated.
*
* @return the last time host send or receive DHCP packet
@@ -178,6 +209,84 @@
}
/**
+ * Gets the latest time this record updated with ip6 Address.
+ *
+ * @return the last time received DHCP packet provide ip6 Address
+ */
+ public long getLastIp6Update() {
+ return lastIp6Update;
+ }
+
+ /**
+ * Updates the update time of this record is given ip6 Address.
+ *
+ * @return the DHCP record
+ */
+ public DhcpRecord updateLastIp6Update() {
+ lastIp6Update = System.currentTimeMillis();
+ return this;
+ }
+
+ /**
+ * Gets the latest time this record updated with pd Prefix.
+ *
+ * @return the last time received DHCP packet provide pd Prefix
+ */
+ public long getLastPdUpdate() {
+ return lastPdUpdate;
+ }
+
+ /**
+ * Updates the update time of this record is given pd Prefix.
+ *
+ * @return the DHCP record
+ */
+ public DhcpRecord updateLastPdUpdate() {
+ lastPdUpdate = System.currentTimeMillis();
+ return this;
+ }
+
+ /**
+ * Gets the IP Address preferred time for this record.
+ *
+ * @return the preferred lease time for this ip address
+ */
+ public long addrPrefTime() {
+ return addrPrefTime;
+ }
+
+ /**
+ * Updates the IP Address preferred time of this record.
+ *
+ * @param prefTime preferred liftme
+ * @return the DHCP record
+ */
+ public DhcpRecord updateAddrPrefTime(long prefTime) {
+ addrPrefTime = prefTime;
+ return this;
+ }
+
+ /**
+ * Gets the PD Prefix preferred time for this record.
+ *
+ * @return the preferred lease time for this PD prefix
+ */
+ public long pdPrefTime() {
+ return pdPrefTime;
+ }
+
+ /**
+ * Updates the PD Prefix preferred time of this record.
+ *
+ * @param prefTime preferred liftme
+ * @return the DHCP record
+ */
+ public DhcpRecord updatePdPrefTime(long prefTime) {
+ pdPrefTime = prefTime;
+ return this;
+ }
+
+ /**
* Indicated that the host is direct connected to the network or not.
*
* @return true if the host is directly connected to the network; false otherwise
@@ -279,6 +388,15 @@
}
/**
+ * Gets dhcp relay counters.
+ *
+ * @return the counter object
+ */
+ public DhcpRelayCounters getV6Counters() {
+ return v6Counters;
+ }
+
+ /**
* Clone this DHCP record.
*
* @return the DHCP record which cloned
@@ -292,15 +410,23 @@
newRecord.ip4Address = ip4Address;
newRecord.ip4Status = ip4Status;
newRecord.ip6Address = ip6Address;
+ newRecord.pdPrefix = pdPrefix;
newRecord.ip6Status = ip6Status;
newRecord.lastSeen = lastSeen;
+ newRecord.lastIp6Update = lastIp6Update;
+ newRecord.lastPdUpdate = lastPdUpdate;
+ newRecord.addrPrefTime = addrPrefTime;
+ newRecord.pdPrefTime = pdPrefTime;
+ newRecord.v6Counters = v6Counters;
+
return newRecord;
}
@Override
public int hashCode() {
return Objects.hash(locations, macAddress, vlanId, ip4Address, ip4Status,
- nextHop, nextHopTemp, ip6Address, ip6Status, lastSeen);
+ nextHop, nextHopTemp, ip6Address, pdPrefix, ip6Status, lastSeen,
+ lastIp6Update, lastPdUpdate, addrPrefTime, pdPrefTime, v6Counters);
}
@Override
@@ -320,9 +446,15 @@
Objects.equals(nextHop, that.nextHop) &&
Objects.equals(nextHopTemp, that.nextHopTemp) &&
Objects.equals(ip6Address, that.ip6Address) &&
+ Objects.equals(pdPrefix, that.pdPrefix) &&
Objects.equals(ip6Status, that.ip6Status) &&
Objects.equals(lastSeen, that.lastSeen) &&
- Objects.equals(directlyConnected, that.directlyConnected);
+ Objects.equals(lastIp6Update, that.lastIp6Update) &&
+ Objects.equals(lastPdUpdate, that.lastPdUpdate) &&
+ Objects.equals(directlyConnected, that.directlyConnected) &&
+ Objects.equals(addrPrefTime, that.addrPrefTime) &&
+ Objects.equals(pdPrefTime, that.pdPrefTime) &&
+ Objects.equals(v6Counters, that.v6Counters);
}
@Override
@@ -336,9 +468,15 @@
.add("nextHop", nextHop)
.add("nextHopTemp", nextHopTemp)
.add("ip6Address", ip6Address)
+ .add("pdPrefix", pdPrefix)
.add("ip6State", ip6Status)
.add("lastSeen", lastSeen)
+ .add("lastIp6Update", lastIp6Update)
+ .add("lastPdUpdate", lastPdUpdate)
.add("directlyConnected", directlyConnected)
+ .add("addPrefTime", addrPrefTime)
+ .add("pdPrefTime", pdPrefTime)
+ .add("v6Counters", v6Counters)
.toString();
}
}
diff --git a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/store/DhcpRelayCounters.java b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/store/DhcpRelayCounters.java
new file mode 100644
index 0000000..2a69c21
--- /dev/null
+++ b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/store/DhcpRelayCounters.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.dhcprelay.store;
+
+
+import com.google.common.collect.ImmutableSet;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.Map;
+import java.util.Objects;
+
+public class DhcpRelayCounters {
+ // common counters
+
+ // IpV6 specific counters
+ public static final String SOLICIT = "SOLICIT";
+ public static final String ADVERTISE = "ADVERTISE";
+ public static final String REQUEST = "REQUEST";
+ public static final String CONFIRM = "CONFIRM";
+ public static final String RENEW = "RENEW";
+ public static final String REBIND = "REBIND";
+ public static final String REPLY = "REPLY";
+ public static final String RELEASE = "RELEASE";
+ public static final String DECLINE = "DECLINE";
+ public static final String RECONFIGURE = "RECONFIGURE";
+ public static final String INFORMATION_REQUEST = "INFORMATION_REQUEST";
+ public static final String RELAY_FORW = "RELAY_FORW";
+ public static final String RELAY_REPL = "RELAY_REPL";
+
+ public static final String NO_LINKLOCAL_GW = "No link-local in Gateway";
+ public static final String NO_LINKLOCAL_FAIL = "No link-local in CLIENT_ID";
+ public static final String NO_CLIENTID_FAIL = "No CLIENT_ID Found";
+ public static final String SVR_CFG_FAIL = "Server Config Error";
+ public static final String OPTION_MISSING_FAIL = "Expected Option missing";
+ public static final String NO_MATCHING_INTF = "No matching Inteface";
+ public static final String NO_CLIENT_INTF_MAC = "No client interface mac";
+ public static final String NO_SERVER_INFO = "No Server info found";
+ public static final String NO_SERVER_IP6ADDR = "No Server ip6 addr found";
+
+ public static final String INVALID_PACKET = "Invalid Packet";
+
+ public static final Set<String> SUPPORTED_COUNTERS =
+ ImmutableSet.of(SOLICIT, ADVERTISE, REQUEST, CONFIRM, RENEW,
+ REBIND, REPLY, RELEASE, DECLINE, RECONFIGURE,
+ INFORMATION_REQUEST, RELAY_FORW, RELAY_REPL,
+ NO_LINKLOCAL_GW, NO_LINKLOCAL_FAIL, NO_CLIENTID_FAIL, SVR_CFG_FAIL, OPTION_MISSING_FAIL,
+ NO_MATCHING_INTF, NO_CLIENT_INTF_MAC, NO_SERVER_INFO, NO_SERVER_IP6ADDR,
+ INVALID_PACKET);
+
+ // TODO Use AtomicInteger for the counters
+ private Map<String, Integer> countersMap = new ConcurrentHashMap<>();
+ public long lastUpdate;
+
+ public void resetCounters() {
+ countersMap.forEach((name, value) -> {
+ countersMap.put(name, 0);
+ });
+ }
+ public boolean incrementCounter(String name) {
+ boolean counterValid = false;
+ if (SUPPORTED_COUNTERS.contains(name)) {
+ Integer counter = countersMap.get(name);
+ if (counter != null) {
+ counter = counter + 1;
+ countersMap.put(name, counter);
+ } else {
+ // this is the first time
+ countersMap.put(name, 1);
+ }
+ lastUpdate = System.currentTimeMillis();
+ counterValid = true;
+ }
+ return counterValid;
+ }
+ public Map<String, Integer> getCounters() {
+ return countersMap;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(countersMap, lastUpdate);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!(obj instanceof DhcpRelayCounters)) {
+ return false;
+ }
+ DhcpRelayCounters that = (DhcpRelayCounters) obj;
+ return Objects.equals(countersMap, that.countersMap) &&
+ Objects.equals(lastUpdate, that.lastUpdate);
+ }
+}
diff --git a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/store/DhcpRelayCountersStore.java b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/store/DhcpRelayCountersStore.java
new file mode 100644
index 0000000..3534871
--- /dev/null
+++ b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/store/DhcpRelayCountersStore.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.dhcprelay.store;
+
+
+import java.util.Optional;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Stores DHCP Relay Counters records.
+ */
+public interface DhcpRelayCountersStore {
+
+ /**
+ * Creates or updates DHCP record for specific host id (mac + vlan).
+ *
+ * @param counterClass class of counters (direct, indirect, global)
+ * @param counterName name of counter
+ */
+ void incrementCounter(String counterClass, String counterName);
+
+ /**
+ * Gets the DHCP counter record for a given counter class.
+ *
+ * @param counterClass the class of counters (direct, indirect, global)
+ * @return the DHCP counter record for a given counter class; empty if record not exists
+ */
+ Optional<DhcpRelayCounters> getCounters(String counterClass);
+
+ /**
+ * Gets all classes of DHCP counters record from store.
+ *
+ * @return all classes of DHCP counters records from store
+ */
+ Set<Map.Entry<String, DhcpRelayCounters>> getAllCounters();
+
+ /**
+ * Resets counter value for a given counter class.
+ *
+ * @param counterClass the class of counters (direct, indirect, global)
+ */
+ void resetCounters(String counterClass);
+
+ /**
+ * Resets counter value for a all counter classes.
+ *
+ */
+ void resetAllCounters();
+
+}
diff --git a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/store/DistributedDhcpRelayCountersStore.java b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/store/DistributedDhcpRelayCountersStore.java
new file mode 100644
index 0000000..4b7b26c
--- /dev/null
+++ b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/store/DistributedDhcpRelayCountersStore.java
@@ -0,0 +1,130 @@
+/*
+ * 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.dhcprelay.store;
+
+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.onlab.util.KryoNamespace;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.store.service.ConsistentMap;
+import org.onosproject.store.service.Serializer;
+import org.onosproject.store.service.StorageService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.onosproject.store.serializers.KryoNamespaces;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import org.onosproject.store.service.Versioned;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+@Component(immediate = true)
+@Service
+public class DistributedDhcpRelayCountersStore implements DhcpRelayCountersStore {
+ private static final KryoNamespace.Builder APP_KYRO = KryoNamespace.newBuilder()
+ .register(KryoNamespaces.API)
+ .register(DhcpRelayCounters.class);
+
+ private Logger log = LoggerFactory.getLogger(getClass());
+ private ConsistentMap<String, DhcpRelayCounters> counters;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected StorageService storageService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected CoreService coreService;
+
+
+ @Activate
+ protected void activated() {
+ ApplicationId appId = coreService.getAppId("org.onosproject.Dhcp6HandlerImpl");
+ counters = storageService.<String, DhcpRelayCounters>consistentMapBuilder()
+ .withSerializer(Serializer.using(APP_KYRO.build()))
+ .withName("Dhcp-Relay-Counters")
+ .withApplicationId(appId)
+ .withPurgeOnUninstall()
+ .build();
+ }
+
+ @Deactivate
+ protected void deactivated() {
+ counters.destroy().join();
+ }
+ @Override
+ public void incrementCounter(String coutnerClass, String counterName) {
+ DhcpRelayCounters countersRecord;
+
+ Versioned<DhcpRelayCounters> vCounters = counters.get(coutnerClass);
+ if (vCounters == null) {
+ countersRecord = new DhcpRelayCounters();
+ } else {
+ countersRecord = vCounters.value();
+ }
+ countersRecord.incrementCounter(counterName);
+ counters.put(coutnerClass, countersRecord);
+ }
+
+ @Override
+ public Set<Map.Entry<String, DhcpRelayCounters>> getAllCounters() {
+ final Set<Map.Entry<String, DhcpRelayCounters>> result =
+ new HashSet<Map.Entry<String, DhcpRelayCounters>>();
+ Set<Map.Entry<String, Versioned<DhcpRelayCounters>>> tmpCounters = counters.entrySet();
+ tmpCounters.forEach(entry -> {
+ String key = entry.getKey();
+ DhcpRelayCounters value = entry.getValue().value();
+ ConcurrentHashMap<String, DhcpRelayCounters> newMap = new ConcurrentHashMap();
+ newMap.put(key, value);
+
+ for (Map.Entry m: newMap.entrySet()) {
+ result.add(m);
+ }
+ });
+ return result;
+ }
+ @Override
+ public Optional<DhcpRelayCounters> getCounters(String counterClass) {
+ DhcpRelayCounters countersRecord;
+ checkNotNull(counterClass, "counter class can't be null");
+ Versioned<DhcpRelayCounters> vCounters = counters.get(counterClass);
+ if (vCounters == null) {
+ return Optional.empty();
+ }
+ return Optional.of(vCounters.value());
+ }
+ @Override
+ public void resetAllCounters() {
+ counters.clear();
+ }
+
+ @Override
+ public void resetCounters(String counterClass) {
+ checkNotNull(counterClass, "counter class can't be null");
+ DhcpRelayCounters countersRecord = counters.get(counterClass).value();
+ countersRecord.resetCounters();
+ counters.put(counterClass, countersRecord);
+ }
+
+}
diff --git a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/store/DistributedDhcpRelayStore.java b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/store/DistributedDhcpRelayStore.java
index 38c0580..884d9cc 100644
--- a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/store/DistributedDhcpRelayStore.java
+++ b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/store/DistributedDhcpRelayStore.java
@@ -52,6 +52,7 @@
.register(DhcpRecord.class)
.register(DHCP.MsgType.class)
.register(DHCP6.MsgType.class)
+ .register(DhcpRelayCounters.class)
.build();
private Logger log = getLogger(getClass());
diff --git a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/store/DistributedFpmPrefixStore.java b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/store/DistributedFpmPrefixStore.java
index b82aac9..bc95d0b 100644
--- a/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/store/DistributedFpmPrefixStore.java
+++ b/apps/dhcprelay/src/main/java/org/onosproject/dhcprelay/store/DistributedFpmPrefixStore.java
@@ -91,7 +91,7 @@
@Override
public void setDelegate(StoreDelegate<FpmPrefixStoreEvent> delegate) {
- checkNotNull("Delegate can't be null", delegate);
+ checkNotNull(delegate, "Delegate can't be null");
this.delegate = delegate;
}
@@ -122,6 +122,7 @@
* @param prefix the route prefix in the advertisement
* @param fpmRecord the route for fpm
**/
+ @Override
public void addFpmRecord(IpPrefix prefix, FpmRecord fpmRecord) {
checkNotNull(prefix, "Prefix can't be null");
checkNotNull(fpmRecord, "Fpm record can't be null");
@@ -134,6 +135,7 @@
* @param prefix the route prefix in the advertisement
* @return none
**/
+ @Override
public Optional<FpmRecord> removeFpmRecord(IpPrefix prefix) {
checkNotNull(prefix, "Prefix can't be null");
return Optional.ofNullable(dhcpFpmRecords.remove(prefix));
diff --git a/apps/dhcprelay/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/apps/dhcprelay/src/main/resources/OSGI-INF/blueprint/shell-config.xml
index b178195..c0a4b6f 100644
--- a/apps/dhcprelay/src/main/resources/OSGI-INF/blueprint/shell-config.xml
+++ b/apps/dhcprelay/src/main/resources/OSGI-INF/blueprint/shell-config.xml
@@ -18,6 +18,10 @@
<command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
<command>
<action class="org.onosproject.dhcprelay.cli.DhcpRelayCommand"/>
+ <completers>
+ <ref component-id="dhcpRelayCounterCompleter"/>
+ <ref component-id="dhcpRelayResetCompleter"/>
+ </completers>
</command>
<command>
<action class="org.onosproject.dhcprelay.cli.DhcpFpmRoutesCommand"/>
@@ -28,5 +32,13 @@
<command>
<action class="org.onosproject.dhcprelay.cli.DhcpFpmDeleteCommand"/>
</command>
+ <command>
+ <action class="org.onosproject.dhcprelay.cli.DhcpRelayAggCountersCommand"/>
+ <completers>
+ <ref component-id="dhcpRelayResetCompleter"/>
+ </completers>
+ </command>
</command-bundle>
+ <bean id="dhcpRelayCounterCompleter" class="org.onosproject.dhcprelay.cli.DhcpRelayCounterCompleter"/>
+ <bean id="dhcpRelayResetCompleter" class="org.onosproject.dhcprelay.cli.DhcpRelayResetCompleter"/>
</blueprint>
diff --git a/apps/dhcprelay/src/test/java/org/onosproject/dhcprelay/DhcpRelayManagerTest.java b/apps/dhcprelay/src/test/java/org/onosproject/dhcprelay/DhcpRelayManagerTest.java
index 74e1379..65518ee 100644
--- a/apps/dhcprelay/src/test/java/org/onosproject/dhcprelay/DhcpRelayManagerTest.java
+++ b/apps/dhcprelay/src/test/java/org/onosproject/dhcprelay/DhcpRelayManagerTest.java
@@ -54,6 +54,13 @@
import org.onlab.packet.dhcp.Dhcp6IaAddressOption;
import org.onlab.packet.dhcp.Dhcp6IaPrefixOption;
import org.onlab.packet.dhcp.Dhcp6Option;
+import org.onlab.packet.dhcp.Dhcp6ClientIdOption;
+import org.onlab.packet.dhcp.Dhcp6Duid;
+import org.onosproject.dhcprelay.store.DhcpRelayStore;
+import org.onosproject.dhcprelay.store.DhcpRecord;
+import org.onosproject.dhcprelay.store.DhcpRelayStoreEvent;
+import org.onosproject.dhcprelay.store.DhcpRelayCounters;
+import org.onosproject.dhcprelay.store.DhcpRelayCountersStore;
import org.onosproject.net.ConnectPoint;
import org.onosproject.TestApplicationId;
import org.onosproject.cfg.ComponentConfigService;
@@ -63,9 +70,6 @@
import org.onosproject.dhcprelay.config.DhcpServerConfig;
import org.onosproject.dhcprelay.config.IgnoreDhcpConfig;
import org.onosproject.dhcprelay.config.IndirectDhcpRelayConfig;
-import org.onosproject.dhcprelay.store.DhcpRecord;
-import org.onosproject.dhcprelay.store.DhcpRelayStore;
-import org.onosproject.dhcprelay.store.DhcpRelayStoreEvent;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.behaviour.Pipeliner;
@@ -253,6 +257,7 @@
private MockPacketService packetService;
private MockRouteStore mockRouteStore;
private MockDhcpRelayStore mockDhcpRelayStore;
+ private MockDhcpRelayCountersStore mockDhcpRelayCountersStore;
private HostProviderService mockHostProviderService;
private FlowObjectiveService flowObjectiveService;
private DeviceService deviceService;
@@ -322,9 +327,11 @@
mockRouteStore = new MockRouteStore();
mockDhcpRelayStore = new MockDhcpRelayStore();
- manager.dhcpRelayStore = mockDhcpRelayStore;
- manager.deviceService = deviceService;
+ mockDhcpRelayCountersStore = new MockDhcpRelayCountersStore();
+ manager.dhcpRelayStore = mockDhcpRelayStore;
+
+ manager.deviceService = deviceService;
manager.interfaceService = new MockInterfaceService();
flowObjectiveService = EasyMock.niceMock(FlowObjectiveService.class);
@@ -344,6 +351,7 @@
v6Handler = new Dhcp6HandlerImpl();
v6Handler.dhcpRelayStore = mockDhcpRelayStore;
+ v6Handler.dhcpRelayCountersStore = mockDhcpRelayCountersStore;
v6Handler.hostService = manager.hostService;
v6Handler.interfaceService = manager.interfaceService;
v6Handler.packetService = manager.packetService;
@@ -358,6 +366,7 @@
// properties
Dictionary<String, Object> dictionary = createNiceMock(Dictionary.class);
expect(dictionary.get("arpEnabled")).andReturn(true).anyTimes();
+ expect(dictionary.get("dhcpPollInterval")).andReturn(120).anyTimes();
ComponentContext context = createNiceMock(ComponentContext.class);
expect(context.getProperties()).andReturn(dictionary).anyTimes();
@@ -1001,6 +1010,48 @@
}
}
+ private class MockDhcpRelayCountersStore implements DhcpRelayCountersStore {
+ private Map<String, DhcpRelayCounters> counters = Maps.newHashMap();
+
+ public void incrementCounter(String coutnerClass, String counterName) {
+ DhcpRelayCounters countersRecord;
+
+ DhcpRelayCounters classCounters = counters.get(coutnerClass);
+ if (classCounters == null) {
+ classCounters = new DhcpRelayCounters();
+ }
+ classCounters.incrementCounter(counterName);
+ counters.put(coutnerClass, classCounters);
+ }
+
+ @Override
+ public Set<Map.Entry<String, DhcpRelayCounters>> getAllCounters() {
+ return counters.entrySet();
+ }
+
+ @Override
+ public Optional<DhcpRelayCounters> getCounters(String counterClass) {
+ DhcpRelayCounters classCounters = counters.get(counterClass);
+ if (classCounters == null) {
+ return Optional.empty();
+ }
+ return Optional.of(classCounters);
+ }
+
+ @Override
+ public void resetAllCounters() {
+ counters.clear();
+ }
+
+ @Override
+ public void resetCounters(String counterClass) {
+ DhcpRelayCounters classCounters = counters.get(counterClass);
+ classCounters.resetCounters();
+ counters.put(counterClass, classCounters);
+ }
+ }
+
+
private class MockPacketService extends PacketServiceAdapter {
Set<PacketProcessor> packetProcessors = Sets.newHashSet();
OutboundPacket emittedPacket;
@@ -1233,6 +1284,14 @@
iaAddressOption.setValidLifetime(1200);
iaAddressOption.setLength((short) Dhcp6IaAddressOption.DEFAULT_LEN);
+ Dhcp6ClientIdOption clientIdOption = new Dhcp6ClientIdOption();
+ Dhcp6Duid dhcp6Duip = new Dhcp6Duid();
+ dhcp6Duip.setDuidType(Dhcp6Duid.DuidType.DUID_LLT);
+ dhcp6Duip.setHardwareType((short) 0x01); // Ethernet
+ dhcp6Duip.setDuidTime(1234);
+ dhcp6Duip.setLinkLayerAddress(CLIENT_MAC.toBytes());
+ clientIdOption.setDuid(dhcp6Duip);
+
Dhcp6IaNaOption iaNaOption = new Dhcp6IaNaOption();
iaNaOption.setCode(DHCP6.OptionCode.IA_NA.value());
iaNaOption.setIaId(0);
@@ -1265,6 +1324,7 @@
dhcp6.setMsgType(msgType);
List<Dhcp6Option> dhcp6Options = new ArrayList<Dhcp6Option>();
dhcp6Options.add(iaNaOption);
+ dhcp6Options.add(clientIdOption);
dhcp6Options.add(iaPdOption);
dhcp6.setOptions(dhcp6Options);
diff --git a/apps/dhcprelay/src/test/java/org/onosproject/dhcprelay/store/DhcpRecordTest.java b/apps/dhcprelay/src/test/java/org/onosproject/dhcprelay/store/DhcpRecordTest.java
index ec6ad5c..7aaf65b 100644
--- a/apps/dhcprelay/src/test/java/org/onosproject/dhcprelay/store/DhcpRecordTest.java
+++ b/apps/dhcprelay/src/test/java/org/onosproject/dhcprelay/store/DhcpRecordTest.java
@@ -86,6 +86,12 @@
TestUtils.setField(record, "lastSeen", 0);
TestUtils.setField(record2, "lastSeen", 0);
+ TestUtils.setField(record, "addrPrefTime", 0);
+ TestUtils.setField(record2, "addrPrefTime", 0);
+ TestUtils.setField(record, "pdPrefTime", 0);
+ TestUtils.setField(record2, "pdPrefTime", 0);
+ TestUtils.setField(record, "v6Counter", null);
+ TestUtils.setField(record2, "v6Counter", null);
assertThat(record, equalTo(record2));
assertThat(record.hashCode(), equalTo(record2.hashCode()));
diff --git a/apps/evpn-route-service/api/src/main/java/org/onosproject/evpnrouteservice/EvpnInstanceRoute.java b/apps/evpn-route-service/api/src/main/java/org/onosproject/evpnrouteservice/EvpnInstanceRoute.java
index 3e98531..ca0c8bd8 100644
--- a/apps/evpn-route-service/api/src/main/java/org/onosproject/evpnrouteservice/EvpnInstanceRoute.java
+++ b/apps/evpn-route-service/api/src/main/java/org/onosproject/evpnrouteservice/EvpnInstanceRoute.java
@@ -198,7 +198,7 @@
EvpnInstanceRoute that = (EvpnInstanceRoute) other;
- return Objects.equals(prefix, prefix)
+ return Objects.equals(prefix, that.prefix)
&& Objects.equals(nextHop, that.nextHop)
&& Objects.equals(evpnName, that.evpnName)
&& Objects.equals(rd, that.rd)
diff --git a/apps/evpn-route-service/api/src/main/java/org/onosproject/evpnrouteservice/EvpnRoute.java b/apps/evpn-route-service/api/src/main/java/org/onosproject/evpnrouteservice/EvpnRoute.java
index 9449093..0f025d3 100644
--- a/apps/evpn-route-service/api/src/main/java/org/onosproject/evpnrouteservice/EvpnRoute.java
+++ b/apps/evpn-route-service/api/src/main/java/org/onosproject/evpnrouteservice/EvpnRoute.java
@@ -115,7 +115,6 @@
checkNotNull(prefixMac);
checkNotNull(prefix);
//checkNotNull(nextHop); //next hop can be null in case of MP un reach.
- checkNotNull(labelToInt);
this.source = checkNotNull(source);
this.prefix = prefix;
this.prefixMac = prefixMac;
@@ -258,7 +257,7 @@
EvpnRoute that = (EvpnRoute) other;
- return Objects.equals(prefixMac, prefixMac)
+ return Objects.equals(prefixMac, that.prefixMac)
&& Objects.equals(prefix, that.prefix)
&& Objects.equals(nextHop, that.nextHop)
&& Objects.equals(this.rd, that.rd)
diff --git a/apps/evpn-route-service/app/src/main/java/org/onosproject/evpnrouteservice/impl/EvpnRouteManager.java b/apps/evpn-route-service/app/src/main/java/org/onosproject/evpnrouteservice/impl/EvpnRouteManager.java
index 19e6311..28abb7d 100644
--- a/apps/evpn-route-service/app/src/main/java/org/onosproject/evpnrouteservice/impl/EvpnRouteManager.java
+++ b/apps/evpn-route-service/app/src/main/java/org/onosproject/evpnrouteservice/impl/EvpnRouteManager.java
@@ -81,7 +81,9 @@
@Deactivate
protected void deactivate() {
evpnRouteStore.unsetDelegate(evpnRouteStoreDelegate);
- listeners.values().forEach(EvpnListenerQueue::stop);
+ synchronized (this) {
+ listeners.values().forEach(EvpnListenerQueue::stop);
+ }
}
/**
@@ -148,6 +150,7 @@
}
+ @Override
public Collection<EvpnRouteTableId> getRouteTables() {
return evpnRouteStore.getRouteTables();
}
diff --git a/apps/evpnopenflow/src/main/java/org/onosproject/evpnopenflow/rsc/vpnport/impl/VpnPortManager.java b/apps/evpnopenflow/src/main/java/org/onosproject/evpnopenflow/rsc/vpnport/impl/VpnPortManager.java
index 18ff172..2babba6 100644
--- a/apps/evpnopenflow/src/main/java/org/onosproject/evpnopenflow/rsc/vpnport/impl/VpnPortManager.java
+++ b/apps/evpnopenflow/src/main/java/org/onosproject/evpnopenflow/rsc/vpnport/impl/VpnPortManager.java
@@ -290,8 +290,6 @@
String cidr = "0.0.0.0/0";
String gatewayIp = "0.0.0.0";
Set<HostRoute> hostRoutes = Sets.newHashSet();
- String ipV6AddressMode = null;
- String ipV6RaMode = null;
TenantNetworkId tenantNetworkId = null;
Set<AllocationPool> allocationPools = Sets.newHashSet();
Iterable<TenantNetwork> networks
@@ -306,11 +304,11 @@
Subnet subnet = new DefaultSubnet(SubnetId.subnetId(id), subnetName,
tenantNetworkId,
tenantId, IpAddress.Version.INET,
- cidr == null ? null : IpPrefix.valueOf(cidr),
- gatewayIp == null ? null : IpAddress.valueOf(gatewayIp),
+ IpPrefix.valueOf(cidr),
+ IpAddress.valueOf(gatewayIp),
false, false, hostRoutes,
- ipV6AddressMode == null ? null : Subnet.Mode.valueOf(ipV6AddressMode),
- ipV6RaMode == null ? null : Subnet.Mode.valueOf(ipV6RaMode),
+ null,
+ null,
allocationPools);
Set<Subnet> subnetsSet = Sets.newHashSet(subnet);
diff --git a/apps/faultmanagement/fmmgr/src/test/java/org/onosproject/faultmanagement/impl/PollingAlarmProviderTest.java b/apps/faultmanagement/fmmgr/src/test/java/org/onosproject/faultmanagement/impl/PollingAlarmProviderTest.java
index b8fa17f..b2f2469 100644
--- a/apps/faultmanagement/fmmgr/src/test/java/org/onosproject/faultmanagement/impl/PollingAlarmProviderTest.java
+++ b/apps/faultmanagement/fmmgr/src/test/java/org/onosproject/faultmanagement/impl/PollingAlarmProviderTest.java
@@ -120,7 +120,7 @@
@Test
public void activate() throws Exception {
- assertFalse("Provider should be registered", providerRegistry.getProviders().contains(provider));
+ assertFalse("Provider should be registered", providerRegistry.getProviders().contains(provider.id()));
assertEquals("Device listener should be added", 1, deviceListeners.size());
assertEquals("Incorrect alarm provider service", alarmProviderService, provider.providerService);
assertEquals("Mastership listener should be added", 1, mastershipListeners.size());
@@ -135,7 +135,7 @@
provider.deactivate();
assertEquals("Device listener should be removed", 0, deviceListeners.size());
assertEquals("Mastership listener should be removed", 0, mastershipListeners.size());
- assertFalse("Provider should not be registered", providerRegistry.getProviders().contains(provider));
+ assertFalse("Provider should not be registered", providerRegistry.getProviders().contains(provider.id()));
assertTrue(provider.alarmsExecutor.isShutdown());
assertNull(provider.providerService);
}
diff --git a/apps/faultmanagement/fmweb/src/test/java/org/onosproject/faultmanagement/web/AlarmsWebResourceTest.java b/apps/faultmanagement/fmweb/src/test/java/org/onosproject/faultmanagement/web/AlarmsWebResourceTest.java
index 94315c7..778c23f 100644
--- a/apps/faultmanagement/fmweb/src/test/java/org/onosproject/faultmanagement/web/AlarmsWebResourceTest.java
+++ b/apps/faultmanagement/fmweb/src/test/java/org/onosproject/faultmanagement/web/AlarmsWebResourceTest.java
@@ -20,7 +20,6 @@
import org.junit.Test;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.TestServiceDirectory;
-import org.onlab.rest.BaseResource;
import org.onosproject.codec.CodecService;
import org.onosproject.codec.impl.CodecManager;
import org.onosproject.rest.resources.ResourceTest;
@@ -48,7 +47,7 @@
// Currently no alarms-service implemented
// .add(AlarmsService.class, alarmsService)
.add(CodecService.class, codecService);
- BaseResource.setServiceDirectory(testDirectory);
+ setServiceDirectory(testDirectory);
}
@Test
diff --git a/apps/gluon/src/main/java/org/onosproject/gluon/rsc/GluonServer.java b/apps/gluon/src/main/java/org/onosproject/gluon/rsc/GluonServer.java
index f4f400e..031ba69 100644
--- a/apps/gluon/src/main/java/org/onosproject/gluon/rsc/GluonServer.java
+++ b/apps/gluon/src/main/java/org/onosproject/gluon/rsc/GluonServer.java
@@ -86,10 +86,10 @@
public class GluonServer {
- private static String protonKeyUri;
- private static String serverUri;
+ private String protonKeyUri;
+ private String serverUri;
- private static CloseableHttpAsyncClient httpClient;
+ private CloseableHttpAsyncClient httpClient;
//store gluon server supported subkeys
private List<String> subKeys = new LinkedList<>();
diff --git a/apps/graphitemetrics/src/test/java/org/onosproject/graphitemetrics/GraphiteMetricsReporterTest.java b/apps/graphitemetrics/src/test/java/org/onosproject/graphitemetrics/GraphiteMetricsReporterTest.java
index 5ecaf28..5036964 100644
--- a/apps/graphitemetrics/src/test/java/org/onosproject/graphitemetrics/GraphiteMetricsReporterTest.java
+++ b/apps/graphitemetrics/src/test/java/org/onosproject/graphitemetrics/GraphiteMetricsReporterTest.java
@@ -49,13 +49,6 @@
}
/**
- * Tears down graphite metrics reporter instance.
- */
- public void tearDown() {
- gmr.deactivate();
- }
-
- /**
* Tests whether the containsName method can always return the correct result
* with the given metric name and a set of prefixes.
*/
diff --git a/apps/influxdbmetrics/src/main/java/org/onosproject/influxdbmetrics/DefaultInfluxMetric.java b/apps/influxdbmetrics/src/main/java/org/onosproject/influxdbmetrics/DefaultInfluxMetric.java
index f3ce81a..bcee522 100644
--- a/apps/influxdbmetrics/src/main/java/org/onosproject/influxdbmetrics/DefaultInfluxMetric.java
+++ b/apps/influxdbmetrics/src/main/java/org/onosproject/influxdbmetrics/DefaultInfluxMetric.java
@@ -67,7 +67,6 @@
@Override
public InfluxMetric build() {
- checkNotNull(oneMinRate, ONE_MIN_RATE_MSG);
checkNotNull(timestamp, TIMESTAMP_MSG);
return new DefaultInfluxMetric(oneMinRate, parseTime(timestamp));
diff --git a/apps/linkprops/src/main/java/org/onosproject/linkprops/LinkPropsTopovMessageHandler.java b/apps/linkprops/src/main/java/org/onosproject/linkprops/LinkPropsTopovMessageHandler.java
index 908c65c..a633ec0 100644
--- a/apps/linkprops/src/main/java/org/onosproject/linkprops/LinkPropsTopovMessageHandler.java
+++ b/apps/linkprops/src/main/java/org/onosproject/linkprops/LinkPropsTopovMessageHandler.java
@@ -248,27 +248,26 @@
*/
private Highlights getBandwidth(Set<Link> links, DeviceId devId) {
LpLinkMap linkMap = new LpLinkMap();
+ Highlights highlights = new Highlights();
if (links != null) {
log.debug("Processing {} links", links.size());
links.forEach(linkMap::add);
+
+ PortNumber portnum = PortNumber.portNumber((int) links.iterator().next().src().port().toLong());
+
+ for (LpLink dlink : linkMap.biLinks()) {
+ DiscreteResourceId parent = Resources.discrete(devId, portnum).id();
+ ContinuousResource continuousResource =
+ (ContinuousResource) resourceQueryService.getAvailableResources(parent,
+ Bandwidth.class).iterator().next();
+ double availBandwidth = continuousResource.value();
+
+ dlink.makeImportant().setLabel(Double.toString(availBandwidth) + " bytes/s");
+ highlights.add(dlink.highlight(null));
+ }
} else {
log.debug("No egress links found for device {}", devId);
}
-
- Highlights highlights = new Highlights();
-
- PortNumber portnum = PortNumber.portNumber((int) links.iterator().next().src().port().toLong());
-
- for (LpLink dlink : linkMap.biLinks()) {
- DiscreteResourceId parent = Resources.discrete(devId, portnum).id();
- ContinuousResource continuousResource =
- (ContinuousResource) resourceQueryService.getAvailableResources(parent,
- Bandwidth.class).iterator().next();
- double availBandwidth = continuousResource.value();
-
- dlink.makeImportant().setLabel(Double.toString(availBandwidth) + " bytes/s");
- highlights.add(dlink.highlight(null));
- }
return highlights;
}
diff --git a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/addresses/UnresolvedExtensionMappingAddress.java b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/addresses/UnresolvedExtensionMappingAddress.java
index a1db59f..3a07879 100644
--- a/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/addresses/UnresolvedExtensionMappingAddress.java
+++ b/apps/mappingmanagement/api/src/main/java/org/onosproject/mapping/addresses/UnresolvedExtensionMappingAddress.java
@@ -18,8 +18,6 @@
import org.onosproject.net.flow.AbstractExtension;
import java.util.Arrays;
-import java.util.Objects;
-
import static com.google.common.base.MoreObjects.toStringHelper;
import static org.onosproject.mapping.addresses.ExtensionMappingAddressType
.ExtensionMappingAddressTypes.UNRESOLVED_TYPE;
@@ -63,7 +61,7 @@
@Override
public int hashCode() {
- return Objects.hash(bytes);
+ return Arrays.hashCode(bytes);
}
@Override
diff --git a/apps/mappingmanagement/web/src/test/java/org/onosproject/mapping/web/MappingsWebResourceTest.java b/apps/mappingmanagement/web/src/test/java/org/onosproject/mapping/web/MappingsWebResourceTest.java
index d2f4c86..4d5f06d 100644
--- a/apps/mappingmanagement/web/src/test/java/org/onosproject/mapping/web/MappingsWebResourceTest.java
+++ b/apps/mappingmanagement/web/src/test/java/org/onosproject/mapping/web/MappingsWebResourceTest.java
@@ -30,7 +30,6 @@
import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.TestServiceDirectory;
import org.onlab.packet.IpPrefix;
-import org.onlab.rest.BaseResource;
import org.onosproject.codec.CodecService;
import org.onosproject.codec.impl.CodecManager;
import org.onosproject.mapping.DefaultMappingKey;
@@ -278,7 +277,7 @@
.add(DeviceService.class, mockDeviceService)
.add(CodecService.class, codecService);
- BaseResource.setServiceDirectory(testDirectory);
+ setServiceDirectory(testDirectory);
}
/**
diff --git a/apps/netconf/client/pom.xml b/apps/netconf/client/pom.xml
index e37a3c5..eba0375 100644
--- a/apps/netconf/client/pom.xml
+++ b/apps/netconf/client/pom.xml
@@ -125,18 +125,6 @@
</dependencies>
<build>
- <pluginManagement>
- <plugins>
-
- <plugin>
- <groupId>org.apache.karaf.tooling</groupId>
- <artifactId>karaf-maven-plugin</artifactId>
- <version>3.0.5</version>
- <extensions>true</extensions>
- </plugin>
-
- </plugins>
- </pluginManagement>
<plugins>
<plugin>
diff --git a/apps/netconf/client/src/main/java/org/onosproject/netconf/client/EventData.java b/apps/netconf/client/src/main/java/org/onosproject/netconf/client/EventData.java
deleted file mode 100644
index 0dce327..0000000
--- a/apps/netconf/client/src/main/java/org/onosproject/netconf/client/EventData.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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.netconf.client;
-
-import org.onosproject.config.DynamicConfigEvent;
-import org.onosproject.net.DeviceId;
-import org.onosproject.yang.model.ResourceId;
-
-
-/**
- * Event details.
- */
-public class EventData {
-
- private DeviceId devId;
- private ResourceId key;
- private DynamicConfigEvent.Type type;
-
- /**
- * Creates an instance of EventData.
- *
- * @param devId device id
- * @param key device key
- * @param type event type
- */
- public EventData(DeviceId devId, ResourceId key, DynamicConfigEvent.Type type) {
- devId = devId;
- key = key;
- type = type;
- }
-
- public DeviceId getDevId() {
- return devId;
- }
-
- public ResourceId getKey() {
- return key;
- }
-
- public DynamicConfigEvent.Type getType() {
- return type;
- }
-}
\ No newline at end of file
diff --git a/apps/ofagent/src/test/java/org/onosproject/ofagent/rest/OFAgentWebResourceTest.java b/apps/ofagent/src/test/java/org/onosproject/ofagent/rest/OFAgentWebResourceTest.java
index 74e2c4a..32eb857 100644
--- a/apps/ofagent/src/test/java/org/onosproject/ofagent/rest/OFAgentWebResourceTest.java
+++ b/apps/ofagent/src/test/java/org/onosproject/ofagent/rest/OFAgentWebResourceTest.java
@@ -27,7 +27,6 @@
import org.onlab.osgi.TestServiceDirectory;
import org.onlab.packet.IpAddress;
import org.onlab.packet.TpPort;
-import org.onlab.rest.BaseResource;
import org.onosproject.incubator.net.virtual.NetworkId;
import org.onosproject.incubator.net.virtual.TenantId;
import org.onosproject.ofagent.api.OFAgent;
@@ -141,7 +140,7 @@
ServiceDirectory testDirectory = new TestServiceDirectory()
.add(OFAgentAdminService.class, mockOFAgentAdminService)
.add(OFAgentService.class, mockOFAgentService);
- BaseResource.setServiceDirectory(testDirectory);
+ setServiceDirectory(testDirectory);
}
/**
diff --git a/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/impl/RulePopulatorUtil.java b/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/impl/RulePopulatorUtil.java
index 07a808d..5dbf7a7 100644
--- a/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/impl/RulePopulatorUtil.java
+++ b/apps/openstacknetworking/src/main/java/org/onosproject/openstacknetworking/impl/RulePopulatorUtil.java
@@ -98,6 +98,10 @@
return null;
}
+ if (device == null) {
+ return null;
+ }
+
ExtensionTreatmentResolver resolver = device.as(ExtensionTreatmentResolver.class);
ExtensionTreatment treatment = resolver.getExtensionInstruction(NICIRA_SET_TUNNEL_DST.type());
try {
diff --git a/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/impl/DefaultOpenstackNodeHandler.java b/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/impl/DefaultOpenstackNodeHandler.java
index e1da821..625d41d 100644
--- a/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/impl/DefaultOpenstackNodeHandler.java
+++ b/apps/openstacknode/app/src/main/java/org/onosproject/openstacknode/impl/DefaultOpenstackNodeHandler.java
@@ -474,6 +474,10 @@
return null;
}
+ if (device == null) {
+ return null;
+ }
+
ExtensionTreatmentResolver resolver = device.as(ExtensionTreatmentResolver.class);
ExtensionTreatment treatment = resolver.getExtensionInstruction(NICIRA_SET_TUNNEL_DST.type());
try {
diff --git a/apps/optical-model/src/main/java/org/onosproject/net/optical/config/OpticalPortOperator.java b/apps/optical-model/src/main/java/org/onosproject/net/optical/config/OpticalPortOperator.java
index f9ee752..ee5ac99 100644
--- a/apps/optical-model/src/main/java/org/onosproject/net/optical/config/OpticalPortOperator.java
+++ b/apps/optical-model/src/main/java/org/onosproject/net/optical/config/OpticalPortOperator.java
@@ -93,7 +93,7 @@
}
OpticalPortConfig opc = lookupConfig(cp);
- if (opc == null) {
+ if (descr == null || opc == null) {
return descr;
}
diff --git a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PceManager.java b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PceManager.java
index 47c369c..d1e3d66 100644
--- a/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PceManager.java
+++ b/apps/pce/app/src/main/java/org/onosproject/pce/pceservice/PceManager.java
@@ -398,7 +398,7 @@
//Log.info("computeExplicitPath :: finalComputedPath " + finalComputedPath);
if (finalComputedPath != null && !finalComputedPath.get(finalComputedPath.size() - 1).links()
- .contains((Link) info.value())) {
+ .contains(info.value())) {
finalComputedPath = null;
}
}
@@ -610,10 +610,7 @@
return false;
}
- DisjointPath path = null;
- if (!paths.isEmpty()) {
- path = paths.iterator().next();
- }
+ DisjointPath path = paths.iterator().next();
Builder annotationBuilder = DefaultAnnotations.builder();
double bw = 0;
@@ -916,7 +913,6 @@
private boolean releaseSharedBwForNewTunnel(Path computedPath, double bandwidthConstraint,
SharedBandwidthConstraint shBwConstraint) {
checkNotNull(computedPath);
- checkNotNull(bandwidthConstraint);
double bwToAllocate;
Double additionalBwValue = null;
@@ -1074,7 +1070,6 @@
private boolean reserveBandwidth(Path computedPath, double bandwidthConstraint,
SharedBandwidthConstraint shBwConstraint) {
checkNotNull(computedPath);
- checkNotNull(bandwidthConstraint);
Resource resource = null;
double bwToAllocate = 0;
Map<Link, Double> linkMap = new HashMap<>();
diff --git a/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/DefaultPcePathTest.java b/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/DefaultPcePathTest.java
index 4b9d0b9..9d95e44 100644
--- a/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/DefaultPcePathTest.java
+++ b/apps/pce/app/src/test/java/org/onosproject/pce/pceservice/DefaultPcePathTest.java
@@ -17,21 +17,8 @@
package org.onosproject.pce.pceservice;
import com.google.common.collect.Lists;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.is;
-import static org.onosproject.pce.pceservice.PathComputationTest.D2;
-import static org.easymock.EasyMock.createMock;
-
import com.google.common.testing.EqualsTester;
-
-import org.onlab.osgi.ServiceDirectory;
-import org.onlab.osgi.TestServiceDirectory;
-import org.onlab.rest.BaseResource;
+import org.junit.Test;
import org.onosproject.incubator.net.tunnel.TunnelId;
import org.onosproject.pce.pceservice.constraint.CostConstraint;
import org.onosproject.pce.pceservice.constraint.PceBandwidthConstraint;
@@ -39,23 +26,17 @@
import java.util.List;
+import static org.easymock.EasyMock.createMock;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.onosproject.pce.pceservice.PathComputationTest.D2;
+
/**
* Unit tests for DefaultPcePath class.
*/
public class DefaultPcePathTest {
private PceStore pceStore = createMock(PceStore.class);
- @Before
- public void setup() {
-
- ServiceDirectory testDirectory = new TestServiceDirectory()
- .add(PceStore.class, pceStore);
- BaseResource.setServiceDirectory(testDirectory);
- }
-
- @After
- public void tearDownTest() {
- }
/**
* Checks the operation of equals() methods.
*/
diff --git a/apps/pce/pcerest/src/test/java/org/onosproject/pcerest/PcePathResourceTest.java b/apps/pce/pcerest/src/test/java/org/onosproject/pcerest/PcePathResourceTest.java
index ae05d7e..51f5c2d 100644
--- a/apps/pce/pcerest/src/test/java/org/onosproject/pcerest/PcePathResourceTest.java
+++ b/apps/pce/pcerest/src/test/java/org/onosproject/pcerest/PcePathResourceTest.java
@@ -44,6 +44,7 @@
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.onlab.junit.TestUtils;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.TestServiceDirectory;
import org.onlab.packet.IpAddress;
@@ -109,7 +110,7 @@
.add(TunnelService.class, tunnelService)
.add(PceStore.class, pceStore)
.add(CodecService.class, context.codecManager());
- BaseResource.setServiceDirectory(testDirectory);
+ TestUtils.setField(BaseResource.class, "services", testDirectory);
// Tunnel creation
// Links
diff --git a/apps/pce/pceweb/src/main/java/org/onosproject/pceweb/PceWebTopovMessageHandler.java b/apps/pce/pceweb/src/main/java/org/onosproject/pceweb/PceWebTopovMessageHandler.java
index a1a9a25..4306f61 100644
--- a/apps/pce/pceweb/src/main/java/org/onosproject/pceweb/PceWebTopovMessageHandler.java
+++ b/apps/pce/pceweb/src/main/java/org/onosproject/pceweb/PceWebTopovMessageHandler.java
@@ -772,7 +772,7 @@
private void findTunnelAndHighlights() {
Collection<Tunnel> tunnelSet = null;
Highlights highlights = new Highlights();
- paths.removeAll(paths);
+ paths.clear();
tunnelSet = tunnelService.queryTunnel(MPLS);
if (tunnelSet.size() == 0) {
log.warn("Tunnel does not exist");
@@ -819,7 +819,7 @@
*/
private void highlightsForTunnel(List<Tunnel> tunnels) {
Highlights highlights = new Highlights();
- paths.removeAll(paths);
+ paths.clear();
if (tunnels.isEmpty()) {
log.error("path does not exist");
diff --git a/apps/reactive-routing/src/main/java/org/onosproject/reactive/routing/SdnIpReactiveRouting.java b/apps/reactive-routing/src/main/java/org/onosproject/reactive/routing/SdnIpReactiveRouting.java
index 5b6ad9c..906e34d 100644
--- a/apps/reactive-routing/src/main/java/org/onosproject/reactive/routing/SdnIpReactiveRouting.java
+++ b/apps/reactive-routing/src/main/java/org/onosproject/reactive/routing/SdnIpReactiveRouting.java
@@ -263,8 +263,10 @@
case HOST_TO_INTERNET:
// If the destination IP address is outside the local SDN network.
// The Step 1 has already handled it. We do not need to do anything here.
- intentRequestListener.setUpConnectivityHostToInternet(srcIpAddress,
- ipPrefix, route.nextHop());
+ if (route != null) {
+ intentRequestListener.setUpConnectivityHostToInternet(srcIpAddress,
+ ipPrefix, route.nextHop());
+ }
break;
case INTERNET_TO_HOST:
intentRequestListener.setUpConnectivityInternetToHost(dstIpAddress);
diff --git a/apps/restconf/api/BUCK b/apps/restconf/api/BUCK
index b54f53c..39a3872 100644
--- a/apps/restconf/api/BUCK
+++ b/apps/restconf/api/BUCK
@@ -6,6 +6,11 @@
'//lib:jersey-server',
]
+TEST_DEPS = [
+ '//lib:TEST_REST',
+]
+
osgi_jar_with_tests (
deps = COMPILE_DEPS,
+ test_deps = TEST_DEPS,
)
diff --git a/apps/restconf/api/pom.xml b/apps/restconf/api/pom.xml
index cadd950..9bc8fea 100644
--- a/apps/restconf/api/pom.xml
+++ b/apps/restconf/api/pom.xml
@@ -47,6 +47,11 @@
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onlab-junit</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
diff --git a/apps/restconf/api/src/main/java/org/onosproject/restconf/api/RestconfError.java b/apps/restconf/api/src/main/java/org/onosproject/restconf/api/RestconfError.java
new file mode 100644
index 0000000..61c7144
--- /dev/null
+++ b/apps/restconf/api/src/main/java/org/onosproject/restconf/api/RestconfError.java
@@ -0,0 +1,332 @@
+/*
+ * 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.restconf.api;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+import java.util.List;
+
+/**
+ * Restconf error structured as in "ietf-restconf@2017-01-26.yang".
+ * An entry containing information about one specific error that occurred while
+ * processing a RESTCONF request.
+ */
+public final class RestconfError {
+ private final ErrorType errorType;
+ private final ErrorTag errorTag;
+ private String errorAppTag;
+ private String errorPath;
+ private String errorMessage;
+ private String errorInfo;
+
+ private RestconfError(ErrorType errorType, ErrorTag errorTag) {
+ this.errorType = errorType;
+ this.errorTag = errorTag;
+ }
+
+ /**
+ * The protocol layer where the error occurred.
+ * @return The error type
+ */
+ public ErrorType getErrorType() {
+ return errorType;
+ }
+
+ /**
+ * The enumerated error-tag.
+ * @return The enumerated error-tag
+ */
+ public ErrorTag getErrorTag() {
+ return errorTag;
+ }
+
+ /**
+ * The application-specific error-tag.
+ * @return The application-specific error-tag
+ */
+ public String getErrorAppTag() {
+ return errorAppTag;
+ }
+
+ /**
+ * The YANG instance identifier associated with the error node.
+ * @return A yang instance represented in XPath
+ */
+ public String getErrorPath() {
+ return errorPath;
+ }
+
+ /**
+ * A message describing the error.
+ * @return A message describing the error
+ */
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ /**
+ * A container with zero or more data nodes representing additional error information.
+ * @return A string serialization of datanodes e.g. a stack trace
+ */
+ public String getErrorInfo() {
+ return errorInfo;
+ }
+
+ /**
+ * Convert the restconf error to Json - this is for one error - many may be included in a response.
+ * @return A JSON object containing the details of one error
+ */
+ public ObjectNode toJson() {
+ ObjectMapper mapper = new ObjectMapper();
+ ObjectNode errorTags = (ObjectNode) mapper.createObjectNode();
+ errorTags.put("error-type", errorType.name().toLowerCase());
+ errorTags.put("error-tag", errorTag.text());
+
+ if (errorAppTag != null) {
+ errorTags.put("error-app-tag", errorAppTag);
+ }
+
+ if (errorPath != null) {
+ errorTags.put("error-path", errorPath);
+ }
+
+ if (errorMessage != null) {
+ errorTags.put("error-message", errorMessage);
+ }
+
+ if (errorInfo != null) {
+ errorTags.put("error-info", errorInfo);
+ }
+
+ ObjectNode errorNode = (ObjectNode) mapper.createObjectNode();
+ errorNode.put("error", errorTags);
+ return errorNode;
+ }
+
+ /**
+ * An enumerated set of the protocol layer involved in a RESTCONF request.
+ */
+ public enum ErrorType {
+ //The transport layer
+ TRANSPORT,
+ //The rpc or notification layer
+ RPC,
+ //The protocol operation layer
+ PROTOCOL,
+ //The server application layer
+ APPLICATION
+ }
+
+ /**
+ * An enumerated set of error 'tags' - consistent labels for error causes.
+ * See <a href="https://tools.ietf.org/html/rfc8040#section-7">Section 7 of RFC 8040</a>
+ * for a list of HTTP status codes associated with these
+ * error tags. Developers should ensure that suitable HTTP status codes are used
+ * when raising RESTCONF errors
+ */
+ public enum ErrorTag {
+ /**
+ * Use with Response 409 {@link javax.ws.rs.core.Response.Status#CONFLICT}.
+ */
+ IN_USE("in-use"),
+ /**
+ * Use with Response 400 {@link javax.ws.rs.core.Response.Status#BAD_REQUEST},
+ * 404 {@link javax.ws.rs.core.Response.Status#NOT_FOUND} or
+ * 406 {@link javax.ws.rs.core.Response.Status#NOT_ACCEPTABLE}.
+ */
+ INVALID_VALUE("invalid-value"),
+ /**
+ * Use with Response 413 {@link javax.ws.rs.core.Response.Status#REQUEST_ENTITY_TOO_LARGE}.
+ */
+ REQUEST_TOO_BIG("too-big"),
+ /**
+ * Use with Response 400 {@link javax.ws.rs.core.Response.Status#BAD_REQUEST}.
+ */
+ RESPONSE_TOO_BIG("too-big"),
+ /**
+ * Use with Response 400 {@link javax.ws.rs.core.Response.Status#BAD_REQUEST}.
+ */
+ MISSING_ATTRIBUTE("missing-attribute"),
+ /**
+ * Use with Response 400 {@link javax.ws.rs.core.Response.Status#BAD_REQUEST}.
+ */
+ BAD_ATTRIBUTE("bad-attribute"),
+ /**
+ * Use with Response 400 {@link javax.ws.rs.core.Response.Status#BAD_REQUEST}.
+ */
+ UNKNOWN_ATTRIBUTE("unknown-attribute"),
+ /**
+ * Use with Response 400 {@link javax.ws.rs.core.Response.Status#BAD_REQUEST}.
+ */
+ BAD_ELEMENT("bad-element"),
+ /**
+ * Use with Response 400 {@link javax.ws.rs.core.Response.Status#BAD_REQUEST}.
+ */
+ UNKNOWN_ELEMENT("unknown-element"),
+ /**
+ * Use with Response 400 {@link javax.ws.rs.core.Response.Status#BAD_REQUEST}.
+ */
+ UNKNOWN_NAMESPACE("unknown-namespace"),
+ /**
+ * Use with Response 401 {@link javax.ws.rs.core.Response.Status#UNAUTHORIZED},
+ * or 403 {@link javax.ws.rs.core.Response.Status#FORBIDDEN}.
+ */
+ ACCESS_DENIED("access-denied"),
+ /**
+ * Use with Response 409 {@link javax.ws.rs.core.Response.Status#CONFLICT}.
+ */
+ LOCK_DENIED("lock-denied"),
+ /**
+ * Use with Response 409 {@link javax.ws.rs.core.Response.Status#CONFLICT}.
+ */
+ RESOURCE_DENIED("resource-denied"),
+ /**
+ * Use with Response 500 {@link javax.ws.rs.core.Response.Status#INTERNAL_SERVER_ERROR}.
+ */
+ ROLLBACK_FAILED("rollback-failed"),
+ /**
+ * Use with Response 409 {@link javax.ws.rs.core.Response.Status#CONFLICT}.
+ */
+ DATA_EXISTS("data-exists"),
+ /**
+ * Use with Response 409 {@link javax.ws.rs.core.Response.Status#CONFLICT}.
+ */
+ DATA_MISSING("data-missing"),
+ /**
+ * Use with Response 405 {@link javax.ws.rs.core.Response.Status#METHOD_NOT_ALLOWED},
+ * or 501 {@link javax.ws.rs.core.Response.Status#NOT_IMPLEMENTED}.
+ */
+ OPERATION_NOT_SUPPORTED("operation-not-supported"),
+ /**
+ * Use with Response 412 {@link javax.ws.rs.core.Response.Status#PRECONDITION_FAILED},
+ * or 500 {@link javax.ws.rs.core.Response.Status#INTERNAL_SERVER_ERROR}.
+ */
+ OPERATION_FAILED("operation-failed"),
+ /**
+ * Use with Response 500 {@link javax.ws.rs.core.Response.Status#INTERNAL_SERVER_ERROR}.
+ */
+ PARTIAL_OPERATION("partial-operation"),
+ /**
+ * Use with Response 400 {@link javax.ws.rs.core.Response.Status#BAD_REQUEST}.
+ */
+ MALFORMED_MESSAGE("malformed-message");
+
+ private String text;
+
+ ErrorTag(String text) {
+ this.text = text;
+ }
+
+ /**
+ * Lowercase version of the error tag compliant with the standard.
+ * @return the associated lowercase version
+ */
+ public String text() {
+ return text;
+ }
+ }
+
+ /**
+ * Build a new RestconfError. ErrorTag and ErrorType are mandatory parameters.
+ * @param errorType The error type
+ * @param errorTag The error Tag
+ * @return A build which an be used to create the RestconfError
+ */
+ public static RestconfError.Builder builder(ErrorType errorType, ErrorTag errorTag) {
+ return new Builder(errorType, errorTag);
+ }
+
+ /**
+ * Create the complete JSON representation of the errors for the Response.
+ * Note this can contain many individual RestconfErrors
+ * @param restconfErrors A list of {@link RestconfError}s
+ * @return A JSON node which can be used in a response
+ */
+ public static ObjectNode wrapErrorAsJson(List<RestconfError> restconfErrors) {
+ ObjectMapper mapper = new ObjectMapper();
+ ArrayNode errorArray = mapper.createArrayNode();
+ restconfErrors.forEach(error -> errorArray.add(error.toJson()));
+ ObjectNode errorsNode = (ObjectNode) mapper.createObjectNode();
+ errorsNode.put("ietf-restconf:errors", errorArray);
+ return errorsNode;
+ }
+
+ /**
+ * A builder for the Restconf Error. ErrorTag and ErrorType are mandatory parameters.
+ */
+ public static final class Builder {
+ private RestconfError restconfError;
+
+ /**
+ * ErrorTag and ErrorType are mandatory parameters of the error.
+ * @param errorType The error-type
+ * @param errorTag The error-tag
+ */
+ private Builder(ErrorType errorType, ErrorTag errorTag) {
+ restconfError = new RestconfError(errorType, errorTag);
+ }
+
+ /**
+ * Set an error-app-tag on the error.
+ * @param errorAppTag a tag relevant to the error in the application
+ * @return The builder
+ */
+ public Builder errorAppTag(String errorAppTag) {
+ this.restconfError.errorAppTag = errorAppTag;
+ return this;
+ }
+
+ /**
+ * Set an error-path on the error.
+ * @param errorPath A path to the resource that caused the error
+ * @return The builder
+ */
+ public Builder errorPath(String errorPath) {
+ this.restconfError.errorPath = errorPath;
+ return this;
+ }
+
+ /**
+ * Set an error-message on the error.
+ * @param errorMessage an explaination of the error
+ * @return The builder
+ */
+ public Builder errorMessage(String errorMessage) {
+ this.restconfError.errorMessage = errorMessage;
+ return this;
+ }
+
+ /**
+ * Set an error-info on the error.
+ * @param errorInfo Any additional infor about the error
+ * @return The builder
+ */
+ public Builder errorInfo(String errorInfo) {
+ this.restconfError.errorInfo = errorInfo;
+ return this;
+ }
+
+ /**
+ * Build the contents of the builder in to a {@link RestconfError}.
+ * @return A RestconfError
+ */
+ public RestconfError build() {
+ return restconfError;
+ }
+ }
+}
diff --git a/apps/restconf/api/src/main/java/org/onosproject/restconf/api/RestconfException.java b/apps/restconf/api/src/main/java/org/onosproject/restconf/api/RestconfException.java
index 8f12b7f..459531f 100644
--- a/apps/restconf/api/src/main/java/org/onosproject/restconf/api/RestconfException.java
+++ b/apps/restconf/api/src/main/java/org/onosproject/restconf/api/RestconfException.java
@@ -15,53 +15,123 @@
*/
package org.onosproject.restconf.api;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
+import java.util.ArrayList;
+import java.util.Optional;
+
import static javax.ws.rs.core.Response.Status;
/**
- * Exceptions raised during RESTCONF operations. This class extends
- * WebApplicationException. The design intention is to create a place holder
- * for RESTCONF specific errors and to be able to add more functions as the
- * subsystem grows.
+ * Exceptions raised during RESTCONF operations. This class extends WebApplicationException.
+ * To comply with the RESTCONF specification on error handling, the parameters given
+ * when creating this exception will be used to create one
+ * {@link org.onosproject.restconf.api.RestconfError}. Additional
+ * {@link org.onosproject.restconf.api.RestconfError}s may be added subsequently.
+ * This exception should be converted to a Json object using the toRestconfError()
+ * method before being passed back to the caller in a response
*/
public class RestconfException extends WebApplicationException {
// This is a randomly generated value. A WebApplicationException class is required to define it.
- private static final long SERIAL_VERSION_UID = 3275970397584007046L;
+ private static final long SERIAL_VERSION_UID = 1275970654684007046L;
+
+ private ArrayList<RestconfError> restconfErrors = new ArrayList<>();
/**
- * Constructs a new RESTCONF server error exception. The caller raising this
- * exception may pass in a HTTP error status code and an error message. The
- * error code will be displayed to the RESTCONF client as part of the
- * response from the RESTCONF server. The error message is a string which
- * may be saved in a log file and may be later retrieved by the
- * getMessage() method.
+ * Constructs a new RESTCONF server error exception based of an existing exception.
+ * The caller raising this exception may pass in a HTTP error status code
+ * and an error message. The error code will be displayed to the RESTCONF
+ * client as part of the response from the RESTCONF server. The error message
+ * is a string which may be saved in a log file and may be later retrieved by
+ * the getMessage() method. The parameters given will be formed in to a
+ * {@link org.onosproject.restconf.api.RestconfError}. Additional errors may be
+ * added after construction.
*
* @param message the detailed error message
- * @param status HTTP error status
+ * @param throwable The existing exception that caused this response.
+ * The message from this exception will be used as error-info
+ * @param errorTag A Restconf Error tag
+ * @param status HTTP error status. Developers are asked to ensure that the correct one for the error-tag is used
+ * @param errorPath An optional path that gives the item that caused the exception
* @throws IllegalArgumentException in case the status code is null or is not from
* javax.ws.rs.core.Response.Status.Family
* status code family
*/
- public RestconfException(String message, Status status) {
- super(message, null, Response.status(status).build());
+ public RestconfException(String message, Throwable throwable,
+ RestconfError.ErrorTag errorTag, Status status,
+ Optional<String> errorPath) {
+ super(message, throwable, Response.status(status).build());
+ RestconfError.Builder bldr = RestconfError
+ .builder(RestconfError.ErrorType.APPLICATION, errorTag)
+ .errorMessage(message);
+ if (throwable != null) {
+ bldr.errorInfo(throwable.getMessage());
+ }
+ if (errorPath.isPresent()) {
+ bldr.errorPath(errorPath.get());
+ }
+ addToErrors(bldr.build());
}
/**
- * Constructs a new RESTCONF server error exception. The caller raising
- * this exception may pass in the numerical value of a HTTP error
- * status code, The error code will be displayed to the RESTCONF client
- * as a response from the RESTCONF server.
+ * Constructs a new RESTCONF server error exception.
+ * The caller raising this exception may pass in a HTTP error status code
+ * and an error message. The error code will be displayed to the RESTCONF
+ * client as part of the response from the RESTCONF server. The error message
+ * is a string which may be saved in a log file and may be later retrieved by
+ * the getMessage() method. The parameters given will be formed in to a
+ * {@link org.onosproject.restconf.api.RestconfError}. Additional errors may be
+ * added after construction.
*
- * @param status HTTP error status
- * @throws IllegalArgumentException in case the status code is not a valid
- * HTTP status code or if it is not from the
+ * @param message the detailed error message
+ * @param errorTag A Restconf Error tag
+ * @param status HTTP error status. Developers are asked to ensure that the correct one for the error-tag is used
+ * @param errorPath An optional path that gives the item that caused the exception
+ * @param errorInfo An optional string with more info about the error
+ * @throws IllegalArgumentException in case the status code is null or is not from
* javax.ws.rs.core.Response.Status.Family
* status code family
*/
- public RestconfException(int status) {
- super((Throwable) null, Response.status(status).build());
+ public RestconfException(String message, RestconfError.ErrorTag errorTag,
+ Status status, Optional<String> errorPath,
+ Optional<String> errorInfo) {
+ super(message, null, Response.status(status).build());
+ RestconfError.Builder bldr = RestconfError
+ .builder(RestconfError.ErrorType.APPLICATION, errorTag)
+ .errorMessage(message);
+ if (errorInfo.isPresent()) {
+ bldr.errorInfo(errorInfo.get());
+ }
+ if (errorPath.isPresent()) {
+ bldr.errorPath(errorPath.get());
+ }
+ addToErrors(bldr.build());
+ }
+
+ /**
+ * Allows additional RestconfErrors to be added to the exception.
+ * @param restconfError An additional RestconfError to be added to the response
+ */
+ public void addToErrors(RestconfError restconfError) {
+ restconfErrors.add(restconfError);
+ }
+
+ /**
+ * Convert the RestconfException and all of its RestconfErrors in to a Json object.
+ * @return A json node generated from the RestconfException
+ */
+ public ObjectNode toRestconfErrorJson() {
+ ObjectMapper mapper = new ObjectMapper();
+ ArrayNode errorArray = mapper.createArrayNode();
+ restconfErrors.forEach(error -> errorArray.add(error.toJson()));
+ ObjectNode errorsNode = (ObjectNode) mapper.createObjectNode();
+ errorsNode.put("ietf-restconf:errors", errorArray);
+ return errorsNode;
}
}
diff --git a/apps/restconf/api/src/main/java/org/onosproject/restconf/api/RestconfService.java b/apps/restconf/api/src/main/java/org/onosproject/restconf/api/RestconfService.java
index 9f3ba53..9a12bd6 100644
--- a/apps/restconf/api/src/main/java/org/onosproject/restconf/api/RestconfService.java
+++ b/apps/restconf/api/src/main/java/org/onosproject/restconf/api/RestconfService.java
@@ -23,7 +23,7 @@
/**
* Abstraction of RESTCONF Server functionality according to the
- * RESTCONF RFC (no official RFC number yet).
+ * RESTCONF RFC 8040.
*/
public interface RestconfService {
/**
diff --git a/apps/restconf/api/src/test/java/org/onosproject/restconf/api/RestconfExceptionTest.java b/apps/restconf/api/src/test/java/org/onosproject/restconf/api/RestconfExceptionTest.java
new file mode 100644
index 0000000..c9a1d04
--- /dev/null
+++ b/apps/restconf/api/src/test/java/org/onosproject/restconf/api/RestconfExceptionTest.java
@@ -0,0 +1,113 @@
+/*
+ * 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.restconf.api;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.junit.Test;
+
+import javax.ws.rs.core.Response;
+
+import java.util.Arrays;
+import java.util.Optional;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test the conversion of RestconfErrors in to JSON.
+ */
+public class RestconfExceptionTest {
+
+ private RestconfError error1 = RestconfError
+ .builder(RestconfError.ErrorType.TRANSPORT, RestconfError.ErrorTag.ACCESS_DENIED)
+ .build();
+
+ private RestconfError error2 = RestconfError
+ .builder(RestconfError.ErrorType.TRANSPORT, RestconfError.ErrorTag.BAD_ATTRIBUTE)
+ .build();
+
+ private RestconfError error3 = RestconfError
+ .builder(RestconfError.ErrorType.RPC, RestconfError.ErrorTag.BAD_ELEMENT)
+ .errorAppTag("my-app-tag")
+ .errorMessage("a message about the error")
+ .errorPath("/a/b/c")
+ .errorInfo("info about the error")
+ .build();
+
+ /**
+ * Test a Restconf Exception with many RestconfErrors converted to Json.
+ */
+ @Test
+ public void testToRestconfErrorJson() {
+ IllegalArgumentException ie = new IllegalArgumentException("This is a test");
+ RestconfException e = new RestconfException("Error in system", ie,
+ RestconfError.ErrorTag.DATA_EXISTS, Response.Status.BAD_REQUEST,
+ Optional.of("/some/path"));
+ e.addToErrors(error1);
+ e.addToErrors(error2);
+ e.addToErrors(error3);
+
+ assertEquals("{\"ietf-restconf:errors\":[" +
+ "{\"error\":{" +
+ "\"error-type\":\"application\"," +
+ "\"error-tag\":\"data-exists\"," +
+ "\"error-path\":\"/some/path\"," +
+ "\"error-message\":\"Error in system\"," +
+ "\"error-info\":\"This is a test\"}}," +
+ "{\"error\":{" +
+ "\"error-type\":\"transport\"," +
+ "\"error-tag\":\"access-denied\"}}," +
+ "{\"error\":{" +
+ "\"error-type\":\"transport\"," +
+ "\"error-tag\":\"bad-attribute\"}}," +
+ "{\"error\":{" +
+ "\"error-type\":\"rpc\"," +
+ "\"error-tag\":\"bad-element\"," +
+ "\"error-app-tag\":\"my-app-tag\"," +
+ "\"error-path\":\"/a/b/c\"," +
+ "\"error-message\":\"a message about the error\"," +
+ "\"error-info\":\"info about the error\"}}]}",
+ e.toRestconfErrorJson().toString());
+ }
+
+ @Test
+ public void testWrappingErrorsNotInException() {
+ RestconfError error4 = RestconfError
+ .builder(RestconfError.ErrorType.TRANSPORT, RestconfError.ErrorTag.UNKNOWN_ELEMENT)
+ .build();
+
+ ObjectNode json = RestconfError.wrapErrorAsJson(Arrays.asList(error4, error1, error2, error3));
+
+ assertEquals("{\"ietf-restconf:errors\":[" +
+ "{\"error\":{" +
+ "\"error-type\":\"transport\"," +
+ "\"error-tag\":\"unknown-element\"}}," +
+ "{\"error\":{" +
+ "\"error-type\":\"transport\"," +
+ "\"error-tag\":\"access-denied\"}}," +
+ "{\"error\":{" +
+ "\"error-type\":\"transport\"," +
+ "\"error-tag\":\"bad-attribute\"}}," +
+ "{\"error\":{" +
+ "\"error-type\":\"rpc\"," +
+ "\"error-tag\":\"bad-element\"," +
+ "\"error-app-tag\":\"my-app-tag\"," +
+ "\"error-path\":\"/a/b/c\"," +
+ "\"error-message\":\"a message about the error\"," +
+ "\"error-info\":\"info about the error\"}}]}",
+ json.toString());
+
+ }
+}
diff --git a/apps/restconf/restconfmgr/src/main/java/org/onosproject/restconf/restconfmanager/RestconfManager.java b/apps/restconf/restconfmgr/src/main/java/org/onosproject/restconf/restconfmanager/RestconfManager.java
index 5334cd0..0ad6b25 100644
--- a/apps/restconf/restconfmgr/src/main/java/org/onosproject/restconf/restconfmanager/RestconfManager.java
+++ b/apps/restconf/restconfmgr/src/main/java/org/onosproject/restconf/restconfmanager/RestconfManager.java
@@ -28,6 +28,7 @@
import org.onosproject.config.DynamicConfigService;
import org.onosproject.config.FailedException;
import org.onosproject.config.Filter;
+import org.onosproject.restconf.api.RestconfError;
import org.onosproject.restconf.api.RestconfException;
import org.onosproject.restconf.api.RestconfRpcOutput;
import org.onosproject.restconf.api.RestconfService;
@@ -46,13 +47,17 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import javax.ws.rs.core.Response;
import java.net.URI;
+import java.util.Arrays;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
+import static javax.ws.rs.core.Response.Status.CONFLICT;
import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR;
import static org.onosproject.d.config.ResourceIds.parentOf;
import static org.onosproject.restconf.utils.RestconfUtils.convertDataNodeToJson;
@@ -119,8 +124,9 @@
dataNode = dynamicConfigService.readNode(rl.ridForDynConfig(), filter);
} catch (FailedException e) {
log.error("ERROR: DynamicConfigService: ", e);
- throw new RestconfException("ERROR: DynamicConfigService",
- INTERNAL_SERVER_ERROR);
+ throw new RestconfException("ERROR: DynamicConfigService", e,
+ RestconfError.ErrorTag.OPERATION_FAILED, INTERNAL_SERVER_ERROR,
+ Optional.of(uri.getPath()));
}
ObjectNode rootNode = convertDataNodeToJson(rl.ridForYangRuntime(), dataNode);
return rootNode;
@@ -146,9 +152,16 @@
try {
dynamicConfigService.createNode(rl.ridForDynConfig(), dataNode);
} catch (FailedException e) {
- log.error("ERROR: DynamicConfigService: ", e);
- throw new RestconfException("ERROR: DynamicConfigService",
- INTERNAL_SERVER_ERROR);
+ if (e.getMessage().startsWith("Requested node already present")) {
+ throw new RestconfException("Already exists", e,
+ RestconfError.ErrorTag.DATA_EXISTS, CONFLICT,
+ Optional.of(uri.getPath()));
+ } else {
+ log.error("ERROR: DynamicConfigService: ", e);
+ throw new RestconfException("ERROR: DynamicConfigService", e,
+ RestconfError.ErrorTag.OPERATION_FAILED, INTERNAL_SERVER_ERROR,
+ Optional.of(uri.getPath()));
+ }
}
}
@@ -176,8 +189,9 @@
} catch (FailedException e) {
log.error("ERROR: DynamicConfigService: ", e);
- throw new RestconfException("ERROR: DynamicConfigService",
- INTERNAL_SERVER_ERROR);
+ throw new RestconfException("ERROR: DynamicConfigService", e,
+ RestconfError.ErrorTag.OPERATION_FAILED, INTERNAL_SERVER_ERROR,
+ Optional.of(uri.getPath()));
}
}
@@ -191,8 +205,9 @@
}
} catch (FailedException e) {
log.error("ERROR: DynamicConfigService: ", e);
- throw new RestconfException("ERROR: DynamicConfigService",
- INTERNAL_SERVER_ERROR);
+ throw new RestconfException("ERROR: DynamicConfigService", e,
+ RestconfError.ErrorTag.OPERATION_FAILED, INTERNAL_SERVER_ERROR,
+ Optional.of(uri.getPath()));
}
}
@@ -217,8 +232,9 @@
dynamicConfigService.updateNode(parentOf(rl.ridForDynConfig()), dataNode);
} catch (FailedException e) {
log.error("ERROR: DynamicConfigService: ", e);
- throw new RestconfException("ERROR: DynamicConfigService",
- INTERNAL_SERVER_ERROR);
+ throw new RestconfException("ERROR: DynamicConfigService", e,
+ RestconfError.ErrorTag.OPERATION_FAILED, INTERNAL_SERVER_ERROR,
+ Optional.of(uri.getPath()));
}
}
@@ -240,6 +256,10 @@
ChunkedOutput<String> output)
throws RestconfException {
//TODO: to be completed
+ throw new RestconfException("Not implemented",
+ RestconfError.ErrorTag.OPERATION_NOT_SUPPORTED,
+ Response.Status.NOT_IMPLEMENTED,
+ Optional.empty(), Optional.of("subscribeEventStream not yet implemented"));
}
@Override
@@ -267,12 +287,26 @@
} catch (InterruptedException e) {
log.error("ERROR: computeResultQ.take() has been interrupted.");
log.debug("executeRpc Exception:", e);
- restconfOutput = new RestconfRpcOutput(INTERNAL_SERVER_ERROR, null);
+ RestconfError error =
+ RestconfError.builder(RestconfError.ErrorType.RPC,
+ RestconfError.ErrorTag.OPERATION_FAILED)
+ .errorMessage("RPC execution has been interrupted")
+ .errorPath(uri.getPath())
+ .build();
+ restconfOutput = new RestconfRpcOutput(INTERNAL_SERVER_ERROR,
+ RestconfError.wrapErrorAsJson(Arrays.asList(error)));
restconfOutput.reason("RPC execution has been interrupted");
} catch (Exception e) {
log.error("ERROR: executeRpc: {}", e.getMessage());
log.debug("executeRpc Exception:", e);
- restconfOutput = new RestconfRpcOutput(INTERNAL_SERVER_ERROR, null);
+ RestconfError error =
+ RestconfError.builder(RestconfError.ErrorType.RPC,
+ RestconfError.ErrorTag.OPERATION_FAILED)
+ .errorMessage(e.getMessage())
+ .errorPath(uri.getPath())
+ .build();
+ restconfOutput = new RestconfRpcOutput(INTERNAL_SERVER_ERROR,
+ RestconfError.wrapErrorAsJson(Arrays.asList(error)));
restconfOutput.reason(e.getMessage());
}
@@ -312,7 +346,8 @@
}
parentId = rid.copyBuilder().removeLastKey().build();
} catch (CloneNotSupportedException e) {
- e.printStackTrace();
+ log.error("getDataForStore()", e);
+ return null;
}
ResourceData.Builder resData = DefaultResourceData.builder();
resData.addDataNode(dbr.build());
diff --git a/apps/restconf/utils/src/main/java/org/onosproject/restconf/utils/RestconfUtils.java b/apps/restconf/utils/src/main/java/org/onosproject/restconf/utils/RestconfUtils.java
index cd0b428..41fcf39 100644
--- a/apps/restconf/utils/src/main/java/org/onosproject/restconf/utils/RestconfUtils.java
+++ b/apps/restconf/utils/src/main/java/org/onosproject/restconf/utils/RestconfUtils.java
@@ -20,9 +20,9 @@
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.commons.io.IOUtils;
import org.onlab.osgi.DefaultServiceDirectory;
+import org.onosproject.restconf.api.RestconfError;
import org.onosproject.restconf.api.RestconfException;
import org.onosproject.restconf.api.RestconfRpcOutput;
-import org.onosproject.restconf.utils.exceptions.RestconfUtilsException;
import org.onosproject.yang.model.DataNode;
import org.onosproject.yang.model.DefaultResourceData;
import org.onosproject.yang.model.ResourceData;
@@ -43,13 +43,9 @@
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
+import java.util.Optional;
-import static javax.ws.rs.core.Response.Status.BAD_REQUEST;
-import static javax.ws.rs.core.Response.Status.EXPECTATION_FAILED;
-import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR;
-import static javax.ws.rs.core.Response.Status.NO_CONTENT;
-import static javax.ws.rs.core.Response.Status.OK;
-import static javax.ws.rs.core.Response.Status.REQUEST_TIMEOUT;
+import static javax.ws.rs.core.Response.Status.*;
/**
* Utilities used by the RESTCONF app.
@@ -84,7 +80,9 @@
try {
rootNode = (ObjectNode) mapper.readTree(inputStream);
} catch (IOException e) {
- throw new RestconfUtilsException("ERROR: InputStream failed to parse");
+ throw new RestconfException("ERROR: InputStream failed to parse",
+ e, RestconfError.ErrorTag.OPERATION_FAILED, INTERNAL_SERVER_ERROR,
+ Optional.empty());
}
return rootNode;
}
@@ -101,7 +99,9 @@
try {
inputStream = IOUtils.toInputStream(json);
} catch (Exception e) {
- throw new RestconfUtilsException("ERROR: Json Node failed to parse");
+ throw new RestconfException("ERROR: Json Node failed to parse", e,
+ RestconfError.ErrorTag.MALFORMED_MESSAGE, BAD_REQUEST,
+ Optional.empty());
}
return inputStream;
}
@@ -142,13 +142,19 @@
// CompositeStream --- YangRuntimeService ---> CompositeData.
CompositeData compositeData = YANG_RUNTIME.decode(compositeStream, context);
resourceData = compositeData.resourceData();
+ } catch (RestconfException ex) {
+ throw ex;
} catch (Exception ex) {
log.error("convertJsonToDataNode failure: {}", ex.getMessage());
log.debug("convertJsonToDataNode failure", ex);
+ throw new RestconfException("ERROR: JSON cannot be converted to DataNode",
+ ex, RestconfError.ErrorTag.OPERATION_FAILED, INTERNAL_SERVER_ERROR,
+ Optional.of(uri.getPath()));
}
if (resourceData == null) {
throw new RestconfException("ERROR: JSON cannot be converted to DataNode",
- INTERNAL_SERVER_ERROR);
+ RestconfError.ErrorTag.DATA_MISSING, CONFLICT,
+ Optional.of(uri.getPath()), Optional.empty());
}
return resourceData;
}
@@ -193,7 +199,8 @@
}
if (rootNode == null) {
throw new RestconfException("ERROR: InputStream can not be convert to ObjectNode",
- INTERNAL_SERVER_ERROR);
+ null, RestconfError.ErrorTag.DATA_MISSING, CONFLICT,
+ Optional.empty());
}
return rootNode;
}
diff --git a/apps/restconf/utils/src/main/java/org/onosproject/restconf/utils/exceptions/RestconfUtilsException.java b/apps/restconf/utils/src/main/java/org/onosproject/restconf/utils/exceptions/RestconfUtilsException.java
deleted file mode 100644
index b0db098..0000000
--- a/apps/restconf/utils/src/main/java/org/onosproject/restconf/utils/exceptions/RestconfUtilsException.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.restconf.utils.exceptions;
-
-/**
- * Represents class of errors related to RESTCONF utilities.
- */
-public class RestconfUtilsException extends RuntimeException {
-
- /**
- * Constructs an exception with the specified message.
- *
- * @param message the message describing the specific nature of the error
- */
- public RestconfUtilsException(String message) {
- super(message);
- }
-
- /**
- * Constructs an exception with the specified message and the underlying
- * cause.
- *
- * @param message the message describing the specific nature of the error
- * @param cause the underlying cause of this error
- */
- public RestconfUtilsException(String message, Throwable cause) {
- super(message, cause);
- }
-}
diff --git a/apps/route-service/app/src/main/java/org/onosproject/routeservice/impl/RouteManager.java b/apps/route-service/app/src/main/java/org/onosproject/routeservice/impl/RouteManager.java
index 8914a1e..0dc5dbe 100644
--- a/apps/route-service/app/src/main/java/org/onosproject/routeservice/impl/RouteManager.java
+++ b/apps/route-service/app/src/main/java/org/onosproject/routeservice/impl/RouteManager.java
@@ -113,7 +113,9 @@
@Deactivate
protected void deactivate() {
routeMonitor.shutdown();
- listeners.values().forEach(ListenerQueue::stop);
+ synchronized (this) {
+ listeners.values().forEach(ListenerQueue::stop);
+ }
routeStore.unsetDelegate(delegate);
hostService.removeListener(hostListener);
@@ -176,6 +178,7 @@
return routeSets.stream().flatMap(r -> r.routes().stream()).collect(Collectors.toList());
}
+ @Override
public Collection<RouteTableId> getRouteTables() {
return routeStore.getRouteTables();
}
diff --git a/apps/routeradvertisement/src/main/java/org/onosproject/ra/RouterAdvertisementManager.java b/apps/routeradvertisement/src/main/java/org/onosproject/ra/RouterAdvertisementManager.java
index 5f31bdf..9f10728 100644
--- a/apps/routeradvertisement/src/main/java/org/onosproject/ra/RouterAdvertisementManager.java
+++ b/apps/routeradvertisement/src/main/java/org/onosproject/ra/RouterAdvertisementManager.java
@@ -160,14 +160,17 @@
private final Map<ConnectPoint, Map.Entry<ScheduledFuture<?>, List<InterfaceIpAddress>>> transmitters =
new LinkedHashMap<>();
+ // TODO: should consider using concurrent variants
@GuardedBy(value = "this")
private final Map<DeviceId, List<InterfaceIpAddress>> globalPrefixes = new LinkedHashMap<>();
@Override
- public ImmutableMap<DeviceId, List<InterfaceIpAddress>> getGlobalPrefixes() {
+ public synchronized ImmutableMap<DeviceId, List<InterfaceIpAddress>> getGlobalPrefixes() {
return ImmutableMap.copyOf(globalPrefixes);
}
+ @SuppressWarnings("GuardedBy")
+ @GuardedBy(value = "this")
private Function<Interface, Map.Entry<ConnectPoint, List<InterfaceIpAddress>>> prefixGenerator =
i -> {
Map.Entry<ConnectPoint, List<InterfaceIpAddress>> prefixEntry;
@@ -282,6 +285,7 @@
clearThreadPool();
}
+ @SuppressWarnings("GuardedBy")
// Loading global prefixes for devices from network configuration
private synchronized void loadGlobalPrefixConfig() {
globalPrefixes.clear();
@@ -507,6 +511,7 @@
solicitHostAddress = ipv6Address;
}
+ @Override
public void run() {
// Router Advertisement header filling. Please refer RFC-2461.
RouterAdvertisement ra = new RouterAdvertisement();
diff --git a/apps/routing-api/src/main/java/org/onosproject/routing/RouterInfo.java b/apps/routing-api/src/main/java/org/onosproject/routing/RouterInfo.java
index 99a6af4..6f2347f 100644
--- a/apps/routing-api/src/main/java/org/onosproject/routing/RouterInfo.java
+++ b/apps/routing-api/src/main/java/org/onosproject/routing/RouterInfo.java
@@ -43,7 +43,7 @@
*/
public RouterInfo(ConnectPoint controlPlaneConnectPoint, boolean ospfEnabled, Set<String> interfaces) {
this.controlPlaneConnectPoint = checkNotNull(controlPlaneConnectPoint);
- this.ospfEnabled = checkNotNull(ospfEnabled);
+ this.ospfEnabled = ospfEnabled;
this.interfaces = ImmutableSet.copyOf(checkNotNull(interfaces));
}
diff --git a/apps/routing/fpm/app/src/main/java/org/onosproject/routing/fpm/FpmManager.java b/apps/routing/fpm/app/src/main/java/org/onosproject/routing/fpm/FpmManager.java
index dbe58fe..0cf9935 100644
--- a/apps/routing/fpm/app/src/main/java/org/onosproject/routing/fpm/FpmManager.java
+++ b/apps/routing/fpm/app/src/main/java/org/onosproject/routing/fpm/FpmManager.java
@@ -362,6 +362,24 @@
}
}
+ private boolean routeInDhcpStore(IpPrefix prefix) {
+
+ if (dhcpStore != null) {
+ Collection<FpmRecord> dhcpRecords = dhcpStore.getFpmRecords();
+ return dhcpRecords.stream().anyMatch(record -> record.ipPrefix().equals(prefix));
+ }
+ return false;
+ }
+
+ private boolean routeInRipStore(IpPrefix prefix) {
+
+ if (ripStore != null) {
+ Collection<FpmRecord> ripRecords = ripStore.getFpmRecords();
+ return ripRecords.stream().anyMatch(record -> record.ipPrefix().equals(prefix));
+ }
+ return false;
+ }
+
private void fpmMessage(FpmPeer peer, FpmHeader fpmMessage) {
if (fpmMessage.type() == FpmHeader.FPM_TYPE_KEEPALIVE) {
return;
@@ -400,6 +418,14 @@
IpPrefix prefix = IpPrefix.valueOf(dstAddress, rtNetlink.dstLength());
+ // Ignore routes that we sent.
+ if (gateway != null && ((prefix.isIp4() && (gateway.equals(pdPushNextHopIPv4))) ||
+ gateway.equals(pdPushNextHopIPv6))) {
+ if (routeInDhcpStore(prefix) || routeInRipStore(prefix)) {
+ return;
+ }
+ }
+
List<Route> updates = new LinkedList<>();
List<Route> withdraws = new LinkedList<>();
diff --git a/apps/routing/fpm/app/src/main/java/org/onosproject/routing/fpm/cli/FpmConnectionsList.java b/apps/routing/fpm/app/src/main/java/org/onosproject/routing/fpm/cli/FpmConnectionsList.java
index 33ff5d6..f55f00e 100644
--- a/apps/routing/fpm/app/src/main/java/org/onosproject/routing/fpm/cli/FpmConnectionsList.java
+++ b/apps/routing/fpm/app/src/main/java/org/onosproject/routing/fpm/cli/FpmConnectionsList.java
@@ -41,9 +41,8 @@
protected void execute() {
FpmInfoService fpmInfo = get(FpmInfoService.class);
- if (fpmInfo.isPdPushEnabled()) {
- print("PD Pushing is enabled/disbled.");
- }
+ print(String.format("PD Pushing is %s.", fpmInfo.isPdPushEnabled() ? "enabled" : "disabled"));
+
fpmInfo.peers().entrySet().stream()
.sorted(Comparator.<Map.Entry<FpmPeer, FpmPeerInfo>, IpAddress>comparing(e -> e.getKey().address())
.thenComparing(e -> e.getKey().port()))
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
index 8b240e6..fd57f09 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/DefaultRoutingHandler.java
@@ -161,8 +161,8 @@
// Route path handling
//////////////////////////////////////
- /* The following three methods represent the three major ways in routing
- * is triggered in the network
+ /* The following three methods represent the three major ways in which
+ * route-path handling is triggered in the network
* a) due to configuration change
* b) due to route-added event
* c) due to change in the topology
@@ -416,11 +416,11 @@
routeChanges = computeRouteChange();
// deal with linkUp of a seen-before link
- if (linkUp != null && srManager.isSeenLink(linkUp)) {
- if (!srManager.isBidirectional(linkUp)) {
+ if (linkUp != null && srManager.linkHandler.isSeenLink(linkUp)) {
+ if (!srManager.linkHandler.isBidirectional(linkUp)) {
log.warn("Not a bidirectional link yet .. not "
+ "processing link {}", linkUp);
- srManager.updateSeenLink(linkUp, true);
+ srManager.linkHandler.updateSeenLink(linkUp, true);
populationStatus = Status.ABORTED;
return;
}
@@ -436,7 +436,7 @@
// now that we are past the check for a previously seen link
// it is safe to update the store for the linkUp
if (linkUp != null) {
- srManager.updateSeenLink(linkUp, true);
+ srManager.linkHandler.updateSeenLink(linkUp, true);
}
//deal with switchDown
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/EcmpShortestPathGraph.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/EcmpShortestPathGraph.java
index 202a564..49bf80f 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/EcmpShortestPathGraph.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/EcmpShortestPathGraph.java
@@ -74,7 +74,7 @@
currDistance = distanceQueue.poll();
for (Link link : srManager.linkService.getDeviceEgressLinks(sw)) {
- if (srManager.avoidLink(link)) {
+ if (srManager.linkHandler.avoidLink(link)) {
continue;
}
DeviceId reachedDevice = link.dst().deviceId();
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/HostHandler.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/HostHandler.java
index 1379e79..908a339 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/HostHandler.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/HostHandler.java
@@ -42,6 +42,7 @@
import com.google.common.collect.Sets;
+import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.Executors;
@@ -88,6 +89,14 @@
private void processHostAdded(Host host) {
host.locations().forEach(location -> processHostAddedAtLocation(host, location));
+ // ensure dual-homed host locations have viable uplinks
+ if (host.locations().size() > 1) {
+ host.locations().forEach(loc -> {
+ if (srManager.mastershipService.isLocalMaster(loc.deviceId())) {
+ srManager.linkHandler.checkUplinksForDualHomedHosts(loc);
+ }
+ });
+ }
}
void processHostAddedAtLocation(Host host, HostLocation location) {
@@ -276,6 +285,15 @@
hostVlanId, ip, false)
);
});
+
+ // ensure dual-homed host locations have viable uplinks
+ if (newLocations.size() > prevLocations.size()) {
+ newLocations.forEach(loc -> {
+ if (srManager.mastershipService.isLocalMaster(loc.deviceId())) {
+ srManager.linkHandler.checkUplinksForDualHomedHosts(loc);
+ }
+ });
+ }
}
void processHostUpdatedEvent(HostEvent event) {
@@ -640,4 +658,23 @@
});
}));
}
+
+ /**
+ * Returns the set of portnumbers on the given device that are part of the
+ * locations for dual-homed hosts.
+ *
+ * @param deviceId the given deviceId
+ * @return set of port numbers on given device that are dual-homed host
+ * locations. May be empty if no dual homed hosts are connected to
+ * the given device
+ */
+ Set<PortNumber> getDualHomedHostPorts(DeviceId deviceId) {
+ Set<PortNumber> dualHomedLocations = new HashSet<>();
+ srManager.hostService.getConnectedHosts(deviceId).stream()
+ .filter(host -> host.locations().size() == 2)
+ .forEach(host -> host.locations().stream()
+ .filter(loc -> loc.deviceId().equals(deviceId))
+ .forEach(loc -> dualHomedLocations.add(loc.port())));
+ return dualHomedLocations;
+ }
}
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/LinkHandler.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/LinkHandler.java
new file mode 100644
index 0000000..ef9fb38
--- /dev/null
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/LinkHandler.java
@@ -0,0 +1,563 @@
+/*
+ * Copyright 2018-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.segmentrouting;
+
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.HostLocation;
+import org.onosproject.net.Link;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.link.LinkService;
+import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
+import org.onosproject.segmentrouting.config.DeviceConfiguration;
+import org.onosproject.segmentrouting.grouphandler.DefaultGroupHandler;
+import org.onosproject.store.service.EventuallyConsistentMap;
+import org.onosproject.store.service.EventuallyConsistentMapBuilder;
+import org.onosproject.store.service.WallClockTimestamp;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Sets;
+
+public class LinkHandler {
+ private static final Logger log = LoggerFactory.getLogger(LinkHandler.class);
+ protected final SegmentRoutingManager srManager;
+ protected LinkService linkService;
+
+ // Local store for all links seen and their present status, used for
+ // optimized routing. The existence of the link in the keys is enough to
+ // know
+ // if the link has been "seen-before" by this instance of the controller.
+ // The boolean value indicates if the link is currently up or not.
+ // XXX Currently the optimized routing logic depends on "forgetting" a link
+ // when a switch goes down, but "remembering" it when only the link goes
+ // down.
+ // Consider changing this logic so we can use the Link Service instead of
+ // a local cache.
+ private Map<Link, Boolean> seenLinks = new ConcurrentHashMap<>();
+
+ private EventuallyConsistentMap<DeviceId, Set<PortNumber>> downedPortStore = null;
+
+ /**
+ * Constructs the LinkHandler.
+ *
+ * @param srManager Segment Routing manager
+ */
+ LinkHandler(SegmentRoutingManager srManager) {
+ this.srManager = srManager;
+ linkService = srManager.linkService;
+ log.debug("Creating EC map downedportstore");
+ EventuallyConsistentMapBuilder<DeviceId, Set<PortNumber>> downedPortsMapBuilder
+ = srManager.storageService.eventuallyConsistentMapBuilder();
+ downedPortStore = downedPortsMapBuilder.withName("downedportstore")
+ .withSerializer(srManager.createSerializer())
+ .withTimestampProvider((k, v) -> new WallClockTimestamp())
+ .build();
+ log.trace("Current size {}", downedPortStore.size());
+ }
+
+ /**
+ * Constructs the LinkHandler for unit-testing.
+ *
+ * @param srManager SegmentRoutingManager
+ * @param linkService LinkService
+ */
+ LinkHandler(SegmentRoutingManager srManager, LinkService linkService) {
+ this.srManager = srManager;
+ this.linkService = linkService;
+ }
+
+ /**
+ * Preprocessing of added link before being sent for route-path handling.
+ * Also performs post processing of link.
+ *
+ * @param link the link to be processed
+ */
+ void processLinkAdded(Link link) {
+ log.info("** LINK ADDED {}", link.toString());
+ if (!isLinkValid(link)) {
+ return;
+ }
+ if (!srManager.deviceConfiguration
+ .isConfigured(link.src().deviceId())) {
+ updateSeenLink(link, true);
+ // XXX revisit - what about devicePortMap
+ log.warn("Source device of this link is not configured.. "
+ + "not processing further");
+ return;
+ }
+
+ // Irrespective of whether the local is a MASTER or not for this device,
+ // create group handler instance and push default TTP flow rules if
+ // needed,
+ // as in a multi-instance setup, instances can initiate groups for any
+ // device.
+ DefaultGroupHandler groupHandler = srManager.groupHandlerMap
+ .get(link.src().deviceId());
+ if (groupHandler != null) {
+ groupHandler.portUpForLink(link);
+ } else {
+ // XXX revisit/cleanup
+ Device device = srManager.deviceService.getDevice(link.src().deviceId());
+ if (device != null) {
+ log.warn("processLinkAdded: Link Added "
+ + "Notification without Device Added "
+ + "event, still handling it");
+ srManager.processDeviceAdded(device);
+ groupHandler = srManager.groupHandlerMap.get(link.src().deviceId());
+ groupHandler.portUpForLink(link);
+ }
+ }
+
+ /*
+ // process link only if it is bidirectional
+ if (!isBidirectional(link)) {
+ log.debug("Link not bidirectional.. waiting for other direction " +
+ "src {} --> dst {} ", link.dst(), link.src());
+ // note that if we are not processing for routing, it should at least
+ // be considered a seen-link
+ updateSeenLink(link, true); return;
+ }
+ //TODO ensure that rehash is still done correctly even if link is not processed for
+ //rerouting - perhaps rehash in both directions when it ultimately becomes bidi?
+ */
+
+ log.debug("Starting optimized route-path processing for added link "
+ + "{} --> {}", link.src(), link.dst());
+ boolean seenBefore = isSeenLink(link);
+ // seenLink updates will be done after route-path changes
+ srManager.defaultRoutingHandler
+ .populateRoutingRulesForLinkStatusChange(null, link, null);
+
+ if (srManager.mastershipService.isLocalMaster(link.src().deviceId())) {
+ // handle edge-ports for dual-homed hosts
+ updateDualHomedHostPorts(link, true);
+
+ // It's possible that linkUp causes no route-path change as ECMP
+ // graph does
+ // not change if the link is a parallel link (same src-dst as
+ // another link.
+ // However we still need to update ECMP hash groups to include new
+ // buckets
+ // for the link that has come up.
+ if (groupHandler != null) {
+ if (!seenBefore && isParallelLink(link)) {
+ // if link seen first time, we need to ensure hash-groups have
+ // all ports
+ log.debug("Attempting retryHash for paralled first-time link {}",
+ link);
+ groupHandler.retryHash(link, false, true);
+ } else {
+ // seen before-link
+ if (isParallelLink(link)) {
+ log.debug("Attempting retryHash for paralled seen-before "
+ + "link {}", link);
+ groupHandler.retryHash(link, false, false);
+ }
+ }
+ }
+ }
+
+ srManager.mcastHandler.init();
+ }
+
+ /**
+ * Preprocessing of removed link before being sent for route-path handling.
+ * Also performs post processing of link.
+ *
+ * @param link the link to be processed
+ */
+ void processLinkRemoved(Link link) {
+ log.info("** LINK REMOVED {}", link.toString());
+ if (!isLinkValid(link)) {
+ return;
+ }
+ // when removing links, update seen links first, before doing route-path
+ // changes
+ updateSeenLink(link, false);
+
+ // device availability check helps to ensure that multiple link-removed
+ // events are actually treated as a single switch removed event.
+ // purgeSeenLink is necessary so we do rerouting (instead of rehashing)
+ // when switch comes back.
+ if (link.src().elementId() instanceof DeviceId
+ && !srManager.deviceService.isAvailable(link.src().deviceId())) {
+ purgeSeenLink(link);
+ return;
+ }
+ if (link.dst().elementId() instanceof DeviceId
+ && !srManager.deviceService.isAvailable(link.dst().deviceId())) {
+ purgeSeenLink(link);
+ return;
+ }
+
+ // handle edge-ports for dual-homed hosts
+ if (srManager.mastershipService.isLocalMaster(link.src().deviceId())) {
+ updateDualHomedHostPorts(link, false);
+ }
+
+ log.debug("Starting optimized route-path processing for removed link "
+ + "{} --> {}", link.src(), link.dst());
+ srManager.defaultRoutingHandler
+ .populateRoutingRulesForLinkStatusChange(link, null, null);
+
+ // update local groupHandler stores
+ DefaultGroupHandler groupHandler = srManager.groupHandlerMap
+ .get(link.src().deviceId());
+ if (groupHandler != null) {
+ if (srManager.mastershipService.isLocalMaster(link.src().deviceId())
+ && isParallelLink(link)) {
+ log.debug("* retrying hash for parallel link removed:{}", link);
+ groupHandler.retryHash(link, true, false);
+ } else {
+ log.debug("Not attempting retry-hash for link removed: {} .. {}",
+ link,
+ (srManager.mastershipService.isLocalMaster(link.src()
+ .deviceId())) ? "not parallel"
+ : "not master");
+ }
+ // ensure local stores are updated
+ groupHandler.portDown(link.src().port());
+ } else {
+ log.warn("group handler not found for dev:{} when removing link: {}",
+ link.src().deviceId(), link);
+ }
+
+ srManager.mcastHandler.processLinkDown(link);
+ }
+
+ /**
+ * Checks validity of link. Examples of invalid links include
+ * indirect-links, links between ports on the same switch, and more.
+ *
+ * @param link the link to be processed
+ * @return true if valid link
+ */
+ private boolean isLinkValid(Link link) {
+ if (link.type() != Link.Type.DIRECT) {
+ // NOTE: A DIRECT link might be transiently marked as INDIRECT
+ // if BDDP is received before LLDP. We can safely ignore that
+ // until the LLDP is received and the link is marked as DIRECT.
+ log.info("Ignore link {}->{}. Link type is {} instead of DIRECT.",
+ link.src(), link.dst(), link.type());
+ return false;
+ }
+ DeviceId srcId = link.src().deviceId();
+ DeviceId dstId = link.dst().deviceId();
+ if (srcId.equals(dstId)) {
+ log.warn("Links between ports on the same switch are not "
+ + "allowed .. ignoring link {}", link);
+ return false;
+ }
+ DeviceConfiguration devConfig = srManager.deviceConfiguration;
+ try {
+ if (!devConfig.isEdgeDevice(srcId)
+ && !devConfig.isEdgeDevice(dstId)) {
+ // ignore links between spines
+ // XXX revisit when handling multi-stage fabrics
+ log.warn("Links between spines not allowed...ignoring "
+ + "link {}", link);
+ return false;
+ }
+ if (devConfig.isEdgeDevice(srcId)
+ && devConfig.isEdgeDevice(dstId)) {
+ // ignore links between leaves if they are not pair-links
+ // XXX revisit if removing pair-link config or allowing more than
+ // one pair-link
+ if (devConfig.getPairDeviceId(srcId).equals(dstId)
+ && devConfig.getPairLocalPort(srcId)
+ .equals(link.src().port())
+ && devConfig.getPairLocalPort(dstId)
+ .equals(link.dst().port())) {
+ // found pair link - allow it
+ return true;
+ } else {
+ log.warn("Links between leaves other than pair-links are "
+ + "not allowed...ignoring link {}", link);
+ return false;
+ }
+ }
+ } catch (DeviceConfigNotFoundException e) {
+ // We still want to count the links in seenLinks even though there
+ // is no config. So we let it return true
+ log.warn("Could not check validity of link {} as subtending devices "
+ + "are not yet configured", link);
+ }
+ return true;
+ }
+
+ /**
+ * Administratively enables or disables edge ports if the link that was
+ * added or removed was the only uplink port from an edge device. Only edge
+ * ports that belong to dual-homed hosts are considered.
+ *
+ * @param link the link to be processed
+ * @param added true if link was added, false if link was removed
+ */
+ private void updateDualHomedHostPorts(Link link, boolean added) {
+ if (!lastUplink(link)) {
+ return;
+ }
+ if (added) {
+ // re-enable previously disabled ports on this dev
+ Set<PortNumber> p = downedPortStore.remove(link.src().deviceId());
+ if (p != null) {
+ log.warn("Link src {} -->dst {} added is the first uplink, "
+ + "enabling dual homed ports: {}", link.src().deviceId(),
+ link.dst().deviceId(), (p.isEmpty()) ? "no ports" : p);
+ p.forEach(pnum -> srManager.deviceAdminService
+ .changePortState(link.src().deviceId(), pnum, true));
+ }
+ } else {
+ // find dual homed hosts on this dev to disable
+ Set<PortNumber> dhp = srManager.hostHandler
+ .getDualHomedHostPorts(link.src().deviceId());
+ log.warn("Link src {} -->dst {} removed was the last uplink, "
+ + "disabling dual homed ports: {}", link.src().deviceId(),
+ link.dst().deviceId(), (dhp.isEmpty()) ? "no ports" : dhp);
+ dhp.forEach(pnum -> srManager.deviceAdminService
+ .changePortState(link.src().deviceId(), pnum, false));
+ if (!dhp.isEmpty()) {
+ // update global store
+ Set<PortNumber> p = downedPortStore.get(link.src().deviceId());
+ if (p == null) {
+ p = dhp;
+ } else {
+ p.addAll(dhp);
+ }
+ downedPortStore.put(link.src().deviceId(), p);
+ }
+ }
+ }
+
+ /**
+ * Returns true if given link is the last active uplink from src-device of
+ * link. An uplink is defined as a unidirectional link with src as
+ * edgeRouter and dst as non-edgeRouter.
+ *
+ * @param link
+ * @return true if given link is-the-first/was-the-last uplink from the src
+ * device
+ */
+ private boolean lastUplink(Link link) {
+ DeviceConfiguration devConfig = srManager.deviceConfiguration;
+ try {
+ if (!devConfig.isEdgeDevice(link.src().deviceId())) {
+ return false;
+ }
+ Set<Link> devLinks = srManager.linkService
+ .getDeviceLinks(link.src().deviceId());
+ boolean foundOtherUplink = false;
+ for (Link l : devLinks) {
+ if (devConfig.isEdgeDevice(l.dst().deviceId()) || l.equals(link)
+ || l.state() == Link.State.INACTIVE) {
+ continue;
+ }
+ foundOtherUplink = true;
+ break;
+ }
+ if (!foundOtherUplink) {
+ return true;
+ }
+ } catch (DeviceConfigNotFoundException e) {
+ log.warn("Unable to determine if link is last uplink"
+ + e.getMessage());
+ }
+ return false;
+ }
+
+ /**
+ * Returns true if this controller instance has seen this link before. The
+ * link may not be currently up, but as long as the link had been seen
+ * before this method will return true. The one exception is when the link
+ * was indeed seen before, but this controller instance was forced to forget
+ * it by a call to purgeSeenLink method.
+ *
+ * @param link the infrastructure link being queried
+ * @return true if this controller instance has seen this link before
+ */
+ boolean isSeenLink(Link link) {
+ return seenLinks.containsKey(link);
+ }
+
+ /**
+ * Updates the seen link store. Updates can be for links that are currently
+ * available or not.
+ *
+ * @param link the link to update in the seen-link local store
+ * @param up the status of the link, true if up, false if down
+ */
+ void updateSeenLink(Link link, boolean up) {
+ seenLinks.put(link, up);
+ }
+
+ /**
+ * Returns the status of a seen-link (up or down). If the link has not been
+ * seen-before, a null object is returned.
+ *
+ * @param link the infrastructure link being queried
+ * @return null if the link was not seen-before; true if the seen-link is
+ * up; false if the seen-link is down
+ */
+ private Boolean isSeenLinkUp(Link link) {
+ return seenLinks.get(link);
+ }
+
+ /**
+ * Makes this controller instance forget a previously seen before link.
+ *
+ * @param link the infrastructure link to purge
+ */
+ private void purgeSeenLink(Link link) {
+ seenLinks.remove(link);
+ }
+
+ /**
+ * Returns the status of a link as parallel link. A parallel link is defined
+ * as a link which has common src and dst switches as another seen-link that
+ * is currently enabled. It is not necessary for the link being queried to
+ * be a seen-link.
+ *
+ * @param link the infrastructure link being queried
+ * @return true if a seen-link exists that is up, and shares the same src
+ * and dst switches as the link being queried
+ */
+ private boolean isParallelLink(Link link) {
+ for (Entry<Link, Boolean> seen : seenLinks.entrySet()) {
+ Link seenLink = seen.getKey();
+ if (seenLink.equals(link)) {
+ continue;
+ }
+ if (seenLink.src().deviceId().equals(link.src().deviceId())
+ && seenLink.dst().deviceId().equals(link.dst().deviceId())
+ && seen.getValue()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns true if the link being queried is a bidirectional link. A bidi
+ * link is defined as a link, whose reverse link - ie. the link in the
+ * reverse direction - has been seen-before and is up. It is not necessary
+ * for the link being queried to be a seen-link.
+ *
+ * @param link the infrastructure link being queried
+ * @return true if another unidirectional link exists in the reverse
+ * direction, has been seen-before and is up
+ */
+ boolean isBidirectional(Link link) {
+ Link reverseLink = linkService.getLink(link.dst(), link.src());
+ if (reverseLink == null) {
+ return false;
+ }
+ Boolean result = isSeenLinkUp(reverseLink);
+ if (result == null) {
+ return false;
+ }
+ return result.booleanValue();
+ }
+
+ /**
+ * Determines if the given link should be avoided in routing calculations by
+ * policy or design.
+ *
+ * @param link the infrastructure link being queried
+ * @return true if link should be avoided
+ */
+ boolean avoidLink(Link link) {
+ // XXX currently only avoids all pair-links. In the future can be
+ // extended to avoid any generic link
+ DeviceId src = link.src().deviceId();
+ PortNumber srcPort = link.src().port();
+ DeviceConfiguration devConfig = srManager.deviceConfiguration;
+ if (devConfig == null || !devConfig.isConfigured(src)) {
+ log.warn("Device {} not configured..cannot avoid link {}", src,
+ link);
+ return false;
+ }
+ DeviceId pairDev;
+ PortNumber pairLocalPort, pairRemotePort = null;
+ try {
+ pairDev = devConfig.getPairDeviceId(src);
+ pairLocalPort = devConfig.getPairLocalPort(src);
+ if (pairDev != null) {
+ pairRemotePort = devConfig
+ .getPairLocalPort(pairDev);
+ }
+ } catch (DeviceConfigNotFoundException e) {
+ log.warn("Pair dev for dev {} not configured..cannot avoid link {}",
+ src, link);
+ return false;
+ }
+
+ return srcPort.equals(pairLocalPort)
+ && link.dst().deviceId().equals(pairDev)
+ && link.dst().port().equals(pairRemotePort);
+ }
+
+ /**
+ * Cleans up internal LinkHandler stores.
+ *
+ * @param device the device that has been removed
+ */
+ void processDeviceRemoved(Device device) {
+ seenLinks.keySet()
+ .removeIf(key -> key.src().deviceId().equals(device.id())
+ || key.dst().deviceId().equals(device.id()));
+ }
+
+ /**
+ * Administratively disables the host location switchport if the edge device
+ * has no viable uplinks.
+ *
+ * @param loc one of the locations of the dual-homed host
+ */
+ void checkUplinksForDualHomedHosts(HostLocation loc) {
+ try {
+ for (Link l : srManager.linkService.getDeviceLinks(loc.deviceId())) {
+ if (srManager.deviceConfiguration.isEdgeDevice(l.dst().deviceId())
+ || l.state() == Link.State.INACTIVE) {
+ continue;
+ }
+ // found valid uplink - so, nothing to do
+ return;
+ }
+ } catch (DeviceConfigNotFoundException e) {
+ log.warn("Could not check for valid uplinks due to missing device"
+ + "config " + e.getMessage());
+ return;
+ }
+ log.warn("Dual homed host location {} has no valid uplinks; "
+ + "disabling dual homed port", loc);
+ srManager.deviceAdminService.changePortState(loc.deviceId(), loc.port(),
+ false);
+ Set<PortNumber> p = downedPortStore.get(loc.deviceId());
+ if (p == null) {
+ p = Sets.newHashSet(loc.port());
+ } else {
+ p.add(loc.port());
+ }
+ downedPortStore.put(loc.deviceId(), p);
+ }
+
+}
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/McastHandler.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/McastHandler.java
index 80affc1..b0be4e3 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/McastHandler.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/McastHandler.java
@@ -411,7 +411,7 @@
log.info("NextObj for {}/{} already exists. Abort", deviceId, port);
return;
}
- portBuilder.addAll(existingPorts).add(port).build();
+ portBuilder.addAll(existingPorts).add(port);
}
// Create, store and apply the new nextObj and fwdObj
ObjectiveContext context = new DefaultObjectiveContext(
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
index 0725e1b..3242866 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingManager.java
@@ -60,6 +60,7 @@
import org.onosproject.net.config.basics.InterfaceConfig;
import org.onosproject.net.config.basics.McastConfig;
import org.onosproject.net.config.basics.SubjectFactories;
+import org.onosproject.net.device.DeviceAdminService;
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceService;
@@ -119,7 +120,6 @@
import java.util.HashSet;
import java.util.List;
import java.util.Map;
-import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@@ -167,6 +167,9 @@
DeviceService deviceService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ DeviceAdminService deviceAdminService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
public FlowObjectiveService flowObjectiveService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
@@ -212,9 +215,10 @@
private InternalDeviceListener deviceListener = null;
private AppConfigHandler appCfgHandler = null;
XConnectHandler xConnectHandler = null;
- private McastHandler mcastHandler = null;
- private HostHandler hostHandler = null;
+ McastHandler mcastHandler = null;
+ HostHandler hostHandler = null;
private RouteHandler routeHandler = null;
+ LinkHandler linkHandler = null;
private SegmentRoutingNeighbourDispatcher neighbourHandler = null;
private L2TunnelHandler l2TunnelHandler = null;
private InternalEventHandler eventHandler = new InternalEventHandler();
@@ -230,7 +234,7 @@
private static ScheduledFuture<?> eventHandlerFuture = null;
@SuppressWarnings("rawtypes")
private ConcurrentLinkedQueue<Event> eventQueue = new ConcurrentLinkedQueue<>();
- private Map<DeviceId, DefaultGroupHandler> groupHandlerMap =
+ Map<DeviceId, DefaultGroupHandler> groupHandlerMap =
new ConcurrentHashMap<>();
/**
* Per device next objective ID store with (device id + destination set) as key.
@@ -251,16 +255,6 @@
private EventuallyConsistentMap<PortNextObjectiveStoreKey, Integer>
portNextObjStore = null;
- // Local store for all links seen and their present status, used for
- // optimized routing. The existence of the link in the keys is enough to know
- // if the link has been "seen-before" by this instance of the controller.
- // The boolean value indicates if the link is currently up or not.
- // XXX Currently the optimized routing logic depends on "forgetting" a link
- // when a switch goes down, but "remembering" it when only the link goes down.
- // Consider changing this logic so we can use the Link Service instead of
- // a local cache.
- private Map<Link, Boolean> seenLinks = new ConcurrentHashMap<>();
-
private EventuallyConsistentMap<String, Tunnel> tunnelStore = null;
private EventuallyConsistentMap<String, Policy> policyStore = null;
@@ -412,6 +406,7 @@
xConnectHandler = new XConnectHandler(this);
mcastHandler = new McastHandler(this);
hostHandler = new HostHandler(this);
+ linkHandler = new LinkHandler(this);
routeHandler = new RouteHandler(this);
neighbourHandler = new SegmentRoutingNeighbourDispatcher(this);
l2TunnelHandler = new L2TunnelHandler(this);
@@ -437,7 +432,7 @@
log.info("Started");
}
- private KryoNamespace.Builder createSerializer() {
+ KryoNamespace.Builder createSerializer() {
return new KryoNamespace.Builder()
.register(KryoNamespaces.API)
.register(DestinationSetNextObjectiveStoreKey.class,
@@ -921,135 +916,6 @@
return defaultRoutingHandler;
}
- /**
- * Returns true if this controller instance has seen this link before. The
- * link may not be currently up, but as long as the link had been seen before
- * this method will return true. The one exception is when the link was
- * indeed seen before, but this controller instance was forced to forget it
- * by a call to purgeSeenLink method.
- *
- * @param link the infrastructure link being queried
- * @return true if this controller instance has seen this link before
- */
- boolean isSeenLink(Link link) {
- return seenLinks.containsKey(link);
- }
-
- /**
- * Updates the seen link store. Updates can be for links that are currently
- * available or not.
- *
- * @param link the link to update in the seen-link local store
- * @param up the status of the link, true if up, false if down
- */
- void updateSeenLink(Link link, boolean up) {
- seenLinks.put(link, up);
- }
-
- /**
- * Returns the status of a seen-link (up or down). If the link has not
- * been seen-before, a null object is returned.
- *
- * @param link the infrastructure link being queried
- * @return null if the link was not seen-before;
- * true if the seen-link is up;
- * false if the seen-link is down
- */
- private Boolean isSeenLinkUp(Link link) {
- return seenLinks.get(link);
- }
-
- /**
- * Makes this controller instance forget a previously seen before link.
- *
- * @param link the infrastructure link to purge
- */
- private void purgeSeenLink(Link link) {
- seenLinks.remove(link);
- }
-
- /**
- * Returns the status of a link as parallel link. A parallel link
- * is defined as a link which has common src and dst switches as another
- * seen-link that is currently enabled. It is not necessary for the link being
- * queried to be a seen-link.
- *
- * @param link the infrastructure link being queried
- * @return true if a seen-link exists that is up, and shares the
- * same src and dst switches as the link being queried
- */
- private boolean isParallelLink(Link link) {
- for (Entry<Link, Boolean> seen : seenLinks.entrySet()) {
- Link seenLink = seen.getKey();
- if (seenLink.equals(link)) {
- continue;
- }
- if (seenLink.src().deviceId().equals(link.src().deviceId()) &&
- seenLink.dst().deviceId().equals(link.dst().deviceId()) &&
- seen.getValue()) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Returns true if the link being queried is a bidirectional link. A bidi
- * link is defined as a link, whose reverse link - ie. the link in the reverse
- * direction - has been seen-before and is up. It is not necessary for the link
- * being queried to be a seen-link.
- *
- * @param link the infrastructure link being queried
- * @return true if another unidirectional link exists in the reverse direction,
- * has been seen-before and is up
- */
- boolean isBidirectional(Link link) {
- Link reverseLink = linkService.getLink(link.dst(), link.src());
- if (reverseLink == null) {
- return false;
- }
- Boolean result = isSeenLinkUp(reverseLink);
- if (result == null) {
- return false;
- }
- return result.booleanValue();
- }
-
- /**
- * Determines if the given link should be avoided in routing calculations
- * by policy or design.
- *
- * @param link the infrastructure link being queried
- * @return true if link should be avoided
- */
- boolean avoidLink(Link link) {
- // XXX currently only avoids all pair-links. In the future can be
- // extended to avoid any generic link
- DeviceId src = link.src().deviceId();
- PortNumber srcPort = link.src().port();
- if (deviceConfiguration == null || !deviceConfiguration.isConfigured(src)) {
- log.warn("Device {} not configured..cannot avoid link {}", src, link);
- return false;
- }
- DeviceId pairDev;
- PortNumber pairLocalPort, pairRemotePort = null;
- try {
- pairDev = deviceConfiguration.getPairDeviceId(src);
- pairLocalPort = deviceConfiguration.getPairLocalPort(src);
- if (pairDev != null) {
- pairRemotePort = deviceConfiguration.getPairLocalPort(pairDev);
- }
- } catch (DeviceConfigNotFoundException e) {
- log.warn("Pair dev for dev {} not configured..cannot avoid link {}",
- src, link);
- return false;
- }
-
- return srcPort.equals(pairLocalPort) &&
- link.dst().deviceId().equals(pairDev) &&
- link.dst().port().equals(pairRemotePort);
- }
-
private class InternalPacketProcessor implements PacketProcessor {
@Override
public void process(PacketContext context) {
@@ -1174,28 +1040,9 @@
// Note: do not update seenLinks here, otherwise every
// link, even one seen for the first time, will be appear
// to be a previously seen link
- processLinkAdded((Link) event.subject());
+ linkHandler.processLinkAdded((Link) event.subject());
} else if (event.type() == LinkEvent.Type.LINK_REMOVED) {
- Link linkRemoved = (Link) event.subject();
- if (linkRemoved.type() == Link.Type.DIRECT) {
- updateSeenLink(linkRemoved, false);
- }
- // device availability check helps to ensure that
- // multiple link-removed events are actually treated as a
- // single switch removed event. purgeSeenLink is necessary
- // so we do rerouting (instead of rehashing) when switch
- // comes back.
- if (linkRemoved.src().elementId() instanceof DeviceId &&
- !deviceService.isAvailable(linkRemoved.src().deviceId())) {
- purgeSeenLink(linkRemoved);
- continue;
- }
- if (linkRemoved.dst().elementId() instanceof DeviceId &&
- !deviceService.isAvailable(linkRemoved.dst().deviceId())) {
- purgeSeenLink(linkRemoved);
- continue;
- }
- processLinkRemoved((Link) event.subject());
+ linkHandler.processLinkRemoved((Link) event.subject());
} else if (event.type() == DeviceEvent.Type.DEVICE_ADDED ||
event.type() == DeviceEvent.Type.DEVICE_AVAILABILITY_CHANGED ||
event.type() == DeviceEvent.Type.DEVICE_UPDATED) {
@@ -1238,164 +1085,7 @@
}
}
- private void processLinkAdded(Link link) {
- log.info("** LINK ADDED {}", link.toString());
- if (!isLinkValid(link)) {
- return;
- }
- if (!deviceConfiguration.isConfigured(link.src().deviceId())) {
- updateSeenLink(link, true);
- // XXX revisit - what about devicePortMap
- log.warn("Source device of this link is not configured.. "
- + "not processing further");
- return;
- }
-
- //Irrespective of whether the local is a MASTER or not for this device,
- //create group handler instance and push default TTP flow rules if needed,
- //as in a multi-instance setup, instances can initiate groups for any device.
- DefaultGroupHandler groupHandler = groupHandlerMap.get(link.src()
- .deviceId());
- if (groupHandler != null) {
- groupHandler.portUpForLink(link);
- } else {
- // XXX revisit/cleanup
- Device device = deviceService.getDevice(link.src().deviceId());
- if (device != null) {
- log.warn("processLinkAdded: Link Added "
- + "Notification without Device Added "
- + "event, still handling it");
- processDeviceAdded(device);
- groupHandler = groupHandlerMap.get(link.src()
- .deviceId());
- groupHandler.portUpForLink(link);
- }
- }
-
- /*// process link only if it is bidirectional
- if (!isBidirectional(link)) {
- log.debug("Link not bidirectional.. waiting for other direction "
- + "src {} --> dst {} ", link.dst(), link.src());
- // note that if we are not processing for routing, it should at least
- // be considered a seen-link
- updateSeenLink(link, true);
- return;
- }
- TO DO this ensure that rehash is still done correctly even if link is
- not processed for rerouting - perhaps rehash in both directions when
- it ultimately becomes bidi?
- */
-
- log.debug("Starting optimized route population process for link "
- + "{} --> {}", link.src(), link.dst());
- boolean seenBefore = isSeenLink(link);
- defaultRoutingHandler.populateRoutingRulesForLinkStatusChange(null, link, null);
-
- // It's possible that linkUp causes no route-path change as ECMP graph does
- // not change if the link is a parallel link (same src-dst as another link.
- // However we still need to update ECMP hash groups to include new buckets
- // for the link that has come up.
- if (mastershipService.isLocalMaster(link.src().deviceId())) {
- if (!seenBefore && isParallelLink(link)) {
- // if link seen first time, we need to ensure hash-groups have all ports
- log.debug("Attempting retryHash for paralled first-time link {}", link);
- groupHandler.retryHash(link, false, true);
- } else {
- //seen before-link
- if (isParallelLink(link)) {
- log.debug("Attempting retryHash for paralled seen-before "
- + "link {}", link);
- groupHandler.retryHash(link, false, false);
- }
- }
- }
-
- mcastHandler.init();
- }
-
- private void processLinkRemoved(Link link) {
- log.info("** LINK REMOVED {}", link.toString());
- if (!isLinkValid(link)) {
- return;
- }
- defaultRoutingHandler.populateRoutingRulesForLinkStatusChange(link, null, null);
-
- // update local groupHandler stores
- DefaultGroupHandler groupHandler = groupHandlerMap.get(link.src().deviceId());
- if (groupHandler != null) {
- if (mastershipService.isLocalMaster(link.src().deviceId()) &&
- isParallelLink(link)) {
- log.debug("* retrying hash for parallel link removed:{}", link);
- groupHandler.retryHash(link, true, false);
- } else {
- log.debug("Not attempting retry-hash for link removed: {} .. {}", link,
- (mastershipService.isLocalMaster(link.src().deviceId()))
- ? "not parallel" : "not master");
- }
- // ensure local stores are updated
- groupHandler.portDown(link.src().port());
- } else {
- log.warn("group handler not found for dev:{} when removing link: {}",
- link.src().deviceId(), link);
- }
-
- mcastHandler.processLinkDown(link);
- l2TunnelHandler.processLinkDown(link);
- }
-
- private boolean isLinkValid(Link link) {
- if (link.type() != Link.Type.DIRECT) {
- // NOTE: A DIRECT link might be transiently marked as INDIRECT
- // if BDDP is received before LLDP. We can safely ignore that
- // until the LLDP is received and the link is marked as DIRECT.
- log.info("Ignore link {}->{}. Link type is {} instead of DIRECT.",
- link.src(), link.dst(), link.type());
- return false;
- }
- DeviceId srcId = link.src().deviceId();
- DeviceId dstId = link.dst().deviceId();
- if (srcId.equals(dstId)) {
- log.warn("Links between ports on the same switch are not "
- + "allowed .. ignoring link {}", link);
- return false;
- }
- try {
- if (!deviceConfiguration.isEdgeDevice(srcId)
- && !deviceConfiguration.isEdgeDevice(dstId)) {
- // ignore links between spines
- // XXX revisit when handling multi-stage fabrics
- log.warn("Links between spines not allowed...ignoring "
- + "link {}", link);
- return false;
- }
- if (deviceConfiguration.isEdgeDevice(srcId)
- && deviceConfiguration.isEdgeDevice(dstId)) {
- // ignore links between leaves if they are not pair-links
- // XXX revisit if removing pair-link config or allowing more than
- // one pair-link
- if (deviceConfiguration.getPairDeviceId(srcId).equals(dstId)
- && deviceConfiguration.getPairLocalPort(srcId)
- .equals(link.src().port())
- && deviceConfiguration.getPairLocalPort(dstId)
- .equals(link.dst().port())) {
- // found pair link - allow it
- return true;
- } else {
- log.warn("Links between leaves other than pair-links are "
- + "not allowed...ignoring link {}", link);
- return false;
- }
- }
- } catch (DeviceConfigNotFoundException e) {
- // We still want to count the links in seenLinks even though there
- // is no config. So we let it return true
- log.warn("Could not check validity of link {} as subtending devices "
- + "are not yet configured", link);
- }
- return true;
- }
-
- private void processDeviceAdded(Device device) {
+ void processDeviceAdded(Device device) {
log.info("** DEVICE ADDED with ID {}", device.id());
// NOTE: Punt ARP/NDP even when the device is not configured.
@@ -1461,9 +1151,7 @@
portNextObjStore.entrySet().stream()
.filter(entry -> entry.getKey().deviceId().equals(device.id()))
.forEach(entry -> portNextObjStore.remove(entry.getKey()));
-
- seenLinks.keySet().removeIf(key -> key.src().deviceId().equals(device.id()) ||
- key.dst().deviceId().equals(device.id()));
+ linkHandler.processDeviceRemoved(device);
DefaultGroupHandler gh = groupHandlerMap.remove(device.id());
if (gh != null) {
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingNeighbourDispatcher.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingNeighbourDispatcher.java
index cc815da..f170fae 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingNeighbourDispatcher.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/SegmentRoutingNeighbourDispatcher.java
@@ -42,7 +42,8 @@
@Override
public void handleMessage(NeighbourMessageContext context, HostService hostService) {
- log.trace("Received a {} packet {}", context.protocol(), context.packet());
+ log.trace("Received {} packet on {}: {}", context.protocol(),
+ context.inPort(), context.packet());
switch (context.protocol()) {
case ARP:
if (this.manager.arpHandler != null) {
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/PwaasConfig.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/PwaasConfig.java
index ed2c067..18fc738 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/PwaasConfig.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/config/PwaasConfig.java
@@ -122,13 +122,13 @@
.map(this::getPwDescription)
.collect(Collectors.toSet());
+ // check semantics now and return
+ return configurationValidity(pseudowires);
+
} catch (IllegalArgumentException e) {
log.warn("{}", e.getMessage());
return false;
}
-
- // check semantics now and return
- return configurationValidity(pseudowires);
}
/**
@@ -204,9 +204,9 @@
tunnelId)));
}
- if (((!ingressOuter.equals(VlanId.NONE) && !ingressOuter.equals(VlanId.NONE)) &&
+ if (((!ingressOuter.equals(VlanId.NONE) && !ingressInner.equals(VlanId.NONE)) &&
(egressOuter.equals(VlanId.NONE) && egressInner.equals(VlanId.NONE)))
- || ((ingressOuter.equals(VlanId.NONE) && ingressOuter.equals(VlanId.NONE)) &&
+ || ((ingressOuter.equals(VlanId.NONE) && ingressInner.equals(VlanId.NONE)) &&
(!egressOuter.equals(VlanId.NONE) && !egressInner.equals(VlanId.NONE)))) {
throw new IllegalArgumentException(String.valueOf(String.format("Support for double tag <-> untag is not" +
"supported for pseudowire %d.",
@@ -656,10 +656,9 @@
newPw.put(MODE, mode);
object.set(tunnelId, newPw);
- try {
- isValid();
- } catch (IllegalArgumentException e) {
- log.info("Pseudowire could not be created : {}", e);
+
+ if (!isValid()) {
+ log.info("Pseudowire could not be created : {}");
object.remove(tunnelId);
return null;
}
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
index ab1363c..75cab32 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/grouphandler/DefaultGroupHandler.java
@@ -247,6 +247,9 @@
Set<DestinationSetNextObjectiveStoreKey> dsKeySet = dsNextObjStore.entrySet()
.stream()
.filter(entry -> entry.getKey().deviceId().equals(deviceId))
+ // Filter out PW transit groups or include them if MPLS ECMP is supported
+ .filter(entry -> !entry.getKey().destinationSet().mplsSet() ||
+ (entry.getKey().destinationSet().mplsSet() && srManager.getMplsEcmp()))
.filter(entry -> entry.getValue().containsNextHop(link.dst().deviceId()))
.map(entry -> entry.getKey())
.collect(Collectors.toSet());
@@ -325,7 +328,7 @@
* a hashed group. User must ensure that all the ports & labels are meant
* same neighbor (ie. dstMac).
*
- * @param portLables a collection of port & label combinations to add
+ * @param portLabels a collection of port & label combinations to add
* to the hash group identified by the nextId
* @param dstMac destination mac address of next-hop
* @param nextId id for next-objective to which buckets will be added
@@ -376,7 +379,7 @@
* a hash group. User must ensure that all the ports & labels are meant
* same neighbor (ie. dstMac).
*
- * @param portLables a collection of port & label combinations to remove
+ * @param portLabels a collection of port & label combinations to remove
* from the hash group identified by the nextId
* @param dstMac destination mac address of next-hop
* @param nextId id for next-objective from which buckets will be removed
@@ -1186,6 +1189,9 @@
if (e.getValue().nextId() != objectiveId) {
continue;
}
+ // Right now it is just used in TunnelHandler
+ // remember in future that PW transit groups could
+ // be Indirect groups
NextObjective.Builder nextObjBuilder = DefaultNextObjective
.builder().withId(objectiveId)
.withType(NextObjective.Type.HASHED).fromApp(appId);
@@ -1344,6 +1350,9 @@
Set<DestinationSetNextObjectiveStoreKey> dsKeySet = dsNextObjStore.entrySet()
.stream()
.filter(entry -> entry.getKey().deviceId().equals(deviceId))
+ // Filter out PW transit groups or include them if MPLS ECMP is supported
+ .filter(entry -> !entry.getKey().destinationSet().mplsSet() ||
+ (entry.getKey().destinationSet().mplsSet() && srManager.getMplsEcmp()))
.map(entry -> entry.getKey())
.collect(Collectors.toSet());
for (DestinationSetNextObjectiveStoreKey dsKey : dsKeySet) {
@@ -1412,4 +1421,4 @@
}
}
-}
\ No newline at end of file
+}
diff --git a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/pwaas/L2TunnelHandler.java b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/pwaas/L2TunnelHandler.java
index 2675734..a2048b0 100644
--- a/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/pwaas/L2TunnelHandler.java
+++ b/apps/segmentrouting/src/main/java/org/onosproject/segmentrouting/pwaas/L2TunnelHandler.java
@@ -373,7 +373,7 @@
// We terminate the tunnel
result = deployPseudoWireTerm(pw.l2Tunnel(),
pw.l2TunnelPolicy().cP2(),
- pw.l2TunnelPolicy().cP2OuterTag(),
+ VlanId.NONE,
FWD,
spinePw);
@@ -414,7 +414,7 @@
result = deployPseudoWireTerm(pw.l2Tunnel(),
pw.l2TunnelPolicy().cP1(),
- pw.l2TunnelPolicy().cP1OuterTag(),
+ VlanId.NONE,
REV,
spinePw);
@@ -725,7 +725,7 @@
return;
}
deployPseudoWireTerm(newPw.l2Tunnel(), newPw.l2TunnelPolicy().cP2(),
- newPw.l2TunnelPolicy().cP2OuterTag(), FWD, finalNewPwSpine);
+ VlanId.NONE, FWD, finalNewPwSpine);
}
});
@@ -756,7 +756,7 @@
}
deployPseudoWireTerm(newPw.l2Tunnel(),
newPw.l2TunnelPolicy().cP1(),
- newPw.l2TunnelPolicy().cP1OuterTag(),
+ VlanId.NONE,
REV, finalNewPwSpine);
}
});
diff --git a/apps/segmentrouting/src/test/java/org/onosproject/segmentrouting/HostHandlerTest.java b/apps/segmentrouting/src/test/java/org/onosproject/segmentrouting/HostHandlerTest.java
index cce5a31..e33a36d 100644
--- a/apps/segmentrouting/src/test/java/org/onosproject/segmentrouting/HostHandlerTest.java
+++ b/apps/segmentrouting/src/test/java/org/onosproject/segmentrouting/HostHandlerTest.java
@@ -212,6 +212,7 @@
srManager.cfgService = mockNetworkConfigRegistry;
mockLocationProbingService = new MockLocationProbingService();
srManager.probingService = mockLocationProbingService;
+ srManager.linkHandler = new MockLinkHandler(srManager);
hostHandler = new HostHandler(srManager);
diff --git a/apps/segmentrouting/src/test/java/org/onosproject/segmentrouting/MockLinkHandler.java b/apps/segmentrouting/src/test/java/org/onosproject/segmentrouting/MockLinkHandler.java
new file mode 100644
index 0000000..2819c9d
--- /dev/null
+++ b/apps/segmentrouting/src/test/java/org/onosproject/segmentrouting/MockLinkHandler.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.segmentrouting;
+
+import org.onosproject.net.HostLocation;
+
+/**
+ * Mocks the LinkHandler in SR.
+ *
+ */
+public class MockLinkHandler extends LinkHandler {
+
+ MockLinkHandler(SegmentRoutingManager srManager) {
+ super(srManager, null);
+ }
+
+ @Override
+ void checkUplinksForDualHomedHosts(HostLocation loc) {
+ // currently does nothing - can be extended to be a useful mock when
+ // implementing unit tests for link handling
+ }
+}
diff --git a/apps/segmentrouting/src/test/java/org/onosproject/segmentrouting/PwaasConfigTest.java b/apps/segmentrouting/src/test/java/org/onosproject/segmentrouting/PwaasConfigTest.java
index 7686242..60163eb 100644
--- a/apps/segmentrouting/src/test/java/org/onosproject/segmentrouting/PwaasConfigTest.java
+++ b/apps/segmentrouting/src/test/java/org/onosproject/segmentrouting/PwaasConfigTest.java
@@ -303,9 +303,9 @@
assertFalse(invalidConfigLabel.isValid());
}
- @Test(expected = IllegalArgumentException.class)
+ @Test
public void testValid4() {
- invalidConfigConflictingVlan.isValid();
+ assertFalse(invalidConfigConflictingVlan.isValid());
}
/**
diff --git a/apps/simplefabric/BUCK b/apps/simplefabric/BUCK
index 8125580..b215c46 100644
--- a/apps/simplefabric/BUCK
+++ b/apps/simplefabric/BUCK
@@ -2,6 +2,10 @@
'//lib:CORE_DEPS',
'//lib:JACKSON',
'//lib:concurrent-trees',
+ '//lib:javax.ws.rs-api',
+ '//lib:org.apache.karaf.shell.console',
+ '//cli:onos-cli',
+ '//utils/rest:onlab-rest',
]
BUNDLES = [
@@ -15,6 +19,7 @@
osgi_jar_with_tests (
deps = COMPILE_DEPS,
test_deps = TEST_DEPS,
+ web_context = '/onos/v1/simplefabric',
)
onos_app (
diff --git a/apps/simplefabric/app.xml b/apps/simplefabric/app.xml
index df5cc60..1984e56 100644
--- a/apps/simplefabric/app.xml
+++ b/apps/simplefabric/app.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- ~ Copyright 2017-present Open Networking Laboratory
+ ~ 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.
diff --git a/apps/simplefabric/features.xml b/apps/simplefabric/features.xml
index 9ab23de..fd67ef1 100644
--- a/apps/simplefabric/features.xml
+++ b/apps/simplefabric/features.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--
- ~ Copyright 2017-present Open Networking Laboratory
+ ~ 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.
diff --git a/apps/simplefabric/network-cfg.json b/apps/simplefabric/network-cfg.json
index f988497..c8e118b 100644
--- a/apps/simplefabric/network-cfg.json
+++ b/apps/simplefabric/network-cfg.json
@@ -38,8 +38,8 @@
"org.onosproject.simplefabric" : {
"simpleFabric" : {
"l2Networks" : [
- { "name" : "LEAF1", "interfaces" : ["h11", "h12", "h13", "h14", "d11", "d12" ], "l2Forward" : true },
- { "name" : "LEAF2", "interfaces" : ["h21", "h22", "h23", "h24", "d21", "d22" ], "l2Forward" : true }
+ { "name" : "LEAF1", "interfaces" : ["h11", "h12", "h13", "h14", "d11", "d12" ], "l2Forward" : true, "l2Broadcast" : true },
+ { "name" : "LEAF2", "interfaces" : ["h21", "h22", "h23", "h24", "d21", "d22" ], "l2Forward" : true, "l2Broadcast" : true }
],
"ipSubnets" : [
{ "ipPrefix" : "10.0.1.0/24", "gatewayIp" : "10.0.1.1", "gatewayMac" : "00:00:10:00:01:01", "l2NetworkName" : "LEAF1" },
diff --git a/apps/simplefabric/pom.xml b/apps/simplefabric/pom.xml
index 8954d24..e276ca7 100644
--- a/apps/simplefabric/pom.xml
+++ b/apps/simplefabric/pom.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- ~ Copyright 2017-present Open Networking Laboratory
+ ~ 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.
diff --git a/apps/simplefabric/rest-simplefabric b/apps/simplefabric/rest-simplefabric
new file mode 100755
index 0000000..130fa3b
--- /dev/null
+++ b/apps/simplefabric/rest-simplefabric
@@ -0,0 +1,62 @@
+#!/bin/bash
+
+#
+# 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.
+#
+
+# -----------------------------------------------------------------------------
+# Tool to manage ONOS applications using REST API.
+# -----------------------------------------------------------------------------
+
+# If ONOS_HOME is set, respect its value.
+# If ONOS_HOME is not set (e.g. in the init or service environment),
+# set it based on this script's path.
+ONOS_HOME=${ONOS_HOME:-$(cd $(dirname $0)/.. >/dev/null 2>&1 && pwd)}
+ONOS_WEB_USER=${ONOS_WEB_USER:-onos} # ONOS WEB User defaults to 'onos'
+ONOS_WEB_PASS=${ONOS_WEB_PASS:-rocks} # ONOS WEB Password defaults to 'rocks'
+
+. ${ONOS_HOME}/bin/_find-node
+
+node=$(find_node ${1:-localhost})
+cmd=${2:-show}
+
+export URL=http://$node:8181/onos/v1/simplefabric/$cmd
+#export HDR="-HContent-Type:application/octet-stream"
+#export HAJ="-HContent-Type:application/json"
+export curl="curl -sS --user $ONOS_WEB_USER:$ONOS_WEB_PASS --noproxy localhost "
+
+# Prints usage help
+function usage {
+ echo "usage: onos-simplefabric <node-ip> status|show|intents|reactive-intents|refresh|flush" >&2
+ exit 1
+}
+
+[ -z $node -o "$node" = "-h" -o "$node" = "--help" -o "$node" = "-?" ] && usage
+
+case $cmd in
+ status) $curl -X GET $URL;;
+ show) $curl -X GET $URL;;
+ intents) $curl -X GET $URL;;
+ reactive-intents) $curl -X GET $URL;;
+ refresh) $curl -X PUT $URL;;
+ flush) $curl -X PUT $URL;;
+
+ *) usage;;
+esac
+
+
+status=$?
+echo # new line for prompt
+exit $status
diff --git a/apps/simplefabric/src/main/java/org/onosproject/simplefabric/L2Network.java b/apps/simplefabric/src/main/java/org/onosproject/simplefabric/L2Network.java
index 31e8cc0..5579159 100644
--- a/apps/simplefabric/src/main/java/org/onosproject/simplefabric/L2Network.java
+++ b/apps/simplefabric/src/main/java/org/onosproject/simplefabric/L2Network.java
@@ -41,6 +41,7 @@
private Set<String> interfaceNames; // also for network configuration
private EncapsulationType encapsulation; // also for network configuration
private boolean l2Forward; // do l2Forward (default:true) or not
+ private boolean l2Broadcast; // do l2Broadcast (default:true) or not
/* status variables */
private Set<Interface> interfaces; // available interfaces from interfaceNames
@@ -54,13 +55,16 @@
* @param ifaceNames the interface names
* @param encapsulation the encapsulation type
* @param l2Forward flag for l2Forward intents to be installed or not
+ * @param l2Broadcast flag for l2Broadcast intents to be installed or not
*/
- L2Network(String name, Collection<String> ifaceNames, EncapsulationType encapsulation, boolean l2Forward) {
+ L2Network(String name, Collection<String> ifaceNames, EncapsulationType encapsulation,
+ boolean l2Forward, boolean l2Broadcast) {
this.name = name;
this.interfaceNames = Sets.newHashSet();
this.interfaceNames.addAll(ifaceNames);
this.encapsulation = encapsulation;
this.l2Forward = (SimpleFabricService.ALLOW_ETH_ADDRESS_SELECTOR) ? l2Forward : false;
+ this.l2Broadcast = (SimpleFabricService.ALLOW_ETH_ADDRESS_SELECTOR) ? l2Broadcast : false;
this.interfaces = Sets.newHashSet();
this.hostIds = Sets.newHashSet();
this.dirty = false;
@@ -77,6 +81,7 @@
this.interfaceNames = Sets.newHashSet();
this.encapsulation = encapsulation;
this.l2Forward = (SimpleFabricService.ALLOW_ETH_ADDRESS_SELECTOR) ? true : false;
+ this.l2Broadcast = (SimpleFabricService.ALLOW_ETH_ADDRESS_SELECTOR) ? true : false;
this.interfaces = Sets.newHashSet();
this.hostIds = Sets.newHashSet();
this.dirty = false;
@@ -105,6 +110,7 @@
L2Network l2NetworkCopy = new L2Network(l2Network.name(), l2Network.encapsulation());
l2NetworkCopy.interfaceNames.addAll(l2Network.interfaceNames());
l2NetworkCopy.l2Forward = (SimpleFabricService.ALLOW_ETH_ADDRESS_SELECTOR) ? l2Network.l2Forward() : false;
+ l2NetworkCopy.l2Broadcast = (SimpleFabricService.ALLOW_ETH_ADDRESS_SELECTOR) ? l2Network.l2Broadcast() : false;
l2NetworkCopy.interfaces.addAll(l2Network.interfaces());
l2NetworkCopy.hostIds.addAll(l2Network.hostIds());
l2NetworkCopy.setDirty(l2Network.dirty());
@@ -150,6 +156,15 @@
}
/**
+ * Gets L2Network l2Broadcast flag.
+ *
+ * @return the l2Broadcast flag of L2Network
+ */
+ public boolean l2Broadcast() {
+ return l2Broadcast;
+ }
+
+ /**
* Gets L2Network interfaces.
*
* @return the interfaces of L2Network
@@ -257,6 +272,7 @@
.add("interfaceNames", interfaceNames)
.add("encapsulation", encapsulation)
.add("l2Forward", l2Forward)
+ .add("l2Broadcast", l2Broadcast)
.add("interfaces", interfaces)
.add("hostIds", hostIds)
.add("dirty", dirty)
@@ -276,12 +292,13 @@
&& Objects.equals(other.interfaceNames, this.interfaceNames)
&& Objects.equals(other.encapsulation, this.encapsulation)
&& Objects.equals(other.l2Forward, this.l2Forward)
+ && Objects.equals(other.l2Broadcast, this.l2Broadcast)
&& Objects.equals(other.interfaces, this.interfaces)
&& Objects.equals(other.hostIds, this.hostIds);
}
@Override
public int hashCode() {
- return Objects.hash(name, interfaces, encapsulation, l2Forward);
+ return Objects.hash(name, interfaces, encapsulation, l2Forward, l2Broadcast);
}
}
diff --git a/apps/simplefabric/src/main/java/org/onosproject/simplefabric/SimpleFabricCommand.java b/apps/simplefabric/src/main/java/org/onosproject/simplefabric/SimpleFabricCommand.java
new file mode 100644
index 0000000..e5ed60e
--- /dev/null
+++ b/apps/simplefabric/src/main/java/org/onosproject/simplefabric/SimpleFabricCommand.java
@@ -0,0 +1,70 @@
+/*
+ * 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.simplefabric;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+
+/**
+ * CLI to interact with the SIMPLE_FABRIC application.
+ */
+@Command(scope = "onos", name = "simpleFabric",
+ description = "Manages the SimpleFabric application")
+public class SimpleFabricCommand extends AbstractShellCommand {
+
+ protected static SimpleFabricService simpleFabric;
+
+ @Argument(index = 0, name = "command",
+ description = "Command: show|intents|reactive-intents|refresh|flush",
+ required = true, multiValued = false)
+ String command = null;
+
+ @Override
+ protected void execute() {
+ if (simpleFabric == null) {
+ simpleFabric = get(SimpleFabricService.class);
+ }
+ if (command == null) {
+ print("command not found", command);
+ return;
+ }
+ switch (command) {
+ case "show":
+ simpleFabric.dumpToStream("show", System.out);
+ break;
+ case "intents":
+ simpleFabric.dumpToStream("intents", System.out);
+ break;
+ case "reactive-intents":
+ simpleFabric.dumpToStream("reactive-intents", System.out);
+ break;
+ case "refresh":
+ simpleFabric.triggerRefresh();
+ System.out.println("simple fabric refresh triggered");
+ break;
+ case "flush":
+ simpleFabric.triggerFlush();
+ System.out.println("simple fabric flush triggered");
+ break;
+ default:
+ System.out.println("unknown command: " + command);
+ break;
+ }
+ }
+
+}
+
diff --git a/apps/simplefabric/src/main/java/org/onosproject/simplefabric/SimpleFabricCommandCompleter.java b/apps/simplefabric/src/main/java/org/onosproject/simplefabric/SimpleFabricCommandCompleter.java
new file mode 100644
index 0000000..b810d73
--- /dev/null
+++ b/apps/simplefabric/src/main/java/org/onosproject/simplefabric/SimpleFabricCommandCompleter.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.simplefabric;
+
+import com.google.common.collect.Lists;
+import org.apache.karaf.shell.console.completer.ArgumentCompleter;
+import org.onosproject.cli.AbstractChoicesCompleter;
+
+import java.util.List;
+import java.util.Arrays;
+import java.util.Collections;
+
+/**
+ * SimpleFabric command completer.
+ */
+public class SimpleFabricCommandCompleter extends AbstractChoicesCompleter {
+
+ public static final List<String> COMMAND_LIST =
+ Arrays.asList("show", "intents", "reactive-intents", "refresh", "flush");
+
+ @Override
+ public List<String> choices() {
+ ArgumentCompleter.ArgumentList argumentList = getArgumentList();
+ if (argumentList == null) {
+ return Collections.emptyList();
+ }
+ List<String> argList = Lists.newArrayList(argumentList.getArguments());
+ String argOne = null;
+ if (argList.size() > 1) {
+ argOne = argList.get(1);
+ }
+ if (COMMAND_LIST.contains(argOne)) {
+ return Collections.emptyList();
+ } else {
+ return COMMAND_LIST;
+ }
+ }
+}
+
diff --git a/apps/simplefabric/src/main/java/org/onosproject/simplefabric/SimpleFabricConfig.java b/apps/simplefabric/src/main/java/org/onosproject/simplefabric/SimpleFabricConfig.java
index a6d83b1..7bae152 100644
--- a/apps/simplefabric/src/main/java/org/onosproject/simplefabric/SimpleFabricConfig.java
+++ b/apps/simplefabric/src/main/java/org/onosproject/simplefabric/SimpleFabricConfig.java
@@ -40,6 +40,7 @@
private static final String INTERFACES = "interfaces";
private static final String ENCAPSULATION = "encapsulation";
private static final String L2FORWARD = "l2Forward";
+ private static final String L2BROADCAST = "l2Broadcast";
private static final String IPSUBNETS = "ipSubnets";
private static final String BORDERROUTES = "borderRoutes";
private static final String IPPREFIX = "ipPrefix";
@@ -78,12 +79,14 @@
if (jsonNode.hasNonNull(L2FORWARD)) {
l2Forward = jsonNode.get(L2FORWARD).asBoolean();
}
+ boolean l2Broadcast = true;
+ if (jsonNode.hasNonNull(L2BROADCAST)) {
+ l2Broadcast = jsonNode.get(L2BROADCAST).asBoolean();
+ }
try {
l2Networks.add(new L2Network(
- jsonNode.get(NAME).asText(),
- ifaces,
- EncapsulationType.enumFromString(encapsulation),
- l2Forward));
+ jsonNode.get(NAME).asText(), ifaces, EncapsulationType.enumFromString(encapsulation),
+ l2Forward, l2Broadcast));
} catch (Exception e) {
log.warn("simple fabric network config l2Network parse failed; skip: error={} jsonNode={}", jsonNode);
}
diff --git a/apps/simplefabric/src/main/java/org/onosproject/simplefabric/SimpleFabricL2Forward.java b/apps/simplefabric/src/main/java/org/onosproject/simplefabric/SimpleFabricL2Forward.java
index 41f0253..a67ed1a 100644
--- a/apps/simplefabric/src/main/java/org/onosproject/simplefabric/SimpleFabricL2Forward.java
+++ b/apps/simplefabric/src/main/java/org/onosproject/simplefabric/SimpleFabricL2Forward.java
@@ -256,15 +256,15 @@
private Set<Intent> generateL2NetworkIntents(L2Network l2Network) {
return new ImmutableSet.Builder<Intent>()
- .addAll(buildBrcIntents(l2Network))
- .addAll(buildUniIntents(l2Network, hostsFromL2Network(l2Network)))
- .build();
+ .addAll(buildBrcIntents(l2Network))
+ .addAll(buildUniIntents(l2Network, hostsFromL2Network(l2Network)))
+ .build();
}
// Build Boadcast Intents for a L2 Network.
private Set<SinglePointToMultiPointIntent> buildBrcIntents(L2Network l2Network) {
Set<Interface> interfaces = l2Network.interfaces();
- if (!l2Network.l2Forward() || interfaces.size() < 2) {
+ if (interfaces.size() < 2 || !l2Network.l2Forward() || !l2Network.l2Broadcast()) {
return ImmutableSet.of();
}
Set<SinglePointToMultiPointIntent> brcIntents = Sets.newHashSet();
@@ -384,7 +384,7 @@
// Dump command handler
private void dump(String subject, PrintStream out) {
- if (subject == "intents") {
+ if ("intents".equals(subject)) {
out.println("L2Forward Broadcast Intents:\n");
for (SinglePointToMultiPointIntent intent: bctIntentsMap.values()) {
out.println(" " + intent.key().toString()
diff --git a/apps/simplefabric/src/main/java/org/onosproject/simplefabric/SimpleFabricManager.java b/apps/simplefabric/src/main/java/org/onosproject/simplefabric/SimpleFabricManager.java
index 2bb53c9..81dd602 100644
--- a/apps/simplefabric/src/main/java/org/onosproject/simplefabric/SimpleFabricManager.java
+++ b/apps/simplefabric/src/main/java/org/onosproject/simplefabric/SimpleFabricManager.java
@@ -71,7 +71,6 @@
import java.io.OutputStream;
import java.io.PrintStream;
import java.nio.ByteBuffer;
-import java.util.Iterator;
import java.util.HashSet;
import java.util.Collection;
import java.util.Set;
@@ -243,7 +242,7 @@
for (Host host : hostService.getHosts()) {
// consider host with ip only
if (!host.ipAddresses().isEmpty()) {
- Interface iface = getAvailableDeviceHostInterface(host);
+ Interface iface = findAvailableDeviceHostInterface(host);
if (iface != null && newL2Network.contains(iface)) {
newL2Network.addHost(host);
}
@@ -358,11 +357,6 @@
}
@Override
- public MacAddress getVMacForIp(IpAddress ip) {
- return virtualGatewayIpMacMap.get(ip);
- }
-
- @Override
public boolean isVMac(MacAddress mac) {
return virtualGatewayIpMacMap.containsValue(mac);
}
@@ -373,6 +367,11 @@
}
@Override
+ public MacAddress findVMacForIp(IpAddress ip) {
+ return virtualGatewayIpMacMap.get(ip);
+ }
+
+ @Override
public L2Network findL2Network(ConnectPoint port, VlanId vlanId) {
for (L2Network l2Network : l2Networks) {
if (l2Network.contains(port, vlanId)) {
@@ -394,34 +393,30 @@
@Override
public IpSubnet findIpSubnet(IpAddress ip) {
- Iterator<IpSubnet> it;
if (ip.isIp4()) {
- it = ip4SubnetTable.getValuesForKeysPrefixing(
- createBinaryString(IpPrefix.valueOf(ip, Ip4Address.BIT_LENGTH))).iterator();
+ return ip4SubnetTable.getValueForLongestKeyPrefixing(
+ createBinaryString(IpPrefix.valueOf(ip, Ip4Address.BIT_LENGTH)));
} else {
- it = ip6SubnetTable.getValuesForKeysPrefixing(
- createBinaryString(IpPrefix.valueOf(ip, Ip6Address.BIT_LENGTH))) .iterator();
+ return ip6SubnetTable.getValueForLongestKeyPrefixing(
+ createBinaryString(IpPrefix.valueOf(ip, Ip6Address.BIT_LENGTH)));
}
- return (it.hasNext()) ? it.next() : null;
}
@Override
public Route findBorderRoute(IpAddress ip) {
// ASSUME: ipAddress is out of ipSubnet
- Iterator<Route> it;
if (ip.isIp4()) {
- it = ip4BorderRouteTable.getValuesForKeysPrefixing(
- createBinaryString(IpPrefix.valueOf(ip, Ip4Address.BIT_LENGTH))) .iterator();
+ return ip4BorderRouteTable.getValueForLongestKeyPrefixing(
+ createBinaryString(IpPrefix.valueOf(ip, Ip4Address.BIT_LENGTH)));
} else {
- it = ip6BorderRouteTable.getValuesForKeysPrefixing(
- createBinaryString(IpPrefix.valueOf(ip, Ip6Address.BIT_LENGTH))) .iterator();
+ return ip6BorderRouteTable.getValueForLongestKeyPrefixing(
+ createBinaryString(IpPrefix.valueOf(ip, Ip6Address.BIT_LENGTH)));
}
- return (it.hasNext()) ? it.next() : null;
}
@Override
- public Interface getHostInterface(Host host) {
+ public Interface findHostInterface(Host host) {
return interfaceService.getInterfaces().stream()
.filter(iface -> iface.connectPoint().equals(host.location()) &&
iface.vlan().equals(host.vlan()))
@@ -429,7 +424,7 @@
.orElse(null);
}
- private Interface getAvailableDeviceHostInterface(Host host) {
+ private Interface findAvailableDeviceHostInterface(Host host) {
return interfaceService.getInterfaces().stream()
.filter(iface -> iface.connectPoint().equals(host.location()) &&
iface.vlan().equals(host.vlan()))
@@ -439,29 +434,6 @@
}
@Override
- public boolean isIpAddressLocal(IpAddress ip) {
- boolean result;
- if (ip.isIp4()) {
- return ip4SubnetTable.getValuesForKeysPrefixing(
- createBinaryString(IpPrefix.valueOf(ip, Ip4Address.BIT_LENGTH)))
- .iterator().hasNext();
- } else {
- return ip6SubnetTable.getValuesForKeysPrefixing(
- createBinaryString(IpPrefix.valueOf(ip, Ip6Address.BIT_LENGTH)))
- .iterator().hasNext();
- }
- }
-
- @Override
- public boolean isIpPrefixLocal(IpPrefix ipPrefix) {
- if (ipPrefix.isIp4()) {
- return (ip4SubnetTable.getValueForExactKey(createBinaryString(ipPrefix)) != null);
- } else {
- return (ip6SubnetTable.getValueForExactKey(createBinaryString(ipPrefix)) != null);
- }
- }
-
- @Override
public boolean requestMac(IpAddress ip) {
IpSubnet ipSubnet = findIpSubnet(ip);
if (ipSubnet == null) {
@@ -510,8 +482,10 @@
// Dump handler
protected void dump(String subject, PrintStream out) {
- if (subject == "show") {
+ if ("show".equals(subject)) {
out.println("Static Configuration Flag:");
+ out.println(" ALLOW_IPV6="
+ + SimpleFabricService.ALLOW_IPV6);
out.println(" ALLOW_ETH_ADDRESS_SELECTOR="
+ SimpleFabricService.ALLOW_ETH_ADDRESS_SELECTOR);
out.println(" REACTIVE_SINGLE_TO_SINGLE="
diff --git a/apps/simplefabric/src/main/java/org/onosproject/simplefabric/SimpleFabricNeighbour.java b/apps/simplefabric/src/main/java/org/onosproject/simplefabric/SimpleFabricNeighbour.java
index 9d0b3fc..d796346 100644
--- a/apps/simplefabric/src/main/java/org/onosproject/simplefabric/SimpleFabricNeighbour.java
+++ b/apps/simplefabric/src/main/java/org/onosproject/simplefabric/SimpleFabricNeighbour.java
@@ -130,7 +130,7 @@
* @param context the message context
*/
protected void handleRequest(NeighbourMessageContext context) {
- MacAddress mac = simpleFabric.getVMacForIp(context.target());
+ MacAddress mac = simpleFabric.findVMacForIp(context.target());
if (mac != null) {
log.trace("simple fabric neightbour request on virtualGatewayAddress {}; response to {} {} mac={}",
context.target(), context.inPort(), context.vlan(), mac);
@@ -181,7 +181,7 @@
L2Network l2Network = simpleFabric.findL2Network(context.inPort(), context.vlan());
if (l2Network != null) {
// TODO: need to check and update simpleFabric.L2Network
- MacAddress mac = simpleFabric.getVMacForIp(context.target());
+ MacAddress mac = simpleFabric.findVMacForIp(context.target());
if (mac != null) {
log.trace("simple fabric neightbour response message to virtual gateway; drop: {} {} target={}",
context.inPort(), context.vlan(), context.target());
@@ -192,7 +192,7 @@
log.trace("simple fabric neightbour response message forward: {} {} target={} -> {}",
context.inPort(), context.vlan(), context.target(), hosts);
hosts.stream()
- .map(host -> simpleFabric.getHostInterface(host))
+ .map(host -> simpleFabric.findHostInterface(host))
.filter(Objects::nonNull)
.forEach(context::forward);
}
diff --git a/apps/simplefabric/src/main/java/org/onosproject/simplefabric/SimpleFabricReactiveRouting.java b/apps/simplefabric/src/main/java/org/onosproject/simplefabric/SimpleFabricReactiveRouting.java
index 10148c8..1a9d64f 100644
--- a/apps/simplefabric/src/main/java/org/onosproject/simplefabric/SimpleFabricReactiveRouting.java
+++ b/apps/simplefabric/src/main/java/org/onosproject/simplefabric/SimpleFabricReactiveRouting.java
@@ -60,6 +60,7 @@
import org.onosproject.net.intent.IntentService;
import org.onosproject.net.intent.Key;
import org.onosproject.net.intent.MultiPointToSinglePointIntent;
+import org.onosproject.net.intf.Interface;
import org.onosproject.net.link.LinkService;
import org.onosproject.net.packet.DefaultOutboundPacket;
import org.onosproject.net.packet.InboundPacket;
@@ -68,7 +69,6 @@
import org.onosproject.net.packet.PacketPriority;
import org.onosproject.net.packet.PacketProcessor;
import org.onosproject.net.packet.PacketService;
-import org.onosproject.net.Port;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -226,7 +226,8 @@
// check if this devices has the ipSubnet, then add ip broadcast flue rule
L2Network l2Network = simpleFabric.findL2Network(subnet.l2NetworkName());
if (l2Network != null && l2Network.contains(device.id())) {
- newInterceptFlowRules.add(generateLocalSubnetIpBctFlowRule(device.id(), subnet.ipPrefix()));
+ newInterceptFlowRules.add(generateLocalSubnetIpBctFlowRule(device.id(), subnet.ipPrefix(),
+ l2Network));
}
// JUST FOR FLOW RULE TEST ONLY
//newInterceptFlowRules.add(generateTestFlowRule(device.id(), subnet.ipPrefix()));
@@ -256,7 +257,7 @@
}
}
- private FlowRule generateInterceptFlowRule(boolean isLocalSubnet, DeviceId deviceId, IpPrefix prefix) {
+ private FlowRule generateInterceptFlowRule(boolean isDstLocalSubnet, DeviceId deviceId, IpPrefix prefix) {
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
if (prefix.isIp4()) {
selector.matchEthType(Ethernet.TYPE_IPV4);
@@ -271,7 +272,7 @@
}
FlowRule rule = DefaultFlowRule.builder()
.forDevice(deviceId)
- .withPriority(reactivePriority(false, isLocalSubnet, prefix.prefixLength()))
+ .withPriority(reactivePriority(false, isDstLocalSubnet, prefix.prefixLength()))
.withSelector(selector.build())
.withTreatment(DefaultTrafficTreatment.builder().punt().build())
.fromApp(reactiveAppId)
@@ -280,7 +281,7 @@
return rule;
}
- private FlowRule generateLocalSubnetIpBctFlowRule(DeviceId deviceId, IpPrefix prefix) {
+ private FlowRule generateLocalSubnetIpBctFlowRule(DeviceId deviceId, IpPrefix prefix, L2Network l2Network) {
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
IpPrefix bctPrefix;
if (prefix.isIp4()) {
@@ -301,8 +302,10 @@
}
TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
Set<ConnectPoint> newEgressPoints = new HashSet<>();
- for (Port port : deviceService.getPorts(deviceId)) {
- treatment.setOutput(port.number());
+ for (Interface iface : l2Network.interfaces()) {
+ if (iface.connectPoint().deviceId().equals(deviceId)) {
+ treatment.setOutput(iface.connectPoint().port());
+ }
}
FlowRule rule = DefaultFlowRule.builder()
.forDevice(deviceId)
@@ -548,8 +551,9 @@
private boolean checkVirtualGatewayIpPacket(InboundPacket pkt, IpAddress srcIp, IpAddress dstIp) {
Ethernet ethPkt = pkt.parsed(); // assume valid
- MacAddress mac = simpleFabric.getVMacForIp(dstIp);
- if (mac == null || !ethPkt.getDestinationMAC().equals(mac)) {
+ MacAddress mac = simpleFabric.findVMacForIp(dstIp);
+ if (mac == null || !simpleFabric.isVMac(ethPkt.getDestinationMAC())) {
+ /* Destination MAC should be any of virtual gateway macs */
return false;
} else if (dstIp.isIp4()) {
IPv4 ipv4Packet = (IPv4) ethPkt.getPayload();
@@ -616,7 +620,6 @@
IpAddress dstNextHop = dstIp;
MacAddress treatmentSrcMac = ethPkt.getDestinationMAC();
int borderRoutePrefixLength = 0;
- boolean isLocalSubnet = true;
boolean updateMac = simpleFabric.isVMac(ethPkt.getDestinationMAC());
// check subnet local or route
@@ -624,25 +627,25 @@
if (srcSubnet == null) {
Route route = simpleFabric.findBorderRoute(srcIp);
if (route == null) {
- log.warn("route unknown: srcIp={}", srcIp);
+ log.warn("unknown srcIp; drop: srcCp={} srcIp={} dstIp={} ipProto={}",
+ srcCp, srcIp, dstIp, ipProto);
return;
}
srcPrefix = route.prefix();
srcNextHop = route.nextHop();
borderRoutePrefixLength = route.prefix().prefixLength();
- isLocalSubnet = false;
}
IpSubnet dstSubnet = simpleFabric.findIpSubnet(dstIp);
if (dstSubnet == null) {
Route route = simpleFabric.findBorderRoute(dstIp);
if (route == null) {
- log.warn("route unknown: dstIp={}", dstIp);
+ log.warn("unknown dstIp; drop: srcCp={} srcIp={} dstIp={} ipProto={}",
+ srcCp, srcIp, dstIp, ipProto);
return;
}
dstPrefix = route.prefix();
dstNextHop = route.nextHop();
borderRoutePrefixLength = route.prefix().prefixLength();
- isLocalSubnet = false;
}
if (dstSubnet != null) {
@@ -687,7 +690,7 @@
srcIp, dstIp, ethPkt.getSourceMAC(), ethPkt.getDestinationMAC(),
ethPkt.getVlanID(), ipProto, updateMac);
setUpConnectivity(srcCp, ipProto, srcPrefix, dstPrefix, dstNextHop, treatmentSrcMac, encap, updateMac,
- isLocalSubnet, borderRoutePrefixLength);
+ dstSubnet != null, borderRoutePrefixLength);
forwardPacketToDstIp(context, dstNextHop, treatmentSrcMac, updateMac);
}
@@ -737,18 +740,7 @@
private boolean setUpConnectivity(ConnectPoint srcCp, byte ipProto, IpPrefix srcPrefix, IpPrefix dstPrefix,
IpAddress nextHopIp, MacAddress treatmentSrcMac,
EncapsulationType encap, boolean updateMac,
- boolean isLocalSubnet, int borderRoutePrefixLength) {
- Key key;
- String keyProtoTag = "";
- if (simpleFabric.REACTIVE_MATCH_IP_PROTO) {
- keyProtoTag = "-p" + ipProto;
- }
- if (simpleFabric.REACTIVE_SINGLE_TO_SINGLE) {
- key = Key.of(srcPrefix.toString() + "-to-" + dstPrefix.toString() + keyProtoTag, reactiveAppId);
- } else {
- key = Key.of(dstPrefix.toString() + keyProtoTag, reactiveAppId);
- }
-
+ boolean isDstLocalSubnet, int borderRoutePrefixLength) {
if (!(simpleFabric.findL2Network(srcCp, VlanId.NONE) != null ||
(simpleFabric.REACTIVE_ALLOW_LINK_CP && !linkService.getIngressLinks(srcCp).isEmpty()))) {
log.warn("NO REGI for srcCp not in L2Network; srcCp={} srcPrefix={} dstPrefix={} nextHopIp={}",
@@ -804,6 +796,19 @@
}
}
+ Key key;
+ String keyProtoTag = "";
+ if (simpleFabric.REACTIVE_MATCH_IP_PROTO) {
+ keyProtoTag = "-p" + ipProto;
+ }
+ if (simpleFabric.REACTIVE_SINGLE_TO_SINGLE) {
+ // allocate intent per (srcPrefix, dstPrefix)
+ key = Key.of(srcPrefix.toString() + "-to-" + dstPrefix.toString() + keyProtoTag, reactiveAppId);
+ } else {
+ // allocate intent per (srcDeviceId, dstPrefix)
+ key = Key.of(srcCp.deviceId().toString() + "-to-" + dstPrefix.toString() + keyProtoTag, reactiveAppId);
+ }
+
// check and merge already existing ingress points
Set<ConnectPoint> ingressPoints = new HashSet<>();
MultiPointToSinglePointIntent existingIntent = (MultiPointToSinglePointIntent) intentService.getIntent(key);
@@ -825,7 +830,7 @@
}
// priority for forwarding case
- int priority = reactivePriority(true, isLocalSubnet, borderRoutePrefixLength);
+ int priority = reactivePriority(true, isDstLocalSubnet, borderRoutePrefixLength);
MultiPointToSinglePointIntent newIntent = MultiPointToSinglePointIntent.builder()
.key(key)
@@ -863,14 +868,14 @@
}
// priority calculator
- private int reactivePriority(boolean isForward, boolean isLocalSubnet, int borderRoutePrefixLength) {
- if (isLocalSubnet) { // localSubnet <-> localSubnet
+ private int reactivePriority(boolean isForward, boolean isDstLocalSubnet, int borderRoutePrefixLength) {
+ if (isDstLocalSubnet) { // -> dst:localSubnet
if (isForward) {
return simpleFabric.PRI_REACTIVE_LOCAL_FORWARD;
} else { // isInterncept
return simpleFabric.PRI_REACTIVE_LOCAL_INTERCEPT;
}
- } else { // isBorder: localSubnet <-> boarderRouteGateway
+ } else { // -> dst:boarderRouteNextHop
int offset;
if (isForward) {
offset = simpleFabric.PRI_REACTIVE_BORDER_FORWARD;
@@ -897,7 +902,7 @@
// Dump Cli Handler
private void dump(String subject, PrintStream out) {
- if (subject == "intents") {
+ if ("intents".equals(subject)) {
out.println("Reactive Routing Route Intents:\n");
for (Intent entry : intentService.getIntents()) {
if (reactiveAppId.equals(entry.appId())) {
@@ -931,7 +936,7 @@
}
out.println("");
- } else if (subject == "reactive-intents") {
+ } else if ("reactive-intents".equals(subject)) {
for (Intent entry : intentService.getIntents()) {
if (reactiveAppId.equals(entry.appId())) {
MultiPointToSinglePointIntent intent = (MultiPointToSinglePointIntent) entry;
diff --git a/apps/simplefabric/src/main/java/org/onosproject/simplefabric/SimpleFabricService.java b/apps/simplefabric/src/main/java/org/onosproject/simplefabric/SimpleFabricService.java
index c27a828..be2bed3 100644
--- a/apps/simplefabric/src/main/java/org/onosproject/simplefabric/SimpleFabricService.java
+++ b/apps/simplefabric/src/main/java/org/onosproject/simplefabric/SimpleFabricService.java
@@ -16,7 +16,6 @@
package org.onosproject.simplefabric;
import org.onlab.packet.IpAddress;
-import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onosproject.core.ApplicationId;
@@ -96,14 +95,6 @@
Set<Route> getBorderRoutes();
/**
- * Gets Virtual Gateway Mac Address for Local Subnet Virtual Gateway Ip.
- *
- * @param ip the ip to check for Virtual Gateway Ip
- * @return mac address of virtual gateway
- */
- MacAddress getVMacForIp(IpAddress ip);
-
- /**
* Evaluates whether a mac is of Virtual Gateway Mac Addresses.
*
* @param mac the MacAddress to evaluate
@@ -120,6 +111,14 @@
boolean isL2NetworkInterface(Interface intf);
/**
+ * Find Virtual Gateway Mac Address for Local Subnet Virtual Gateway Ip.
+ *
+ * @param ip the ip to check for Virtual Gateway Ip
+ * @return mac address of virtual gateway
+ */
+ MacAddress findVMacForIp(IpAddress ip);
+
+ /**
* Finds the L2 Network with given port and vlanId.
*
* @param port the port to be matched
@@ -159,23 +158,7 @@
* @param host the host
* @return the interface related to the host
*/
- Interface getHostInterface(Host host);
-
- /**
- * Evaluates whether an IP address belongs to local SDN network.
- *
- * @param ipAddress the IP address to evaluate
- * @return true if the IP address belongs to local SDN network, otherwise false
- */
- boolean isIpAddressLocal(IpAddress ipAddress);
-
- /**
- * Evaluates whether an IP prefix belongs to local SDN network.
- *
- * @param ipPrefix the IP prefix to evaluate
- * @return true if the IP prefix belongs to local SDN network, otherwise false
- */
- boolean isIpPrefixLocal(IpPrefix ipPrefix);
+ Interface findHostInterface(Host host);
/**
* Sends Neighbour Query (ARP or NDP) to Find Host Location.
diff --git a/apps/restconf/utils/src/main/java/org/onosproject/restconf/utils/exceptions/package-info.java b/apps/simplefabric/src/main/java/org/onosproject/simplefabric/SimpleFabricWebApplication.java
similarity index 63%
copy from apps/restconf/utils/src/main/java/org/onosproject/restconf/utils/exceptions/package-info.java
copy to apps/simplefabric/src/main/java/org/onosproject/simplefabric/SimpleFabricWebApplication.java
index a0fe88e..d82de73 100644
--- a/apps/restconf/utils/src/main/java/org/onosproject/restconf/utils/exceptions/package-info.java
+++ b/apps/simplefabric/src/main/java/org/onosproject/simplefabric/SimpleFabricWebApplication.java
@@ -14,7 +14,19 @@
* limitations under the License.
*/
+package org.onosproject.simplefabric;
+
+import org.onlab.rest.AbstractWebApplication;
+
+import java.util.Set;
+
/**
- * Parse utils custom exceptions.
+ * SIMPLE_FABRIC REST API web application.
*/
-package org.onosproject.restconf.utils.exceptions;
\ No newline at end of file
+public class SimpleFabricWebApplication extends AbstractWebApplication {
+ @Override
+ public Set<Class<?>> getClasses() {
+ return getClasses(SimpleFabricWebResource.class);
+ }
+}
+
diff --git a/apps/simplefabric/src/main/java/org/onosproject/simplefabric/SimpleFabricWebResource.java b/apps/simplefabric/src/main/java/org/onosproject/simplefabric/SimpleFabricWebResource.java
new file mode 100644
index 0000000..f1e9af7
--- /dev/null
+++ b/apps/simplefabric/src/main/java/org/onosproject/simplefabric/SimpleFabricWebResource.java
@@ -0,0 +1,108 @@
+/*
+ * 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.simplefabric;
+
+import org.onosproject.rest.AbstractWebResource;
+
+import java.io.ByteArrayOutputStream;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Response;
+
+/**
+ * Manage SIMPLE_FABRIC Status.
+ */
+@Path("")
+public class SimpleFabricWebResource extends AbstractWebResource {
+
+ /**
+ * SIMPLE_FABRIC Show Status; dummy for now.
+ *
+ * @return 200 OK
+ */
+ @GET
+ @Path("status")
+ public Response queryStatus() {
+ return Response.ok("ok").build();
+ }
+
+ /**
+ * SIMPLE_FABRIC Show Configurations.
+ *
+ * @return 200 OK
+ */
+ @GET
+ @Path("show")
+ public Response queryShow() {
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ get(SimpleFabricService.class).dumpToStream("show", outputStream);
+ return Response.ok(outputStream.toString()).build();
+ }
+
+ /**
+ * SIMPLE_FABRIC Intents Infos.
+ *
+ * @return 200 OK
+ */
+ @GET
+ @Path("intents")
+ public Response queryIntents() {
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ get(SimpleFabricService.class).dumpToStream("intents", outputStream);
+ return Response.ok(outputStream.toString()).build();
+ }
+
+ /**
+ * SIMPLE_FABRIC Reactive Intents Infos.
+ *
+ * @return 200 OK
+ */
+ @GET
+ @Path("reactive-intents")
+ public Response queryReactiveIntents() {
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ get(SimpleFabricService.class).dumpToStream("reactive-intents", outputStream);
+ return Response.ok(outputStream.toString()).build();
+ }
+
+ /**
+ * Trigger SimpleFabric Service Refresh.
+ *
+ * @return 204 No Content
+ */
+ @PUT
+ @Path("refresh")
+ public Response triggerRefresh() {
+ get(SimpleFabricService.class).triggerRefresh();
+ return Response.status(204).build();
+ }
+
+ /**
+ * Trigger SimpleFabric Service Flush Reactive Intents.
+ *
+ * @return 204 No Content
+ */
+ @PUT
+ @Path("flush")
+ public Response triggerFlush() {
+ get(SimpleFabricService.class).triggerFlush();
+ return Response.status(204).build();
+ }
+
+}
+
diff --git a/apps/simplefabric/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/apps/simplefabric/src/main/resources/OSGI-INF/blueprint/shell-config.xml
new file mode 100644
index 0000000..7b6893b
--- /dev/null
+++ b/apps/simplefabric/src/main/resources/OSGI-INF/blueprint/shell-config.xml
@@ -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.
+ -->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+
+ <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
+ <command>
+ <action class="org.onosproject.simplefabric.SimpleFabricCommand"/>
+ <completers>
+ <ref component-id="SimpleFabricCommandCompleter"/>
+ </completers>
+ </command>
+ </command-bundle>
+
+ <bean id="SimpleFabricCommandCompleter" class="org.onosproject.simplefabric.SimpleFabricCommandCompleter"/>
+</blueprint>
diff --git a/apps/simplefabric/src/main/webapp/WEB-INF/web.xml b/apps/simplefabric/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..a0e0004
--- /dev/null
+++ b/apps/simplefabric/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2017-present Open Networking Foundation
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
+ id="ONOS" version="2.5">
+ <display-name>Simple Fabric application REST API</display-name>
+
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>Secured</web-resource-name>
+ <url-pattern>/*</url-pattern>
+ </web-resource-collection>
+ <auth-constraint>
+ <role-name>admin</role-name>
+ </auth-constraint>
+ </security-constraint>
+
+ <security-role>
+ <role-name>admin</role-name>
+ </security-role>
+
+ <login-config>
+ <auth-method>BASIC</auth-method>
+ <realm-name>karaf</realm-name>
+ </login-config>
+
+ <servlet>
+ <servlet-name>JAX-RS Service</servlet-name>
+ <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+ <init-param>
+ <param-name>javax.ws.rs.Application</param-name>
+ <param-value>org.onosproject.simplefabric.SimpleFabricWebApplication</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>JAX-RS Service</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+
+</web-app>
diff --git a/apps/t3/BUCK b/apps/t3/BUCK
index bca18be..a21999d 100644
--- a/apps/t3/BUCK
+++ b/apps/t3/BUCK
@@ -6,16 +6,23 @@
'//core/api:onos-api',
'//lib:org.apache.karaf.shell.console',
'//cli:onos-cli',
+ '//drivers/default:onos-drivers-default',
+]
+
+TEST_DEPS = [
+ '//lib:TEST_ADAPTERS',
+ '//utils/misc:onlab-misc',
]
osgi_jar_with_tests (
deps = COMPILE_DEPS,
+ test_deps = TEST_DEPS,
)
onos_app (
title = 'Trellis Troubleshooting Toolkit',
- category = 'Utility',
- url = 'http://onosproject.org',
+ category = 'Utilities',
+ url = 'https://wiki.opencord.org/pages/viewpage.action?pageId=4456974',
description = 'Provides static analysis of flows and groups ' +
'to determine the possible paths a packet may take.',
)
diff --git a/apps/t3/pom.xml b/apps/t3/pom.xml
index ef1349e..e82a900 100644
--- a/apps/t3/pom.xml
+++ b/apps/t3/pom.xml
@@ -54,6 +54,12 @@
</dependency>
<dependency>
<groupId>org.onosproject</groupId>
+ <artifactId>onos-api</artifactId>
+ <scope>test</scope>
+ <classifier>tests</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
<artifactId>onos-core-primitives</artifactId>
<version>${project.version}</version>
</dependency>
@@ -70,6 +76,16 @@
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr.annotations</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-drivers-default</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onlab-misc</artifactId>
+ <version>${project.version}</version>
+ </dependency>
</dependencies>
</project>
diff --git a/apps/t3/src/main/java/org/onosproject/t3/api/GroupsInDevice.java b/apps/t3/src/main/java/org/onosproject/t3/api/GroupsInDevice.java
new file mode 100644
index 0000000..3cfb41a
--- /dev/null
+++ b/apps/t3/src/main/java/org/onosproject/t3/api/GroupsInDevice.java
@@ -0,0 +1,81 @@
+/*
+ * 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.t3.api;
+
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.group.Group;
+
+import java.util.List;
+
+/**
+ * Class to represent the groups in a device for a given output and packet.
+ */
+//FIXME consider removing.
+public class GroupsInDevice {
+
+ private ConnectPoint output;
+ private List<Group> groups;
+ private TrafficSelector selector;
+
+ /**
+ * Saves the given groups for the output connect point and the selector.
+ * @param output the output connect point
+ * @param groups the groups
+ * @param selector the selector representing the final packet
+ */
+ public GroupsInDevice(ConnectPoint output, List<Group> groups, TrafficSelector selector) {
+
+ this.output = output;
+ this.groups = groups;
+ this.selector = selector;
+ }
+
+ /**
+ * Returns the output connect point.
+ * @return the connect point
+ */
+ public ConnectPoint getOutput() {
+ return output;
+ }
+
+ /**
+ * Returns the groups.
+ * @return groups.
+ */
+ public List<Group> getGroups() {
+ return groups;
+ }
+
+ /**
+ * Returns the final packet after traversing the network.
+ * @return the selector with packet info
+ */
+ public TrafficSelector getFinalPacket() {
+ return selector;
+ }
+
+ @Override
+ public String toString() {
+ return "GroupsInDevice{" +
+ "output=" + output +
+ ", groups=" + groups +
+ ", selector=" + selector +
+ '}';
+ }
+
+}
diff --git a/apps/t3/src/main/java/org/onosproject/t3/api/StaticPacketTrace.java b/apps/t3/src/main/java/org/onosproject/t3/api/StaticPacketTrace.java
index e6ee8e8..e56035d 100644
--- a/apps/t3/src/main/java/org/onosproject/t3/api/StaticPacketTrace.java
+++ b/apps/t3/src/main/java/org/onosproject/t3/api/StaticPacketTrace.java
@@ -16,10 +16,154 @@
package org.onosproject.t3.api;
+import com.google.common.collect.ImmutableList;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.flow.FlowEntry;
+import org.onosproject.net.flow.TrafficSelector;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
/**
* Encapsulates the result of tracing a packet (traffic selector) through
* the current topology.
*/
public class StaticPacketTrace {
+ private final TrafficSelector inPacket;
+ private final ConnectPoint in;
+ List<List<ConnectPoint>> completePaths;
+ private Map<DeviceId, List<GroupsInDevice>> outputsForDevice;
+ private Map<DeviceId, List<FlowEntry>> flowsForDevice;
+ private StringBuilder resultMessage;
+
+ /**
+ * Builds the trace with a given packet and a connect point.
+ *
+ * @param packet the packet to trace
+ * @param in the initial connect point
+ */
+ public StaticPacketTrace(TrafficSelector packet, ConnectPoint in) {
+ this.inPacket = packet;
+ this.in = in;
+ completePaths = new ArrayList<>();
+ outputsForDevice = new HashMap<>();
+ flowsForDevice = new HashMap<>();
+ resultMessage = new StringBuilder();
+ }
+
+ /**
+ * Return the initial packet.
+ *
+ * @return the initial packet in the form of a selector.
+ */
+ public TrafficSelector getInitialPacket() {
+ return inPacket;
+ }
+
+ /**
+ * Returns the first connect point the packet came in through.
+ *
+ * @return the connect point
+ */
+ public ConnectPoint getInitialConnectPoint() {
+ return in;
+ }
+
+ /**
+ * Add a result message for the Trace.
+ *
+ * @param resultMessage the message
+ */
+ public void addResultMessage(String resultMessage) {
+ if (this.resultMessage.length() != 0) {
+ this.resultMessage.append("\n");
+ }
+ this.resultMessage.append(resultMessage);
+ }
+
+ /**
+ * Return the result message.
+ *
+ * @return the message
+ */
+ public String resultMessage() {
+ return resultMessage.toString();
+ }
+
+ /**
+ * Adds the groups for a given device.
+ *
+ * @param deviceId the device
+ * @param outputPath the groups in device objects
+ */
+ public void addGroupOutputPath(DeviceId deviceId, GroupsInDevice outputPath) {
+ if (!outputsForDevice.containsKey(deviceId)) {
+ outputsForDevice.put(deviceId, new ArrayList<>());
+ }
+ outputsForDevice.get(deviceId).add(outputPath);
+ }
+
+ /**
+ * Returns all the possible group-based outputs for a given device.
+ *
+ * @param deviceId the device
+ * @return the list of Groups for this device.
+ */
+ public List<GroupsInDevice> getGroupOuputs(DeviceId deviceId) {
+ return outputsForDevice.get(deviceId);
+ }
+
+ /**
+ * Adds a complete possible path.
+ *
+ * @param completePath the path
+ */
+ public void addCompletePath(List<ConnectPoint> completePath) {
+ completePaths.add(completePath);
+ }
+
+ /**
+ * Return all the possible path the packet can take through the network.
+ *
+ * @return a list of paths
+ */
+ public List<List<ConnectPoint>> getCompletePaths() {
+ return completePaths;
+ }
+
+ /**
+ * Add the flows traversed by the packet in a given device.
+ *
+ * @param deviceId the device considered
+ * @param flows the flows
+ */
+ public void addFlowsForDevice(DeviceId deviceId, List<FlowEntry> flows) {
+ flowsForDevice.put(deviceId, flows);
+ }
+
+ /**
+ * Returns the flows matched by this trace's packet for a given device.
+ *
+ * @param deviceId the device
+ * @return the flows matched
+ */
+ public List<FlowEntry> getFlowsForDevice(DeviceId deviceId) {
+ return flowsForDevice.getOrDefault(deviceId, ImmutableList.of());
+ }
+
+ @Override
+ public String toString() {
+ return "StaticPacketTrace{" +
+ "inPacket=" + inPacket +
+ ", in=" + in +
+ ", completePaths=" + completePaths +
+ ", outputsForDevice=" + outputsForDevice +
+ ", flowsForDevice=" + flowsForDevice +
+ ", resultMessage=" + resultMessage +
+ '}';
+ }
}
diff --git a/apps/t3/src/main/java/org/onosproject/t3/cli/TroubleshootTraceCommand.java b/apps/t3/src/main/java/org/onosproject/t3/cli/TroubleshootTraceCommand.java
new file mode 100644
index 0000000..c809065
--- /dev/null
+++ b/apps/t3/src/main/java/org/onosproject/t3/cli/TroubleshootTraceCommand.java
@@ -0,0 +1,255 @@
+/*
+ * 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.
+ */
+
+package org.onosproject.t3.cli;
+
+import org.apache.karaf.shell.commands.Command;
+import org.apache.karaf.shell.commands.Option;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.MplsLabel;
+import org.onlab.packet.TpPort;
+import org.onlab.packet.VlanId;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.group.GroupBucket;
+import org.onosproject.t3.api.StaticPacketTrace;
+import org.onosproject.t3.api.TroubleshootService;
+
+import java.util.List;
+
+import static org.onlab.packet.EthType.EtherType;
+
+/**
+ * Starts a Static Packet Trace for a given input and prints the result.
+ */
+@Command(scope = "onos", name = "troubleshoot",
+ description = "troubleshoots flows and groups between source and destination")
+public class TroubleshootTraceCommand extends AbstractShellCommand {
+
+
+ private static final String FLOW_SHORT_FORMAT = " %s, bytes=%s, packets=%s, "
+ + "table=%s, priority=%s, selector=%s, treatment=%s";
+
+ private static final String GROUP_FORMAT =
+ " id=0x%s, state=%s, type=%s, bytes=%s, packets=%s, appId=%s, referenceCount=%s";
+ private static final String GROUP_BUCKET_FORMAT =
+ " id=0x%s, bucket=%s, bytes=%s, packets=%s, actions=%s";
+
+ @Option(name = "-v", aliases = "--verbose", description = "Outputs complete path")
+ private boolean verbosity1 = false;
+
+ @Option(name = "-vv", aliases = "--veryverbose", description = "Outputs flows and groups for every device")
+ private boolean verbosity2 = false;
+
+ @Option(name = "-s", aliases = "--srcIp", description = "Source IP")
+ String srcIp = null;
+
+ @Option(name = "-sp", aliases = "--srcPort", description = "Source Port", required = true)
+ String srcPort = null;
+
+ @Option(name = "-sm", aliases = "--srcMac", description = "Source MAC")
+ String srcMac = null;
+
+ @Option(name = "-et", aliases = "--ethType", description = "ETH Type", valueToShowInHelp = "ipv4")
+ String ethType = "ipv4";
+
+ @Option(name = "-stp", aliases = "--srcTcpPort", description = "Source TCP Port")
+ String srcTcpPort = null;
+
+ @Option(name = "-d", aliases = "--dstIp", description = "Destination IP")
+ String dstIp = null;
+
+ @Option(name = "-dm", aliases = "--dstMac", description = "Destination MAC")
+ String dstMac = null;
+
+ @Option(name = "-dtp", aliases = "dstTcpPort", description = "destination TCP Port")
+ String dstTcpPort = null;
+
+ @Option(name = "-vid", aliases = "--vlanId", description = "Vlan of incoming packet", valueToShowInHelp = "None")
+ String vlan = "None";
+
+ @Option(name = "-ml", aliases = "--mplsLabel", description = "Mpls label of incoming packet")
+ String mplsLabel = null;
+
+ @Option(name = "-mb", aliases = "--mplsBos", description = "MPLS BOS", valueToShowInHelp = "True")
+ String mplsBos = null;
+
+ @Override
+ protected void execute() {
+ TroubleshootService service = get(TroubleshootService.class);
+ ConnectPoint cp = ConnectPoint.deviceConnectPoint(srcPort);
+ EtherType type = EtherType.valueOf(ethType.toUpperCase());
+
+ //Input Port must be specified
+ TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder()
+ .matchInPort(cp.port());
+
+ if (srcIp != null) {
+ if (type.equals(EtherType.IPV6)) {
+ selectorBuilder.matchIPv6Src(IpAddress.valueOf(srcIp).toIpPrefix());
+ } else {
+ selectorBuilder.matchIPSrc(IpAddress.valueOf(srcIp).toIpPrefix());
+ }
+ }
+
+ if (srcMac != null) {
+ selectorBuilder.matchEthSrc(MacAddress.valueOf(srcMac));
+ }
+
+ //if EthType option is not specified using IPv4
+ selectorBuilder.matchEthType(type.ethType().toShort());
+
+ if (srcTcpPort != null) {
+ selectorBuilder.matchTcpSrc(TpPort.tpPort(Integer.parseInt(srcTcpPort)));
+ }
+
+ if (dstIp != null) {
+ if (type.equals(EtherType.IPV6)) {
+ selectorBuilder.matchIPv6Dst(IpAddress.valueOf(dstIp).toIpPrefix());
+ } else {
+ selectorBuilder.matchIPDst(IpAddress.valueOf(dstIp).toIpPrefix());
+ }
+ }
+
+ if (dstMac != null) {
+ selectorBuilder.matchEthDst(MacAddress.valueOf(dstMac));
+ }
+ if (dstTcpPort != null) {
+ selectorBuilder.matchTcpDst(TpPort.tpPort(Integer.parseInt(dstTcpPort)));
+ }
+
+ //if vlan option is not specified using NONE
+ selectorBuilder.matchVlanId(VlanId.vlanId(vlan));
+
+ if (mplsLabel != null) {
+ selectorBuilder.matchMplsLabel(MplsLabel.mplsLabel(Integer.parseInt(mplsLabel)));
+ }
+
+ if (mplsBos != null) {
+ selectorBuilder.matchMplsBos(Boolean.valueOf(mplsBos));
+ }
+
+ TrafficSelector packet = selectorBuilder.build();
+
+ //Printing the created packet
+ print("Tracing packet: %s", packet.criteria());
+
+ //Build the trace
+ StaticPacketTrace trace = service.trace(packet, cp);
+
+ //Print based on verbosity
+ if (verbosity1) {
+ printTrace(trace, false);
+ } else if (verbosity2) {
+ printTrace(trace, true);
+ } else {
+ print("Paths");
+ List<List<ConnectPoint>> paths = trace.getCompletePaths();
+ paths.forEach(path -> print("%s", path));
+ }
+ print("Result: \n%s", trace.resultMessage());
+ }
+
+ //prints the trace
+ private void printTrace(StaticPacketTrace trace, boolean verbose) {
+ List<List<ConnectPoint>> paths = trace.getCompletePaths();
+ paths.forEach(path -> {
+ print("Path %s", path);
+ ConnectPoint previous = null;
+ for (ConnectPoint connectPoint : path) {
+ if (previous == null || !previous.deviceId().equals(connectPoint.deviceId())) {
+ print("Device %s", connectPoint.deviceId());
+ print("Input from %s", connectPoint);
+ printFlows(trace, verbose, connectPoint);
+ } else {
+ printGroups(trace, verbose, connectPoint);
+ print("Output through %s", connectPoint);
+ print("");
+ }
+ previous = connectPoint;
+ }
+ });
+ }
+
+ //Prints the flows for a given trace and a specified level of verbosity
+ private void printFlows(StaticPacketTrace trace, boolean verbose, ConnectPoint connectPoint) {
+ print("Flows");
+ trace.getFlowsForDevice(connectPoint.deviceId()).forEach(f -> {
+ if (verbose) {
+ print(FLOW_SHORT_FORMAT, f.state(), f.bytes(), f.packets(),
+ f.table(), f.priority(), f.selector().criteria(),
+ printTreatment(f.treatment()));
+ } else {
+ print(" flowId=%s, selector=%s ", f.id(), f.selector().criteria());
+ }
+ });
+ }
+
+ //Prints the groups for a given trace and a specified level of verbosity
+ private void printGroups(StaticPacketTrace trace, boolean verbose, ConnectPoint connectPoint) {
+ print("Groups");
+ trace.getGroupOuputs(connectPoint.deviceId()).forEach(output -> {
+ if (output.getOutput().equals(connectPoint)) {
+ output.getGroups().forEach(group -> {
+ if (verbose) {
+ print(GROUP_FORMAT, Integer.toHexString(group.id().id()), group.state(), group.type(),
+ group.bytes(), group.packets(), group.appId().name(), group.referenceCount());
+ int i = 0;
+ for (GroupBucket bucket : group.buckets().buckets()) {
+ print(GROUP_BUCKET_FORMAT, Integer.toHexString(group.id().id()), ++i,
+ bucket.bytes(), bucket.packets(),
+ bucket.treatment().allInstructions());
+ }
+ } else {
+ print(" groupId=%s", group.id());
+ }
+ });
+ print("Outgoing Packet %s", output.getFinalPacket());
+ }
+ });
+ }
+
+ private String printTreatment(TrafficTreatment treatment) {
+ final String delimiter = ", ";
+ StringBuilder builder = new StringBuilder("[");
+ if (!treatment.immediate().isEmpty()) {
+ builder.append("immediate=" + treatment.immediate() + delimiter);
+ }
+ if (!treatment.deferred().isEmpty()) {
+ builder.append("deferred=" + treatment.deferred() + delimiter);
+ }
+ if (treatment.clearedDeferred()) {
+ builder.append("clearDeferred" + delimiter);
+ }
+ if (treatment.tableTransition() != null) {
+ builder.append("transition=" + treatment.tableTransition() + delimiter);
+ }
+ if (treatment.metered() != null) {
+ builder.append("meter=" + treatment.metered() + delimiter);
+ }
+ if (treatment.writeMetadata() != null) {
+ builder.append("metadata=" + treatment.writeMetadata() + delimiter);
+ }
+ // Chop off last delimiter
+ builder.replace(builder.length() - delimiter.length(), builder.length(), "");
+ builder.append("]");
+ return builder.toString();
+ }
+}
diff --git a/apps/t3/src/main/java/org/onosproject/t3/impl/Subnet.java b/apps/t3/src/main/java/org/onosproject/t3/impl/Subnet.java
new file mode 100644
index 0000000..ac5a741
--- /dev/null
+++ b/apps/t3/src/main/java/org/onosproject/t3/impl/Subnet.java
@@ -0,0 +1,133 @@
+/*
+ * 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.t3.impl;
+
+import java.math.BigInteger;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ * Utility class to test if an Ip is in a given subnet.
+ */
+public class Subnet {
+ private final int bytesSubnetCount;
+ private final BigInteger bigMask;
+ private final BigInteger bigSubnetMasked;
+
+ /**
+ * Constructor for use via format "192.168.0.0/24" or "2001:db8:85a3:880:0:0:0:0/57".
+ * @param subnetAddress the address
+ * @param bits the mask
+ */
+ public Subnet(InetAddress subnetAddress, int bits) {
+ bytesSubnetCount = subnetAddress.getAddress().length; // 4 or 16
+ bigMask = BigInteger.valueOf(-1).shiftLeft(bytesSubnetCount * 8 - bits); // mask = -1 << 32 - bits
+ bigSubnetMasked = new BigInteger(subnetAddress.getAddress()).and(bigMask);
+ }
+
+ /**
+ * Constructor for use via format "192.168.0.0/255.255.255.0" or single address.
+ * @param subnetAddress the address
+ * @param mask the mask
+ */
+ public Subnet(InetAddress subnetAddress, InetAddress mask) {
+ bytesSubnetCount = subnetAddress.getAddress().length;
+ // no mask given case is handled here.
+ bigMask = null == mask ? BigInteger.valueOf(-1) : new BigInteger(mask.getAddress());
+ bigSubnetMasked = new BigInteger(subnetAddress.getAddress()).and(bigMask);
+ }
+
+ /**
+ * Subnet factory method.
+ *
+ * @param subnetMask format: "192.168.0.0/24" or "192.168.0.0/255.255.255.0"
+ * or single address or "2001:db8:85a3:880:0:0:0:0/57"
+ * @return a new instance
+ * @throws UnknownHostException thrown if unsupported subnet mask.
+ */
+ public static Subnet createInstance(String subnetMask)
+ throws UnknownHostException {
+ final String[] stringArr = subnetMask.split("/");
+ if (2 > stringArr.length) {
+ return new Subnet(InetAddress.getByName(stringArr[0]), (InetAddress) null);
+ } else if (stringArr[1].contains(".") || stringArr[1].contains(":")) {
+ return new Subnet(InetAddress.getByName(stringArr[0]), InetAddress.getByName(stringArr[1]));
+ } else {
+ return new Subnet(InetAddress.getByName(stringArr[0]), Integer.parseInt(stringArr[1]));
+ }
+ }
+
+ /**
+ * Tests if the address is in the given subnet.
+ * @param address the address to test.
+ * @return true if inside the subnet
+ */
+ public boolean isInSubnet(InetAddress address) {
+ byte[] bytesAddress = address.getAddress();
+ if (this.bytesSubnetCount != bytesAddress.length) {
+ return false;
+ }
+ BigInteger bigAddress = new BigInteger(bytesAddress);
+ return bigAddress.and(this.bigMask).equals(this.bigSubnetMasked);
+ }
+
+ @Override
+ public final boolean equals(Object obj) {
+ if (!(obj instanceof Subnet)) {
+ return false;
+ }
+ final Subnet other = (Subnet) obj;
+ return bigSubnetMasked.equals(other.bigSubnetMasked) &&
+ bigMask.equals(other.bigMask) &&
+ bytesSubnetCount == other.bytesSubnetCount;
+ }
+
+ @Override
+ public final int hashCode() {
+ return bytesSubnetCount;
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder buf = new StringBuilder();
+ bigInteger2IpString(buf, bigSubnetMasked, bytesSubnetCount);
+ buf.append('/');
+ bigInteger2IpString(buf, bigMask, bytesSubnetCount);
+ return buf.toString();
+ }
+
+ private void bigInteger2IpString(StringBuilder buf, BigInteger bigInteger, int displayBytes) {
+ boolean isIPv4 = 4 == displayBytes;
+ byte[] bytes = bigInteger.toByteArray();
+ int diffLen = displayBytes - bytes.length;
+ byte fillByte = 0 > (int) bytes[0] ? (byte) 0xFF : (byte) 0x00;
+
+ int integer;
+ for (int i = 0; i < displayBytes; i++) {
+ if (0 < i && !isIPv4 && i % 2 == 0) {
+ buf.append(':');
+ } else if (0 < i && isIPv4) {
+ buf.append('.');
+ }
+ integer = 0xFF & (i < diffLen ? fillByte : bytes[i - diffLen]);
+ if (!isIPv4 && 0x10 > integer) {
+ buf.append('0');
+ }
+ buf.append(isIPv4 ? integer : Integer.toHexString(integer));
+ }
+ }
+}
diff --git a/apps/t3/src/main/java/org/onosproject/t3/impl/TroubleshootManager.java b/apps/t3/src/main/java/org/onosproject/t3/impl/TroubleshootManager.java
index 03f1e75..b66996d 100644
--- a/apps/t3/src/main/java/org/onosproject/t3/impl/TroubleshootManager.java
+++ b/apps/t3/src/main/java/org/onosproject/t3/impl/TroubleshootManager.java
@@ -16,22 +16,64 @@
package org.onosproject.t3.impl;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
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.VlanId;
import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Host;
+import org.onosproject.net.Link;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.driver.DriverService;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.FlowEntry;
+import org.onosproject.net.flow.FlowRule;
import org.onosproject.net.flow.FlowRuleService;
+import org.onosproject.net.flow.IndexTableId;
+import org.onosproject.net.flow.TableId;
import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.criteria.Criteria;
+import org.onosproject.net.flow.criteria.Criterion;
+import org.onosproject.net.flow.criteria.EthCriterion;
+import org.onosproject.net.flow.criteria.EthTypeCriterion;
+import org.onosproject.net.flow.criteria.IPCriterion;
+import org.onosproject.net.flow.instructions.Instruction;
+import org.onosproject.net.flow.instructions.Instructions;
+import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction;
+import org.onosproject.net.group.Group;
+import org.onosproject.net.group.GroupBucket;
import org.onosproject.net.group.GroupService;
+import org.onosproject.net.host.HostService;
+import org.onosproject.net.link.LinkService;
+import org.onosproject.t3.api.GroupsInDevice;
import org.onosproject.t3.api.StaticPacketTrace;
import org.onosproject.t3.api.TroubleshootService;
import org.slf4j.Logger;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static org.onlab.packet.EthType.EtherType;
+import static org.onosproject.net.flow.instructions.Instructions.GroupInstruction;
import static org.slf4j.LoggerFactory.getLogger;
/**
- * Designates ...
+ * Manager to troubleshoot packets inside the network.
+ * Given a representation of a packet follows it's path in the network according to the existing flows and groups in
+ * the devices.
*/
@Service
@Component(immediate = true)
@@ -45,10 +87,606 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected GroupService groupService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected LinkService linkService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected HostService hostService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DriverService driverService;
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected DeviceService deviceService;
@Override
public StaticPacketTrace trace(TrafficSelector packet, ConnectPoint in) {
- return null;
+ log.info("Tracing packet {} coming in through {}", packet, in);
+ //device must exist in ONOS
+ Preconditions.checkNotNull(deviceService.getDevice(in.deviceId()),
+ "Device " + in.deviceId() + " must exist in ONOS");
+
+ StaticPacketTrace trace = new StaticPacketTrace(packet, in);
+ //FIXME this can be done recursively
+ trace = traceInDevice(trace, packet, in);
+ //Building output connect Points
+ List<ConnectPoint> path = new ArrayList<>();
+ trace = getTrace(path, in, trace);
+ return trace;
+ }
+
+ /**
+ * Computes a trace for a give packet that start in the network at the given connect point.
+ *
+ * @param completePath the path traversed by the packet
+ * @param in the input connect point
+ * @param trace the trace to build
+ * @return the build trace for that packet.
+ */
+ private StaticPacketTrace getTrace(List<ConnectPoint> completePath, ConnectPoint in, StaticPacketTrace trace) {
+
+ //if the trace already contains the input connect point there is a loop
+ if (pathContainsDevice(completePath, in.deviceId())) {
+ trace.addResultMessage("Loop encountered in device " + in.deviceId());
+ return trace;
+ }
+
+ //let's add the input connect point
+ completePath.add(in);
+
+ //If the trace has no outputs for the given input we stop here
+ if (trace.getGroupOuputs(in.deviceId()) == null) {
+ computePath(completePath, trace, null);
+ trace.addResultMessage("No output out of device " + in.deviceId() + ". Packet is dropped");
+ return trace;
+ }
+
+ //If the trace has ouputs we analyze them all
+ for (GroupsInDevice outputPath : trace.getGroupOuputs(in.deviceId())) {
+ log.debug("Output path {}", outputPath.getOutput());
+ //Hosts for the the given output
+ Set<Host> hostsList = hostService.getConnectedHosts(outputPath.getOutput());
+ //Hosts queried from the original ip or mac
+ Set<Host> hosts = getHosts(trace);
+
+ //If the two host collections contain the same item it means we reached the proper output
+ if (!Collections.disjoint(hostsList, hosts)) {
+ log.debug("Stopping here because host is expected destination");
+ trace.addResultMessage("Reached required destination Host");
+ computePath(completePath, trace, outputPath.getOutput());
+ break;
+ } else {
+ ConnectPoint cp = outputPath.getOutput();
+ //let's add the ouput for the input
+ completePath.add(cp);
+ log.debug("------------------------------------------------------------");
+ log.debug("Connect Point out {}", cp);
+ //let's compute the links for the given output
+ Set<Link> links = linkService.getEgressLinks(cp);
+ log.debug("Egress Links {}", links);
+ //No links means that the packet gets dropped.
+ if (links.size() == 0) {
+ log.warn("No links out of {}", cp);
+ computePath(completePath, trace, cp);
+ trace.addResultMessage("No links depart from " + cp + ". Packet is dropped");
+ return trace;
+ }
+ //For each link we trace the corresponding device
+ for (Link link : links) {
+ ConnectPoint dst = link.dst();
+ //change in-port to the dst link in port
+ TrafficSelector.Builder updatedPacket = DefaultTrafficSelector.builder();
+ outputPath.getFinalPacket().criteria().forEach(updatedPacket::add);
+ updatedPacket.add(Criteria.matchInPort(dst.port()));
+ log.debug("DST Connect Point {}", dst);
+ //build the elements for that device
+ traceInDevice(trace, updatedPacket.build(), dst);
+ //continue the trace along the path
+ getTrace(completePath, dst, trace);
+ }
+
+ }
+ }
+ return trace;
+ }
+
+ /**
+ * Checks if the path contains the device.
+ *
+ * @param completePath the path
+ * @param deviceId the device to check
+ * @return true if the path contains the device
+ */
+ //TODO might prove costly, improvement: a class with both CPs and DeviceIds point.
+ private boolean pathContainsDevice(List<ConnectPoint> completePath, DeviceId deviceId) {
+ for (ConnectPoint cp : completePath) {
+ if (cp.deviceId().equals(deviceId)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Gets the hosts for the given initial packet.
+ *
+ * @param trace the trace we are building
+ * @return set of the hosts we are trying to reach
+ */
+ private Set<Host> getHosts(StaticPacketTrace trace) {
+ IPCriterion ipv4Criterion = ((IPCriterion) trace.getInitialPacket()
+ .getCriterion(Criterion.Type.IPV4_DST));
+ IPCriterion ipv6Criterion = ((IPCriterion) trace.getInitialPacket()
+ .getCriterion(Criterion.Type.IPV6_DST));
+ Set<Host> hosts = new HashSet<>();
+ if (ipv4Criterion != null) {
+ hosts.addAll(hostService.getHostsByIp(ipv4Criterion.ip().address()));
+ }
+ if (ipv6Criterion != null) {
+ hosts.addAll(hostService.getHostsByIp(ipv6Criterion.ip().address()));
+ }
+ EthCriterion ethCriterion = ((EthCriterion) trace.getInitialPacket()
+ .getCriterion(Criterion.Type.ETH_DST));
+ if (ethCriterion != null) {
+ hosts.addAll(hostService.getHostsByMac(ethCriterion.mac()));
+ }
+ return hosts;
+ }
+
+ /**
+ * Computes the list of traversed connect points.
+ *
+ * @param completePath the list of devices
+ * @param trace the trace we are building
+ * @param output the final output connect point
+ */
+ private void computePath(List<ConnectPoint> completePath, StaticPacketTrace trace, ConnectPoint output) {
+ List<ConnectPoint> traverseList = new ArrayList<>();
+ if (!completePath.contains(trace.getInitialConnectPoint())) {
+ traverseList.add(trace.getInitialConnectPoint());
+ }
+ traverseList.addAll(completePath);
+ if (output != null && !completePath.contains(output)) {
+ traverseList.add(output);
+ }
+ trace.addCompletePath(traverseList);
+ completePath.clear();
+ }
+
+ /**
+ * Traces the packet inside a device starting from an input connect point.
+ *
+ * @param trace the trace we are building
+ * @param packet the packet we are tracing
+ * @param in the input connect point.
+ * @return updated trace
+ */
+ private StaticPacketTrace traceInDevice(StaticPacketTrace trace, TrafficSelector packet, ConnectPoint in) {
+ log.debug("Packet {} coming in from {}", packet, in);
+
+ //if device is not available exit here.
+ if (!deviceService.isAvailable(in.deviceId())) {
+ trace.addResultMessage("Device is offline " + in.deviceId());
+ return trace;
+ }
+
+ List<FlowEntry> flows = new ArrayList<>();
+ List<FlowEntry> outputFlows = new ArrayList<>();
+
+ FlowEntry nextTableIdEntry = findNextTableIdEntry(in.deviceId(), -1);
+ if (nextTableIdEntry == null) {
+ trace.addResultMessage("No flow rules for device " + in.deviceId() + ". Aborting");
+ return trace;
+ }
+ TableId tableId = nextTableIdEntry.table();
+ FlowEntry flowEntry;
+ boolean output = false;
+ while (!output) {
+ log.debug("Searching a Flow Entry on table {} for packet {}", tableId, packet);
+ //get the rule that matches the incoming packet
+ flowEntry = matchHighestPriority(packet, in, tableId);
+ log.debug("Found Flow Entry {}", flowEntry);
+
+ boolean isOfdpaHardware = TroubleshootUtils.hardwareOfdpaMap
+ .getOrDefault(driverService.getDriver(in.deviceId()).name(), false);
+
+ //if the flow entry on a table is null and we are on hardware we treat as table miss, with few exceptions
+ if (flowEntry == null && isOfdpaHardware) {
+ log.debug("Ofdpa Hw setup, no flow rule means table miss");
+
+ //Handling Hardware Specifics
+ if (((IndexTableId) tableId).id() == 27) {
+ //Apparently a miss but Table 27 on OFDPA is a fixed table
+ packet = handleOfdpa27FixedTable(trace, packet);
+ }
+
+ //Finding next table to go In case of miss
+ nextTableIdEntry = findNextTableIdEntry(in.deviceId(), ((IndexTableId) tableId).id());
+ log.debug("Next table id entry {}", nextTableIdEntry);
+
+ //FIXME find better solution that enable granularity greater than 0 or all rules
+ //(another possibility is max tableId)
+ if (nextTableIdEntry == null && flows.size() == 0) {
+ trace.addResultMessage("No flow rules for device" + in.deviceId() + ". Aborting");
+ return trace;
+
+ } else if (nextTableIdEntry == null) {
+ //Means that no more flow rules are present
+ output = true;
+
+ } else if (((IndexTableId) tableId).id() == 20) {
+ //if the table is 20 OFDPA skips to table 50
+ log.debug("A miss on Table 20 on OFDPA means that we skip directly to table 50");
+ tableId = IndexTableId.of(50);
+
+ } else {
+ tableId = nextTableIdEntry.table();
+ }
+
+
+ } else if (flowEntry == null) {
+ trace.addResultMessage("Packet has no match on table " + tableId + " in device " +
+ in.deviceId() + ". Dropping");
+ return trace;
+ } else {
+ //IF the table has a transition
+ if (flowEntry.treatment().tableTransition() != null) {
+ //update the next table we transitions to
+ tableId = IndexTableId.of(flowEntry.treatment().tableTransition().tableId());
+ log.debug("Flow Entry has transition to table Id {}", tableId);
+ flows.add(flowEntry);
+ } else {
+ //table has no transition so it means that it's an output rule if on the last table
+ log.debug("Flow Entry has no transition to table, treating as last rule {}", flowEntry);
+ flows.add(flowEntry);
+ outputFlows.add(flowEntry);
+ output = true;
+ }
+ //update the packet according to the actions of this flow rule.
+ packet = updatePacket(packet, flowEntry.treatment().allInstructions()).build();
+ }
+ }
+
+ //Creating a modifiable builder for the output packet
+ TrafficSelector.Builder builder = DefaultTrafficSelector.builder();
+ packet.criteria().forEach(builder::add);
+ //Adding all the flows to the trace
+ trace.addFlowsForDevice(in.deviceId(), flows);
+
+ log.debug("Flows traversed by {}", packet);
+ flows.forEach(entry -> {
+ log.debug("Flow {}", entry);
+ });
+
+ log.debug("Output Flows for {}", packet);
+ outputFlows.forEach(entry -> {
+ log.debug("Output Flow {}", entry);
+ });
+ List<PortNumber> outputPorts = new ArrayList<>();
+
+ //Decide Output for packet when flow rule contains an OUTPUT instruction
+ Set<Instruction> outputFlowEntries = outputFlows.stream().flatMap(flow -> {
+ return flow.treatment().allInstructions().stream();
+ })
+ .filter(instruction -> {
+ return instruction.type().equals(Instruction.Type.OUTPUT);
+ }).collect(Collectors.toSet());
+ log.debug("Output instructions {}", outputFlowEntries);
+
+ if (outputFlowEntries.size() != 0) {
+ outputThroughFlows(trace, packet, in, builder, outputPorts, outputFlowEntries);
+
+ } else {
+ log.debug("Handling Groups");
+ //Analyze Groups
+ List<Group> groups = new ArrayList<>();
+
+ for (FlowEntry entry : flows) {
+ getGroupsFromInstructions(trace, groups, entry.treatment().allInstructions(),
+ entry.deviceId(), builder, outputPorts, in);
+ }
+ packet = builder.build();
+ log.debug("Groups hit by packet {}", packet);
+ groups.forEach(group -> {
+ log.debug("Group {}", group);
+ });
+ }
+ log.debug("Output ports for packet {}", packet);
+ outputPorts.forEach(port -> {
+ log.debug("Port {}", port);
+ });
+ log.debug("Output Packet {}", packet);
+ return trace;
+ }
+
+ /**
+ * Method that saves the output if that si done via an OUTPUT treatment of a flow rule.
+ *
+ * @param trace the trace
+ * @param packet the packet coming in to this device
+ * @param in the input connect point for this device
+ * @param builder the updated packet0
+ * @param outputPorts the list of output ports for this device
+ * @param outputFlowEntries the list of flow entries with OUTPUT treatment
+ */
+ private void outputThroughFlows(StaticPacketTrace trace, TrafficSelector packet, ConnectPoint in,
+ TrafficSelector.Builder builder, List<PortNumber> outputPorts,
+ Set<Instruction> outputFlowEntries) {
+ if (outputFlowEntries.size() > 1) {
+ log.warn("There cannot be more than one flow entry with OUTPUT instruction for {}", packet);
+ } else {
+ OutputInstruction outputInstruction = (OutputInstruction) outputFlowEntries.iterator().next();
+ //FIXME using GroupsInDevice for output even if flows.
+ buildOutputFromDevice(trace, in, builder, outputPorts, outputInstruction, ImmutableList.of());
+ }
+ }
+
+ /**
+ * Handles table 27 in Ofpda which is a fixed table not visible to any controller that handles Mpls Labels.
+ *
+ * @param packet the incoming packet
+ * @return the updated packet
+ */
+ private TrafficSelector handleOfdpa27FixedTable(StaticPacketTrace trace, TrafficSelector packet) {
+ log.debug("Handling table 27 on OFDPA, removing mpls ETH Type and change mpls label");
+ Criterion mplsCriterion = packet.getCriterion(Criterion.Type.ETH_TYPE);
+ ImmutableList.Builder<Instruction> builder = ImmutableList.builder();
+
+ //If the pakcet comes in with the expected elements we update it as per OFDPA spec.
+ if (mplsCriterion != null && ((EthTypeCriterion) mplsCriterion).ethType()
+ .equals(EtherType.MPLS_UNICAST.ethType())) {
+ //TODO update with parsing with eth MPLS pop Instruction for treating label an bos
+ Instruction ethInstruction = Instructions.popMpls(((EthTypeCriterion) trace.getInitialPacket()
+ .getCriterion(Criterion.Type.ETH_TYPE)).ethType());
+ //FIXME what do we use as L3_Unicast mpls Label ?
+ //translateInstruction(builder, ethInstruction);
+ builder.add(ethInstruction);
+ }
+ packet = updatePacket(packet, builder.build()).build();
+ return packet;
+ }
+
+ /**
+ * Finds the flow entry with the minimun next table Id.
+ *
+ * @param deviceId the device to search
+ * @param currentId the current id. the search will use this as minimum
+ * @return the flow entry with the minimum table Id after the given one.
+ */
+ private FlowEntry findNextTableIdEntry(DeviceId deviceId, int currentId) {
+
+ final Comparator<FlowEntry> comparator = Comparator.comparing((FlowEntry f) -> ((IndexTableId) f.table()).id());
+
+ return Lists.newArrayList(flowRuleService.getFlowEntries(deviceId).iterator())
+ .stream().filter(f -> ((IndexTableId) f.table()).id() > currentId).min(comparator).orElse(null);
+ }
+
+ /**
+ * Gets group information from instructions.
+ *
+ * @param trace the trace we are building
+ * @param groupsForDevice the set of groups for this device
+ * @param instructions the set of instructions we are searching for groups.
+ * @param deviceId the device we are considering
+ * @param builder the builder of the input packet
+ * @param outputPorts the output ports for that packet
+ */
+ private void getGroupsFromInstructions(StaticPacketTrace trace, List<Group> groupsForDevice,
+ List<Instruction> instructions, DeviceId deviceId,
+ TrafficSelector.Builder builder, List<PortNumber> outputPorts,
+ ConnectPoint in) {
+ List<Instruction> groupInstructionlist = new ArrayList<>();
+ for (Instruction instruction : instructions) {
+ log.debug("Considering Instruction {}", instruction);
+ //if the instruction is not group we need to update the packet or add the output
+ //to the possible outputs for this packet
+ if (!instruction.type().equals(Instruction.Type.GROUP)) {
+ //if the instruction is not group we need to update the packet or add the output
+ //to the possible outputs for this packet
+ if (instruction.type().equals(Instruction.Type.OUTPUT)) {
+ buildOutputFromDevice(trace, in, builder, outputPorts,
+ (OutputInstruction) instruction, groupsForDevice);
+ } else {
+ builder = translateInstruction(builder, instruction);
+ }
+ } else {
+ //if the instuction is pointing to a group we need to get the group
+ groupInstructionlist.add(instruction);
+ }
+ }
+ //handle all the internal instructions pointing to a group.
+ for (Instruction instr : groupInstructionlist) {
+ GroupInstruction groupInstruction = (GroupInstruction) instr;
+ Group group = Lists.newArrayList(groupService.getGroups(deviceId)).stream().filter(groupInternal -> {
+ return groupInternal.id().equals(groupInstruction.groupId());
+ }).findAny().orElse(null);
+ if (group == null) {
+ trace.addResultMessage("Null group for Instruction " + instr);
+ break;
+ }
+ //add the group to the traversed groups
+ groupsForDevice.add(group);
+ //Cycle in each of the group's buckets and add them to the groups for this Device.
+ for (GroupBucket bucket : group.buckets().buckets()) {
+ getGroupsFromInstructions(trace, groupsForDevice, bucket.treatment().allInstructions(),
+ deviceId, builder, outputPorts, in);
+ }
+ }
+ }
+
+ /**
+ * Check if the output is the input port, if so adds a dop result message, otherwise builds
+ * a possible output from this device.
+ *
+ * @param trace the trace
+ * @param in the input connect point
+ * @param builder the packet builder
+ * @param outputPorts the list of output ports for this device
+ * @param outputInstruction the output instruction
+ * @param groupsForDevice
+ */
+ private void buildOutputFromDevice(StaticPacketTrace trace, ConnectPoint in, TrafficSelector.Builder builder,
+ List<PortNumber> outputPorts, OutputInstruction outputInstruction,
+ List<Group> groupsForDevice) {
+ ConnectPoint output = ConnectPoint.deviceConnectPoint(in.deviceId() + "/" +
+ outputInstruction.port());
+ if (output.equals(in)) {
+ trace.addResultMessage("Connect point out " + output + " is same as initial input " +
+ trace.getInitialConnectPoint());
+ } else {
+ trace.addGroupOutputPath(in.deviceId(),
+ new GroupsInDevice(output, groupsForDevice, builder.build()));
+ outputPorts.add(outputInstruction.port());
+ }
+ }
+
+ /**
+ * Applies all give instructions to the input packet.
+ *
+ * @param packet the input packet
+ * @param instructions the set of instructions
+ * @return the packet with the applied instructions
+ */
+ private TrafficSelector.Builder updatePacket(TrafficSelector packet, List<Instruction> instructions) {
+ TrafficSelector.Builder newSelector = DefaultTrafficSelector.builder();
+ packet.criteria().forEach(newSelector::add);
+ //FIXME optimize
+ for (Instruction instruction : instructions) {
+ newSelector = translateInstruction(newSelector, instruction);
+ }
+ return newSelector;
+ }
+
+ /**
+ * Applies an instruction to the packet in the form of a selector.
+ *
+ * @param newSelector the packet selector
+ * @param instruction the instruction to be translated
+ * @return the new selector with the applied instruction
+ */
+ private TrafficSelector.Builder translateInstruction(TrafficSelector.Builder newSelector, Instruction instruction) {
+ log.debug("Translating instruction {}", instruction);
+ log.debug("New Selector {}", newSelector.build());
+ //TODO add as required
+ Criterion criterion = null;
+ switch (instruction.type()) {
+ case L2MODIFICATION:
+ L2ModificationInstruction l2Instruction = (L2ModificationInstruction) instruction;
+ switch (l2Instruction.subtype()) {
+ case VLAN_ID:
+ L2ModificationInstruction.ModVlanIdInstruction vlanIdInstruction =
+ (L2ModificationInstruction.ModVlanIdInstruction) instruction;
+ VlanId id = vlanIdInstruction.vlanId();
+ criterion = Criteria.matchVlanId(id);
+ break;
+ case VLAN_POP:
+ criterion = Criteria.matchVlanId(VlanId.NONE);
+ break;
+ case MPLS_PUSH:
+ L2ModificationInstruction.ModMplsHeaderInstruction mplsEthInstruction =
+ (L2ModificationInstruction.ModMplsHeaderInstruction) instruction;
+ criterion = Criteria.matchEthType(mplsEthInstruction.ethernetType().toShort());
+ break;
+ case MPLS_POP:
+ L2ModificationInstruction.ModMplsHeaderInstruction mplsPopInstruction =
+ (L2ModificationInstruction.ModMplsHeaderInstruction) instruction;
+ criterion = Criteria.matchEthType(mplsPopInstruction.ethernetType().toShort());
+
+ //When popping MPLS we remove label and BOS
+ TrafficSelector temporaryPacket = newSelector.build();
+ if (temporaryPacket.getCriterion(Criterion.Type.MPLS_LABEL) != null) {
+ TrafficSelector.Builder noMplsSelector = DefaultTrafficSelector.builder();
+ temporaryPacket.criteria().stream().filter(c -> {
+ return !c.type().equals(Criterion.Type.MPLS_LABEL) &&
+ !c.type().equals(Criterion.Type.MPLS_BOS);
+ }).forEach(noMplsSelector::add);
+ newSelector = noMplsSelector;
+ }
+
+ break;
+ case MPLS_LABEL:
+ L2ModificationInstruction.ModMplsLabelInstruction mplsLabelInstruction =
+ (L2ModificationInstruction.ModMplsLabelInstruction) instruction;
+ criterion = Criteria.matchMplsLabel(mplsLabelInstruction.label());
+ newSelector.matchMplsBos(true);
+ break;
+ case ETH_DST:
+ L2ModificationInstruction.ModEtherInstruction modEtherDstInstruction =
+ (L2ModificationInstruction.ModEtherInstruction) instruction;
+ criterion = Criteria.matchEthDst(modEtherDstInstruction.mac());
+ break;
+ case ETH_SRC:
+ L2ModificationInstruction.ModEtherInstruction modEtherSrcInstruction =
+ (L2ModificationInstruction.ModEtherInstruction) instruction;
+ criterion = Criteria.matchEthSrc(modEtherSrcInstruction.mac());
+ break;
+ default:
+ log.debug("Unsupported L2 Instruction");
+ break;
+ }
+ break;
+ default:
+ log.debug("Unsupported Instruction");
+ break;
+ }
+ if (criterion != null) {
+ log.debug("Adding criterion {}", criterion);
+ newSelector.add(criterion);
+ }
+ return newSelector;
+ }
+
+ /**
+ * Finds the rule in the device that mathces the input packet and has the highest priority.
+ *
+ * @param packet the input packet
+ * @param in the connect point the packet comes in from
+ * @param tableId the table to search
+ * @return the flow entry
+ */
+ private FlowEntry matchHighestPriority(TrafficSelector packet, ConnectPoint in, TableId tableId) {
+ //Computing the possible match rules.
+ final Comparator<FlowEntry> comparator = Comparator.comparing(FlowRule::priority);
+ return Lists.newArrayList(flowRuleService.getFlowEntries(in.deviceId()).iterator())
+ .stream()
+ .filter(flowEntry -> {
+ return flowEntry.table().equals(tableId);
+ })
+ .filter(flowEntry -> {
+ return match(packet, flowEntry);
+ }).max(comparator).orElse(null);
+ }
+
+ /**
+ * Matches the packet with the given flow entry.
+ *
+ * @param packet the packet to match
+ * @param flowEntry the flow entry to match the packet against
+ * @return true if the packet matches the flow.
+ */
+ private boolean match(TrafficSelector packet, FlowEntry flowEntry) {
+ //TODO handle MAC matching
+ return flowEntry.selector().criteria().stream().allMatch(criterion -> {
+ Criterion.Type type = criterion.type();
+ //If the critrion has IP we need to do LPM to establish matching.
+ if (type.equals(Criterion.Type.IPV4_SRC) || type.equals(Criterion.Type.IPV4_DST) ||
+ type.equals(Criterion.Type.IPV6_SRC) || type.equals(Criterion.Type.IPV6_DST)) {
+ IPCriterion ipCriterion = (IPCriterion) criterion;
+ IPCriterion matchCriterion = (IPCriterion) packet.getCriterion(ipCriterion.type());
+ //if the packet does not have an IPv4 or IPv6 criterion we return true
+ if (matchCriterion == null) {
+ return true;
+ }
+ try {
+ Subnet subnet = Subnet.createInstance(ipCriterion.ip().toString());
+ return subnet.isInSubnet(matchCriterion.ip().address().toInetAddress());
+ } catch (UnknownHostException e) {
+ return false;
+ }
+ //we check that the packet contains the criterion provided by the flow rule.
+ } else {
+ return packet.criteria().contains(criterion);
+ }
+ });
}
}
diff --git a/apps/t3/src/main/java/org/onosproject/t3/impl/TroubleshootUtils.java b/apps/t3/src/main/java/org/onosproject/t3/impl/TroubleshootUtils.java
new file mode 100644
index 0000000..f89a413
--- /dev/null
+++ b/apps/t3/src/main/java/org/onosproject/t3/impl/TroubleshootUtils.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2018-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.t3.impl;
+
+import com.google.common.collect.ImmutableMap;
+
+import java.util.Map;
+
+/**
+ * Utility class for the troubleshooting tool.
+ */
+final class TroubleshootUtils {
+
+ private TroubleshootUtils() {
+ //Banning construction
+ }
+
+ /**
+ * Map defining if a specific driver is for a HW switch.
+ */
+ //Done with builder() instead of of() for clarity
+ static Map<String, Boolean> hardwareOfdpaMap = ImmutableMap.<String, Boolean>builder()
+ .put("ofdpa", true)
+ .put("ofdpa3", true)
+ .put("qmx-ofdpa3", true)
+ .put("as7712-32x-premium", true)
+ .put("as5912-54x-premium", true)
+ .put("as5916-54x-premium", true)
+ .put("accton-ofdpa3", true)
+ .put("znyx-ofdpa", true)
+ .build();
+}
diff --git a/apps/t3/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/apps/t3/src/main/resources/OSGI-INF/blueprint/shell-config.xml
new file mode 100644
index 0000000..7da87bc
--- /dev/null
+++ b/apps/t3/src/main/resources/OSGI-INF/blueprint/shell-config.xml
@@ -0,0 +1,26 @@
+<!--
+ ~ 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.
+ -->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+
+ <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
+ <command>
+ <action class="org.onosproject.t3.cli.TroubleshootTraceCommand"/>
+ </command>
+ </command-bundle>
+
+</blueprint>
+
+
diff --git a/apps/t3/src/test/java/org/onosproject/t3/impl/T3TestObjects.java b/apps/t3/src/test/java/org/onosproject/t3/impl/T3TestObjects.java
new file mode 100644
index 0000000..15cee5f
--- /dev/null
+++ b/apps/t3/src/test/java/org/onosproject/t3/impl/T3TestObjects.java
@@ -0,0 +1,356 @@
+/*
+ * Copyright 2018-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.t3.impl;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import org.onlab.packet.EthType;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.MplsLabel;
+import org.onlab.packet.VlanId;
+import org.onosproject.core.DefaultApplicationId;
+import org.onosproject.core.GroupId;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DefaultHost;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Host;
+import org.onosproject.net.HostId;
+import org.onosproject.net.HostLocation;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.DefaultFlowEntry;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.FlowEntry;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.group.DefaultGroup;
+import org.onosproject.net.group.DefaultGroupBucket;
+import org.onosproject.net.group.Group;
+import org.onosproject.net.group.GroupBucket;
+import org.onosproject.net.group.GroupBuckets;
+import org.onosproject.net.provider.ProviderId;
+
+/**
+ * Helper class for objects related to the Troubleshoot Manager Test.
+ */
+final class T3TestObjects {
+
+ private T3TestObjects(){
+ //banning construction
+ }
+
+ private static final String HOST_ONE_MAC = "00:00:00:00:00:01";
+ private static final String HOST_TWO_MAC = "00:00:00:00:00:02";
+ private static final String HOST_ONE_VLAN = "None";
+ private static final String HOST_TWO_VLAN = "None";
+ private static final String HOST_ONE = HOST_ONE_MAC + "/" + HOST_ONE_VLAN;
+ private static final String HOST_TWO = HOST_TWO_MAC + "/" + HOST_TWO_VLAN;
+
+ //offline device
+ static final DeviceId OFFLINE_DEVICE = DeviceId.deviceId("offlineDevice");
+
+ //Single Flow Test
+ static final DeviceId SINGLE_FLOW_DEVICE = DeviceId.deviceId("SingleFlowDevice");
+ private static final TrafficSelector SINGLE_FLOW_SELECTOR = DefaultTrafficSelector.builder()
+ .matchInPort(PortNumber.portNumber(1))
+ .matchIPSrc(IpPrefix.valueOf("127.0.0.1/32"))
+ .matchIPDst(IpPrefix.valueOf("127.0.0.2/32"))
+ .build();
+
+ private static final TrafficTreatment OUTPUT_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
+ .setOutput(PortNumber.portNumber(2)).build();
+ private static final FlowRule SINGLE_FLOW = DefaultFlowEntry.builder().forDevice(SINGLE_FLOW_DEVICE)
+ .forTable(0)
+ .withPriority(100)
+ .withSelector(SINGLE_FLOW_SELECTOR)
+ .withTreatment(OUTPUT_FLOW_TREATMENT)
+ .fromApp(new DefaultApplicationId(0, "TestApp"))
+ .makePermanent()
+ .build();
+ static final FlowEntry SINGLE_FLOW_ENTRY = new DefaultFlowEntry(SINGLE_FLOW);
+
+ static final ConnectPoint SINGLE_FLOW_IN_CP = ConnectPoint.deviceConnectPoint(SINGLE_FLOW_DEVICE + "/" + 1);
+
+ static final ConnectPoint SINGLE_FLOW_OUT_CP = ConnectPoint.deviceConnectPoint(SINGLE_FLOW_DEVICE + "/" + 2);
+
+ //same output as input
+ static final DeviceId SAME_OUTPUT_FLOW_DEVICE = DeviceId.deviceId("sameOutputDevice");
+
+ private static final TrafficTreatment SAME_OUTPUT_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
+ .setOutput(PortNumber.portNumber(1)).build();
+ private static final FlowRule SAME_OUTPUT_FLOW = DefaultFlowEntry.builder().forDevice(SAME_OUTPUT_FLOW_DEVICE)
+ .forTable(0)
+ .withPriority(100)
+ .withSelector(SINGLE_FLOW_SELECTOR)
+ .withTreatment(SAME_OUTPUT_FLOW_TREATMENT)
+ .fromApp(new DefaultApplicationId(0, "TestApp"))
+ .makePermanent()
+ .build();
+ static final FlowEntry SAME_OUTPUT_FLOW_ENTRY = new DefaultFlowEntry(SAME_OUTPUT_FLOW);
+
+ static final ConnectPoint SAME_OUTPUT_FLOW_CP = ConnectPoint.deviceConnectPoint(SAME_OUTPUT_FLOW_DEVICE + "/" + 1);
+
+
+ //Dual Flow Test
+ static final DeviceId DUAL_FLOW_DEVICE = DeviceId.deviceId("DualFlowDevice");
+ private static final TrafficTreatment TRANSITION_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
+ .setVlanId(VlanId.vlanId((short) 100))
+ .transition(10)
+ .build();
+ private static final TrafficSelector VLAN_FLOW_SELECTOR = DefaultTrafficSelector.builder()
+ .matchVlanId(VlanId.vlanId((short) 100))
+ .build();
+ private static final FlowRule FIRST_FLOW = DefaultFlowEntry.builder().forDevice(DUAL_FLOW_DEVICE)
+ .forTable(0)
+ .withPriority(100)
+ .withSelector(SINGLE_FLOW_SELECTOR)
+ .withTreatment(TRANSITION_FLOW_TREATMENT)
+ .fromApp(new DefaultApplicationId(0, "TestApp"))
+ .makePermanent()
+ .build();
+ static final FlowEntry FIRST_FLOW_ENTRY = new DefaultFlowEntry(FIRST_FLOW);
+ private static final FlowRule SECOND_FLOW = DefaultFlowEntry.builder().forDevice(DUAL_FLOW_DEVICE)
+ .forTable(10)
+ .withPriority(100)
+ .withSelector(VLAN_FLOW_SELECTOR)
+ .withTreatment(OUTPUT_FLOW_TREATMENT)
+ .fromApp(new DefaultApplicationId(0, "TestApp"))
+ .makePermanent()
+ .build();
+ static final FlowEntry SECOND_FLOW_ENTRY = new DefaultFlowEntry(SECOND_FLOW);
+
+ static final ConnectPoint DUAL_FLOW_IN_CP = ConnectPoint.deviceConnectPoint(DUAL_FLOW_DEVICE + "/" + 1);
+
+ static final ConnectPoint DUAL_FLOW_OUT_CP = ConnectPoint.deviceConnectPoint(DUAL_FLOW_DEVICE + "/" + 2);
+
+ //Flow and Group Test
+ static final DeviceId GROUP_FLOW_DEVICE = DeviceId.deviceId("GroupFlowDevice");
+
+ private static final GroupId GROUP_ID = GroupId.valueOf(1);
+
+ private static final TrafficTreatment GROUP_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
+ .pushMpls()
+ .setMpls(MplsLabel.mplsLabel(100))
+ .group(GROUP_ID)
+ .build();
+ private static final FlowRule GROUP_FLOW = DefaultFlowEntry.builder().forDevice(GROUP_FLOW_DEVICE)
+ .forTable(0)
+ .withPriority(100)
+ .withSelector(SINGLE_FLOW_SELECTOR)
+ .withTreatment(GROUP_FLOW_TREATMENT)
+ .fromApp(new DefaultApplicationId(0, "TestApp"))
+ .makePermanent()
+ .build();
+ static final FlowEntry GROUP_FLOW_ENTRY = new DefaultFlowEntry(GROUP_FLOW);
+
+ private static final TrafficTreatment OUTPUT_GROUP_TREATMENT = DefaultTrafficTreatment.builder()
+ .popMpls(EthType.EtherType.IPV4.ethType())
+ .setOutput(PortNumber.portNumber(2)).build();
+
+ private static final GroupBucket BUCKET = DefaultGroupBucket.createSelectGroupBucket(OUTPUT_GROUP_TREATMENT);
+
+ private static final GroupBuckets BUCKETS = new GroupBuckets(ImmutableList.of(BUCKET));
+
+ static final Group GROUP = new DefaultGroup(GROUP_ID, GROUP_FLOW_DEVICE, Group.Type.SELECT, BUCKETS);
+
+ static final ConnectPoint GROUP_FLOW_IN_CP = ConnectPoint.deviceConnectPoint(GROUP_FLOW_DEVICE + "/" + 1);
+
+ static final ConnectPoint GROUP_FLOW_OUT_CP = ConnectPoint.deviceConnectPoint(GROUP_FLOW_DEVICE + "/" + 2);
+
+ //topology
+
+ static final DeviceId TOPO_FLOW_DEVICE = DeviceId.deviceId("SingleFlowDevice1");
+
+ static final DeviceId TOPO_FLOW_2_DEVICE = DeviceId.deviceId("SingleFlowDevice2");
+
+ static final DeviceId TOPO_FLOW_3_DEVICE = DeviceId.deviceId("SingleFlowDevice3");
+
+ private static final TrafficSelector TOPO_FLOW_SELECTOR = DefaultTrafficSelector.builder()
+ .matchInPort(PortNumber.portNumber(1))
+ .matchIPSrc(IpPrefix.valueOf("127.0.0.1/32"))
+ .matchIPDst(IpPrefix.valueOf("127.0.0.3/32"))
+ .build();
+
+ private static final FlowRule TOPO_SINGLE_FLOW = DefaultFlowEntry.builder().forDevice(TOPO_FLOW_DEVICE)
+ .forTable(0)
+ .withPriority(100)
+ .withSelector(TOPO_FLOW_SELECTOR)
+ .withTreatment(OUTPUT_FLOW_TREATMENT)
+ .fromApp(new DefaultApplicationId(0, "TestApp"))
+ .makePermanent()
+ .build();
+
+ static final FlowEntry TOPO_SINGLE_FLOW_ENTRY = new DefaultFlowEntry(TOPO_SINGLE_FLOW);
+
+ static final ConnectPoint TOPO_FLOW_1_IN_CP = ConnectPoint.deviceConnectPoint(TOPO_FLOW_DEVICE + "/" + 1);
+
+ static final ConnectPoint TOPO_FLOW_1_OUT_CP = ConnectPoint.deviceConnectPoint(TOPO_FLOW_DEVICE + "/" + 2);
+
+ static final ConnectPoint TOPO_FLOW_2_IN_CP = ConnectPoint.deviceConnectPoint(TOPO_FLOW_2_DEVICE + "/" + 1);
+
+ static final ConnectPoint TOPO_FLOW_2_OUT_CP = ConnectPoint.deviceConnectPoint(TOPO_FLOW_2_DEVICE + "/" + 2);
+
+ static final ConnectPoint TOPO_FLOW_3_IN_CP = ConnectPoint.deviceConnectPoint(TOPO_FLOW_3_DEVICE + "/" + 1);
+
+ static final ConnectPoint TOPO_FLOW_3_OUT_CP = ConnectPoint.deviceConnectPoint(TOPO_FLOW_3_DEVICE + "/" + 2);
+
+
+ //Topology with Groups
+
+ static final DeviceId TOPO_GROUP_FLOW_DEVICE = DeviceId.deviceId("TopoGroupFlowDevice");
+
+ private static final TrafficSelector TOPO_SECOND_INPUT_FLOW_SELECTOR = DefaultTrafficSelector.builder()
+ .matchInPort(PortNumber.portNumber(3))
+ .matchIPSrc(IpPrefix.valueOf("127.0.0.1/32"))
+ .matchIPDst(IpPrefix.valueOf("127.0.0.3/32"))
+ .build();
+
+ private static final FlowRule TOPO_SECOND_INPUT_FLOW = DefaultFlowEntry.builder().forDevice(TOPO_FLOW_3_DEVICE)
+ .forTable(0)
+ .withPriority(100)
+ .withSelector(TOPO_SECOND_INPUT_FLOW_SELECTOR)
+ .withTreatment(OUTPUT_FLOW_TREATMENT)
+ .fromApp(new DefaultApplicationId(0, "TestApp"))
+ .makePermanent()
+ .build();
+
+ private static final TrafficTreatment OUTPUT_2_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
+ .setOutput(PortNumber.portNumber(3)).build();
+
+
+ private static final GroupId TOPO_GROUP_ID = GroupId.valueOf(1);
+
+ private static final TrafficTreatment TOPO_GROUP_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
+ .group(TOPO_GROUP_ID)
+ .build();
+ private static final FlowRule TOPO_GROUP_FLOW = DefaultFlowEntry.builder().forDevice(TOPO_GROUP_FLOW_DEVICE)
+ .forTable(0)
+ .withPriority(100)
+ .withSelector(TOPO_FLOW_SELECTOR)
+ .withTreatment(TOPO_GROUP_FLOW_TREATMENT)
+ .fromApp(new DefaultApplicationId(0, "TestApp"))
+ .makePermanent()
+ .build();
+ static final FlowEntry TOPO_GROUP_FLOW_ENTRY = new DefaultFlowEntry(TOPO_GROUP_FLOW);
+
+ private static final GroupBucket BUCKET_2 = DefaultGroupBucket.createSelectGroupBucket(OUTPUT_2_FLOW_TREATMENT);
+
+ private static final GroupBuckets BUCKETS_MULTIPLE = new GroupBuckets(ImmutableList.of(BUCKET, BUCKET_2));
+
+ static final Group TOPO_GROUP = new DefaultGroup(TOPO_GROUP_ID, TOPO_GROUP_FLOW_DEVICE,
+ Group.Type.SELECT, BUCKETS_MULTIPLE);
+
+ static final FlowEntry TOPO_SECOND_INPUT_FLOW_ENTRY = new DefaultFlowEntry(TOPO_SECOND_INPUT_FLOW);
+
+ static final DeviceId TOPO_FLOW_4_DEVICE = DeviceId.deviceId("SingleFlowDevice4");
+
+ static final ConnectPoint TOPO_FLOW_IN_CP = ConnectPoint.deviceConnectPoint(TOPO_GROUP_FLOW_DEVICE + "/" + 1);
+
+ static final ConnectPoint TOPO_FLOW_OUT_CP_1 = ConnectPoint.deviceConnectPoint(TOPO_GROUP_FLOW_DEVICE + "/" + 2);
+
+ protected static final ConnectPoint TOPO_FLOW_OUT_CP_2 =
+ ConnectPoint.deviceConnectPoint(TOPO_GROUP_FLOW_DEVICE + "/" + 3);
+
+ static final ConnectPoint TOPO_FLOW_4_IN_CP = ConnectPoint.deviceConnectPoint(TOPO_FLOW_4_DEVICE + "/" + 1);
+
+ static final ConnectPoint TOPO_FLOW_3_IN_2_CP = ConnectPoint.deviceConnectPoint(TOPO_FLOW_3_DEVICE + "/" + 3);
+
+ static final ConnectPoint TOPO_FLOW_4_OUT_CP = ConnectPoint.deviceConnectPoint(TOPO_FLOW_4_DEVICE + "/" + 2);
+
+
+ //hardware
+
+ static final DeviceId HARDWARE_DEVICE = DeviceId.deviceId("HardwareDevice");
+
+ static final ConnectPoint HARDWARE_DEVICE_IN_CP = ConnectPoint.deviceConnectPoint(HARDWARE_DEVICE + "/" + 1);
+
+ static final ConnectPoint HARDWARE_DEVICE_OUT_CP = ConnectPoint.deviceConnectPoint(HARDWARE_DEVICE + "/" + 2);
+
+ private static final TrafficSelector HARDWARE_FLOW_SELECTOR = DefaultTrafficSelector.builder()
+ .matchInPort(PortNumber.portNumber(1))
+ .matchIPSrc(IpPrefix.valueOf("127.0.0.1/32"))
+ .matchIPDst(IpPrefix.valueOf("127.0.0.2/32"))
+ .build();
+
+ private static final TrafficTreatment HW_TRANSITION_FLOW_TREATMENT = DefaultTrafficTreatment.builder()
+ .pushMpls()
+ .transition(27)
+ .build();
+
+ private static final FlowRule HARDWARE_FLOW = DefaultFlowEntry.builder().forDevice(TOPO_FLOW_3_DEVICE)
+ .forTable(0)
+ .withPriority(100)
+ .withSelector(HARDWARE_FLOW_SELECTOR)
+ .withTreatment(HW_TRANSITION_FLOW_TREATMENT)
+ .fromApp(new DefaultApplicationId(0, "TestApp"))
+ .makePermanent()
+ .build();
+
+ static final FlowEntry HARDWARE_FLOW_ENTRY = new DefaultFlowEntry(HARDWARE_FLOW);
+
+ private static final TrafficSelector HARDWARE_ETH_FLOW_SELECTOR = DefaultTrafficSelector.builder()
+ .matchInPort(PortNumber.portNumber(1))
+ .matchIPSrc(IpPrefix.valueOf("127.0.0.1/32"))
+ .matchIPDst(IpPrefix.valueOf("127.0.0.2/32"))
+ .matchEthType(EthType.EtherType.IPV4.ethType().toShort())
+ .build();
+
+ private static final FlowRule HARDWARE_ETH_FLOW = DefaultFlowEntry.builder().forDevice(TOPO_FLOW_3_DEVICE)
+ .forTable(30)
+ .withPriority(100)
+ .withSelector(HARDWARE_ETH_FLOW_SELECTOR)
+ .withTreatment(OUTPUT_FLOW_TREATMENT)
+ .fromApp(new DefaultApplicationId(0, "TestApp"))
+ .makePermanent()
+ .build();
+
+ static final FlowEntry HARDWARE_ETH_FLOW_ENTRY = new DefaultFlowEntry(HARDWARE_ETH_FLOW);
+
+
+
+
+ //helper elements
+
+ static final Host H1 = new DefaultHost(ProviderId.NONE, HostId.hostId(HOST_ONE), MacAddress.valueOf(100),
+ VlanId.NONE, new HostLocation(SINGLE_FLOW_DEVICE, PortNumber.portNumber(2), 0),
+ ImmutableSet.of(IpAddress.valueOf("127.0.0.2")));
+
+ static final Host H2 = new DefaultHost(ProviderId.NONE, HostId.hostId(HOST_TWO), MacAddress.valueOf(100),
+ VlanId.NONE, new HostLocation(TOPO_FLOW_3_DEVICE, PortNumber.portNumber(2), 0),
+ ImmutableSet.of(IpAddress.valueOf("127.0.0.3")));
+
+ static final TrafficSelector PACKET_OK = DefaultTrafficSelector.builder()
+ .matchInPort(PortNumber.portNumber(1))
+ .matchEthType(EthType.EtherType.IPV4.ethType().toShort())
+ .matchIPSrc(IpPrefix.valueOf("127.0.0.1/32"))
+ .matchIPDst(IpPrefix.valueOf("127.0.0.2/32"))
+ .build();
+
+ static final TrafficSelector PACKET_OK_TOPO = DefaultTrafficSelector.builder()
+ .matchInPort(PortNumber.portNumber(1))
+ .matchIPSrc(IpPrefix.valueOf("127.0.0.1/32"))
+ .matchIPDst(IpPrefix.valueOf("127.0.0.3/32"))
+ .build();
+
+ static final TrafficSelector PACKET_FAIL = DefaultTrafficSelector.builder()
+ .matchInPort(PortNumber.portNumber(1))
+ .matchIPSrc(IpPrefix.valueOf("127.0.0.1/32"))
+ .matchIPDst(IpPrefix.valueOf("127.0.0.99/32"))
+ .build();
+}
diff --git a/apps/t3/src/test/java/org/onosproject/t3/impl/TroubleshootManagerTest.java b/apps/t3/src/test/java/org/onosproject/t3/impl/TroubleshootManagerTest.java
new file mode 100644
index 0000000..a8f6524
--- /dev/null
+++ b/apps/t3/src/test/java/org/onosproject/t3/impl/TroubleshootManagerTest.java
@@ -0,0 +1,403 @@
+/*
+ * Copyright 2018-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.t3.impl;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.packet.ChassisId;
+import org.onlab.packet.EthType;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DefaultAnnotations;
+import org.onosproject.net.DefaultDevice;
+import org.onosproject.net.DefaultLink;
+import org.onosproject.net.Device;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Host;
+import org.onosproject.net.Link;
+import org.onosproject.net.device.DeviceServiceAdapter;
+import org.onosproject.net.driver.DefaultDriver;
+import org.onosproject.net.driver.Driver;
+import org.onosproject.net.driver.DriverServiceAdapter;
+import org.onosproject.net.flow.FlowEntry;
+import org.onosproject.net.flow.FlowRuleServiceAdapter;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.criteria.Criterion;
+import org.onosproject.net.flow.criteria.EthTypeCriterion;
+import org.onosproject.net.flow.criteria.VlanIdCriterion;
+import org.onosproject.net.group.Group;
+import org.onosproject.net.group.GroupServiceAdapter;
+import org.onosproject.net.host.HostServiceAdapter;
+import org.onosproject.net.link.LinkServiceAdapter;
+import org.onosproject.net.provider.ProviderId;
+import org.onosproject.t3.api.StaticPacketTrace;
+import org.slf4j.Logger;
+
+import java.util.HashMap;
+import java.util.Set;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.onosproject.net.Device.Type.SWITCH;
+import static org.onosproject.t3.impl.T3TestObjects.*;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Test Class for Troubleshoot Manager.
+ */
+public class TroubleshootManagerTest {
+
+ private static final Logger log = getLogger(TroubleshootManager.class);
+
+ private TroubleshootManager mngr;
+
+ @Before
+ public void setUp() throws Exception {
+ mngr = new TroubleshootManager();
+ mngr.flowRuleService = new TestFlowRuleService();
+ mngr.hostService = new TestHostService();
+ mngr.linkService = new TestLinkService();
+ mngr.driverService = new TestDriverService();
+ mngr.groupService = new TestGroupService();
+ mngr.deviceService = new TestDeviceService();
+
+ assertNotNull("Manager should not be null", mngr);
+
+ assertNotNull("Flow rule Service should not be null", mngr.flowRuleService);
+ assertNotNull("Host Service should not be null", mngr.hostService);
+ assertNotNull("Group Service should not be null", mngr.groupService);
+ assertNotNull("Driver Service should not be null", mngr.driverService);
+ assertNotNull("Link Service should not be null", mngr.linkService);
+ assertNotNull("Device Service should not be null", mngr.deviceService);
+ }
+
+ /**
+ * Tests failure on non existent device.
+ */
+ @Test(expected = NullPointerException.class)
+ public void nonExistentDevice() {
+ StaticPacketTrace traceFail = mngr.trace(PACKET_OK, ConnectPoint.deviceConnectPoint("nonexistent" + "/1"));
+ }
+
+ /**
+ * Tests failure on offline device.
+ */
+ @Test
+ public void offlineDevice() {
+ StaticPacketTrace traceFail = mngr.trace(PACKET_OK, ConnectPoint.deviceConnectPoint(OFFLINE_DEVICE + "/1"));
+ assertNotNull("Trace should not be null", traceFail);
+ assertNull("Trace should have 0 output", traceFail.getGroupOuputs(SINGLE_FLOW_DEVICE));
+ }
+
+ /**
+ * Tests failure on same output.
+ */
+ @Test
+ public void sameOutput() {
+ StaticPacketTrace traceFail = mngr.trace(PACKET_OK, SAME_OUTPUT_FLOW_CP);
+ assertNotNull("Trace should not be null", traceFail);
+ assertTrue("Trace should be unsuccessful",
+ traceFail.resultMessage().contains("is same as initial input"));
+ log.info("trace {}", traceFail.resultMessage());
+ }
+
+
+ /**
+ * Tests failure on device with no flows.
+ */
+ @Test
+ public void noFlows() {
+ StaticPacketTrace traceFail = mngr.trace(PACKET_OK, ConnectPoint.deviceConnectPoint("test/1"));
+ assertNotNull("Trace should not be null", traceFail);
+ assertNull("Trace should have 0 output", traceFail.getGroupOuputs(SINGLE_FLOW_DEVICE));
+ log.info("trace {}", traceFail.resultMessage());
+ }
+
+ /**
+ * Test a single flow rule that has output port in it.
+ */
+ @Test
+ public void testSingleFlowRule() {
+
+ testSuccess(PACKET_OK, SINGLE_FLOW_IN_CP, SINGLE_FLOW_DEVICE, SINGLE_FLOW_OUT_CP, 1);
+
+ testFaliure(PACKET_FAIL, SINGLE_FLOW_IN_CP, SINGLE_FLOW_DEVICE);
+ }
+
+ /**
+ * Tests two flow rule the last one of which has output port in it.
+ */
+ @Test
+ public void testDualFlowRule() {
+
+ //Test Success
+
+ StaticPacketTrace traceSuccess = testSuccess(PACKET_OK, DUAL_FLOW_IN_CP, DUAL_FLOW_DEVICE,
+ DUAL_FLOW_OUT_CP, 1);
+
+ //Testing Vlan
+ Criterion criterion = traceSuccess.getGroupOuputs(DUAL_FLOW_DEVICE).get(0).
+ getFinalPacket().getCriterion(Criterion.Type.VLAN_VID);
+ assertNotNull("Packet Should have Vlan", criterion);
+
+ VlanIdCriterion vlanIdCriterion = (VlanIdCriterion) criterion;
+
+ assertEquals("Vlan should be 100", VlanId.vlanId((short) 100), vlanIdCriterion.vlanId());
+
+ //Test Faliure
+ testFaliure(PACKET_FAIL, DUAL_FLOW_IN_CP, DUAL_FLOW_DEVICE);
+
+ }
+
+ /**
+ * Test a single flow rule that points to a group with output port in it.
+ */
+ @Test
+ public void flowAndGroup() throws Exception {
+
+ StaticPacketTrace traceSuccess = testSuccess(PACKET_OK, GROUP_FLOW_IN_CP, GROUP_FLOW_DEVICE,
+ GROUP_FLOW_OUT_CP, 1);
+
+ assertTrue("Wrong Output Group", traceSuccess.getGroupOuputs(GROUP_FLOW_DEVICE)
+ .get(0).getGroups().contains(GROUP));
+ assertEquals("Packet should not have MPLS Label", EthType.EtherType.IPV4.ethType(),
+ ((EthTypeCriterion) traceSuccess.getGroupOuputs(GROUP_FLOW_DEVICE)
+ .get(0).getFinalPacket().getCriterion(Criterion.Type.ETH_TYPE)).ethType());
+ assertNull("Packet should not have MPLS Label", traceSuccess.getGroupOuputs(GROUP_FLOW_DEVICE)
+ .get(0).getFinalPacket().getCriterion(Criterion.Type.MPLS_LABEL));
+ assertNull("Packet should not have MPLS Label", traceSuccess.getGroupOuputs(GROUP_FLOW_DEVICE)
+ .get(0).getFinalPacket().getCriterion(Criterion.Type.MPLS_BOS));
+
+ }
+
+ /**
+ * Test path through a 3 device topology.
+ */
+ @Test
+ public void singlePathTopology() throws Exception {
+
+ StaticPacketTrace traceSuccess = testSuccess(PACKET_OK_TOPO, TOPO_FLOW_1_IN_CP,
+ TOPO_FLOW_3_DEVICE, TOPO_FLOW_3_OUT_CP, 1);
+
+ assertTrue("Incorrect path",
+ traceSuccess.getCompletePaths().get(0).contains(TOPO_FLOW_2_IN_CP));
+ assertTrue("Incorrect path",
+ traceSuccess.getCompletePaths().get(0).contains(TOPO_FLOW_2_OUT_CP));
+ assertTrue("Incorrect path",
+ traceSuccess.getCompletePaths().get(0).contains(TOPO_FLOW_3_IN_CP));
+
+ }
+
+ /**
+ * Test path through a 4 device topology with first device that has groups with multiple output buckets.
+ */
+ @Test
+ public void testGroupTopo() throws Exception {
+
+ StaticPacketTrace traceSuccess = testSuccess(PACKET_OK_TOPO, TOPO_FLOW_IN_CP,
+ TOPO_FLOW_3_DEVICE, TOPO_FLOW_3_OUT_CP, 2);
+
+ assertTrue("Incorrect groups",
+ traceSuccess.getGroupOuputs(TOPO_GROUP_FLOW_DEVICE).get(0).getGroups().contains(TOPO_GROUP));
+ assertTrue("Incorrect bucket",
+ traceSuccess.getGroupOuputs(TOPO_GROUP_FLOW_DEVICE).get(1).getGroups().contains(TOPO_GROUP));
+ }
+
+ /**
+ * Test HW support in a single device with 2 flow rules to check hit of static HW rules.
+ */
+ @Test
+ public void hardwareTest() throws Exception {
+
+ StaticPacketTrace traceSuccess = testSuccess(PACKET_OK, HARDWARE_DEVICE_IN_CP,
+ HARDWARE_DEVICE, HARDWARE_DEVICE_OUT_CP, 1);
+
+ assertEquals("wrong ETH type", EthType.EtherType.IPV4.ethType(),
+ ((EthTypeCriterion) traceSuccess.getGroupOuputs(HARDWARE_DEVICE).get(0).getFinalPacket()
+ .getCriterion(Criterion.Type.ETH_TYPE)).ethType());
+
+ }
+
+ private StaticPacketTrace testSuccess(TrafficSelector packet, ConnectPoint in, DeviceId deviceId, ConnectPoint out,
+ int paths) {
+ StaticPacketTrace traceSuccess = mngr.trace(packet, in);
+
+ log.info("trace {}", traceSuccess);
+
+ log.info("trace {}", traceSuccess.resultMessage());
+
+ assertNotNull("trace should not be null", traceSuccess);
+ assertEquals("Trace should have " + paths + " output", paths, traceSuccess.getGroupOuputs(deviceId).size());
+ assertEquals("Trace should only have " + paths + "output", paths, traceSuccess.getCompletePaths().size());
+ assertTrue("Trace should be successful",
+ traceSuccess.resultMessage().contains("Reached required destination Host"));
+ assertEquals("Incorrect Output CP", out,
+ traceSuccess.getGroupOuputs(deviceId).get(0).getOutput());
+
+ return traceSuccess;
+ }
+
+ private void testFaliure(TrafficSelector packet, ConnectPoint in, DeviceId deviceId) {
+ StaticPacketTrace traceFail = mngr.trace(packet, in);
+
+ log.info("trace {}", traceFail.resultMessage());
+
+ assertNotNull("Trace should not be null", traceFail);
+ assertNull("Trace should have 0 output", traceFail.getGroupOuputs(deviceId));
+ }
+
+ private class TestFlowRuleService extends FlowRuleServiceAdapter {
+ @Override
+ public Iterable<FlowEntry> getFlowEntries(DeviceId deviceId) {
+ if (deviceId.equals(SINGLE_FLOW_DEVICE)) {
+ return ImmutableList.of(SINGLE_FLOW_ENTRY);
+ } else if (deviceId.equals(DUAL_FLOW_DEVICE)) {
+ return ImmutableList.of(FIRST_FLOW_ENTRY, SECOND_FLOW_ENTRY);
+ } else if (deviceId.equals(GROUP_FLOW_DEVICE)) {
+ return ImmutableList.of(GROUP_FLOW_ENTRY);
+ } else if (deviceId.equals(TOPO_FLOW_DEVICE) ||
+ deviceId.equals(TOPO_FLOW_2_DEVICE) ||
+ deviceId.equals(TOPO_FLOW_3_DEVICE) ||
+ deviceId.equals(TOPO_FLOW_4_DEVICE)) {
+ return ImmutableList.of(TOPO_SINGLE_FLOW_ENTRY, TOPO_SECOND_INPUT_FLOW_ENTRY);
+ } else if (deviceId.equals(TOPO_GROUP_FLOW_DEVICE)) {
+ return ImmutableList.of(TOPO_GROUP_FLOW_ENTRY);
+ } else if (deviceId.equals(HARDWARE_DEVICE)) {
+ return ImmutableList.of(HARDWARE_ETH_FLOW_ENTRY, HARDWARE_FLOW_ENTRY);
+ } else if (deviceId.equals(SAME_OUTPUT_FLOW_DEVICE)) {
+ return ImmutableList.of(SAME_OUTPUT_FLOW_ENTRY);
+ }
+ return ImmutableList.of();
+ }
+ }
+
+ private class TestDriverService extends DriverServiceAdapter {
+ @Override
+ public Driver getDriver(DeviceId deviceId) {
+ if (deviceId.equals(HARDWARE_DEVICE)) {
+ return new DefaultDriver("ofdpa", ImmutableList.of(),
+ "test", "test", "test", new HashMap<>(), new HashMap<>());
+ }
+ return new DefaultDriver("NotHWDriver", ImmutableList.of(),
+ "test", "test", "test", new HashMap<>(), new HashMap<>());
+ }
+ }
+
+ private class TestGroupService extends GroupServiceAdapter {
+ @Override
+ public Iterable<Group> getGroups(DeviceId deviceId) {
+ if (deviceId.equals(GROUP_FLOW_DEVICE)) {
+ return ImmutableList.of(GROUP);
+ } else if (deviceId.equals(TOPO_GROUP_FLOW_DEVICE)) {
+ return ImmutableList.of(TOPO_GROUP);
+ }
+ return ImmutableList.of();
+ }
+ }
+
+ private class TestHostService extends HostServiceAdapter {
+ @Override
+ public Set<Host> getConnectedHosts(ConnectPoint connectPoint) {
+ if (connectPoint.equals(TOPO_FLOW_3_OUT_CP)) {
+ return ImmutableSet.of(H2);
+ }
+ return ImmutableSet.of(H1);
+ }
+
+ @Override
+ public Set<Host> getHostsByMac(MacAddress mac) {
+ if (mac.equals(H1.mac())) {
+ return ImmutableSet.of(H1);
+ } else if (mac.equals(H2.mac())) {
+ return ImmutableSet.of(H2);
+ }
+ return ImmutableSet.of();
+ }
+
+ @Override
+ public Set<Host> getHostsByIp(IpAddress ip) {
+ if ((H1.ipAddresses().contains(ip))) {
+ return ImmutableSet.of(H1);
+ } else if ((H2.ipAddresses().contains(ip))) {
+ return ImmutableSet.of(H2);
+ }
+ return ImmutableSet.of();
+ }
+ }
+
+ private class TestLinkService extends LinkServiceAdapter {
+ @Override
+ public Set<Link> getEgressLinks(ConnectPoint connectPoint) {
+ if (connectPoint.equals(TOPO_FLOW_1_OUT_CP)
+ || connectPoint.equals(TOPO_FLOW_OUT_CP_1)) {
+ return ImmutableSet.of(DefaultLink.builder()
+ .providerId(ProviderId.NONE)
+ .type(Link.Type.DIRECT)
+ .src(connectPoint)
+ .dst(TOPO_FLOW_2_IN_CP)
+ .build());
+ } else if (connectPoint.equals(TOPO_FLOW_2_OUT_CP)) {
+ return ImmutableSet.of(DefaultLink.builder()
+ .providerId(ProviderId.NONE)
+ .type(Link.Type.DIRECT)
+ .src(TOPO_FLOW_2_OUT_CP)
+ .dst(TOPO_FLOW_3_IN_CP)
+ .build());
+ } else if (connectPoint.equals(TOPO_FLOW_OUT_CP_2)) {
+ return ImmutableSet.of(DefaultLink.builder()
+ .providerId(ProviderId.NONE)
+ .type(Link.Type.DIRECT)
+ .src(TOPO_FLOW_OUT_CP_2)
+ .dst(TOPO_FLOW_4_IN_CP)
+ .build());
+ } else if (connectPoint.equals(TOPO_FLOW_4_OUT_CP)) {
+ return ImmutableSet.of(DefaultLink.builder()
+ .providerId(ProviderId.NONE)
+ .type(Link.Type.DIRECT)
+ .src(TOPO_FLOW_4_OUT_CP)
+ .dst(TOPO_FLOW_3_IN_2_CP)
+ .build());
+ }
+ return ImmutableSet.of();
+ }
+ }
+
+ private class TestDeviceService extends DeviceServiceAdapter {
+ @Override
+ public Device getDevice(DeviceId deviceId) {
+ if (deviceId.equals(DeviceId.deviceId("nonexistent"))) {
+ return null;
+ }
+ return new DefaultDevice(ProviderId.NONE, DeviceId.deviceId("test"), SWITCH,
+ "test", "test", "test", "test", new ChassisId(),
+ DefaultAnnotations.builder().set("foo", "bar").build());
+ }
+
+ @Override
+ public boolean isAvailable(DeviceId deviceId) {
+ if (deviceId.equals(OFFLINE_DEVICE)) {
+ return false;
+ }
+ return true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/apps/tenbi/topology/pom.xml b/apps/tenbi/topology/pom.xml
index b3ac945..61b1453 100644
--- a/apps/tenbi/topology/pom.xml
+++ b/apps/tenbi/topology/pom.xml
@@ -62,4 +62,33 @@
</dependency>
</dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <compilerArgs>
+ <arg>-XepDisableAllChecks</arg>
+ <arg>-Xep:BetaApi:OFF</arg>
+ </compilerArgs>
+ </configuration>
+ <executions>
+ <execution>
+ <phase>compile</phase>
+ <goals>
+ <goal>compile</goal>
+ </goals>
+ <configuration>
+ <compilerArgs>
+ <arg>-XepDisableAllChecks</arg>
+ <arg>-Xep:BetaApi:OFF</arg>
+ </compilerArgs>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
</project>
diff --git a/apps/tenbi/tunnel/pom.xml b/apps/tenbi/tunnel/pom.xml
index 2a64af3..2c114a7 100644
--- a/apps/tenbi/tunnel/pom.xml
+++ b/apps/tenbi/tunnel/pom.xml
@@ -90,6 +90,32 @@
</instructions>
</configuration>
</plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <compilerArgs>
+ <arg>-XepDisableAllChecks</arg>
+ <arg>-Xep:BetaApi:OFF</arg>
+ </compilerArgs>
+ </configuration>
+ <executions>
+ <execution>
+ <phase>compile</phase>
+ <goals>
+ <goal>compile</goal>
+ </goals>
+ <configuration>
+ <compilerArgs>
+ <arg>-XepDisableAllChecks</arg>
+ <arg>-Xep:BetaApi:OFF</arg>
+ </compilerArgs>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
</plugins>
</build>
diff --git a/apps/tenbi/utils/pom.xml b/apps/tenbi/utils/pom.xml
index 817a6da..b15a235 100644
--- a/apps/tenbi/utils/pom.xml
+++ b/apps/tenbi/utils/pom.xml
@@ -51,4 +51,34 @@
<version>${project.version}</version>
</dependency>
</dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <compilerArgs>
+ <arg>-XepDisableAllChecks</arg>
+ <arg>-Xep:BetaApi:OFF</arg>
+ </compilerArgs>
+ </configuration>
+ <executions>
+ <execution>
+ <phase>compile</phase>
+ <goals>
+ <goal>compile</goal>
+ </goals>
+ <configuration>
+ <compilerArgs>
+ <arg>-XepDisableAllChecks</arg>
+ <arg>-Xep:BetaApi:OFF</arg>
+ </compilerArgs>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
</project>
diff --git a/apps/tenbi/yangmodel/pom.xml b/apps/tenbi/yangmodel/pom.xml
index a38a441..2ad8679 100644
--- a/apps/tenbi/yangmodel/pom.xml
+++ b/apps/tenbi/yangmodel/pom.xml
@@ -44,6 +44,33 @@
<build>
<plugins>
+
+ <!-- FIXME: YANG tool generates problematic code -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <compilerArgs>
+ <arg>-XepDisableAllChecks</arg>
+ <arg>-Xep:BetaApi:OFF</arg>
+ </compilerArgs>
+ </configuration>
+ <executions>
+ <execution>
+ <phase>compile</phase>
+ <goals>
+ <goal>compile</goal>
+ </goals>
+ <configuration>
+ <compilerArgs>
+ <arg>-XepDisableAllChecks</arg>
+ <arg>-Xep:BetaApi:OFF</arg>
+ </compilerArgs>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
<plugin>
<groupId>org.onosproject</groupId>
<artifactId>onos-yang-maven-plugin</artifactId>
diff --git a/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/DistributedTeTopologyStore.java b/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/DistributedTeTopologyStore.java
index 4a8684e..c9a0b50 100644
--- a/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/DistributedTeTopologyStore.java
+++ b/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/DistributedTeTopologyStore.java
@@ -1100,7 +1100,7 @@
InternalNetwork intNework = networkMap.get(nodeKey.networkId());
if (intNework != null && CollectionUtils.isNotEmpty(intNework.nodeIds())) {
intNework.setChildUpdate(true);
- intNework.nodeIds().remove(nodeKey.nodeId());
+ intNework.nodeIds().remove(nodeKey);
}
InternalNetworkNode intNode = networkNodeMap.remove(nodeKey);
if (intNode != null && CollectionUtils.isNotEmpty(intNode.tpIds())) {
@@ -1287,7 +1287,7 @@
InternalNetwork intNework = networkMap.get(linkKey.networkId());
if (intNework != null && CollectionUtils.isNotEmpty(intNework.linkIds())) {
intNework.setChildUpdate(true);
- intNework.linkIds().remove(linkKey.linkId());
+ intNework.linkIds().remove(linkKey);
}
// Remove it from networkLinkMap
InternalNetworkLink intLink = networkLinkMap.remove(linkKey);
@@ -1316,7 +1316,7 @@
TeNodeKey myTeNodeKey;
InternalNetworkNode intNode = null;
if (!parentUpdate) {
- intNode = networkNodeMap.get(tpKey.nodeId());
+ intNode = networkNodeMap.get(tpKey);
if (intNode == null) {
log.error(" node is not in dataStore for tp update {}", tpKey);
return;
@@ -1351,7 +1351,7 @@
@Override
public void removeTerminationPoint(TerminationPointKey tpKey) {
// Update InternalNetworkNode
- InternalNetworkNode intNode = networkNodeMap.get(tpKey.nodeId());
+ InternalNetworkNode intNode = networkNodeMap.get(tpKey);
if (intNode != null && CollectionUtils.isNotEmpty(intNode.tpIds())) {
intNode.setChildUpdate(true);
intNode.tpIds().remove(tpKey.tpId());
diff --git a/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/TeTopologyManager.java b/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/TeTopologyManager.java
index a0cb597..5ce27e3 100644
--- a/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/TeTopologyManager.java
+++ b/apps/tetopology/app/src/main/java/org/onosproject/tetopology/management/impl/TeTopologyManager.java
@@ -916,7 +916,7 @@
if (newKey != null) {
DefaultTeTopology newTopology = new DefaultTeTopology(
- newKey == null ? teTopology.teTopologyId() : newKey,
+ newKey,
teTopology.teNodes(), teTopology.teLinks(),
teTopology.teTopologyIdStringValue(), new CommonTopologyData(teTopology));
// Update with new data
diff --git a/apps/tetopology/app/src/test/java/org/onosproject/tetopology/management/DefaultBuilder.java b/apps/tetopology/app/src/test/java/org/onosproject/tetopology/management/DefaultBuilder.java
index 47cdcd6..1c82fcc 100644
--- a/apps/tetopology/app/src/test/java/org/onosproject/tetopology/management/DefaultBuilder.java
+++ b/apps/tetopology/app/src/test/java/org/onosproject/tetopology/management/DefaultBuilder.java
@@ -143,7 +143,7 @@
for (long i = 0; i < numTtps; i++) {
ttps.put(i, ttpBuilder(i));
}
- ttp = ttps.get(FIRST_INDEX);
+ ttp = ttps.get((long) FIRST_INDEX);
//TeNode
teNode = new DefaultTeNode(teNodeId, underlayTopologyId,
supportTeNodeId, sourceTeNodeId,
diff --git a/apps/tetopology/app/src/test/java/org/onosproject/tetopology/management/SimpleTeTopologyStore.java b/apps/tetopology/app/src/test/java/org/onosproject/tetopology/management/SimpleTeTopologyStore.java
index bc1c818..7f010fa 100644
--- a/apps/tetopology/app/src/test/java/org/onosproject/tetopology/management/SimpleTeTopologyStore.java
+++ b/apps/tetopology/app/src/test/java/org/onosproject/tetopology/management/SimpleTeTopologyStore.java
@@ -697,7 +697,7 @@
if (intNework != null
&& CollectionUtils.isNotEmpty(intNework.nodeIds())) {
intNework.setChildUpdate(true);
- intNework.nodeIds().remove(nodeKey.nodeId());
+ intNework.nodeIds().remove(nodeKey);
}
InternalNetworkNode intNode = networkNodeMap.remove(nodeKey);
if (intNode != null && CollectionUtils.isNotEmpty(intNode.tpIds())) {
@@ -905,7 +905,7 @@
if (intNework != null
&& CollectionUtils.isNotEmpty(intNework.linkIds())) {
intNework.setChildUpdate(true);
- intNework.linkIds().remove(linkKey.linkId());
+ intNework.linkIds().remove(linkKey);
}
// Remove it from networkLinkMap
InternalNetworkLink intLink = networkLinkMap.remove(linkKey);
@@ -937,7 +937,7 @@
TeNodeKey myTeNodeKey;
InternalNetworkNode intNode = null;
if (!parentUpdate) {
- intNode = networkNodeMap.get(tpKey.nodeId());
+ intNode = networkNodeMap.get(tpKey);
if (intNode == null) {
log.error(" node is not in dataStore for tp update {}", tpKey);
return;
@@ -974,7 +974,7 @@
@Override
public void removeTerminationPoint(TerminationPointKey tpKey) {
// Update InternalNetworkNode
- InternalNetworkNode intNode = networkNodeMap.get(tpKey.nodeId());
+ InternalNetworkNode intNode = networkNodeMap.get(tpKey);
if (intNode != null && CollectionUtils.isNotEmpty(intNode.tpIds())) {
intNode.setChildUpdate(true);
intNode.tpIds().remove(tpKey.tpId());
diff --git a/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VbngConfigurationManager.java b/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VbngConfigurationManager.java
index dded6bd..1e8a5ed 100644
--- a/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VbngConfigurationManager.java
+++ b/apps/virtualbng/src/main/java/org/onosproject/virtualbng/VbngConfigurationManager.java
@@ -280,10 +280,10 @@
return true;
}
}
- if (!isPublicIpExist) {
- log.info("The public IP address {} retrieved from XOS mapping does "
- + "not exist", publicIpAddress);
- }
+
+ log.info("The public IP address {} retrieved from XOS mapping does "
+ + "not exist", publicIpAddress);
+
return false;
}
diff --git a/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsCommand.java b/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsCommand.java
index 35caa97..72489b1 100644
--- a/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsCommand.java
+++ b/apps/vpls/src/main/java/org/onosproject/vpls/cli/VplsCommand.java
@@ -101,8 +101,8 @@
COLOR_ERROR + "Interface " + BOLD + "%s" + RESET + COLOR_ERROR +
" cannot be removed from VPLS " + BOLD + "%s" + RESET + ".";
- protected static Vpls vpls;
- protected static InterfaceService interfaceService;
+ protected Vpls vpls;
+ protected InterfaceService interfaceService;
@Argument(index = 0, name = "command", description = "Command name (add-if|" +
"create|delete|list|rem-if|set-encap|show)",
@@ -377,7 +377,7 @@
* @return true if the interface is already associated to a VPLS; false
* otherwise
*/
- private static boolean isIfaceAssociated(Interface iface) {
+ private boolean isIfaceAssociated(Interface iface) {
return vpls.getAllVpls()
.stream()
.map(VplsData::interfaces)
diff --git a/apps/vpls/src/main/java/org/onosproject/vpls/cli/completer/VplsOptArgCompleter.java b/apps/vpls/src/main/java/org/onosproject/vpls/cli/completer/VplsOptArgCompleter.java
index 0624005..4b5ec46 100644
--- a/apps/vpls/src/main/java/org/onosproject/vpls/cli/completer/VplsOptArgCompleter.java
+++ b/apps/vpls/src/main/java/org/onosproject/vpls/cli/completer/VplsOptArgCompleter.java
@@ -38,8 +38,8 @@
* VPLS optional argument completer.
*/
public class VplsOptArgCompleter extends AbstractChoicesCompleter {
- protected static Vpls vpls;
- protected static InterfaceService interfaceService;
+ protected Vpls vpls;
+ protected InterfaceService interfaceService;
@Override
public List<String> choices() {
diff --git a/apps/vpls/src/test/java/org/onosproject/vpls/VplsTest.java b/apps/vpls/src/test/java/org/onosproject/vpls/VplsTest.java
index 2e42254..10bd51c 100644
--- a/apps/vpls/src/test/java/org/onosproject/vpls/VplsTest.java
+++ b/apps/vpls/src/test/java/org/onosproject/vpls/VplsTest.java
@@ -52,6 +52,7 @@
import org.onosproject.net.host.HostEvent;
import org.onosproject.net.host.HostListener;
import org.onosproject.net.host.HostServiceAdapter;
+import org.onosproject.net.host.InterfaceIpAddress;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentData;
import org.onosproject.net.intent.IntentEvent;
@@ -396,7 +397,11 @@
@Override
public Set<Interface> getInterfacesByIp(IpAddress ip) {
return AVAILABLE_INTERFACES.stream()
- .filter(intf -> intf.ipAddressesList().contains(ip))
+ .filter(intf -> intf.ipAddressesList().stream()
+ .map(InterfaceIpAddress::ipAddress)
+ .filter(ip::equals)
+ .findAny()
+ .isPresent())
.collect(Collectors.toSet());
}
@@ -410,7 +415,11 @@
@Override
public Interface getMatchingInterface(IpAddress ip) {
return AVAILABLE_INTERFACES.stream()
- .filter(intf -> intf.ipAddressesList().contains(ip))
+ .filter(intf -> intf.ipAddressesList().stream()
+ .map(InterfaceIpAddress::ipAddress)
+ .filter(ip::equals)
+ .findAny()
+ .isPresent())
.findFirst()
.orElse(null);
}
@@ -418,7 +427,11 @@
@Override
public Set<Interface> getMatchingInterfaces(IpAddress ip) {
return AVAILABLE_INTERFACES.stream()
- .filter(intf -> intf.ipAddressesList().contains(ip))
+ .filter(intf -> intf.ipAddressesList().stream()
+ .map(InterfaceIpAddress::ipAddress)
+ .filter(ip::equals)
+ .findAny()
+ .isPresent())
.collect(Collectors.toSet());
}
}
diff --git a/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/manager/impl/VtnManager.java b/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/manager/impl/VtnManager.java
index fb1bafc..b1e2f94 100644
--- a/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/manager/impl/VtnManager.java
+++ b/apps/vtn/vtnmgr/src/main/java/org/onosproject/vtn/manager/impl/VtnManager.java
@@ -1121,7 +1121,7 @@
break;
}
}
- if (host != null && vmPort != null && fipPort != null) {
+ if (host != null && fipPort != null) {
DeviceId deviceId = host.location().deviceId();
Port exPort = exPortOfDevice.get(deviceId);
TenantRouter tenantRouter = TenantRouter
@@ -1205,8 +1205,7 @@
.programExternalOut(deviceId, fipNetwork.segmentationId(),
exPort.number(), exPortMac, operation);
} else if (operation == Objective.Operation.REMOVE) {
- if (hostFlag || (!hostFlag
- && routerInfFlagOfTenantRouter.get(tenantRouter) == null)) {
+ if (hostFlag || (routerInfFlagOfTenantRouter.get(tenantRouter) == null)) {
sendNorthSouthL3Flows(deviceId, floatingIp, dstVmGwIp, dstVmGwMac,
l3vni, vmNetwork, vmPort, host, operation);
}
diff --git a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultRouter.java b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultRouter.java
index f31aed1..fc8bbe5 100644
--- a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultRouter.java
+++ b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/DefaultRouter.java
@@ -55,9 +55,9 @@
List<String> routes) {
this.id = checkNotNull(id, "id cannot be null");
this.name = routerName;
- this.adminStateUp = checkNotNull(adminStateUp, "adminStateUp cannot be null");
+ this.adminStateUp = adminStateUp;
this.status = checkNotNull(status, "status cannot be null");
- this.distributed = checkNotNull(distributed, "distributed cannot be null");
+ this.distributed = distributed;
this.externalGatewayInfo = externalGatewayInfo;
this.gatewayPortId = gatewayPortId;
this.tenantId = checkNotNull(tenantId, "tenantId cannot be null");
diff --git a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/RouterGateway.java b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/RouterGateway.java
index 27e1473..6aef24e 100644
--- a/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/RouterGateway.java
+++ b/apps/vtn/vtnrsc/src/main/java/org/onosproject/vtnrsc/RouterGateway.java
@@ -35,7 +35,7 @@
private RouterGateway(TenantNetworkId networkId, boolean enableSnat,
Set<FixedIp> externalFixedIps) {
this.networkId = checkNotNull(networkId, "networkId cannot be null");
- this.enableSnat = checkNotNull(enableSnat, "enableSnat cannot be null");
+ this.enableSnat = enableSnat;
this.externalFixedIps = checkNotNull(externalFixedIps, "externalFixedIps cannot be null");
}
diff --git a/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/util/VtnEventuallyConsistentMapTest.java b/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/util/VtnEventuallyConsistentMapTest.java
index b95b0be..38ceb0b 100644
--- a/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/util/VtnEventuallyConsistentMapTest.java
+++ b/apps/vtn/vtnrsc/src/test/java/org/onosproject/vtnrsc/util/VtnEventuallyConsistentMapTest.java
@@ -89,6 +89,7 @@
return map.get(key);
}
+ @SuppressWarnings("ReturnValueIgnored")
@Override
public void put(K key, V value) {
map.put(key, value);
diff --git a/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/ClassifierResourceTest.java b/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/ClassifierResourceTest.java
index 2307da4..5fa977c 100644
--- a/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/ClassifierResourceTest.java
+++ b/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/ClassifierResourceTest.java
@@ -23,7 +23,6 @@
import org.junit.Test;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.TestServiceDirectory;
-import org.onlab.rest.BaseResource;
import org.onosproject.codec.CodecService;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
@@ -57,7 +56,7 @@
SfcCodecContext context = new SfcCodecContext();
ServiceDirectory testDirectory = new TestServiceDirectory().add(ClassifierService.class, classifierService)
.add(CodecService.class, context.codecManager());
- BaseResource.setServiceDirectory(testDirectory);
+ setServiceDirectory(testDirectory);
}
diff --git a/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/FlowClassifierResourceTest.java b/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/FlowClassifierResourceTest.java
index f98605e..da9d6d8 100644
--- a/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/FlowClassifierResourceTest.java
+++ b/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/FlowClassifierResourceTest.java
@@ -23,7 +23,6 @@
import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.TestServiceDirectory;
import org.onlab.packet.IpPrefix;
-import org.onlab.rest.BaseResource;
import org.onosproject.codec.CodecService;
import org.onosproject.vtnrsc.FlowClassifier;
import org.onosproject.vtnrsc.FlowClassifierId;
@@ -208,7 +207,7 @@
ServiceDirectory testDirectory = new TestServiceDirectory()
.add(FlowClassifierService.class, flowClassifierService)
.add(CodecService.class, context.codecManager());
- BaseResource.setServiceDirectory(testDirectory);
+ setServiceDirectory(testDirectory);
}
diff --git a/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortChainDeviceMapResourceTest.java b/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortChainDeviceMapResourceTest.java
index c4e219b..15c2104 100644
--- a/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortChainDeviceMapResourceTest.java
+++ b/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortChainDeviceMapResourceTest.java
@@ -15,27 +15,15 @@
*/
package org.onosproject.vtnweb.resources;
-import static org.easymock.EasyMock.anyObject;
-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.hamcrest.Matchers.notNullValue;
-import static org.junit.Assert.assertThat;
-
-import java.util.HashSet;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
-
-import javax.ws.rs.client.WebTarget;
-
+import com.eclipsesource.json.Json;
+import com.eclipsesource.json.JsonObject;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
import org.junit.After;
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.codec.CodecService;
import org.onosproject.net.DeviceId;
import org.onosproject.vtnrsc.FiveTuple;
@@ -49,10 +37,19 @@
import org.onosproject.vtnrsc.portchain.PortChainService;
import org.onosproject.vtnweb.web.SfcCodecContext;
-import com.eclipsesource.json.Json;
-import com.eclipsesource.json.JsonObject;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
+import javax.ws.rs.client.WebTarget;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+import static org.easymock.EasyMock.anyObject;
+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.hamcrest.Matchers.notNullValue;
+import static org.junit.Assert.assertThat;
/**
* Unit tests for port chain device map REST APIs.
@@ -223,7 +220,7 @@
ServiceDirectory testDirectory = new TestServiceDirectory()
.add(PortChainService.class, portChainService)
.add(CodecService.class, context.codecManager());
- BaseResource.setServiceDirectory(testDirectory);
+ setServiceDirectory(testDirectory);
}
/**
diff --git a/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortChainResourceTest.java b/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortChainResourceTest.java
index 4fbc63f..dd81814 100644
--- a/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortChainResourceTest.java
+++ b/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortChainResourceTest.java
@@ -15,35 +15,15 @@
*/
package org.onosproject.vtnweb.resources;
-import static org.easymock.EasyMock.anyObject;
-import static org.easymock.EasyMock.createMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-import static org.hamcrest.Matchers.containsString;
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.notNullValue;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-
-import java.io.InputStream;
-import java.net.HttpURLConnection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
-
-import javax.ws.rs.NotFoundException;
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.client.WebTarget;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
+import com.eclipsesource.json.Json;
+import com.eclipsesource.json.JsonObject;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
import org.junit.After;
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.codec.CodecService;
import org.onosproject.net.DeviceId;
import org.onosproject.vtnrsc.FiveTuple;
@@ -57,10 +37,27 @@
import org.onosproject.vtnrsc.portchain.PortChainService;
import org.onosproject.vtnweb.web.SfcCodecContext;
-import com.eclipsesource.json.Json;
-import com.eclipsesource.json.JsonObject;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
+import javax.ws.rs.NotFoundException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+
+import static org.easymock.EasyMock.anyObject;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
/**
* Unit tests for port chain REST APIs.
@@ -221,7 +218,7 @@
ServiceDirectory testDirectory = new TestServiceDirectory()
.add(PortChainService.class, portChainService)
.add(CodecService.class, context.codecManager());
- BaseResource.setServiceDirectory(testDirectory);
+ setServiceDirectory(testDirectory);
}
diff --git a/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortChainSfMapResourceTest.java b/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortChainSfMapResourceTest.java
index d8983b0..e3866ce 100644
--- a/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortChainSfMapResourceTest.java
+++ b/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortChainSfMapResourceTest.java
@@ -15,6 +15,25 @@
*/
package org.onosproject.vtnweb.resources;
+import com.eclipsesource.json.Json;
+import com.eclipsesource.json.JsonObject;
+import com.google.common.collect.Lists;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.osgi.ServiceDirectory;
+import org.onlab.osgi.TestServiceDirectory;
+import org.onosproject.codec.CodecService;
+import org.onosproject.vtnrsc.PortPairId;
+import org.onosproject.vtnrsc.ServiceFunctionGroup;
+import org.onosproject.vtnrsc.portchainsfmap.PortChainSfMapService;
+import org.onosproject.vtnweb.web.SfcCodecContext;
+
+import javax.ws.rs.client.WebTarget;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
@@ -23,28 +42,6 @@
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
-import javax.ws.rs.client.WebTarget;
-
-import org.junit.After;
-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.codec.CodecService;
-import org.onosproject.vtnrsc.PortPairId;
-import org.onosproject.vtnrsc.ServiceFunctionGroup;
-import org.onosproject.vtnrsc.portchainsfmap.PortChainSfMapService;
-import org.onosproject.vtnweb.web.SfcCodecContext;
-
-import com.eclipsesource.json.Json;
-import com.eclipsesource.json.JsonObject;
-import com.google.common.collect.Lists;
-
/**
* Unit tests for port chain sf map REST APIs.
*/
@@ -68,7 +65,7 @@
ServiceDirectory testDirectory = new TestServiceDirectory()
.add(PortChainSfMapService.class, portChainSfMapService)
.add(CodecService.class, context.codecManager());
- BaseResource.setServiceDirectory(testDirectory);
+ setServiceDirectory(testDirectory);
}
/**
diff --git a/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortPairGroupResourceTest.java b/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortPairGroupResourceTest.java
index c781c88..a5f2150 100644
--- a/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortPairGroupResourceTest.java
+++ b/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortPairGroupResourceTest.java
@@ -19,13 +19,11 @@
import com.eclipsesource.json.JsonObject;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
-import java.util.Map;
import org.junit.After;
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.codec.CodecService;
import org.onosproject.vtnrsc.PortPairGroup;
import org.onosproject.vtnrsc.PortPairGroupId;
@@ -43,6 +41,7 @@
import java.net.HttpURLConnection;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Objects;
import java.util.Set;
@@ -151,7 +150,7 @@
ServiceDirectory testDirectory = new TestServiceDirectory()
.add(PortPairGroupService.class, portPairGroupService)
.add(CodecService.class, context.codecManager());
- BaseResource.setServiceDirectory(testDirectory);
+ setServiceDirectory(testDirectory);
}
diff --git a/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortPairResourceTest.java b/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortPairResourceTest.java
index 7f73b83..63e89b9 100644
--- a/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortPairResourceTest.java
+++ b/apps/vtn/vtnweb/src/test/java/org/onosproject/vtnweb/resources/PortPairResourceTest.java
@@ -22,7 +22,6 @@
import org.junit.Test;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.TestServiceDirectory;
-import org.onlab.rest.BaseResource;
import org.onosproject.codec.CodecService;
import org.onosproject.vtnrsc.PortPair;
import org.onosproject.vtnrsc.PortPairId;
@@ -135,7 +134,7 @@
SfcCodecContext context = new SfcCodecContext();
ServiceDirectory testDirectory = new TestServiceDirectory().add(PortPairService.class, portPairService)
.add(CodecService.class, context.codecManager());
- BaseResource.setServiceDirectory(testDirectory);
+ setServiceDirectory(testDirectory);
}
diff --git a/apps/yms/app/pom.xml b/apps/yms/app/pom.xml
index 08a3713..e65758d 100644
--- a/apps/yms/app/pom.xml
+++ b/apps/yms/app/pom.xml
@@ -66,7 +66,6 @@
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>3.2.0</version>
<extensions>true</extensions>
<configuration>
<instructions>
@@ -79,6 +78,32 @@
</instructions>
</configuration>
</plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <compilerArgs>
+ <arg>-XepDisableAllChecks</arg>
+ <arg>-Xep:BetaApi:OFF</arg>
+ </compilerArgs>
+ </configuration>
+ <executions>
+ <execution>
+ <phase>compile</phase>
+ <goals>
+ <goal>compile</goal>
+ </goals>
+ <configuration>
+ <compilerArgs>
+ <arg>-XepDisableAllChecks</arg>
+ <arg>-Xep:BetaApi:OFF</arg>
+ </compilerArgs>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
</plugins>
</build>
</project>
diff --git a/apps/yms/ut/pom.xml b/apps/yms/ut/pom.xml
index a89438b..ca2f681 100644
--- a/apps/yms/ut/pom.xml
+++ b/apps/yms/ut/pom.xml
@@ -115,6 +115,31 @@
</executions>
</plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <compilerArgs>
+ <arg>-XepDisableAllChecks</arg>
+ <arg>-Xep:BetaApi:OFF</arg>
+ </compilerArgs>
+ </configuration>
+ <executions>
+ <execution>
+ <phase>compile</phase>
+ <goals>
+ <goal>compile</goal>
+ </goals>
+ <configuration>
+ <compilerArgs>
+ <arg>-XepDisableAllChecks</arg>
+ <arg>-Xep:BetaApi:OFF</arg>
+ </compilerArgs>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
</plugins>
</build>
</project>
diff --git a/buck-tools/default.defs b/buck-tools/default.defs
index ad9f8aa..0e3ff13 100644
--- a/buck-tools/default.defs
+++ b/buck-tools/default.defs
@@ -5,6 +5,7 @@
include_defs('//bucklets/yang.bucklet')
include_defs('//bucklets/remote_jar.bucklet')
include_defs('//bucklets/grpc.bucklet')
+include_defs('//bucklets/jaxb2.bucklet')
BASE_DEPS = [
'//lib:junit',
diff --git a/bucklets/jaxb2.bucklet b/bucklets/jaxb2.bucklet
new file mode 100644
index 0000000..f3bb9fb
--- /dev/null
+++ b/bucklets/jaxb2.bucklet
@@ -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.
+#
+# Bucklet to create Java Code from XSD using the 'xjc' tool from the JAXB API v2.
+# The genrule() creates the Java code, zips it and puts it in the output of jaxb2-xjc
+# The osgi_jar_with_tests() takes the sources in this ZIP and adds them to what ever
+# sources were used in the call to this method, and compiles all of them and adds
+# them to a JAR file in the output folder
+
+include_defs('//onos.defs')
+include_defs('//bucklets/onos.bucklet')
+
+def _get_name():
+ base_path = get_base_path()
+ return ONOS_ARTIFACT_BASE + base_path.replace('/', '-') #TODO Unix-separator
+
+def jaxb2_xjc_osgi_jar(
+ name,
+ srcs,
+ xsd,
+ bindinfo=None,
+ destdir='.',
+ deps=[],
+ test_deps=[],
+ visibility = [],
+ **kwargs
+ ):
+ if name is None:
+ name = _get_name()
+
+ cmd = 'xjc '+xsd
+ if bindinfo is not None:
+ cmd=cmd+' -b '+bindinfo
+ cmd=cmd+' -d '+destdir
+
+ genrule(
+ name = 'jaxb2-xjc',
+ srcs = glob(['src/main/resources/*.xsd','src/main/resources/*.xjb']),
+ bash = cmd + ' && zip $OUT -r *',
+ out = name+'.src.zip',
+ visibility = [ ],
+ )
+
+ osgi_jar_with_tests (
+ deps = [":jaxb2-xjc"] + deps,
+ srcs = [':jaxb2-xjc'] + srcs,
+ test_deps = test_deps,
+ do_javadocs = False,
+ do_checkstyle = False,
+ **kwargs
+ )
+
diff --git a/cli/src/main/java/org/onosproject/cli/AbstractShellCommand.java b/cli/src/main/java/org/onosproject/cli/AbstractShellCommand.java
index 444631e..f83c5fa 100644
--- a/cli/src/main/java/org/onosproject/cli/AbstractShellCommand.java
+++ b/cli/src/main/java/org/onosproject/cli/AbstractShellCommand.java
@@ -91,7 +91,8 @@
*/
public static String annotations(Annotations annotations) {
StringBuilder sb = new StringBuilder();
- for (String key : annotations.keys()) {
+ Set<String> keys = new TreeSet<>(annotations.keys());
+ for (String key : keys) {
sb.append(", ").append(key).append('=').append(annotations.value(key));
}
return sb.toString();
diff --git a/cli/src/main/java/org/onosproject/cli/net/FlowsListCommand.java b/cli/src/main/java/org/onosproject/cli/net/FlowsListCommand.java
index ec6178b..331431a 100644
--- a/cli/src/main/java/org/onosproject/cli/net/FlowsListCommand.java
+++ b/cli/src/main/java/org/onosproject/cli/net/FlowsListCommand.java
@@ -39,6 +39,7 @@
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -303,7 +304,7 @@
print(LONG_FORMAT, Long.toHexString(f.id().value()), f.state(),
f.bytes(), f.packets(), f.life(), f.liveType(), f.priority(), f.table(),
appId != null ? appId.name() : "<none>",
- f.payLoad() == null ? null : f.payLoad().payLoad().toString(),
+ f.payLoad() == null ? null : Arrays.toString(f.payLoad().payLoad()),
f.selector().criteria(), f.treatment());
}
}
diff --git a/cli/src/main/java/org/onosproject/cli/net/IntentRemoveCommand.java b/cli/src/main/java/org/onosproject/cli/net/IntentRemoveCommand.java
index 4ead980..cadae7e 100644
--- a/cli/src/main/java/org/onosproject/cli/net/IntentRemoveCommand.java
+++ b/cli/src/main/java/org/onosproject/cli/net/IntentRemoveCommand.java
@@ -214,7 +214,7 @@
if (event.type() == IntentEvent.Type.WITHDRAWN ||
event.type() == IntentEvent.Type.FAILED) {
withdrawLatch.countDown();
- } else if (purgeAfterRemove &&
+ } else if (purgeLatch != null && purgeAfterRemove &&
event.type() == IntentEvent.Type.PURGED) {
purgeLatch.countDown();
}
@@ -229,13 +229,13 @@
// request the withdraw
intentService.withdraw(intent);
- if (purgeAfterRemove || sync) {
+ if (withdrawLatch != null && (purgeAfterRemove || sync)) {
try { // wait for withdraw event
withdrawLatch.await(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
print("Timed out waiting for intent {} withdraw", key);
}
- if (purgeAfterRemove && CAN_PURGE.contains(intentService.getIntentState(key))) {
+ if (purgeLatch != null && purgeAfterRemove && CAN_PURGE.contains(intentService.getIntentState(key))) {
intentService.purge(intent);
if (sync) { // wait for purge event
/* TODO
diff --git a/cli/src/main/java/org/onosproject/cli/net/IntentsListCommand.java b/cli/src/main/java/org/onosproject/cli/net/IntentsListCommand.java
index fa504df..8fb3714 100644
--- a/cli/src/main/java/org/onosproject/cli/net/IntentsListCommand.java
+++ b/cli/src/main/java/org/onosproject/cli/net/IntentsListCommand.java
@@ -553,8 +553,9 @@
builder.append('\n').append(format("bidirectional=%s", ci.isBidirectional()));
}
- List<Intent> installable = service.getInstallableIntents(intent.key());
- installable.stream().filter(i -> contentFilter.filter(i));
+ List<Intent> installable = service.getInstallableIntents(intent.key())
+ .stream().filter(i -> contentFilter.filter(i))
+ .collect(Collectors.toList());
if (showInstallable && installable != null && !installable.isEmpty()) {
builder.append('\n').append(format(INSTALLABLE, installable));
}
diff --git a/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualFlowsListCommand.java b/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualFlowsListCommand.java
index 8959389..ff0cf7d 100644
--- a/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualFlowsListCommand.java
+++ b/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualFlowsListCommand.java
@@ -38,6 +38,7 @@
import org.onosproject.utils.Comparators;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -237,7 +238,7 @@
print(LONG_FORMAT, Long.toHexString(f.id().value()), f.state(),
f.bytes(), f.packets(), f.life(), f.liveType(), f.priority(), f.tableId(),
appId != null ? appId.name() : "<none>",
- f.payLoad() == null ? null : f.payLoad().payLoad().toString(),
+ f.payLoad() == null ? null : Arrays.toString(f.payLoad().payLoad()),
f.selector().criteria(), f.treatment());
}
}
diff --git a/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualNetworkIntentRemoveCommand.java b/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualNetworkIntentRemoveCommand.java
index 8f073e6..7ba6791 100644
--- a/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualNetworkIntentRemoveCommand.java
+++ b/cli/src/main/java/org/onosproject/cli/net/vnet/VirtualNetworkIntentRemoveCommand.java
@@ -140,7 +140,7 @@
if (event.type() == IntentEvent.Type.WITHDRAWN ||
event.type() == IntentEvent.Type.FAILED) {
withdrawLatch.countDown();
- } else if (purgeAfterRemove &&
+ } else if (purgeLatch != null && purgeAfterRemove &&
event.type() == IntentEvent.Type.PURGED) {
purgeLatch.countDown();
}
@@ -155,7 +155,7 @@
// request the withdraw
intentService.withdraw(intent);
- if (purgeAfterRemove || sync) {
+ if ((purgeAfterRemove || sync) && purgeLatch != null) {
try { // wait for withdraw event
withdrawLatch.await(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
diff --git a/core/api/src/main/java/org/onosproject/cluster/ClusterMetadata.java b/core/api/src/main/java/org/onosproject/cluster/ClusterMetadata.java
index bd3e65e..c205345 100644
--- a/core/api/src/main/java/org/onosproject/cluster/ClusterMetadata.java
+++ b/core/api/src/main/java/org/onosproject/cluster/ClusterMetadata.java
@@ -17,6 +17,7 @@
import java.util.Arrays;
import java.util.Collection;
+import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
@@ -140,17 +141,19 @@
@Override
public boolean equals(Object object) {
+ if (object == null) {
+ return false;
+ }
+
if (!ClusterMetadata.class.isInstance(object)) {
return false;
}
ClusterMetadata that = (ClusterMetadata) object;
- if (!this.name.equals(that.name) || this.nodes.size() != that.nodes.size()
- || this.partitions.size() != that.partitions.size()) {
- return false;
- }
-
- return Sets.symmetricDifference(this.nodes, that.nodes).isEmpty()
- && Sets.symmetricDifference(this.partitions, that.partitions).isEmpty();
+ return Objects.equals(this.name, that.name) &&
+ Objects.equals(this.nodes.size(), that.nodes.size()) &&
+ Objects.equals(this.partitions.size(), that.partitions.size()) &&
+ Sets.symmetricDifference(this.nodes, that.nodes).isEmpty() &&
+ Sets.symmetricDifference(this.partitions, that.partitions).isEmpty();
}
}
diff --git a/core/api/src/main/java/org/onosproject/net/config/basics/SubjectFactories.java b/core/api/src/main/java/org/onosproject/net/config/basics/SubjectFactories.java
index 1eda703..aeaf84d 100644
--- a/core/api/src/main/java/org/onosproject/net/config/basics/SubjectFactories.java
+++ b/core/api/src/main/java/org/onosproject/net/config/basics/SubjectFactories.java
@@ -140,7 +140,7 @@
*
* @param service core service reference
*/
- public static void setCoreService(CoreService service) {
+ public static synchronized void setCoreService(CoreService service) {
coreService = service;
}
diff --git a/core/api/src/main/java/org/onosproject/net/flow/criteria/UnresolvedExtensionSelector.java b/core/api/src/main/java/org/onosproject/net/flow/criteria/UnresolvedExtensionSelector.java
index 17f527b..22bf95c 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/criteria/UnresolvedExtensionSelector.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/criteria/UnresolvedExtensionSelector.java
@@ -17,7 +17,6 @@
import org.onosproject.net.flow.AbstractExtension;
import java.util.Arrays;
-import java.util.Objects;
import static com.google.common.base.MoreObjects.toStringHelper;
@@ -57,7 +56,7 @@
@Override
public int hashCode() {
- return Objects.hash(bytes);
+ return Arrays.hashCode(bytes);
}
@Override
diff --git a/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java b/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java
index 9bd7df5..33b7482 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/instructions/Instructions.java
@@ -101,7 +101,6 @@
* @return set-queue instruction
*/
public static SetQueueInstruction setQueue(final long queueId, final PortNumber port) {
- checkNotNull(queueId, "queue ID cannot be null");
return new SetQueueInstruction(queueId, port);
}
@@ -328,7 +327,6 @@
* @return a l3 modification
*/
public static L3ModificationInstruction modL3ArpOp(short op) {
- checkNotNull(op, "Arp operation cannot be null");
return new ModArpOpInstruction(L3SubType.ARP_OP, op);
}
@@ -428,7 +426,6 @@
* @return a L2 modification
*/
public static L2ModificationInstruction modTunnelId(long tunnelId) {
- checkNotNull(tunnelId, "Tunnel id cannot be null");
return new L2ModificationInstruction.ModTunnelIdInstruction(tunnelId);
}
diff --git a/core/api/src/main/java/org/onosproject/net/flow/instructions/UnresolvedExtensionTreatment.java b/core/api/src/main/java/org/onosproject/net/flow/instructions/UnresolvedExtensionTreatment.java
index bbe1d33..6c4a8c2 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/instructions/UnresolvedExtensionTreatment.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/instructions/UnresolvedExtensionTreatment.java
@@ -19,7 +19,6 @@
import com.google.common.base.MoreObjects;
import org.onosproject.net.flow.AbstractExtension;
import java.util.Arrays;
-import java.util.Objects;
/**
* Unresolved extension treatment.
@@ -57,7 +56,7 @@
@Override
public int hashCode() {
- return Objects.hash(bytes);
+ return Arrays.hashCode(bytes);
}
@Override
diff --git a/core/api/src/main/java/org/onosproject/net/intent/Intent.java b/core/api/src/main/java/org/onosproject/net/intent/Intent.java
index 7a541e7..b7af54f 100644
--- a/core/api/src/main/java/org/onosproject/net/intent/Intent.java
+++ b/core/api/src/main/java/org/onosproject/net/intent/Intent.java
@@ -48,6 +48,7 @@
private final ResourceGroup resourceGroup;
private static IdGenerator idGenerator;
+ private static final Object ID_GENERATOR_LOCK = new Object();
/**
* Constructor for serializer.
@@ -248,8 +249,10 @@
* @param newIdGenerator id generator
*/
public static void bindIdGenerator(IdGenerator newIdGenerator) {
- checkState(idGenerator == null, "Id generator is already bound.");
- idGenerator = checkNotNull(newIdGenerator);
+ synchronized (ID_GENERATOR_LOCK) {
+ checkState(idGenerator == null, "Id generator is already bound.");
+ idGenerator = checkNotNull(newIdGenerator);
+ }
}
/**
@@ -260,8 +263,10 @@
* @param oldIdGenerator the current id generator
*/
public static void unbindIdGenerator(IdGenerator oldIdGenerator) {
- if (idGenerator == oldIdGenerator) {
- idGenerator = null;
+ synchronized (ID_GENERATOR_LOCK) {
+ if (idGenerator == oldIdGenerator) {
+ idGenerator = null;
+ }
}
}
diff --git a/core/api/src/main/java/org/onosproject/net/intent/IntentOperationContext.java b/core/api/src/main/java/org/onosproject/net/intent/IntentOperationContext.java
index 6fc3f2e..528f4ba 100644
--- a/core/api/src/main/java/org/onosproject/net/intent/IntentOperationContext.java
+++ b/core/api/src/main/java/org/onosproject/net/intent/IntentOperationContext.java
@@ -103,7 +103,7 @@
IntentOperationContext that = (IntentOperationContext) obj;
return Objects.equals(intentsToInstall, that.intentsToInstall) &&
Objects.equals(intentsToUninstall, that.intentsToUninstall) &&
- Objects.equals(intentInstallationContext, intentInstallationContext);
+ Objects.equals(intentInstallationContext, that.intentInstallationContext);
}
@Override
diff --git a/core/api/src/main/java/org/onosproject/net/intent/util/IntentFilter.java b/core/api/src/main/java/org/onosproject/net/intent/util/IntentFilter.java
index 99b887f..24be4ef 100644
--- a/core/api/src/main/java/org/onosproject/net/intent/util/IntentFilter.java
+++ b/core/api/src/main/java/org/onosproject/net/intent/util/IntentFilter.java
@@ -132,18 +132,18 @@
if (objective instanceof NextObjective) {
nextObjective = (DefaultNextObjective) objective;
- continue;
-
} else if (objective instanceof ForwardingObjective) {
forwardObjective = (DefaultForwardingObjective) objective;
- FlowRule flowRule = DefaultFlowRule.builder()
+ FlowRule.Builder builder = DefaultFlowRule.builder()
.forDevice(deviceId)
.withSelector(forwardObjective.selector())
- .withTreatment(nextObjective.next().iterator().next())
.withPriority(intent.priority())
.fromApp(intent.appId())
- .makePermanent()
- .build();
+ .makePermanent();
+ if (nextObjective != null) {
+ builder.withTreatment(nextObjective.next().iterator().next());
+ }
+ FlowRule flowRule = builder.build();
flowEntry = getFlowEntry(flowRule);
if (flowEntry != null) {
diff --git a/core/api/src/main/java/org/onosproject/store/cluster/messaging/ClusterMessage.java b/core/api/src/main/java/org/onosproject/store/cluster/messaging/ClusterMessage.java
index 4c03699..5327d48 100644
--- a/core/api/src/main/java/org/onosproject/store/cluster/messaging/ClusterMessage.java
+++ b/core/api/src/main/java/org/onosproject/store/cluster/messaging/ClusterMessage.java
@@ -155,6 +155,6 @@
@Override
public int hashCode() {
- return Objects.hash(sender, subject, payload);
+ return Objects.hash(sender, subject, Arrays.hashCode(payload));
}
}
diff --git a/core/api/src/test/java/org/onosproject/net/link/LinkProviderRegistryAdapter.java b/core/api/src/test/java/org/onosproject/net/link/LinkProviderRegistryAdapter.java
index d2cfec2..c0ee902 100644
--- a/core/api/src/test/java/org/onosproject/net/link/LinkProviderRegistryAdapter.java
+++ b/core/api/src/test/java/org/onosproject/net/link/LinkProviderRegistryAdapter.java
@@ -36,11 +36,18 @@
@Override
public void unregister(LinkProvider provider) {
+ if (providerService != null && provider.id().equals(providerService.provider().id())) {
+ providerService = null;
+ }
}
@Override
public Set<ProviderId> getProviders() {
- return ImmutableSet.of(providerService.provider().id());
+ if (providerService != null) {
+ return ImmutableSet.of(providerService.provider().id());
+ } else {
+ return ImmutableSet.of();
+ }
}
public LinkProviderServiceAdapter registeredProvider() {
diff --git a/core/api/src/test/java/org/onosproject/security/PermissionTest.java b/core/api/src/test/java/org/onosproject/security/PermissionTest.java
index 191d868..bdab240 100644
--- a/core/api/src/test/java/org/onosproject/security/PermissionTest.java
+++ b/core/api/src/test/java/org/onosproject/security/PermissionTest.java
@@ -17,8 +17,6 @@
package org.onosproject.security;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertSame;
-
import org.junit.Test;
/**
@@ -70,7 +68,7 @@
public void testEqualsObject() {
Permission permissionA = new Permission("classname", "name", "actions");
Permission permissionB = new Permission("classname", "name", "actions");
- assertSame(permissionA, permissionA);
+ assertEquals(permissionA, permissionB);
assertEquals(permissionA.getClassName(), permissionB.getClassName());
assertEquals(permissionA.getName(), permissionB.getName());
assertEquals(permissionA.getActions(), permissionB.getActions());
diff --git a/core/api/src/test/java/org/onosproject/store/service/DocumentPathTest.java b/core/api/src/test/java/org/onosproject/store/service/DocumentPathTest.java
index c0137c8..19c34bd 100644
--- a/core/api/src/test/java/org/onosproject/store/service/DocumentPathTest.java
+++ b/core/api/src/test/java/org/onosproject/store/service/DocumentPathTest.java
@@ -73,6 +73,7 @@
DocumentPath path1 = exceptions("node|name", parentPath);
}
+ @SuppressWarnings("SelfComparison")
@Test
public void comparePaths() {
DocumentPath one = path("root");
diff --git a/core/api/src/test/java/org/onosproject/store/service/TestEventuallyConsistentMap.java b/core/api/src/test/java/org/onosproject/store/service/TestEventuallyConsistentMap.java
index 4a8dc47..280cffb 100644
--- a/core/api/src/test/java/org/onosproject/store/service/TestEventuallyConsistentMap.java
+++ b/core/api/src/test/java/org/onosproject/store/service/TestEventuallyConsistentMap.java
@@ -86,6 +86,7 @@
return map.get(key);
}
+ @SuppressWarnings("ReturnValueIgnored")
@Override
public void put(K key, V value) {
map.put(key, value);
diff --git a/core/api/src/test/java/org/onosproject/store/service/WallClockTimestampTest.java b/core/api/src/test/java/org/onosproject/store/service/WallClockTimestampTest.java
index 3f02fef..8ea04fd 100644
--- a/core/api/src/test/java/org/onosproject/store/service/WallClockTimestampTest.java
+++ b/core/api/src/test/java/org/onosproject/store/service/WallClockTimestampTest.java
@@ -30,6 +30,7 @@
*/
public class WallClockTimestampTest {
+ @SuppressWarnings("SelfComparison")
@Test
public final void testBasic() throws InterruptedException {
WallClockTimestamp ts1 = new WallClockTimestamp();
diff --git a/core/common/src/main/java/org/onosproject/codec/impl/AnnotationsCodec.java b/core/common/src/main/java/org/onosproject/codec/impl/AnnotationsCodec.java
index 754e24e..a155e3b 100644
--- a/core/common/src/main/java/org/onosproject/codec/impl/AnnotationsCodec.java
+++ b/core/common/src/main/java/org/onosproject/codec/impl/AnnotationsCodec.java
@@ -23,6 +23,9 @@
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.DefaultAnnotations.Builder;
+import java.util.Set;
+import java.util.TreeSet;
+
/**
* Annotations JSON codec.
*/
@@ -31,7 +34,8 @@
@Override
public ObjectNode encode(Annotations annotations, CodecContext context) {
ObjectNode result = context.mapper().createObjectNode();
- for (String key : annotations.keys()) {
+ Set<String> keys = new TreeSet<>(annotations.keys());
+ for (String key : keys) {
result.put(key, annotations.value(key));
}
return result;
diff --git a/core/common/src/main/java/org/onosproject/common/DefaultTopology.java b/core/common/src/main/java/org/onosproject/common/DefaultTopology.java
index d94c88c..4b266a8 100644
--- a/core/common/src/main/java/org/onosproject/common/DefaultTopology.java
+++ b/core/common/src/main/java/org/onosproject/common/DefaultTopology.java
@@ -119,7 +119,7 @@
*
* @param linkWeigher new default link-weight
*/
- public static void setDefaultLinkWeigher(LinkWeigher linkWeigher) {
+ public static synchronized void setDefaultLinkWeigher(LinkWeigher linkWeigher) {
log.info("Setting new default link-weight function to {}", linkWeigher);
defaultLinkWeigher = linkWeigher;
}
@@ -130,7 +130,7 @@
*
* @param graphPathSearch new default algorithm
*/
- public static void setDefaultGraphPathSearch(
+ public static synchronized void setDefaultGraphPathSearch(
GraphPathSearch<TopologyVertex, TopologyEdge> graphPathSearch) {
log.info("Setting new default graph path algorithm to {}", graphPathSearch);
defaultGraphPathSearch = graphPathSearch;
diff --git a/core/net/src/main/java/org/onosproject/net/device/impl/DeviceManager.java b/core/net/src/main/java/org/onosproject/net/device/impl/DeviceManager.java
index a0c74ca..f499d1b 100644
--- a/core/net/src/main/java/org/onosproject/net/device/impl/DeviceManager.java
+++ b/core/net/src/main/java/org/onosproject/net/device/impl/DeviceManager.java
@@ -434,6 +434,7 @@
// can't be master if device is not reachable
try {
if (myRole == MASTER) {
+ log.info("Local Role {}, Marking unreachable device {} offline", MASTER, deviceId);
post(store.markOffline(deviceId));
}
//relinquish master role and ability to be backup.
@@ -445,10 +446,11 @@
log.error("Exception thrown while relinquishing role for {}", deviceId, e);
}
} else {
- // check if the device has master, if not, mark it offline
+ // check if the device has master and is available to the store, if not, mark it offline
// only the nodes which has mastership role can mark any device offline.
+ // This condition should never be hit unless in a device removed phase for NONE mastership roles.
NodeId master = mastershipService.getMasterFor(deviceId);
- if (master == null) {
+ if (master == null && isAvailable(deviceId)) {
CompletableFuture<MastershipRole> roleFuture = mastershipService.requestRoleFor(deviceId);
roleFuture.thenAccept(role -> {
MastershipTerm term = termService.getMastershipTerm(deviceId);
diff --git a/core/net/src/main/java/org/onosproject/net/flowobjective/impl/FlowObjectiveManager.java b/core/net/src/main/java/org/onosproject/net/flowobjective/impl/FlowObjectiveManager.java
index 09d3a24..c623bf2 100644
--- a/core/net/src/main/java/org/onosproject/net/flowobjective/impl/FlowObjectiveManager.java
+++ b/core/net/src/main/java/org/onosproject/net/flowobjective/impl/FlowObjectiveManager.java
@@ -208,7 +208,7 @@
public ObjectiveInstaller(DeviceId deviceId, Objective objective, int attemps) {
this.deviceId = checkNotNull(deviceId);
this.objective = checkNotNull(objective);
- this.numAttempts = checkNotNull(attemps);
+ this.numAttempts = attemps;
}
@Override
diff --git a/core/net/src/main/java/org/onosproject/net/flowobjective/impl/composition/FlowObjectiveCompositionManager.java b/core/net/src/main/java/org/onosproject/net/flowobjective/impl/composition/FlowObjectiveCompositionManager.java
index be90cb5..a765648 100644
--- a/core/net/src/main/java/org/onosproject/net/flowobjective/impl/composition/FlowObjectiveCompositionManager.java
+++ b/core/net/src/main/java/org/onosproject/net/flowobjective/impl/composition/FlowObjectiveCompositionManager.java
@@ -177,7 +177,7 @@
public ObjectiveInstaller(DeviceId deviceId, Objective objective, int attemps) {
this.deviceId = checkNotNull(deviceId);
this.objective = checkNotNull(objective);
- this.numAttempts = checkNotNull(attemps);
+ this.numAttempts = attemps;
}
@Override
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/LinkCollectionCompiler.java b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/LinkCollectionCompiler.java
index 75b3eba..41e8e2c 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/LinkCollectionCompiler.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/LinkCollectionCompiler.java
@@ -504,7 +504,7 @@
* The ordering criteria is untagged. First we add the untagged
* ports. Then the others.
*/
- if (vlanIdCriterion == null && mplsLabelCriterion == null) {
+ if (vlanIdCriterion == null) {
orderedList.addAll(untaggedEgressPoints);
orderedList.addAll(vlanEgressPoints);
orderedList.addAll(mplsEgressPoints);
diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/PointToPointIntentCompiler.java b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/PointToPointIntentCompiler.java
index b53143b..0c47196 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/PointToPointIntentCompiler.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/compiler/PointToPointIntentCompiler.java
@@ -589,36 +589,34 @@
PointToPointIntent pointIntent) {
List<Intent> intentList = new ArrayList<>();
intentList.addAll(oldInstallables);
- erasePrimary = false;
- eraseBackup = false;
- if (intentList != null) {
- Iterator<Intent> iterator = intentList.iterator();
- while (iterator.hasNext() && !(erasePrimary && eraseBackup)) {
- Intent intent = iterator.next();
- intent.resources().forEach(resource -> {
- if (resource instanceof Link) {
- Link link = (Link) resource;
- if (link.state() == Link.State.INACTIVE) {
+
+ Iterator<Intent> iterator = intentList.iterator();
+ while (iterator.hasNext()) {
+ Intent intent = iterator.next();
+ intent.resources().forEach(resource -> {
+ if (resource instanceof Link) {
+ Link link = (Link) resource;
+ if (link.state() == Link.State.INACTIVE) {
+ setPathsToRemove(intent);
+ } else if (link instanceof EdgeLink) {
+ ConnectPoint connectPoint = (link.src().elementId() instanceof DeviceId)
+ ? link.src() : link.dst();
+ Port port = deviceService.getPort(connectPoint.deviceId(), connectPoint.port());
+ if (port == null || !port.isEnabled()) {
setPathsToRemove(intent);
- } else if (link instanceof EdgeLink) {
- ConnectPoint connectPoint = (link.src().elementId() instanceof DeviceId)
- ? link.src() : link.dst();
- Port port = deviceService.getPort(connectPoint.deviceId(), connectPoint.port());
- if (port == null || !port.isEnabled()) {
- setPathsToRemove(intent);
- }
- } else {
- Port port1 = deviceService.getPort(link.src().deviceId(), link.src().port());
- Port port2 = deviceService.getPort(link.dst().deviceId(), link.dst().port());
- if (port1 == null || !port1.isEnabled() || port2 == null || !port2.isEnabled()) {
- setPathsToRemove(intent);
- }
+ }
+ } else {
+ Port port1 = deviceService.getPort(link.src().deviceId(), link.src().port());
+ Port port2 = deviceService.getPort(link.dst().deviceId(), link.dst().port());
+ if (port1 == null || !port1.isEnabled() || port2 == null || !port2.isEnabled()) {
+ setPathsToRemove(intent);
}
}
- });
- }
- removeAndUpdateIntents(intentList, pointIntent);
+ }
+ });
}
+ removeAndUpdateIntents(intentList, pointIntent);
+
return intentList;
}
diff --git a/core/net/src/main/java/org/onosproject/net/packet/impl/PacketManager.java b/core/net/src/main/java/org/onosproject/net/packet/impl/PacketManager.java
index 943bb93..657ca48 100644
--- a/core/net/src/main/java/org/onosproject/net/packet/impl/PacketManager.java
+++ b/core/net/src/main/java/org/onosproject/net/packet/impl/PacketManager.java
@@ -385,9 +385,19 @@
// TODO filter packets sent to processors based on registrations
for (ProcessorEntry entry : processors) {
try {
+ if (log.isTraceEnabled()) {
+ log.trace("Starting packet processing by {}",
+ entry.processor().getClass().getName());
+ }
+
long start = System.nanoTime();
entry.processor().process(context);
entry.addNanos(System.nanoTime() - start);
+
+ if (log.isTraceEnabled()) {
+ log.trace("Finished packet processing by {}",
+ entry.processor().getClass().getName());
+ }
} catch (Exception e) {
log.warn("Packet processor {} threw an exception", entry.processor(), e);
}
diff --git a/core/net/src/main/java/org/onosproject/net/pi/impl/PiFlowRuleTranslatorImpl.java b/core/net/src/main/java/org/onosproject/net/pi/impl/PiFlowRuleTranslatorImpl.java
index f04e7b0..430e5e1 100644
--- a/core/net/src/main/java/org/onosproject/net/pi/impl/PiFlowRuleTranslatorImpl.java
+++ b/core/net/src/main/java/org/onosproject/net/pi/impl/PiFlowRuleTranslatorImpl.java
@@ -31,6 +31,7 @@
import org.onosproject.net.pi.model.PiActionParamModel;
import org.onosproject.net.pi.model.PiMatchFieldId;
import org.onosproject.net.pi.model.PiMatchFieldModel;
+import org.onosproject.net.pi.model.PiMatchType;
import org.onosproject.net.pi.model.PiPipeconf;
import org.onosproject.net.pi.model.PiPipelineInterpreter;
import org.onosproject.net.pi.model.PiPipelineModel;
@@ -103,26 +104,23 @@
// Build PI entry.
final PiTableEntry.Builder tableEntryBuilder = PiTableEntry.builder();
- // In the P4 world 0 is the highest priority, in ONOS the lowest one.
- // FIXME: move priority conversion to the driver, where different constraints might apply
- // e.g. less bits for encoding priority in TCAM-based implementations.
- final int newPriority;
- if (rule.priority() > MAX_PI_PRIORITY) {
- log.warn("Flow rule priority too big, setting translated priority to max value {}: {}",
- MAX_PI_PRIORITY, rule);
- newPriority = 0;
- } else {
- newPriority = MAX_PI_PRIORITY - rule.priority();
- }
+ // FIXME: P4Runtime limit
+ // Need to ignore priority if no TCAM lookup match field
+ boolean dontIgnorePriority = fieldMatches.stream()
+ .anyMatch(match -> match.type() == PiMatchType.TERNARY ||
+ match.type() == PiMatchType.RANGE);
tableEntryBuilder
.forTable(piTableId)
- .withPriority(newPriority)
.withMatchKey(PiMatchKey.builder()
.addFieldMatches(fieldMatches)
.build())
.withAction(piTableAction);
+ if (dontIgnorePriority) {
+ tableEntryBuilder.withPriority(rule.priority());
+ }
+
if (!rule.isPermanent()) {
if (tableModel.supportsAging()) {
tableEntryBuilder.withTimeout((double) rule.timeout());
diff --git a/core/net/src/test/java/org/onosproject/net/config/basics/PortAnnotationConfigTest.java b/core/net/src/test/java/org/onosproject/net/config/basics/PortAnnotationConfigTest.java
index dd3211c..df6ce7b 100644
--- a/core/net/src/test/java/org/onosproject/net/config/basics/PortAnnotationConfigTest.java
+++ b/core/net/src/test/java/org/onosproject/net/config/basics/PortAnnotationConfigTest.java
@@ -126,6 +126,7 @@
assertThat(annotations.get(key), is(value));
}
+ @Test
public void writeEntryTest() throws JsonProcessingException, IOException {
PortAnnotationConfig w = new PortAnnotationConfig();
@@ -146,6 +147,7 @@
assertThat(annotations.get(key), is(value));
}
+ @Test
public void writeMapTest() throws JsonProcessingException, IOException {
PortAnnotationConfig w = new PortAnnotationConfig();
diff --git a/core/net/src/test/java/org/onosproject/net/pi/impl/PiPipeconfManagerTest.java b/core/net/src/test/java/org/onosproject/net/pi/impl/PiPipeconfManagerTest.java
index ff3b119..b269751 100644
--- a/core/net/src/test/java/org/onosproject/net/pi/impl/PiPipeconfManagerTest.java
+++ b/core/net/src/test/java/org/onosproject/net/pi/impl/PiPipeconfManagerTest.java
@@ -138,7 +138,7 @@
@Test
public void register() {
piPipeconfService.register(piPipeconf);
- assertTrue("PiPipeconf should be registered", piPipeconfService.piPipeconfs.contains(piPipeconf));
+ assertTrue("PiPipeconf should be registered", piPipeconfService.piPipeconfs.containsValue(piPipeconf));
}
@Test
diff --git a/core/net/src/test/java/org/onosproject/net/pi/impl/PiTranslatorServiceTest.java b/core/net/src/test/java/org/onosproject/net/pi/impl/PiTranslatorServiceTest.java
index 801780e..500f8cf 100644
--- a/core/net/src/test/java/org/onosproject/net/pi/impl/PiTranslatorServiceTest.java
+++ b/core/net/src/test/java/org/onosproject/net/pi/impl/PiTranslatorServiceTest.java
@@ -66,7 +66,6 @@
import static org.onlab.util.ImmutableByteSequence.copyFrom;
import static org.onlab.util.ImmutableByteSequence.fit;
import static org.onosproject.net.group.GroupDescription.Type.SELECT;
-import static org.onosproject.net.pi.impl.PiFlowRuleTranslatorImpl.MAX_PI_PRIORITY;
import static org.onosproject.pipelines.basic.BasicConstants.ACT_PRF_WCMP_SELECTOR_ID;
import static org.onosproject.pipelines.basic.BasicConstants.ACT_PRM_PORT_ID;
import static org.onosproject.pipelines.basic.BasicConstants.ACT_SET_EGRESS_PORT_ID;
@@ -199,8 +198,10 @@
ethTypeParam.value().asReadOnlyBuffer().getShort(), is(equalTo(ethType)));
assertThat("Incorrect ethType match param mask",
ethTypeParam.mask().asReadOnlyBuffer().getShort(), is(equalTo(ETH_TYPE_MASK)));
- assertThat("Incorrect priority value",
- entry1.priority().get(), is(equalTo(MAX_PI_PRIORITY - rule1.priority())));
+ // FIXME: re-enable when P4Runtime priority handling will be moved out of transltion service
+ // see PiFlowRuleTranslatorImpl
+ // assertThat("Incorrect priority value",
+ // entry1.priority().get(), is(equalTo(MAX_PI_PRIORITY - rule1.priority())));
assertThat("Incorrect timeout value",
entry1.timeout(), is(equalTo(expectedTimeout)));
diff --git a/core/store/dist/src/main/java/org/onosproject/store/app/DistributedApplicationStore.java b/core/store/dist/src/main/java/org/onosproject/store/app/DistributedApplicationStore.java
index ffda6f5..243c3c2 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/app/DistributedApplicationStore.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/app/DistributedApplicationStore.java
@@ -150,33 +150,33 @@
@Activate
public void activate() {
messageHandlingExecutor = newSingleThreadExecutor(groupedThreads("onos/store/app",
- "message-handler", log));
+ "message-handler", log));
clusterCommunicator.addSubscriber(APP_BITS_REQUEST,
- bytes -> new String(bytes, Charsets.UTF_8),
- name -> {
- try {
- log.info("Sending bits for application {}", name);
- return toByteArray(getApplicationInputStream(name));
- } catch (IOException e) {
- throw new StorageException(e);
- }
- },
- Function.identity(),
- messageHandlingExecutor);
+ bytes -> new String(bytes, Charsets.UTF_8),
+ name -> {
+ try {
+ log.info("Sending bits for application {}", name);
+ return toByteArray(getApplicationInputStream(name));
+ } catch (IOException e) {
+ throw new StorageException(e);
+ }
+ },
+ Function.identity(),
+ messageHandlingExecutor);
apps = storageService.<ApplicationId, InternalApplicationHolder>consistentMapBuilder()
.withName("onos-apps")
.withRelaxedReadConsistency()
.withSerializer(Serializer.using(KryoNamespaces.API,
- InternalApplicationHolder.class,
- InternalState.class))
+ InternalApplicationHolder.class,
+ InternalState.class))
.build();
appActivationTopic = storageService.getTopic("onos-apps-activation-topic",
- Serializer.using(KryoNamespaces.API));
+ Serializer.using(KryoNamespaces.API));
activationExecutor = newSingleThreadExecutor(groupedThreads("onos/store/app",
- "app-activation", log));
+ "app-activation", log));
appActivationTopic.subscribe(appActivator, activationExecutor);
executor = newSingleThreadScheduledExecutor(groupedThreads("onos/app", "store", log));
@@ -313,10 +313,10 @@
@Override
public Set<Application> getApplications() {
return ImmutableSet.copyOf(apps.values()
- .stream()
- .map(Versioned::value)
- .map(InternalApplicationHolder::app)
- .collect(Collectors.toSet()));
+ .stream()
+ .map(Versioned::value)
+ .map(InternalApplicationHolder::app)
+ .collect(Collectors.toSet()));
}
@Override
@@ -425,11 +425,11 @@
if (requiredBy.get(appId).isEmpty()) {
AtomicBoolean stateChanged = new AtomicBoolean(false);
apps.computeIf(appId,
- v -> v != null && v.state() != DEACTIVATED,
- (k, v) -> {
- stateChanged.set(true);
- return new InternalApplicationHolder(v.app(), DEACTIVATED, v.permissions());
- });
+ v -> v != null && v.state() != DEACTIVATED,
+ (k, v) -> {
+ stateChanged.set(true);
+ return new InternalApplicationHolder(v.app(), DEACTIVATED, v.permissions());
+ });
if (stateChanged.get()) {
updateTime(appId.name());
deactivateRequiredApps(appId);
@@ -440,22 +440,22 @@
// Deactivates all apps that require this application.
private void deactivateDependentApps(ApplicationId appId) {
apps.values()
- .stream()
- .map(Versioned::value)
- .filter(a -> a.state() == ACTIVATED)
- .filter(a -> a.app().requiredApps().contains(appId.name()))
- .forEach(a -> deactivate(a.app().id()));
+ .stream()
+ .map(Versioned::value)
+ .filter(a -> a.state() == ACTIVATED)
+ .filter(a -> a.app().requiredApps().contains(appId.name()))
+ .forEach(a -> deactivate(a.app().id()));
}
// Deactivates all apps required by this application.
private void deactivateRequiredApps(ApplicationId appId) {
getApplication(appId).requiredApps()
- .stream()
- .map(this::getId)
- .map(apps::get)
- .map(Versioned::value)
- .filter(a -> a.state() == ACTIVATED)
- .forEach(a -> deactivate(a.app().id(), appId));
+ .stream()
+ .map(this::getId)
+ .map(apps::get)
+ .map(Versioned::value)
+ .filter(a -> a.state() == ACTIVATED)
+ .forEach(a -> deactivate(a.app().id(), appId));
}
@Override
@@ -468,11 +468,11 @@
public void setPermissions(ApplicationId appId, Set<Permission> permissions) {
AtomicBoolean permissionsChanged = new AtomicBoolean(false);
Versioned<InternalApplicationHolder> appHolder = apps.computeIf(appId,
- v -> v != null && !Sets.symmetricDifference(v.permissions(), permissions).isEmpty(),
- (k, v) -> {
- permissionsChanged.set(true);
- return new InternalApplicationHolder(v.app(), v.state(), ImmutableSet.copyOf(permissions));
- });
+ v -> v != null && !Sets.symmetricDifference(v.permissions(), permissions).isEmpty(),
+ (k, v) -> {
+ permissionsChanged.set(true);
+ return new InternalApplicationHolder(v.app(), v.state(), ImmutableSet.copyOf(permissions));
+ });
if (permissionsChanged.get()) {
notifyDelegate(new ApplicationEvent(APP_PERMISSIONS_CHANGED, appHolder.value().app()));
}
@@ -509,14 +509,18 @@
ApplicationId appId = event.key();
InternalApplicationHolder newApp = event.newValue() == null ? null : event.newValue().value();
InternalApplicationHolder oldApp = event.oldValue() == null ? null : event.oldValue().value();
- if (event.type() == MapEvent.Type.INSERT || event.type() == MapEvent.Type.UPDATE) {
- if (event.type() == MapEvent.Type.UPDATE && newApp.state() == oldApp.state()) {
- return;
- }
+ if (event.type() == MapEvent.Type.UPDATE && (newApp == null || oldApp == null ||
+ newApp.state() == oldApp.state())) {
+ log.warn("Can't update the application {}", event.key());
+ return;
+ }
+ if ((event.type() == MapEvent.Type.INSERT || event.type() == MapEvent.Type.UPDATE) && newApp != null) {
setupApplicationAndNotify(appId, newApp.app(), newApp.state());
- } else if (event.type() == MapEvent.Type.REMOVE) {
- purgeApplication(appId.name());
+ } else if (event.type() == MapEvent.Type.REMOVE && oldApp != null) {
notifyDelegate(new ApplicationEvent(APP_UNINSTALLED, oldApp.app()));
+ purgeApplication(appId.name());
+ } else {
+ log.warn("Can't perform {} on application {}", event.type(), event.key());
}
}
}
@@ -580,22 +584,22 @@
continue;
}
clusterCommunicator.sendAndReceive(app.id().name(),
- APP_BITS_REQUEST,
- s -> s.getBytes(Charsets.UTF_8),
- Function.identity(),
- node.id())
+ APP_BITS_REQUEST,
+ s -> s.getBytes(Charsets.UTF_8),
+ Function.identity(),
+ node.id())
.whenCompleteAsync((bits, error) -> {
if (error == null && latch.getCount() > 0) {
saveApplication(new ByteArrayInputStream(bits));
log.info("Downloaded bits for application {} from node {}",
- app.id().name(), node.id());
+ app.id().name(), node.id());
latch.countDown();
if (delegateInstallation) {
notifyDelegate(new ApplicationEvent(APP_INSTALLED, app));
}
} else if (error != null) {
log.warn("Unable to fetch bits for application {} from node {}",
- app.id().name(), node.id());
+ app.id().name(), node.id());
}
}, messageHandlingExecutor);
}
diff --git a/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/DistributedClusterStore.java b/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/DistributedClusterStore.java
index b106763..47e5a96 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/DistributedClusterStore.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/DistributedClusterStore.java
@@ -293,6 +293,7 @@
if (phi >= phiFailureThreshold) {
if (currentState.isActive()) {
updateNode(node.id(), State.INACTIVE, null);
+ failureDetector.reset(node.id());
}
} else {
if (currentState == State.INACTIVE) {
@@ -334,7 +335,12 @@
public void accept(Endpoint sender, byte[] message) {
HeartbeatMessage hb = SERIALIZER.decode(message);
if (clusterMetadataService.getClusterMetadata().getNodes().contains(hb.source())) {
- failureDetector.report(hb.source().id());
+ // Avoid reporting heartbeats that have been enqueued by setting a minimum interval.
+ long heartbeatTime = System.currentTimeMillis();
+ long lastHeartbeatTime = failureDetector.getLastHeartbeatTime(hb.source().id());
+ if (heartbeatTime - lastHeartbeatTime > heartbeatInterval / 2) {
+ failureDetector.report(hb.source().id(), heartbeatTime);
+ }
updateNode(hb.source().id(), hb.state, hb.version);
}
}
diff --git a/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/PhiAccrualFailureDetector.java b/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/PhiAccrualFailureDetector.java
index 590946d..b80142b 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/PhiAccrualFailureDetector.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/cluster/impl/PhiAccrualFailureDetector.java
@@ -49,6 +49,17 @@
private double bootstrapPhiValue = DEFAULT_BOOTSTRAP_PHI_VALUE;
/**
+ * Returns the last heartbeat time for the given node.
+ *
+ * @param nodeId the node identifier
+ * @return the last heartbeat time for the given node
+ */
+ public long getLastHeartbeatTime(NodeId nodeId) {
+ History nodeState = states.computeIfAbsent(nodeId, key -> new History());
+ return nodeState.latestHeartbeatTime();
+ }
+
+ /**
* Report a new heart beat for the specified node id.
* @param nodeId node id
*/
@@ -75,7 +86,14 @@
}
}
-
+ /**
+ * Resets the failure detector for the given node.
+ *
+ * @param nodeId node identifier for the node for which to reset the failure detector
+ */
+ public void reset(NodeId nodeId) {
+ states.remove(nodeId);
+ }
/**
* Compute phi for the specified node id.
diff --git a/core/store/dist/src/main/java/org/onosproject/store/cluster/messaging/impl/NettyMessagingManager.java b/core/store/dist/src/main/java/org/onosproject/store/cluster/messaging/impl/NettyMessagingManager.java
index 50c8fc6f..a5c5f3b 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/cluster/messaging/impl/NettyMessagingManager.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/cluster/messaging/impl/NettyMessagingManager.java
@@ -49,10 +49,8 @@
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
-import java.util.function.Consumer;
import java.util.function.Function;
-import com.google.common.base.Throwables;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.Lists;
@@ -341,40 +339,10 @@
return Math.abs(messageType.hashCode() % CHANNEL_POOL_SIZE);
}
- private <T> CompletableFuture<T> executeOnPooledConnection(
- Endpoint endpoint,
- String type,
- Function<ClientConnection, CompletableFuture<T>> callback,
- Executor executor) {
- CompletableFuture<T> future = new CompletableFuture<T>();
- executeOnPooledConnection(endpoint, type, callback, executor, future);
- return future;
- }
-
- private <T> void executeOnPooledConnection(
- Endpoint endpoint,
- String type,
- Function<ClientConnection, CompletableFuture<T>> callback,
- Executor executor,
- CompletableFuture<T> future) {
-
- // If the endpoint is the local node, avoid the loopback interface and use the singleton local connection.
- if (endpoint.equals(localEndpoint)) {
- callback.apply(localClientConnection).whenComplete((result, error) -> {
- if (error == null) {
- executor.execute(() -> future.complete(result));
- } else {
- executor.execute(() -> future.completeExceptionally(error));
- }
- });
- return;
- }
-
- // Get the channel pool and the offset for this message type.
+ private CompletableFuture<Channel> getChannel(Endpoint endpoint, String messageType) {
List<CompletableFuture<Channel>> channelPool = getChannelPool(endpoint);
- int offset = getChannelOffset(type);
+ int offset = getChannelOffset(messageType);
- // If the channel future is completed exceptionally, open a new channel.
CompletableFuture<Channel> channelFuture = channelPool.get(offset);
if (channelFuture == null || channelFuture.isCompletedExceptionally()) {
synchronized (channelPool) {
@@ -386,29 +354,7 @@
}
}
- // Create a consumer with which to complete the send operation on a given channel.
- final Consumer<Channel> runner = channel -> {
- ClientConnection connection = clientConnections.computeIfAbsent(channel, RemoteClientConnection::new);
- callback.apply(connection).whenComplete((result, sendError) -> {
- if (sendError == null) {
- executor.execute(() -> future.complete(result));
- } else {
- // If an exception other than a TimeoutException occurred, close the connection and
- // remove the channel from the pool.
- if (!(Throwables.getRootCause(sendError) instanceof TimeoutException)) {
- synchronized (channelPool) {
- channelPool.set(offset, null);
- }
- connection.close();
- channel.close();
- }
- executor.execute(() -> future.completeExceptionally(sendError));
- }
- });
- };
-
- // Wait for the channel future to be completed. Once it's complete, if the channel is active then
- // attempt to send the message. Otherwise, if the channel is inactive then attempt to open a new channel.
+ CompletableFuture<Channel> future = new CompletableFuture<>();
final CompletableFuture<Channel> finalFuture = channelFuture;
finalFuture.whenComplete((channel, error) -> {
if (error == null) {
@@ -417,11 +363,17 @@
CompletableFuture<Channel> currentFuture = channelPool.get(offset);
if (currentFuture == finalFuture) {
channelPool.set(offset, null);
- executeOnPooledConnection(endpoint, type, callback, executor);
+ getChannel(endpoint, messageType).whenComplete((recursiveResult, recursiveError) -> {
+ if (recursiveError == null) {
+ future.complete(recursiveResult);
+ } else {
+ future.completeExceptionally(recursiveError);
+ }
+ });
} else {
currentFuture.whenComplete((recursiveResult, recursiveError) -> {
if (recursiveError == null) {
- runner.accept(recursiveResult);
+ future.complete(recursiveResult);
} else {
future.completeExceptionally(recursiveError);
}
@@ -429,12 +381,56 @@
}
}
} else {
- runner.accept(channel);
+ future.complete(channel);
}
} else {
future.completeExceptionally(error);
}
});
+ return future;
+ }
+
+ private <T> CompletableFuture<T> executeOnPooledConnection(
+ Endpoint endpoint,
+ String type,
+ Function<ClientConnection, CompletableFuture<T>> callback,
+ Executor executor) {
+ CompletableFuture<T> future = new CompletableFuture<T>();
+ executeOnPooledConnection(endpoint, type, callback, executor, future);
+ return future;
+ }
+
+ private <T> void executeOnPooledConnection(
+ Endpoint endpoint,
+ String type,
+ Function<ClientConnection, CompletableFuture<T>> callback,
+ Executor executor,
+ CompletableFuture<T> future) {
+ if (endpoint.equals(localEndpoint)) {
+ callback.apply(localClientConnection).whenComplete((result, error) -> {
+ if (error == null) {
+ executor.execute(() -> future.complete(result));
+ } else {
+ executor.execute(() -> future.completeExceptionally(error));
+ }
+ });
+ return;
+ }
+
+ getChannel(endpoint, type).whenComplete((channel, channelError) -> {
+ if (channelError == null) {
+ ClientConnection connection = clientConnections.computeIfAbsent(channel, RemoteClientConnection::new);
+ callback.apply(connection).whenComplete((result, sendError) -> {
+ if (sendError == null) {
+ executor.execute(() -> future.complete(result));
+ } else {
+ executor.execute(() -> future.completeExceptionally(sendError));
+ }
+ });
+ } else {
+ executor.execute(() -> future.completeExceptionally(channelError));
+ }
+ });
}
@Override
diff --git a/core/store/dist/src/main/java/org/onosproject/store/device/impl/GossipDeviceStore.java b/core/store/dist/src/main/java/org/onosproject/store/device/impl/GossipDeviceStore.java
index c4fe0a8..ded0f31 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/device/impl/GossipDeviceStore.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/device/impl/GossipDeviceStore.java
@@ -317,7 +317,7 @@
? deviceClockService.getTimestamp(deviceId)
: removalRequest.getOrDefault(deviceId, DEFAULT_TIMESTAMP);
} catch (IllegalStateException e) {
- newTimestamp = removalRequest.getOrDefault(deviceDescription, DEFAULT_TIMESTAMP);
+ newTimestamp = removalRequest.getOrDefault(deviceId, DEFAULT_TIMESTAMP);
isMaster = false;
}
final Timestamped<DeviceDescription> deltaDesc = new Timestamped<>(deviceDescription, newTimestamp);
@@ -617,7 +617,7 @@
return Collections.emptyList();
}
- return deviceEvents == null ? Collections.emptyList() : deviceEvents;
+ return deviceEvents;
}
private List<DeviceEvent> updatePortsInternal(ProviderId providerId,
diff --git a/core/store/dist/src/main/java/org/onosproject/store/flow/impl/ECFlowRuleStore.java b/core/store/dist/src/main/java/org/onosproject/store/flow/impl/ECFlowRuleStore.java
index 266e6fb..64c09cf 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/flow/impl/ECFlowRuleStore.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/flow/impl/ECFlowRuleStore.java
@@ -827,15 +827,16 @@
public FlowEntry remove(DeviceId deviceId, FlowEntry rule) {
final AtomicReference<FlowEntry> removedRule = new AtomicReference<>();
- getFlowEntriesInternal(rule.deviceId(), rule.id())
- .computeIfPresent((StoredFlowEntry) rule, (k, stored) -> {
+ final Map<FlowId, Map<StoredFlowEntry, StoredFlowEntry>> flowTable = getFlowTable(deviceId);
+ flowTable.computeIfPresent(rule.id(), (flowId, flowEntries) -> {
+ flowEntries.computeIfPresent((StoredFlowEntry) rule, (k, stored) -> {
if (rule instanceof DefaultFlowEntry) {
DefaultFlowEntry toRemove = (DefaultFlowEntry) rule;
if (stored instanceof DefaultFlowEntry) {
DefaultFlowEntry storedEntry = (DefaultFlowEntry) stored;
if (toRemove.created() < storedEntry.created()) {
log.debug("Trying to remove more recent flow entry {} (stored: {})",
- toRemove, stored);
+ toRemove, stored);
// the key is not updated, removedRule remains null
return stored;
}
@@ -844,6 +845,8 @@
removedRule.set(stored);
return null;
});
+ return flowEntries.isEmpty() ? null : flowEntries;
+ });
if (removedRule.get() != null) {
lastUpdateTimes.put(deviceId, System.currentTimeMillis());
diff --git a/core/store/dist/src/main/java/org/onosproject/store/host/impl/DistributedHostStore.java b/core/store/dist/src/main/java/org/onosproject/store/host/impl/DistributedHostStore.java
index dcf58e6..9cf9856 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/host/impl/DistributedHostStore.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/host/impl/DistributedHostStore.java
@@ -477,7 +477,7 @@
}
}
- if (existingHosts.isEmpty()) {
+ if (existingHosts == null || existingHosts.isEmpty()) {
return null;
}
return existingHosts;
diff --git a/core/store/dist/src/main/java/org/onosproject/store/resource/impl/ConsistentResourceStore.java b/core/store/dist/src/main/java/org/onosproject/store/resource/impl/ConsistentResourceStore.java
index 14ed0ed..e5ed75b 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/resource/impl/ConsistentResourceStore.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/resource/impl/ConsistentResourceStore.java
@@ -63,6 +63,7 @@
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
+import static java.util.stream.Collectors.groupingBy;
import static org.onosproject.net.resource.ResourceEvent.Type.RESOURCE_ADDED;
import static org.onosproject.net.resource.ResourceEvent.Type.RESOURCE_REMOVED;
@@ -132,7 +133,7 @@
// the order is preserved by LinkedHashMap
Map<DiscreteResource, List<Resource>> resourceMap = resources.stream()
.filter(x -> x.parent().isPresent())
- .collect(Collectors.groupingBy(x -> x.parent().get(), LinkedHashMap::new, Collectors.toList()));
+ .collect(groupingBy(x -> x.parent().get(), LinkedHashMap::new, Collectors.<Resource>toList()));
TransactionalDiscreteResourceSubStore discreteTxStore = discreteStore.transactional(tx);
TransactionalContinuousResourceSubStore continuousTxStore = continuousStore.transactional(tx);
diff --git a/core/store/dist/src/test/java/org/onosproject/store/impl/MastershipBasedTimestampTest.java b/core/store/dist/src/test/java/org/onosproject/store/impl/MastershipBasedTimestampTest.java
index 605de95..bbbc616 100644
--- a/core/store/dist/src/test/java/org/onosproject/store/impl/MastershipBasedTimestampTest.java
+++ b/core/store/dist/src/test/java/org/onosproject/store/impl/MastershipBasedTimestampTest.java
@@ -47,6 +47,7 @@
assertEquals(sequenceNumber, ts.sequenceNumber());
}
+ @SuppressWarnings("SelfComparison")
@Test
public final void testCompareTo() {
assertTrue(TS_1_1.compareTo(TS_1_1) == 0);
diff --git a/core/store/primitives/pom.xml b/core/store/primitives/pom.xml
index a0b7473..5f4d799 100644
--- a/core/store/primitives/pom.xml
+++ b/core/store/primitives/pom.xml
@@ -70,7 +70,7 @@
<dependency>
<groupId>io.atomix</groupId>
<artifactId>atomix</artifactId>
- <version>2.0.12</version>
+ <version>2.0.14</version>
</dependency>
<dependency>
diff --git a/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/StoragePartition.java b/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/StoragePartition.java
index c419d98..5d33e1c 100644
--- a/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/StoragePartition.java
+++ b/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/StoragePartition.java
@@ -265,7 +265,7 @@
// Only need to do action if our membership changed
if (wasPresent) {
leaveCluster();
- } else if (isPresent) {
+ } else {
joinCluster();
}
}
diff --git a/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/StoragePartitionClient.java b/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/StoragePartitionClient.java
index f5f8a99..723dc51 100644
--- a/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/StoragePartitionClient.java
+++ b/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/StoragePartitionClient.java
@@ -64,13 +64,15 @@
*/
public class StoragePartitionClient implements DistributedPrimitiveCreator, Managed<StoragePartitionClient> {
+ private static final int MAX_RETRIES = 8;
+ private static final String ATOMIC_VALUES_CONSISTENT_MAP_NAME = "onos-atomic-values";
+
private final Logger log = getLogger(getClass());
private final StoragePartition partition;
private final MemberId localMemberId;
private final RaftClientProtocol protocol;
private RaftClient client;
- private static final String ATOMIC_VALUES_CONSISTENT_MAP_NAME = "onos-atomic-values";
private final com.google.common.base.Supplier<AsyncConsistentMap<String, byte[]>> onosAtomicValuesMap =
Suppliers.memoize(() -> newAsyncConsistentMap(ATOMIC_VALUES_CONSISTENT_MAP_NAME,
Serializer.using(KryoNamespaces.BASIC)));
@@ -110,7 +112,7 @@
.withReadConsistency(ReadConsistency.SEQUENTIAL)
.withCommunicationStrategy(CommunicationStrategy.ANY)
.withTimeout(Duration.ofSeconds(30))
- .withMaxRetries(5)
+ .withMaxRetries(MAX_RETRIES)
.build()
.open()
.join());
@@ -135,7 +137,7 @@
.withReadConsistency(ReadConsistency.SEQUENTIAL)
.withCommunicationStrategy(CommunicationStrategy.ANY)
.withTimeout(Duration.ofSeconds(30))
- .withMaxRetries(5)
+ .withMaxRetries(MAX_RETRIES)
.build()
.open()
.join());
@@ -159,7 +161,7 @@
.withReadConsistency(ReadConsistency.SEQUENTIAL)
.withCommunicationStrategy(CommunicationStrategy.ANY)
.withTimeout(Duration.ofSeconds(30))
- .withMaxRetries(5)
+ .withMaxRetries(MAX_RETRIES)
.build()
.open()
.join());
@@ -189,7 +191,7 @@
.withReadConsistency(ReadConsistency.LINEARIZABLE_LEASE)
.withCommunicationStrategy(CommunicationStrategy.LEADER)
.withTimeout(Duration.ofSeconds(30))
- .withMaxRetries(5)
+ .withMaxRetries(MAX_RETRIES)
.build()
.open()
.join());
@@ -211,7 +213,7 @@
.withReadConsistency(ReadConsistency.LINEARIZABLE_LEASE)
.withCommunicationStrategy(CommunicationStrategy.LEADER)
.withTimeout(Duration.ofSeconds(30))
- .withMaxRetries(5)
+ .withMaxRetries(MAX_RETRIES)
.build()
.open()
.join());
@@ -235,7 +237,7 @@
.withReadConsistency(ReadConsistency.LINEARIZABLE_LEASE)
.withCommunicationStrategy(CommunicationStrategy.LEADER)
.withTimeout(Duration.ofSeconds(5))
- .withMaxRetries(5)
+ .withMaxRetries(MAX_RETRIES)
.build()
.open()
.join());
@@ -250,7 +252,7 @@
.withReadConsistency(ReadConsistency.SEQUENTIAL)
.withCommunicationStrategy(CommunicationStrategy.ANY)
.withTimeout(Duration.ofSeconds(30))
- .withMaxRetries(5)
+ .withMaxRetries(MAX_RETRIES)
.build()
.open()
.join());
@@ -266,7 +268,7 @@
.withCommunicationStrategy(CommunicationStrategy.LEADER)
.withMinTimeout(Duration.ofMillis(timeUnit.toMillis(leaderTimeout)))
.withMaxTimeout(Duration.ofSeconds(5))
- .withMaxRetries(5)
+ .withMaxRetries(MAX_RETRIES)
.build()
.open()
.join());
diff --git a/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/StoragePartitionServer.java b/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/StoragePartitionServer.java
index c9cfe53..1b201cd 100644
--- a/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/StoragePartitionServer.java
+++ b/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/StoragePartitionServer.java
@@ -49,7 +49,8 @@
private static final int MAX_SEGMENT_SIZE = 1024 * 1024 * 64;
private static final long ELECTION_TIMEOUT_MILLIS = 2500;
- private static final long HEARTBEAT_INTERVAL_MILLIS = 250;
+ private static final int ELECTION_THRESHOLD = 5;
+ private static final long HEARTBEAT_INTERVAL_MILLIS = 500;
private final MemberId localMemberId;
private final StoragePartition partition;
@@ -143,9 +144,11 @@
clusterCommunicator))
.withElectionTimeout(Duration.ofMillis(ELECTION_TIMEOUT_MILLIS))
.withHeartbeatInterval(Duration.ofMillis(HEARTBEAT_INTERVAL_MILLIS))
+ .withElectionThreshold(ELECTION_THRESHOLD)
.withStorage(RaftStorage.newBuilder()
.withPrefix(String.format("partition-%s", partition.getId()))
- .withStorageLevel(StorageLevel.MAPPED)
+ .withStorageLevel(StorageLevel.DISK)
+ .withFlushOnCommit()
.withSerializer(new AtomixSerializerAdapter(Serializer.using(StorageNamespaces.RAFT_STORAGE)))
.withDirectory(partition.getDataFolder())
.withMaxSegmentSize(MAX_SEGMENT_SIZE)
@@ -200,9 +203,11 @@
clusterCommunicator))
.withElectionTimeout(Duration.ofMillis(ELECTION_TIMEOUT_MILLIS))
.withHeartbeatInterval(Duration.ofMillis(HEARTBEAT_INTERVAL_MILLIS))
+ .withElectionThreshold(ELECTION_THRESHOLD)
.withStorage(RaftStorage.newBuilder()
.withPrefix(String.format("partition-%s", partition.getId()))
- .withStorageLevel(StorageLevel.MAPPED)
+ .withStorageLevel(StorageLevel.DISK)
+ .withFlushOnCommit()
.withSerializer(new AtomixSerializerAdapter(Serializer.using(StorageNamespaces.RAFT_STORAGE)))
.withDirectory(partition.getDataFolder())
.withMaxSegmentSize(MAX_SEGMENT_SIZE)
diff --git a/core/store/primitives/src/main/java/org/onosproject/store/primitives/resources/impl/DefaultDocumentTree.java b/core/store/primitives/src/main/java/org/onosproject/store/primitives/resources/impl/DefaultDocumentTree.java
index 82098d3..2d5832c 100644
--- a/core/store/primitives/src/main/java/org/onosproject/store/primitives/resources/impl/DefaultDocumentTree.java
+++ b/core/store/primitives/src/main/java/org/onosproject/store/primitives/resources/impl/DefaultDocumentTree.java
@@ -21,6 +21,7 @@
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
+import java.util.Optional;
import java.util.concurrent.atomic.AtomicLong;
import org.onosproject.store.service.DocumentPath;
@@ -148,13 +149,17 @@
}
@Override
- public boolean replace(DocumentPath path, V newValue, V currentValue) {
+ public boolean replace(DocumentPath path, V newValue, V expectedValue) {
checkRootModification(path);
- if (Objects.equals(newValue, currentValue)) {
+ if (Objects.equals(newValue, expectedValue)) {
return false;
}
DocumentTreeNode<V> node = getNode(path);
- if (node != null && Objects.equals(Versioned.valueOrNull(node.value()), currentValue)) {
+ V prevValue = Optional.ofNullable(node)
+ .map(DocumentTreeNode::value)
+ .map(Versioned::valueOrNull)
+ .orElse(null);
+ if (Objects.equals(prevValue, expectedValue)) {
set(path, newValue);
return true;
}
diff --git a/core/store/primitives/src/test/java/org/onosproject/store/primitives/impl/MapValueTest.java b/core/store/primitives/src/test/java/org/onosproject/store/primitives/impl/MapValueTest.java
index 70c33e1..cfad4e4 100644
--- a/core/store/primitives/src/test/java/org/onosproject/store/primitives/impl/MapValueTest.java
+++ b/core/store/primitives/src/test/java/org/onosproject/store/primitives/impl/MapValueTest.java
@@ -48,6 +48,7 @@
assertEquals(actual, expected);
}
+ @SuppressWarnings("SelfComparison")
@Test
public void testComparison() {
Timestamp ts1 = new LogicalTimestamp(9);
diff --git a/core/store/primitives/src/test/java/org/onosproject/store/primitives/impl/TranscodingAsyncConsistentMapTest.java b/core/store/primitives/src/test/java/org/onosproject/store/primitives/impl/TranscodingAsyncConsistentMapTest.java
index 2cc9631..6466c12 100644
--- a/core/store/primitives/src/test/java/org/onosproject/store/primitives/impl/TranscodingAsyncConsistentMapTest.java
+++ b/core/store/primitives/src/test/java/org/onosproject/store/primitives/impl/TranscodingAsyncConsistentMapTest.java
@@ -115,6 +115,7 @@
assertFalse(transcodingMap.containsValue(DEV1).join());
}
+ @Test
public void testGet() throws Exception {
assertNull(transcodingMap.get(KEY1).join().value());
transcodingMap.put(KEY2, DEV1).join();
diff --git a/core/store/primitives/src/test/java/org/onosproject/store/primitives/resources/impl/AtomixConsistentSetMultimapServiceTest.java b/core/store/primitives/src/test/java/org/onosproject/store/primitives/resources/impl/AtomixConsistentSetMultimapServiceTest.java
index c05ebcb..66173d0 100644
--- a/core/store/primitives/src/test/java/org/onosproject/store/primitives/resources/impl/AtomixConsistentSetMultimapServiceTest.java
+++ b/core/store/primitives/src/test/java/org/onosproject/store/primitives/resources/impl/AtomixConsistentSetMultimapServiceTest.java
@@ -15,8 +15,8 @@
*/
package org.onosproject.store.primitives.resources.impl;
-import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import io.atomix.protocols.raft.service.ServiceId;
import io.atomix.protocols.raft.service.impl.DefaultCommit;
@@ -57,7 +57,7 @@
2,
PUT,
new AtomixConsistentSetMultimapOperations.Put(
- "foo", Arrays.asList("Hello world!".getBytes()), Match.ANY),
+ "foo", Collections.singletonList("Hello world!".getBytes()), Match.ANY),
mock(RaftSessionContext.class),
System.currentTimeMillis()));
diff --git a/core/store/primitives/src/test/java/org/onosproject/store/primitives/resources/impl/AtomixDocumentTreeTest.java b/core/store/primitives/src/test/java/org/onosproject/store/primitives/resources/impl/AtomixDocumentTreeTest.java
index 18746a7..7a41395 100644
--- a/core/store/primitives/src/test/java/org/onosproject/store/primitives/resources/impl/AtomixDocumentTreeTest.java
+++ b/core/store/primitives/src/test/java/org/onosproject/store/primitives/resources/impl/AtomixDocumentTreeTest.java
@@ -27,6 +27,7 @@
import com.google.common.base.Throwables;
import io.atomix.protocols.raft.proxy.RaftProxy;
import io.atomix.protocols.raft.service.RaftService;
+
import org.junit.Test;
import org.onosproject.store.primitives.NodeUpdate;
import org.onosproject.store.primitives.TransactionId;
@@ -219,6 +220,9 @@
assertArrayEquals("newAB".getBytes(), tree.get(path("root.a.b")).join().value());
assertFalse(tree.replace(path("root.a.d"), "bar".getBytes(), "foo".getBytes()).join());
+
+ assertTrue(tree.replace(path("root.x"), "beta".getBytes(), null).join());
+
}
/**
diff --git a/core/store/primitives/src/test/java/org/onosproject/store/primitives/resources/impl/AtomixWorkQueueServiceTest.java b/core/store/primitives/src/test/java/org/onosproject/store/primitives/resources/impl/AtomixWorkQueueServiceTest.java
index 919d3c9..2529523 100644
--- a/core/store/primitives/src/test/java/org/onosproject/store/primitives/resources/impl/AtomixWorkQueueServiceTest.java
+++ b/core/store/primitives/src/test/java/org/onosproject/store/primitives/resources/impl/AtomixWorkQueueServiceTest.java
@@ -15,8 +15,8 @@
*/
package org.onosproject.store.primitives.resources.impl;
-import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import io.atomix.protocols.raft.ReadConsistency;
import io.atomix.protocols.raft.cluster.MemberId;
@@ -93,7 +93,7 @@
service.add(new DefaultCommit<>(
2,
ADD,
- new AtomixWorkQueueOperations.Add(Arrays.asList("Hello world!".getBytes())),
+ new AtomixWorkQueueOperations.Add(Collections.singletonList("Hello world!".getBytes())),
session,
System.currentTimeMillis()));
diff --git a/core/store/primitives/src/test/java/org/onosproject/store/primitives/resources/impl/DefaultDocumentTreeTest.java b/core/store/primitives/src/test/java/org/onosproject/store/primitives/resources/impl/DefaultDocumentTreeTest.java
index 5505e0d..1398300 100644
--- a/core/store/primitives/src/test/java/org/onosproject/store/primitives/resources/impl/DefaultDocumentTreeTest.java
+++ b/core/store/primitives/src/test/java/org/onosproject/store/primitives/resources/impl/DefaultDocumentTreeTest.java
@@ -148,6 +148,7 @@
tree.set(path("root.a.b"), "alpha");
}
+ @Test
public void testReplaceWithVersion() {
DocumentTree<String> tree = new DefaultDocumentTree<>();
tree.create(path("root.a"), "bar");
@@ -158,6 +159,7 @@
Assert.assertFalse(tree.replace(path("root.x"), "beta", 1));
}
+ @Test
public void testReplaceWithValue() {
DocumentTree<String> tree = new DefaultDocumentTree<>();
tree.create(path("root.a"), "bar");
diff --git a/core/store/primitives/src/test/java/org/onosproject/store/primitives/resources/impl/TestClusterCommunicationService.java b/core/store/primitives/src/test/java/org/onosproject/store/primitives/resources/impl/TestClusterCommunicationService.java
index a15bba4..791a488 100644
--- a/core/store/primitives/src/test/java/org/onosproject/store/primitives/resources/impl/TestClusterCommunicationService.java
+++ b/core/store/primitives/src/test/java/org/onosproject/store/primitives/resources/impl/TestClusterCommunicationService.java
@@ -72,9 +72,9 @@
@Override
public <M> void multicast(M message, MessageSubject subject, Function<M, byte[]> encoder, Set<NodeId> nodeIds) {
- nodes.values().stream()
- .filter(n -> nodeIds.contains(n))
- .forEach(n -> n.handle(subject, encoder.apply(message)));
+ nodes.entrySet().stream()
+ .filter(e -> nodeIds.contains(e.getKey()))
+ .forEach(e -> e.getValue().handle(subject, encoder.apply(message)));
}
@Override
diff --git a/drivers/bmv2/BUCK b/drivers/bmv2/BUCK
index 63feb68..728f92b 100644
--- a/drivers/bmv2/BUCK
+++ b/drivers/bmv2/BUCK
@@ -28,6 +28,7 @@
included_bundles = BUNDLES,
required_apps = [
'org.onosproject.drivers.p4runtime',
+ 'org.onosproject.drivers.gnmi',
'org.onosproject.pipelines.basic',
],
)
diff --git a/drivers/bmv2/src/main/resources/bmv2-drivers.xml b/drivers/bmv2/src/main/resources/bmv2-drivers.xml
index 22bf067..0d6e0daa 100644
--- a/drivers/bmv2/src/main/resources/bmv2-drivers.xml
+++ b/drivers/bmv2/src/main/resources/bmv2-drivers.xml
@@ -15,7 +15,7 @@
~ limitations under the License.
-->
<drivers>
- <driver name="bmv2" manufacturer="p4.org" hwVersion="master" swVersion="master" extends="p4runtime">
+ <driver name="bmv2" manufacturer="p4.org" hwVersion="master" swVersion="master" extends="p4runtime, gnmi">
<behaviour api="org.onosproject.net.behaviour.PiPipelineProgrammable"
impl="org.onosproject.drivers.bmv2.Bmv2PipelineProgrammable"/>
</driver>
diff --git a/drivers/ciena/src/main/java/org/onosproject/drivers/ciena/CienaWaveserverDeviceDescription.java b/drivers/ciena/src/main/java/org/onosproject/drivers/ciena/CienaWaveserverDeviceDescription.java
index 1c4114c..8a6113b 100644
--- a/drivers/ciena/src/main/java/org/onosproject/drivers/ciena/CienaWaveserverDeviceDescription.java
+++ b/drivers/ciena/src/main/java/org/onosproject/drivers/ciena/CienaWaveserverDeviceDescription.java
@@ -169,8 +169,9 @@
//Working in Ghz //(Nominal central frequency - 193.1)/channelSpacing = spacingMultiplier
final int baseFrequency = 193100;
+ long spacingFrequency = chSpacing == null ? baseFrequency : chSpacing.frequency().asHz();
int spacingMult = ((int) (toGbps(((int) config.getDouble(frequency) -
- baseFrequency)) / toGbpsFromHz(chSpacing.frequency().asHz()))); //FIXME is there a better way ?
+ baseFrequency)) / toGbpsFromHz(spacingFrequency))); //FIXME is there a better way ?
return ochPortDescription(PortNumber.portNumber(portNumber), isEnabled, OduSignalType.ODU4, isTunable,
new OchSignal(gridType, chSpacing, spacingMult, 1), annotations);
diff --git a/drivers/corsa/src/main/java/org/onosproject/drivers/corsa/CorsaPipelineV3.java b/drivers/corsa/src/main/java/org/onosproject/drivers/corsa/CorsaPipelineV3.java
index 098da40..3eb6261 100644
--- a/drivers/corsa/src/main/java/org/onosproject/drivers/corsa/CorsaPipelineV3.java
+++ b/drivers/corsa/src/main/java/org/onosproject/drivers/corsa/CorsaPipelineV3.java
@@ -82,10 +82,8 @@
switch (i.type()) {
case L2MODIFICATION:
L2ModificationInstruction l2i = (L2ModificationInstruction) i;
- if (l2i instanceof L2ModificationInstruction.ModVlanIdInstruction ||
- l2i instanceof L2ModificationInstruction.ModEtherInstruction) {
- return true;
- }
+ return l2i instanceof L2ModificationInstruction.ModVlanIdInstruction ||
+ l2i instanceof L2ModificationInstruction.ModEtherInstruction;
case OUTPUT:
return true;
default:
@@ -117,6 +115,7 @@
isPresentModEthDst = true;
}
}
+ break;
case OUTPUT:
isPresentOutpuPort = true;
default:
diff --git a/drivers/corsa/src/main/java/org/onosproject/drivers/corsa/CorsaPipelineV39.java b/drivers/corsa/src/main/java/org/onosproject/drivers/corsa/CorsaPipelineV39.java
index bb2cd4d..9a684f5 100644
--- a/drivers/corsa/src/main/java/org/onosproject/drivers/corsa/CorsaPipelineV39.java
+++ b/drivers/corsa/src/main/java/org/onosproject/drivers/corsa/CorsaPipelineV39.java
@@ -234,12 +234,10 @@
switch (i.type()) {
case L2MODIFICATION:
L2ModificationInstruction l2i = (L2ModificationInstruction) i;
- if (l2i.subtype() == VLAN_ID ||
+ return l2i.subtype() == VLAN_ID ||
l2i.subtype() == VLAN_POP ||
l2i.subtype() == ETH_DST ||
- l2i.subtype() == ETH_SRC) {
- return true;
- }
+ l2i.subtype() == ETH_SRC;
case OUTPUT:
return true;
default:
@@ -270,6 +268,7 @@
isPresentModEthDst = true;
}
}
+ break;
case OUTPUT:
isPresentOutpuPort = true;
default:
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraResubmitTable.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraResubmitTable.java
index bb6347e..3e1dd05 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraResubmitTable.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraResubmitTable.java
@@ -65,7 +65,6 @@
*/
public NiciraResubmitTable(PortNumber inPort, short table) {
checkNotNull(inPort);
- checkNotNull(table);
this.inPort = inPort;
this.table = table;
}
@@ -76,7 +75,6 @@
* @param table table
*/
public NiciraResubmitTable(short table) {
- checkNotNull(table);
this.inPort = DEFAULT_IN_PORT;
this.table = table;
}
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/Ofdpa3SetMplsType.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/Ofdpa3SetMplsType.java
index ca0f03d..a160b3a 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/extensions/Ofdpa3SetMplsType.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/Ofdpa3SetMplsType.java
@@ -49,7 +49,6 @@
* @param mplsType MPLS type in short
*/
public Ofdpa3SetMplsType(short mplsType) {
- checkNotNull(mplsType);
this.mplsType = mplsType;
}
diff --git a/drivers/default/src/main/java/org/onosproject/driver/handshaker/Ofdpa3SwitchHandshaker.java b/drivers/default/src/main/java/org/onosproject/driver/handshaker/Ofdpa3SwitchHandshaker.java
new file mode 100644
index 0000000..40e54c1
--- /dev/null
+++ b/drivers/default/src/main/java/org/onosproject/driver/handshaker/Ofdpa3SwitchHandshaker.java
@@ -0,0 +1,52 @@
+/*
+ * 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.driver.handshaker;
+
+import org.projectfloodlight.openflow.protocol.OFCapabilities;
+import org.projectfloodlight.openflow.protocol.OFFeaturesReply;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Driver for ofdpa 3 switches
+ * TODO : Remove this and also remove the specific switch handler from
+ * onos-drivers.xml once bug with GROUP_STATS is fixed.
+ */
+public class Ofdpa3SwitchHandshaker extends DefaultSwitchHandshaker {
+
+ @Override
+ public void setFeaturesReply(OFFeaturesReply featuresReply) {
+
+ OFFeaturesReply.Builder builder = featuresReply.createBuilder();
+
+ // do not try to set PORTS or ACTIONS,
+ // they are not supported for this openflow version
+ builder.setAuxiliaryId(featuresReply.getAuxiliaryId());
+ builder.setDatapathId(featuresReply.getDatapathId());
+ builder.setNBuffers(featuresReply.getNBuffers());
+ builder.setReserved(featuresReply.getReserved());
+ builder.setXid(featuresReply.getXid());
+
+ Set<OFCapabilities> capabilities = new HashSet<>(featuresReply.getCapabilities());
+ capabilities.add(OFCapabilities.GROUP_STATS);
+ builder.setCapabilities(capabilities);
+
+ super.setFeaturesReply(builder.build());
+ }
+
+}
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/PicaPipeline.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/PicaPipeline.java
index 6c73693..ef79ee3 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/PicaPipeline.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/PicaPipeline.java
@@ -381,7 +381,8 @@
return;
}
- EthCriterion e = null; VlanIdCriterion v = null;
+ EthCriterion e = null;
+ VlanIdCriterion v = null;
Collection<IPCriterion> ips = new ArrayList<IPCriterion>();
// convert filtering conditions for switch-intfs into flowrules
FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
@@ -399,6 +400,12 @@
}
}
+ if (v == null || e == null) {
+ log.warn("Pica Pipeline ETH_DST and/or VLAN_ID not specified");
+ fail(filt, ObjectiveError.BADPARAMS);
+ return;
+ }
+
// cache for later use
Filter filter = new Filter(p, e, v, ips);
filters.add(filter);
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/SoftRouterPipeline.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/SoftRouterPipeline.java
index 03a77ba..9ca9420 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/SoftRouterPipeline.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/SoftRouterPipeline.java
@@ -270,6 +270,12 @@
}
+ if (v == null || e == null) {
+ log.warn("Soft Router Pipeline ETH_DST and/or VLAN_ID not specified");
+ fail(filt, ObjectiveError.BADPARAMS);
+ return;
+ }
+
log.debug("Modifying Port/VLAN/MAC filtering rules in filter table: {}/{}/{}",
p.port(), v.vlanId(), e.mac());
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/CpqdOfdpa2Pipeline.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/CpqdOfdpa2Pipeline.java
index c5698a4..d8de983 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/CpqdOfdpa2Pipeline.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/CpqdOfdpa2Pipeline.java
@@ -336,14 +336,16 @@
// ofdpa cannot match on ALL portnumber, so we need to use separate
// rules for each port.
List<PortNumber> portnums = new ArrayList<PortNumber>();
- if (portCriterion.port() == PortNumber.ALL) {
- for (Port port : deviceService.getPorts(deviceId)) {
- if (port.number().toLong() > 0 && port.number().toLong() < OFPP_MAX) {
- portnums.add(port.number());
+ if (portCriterion != null) {
+ if (portCriterion.port() == PortNumber.ALL) {
+ for (Port port : deviceService.getPorts(deviceId)) {
+ if (port.number().toLong() > 0 && port.number().toLong() < OFPP_MAX) {
+ portnums.add(port.number());
+ }
}
+ } else {
+ portnums.add(portCriterion.port());
}
- } else {
- portnums.add(portCriterion.port());
}
List<FlowRule> rules = new ArrayList<FlowRule>();
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/CpqdOfdpa2VlanPipeline.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/CpqdOfdpa2VlanPipeline.java
index 701b76e..0279cb1 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/CpqdOfdpa2VlanPipeline.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/CpqdOfdpa2VlanPipeline.java
@@ -108,14 +108,16 @@
// ofdpa cannot match on ALL portnumber, so we need to use separate
// rules for each port.
List<PortNumber> portnums = new ArrayList<PortNumber>();
- if (portCriterion.port() == PortNumber.ALL) {
- for (Port port : deviceService.getPorts(deviceId)) {
- if (port.number().toLong() > 0 && port.number().toLong() < OFPP_MAX) {
- portnums.add(port.number());
+ if (portCriterion != null) {
+ if (portCriterion.port() == PortNumber.ALL) {
+ for (Port port : deviceService.getPorts(deviceId)) {
+ if (port.number().toLong() > 0 && port.number().toLong() < OFPP_MAX) {
+ portnums.add(port.number());
+ }
}
+ } else {
+ portnums.add(portCriterion.port());
}
- } else {
- portnums.add(portCriterion.port());
}
List<FlowRule> rules = new ArrayList<FlowRule>();
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2GroupHandler.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2GroupHandler.java
index bec569e..38cc72b 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2GroupHandler.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2GroupHandler.java
@@ -1440,6 +1440,7 @@
// get a fresh copy of what the store holds
NextGroup next = flowObjectiveStore.getNextGroup(nextObjective.id());
List<Deque<GroupKey>> allActiveKeys = appKryo.deserialize(next.data());
+ allActiveKeys = Lists.newArrayList(allActiveKeys);
// Note that since we got a new object, and ArrayDeque does not implement
// Object.equals(), we have to check the deque elems one by one
allActiveKeys
@@ -1814,6 +1815,7 @@
}
if (nextGrp.nextObjective().op() == Operation.ADD_TO_EXISTING) {
List<Deque<GroupKey>> allActiveKeys = appKryo.deserialize(next.data());
+ allActiveKeys = Lists.newArrayList(allActiveKeys);
// If active keys shows only the top-level group without a chain of groups,
// then it represents an empty group. Update by replacing empty chain.
if (allActiveKeys.size() == 1 && allActiveKeys.get(0).size() == 1) {
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2Pipeline.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2Pipeline.java
index a1cd29a..383ba4d 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2Pipeline.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/Ofdpa2Pipeline.java
@@ -1044,7 +1044,7 @@
for (Instruction ins : fwd.treatment().allInstructions()) {
if (ins instanceof OutputInstruction) {
OutputInstruction o = (OutputInstruction) ins;
- if (o != null && PortNumber.CONTROLLER.equals(o.port())) {
+ if (PortNumber.CONTROLLER.equals(o.port())) {
ttBuilder.add(o);
} else {
log.warn("Only allowed treatments in versatile forwarding "
diff --git a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/OfdpaGroupHandlerUtility.java b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/OfdpaGroupHandlerUtility.java
index f9cf3d0..df03656 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/OfdpaGroupHandlerUtility.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/pipeline/ofdpa/OfdpaGroupHandlerUtility.java
@@ -534,22 +534,30 @@
@Override
public void run() {
- if (groupHandler.pendingGroups().size() != 0) {
- log.debug("pending groups being checked: {}", groupHandler.pendingGroups().asMap().keySet());
- }
- if (groupHandler.pendingAddNextObjectives().size() != 0) {
- log.debug("pending add-next-obj being checked: {}",
- groupHandler.pendingAddNextObjectives().asMap().keySet());
- }
- Set<GroupKey> keys = groupHandler.pendingGroups().asMap().keySet().stream()
- .filter(key -> groupHandler.groupService.getGroup(groupHandler.deviceId, key) != null)
- .collect(Collectors.toSet());
- Set<GroupKey> otherkeys = groupHandler.pendingAddNextObjectives().asMap().keySet().stream()
- .filter(otherkey -> groupHandler.groupService.getGroup(groupHandler.deviceId, otherkey) != null)
- .collect(Collectors.toSet());
- keys.addAll(otherkeys);
+ // GroupChecker execution needs to be protected
+ // from unhandled exceptions
+ try {
+ if (groupHandler.pendingGroups().size() != 0) {
+ log.debug("pending groups being checked: {}", groupHandler.pendingGroups().asMap().keySet());
+ }
+ if (groupHandler.pendingAddNextObjectives().size() != 0) {
+ log.debug("pending add-next-obj being checked: {}",
+ groupHandler.pendingAddNextObjectives().asMap().keySet());
+ }
+ Set<GroupKey> keys = groupHandler.pendingGroups().asMap().keySet().stream()
+ .filter(key -> groupHandler.groupService.getGroup(groupHandler.deviceId, key) != null)
+ .collect(Collectors.toSet());
+ Set<GroupKey> otherkeys = groupHandler.pendingAddNextObjectives().asMap().keySet().stream()
+ .filter(otherkey -> groupHandler.groupService.getGroup(groupHandler.deviceId, otherkey) != null)
+ .collect(Collectors.toSet());
+ keys.addAll(otherkeys);
- keys.forEach(key -> groupHandler.processPendingAddGroupsOrNextObjs(key, false));
+ keys.forEach(key -> groupHandler.processPendingAddGroupsOrNextObjs(key, false));
+ } catch (Exception exception) {
+ // Just log. It is safe for now.
+ log.warn("Uncaught exception is detected: {}", exception.getMessage());
+ log.debug("Uncaught exception is detected (full stack trace): ", exception);
+ }
}
}
}
diff --git a/drivers/default/src/main/resources/onos-drivers.xml b/drivers/default/src/main/resources/onos-drivers.xml
index dec58e5..180c852 100644
--- a/drivers/default/src/main/resources/onos-drivers.xml
+++ b/drivers/default/src/main/resources/onos-drivers.xml
@@ -76,6 +76,7 @@
<!-- Driver for OFDPA 3.0 EA*.
~ TODO: version number from switch is still 2.0. Update when 3.0 is GA.
+ ~ TODO: remove Ofdpa3SwitchHandshaker when bug for GroupStats is fixed.
-->
<driver name="ofdpa3" extends="ofdpa"
manufacturer="Broadcom Corp\." hwVersion="OF-DPA 2.0" swVersion="OF-DPA 2.0">
@@ -93,6 +94,8 @@
impl="org.onosproject.driver.extensions.Ofdpa3ExtensionTreatmentInterpreter" />
<behaviour api="org.onosproject.net.flow.ExtensionSelectorCodec"
impl="org.onosproject.driver.extensions.Ofdpa3ExtensionSelectorInterpreter" />
+ <behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver"
+ impl="org.onosproject.driver.handshaker.Ofdpa3SwitchHandshaker"/>
</driver>
<driver name="xpliant" extends="ofdpa3"
diff --git a/drivers/fujitsu/src/main/java/org/onosproject/drivers/fujitsu/FujitsuVoltControllerConfig.java b/drivers/fujitsu/src/main/java/org/onosproject/drivers/fujitsu/FujitsuVoltControllerConfig.java
index 9d5ba5c..b238b37 100644
--- a/drivers/fujitsu/src/main/java/org/onosproject/drivers/fujitsu/FujitsuVoltControllerConfig.java
+++ b/drivers/fujitsu/src/main/java/org/onosproject/drivers/fujitsu/FujitsuVoltControllerConfig.java
@@ -212,13 +212,13 @@
try {
editcfg = (XMLConfiguration) cfg;
} catch (ClassCastException e) {
- e.printStackTrace();
+ return null;
}
StringWriter stringWriter = new StringWriter();
try {
editcfg.save(stringWriter);
} catch (ConfigurationException e) {
- e.printStackTrace();
+ return null;
}
String s = stringWriter.toString();
String fromStr = buildStartTag(TARGET, false) + target +
diff --git a/drivers/gnmi/BUCK b/drivers/gnmi/BUCK
new file mode 100644
index 0000000..0fe379e
--- /dev/null
+++ b/drivers/gnmi/BUCK
@@ -0,0 +1,38 @@
+PROTOBUF_VER = '3.2.0'
+GRPC_VER = '1.3.1'
+
+COMPILE_DEPS = [
+ '//lib:CORE_DEPS',
+ '//lib:KRYO',
+ '//protocols/grpc/api:onos-protocols-grpc-api',
+ '//protocols/grpc/proto:onos-protocols-grpc-proto',
+ '//incubator/grpc-dependencies:grpc-core-repkg-' + GRPC_VER,
+ '//lib:grpc-netty-' + GRPC_VER,
+ '//lib:protobuf-java-' + PROTOBUF_VER,
+ '//lib:grpc-stub-' + GRPC_VER,
+ '//core/store/serializers:onos-core-serializers',
+ '//protocols/gnmi/stub:onos-protocols-gnmi-stub',
+]
+
+BUNDLES = [
+ ':onos-drivers-gnmi',
+]
+
+osgi_jar (
+ deps = COMPILE_DEPS,
+)
+
+onos_app (
+ app_name = 'org.onosproject.drivers.gnmi',
+ title = 'gNMI Drivers',
+ category = 'Drivers',
+ url = 'http://onosproject.org',
+ description = 'Adds support for devices using gNMI protocol based on ' +
+ ' openconfig models: http://openconfig.net/ .',
+ included_bundles = BUNDLES,
+ required_apps = [
+ 'org.onosproject.generaldeviceprovider',
+ 'org.onosproject.protocols.grpc',
+ 'org.onosproject.protocols.gnmi'
+ ],
+)
\ No newline at end of file
diff --git a/drivers/gnmi/features.xml b/drivers/gnmi/features.xml
new file mode 100644
index 0000000..448f07a
--- /dev/null
+++ b/drivers/gnmi/features.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+ ~ 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.
+ -->
+<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="${project.artifactId}-${project.version}">
+ <feature name="${project.artifactId}" version="${project.version}"
+ description="${project.description}">
+ <feature>onos-api</feature>
+ <bundle>mvn:${project.groupId}/${project.artifactId}/${project.version}</bundle>
+
+ </feature>
+</features>
diff --git a/drivers/gnmi/pom.xml b/drivers/gnmi/pom.xml
new file mode 100644
index 0000000..ae046d6
--- /dev/null
+++ b/drivers/gnmi/pom.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2017-present Open Networking Foundation
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>onos-drivers-general</artifactId>
+ <groupId>org.onosproject</groupId>
+ <version>1.11.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>onos-drivers-gnmi</artifactId>
+ <packaging>bundle</packaging>
+
+ <description>gNMI device drivers</description>
+ <dependencies>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-grpc-protocol-api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>io.grpc</groupId>
+ <artifactId>grpc-netty</artifactId>
+ <version>1.3.1</version>
+ </dependency>
+
+ <!-- protocols/gnmi/api missing -->
+
+ </dependencies>
+
+ <properties>
+ <onos.app.name>org.onosproject.drivers.gnmi</onos.app.name>
+ <onos.app.origin>ON.Lab</onos.app.origin>
+ <onos.app.title>gNMI Device Drivers</onos.app.title>
+ <onos.app.category>Drivers</onos.app.category>
+ <onos.app.url>http://onosproject.org</onos.app.url>
+ <onos.app.requires>
+ org.onosproject.generaldeviceprovider
+ </onos.app.requires>
+ </properties>
+
+</project>
\ No newline at end of file
diff --git a/drivers/gnmi/src/main/java/org/onosproject/drivers/gnmi/GnmiDeviceDescriptionDiscovery.java b/drivers/gnmi/src/main/java/org/onosproject/drivers/gnmi/GnmiDeviceDescriptionDiscovery.java
new file mode 100644
index 0000000..04c9f01
--- /dev/null
+++ b/drivers/gnmi/src/main/java/org/onosproject/drivers/gnmi/GnmiDeviceDescriptionDiscovery.java
@@ -0,0 +1,305 @@
+/*
+ * 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.gnmi;
+
+import com.google.common.collect.ImmutableList;
+import gnmi.gNMIGrpc;
+import io.grpc.ManagedChannel;
+import io.grpc.ManagedChannelBuilder;
+import io.grpc.Status;
+import io.grpc.StatusRuntimeException;
+import io.grpc.internal.DnsNameResolverProvider;
+import io.grpc.netty.NettyChannelBuilder;
+import io.grpc.stub.StreamObserver;
+import org.onosproject.grpc.api.GrpcChannelId;
+import org.onosproject.grpc.api.GrpcController;
+import org.onosproject.net.DefaultAnnotations;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.device.DefaultPortDescription;
+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 org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import static gnmi.Gnmi.Path;
+import static gnmi.Gnmi.PathElem;
+import static gnmi.Gnmi.SubscribeRequest;
+import static gnmi.Gnmi.SubscribeResponse;
+import static gnmi.Gnmi.Subscription;
+import static gnmi.Gnmi.SubscriptionList;
+import static gnmi.Gnmi.Update;
+
+/**
+ * Class that discovers the device description and ports of a device that
+ * supports the gNMI protocol and Openconfig models.
+ */
+public class GnmiDeviceDescriptionDiscovery
+ extends AbstractHandlerBehaviour
+ implements DeviceDescriptionDiscovery {
+
+ private static final int REQUEST_TIMEOUT_SECONDS = 5;
+
+ private static final Logger log = LoggerFactory
+ .getLogger(GnmiDeviceDescriptionDiscovery.class);
+
+ private static final String GNMI_SERVER_ADDR_KEY = "gnmi_ip";
+ private static final String GNMI_SERVER_PORT_KEY = "gnmi_port";
+
+ @Override
+ public DeviceDescription discoverDeviceDetails() {
+ return null;
+ }
+
+ @Override
+ public List<PortDescription> discoverPortDetails() {
+ log.info("Discovering port details on device {}", handler().data().deviceId());
+
+ // Get the channel
+ ManagedChannel channel = getChannel();
+
+ if (channel == null) {
+ return ImmutableList.of();
+ }
+
+ // Build the subscribe request
+ SubscribeRequest request = subscribeRequest();
+
+ // New stub
+ gNMIGrpc.gNMIStub gnmiStub = gNMIGrpc.newStub(channel);
+
+ final CompletableFuture<List<PortDescription>>
+ reply = new CompletableFuture<>();
+
+ // Subscribe to the replies
+ StreamObserver<SubscribeRequest> subscribeRequest = gnmiStub
+ .subscribe(new SubscribeResponseObserver(reply));
+ log.debug("Interfaces request {}", request);
+
+ List<PortDescription> ports;
+ try {
+ // Issue the request
+ subscribeRequest.onNext(request);
+ ports = reply.get(REQUEST_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+ } catch (InterruptedException | ExecutionException | TimeoutException
+ | StatusRuntimeException e) {
+ log.warn("Unable to discover ports from {}: {}",
+ data().deviceId(), e.getMessage());
+ log.debug("{}", e);
+ return ImmutableList.of();
+ } finally {
+ subscribeRequest.onCompleted();
+ }
+
+ return ports;
+ }
+
+ /**
+ * Obtains the ManagedChannel to be used for the communication.
+ *
+ * @return the managed channel
+ */
+ private ManagedChannel getChannel() {
+
+ DeviceId deviceId = handler().data().deviceId();
+ String serverAddr = this.data().value(GNMI_SERVER_ADDR_KEY);
+ String serverPortString = this.data().value(GNMI_SERVER_PORT_KEY);
+
+ GrpcController controller = handler().get(GrpcController.class);
+ ManagedChannel channel = null;
+
+ //FIXME can be optimized
+ //getting a channel if exists.
+ ManagedChannel managedChannel = controller
+ .getChannels(handler().data().deviceId()).stream().filter(c -> {
+ String[] authority = c.authority().split(":");
+ String host = authority[0];
+ String port = authority[1];
+ return host.equals(serverAddr) && port.equals(serverPortString);
+ }).findAny().orElse(null);
+
+ if (managedChannel != null) {
+ log.debug("Reusing Channel");
+ channel = managedChannel;
+ } else {
+ log.debug("Creating Channel");
+ GrpcChannelId newChannelId = GrpcChannelId.of(deviceId, "gnmi");
+
+ ManagedChannelBuilder channelBuilder = NettyChannelBuilder
+ .forAddress(serverAddr, Integer.valueOf(serverPortString))
+ .usePlaintext(true)
+ .nameResolverFactory(new DnsNameResolverProvider());
+
+ try {
+ channel = controller.connectChannel(newChannelId, channelBuilder);
+ } catch (IOException e) {
+ log.warn("Unable to connect to gRPC server of {}: {}",
+ deviceId, e.getMessage());
+ }
+ }
+ return channel;
+ }
+
+ /**
+ * Creates the subscribe request for the interfaces.
+ *
+ * @return subscribe request
+ */
+ private SubscribeRequest subscribeRequest() {
+ Path path = Path.newBuilder()
+ .addElem(PathElem.newBuilder().setName("interfaces").build())
+ .addElem(PathElem.newBuilder().setName("interface").build())
+ .addElem(PathElem.newBuilder().setName("...").build())
+ .build();
+ Subscription subscription = Subscription.newBuilder().setPath(path).build();
+ SubscriptionList list = SubscriptionList.newBuilder().setMode(SubscriptionList.Mode.ONCE)
+ .addSubscription(subscription).build();
+ return SubscribeRequest.newBuilder().setSubscribe(list).build();
+ }
+
+ /**
+ * Handles messages received from the device on the stream channel.
+ */
+ private final class SubscribeResponseObserver
+ implements StreamObserver<SubscribeResponse> {
+
+ private final CompletableFuture<List<PortDescription>> reply;
+
+ private SubscribeResponseObserver(CompletableFuture<List<PortDescription>> reply) {
+ this.reply = reply;
+ }
+
+ @Override
+ public void onNext(SubscribeResponse message) {
+ Map<String, DefaultPortDescription.Builder> ports = new HashMap<>();
+ Map<String, DefaultAnnotations.Builder> portsAnnotations = new HashMap<>();
+ log.debug("Response {} ", message.getUpdate().toString());
+ message.getUpdate().getUpdateList().forEach(update -> {
+ parseUpdate(ports, portsAnnotations, update);
+ });
+
+ List<PortDescription> portDescriptionList = new ArrayList<>();
+ ports.forEach((k, v) -> {
+// v.portSpeed(1000L);
+ v.type(Port.Type.COPPER);
+ v.annotations(portsAnnotations.get(k).set("name", k).build());
+ portDescriptionList.add(v.build());
+ });
+
+ reply.complete(portDescriptionList);
+ }
+
+
+ @Override
+ public void onError(Throwable throwable) {
+ log.warn("Error on stream channel for {}: {}",
+ data().deviceId(), Status.fromThrowable(throwable));
+ log.debug("{}", throwable);
+ }
+
+ @Override
+ public void onCompleted() {
+ log.debug("SubscribeResponseObserver completed");
+ }
+ }
+
+ /**
+ * Parses the update received from the device.
+ *
+ * @param ports the ports description to build
+ * @param portsAnnotations the ports annotations list to populate
+ * @param update the update received
+ */
+ private void parseUpdate(Map<String, DefaultPortDescription.Builder> ports,
+ Map<String, DefaultAnnotations.Builder> portsAnnotations,
+ Update update) {
+
+ //FIXME crude parsing, can be done via object (de)serialization
+ if (update.getPath().getElemList().size() > 3) {
+ String name = update.getPath().getElem(3).getName();
+ String portId = update.getPath().getElem(1).getKeyMap().get("name");
+ if (!ports.containsKey(portId)) {
+ int number = Character.getNumericValue(portId.charAt(portId.length() - 1));
+ PortNumber portNumber = PortNumber.portNumber(number, portId);
+ ports.put(portId, DefaultPortDescription.builder()
+ .withPortNumer(portNumber));
+ }
+ if (name.equals("enabled")) {
+ DefaultPortDescription.Builder builder = ports.get(portId);
+ builder = builder.isEnabled(update.getVal().getBoolVal());
+ ports.put(portId, builder);
+ } else if (name.equals("state")) {
+ String speedName = update.getPath().getElem(4).getName();
+ if (speedName.equals("negotiated-port-speed")) {
+ DefaultPortDescription.Builder builder = ports.get(portId);
+ long speed = parsePortSpeed(update.getVal().getStringVal());
+ builder = builder.portSpeed(speed);
+ ports.put(portId, builder);
+ }
+ } else if (!name.equals("ifindex")) {
+ if (!portsAnnotations.containsKey(portId)) {
+ portsAnnotations.put(portId, DefaultAnnotations.builder()
+ .set(name, update.getVal().toByteString()
+ .toString(Charset.defaultCharset()).trim()));
+ } else {
+ DefaultAnnotations.Builder builder = portsAnnotations.get(portId);
+ builder = builder.set(name, update.getVal().toByteString().
+ toString(Charset.defaultCharset()).trim());
+ portsAnnotations.put(portId, builder);
+ }
+ }
+ }
+ }
+
+ private long parsePortSpeed(String speed) {
+ log.debug("Speed from config {}", speed);
+ switch (speed) {
+ case "SPEED_10MB":
+ return 10;
+ case "SPEED_100MB":
+ return 10;
+ case "SPEED_1GB":
+ return 1000;
+ case "SPEED_10GB":
+ return 10000;
+ case "SPEED_25GB":
+ return 25000;
+ case "SPEED_40GB":
+ return 40000;
+ case "SPEED_50GB":
+ return 50000;
+ case "SPEED_100GB":
+ return 100000;
+ default:
+ return 1000;
+ }
+ }
+}
diff --git a/drivers/gnmi/src/main/java/org/onosproject/drivers/gnmi/GnmiDriversLoader.java b/drivers/gnmi/src/main/java/org/onosproject/drivers/gnmi/GnmiDriversLoader.java
new file mode 100644
index 0000000..689a53b
--- /dev/null
+++ b/drivers/gnmi/src/main/java/org/onosproject/drivers/gnmi/GnmiDriversLoader.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.drivers.gnmi;
+
+import org.apache.felix.scr.annotations.Component;
+import org.onosproject.net.driver.AbstractDriverLoader;
+
+/**
+ * Loader for gNMI device drivers.
+ */
+@Component(immediate = true)
+public class GnmiDriversLoader extends AbstractDriverLoader {
+
+ public GnmiDriversLoader() {
+ super("/gnmi-drivers.xml");
+ }
+
+ @Override
+ public void activate() {
+ super.activate();
+ }
+}
diff --git a/apps/restconf/utils/src/main/java/org/onosproject/restconf/utils/exceptions/package-info.java b/drivers/gnmi/src/main/java/org/onosproject/drivers/gnmi/package-info.java
similarity index 87%
rename from apps/restconf/utils/src/main/java/org/onosproject/restconf/utils/exceptions/package-info.java
rename to drivers/gnmi/src/main/java/org/onosproject/drivers/gnmi/package-info.java
index a0fe88e..832ad5a 100644
--- a/apps/restconf/utils/src/main/java/org/onosproject/restconf/utils/exceptions/package-info.java
+++ b/drivers/gnmi/src/main/java/org/onosproject/drivers/gnmi/package-info.java
@@ -15,6 +15,6 @@
*/
/**
- * Parse utils custom exceptions.
+ * Package for gnmi device drivers.
*/
-package org.onosproject.restconf.utils.exceptions;
\ No newline at end of file
+package org.onosproject.drivers.gnmi;
\ No newline at end of file
diff --git a/drivers/gnmi/src/main/resources/gnmi-drivers.xml b/drivers/gnmi/src/main/resources/gnmi-drivers.xml
new file mode 100644
index 0000000..3744781
--- /dev/null
+++ b/drivers/gnmi/src/main/resources/gnmi-drivers.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2017-present Open Networking Foundation
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<drivers>
+ <driver name="gnmi" manufacturer="gnmi" hwVersion="master" swVersion="master">
+ <behaviour api="org.onosproject.net.device.DeviceDescriptionDiscovery"
+ impl="org.onosproject.drivers.gnmi.GnmiDeviceDescriptionDiscovery"/>
+ </driver>
+</drivers>
+
diff --git a/drivers/hp/src/main/java/org/onosproject/drivers/hp/HPPipelineV1.java b/drivers/hp/src/main/java/org/onosproject/drivers/hp/HPPipelineV1.java
index 48e6122..27a585b 100644
--- a/drivers/hp/src/main/java/org/onosproject/drivers/hp/HPPipelineV1.java
+++ b/drivers/hp/src/main/java/org/onosproject/drivers/hp/HPPipelineV1.java
@@ -261,7 +261,7 @@
*/
if (instruction.type() == Instruction.Type.L2MODIFICATION) {
- if (!this.hardwareInstructionsL3mod.contains(((L2ModificationInstruction) instruction).subtype())) {
+ if (!this.hardwareInstructionsL2mod.contains(((L2ModificationInstruction) instruction).subtype())) {
log.warn("HP V1 Driver - L2MODIFICATION.subtype {} only supported in SOFTWARE",
((L2ModificationInstruction) instruction).subtype());
diff --git a/drivers/hp/src/main/java/org/onosproject/drivers/hp/HPPipelineV3500.java b/drivers/hp/src/main/java/org/onosproject/drivers/hp/HPPipelineV3500.java
index a488439..06e01c1 100644
--- a/drivers/hp/src/main/java/org/onosproject/drivers/hp/HPPipelineV3500.java
+++ b/drivers/hp/src/main/java/org/onosproject/drivers/hp/HPPipelineV3500.java
@@ -252,7 +252,7 @@
* */
if (instruction.type() == Instruction.Type.L2MODIFICATION) {
- if (!this.hardwareInstructionsL3mod.contains(((L2ModificationInstruction) instruction).subtype())) {
+ if (!this.hardwareInstructionsL2mod.contains(((L2ModificationInstruction) instruction).subtype())) {
log.warn("HP V3500 Driver - L2MODIFICATION.subtype {} only supported in SOFTWARE",
((L2ModificationInstruction) instruction).subtype());
diff --git a/drivers/microsemi/BUCK b/drivers/microsemi/BUCK
index 80ef2c8..210d76cc 100644
--- a/drivers/microsemi/BUCK
+++ b/drivers/microsemi/BUCK
@@ -15,7 +15,8 @@
'//core/api:onos-api-tests',
'//drivers/netconf:onos-drivers-netconf-tests',
'//utils/osgi:onlab-osgi-tests',
- '//incubator/net:onos-incubator-net'
+ '//incubator/net:onos-incubator-net',
+ '//incubator/net:onos-incubator-net-tests'
]
APPS = [
diff --git a/drivers/microsemi/pom.xml b/drivers/microsemi/pom.xml
index ac299d4..4746d50 100644
--- a/drivers/microsemi/pom.xml
+++ b/drivers/microsemi/pom.xml
@@ -133,6 +133,21 @@
<dependency>
<groupId>org.onosproject</groupId>
+ <artifactId>onos-incubator-net</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-incubator-net</artifactId>
+ <version>${project.version}</version>
+ <classifier>tests</classifier>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onosproject</groupId>
<artifactId>onos-api</artifactId>
<scope>test</scope>
<classifier>tests</classifier>
@@ -140,25 +155,15 @@
<dependency>
<groupId>org.onosproject</groupId>
- <artifactId>onos-incubator-net</artifactId>
+ <artifactId>onos-core-common</artifactId>
+ <classifier>tests</classifier>
<scope>test</scope>
</dependency>
+
</dependencies>
<build>
- <pluginManagement>
- <plugins>
-
- <plugin>
- <groupId>org.apache.karaf.tooling</groupId>
- <artifactId>karaf-maven-plugin</artifactId>
- <version>3.0.5</version>
- <extensions>true</extensions>
- </plugin>
-
- </plugins>
- </pluginManagement>
<plugins>
<plugin>
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
index 143ee79..a5ff236 100755
--- a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/EA1000CfmMepProgrammable.java
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/EA1000CfmMepProgrammable.java
@@ -16,12 +16,17 @@
package org.onosproject.drivers.microsemi;
import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onosproject.drivers.microsemi.yang.utils.MaNameUtil.getApiMaIdFromYangMaName;
+import static org.onosproject.drivers.microsemi.yang.utils.MdNameUtil.getApiMdIdFromYangMdName;
+import static org.onosproject.drivers.microsemi.yang.utils.MdNameUtil.getYangMdNameFromApiMdId;
import static org.slf4j.LoggerFactory.getLogger;
import java.time.Duration;
+import java.util.ArrayList;
import java.util.Collection;
+import java.util.NoSuchElementException;
+import java.util.Optional;
-import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
import org.onlab.util.HexString;
@@ -47,14 +52,12 @@
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.identifier.MepKeyId;
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.net.DeviceId;
import org.onosproject.net.PortNumber;
import org.onosproject.net.driver.AbstractHandlerBehaviour;
@@ -62,7 +65,6 @@
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;
@@ -83,11 +85,6 @@
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;
@@ -97,8 +94,6 @@
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;
@@ -128,46 +123,34 @@
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();
+ NetconfSession session = checkNotNull(controller.getDevicesMap()
+ .get(handler().data().deviceId()).getSession());
MseaCfmNetconfService mseaCfmService =
checkNotNull(handler().get(MseaCfmNetconfService.class));
+ CfmMepService cfmMepService =
+ checkNotNull(handler().get(CfmMepService.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();
+ MseaCfmOpParam mseaCfmOpParam = getMaYangObject(cfmMdService, mdName, maName);
- 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");
- }
+ mseaCfmOpParam.mefCfm().maintenanceDomain().get(0)
+ .maintenanceAssociation().get(0).addToMaintenanceAssociationEndPoint(yangMep);
+ //Add this mepId to the list of remoteMeps on the device
+ mseaCfmOpParam.mefCfm().maintenanceDomain().get(0)
+ .maintenanceAssociation().get(0).addToRemoteMeps(MepIdType.of(mep.mepId().value()));
- 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);
+ //Add all of the existing meps on this MD/MA to the remote meps list
+ cfmMepService.getAllMeps(mdName, maName).forEach(m -> {
+ mseaCfmOpParam.mefCfm().maintenanceDomain().get(0)
+ .maintenanceAssociation().get(0).addToRemoteMeps(MepIdType.of(m.mepId().value()));
+ });
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 {}",
@@ -177,11 +160,6 @@
}
@Override
- public Collection<MepEntry> 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));
@@ -189,31 +167,20 @@
throw new CfmConfigException("Device is not ready - connecting or "
+ "disconnected for MEP " + mdName + "/" + maName + "/" + mepId);
}
- NetconfSession session = controller.getDevicesMap().get(handler().data().deviceId()).getSession();
+ NetconfSession session = checkNotNull(controller.getDevicesMap()
+ .get(handler().data().deviceId()).getSession());
MseaCfmNetconfService mseaCfmService = checkNotNull(handler().get(MseaCfmNetconfService.class));
try {
MseaCfm mseacfm =
mseaCfmService.getMepFull(mdName, maName, mepId, session);
- if (mseacfm != null && mseacfm.mefCfm() != null &&
- mseacfm.mefCfm().maintenanceDomain() != null) {
- 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);
- }
- }
- }
+ Collection<MepEntry> mepEntries = getMepEntriesFromYangResponse(mseacfm);
+ if (mepEntries == null || mepEntries.size() != 1) {
+ log.warn("Mep " + mepId + " not found on device " + handler().data().deviceId());
+ return null;
+ } else {
+ return mepEntries.stream().findFirst().get();
}
- 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());
@@ -221,12 +188,37 @@
}
}
+ private Collection<MepEntry> getMepEntriesFromYangResponse(MseaCfm mseacfm)
+ throws CfmConfigException {
+
+ Collection<MepEntry> mepEntries = new ArrayList<>();
+ if (mseacfm == null || mseacfm.mefCfm() == null || mseacfm.mefCfm().maintenanceDomain() == null) {
+ return mepEntries;
+ }
+
+ 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()) {
+ mepEntries.add(buildApiMepEntryFromYangMep(
+ replyMep, handler().data().deviceId(), replyMd, replyMa));
+ }
+ }
+ }
+ return mepEntries;
+ }
+
@Override
- public boolean deleteMep(MdId mdName, MaIdShort maName, MepId mepId) throws CfmConfigException {
+ public boolean deleteMep(MdId mdName, MaIdShort maName, MepId mepId,
+ Optional<MaintenanceDomain> oldMd) throws CfmConfigException {
NetconfController controller = checkNotNull(handler().get(NetconfController.class));
- NetconfSession session = controller.getDevicesMap().get(handler().data().deviceId()).getSession();
+ NetconfSession session = checkNotNull(controller.getDevicesMap()
+ .get(handler().data().deviceId()).getSession());
MseaCfmNetconfService mseaCfmService = checkNotNull(handler().get(MseaCfmNetconfService.class));
+ CfmMdService mdService = checkNotNull(handler().get(CfmMdService.class));
MaintenanceAssociationEndPoint mep =
new DefaultMaintenanceAssociationEndPoint();
@@ -234,12 +226,34 @@
org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain
.MaintenanceAssociation yangMa = new DefaultMaintenanceAssociation();
- yangMa.maNameAndTypeCombo(MaNameUtil.getYangMaNameFromApiMaId(maName));
+ Short maNumericId = null;
+ try {
+ maNumericId =
+ mdService.getMaintenanceAssociation(mdName, maName).get().maNumericId();
+ yangMa.id(maNumericId);
+ } catch (NoSuchElementException | IllegalArgumentException e) {
+ //The MA and/or MD have probably been deleted
+ // try to get numeric id values from oldMd
+ log.debug("Could not get MD/MA details from MD service during deletion of MEP {}." +
+ "Continuing with values from event", new MepKeyId(mdName, maName, mepId));
+ yangMa.id(getMaNumericId(oldMd.get(), maName));
+ }
+
yangMa.addToMaintenanceAssociationEndPoint(mep);
org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.MaintenanceDomain yangMd =
new DefaultMaintenanceDomain();
- yangMd.mdNameAndTypeCombo(getYangMdNameFromApiMdId(mdName));
+ Short mdNumericId = null;
+ try {
+ mdNumericId = mdService.getMaintenanceDomain(mdName).get().mdNumericId();
+ yangMd.id(mdNumericId);
+ } catch (NoSuchElementException | IllegalArgumentException e) {
+ //The MD has probably been deleted
+ // try to get numeric id values from oldMd
+ log.debug("Could not get MD details from MD service during deletion of MEP {}." +
+ "Continuing with values from event", new MepKeyId(mdName, maName, mepId));
+ yangMd.id(oldMd.get().mdNumericId());
+ }
yangMd.addToMaintenanceAssociation(yangMa);
MefCfm mefCfm = new DefaultMefCfm();
@@ -254,14 +268,281 @@
"/" + mepId, handler().data().deviceId());
return true;
} catch (NetconfException e) {
- log.error("Unable to delete MEP {}/{}/{} on device {}",
- mdName, maName, mepId, handler().data().deviceId());
+ log.error("Unable to delete MEP {} ({}) on device {}",
+ mdName + "/" + maName + "/" + mepId,
+ mdNumericId + "/" + maNumericId, handler().data().deviceId(), e);
throw new CfmConfigException("Unable to delete MEP :" + e.getMessage());
}
}
@Override
+ public boolean createMdOnDevice(MdId mdId) throws CfmConfigException {
+ NetconfController controller =
+ checkNotNull(handler().get(NetconfController.class));
+ NetconfSession session = checkNotNull(controller.getDevicesMap()
+ .get(handler().data().deviceId()).getSession());
+
+ CfmMdService cfmMdService = checkNotNull(handler().get(CfmMdService.class));
+ MaintenanceDomain md = cfmMdService.getMaintenanceDomain(mdId).get();
+
+ org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm
+ .mefcfm.MaintenanceDomain yangMd = buildYangMdFromApiMd(md);
+
+ if (md.mdNumericId() <= 0 || md.mdNumericId() > NUMERIC_ID_MAX) {
+ throw new CfmConfigException("Numeric id of MD " + mdId + " must"
+ + " be between 1 and 64 inclusive for EA1000");
+ }
+
+ for (MaintenanceAssociation ma:md.maintenanceAssociationList()) {
+ if (ma.maNumericId() <= 0 || ma.maNumericId() > NUMERIC_ID_MAX) {
+ throw new CfmConfigException("Numeric id of MA " + mdId + " must"
+ + " be between 1 and 64 inclusive for EA1000");
+ }
+ org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain
+ .MaintenanceAssociation yangMa = buildYangMaFromApiMa(ma);
+ yangMd.addToMaintenanceAssociation(yangMa);
+ }
+
+ MefCfm mefCfm = new DefaultMefCfm();
+ mefCfm.addToMaintenanceDomain(yangMd);
+
+ MseaCfmOpParam mseaCfmOpParam = new MseaCfmOpParam();
+ mseaCfmOpParam.mefCfm(mefCfm);
+
+ MseaCfmNetconfService mseaCfmService =
+ checkNotNull(handler().get(MseaCfmNetconfService.class));
+
+ try {
+ boolean created = mseaCfmService.setMseaCfm(mseaCfmOpParam, session, DatastoreId.RUNNING);
+ log.info("Created MD {} on device {}", mdId.mdName(),
+ handler().data().deviceId());
+ return created;
+ } catch (NetconfException e) {
+ log.error("Unable to create MD {} on device {}",
+ mdId.mdName(), handler().data().deviceId());
+ throw new CfmConfigException("Unable to create MD :" + e.getMessage());
+ }
+ }
+
+ @Override
+ public boolean createMaOnDevice(MdId mdId, MaIdShort maId) throws CfmConfigException {
+ NetconfController controller =
+ checkNotNull(handler().get(NetconfController.class));
+ NetconfSession session = checkNotNull(controller.getDevicesMap()
+ .get(handler().data().deviceId()).getSession());
+
+ CfmMdService mdService = checkNotNull(handler().get(CfmMdService.class));
+ MseaCfmOpParam mseaCfmOpParam = getMaYangObject(mdService, mdId, maId);
+ MseaCfmNetconfService mseaCfmService =
+ checkNotNull(handler().get(MseaCfmNetconfService.class));
+
+ try {
+ boolean created = mseaCfmService.setMseaCfm(mseaCfmOpParam, session, DatastoreId.RUNNING);
+ log.info("Created MA {} on device {}", mdId.mdName() + "/" + maId.maName(),
+ handler().data().deviceId());
+ return created;
+ } catch (NetconfException e) {
+ log.error("Unable to create MA {} on device {}",
+ mdId.mdName() + "/" + maId.maName(), handler().data().deviceId());
+ throw new CfmConfigException("Unable to create MA :" + e.getMessage());
+ }
+ }
+
+ private static MseaCfmOpParam getMaYangObject(CfmMdService cfmMdService,
+ MdId mdName, MaIdShort maName) throws CfmConfigException {
+ MaintenanceDomain md = cfmMdService.getMaintenanceDomain(mdName).get();
+ MaintenanceAssociation ma = cfmMdService.getMaintenanceAssociation(mdName, maName).get();
+
+ org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain
+ .MaintenanceAssociation yangMa = buildYangMaFromApiMa(ma);
+
+ org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm
+ .mefcfm.MaintenanceDomain yangMd = buildYangMdFromApiMd(md);
+ yangMd.addToMaintenanceAssociation(yangMa);
+
+ 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");
+ }
+
+ MefCfm mefCfm = new DefaultMefCfm();
+ mefCfm.addToMaintenanceDomain(yangMd);
+
+ MseaCfmOpParam mseaCfmOpParam = new MseaCfmOpParam();
+ mseaCfmOpParam.mefCfm(mefCfm);
+
+ return mseaCfmOpParam;
+ }
+
+ @Override
+ public boolean deleteMdOnDevice(MdId mdId, Optional<MaintenanceDomain> oldMd)
+ throws CfmConfigException {
+ NetconfController controller =
+ checkNotNull(handler().get(NetconfController.class));
+ NetconfSession session = controller.getDevicesMap()
+ .get(handler().data().deviceId()).getSession();
+
+ //First check if this MD is known to ONOS if it is does it have MAs and
+ // do they have any Meps known to ONOS. If there are Meps throw an exception -
+ // the Meps should have been deleted first
+ //If there are none known to ONOS we do not check for Meps on the actual device
+ // - there might might be some orphaned ones down there - we want to delete these
+ //FIXME: When CfmMepService is extended to be persistent come back and enable check
+ CfmMdService mdService = checkNotNull(handler().get(CfmMdService.class));
+ MseaCfmNetconfService mseaCfmService =
+ checkNotNull(handler().get(MseaCfmNetconfService.class));
+
+ MdNameAndTypeCombo mdName = getYangMdNameFromApiMdId(mdId);
+ org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.MaintenanceDomain yangMd =
+ new DefaultMaintenanceDomain();
+ Short mdNumericId = null;
+ try {
+ mdNumericId = mdService.getMaintenanceDomain(mdId).get().mdNumericId();
+ yangMd.id(mdNumericId);
+ } catch (NoSuchElementException e) {
+ yangMd.id(oldMd.get().mdNumericId());
+ }
+
+ MefCfm mefCfm = new DefaultMefCfm();
+ mefCfm.addToMaintenanceDomain(yangMd);
+
+ MseaCfmOpParam mseaCfmOpParam = new MseaCfmOpParam();
+ mseaCfmOpParam.mefCfm(mefCfm);
+
+ try {
+ boolean deleted = mseaCfmService.deleteMseaMd(mseaCfmOpParam, session, DatastoreId.RUNNING);
+ log.info("Deleted MD {} on device {}", mdName,
+ handler().data().deviceId());
+ return deleted;
+ } catch (NetconfException e) {
+ log.error("Unable to delete MD {} ({}) on device {}",
+ mdName, mdNumericId, handler().data().deviceId());
+ throw new CfmConfigException("Unable to delete MD :" + e.getMessage());
+ }
+
+ }
+
+ @Override
+ public boolean deleteMaOnDevice(MdId mdId, MaIdShort maId, Optional<MaintenanceDomain> oldMd)
+ throws CfmConfigException {
+ NetconfController controller =
+ checkNotNull(handler().get(NetconfController.class));
+ NetconfSession session = controller.getDevicesMap()
+ .get(handler().data().deviceId()).getSession();
+
+ CfmMdService mdService = checkNotNull(handler().get(CfmMdService.class));
+
+ MseaCfmNetconfService mseaCfmService =
+ checkNotNull(handler().get(MseaCfmNetconfService.class));
+
+ org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain
+ .MaintenanceAssociation yangMa = new DefaultMaintenanceAssociation();
+ Short maNumericId = null;
+ try {
+ maNumericId =
+ mdService.getMaintenanceAssociation(mdId, maId).get().maNumericId();
+ yangMa.id(maNumericId);
+ } catch (NoSuchElementException e) {
+ yangMa.id(getMaNumericId(oldMd.get(), maId));
+ }
+
+ org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.MaintenanceDomain yangMd =
+ new DefaultMaintenanceDomain();
+ Short mdNumericId = null;
+ try {
+ mdNumericId = mdService.getMaintenanceDomain(mdId).get().mdNumericId();
+ yangMd.id(mdNumericId);
+ } catch (NoSuchElementException e) {
+ yangMd.id(oldMd.get().mdNumericId());
+ }
+ yangMd.addToMaintenanceAssociation(yangMa);
+
+ MefCfm mefCfm = new DefaultMefCfm();
+ mefCfm.addToMaintenanceDomain(yangMd);
+
+ MseaCfmOpParam mseaCfmOpParam = new MseaCfmOpParam();
+ mseaCfmOpParam.mefCfm(mefCfm);
+
+ try {
+ boolean deleted = mseaCfmService.deleteMseaMa(mseaCfmOpParam, session, DatastoreId.RUNNING);
+ log.info("Deleted MA {} ({})on device {}", mdId.mdName() + "/" + maId.maName(),
+ mdNumericId + "/" + maNumericId, handler().data().deviceId());
+ return deleted;
+ } catch (NetconfException e) {
+ log.error("Unable to delete MA {} ({}) on device {}",
+ mdId.mdName() + "/" + maId.maName(),
+ mdNumericId + "/" + maNumericId, handler().data().deviceId());
+ throw new CfmConfigException("Unable to delete MA :" + e.getMessage());
+ }
+ }
+
+ @Override
+ public boolean createMaRemoteMepOnDevice(MdId mdId, MaIdShort maId, MepId remoteMep) throws CfmConfigException {
+ return crDelMaRemoteMep(mdId, maId, remoteMep, true);
+ }
+
+ @Override
+ public boolean deleteMaRemoteMepOnDevice(MdId mdId, MaIdShort maId, MepId remoteMep) throws CfmConfigException {
+ return crDelMaRemoteMep(mdId, maId, remoteMep, false);
+ }
+
+ private boolean crDelMaRemoteMep(MdId mdId, MaIdShort maId, MepId remoteMep,
+ boolean isCreate) throws CfmConfigException {
+ NetconfController controller =
+ checkNotNull(handler().get(NetconfController.class));
+ NetconfSession session = controller.getDevicesMap()
+ .get(handler().data().deviceId()).getSession();
+
+ CfmMdService mdService = checkNotNull(handler().get(CfmMdService.class));
+
+ Short mdNumericId = mdService.getMaintenanceDomain(mdId).get().mdNumericId();
+ Short maNumericId =
+ mdService.getMaintenanceAssociation(mdId, maId).get().maNumericId();
+
+ MseaCfmNetconfService mseaCfmService =
+ checkNotNull(handler().get(MseaCfmNetconfService.class));
+
+ org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain
+ .MaintenanceAssociation yangMa = new DefaultMaintenanceAssociation();
+ yangMa.id(maNumericId);
+ yangMa.addToRemoteMeps(MepIdType.of(remoteMep.value()));
+
+ org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.MaintenanceDomain yangMd =
+ new DefaultMaintenanceDomain();
+ yangMd.id(mdNumericId);
+ yangMd.addToMaintenanceAssociation(yangMa);
+
+ MefCfm mefCfm = new DefaultMefCfm();
+ mefCfm.addToMaintenanceDomain(yangMd);
+
+ MseaCfmOpParam mseaCfmOpParam = new MseaCfmOpParam();
+ mseaCfmOpParam.mefCfm(mefCfm);
+
+ try {
+ boolean result = false;
+ if (isCreate) {
+ result = mseaCfmService.setMseaCfm(mseaCfmOpParam, session, DatastoreId.RUNNING);
+ } else {
+ result = mseaCfmService.deleteMseaMaRMep(mseaCfmOpParam, session, DatastoreId.RUNNING);
+ }
+ log.info("{} Remote MEP {} in MA {} on device {}", isCreate ? "Created" : "Deleted",
+ remoteMep, mdId.mdName() + "/" + maId.maName(), handler().data().deviceId());
+ return result;
+ } catch (NetconfException e) {
+ log.error("Unable to {} RemoteMep {} in MA {} on device {}",
+ isCreate ? "create" : "delete", remoteMep, mdId.mdName() + "/" + maId.maName(),
+ handler().data().deviceId());
+ throw new CfmConfigException("Unable to " + (isCreate ? "create" : "delete")
+ + " Remote Mep:" + e.getMessage());
+ }
+ }
+
+
+ @Override
public void transmitLoopback(MdId mdName, MaIdShort maName, MepId mepId,
MepLbCreate lbCreate) throws CfmConfigException {
NetconfController controller =
@@ -361,7 +642,7 @@
throw new UnsupportedOperationException("Not yet implemented");
}
- private org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm
+ private static org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm
.MaintenanceDomain buildYangMdFromApiMd(MaintenanceDomain md)
throws CfmConfigException {
MdNameAndTypeCombo mdName = getYangMdNameFromApiMdId(md.mdId());
@@ -375,44 +656,7 @@
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
+ private static org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm
.maintenancedomain.MaintenanceAssociation buildYangMaFromApiMa(
MaintenanceAssociation apiMa) throws CfmConfigException {
@@ -422,12 +666,6 @@
.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()));
}
@@ -486,7 +724,7 @@
return yamgMa;
}
- private MaintenanceAssociationEndPoint buildYangMepFromApiMep(Mep mep)
+ private static MaintenanceAssociationEndPoint buildYangMepFromApiMep(Mep mep)
throws CfmConfigException {
MaintenanceAssociationEndPoint mepBuilder =
new DefaultMaintenanceAssociationEndPoint();
@@ -515,14 +753,19 @@
private MepEntry buildApiMepEntryFromYangMep(
MaintenanceAssociationEndPoint yangMep, DeviceId deviceId,
- MdId mdName, MaIdShort maName) throws CfmConfigException {
+ org.onosproject.yang.gen.v1.mseacfm.rev20160229.
+ mseacfm.mefcfm.MaintenanceDomain replyMd,
+ org.onosproject.yang.gen.v1.mseacfm.rev20160229.
+ mseacfm.mefcfm.maintenancedomain.MaintenanceAssociation replyMa)
+ 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);
+ getApiMdIdFromYangMdName(replyMd.mdNameAndTypeCombo()),
+ getApiMaIdFromYangMaName(replyMa.maNameAndTypeCombo()));
if (yangMep.loopback() != null) {
MepLbEntryBuilder lbEntryBuilder = DefaultMepLbEntry.builder();
@@ -614,4 +857,10 @@
}
return rmepBuilder.build();
}
+
+ private static short getMaNumericId(MaintenanceDomain md, MaIdShort maId) {
+ return md.maintenanceAssociationList().stream()
+ .filter(ma -> maId.equals(ma.maId()))
+ .findFirst().get().maNumericId();
+ }
}
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 1bc32ca..cbe41ba 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
@@ -18,6 +18,7 @@
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.SoamId;
import org.onosproject.netconf.DatastoreId;
import org.onosproject.netconf.NetconfException;
@@ -29,6 +30,8 @@
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitlinktrace.TransmitLinktraceOutput;
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.transmitloopback.TransmitLoopbackInput;
+import java.util.Optional;
+
/**
* Extension of mseaCfmService to include NETCONF sessions.
*
@@ -65,6 +68,19 @@
MseaCfm getMepFull(MdId mdId, MaIdShort maId, MepId mepId,
NetconfSession session) throws NetconfException;
+
+ /**
+ * Returns set of all MepIds from one Md or Ma or all.
+ *
+ * @param mdIdOptional An MdId to filter by, or empty to select all
+ * @param maIdOptional An MaId to filter by, or empty to select all
+ * @param session An active NETCONF session
+ * @param targetDs one of running, candidate or startup
+ * @return mseaCfm
+ * @throws NetconfException if the session has any error
+ */
+ MseaCfm getMepIds(Optional<MdId> mdIdOptional, Optional<MaIdShort> maIdOptional,
+ NetconfSession session, DatastoreId targetDs) throws NetconfException;
/**
* Returns attributes of DM.
*
@@ -102,10 +118,52 @@
* @param targetDs one of running, candidate or startup
* @return Boolean to indicate success or failure
* @throws NetconfException if the session has any error
+ * @throws CfmConfigException if the Cfm config has any error
*/
boolean deleteMseaMep(MseaCfmOpParam mseaCfm, NetconfSession session,
- DatastoreId targetDs) throws NetconfException;
+ DatastoreId targetDs) throws NetconfException, CfmConfigException;
+ /**
+ * Deletes named Ma of mseaCfm.
+ * Expects to see a list of Mas
+ *
+ * @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
+ * @throws CfmConfigException if the Cfm config has any error
+ */
+ boolean deleteMseaMa(MseaCfmOpParam mseaCfm, NetconfSession session,
+ DatastoreId targetDs) throws NetconfException, CfmConfigException;
+
+ /**
+ * Deletes a remote Mep from an MA.
+ * Expects one or more RMeps
+ *
+ * @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
+ * @throws CfmConfigException if the Cfm config has any error
+ */
+ boolean deleteMseaMaRMep(MseaCfmOpParam mseaCfm, NetconfSession session,
+ DatastoreId targetDs) throws NetconfException, CfmConfigException;
+
+ /**
+ * Deletes named Md of mseaCfm.
+ * Expects to see a list of Mds
+ *
+ * @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
+ * @throws CfmConfigException if the Cfm config has any error
+ */
+ boolean deleteMseaMd(MseaCfmOpParam mseaCfm, NetconfSession session,
+ DatastoreId targetDs) throws NetconfException, CfmConfigException;
/**
* Deletes named delay measurements of mseaCfm.
@@ -116,9 +174,10 @@
* @param targetDs one of running, candidate or startup
* @return Boolean to indicate success or failure
* @throws NetconfException if the session has any error
+ * @throws CfmConfigException if the Cfm config has any error
*/
boolean deleteMseaCfmDm(MseaCfmOpParam mseaCfm, NetconfSession session,
- DatastoreId targetDs) throws NetconfException;
+ DatastoreId targetDs) throws NetconfException, CfmConfigException;
/**
* Service interface of transmitLoopback.
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaCfmManager.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaCfmManager.java
index 695dfcb..ef40928 100644
--- a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaCfmManager.java
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaCfmManager.java
@@ -25,6 +25,7 @@
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.SoamId;
import org.onosproject.netconf.DatastoreId;
import org.onosproject.netconf.NetconfException;
@@ -42,6 +43,7 @@
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.delaymeasurements.DelayMeasurement;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.MepIdType;
import org.onosproject.yang.model.DefaultModelObjectData;
import org.onosproject.yang.model.ModelConverter;
import org.onosproject.yang.model.ModelObject;
@@ -54,6 +56,7 @@
import org.onosproject.yang.runtime.DefaultCompositeStream;
import java.io.ByteArrayInputStream;
+import java.util.Optional;
import java.util.regex.Pattern;
/**
@@ -64,10 +67,10 @@
public class MseaCfmManager extends AbstractYangServiceImpl
implements MseaCfmNetconfService {
- public static final String MSEA_CFM = "org.onosproject.drivers.microsemi.yang.mseacfmservice";
+ private static final String MSEA_CFM = "org.onosproject.drivers.microsemi.yang.mseacfmservice";
- public static final String MSEA_CFM_NS = "http://www.microsemi.com/microsemi-edge-assure/msea-cfm";
- public static final String MSEA_CFM_PM_NS = "http://www.microsemi.com/microsemi-edge-assure/msea-soam-pm";
+ private static final String MSEA_CFM_NS = "http://www.microsemi.com/microsemi-edge-assure/msea-cfm";
+ private static final String MSEA_CFM_PM_NS = "http://www.microsemi.com/microsemi-edge-assure/msea-soam-pm";
//FIXME Remove when the issue with Null bits on onos-yang-tools is sorted
@Deprecated
@@ -77,6 +80,19 @@
@Deprecated
protected static final Pattern REGEX_EMPTY_LAST_DEFECT_SENT =
Pattern.compile("(<msea-soam-fm:last-defect-sent)[ ]?(/>)", Pattern.DOTALL);
+ private static final String MEF_CFM = "mef-cfm";
+ private static final String MAINTENANCE_DOMAIN = "maintenance-domain";
+ public static final String ID = "id";
+ private static final String MAINTENANCE_ASSOCIATION = "maintenance-association";
+ private static final String TRANSMIT_LOOPBACK = "transmit-loopback";
+ private static final String ABORT_LOOPBACK = "abort-loopback";
+ private static final String MAINTENANCE_ASSOCIATION_END_POINT = "maintenance-association-end-point";
+ private static final String MEP_ID = "mep-id";
+ private static final String DELAY_MEASUREMENTS = "delay-measurements";
+ private static final String DELAY_MEASUREMENT = "delay-measurement";
+ private static final String DM_ID = "dm-id";
+ private static final String MEP_IDENTIFIER = "mep-identifier";
+ private static final String REMOTE_MEPS = "remote-meps";
@Activate
public void activate() {
@@ -153,6 +169,38 @@
}
@Override
+ public MseaCfm getMepIds(Optional<MdId> mdIdOptional, Optional<MaIdShort> maIdOptional,
+ NetconfSession session, DatastoreId targetDs) throws NetconfException {
+
+ ModelObjectData.Builder moQueryBldr = DefaultModelObjectData.builder();
+
+ ArrayList<AnnotatedNodeInfo> annotations = new ArrayList<>();
+ String xmlQueryStr = encodeMoToXmlStr(moQueryBldr.build(), annotations);
+
+ log.debug("Sending <get> for full MEP" +
+ " query on NETCONF session " + session.getSessionId() +
+ ":\n" + xmlQueryStr);
+
+ String xmlResult = session.get(xmlQueryStr, null);
+ xmlResult = removeRpcReplyData(xmlResult);
+ xmlResult = removeEmptyActiveDefects(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 getSoamDm(MdId mdName, MaIdShort maName, MepId mepId,
SoamId dmId, DmEntryParts parts, NetconfSession session)
throws NetconfException {
@@ -190,38 +238,45 @@
@Override
public boolean deleteMseaCfmDm(MseaCfmOpParam mseaCfm, NetconfSession session,
- DatastoreId targetDs) throws NetconfException {
+ DatastoreId targetDs) throws NetconfException, CfmConfigException {
+ if (mseaCfm.mefCfm() == null) {
+ throw new CfmConfigException("mefCfm object must be present before Meps can be added");
+ }
ModelObjectData mseCfmDmList = DefaultModelObjectData.builder()
- .addModelObject((ModelObject) mseaCfm).build();
+ .addModelObject(mseaCfm).build();
- ArrayList anis = new ArrayList<AnnotatedNodeInfo>();
- 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);
- }
+ ArrayList<AnnotatedNodeInfo> anis = new ArrayList<>();
+ for (MaintenanceDomain md:mseaCfm.mefCfm().maintenanceDomain()) {
+ if (md.id() == 0) {
+ throw new CfmConfigException("An MD numeric ID must be given");
+ }
+ for (MaintenanceAssociation ma:md.maintenanceAssociation()) {
+ if (ma.id() == 0) {
+ throw new CfmConfigException("An MA numeric ID must be given");
+ }
+ for (MaintenanceAssociationEndPoint mep:ma.maintenanceAssociationEndPoint()) {
+ AugmentedMseaCfmMaintenanceAssociationEndPoint mepAugment =
+ mep.augmentation(DefaultAugmentedMseaCfmMaintenanceAssociationEndPoint.class);
+ if (mepAugment != null && mepAugment.delayMeasurements() != null) {
+ for (DelayMeasurement dm: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, dm.dmId());
+ AnnotatedNodeInfo ani = DefaultAnnotatedNodeInfo.builder()
+ .resourceId(ridBuilder.build())
+ .addAnnotation(new DefaultAnnotation(NC_OPERATION, OP_DELETE))
+ .build();
+ anis.add(ani);
}
}
}
@@ -233,29 +288,38 @@
@Override
public boolean deleteMseaMep(MseaCfmOpParam mseaCfm, NetconfSession session,
- DatastoreId targetDs) throws NetconfException {
+ DatastoreId targetDs) throws NetconfException, CfmConfigException {
+ if (mseaCfm.mefCfm() == null) {
+ throw new CfmConfigException("mefCfm object must be present before Meps can be added");
+ }
ModelObjectData mseCfmMepList = DefaultModelObjectData.builder()
.addModelObject((ModelObject) mseaCfm.mefCfm()).build();
- ArrayList anis = new ArrayList<AnnotatedNodeInfo>();
- 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);
- }
+ ArrayList<AnnotatedNodeInfo> anis = new ArrayList<>();
+ for (MaintenanceDomain md:mseaCfm.mefCfm().maintenanceDomain()) {
+ if (md.id() == 0) {
+ throw new CfmConfigException("An MD numeric ID must be given");
+ }
+ for (MaintenanceAssociation ma:md.maintenanceAssociation()) {
+ if (ma.id() == 0) {
+ throw new CfmConfigException("An MA numeric ID must be given");
+ }
+ for (MaintenanceAssociationEndPoint mep:ma.maintenanceAssociationEndPoint()) {
+ 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_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);
}
}
}
@@ -263,6 +327,112 @@
return setNetconfObject(mseCfmMepList, session, targetDs, anis);
}
+ @Override
+ public boolean deleteMseaMa(MseaCfmOpParam mseaCfm, NetconfSession session,
+ DatastoreId targetDs) throws NetconfException, CfmConfigException {
+ if (mseaCfm.mefCfm() == null) {
+ throw new CfmConfigException("mefCfm object must be present before Meps can be added");
+ }
+
+ ModelObjectData mseCfmMepList = DefaultModelObjectData.builder()
+ .addModelObject((ModelObject) mseaCfm.mefCfm()).build();
+ ArrayList<AnnotatedNodeInfo> anis = new ArrayList<>();
+ for (MaintenanceDomain md:mseaCfm.mefCfm().maintenanceDomain()) {
+ if (md.id() == 0) {
+ throw new CfmConfigException("An MD numeric ID must be given");
+ }
+ for (MaintenanceAssociation ma:md.maintenanceAssociation()) {
+ if (ma.id() == 0) {
+ throw new CfmConfigException("An MA numeric ID must be given");
+ }
+ 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());
+
+ AnnotatedNodeInfo ani = DefaultAnnotatedNodeInfo.builder()
+ .resourceId(ridBuilder.build())
+ .addAnnotation(new DefaultAnnotation(NC_OPERATION, OP_DELETE))
+ .build();
+ anis.add(ani);
+ }
+ }
+
+ return setNetconfObject(mseCfmMepList, session, targetDs, anis);
+ }
+
+ @Override
+ public boolean deleteMseaMaRMep(MseaCfmOpParam mseaCfm, NetconfSession session,
+ DatastoreId targetDs) throws NetconfException, CfmConfigException {
+ if (mseaCfm.mefCfm() == null) {
+ throw new CfmConfigException("mefCfm object must be present before Meps can be added");
+ }
+
+ ModelObjectData mseCfmMepList = DefaultModelObjectData.builder()
+ .addModelObject((ModelObject) mseaCfm.mefCfm()).build();
+ ArrayList<AnnotatedNodeInfo> anis = new ArrayList<>();
+ for (MaintenanceDomain md:mseaCfm.mefCfm().maintenanceDomain()) {
+ if (md.id() == 0) {
+ throw new CfmConfigException("An MD numeric ID must be given");
+ }
+ for (MaintenanceAssociation ma:md.maintenanceAssociation()) {
+ if (ma.id() == 0) {
+ throw new CfmConfigException("An MA numeric ID must be given");
+ }
+ for (MepIdType rmep:ma.remoteMeps()) {
+ 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())
+ .addLeafListBranchPoint(REMOTE_MEPS, MSEA_CFM_NS,
+ rmep.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);
+ }
+
+
+ @Override
+ public boolean deleteMseaMd(MseaCfmOpParam mseaCfm, NetconfSession session,
+ DatastoreId targetDs) throws NetconfException, CfmConfigException {
+ if (mseaCfm.mefCfm() == null) {
+ throw new CfmConfigException("mefCfm object must be present before Meps can be added");
+ }
+ ModelObjectData mseCfmMepList = DefaultModelObjectData.builder()
+ .addModelObject((ModelObject) mseaCfm.mefCfm()).build();
+
+ ArrayList<AnnotatedNodeInfo> anis = new ArrayList<>();
+ for (MaintenanceDomain md:mseaCfm.mefCfm().maintenanceDomain()) {
+ if (md.id() == 0) {
+ throw new CfmConfigException("An MD numeric ID must be given");
+ }
+ 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());
+ 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.
@@ -275,7 +445,7 @@
.addModelObject((ModelObject) inputVar).build();
customRpcNetconf(transLoopbackMo,
- "transmit-loopback", session);
+ TRANSMIT_LOOPBACK, session);
}
@Override
@@ -284,7 +454,7 @@
ModelObjectData abortLoopbackMo = DefaultModelObjectData.builder()
.addModelObject((ModelObject) inputVar).build();
- customRpcNetconf(abortLoopbackMo, "abort-loopback", session);
+ customRpcNetconf(abortLoopbackMo, ABORT_LOOPBACK, session);
}
@Override
@@ -314,15 +484,21 @@
rpc.append("xmlns:msea-soam-pm=\"http://www.microsemi.com/microsemi-edge-assure/msea-soam-pm\">\n");
rpc.append("<maintenance-domain>\n");
rpc.append("<id/>\n");
- rpc.append("<name>" + mdId.mdName() + "</name>\n");
+ rpc.append("<name>");
+ rpc.append(mdId.mdName());
+ rpc.append("</name>\n");
rpc.append("<maintenance-association>\n");
rpc.append("<id/>\n");
- rpc.append("<name>" + maId.maName() + "</name>\n");
+ rpc.append("<name>");
+ rpc.append(maId.maName());
+ rpc.append("</name>\n");
rpc.append("<ccm-interval>10ms</ccm-interval>\n");
rpc.append("<remote-meps/>\n");
rpc.append("<component-list/>\n");
rpc.append("<maintenance-association-end-point>\n");
- rpc.append("<mep-identifier>" + mepId.id() + "</mep-identifier>\n");
+ rpc.append("<mep-identifier>");
+ rpc.append(mepId.id());
+ rpc.append("</mep-identifier>\n");
rpc.append("<mac-address/>\n");
rpc.append("<remote-mep-database>\n");
rpc.append("<remote-mep>\n");
@@ -356,12 +532,18 @@
rpc.append("xmlns:msea-soam-pm=\"http://www.microsemi.com/microsemi-edge-assure/msea-soam-pm\">\n");
rpc.append("<maintenance-domain>\n");
rpc.append("<id/>\n");
- rpc.append("<name>" + mdId.mdName() + "</name>\n");
+ rpc.append("<name>");
+ rpc.append(mdId.mdName());
+ rpc.append("</name>\n");
rpc.append("<maintenance-association>\n");
rpc.append("<id/>\n");
- rpc.append("<name>" + maId.maName() + "</name>\n");
+ rpc.append("<name>");
+ rpc.append(maId.maName());
+ rpc.append("</name>\n");
rpc.append("<maintenance-association-end-point>\n");
- rpc.append("<mep-identifier>" + mepId.id() + "</mep-identifier>\n");
+ rpc.append("<mep-identifier>");
+ rpc.append(mepId.id());
+ rpc.append("</mep-identifier>\n");
rpc.append("<interface/>\n");
//Direction will always be DOWN for EA1000
rpc.append("<primary-vid/>\n");
@@ -396,16 +578,24 @@
rpc.append("xmlns:msea-soam-pm=\"http://www.microsemi.com/microsemi-edge-assure/msea-soam-pm\">\n");
rpc.append("<maintenance-domain>\n");
rpc.append("<id/>\n");
- rpc.append("<name>" + mdId.mdName() + "</name>\n");
+ rpc.append("<name>");
+ rpc.append(mdId.mdName());
+ rpc.append("</name>\n");
rpc.append("<maintenance-association>\n");
rpc.append("<id/>\n");
- rpc.append("<name>" + maId.maName() + "</name>\n");
+ rpc.append("<name>");
+ rpc.append(maId.maName());
+ rpc.append("</name>\n");
rpc.append("<maintenance-association-end-point>\n");
- rpc.append("<mep-identifier>" + mepId.id() + "</mep-identifier>\n");
+ rpc.append("<mep-identifier>");
+ rpc.append(mepId.id());
+ rpc.append("</mep-identifier>\n");
if (dmId != null) {
rpc.append("<msea-soam-pm:delay-measurements>");
rpc.append("<msea-soam-pm:delay-measurement>\n");
- rpc.append("<msea-soam-pm:dm-id>" + dmId.id() + "</msea-soam-pm:dm-id>\n");
+ rpc.append("<msea-soam-pm:dm-id>");
+ rpc.append(dmId.id());
+ rpc.append("</msea-soam-pm:dm-id>\n");
rpc.append("<msea-soam-pm:mep-id/>");
rpc.append("<msea-soam-pm:mac-address/>");
rpc.append("<msea-soam-pm:administrative-state/>\n");
@@ -445,9 +635,15 @@
StringBuilder rpc = new StringBuilder();
rpc.append("<abort-loopback xmlns=\"http://www.microsemi.com/microsemi-edge-assure/msea-cfm\">");
- rpc.append("<maintenance-domain>" + mdId + "</maintenance-domain>");
- rpc.append("<maintenance-association>" + maId + "</maintenance-association>");
- rpc.append("<maintenance-association-end-point>" + mepId + "</maintenance-association-end-point>");
+ rpc.append("<maintenance-domain>");
+ rpc.append(mdId);
+ rpc.append("</maintenance-domain>");
+ rpc.append("<maintenance-association>");
+ rpc.append(maId);
+ rpc.append("</maintenance-association>");
+ rpc.append("<maintenance-association-end-point>");
+ rpc.append(mepId);
+ rpc.append("</maintenance-association-end-point>");
rpc.append("</abort-loopback>");
return rpc.toString();
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaSaFilteringManager.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaSaFilteringManager.java
index f9ed7a1..78c6315 100644
--- a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaSaFilteringManager.java
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/impl/MseaSaFilteringManager.java
@@ -119,7 +119,7 @@
reply.sourceIpaddressFiltering((SourceIpaddressFiltering) mo);
}
}
- if (reply != null && reply.sourceIpaddressFiltering() != null &&
+ if (reply.sourceIpaddressFiltering() != null &&
reply.sourceIpaddressFiltering().interfaceEth0() != null) {
return reply.sourceIpaddressFiltering().interfaceEth0().sourceAddressRange();
} else {
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/CeVlanMapUtils.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/CeVlanMapUtils.java
index 8b9309c..76534d0 100644
--- a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/CeVlanMapUtils.java
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/CeVlanMapUtils.java
@@ -155,7 +155,7 @@
public static String removeZeroIfPossible(String existingMap) {
if (existingMap == null || existingMap.isEmpty()) {
return "0";
- } else if (existingMap == "0") {
+ } else if ("0".equals(existingMap)) {
return existingMap;
}
return removeFromCeVlanMap(existingMap, (short) 0);
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/MaNameUtil.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/MaNameUtil.java
index 16e9686..e18abe6 100644
--- a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/MaNameUtil.java
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/MaNameUtil.java
@@ -30,11 +30,14 @@
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.manameandtypecombo.DefaultNameRfc2685VpnId;
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.manameandtypecombo.DefaultNameUint16;
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.manameandtypecombo.DefaultNameY1731Icc;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.manameandtypecombo.NameCharacterString;
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.manameandtypecombo.nameprimaryvid.NamePrimaryVidUnion;
import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.Identifier45;
/**
- * This is a workaround for Checkstyle issue.
+ * Utility for translating between Maintenance Association names in the CFM API model and the device YANG.
+ *
+ * This has to be in a separate file as a workaround for Checkstyle issue.
* https://github.com/checkstyle/checkstyle/issues/3850
* There are two types of DefaultNameCharacterString - one for MA and another for MD
* Putting both together in a file means that the full path has to be given which
@@ -46,6 +49,12 @@
//Hidden
}
+ /**
+ * Convert CFM API MA identifier to the YANG model MA identifier.
+ * @param maId Maintenance Association ID in CFM API
+ * @return Maintenance Association ID in YANG API
+ * @throws CfmConfigException If there's a problem with the name
+ */
public static MaNameAndTypeCombo getYangMaNameFromApiMaId(MaIdShort maId)
throws CfmConfigException {
MaNameAndTypeCombo maName;
@@ -70,4 +79,52 @@
}
return maName;
}
+
+ /**
+ * Convert YANG API MA identifier to the CFM API MA identifier.
+ * @param nameAndTypeCombo Maintenance Association ID in YANG API
+ * @return Maintenance Association ID in CFM API
+ */
+ public static MaIdShort getApiMaIdFromYangMaName(MaNameAndTypeCombo nameAndTypeCombo) {
+ MaIdShort maId;
+ if (nameAndTypeCombo instanceof DefaultNameCharacterString) {
+ maId = MaIdCharStr.asMaId(
+ ((DefaultNameCharacterString) nameAndTypeCombo).name().string());
+ } else if (nameAndTypeCombo instanceof DefaultNamePrimaryVid) {
+ if (((DefaultNamePrimaryVid) nameAndTypeCombo).namePrimaryVid().enumeration() != null) {
+ maId = MaIdPrimaryVid.asMaId(
+ ((DefaultNamePrimaryVid) nameAndTypeCombo).namePrimaryVid().enumeration().name());
+ } else if (((DefaultNamePrimaryVid) nameAndTypeCombo).namePrimaryVid().vlanIdType() != null) {
+ maId = MaIdPrimaryVid.asMaId(
+ ((DefaultNamePrimaryVid) nameAndTypeCombo).namePrimaryVid().vlanIdType().uint16());
+ } else {
+ throw new IllegalArgumentException("Unexpected primaryVid for " +
+ "MaNameAndTypeCombo: " + nameAndTypeCombo.toString());
+ }
+ } else if (nameAndTypeCombo instanceof DefaultNameUint16) {
+ maId = MaId2Octet.asMaId(((DefaultNameUint16) nameAndTypeCombo).nameUint16());
+
+ } else if (nameAndTypeCombo instanceof DefaultNameRfc2685VpnId) {
+ maId = MaIdRfc2685VpnId.asMaIdHex(
+ HexString.toHexString(
+ ((DefaultNameRfc2685VpnId) nameAndTypeCombo).nameRfc2685VpnId()));
+ } else if (nameAndTypeCombo instanceof DefaultNameY1731Icc) {
+ maId = MaIdIccY1731.asMaId(((DefaultNameY1731Icc) nameAndTypeCombo).nameY1731Icc().string());
+
+ } else {
+ throw new IllegalArgumentException("Unexpected type for " +
+ "MaNameAndTypeCombo: " + nameAndTypeCombo.toString());
+ }
+
+ return maId;
+ }
+
+ /**
+ * Cast the YANG generic type of MaNameAndTypeCombo specifically to char string.
+ * @param maName a YANG generic MaNameAndTypeCombo
+ * @return a YANG specific MaNameAndTypeCombo for Char string
+ */
+ public static NameCharacterString cast(MaNameAndTypeCombo maName) {
+ return (NameCharacterString) maName;
+ }
}
diff --git a/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/MdNameUtil.java b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/MdNameUtil.java
new file mode 100644
index 0000000..ba0cc96
--- /dev/null
+++ b/drivers/microsemi/src/main/java/org/onosproject/drivers/microsemi/yang/utils/MdNameUtil.java
@@ -0,0 +1,139 @@
+/*
+ * 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.utils;
+
+import org.onlab.packet.IpAddress;
+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.yang.gen.v1.ietfinettypes.rev20130715.ietfinettypes.DomainName;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.MdNameAndTypeCombo;
+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.MacAddressAndUint;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.NameCharacterString;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.namedomainname.NameDomainNameUnion;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.Identifier45;
+import org.onosproject.yang.gen.v1.mseatypes.rev20160229.mseatypes.MacAddressAndUintStr;
+
+/**
+ * Utility for translating between Maintenance Domain names in the CFM API model and the device YANG.
+ *
+ * This has to be in a separate file as a workaround for Checkstyle issue.
+ * https://github.com/checkstyle/checkstyle/issues/3850
+ * There are two types of DefaultNameCharacterString - one for MA and another for MD
+ * Putting both together in a file means that the full path has to be given which
+ * will then fail checkstyle
+ */
+public final class MdNameUtil {
+
+ private MdNameUtil() {
+ //Hidden
+ }
+
+ /**
+ * Convert CFM API MD identifier to the YANG model MD identifier.
+ * @param mdId Maintenance Domain ID in CFM API
+ * @return Maintenance Domain ID in YANG API
+ * @throws CfmConfigException If there's a problem with the name
+ */
+ public 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;
+ }
+
+ /**
+ * Convert YANG API MD identifier to the CFM API MD identifier.
+ * @param nameAndTypeCombo Maintenance Domain ID in YANG API
+ * @return Maintenance Domain ID in CFM API
+ */
+ public static MdId getApiMdIdFromYangMdName(MdNameAndTypeCombo nameAndTypeCombo) {
+ MdId mdId;
+ if (nameAndTypeCombo instanceof DefaultNameDomainName) {
+ NameDomainNameUnion domainName =
+ ((DefaultNameDomainName) nameAndTypeCombo).nameDomainName();
+ if (domainName.ipAddress() != null) {
+ mdId = MdIdDomainName.asMdId(domainName.ipAddress().toString());
+ } else if (domainName.domainName() != null) {
+ mdId = MdIdDomainName.asMdId(domainName.domainName().string());
+ } else {
+ throw new IllegalArgumentException("Unexpected domainName for " +
+ "MdNameAndTypeCombo: " + nameAndTypeCombo.toString());
+ }
+ } else if (nameAndTypeCombo instanceof DefaultNameCharacterString) {
+ mdId = MdIdCharStr.asMdId(
+ ((NameCharacterString) nameAndTypeCombo).name().string());
+
+ } else if (nameAndTypeCombo instanceof DefaultMacAddressAndUint) {
+ mdId = MdIdMacUint.asMdId(
+ ((MacAddressAndUint) nameAndTypeCombo).nameMacAddressAndUint().string());
+
+ } else if (nameAndTypeCombo instanceof DefaultNameNone) {
+ mdId = MdIdNone.asMdId();
+ } else {
+ throw new IllegalArgumentException("Unexpected type for " +
+ "MdNameAndTypeCombo: " + nameAndTypeCombo.toString());
+ }
+
+ return mdId;
+ }
+
+ /**
+ * Cast the YANG generic type of MdNameAndTypeCombo specifically to char string.
+ * @param maName a YANG generic MdNameAndTypeCombo
+ * @return a YANG specific MdNameAndTypeCombo for Char string
+ */
+ public static NameCharacterString cast(MdNameAndTypeCombo maName) {
+ return (NameCharacterString) maName;
+ }
+}
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
index 20e80a1..1f87634 100644
--- a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/EA1000CfmMepProgrammableTest.java
+++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/EA1000CfmMepProgrammableTest.java
@@ -20,11 +20,13 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import static org.onosproject.drivers.microsemi.yang.utils.MdNameUtil.getYangMdNameFromApiMdId;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.onosproject.drivers.microsemi.yang.utils.MaNameUtil;
+import org.onosproject.drivers.microsemi.yang.utils.MdNameUtil;
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;
@@ -38,21 +40,24 @@
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.CfmMepProgrammable;
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;
import java.util.BitSet;
+import java.util.Optional;
/**
* Test of the CFM implementation on EA1000 through the incubator/net/l2monitoring interface.
*/
public class EA1000CfmMepProgrammableTest {
- EA1000CfmMepProgrammable cfmProgrammable;
public static final MdId MD_ID_1 = MdIdCharStr.asMdId("md-1");
public static final MaIdShort MA_ID_11 = MaIdCharStr.asMaId("ma-1-1");
public static final MepId MEP_111 = MepId.valueOf((short) 1);
public static final MepId MEP_112 = MepId.valueOf((short) 2);
+ private CfmMepProgrammable cfmProgrammable;
+
@Before
public void setUp() throws Exception {
cfmProgrammable = new EA1000CfmMepProgrammable();
@@ -67,12 +72,6 @@
fail("Not yet implemented");
}
- @Ignore
- @Test
- public void testGetAllMeps() {
- fail("Not yet implemented");
- }
-
@Test
public void testGetMep() throws CfmConfigException {
MepEntry mepEntry = cfmProgrammable.getMep(MD_ID_1, MA_ID_11, MEP_111);
@@ -143,7 +142,107 @@
*/
@Test
public void testDeleteMep() throws CfmConfigException {
- assertTrue(cfmProgrammable.deleteMep(MD_ID_1, MA_ID_11, MEP_111));
+ assertTrue(cfmProgrammable.deleteMep(MD_ID_1, MA_ID_11, MEP_111, Optional.empty()));
+ }
+
+ /**
+ * Create the MD md-1 on the device.
+ * This will retrieve the MD from the MockCfmMdService and will create it
+ * and its MA on the device
+ * Depends on sampleXmlRegexCreateMseaCfmMa
+ */
+ @Test
+ public void testCreateMaintenanceDomainOnDevice() throws CfmConfigException {
+ boolean success =
+ cfmProgrammable.createMdOnDevice(MdIdCharStr.asMdId("md-1"));
+ assertTrue(success);
+ }
+
+ /**
+ * Create the MD md-2 on the device.
+ * This will retrieve the MD from the MockCfmMdService and will create it on
+ * the device. This MD has no MA
+ * Depends on sampleXmlRegexCreateMseaCfmMa
+ */
+ @Test
+ public void testCreateMaintenanceDomainOnDevice2() throws CfmConfigException {
+ boolean success =
+ cfmProgrammable.createMdOnDevice(MdIdCharStr.asMdId("md-2"));
+ assertTrue(success);
+ }
+
+ /**
+ * Delete the MD md-1 on the device.
+ * This will retrieve the MD from the MockCfmMdService and will delete it on
+ * the device.
+ * Depends on sampleXmlRegexCreateMseaCfmMa
+ */
+ @Test
+ public void testDeleteMaintenanceDomainOnDevice() throws CfmConfigException {
+ boolean success =
+ cfmProgrammable.deleteMdOnDevice(MdIdCharStr.asMdId("md-1"), Optional.empty());
+ assertTrue(success);
+ }
+
+
+ /**
+ * Create the MA ma-1-1 on the device.
+ * This will retrieve the MA from the MockCfmMdService and will create it
+ * on the device under md-1
+ * Depends on sampleXmlRegexCreateMseaCfmMa
+ */
+ @Test
+ public void testCreateMaintenanceAssociationOnDevice() throws CfmConfigException {
+ boolean success =
+ cfmProgrammable.createMaOnDevice(
+ MdIdCharStr.asMdId("md-1"), MaIdCharStr.asMaId("ma-1-1"));
+ assertTrue(success);
+ }
+
+ /**
+ * Delete the MD md-1 on the device.
+ * This will retrieve the MD from the MockCfmMdService and will delete it on
+ * the device.
+ * Depends on sampleXmlRegexCreateMseaCfmMa
+ */
+ @Test
+ public void testDeleteMaintenanceAssociationOnDevice() throws CfmConfigException {
+ boolean success =
+ cfmProgrammable.deleteMaOnDevice(
+ MdIdCharStr.asMdId("md-1"),
+ MaIdCharStr.asMaId("ma-1-1"),
+ Optional.empty());
+ assertTrue(success);
+ }
+
+ /**
+ * Create the Remote Mep 10001 in ma-1-1 on the device.
+ * This will retrieve the MA from the MockCfmMdService and will create the
+ * new remote mep under it on the device
+ * Depends on sampleXmlRegexCreateMseaCfmMa
+ */
+ @Test
+ public void testCreateRemoteMepOnDevice() throws CfmConfigException {
+ boolean success =
+ cfmProgrammable.createMaRemoteMepOnDevice(
+ MdIdCharStr.asMdId("md-1"), MaIdCharStr.asMaId("ma-1-1"),
+ MepId.valueOf((short) 1001));
+ assertTrue(success);
+ }
+
+ /**
+ * Delete the Remote Mep 1002 in ma-1-1 on the device.
+ * This will retrieve the MA from the MockCfmMdService and will delete the
+ * existing remote mep under it on the device
+ * Depends on sampleXmlRegexCreateMseaCfmMa
+ */
+ @Test
+ public void testDeleteRemoteMepOnDevice() throws CfmConfigException {
+ boolean success =
+ cfmProgrammable.deleteMaRemoteMepOnDevice(
+ MdIdCharStr.asMdId("md-1"), MaIdCharStr.asMaId("ma-1-1"),
+ MepId.valueOf((short) 1001));
+ assertTrue(success);
}
/**
@@ -167,25 +266,21 @@
cfmProgrammable.abortLoopback(MD_ID_1, MA_ID_11, MEP_111);
}
-// @Test
-// public void testTransmitLinktrace() {
-// fail("Not yet implemented");
-// }
+ @Ignore
+ @Test
+ public void testTransmitLinktrace() {
+ fail("Not yet implemented");
+ }
@Test
public void testGetYangMdNameFromApiMdId() throws CfmConfigException {
- MdNameAndTypeCombo name = EA1000CfmMepProgrammable
- .getYangMdNameFromApiMdId(MdIdCharStr.asMdId("md-1"));
+ MdNameAndTypeCombo name = 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());
+ assertEquals("md-1", MdNameUtil.cast(name).name().string());
}
@Test
@@ -196,11 +291,6 @@
.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());
+ assertEquals("ma-1-1", MaNameUtil.cast(name).name().string());
}
-
}
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 58a8a5b..742f8c9 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
@@ -20,6 +20,7 @@
import org.onosproject.core.CoreService;
import org.onosproject.drivers.microsemi.yang.MockCfmMdService;
+import org.onosproject.drivers.microsemi.yang.MockCfmMepService;
import org.onosproject.drivers.microsemi.yang.MockMseaCfmManager;
import org.onosproject.drivers.microsemi.yang.MockMseaSaFilteringManager;
import org.onosproject.drivers.microsemi.yang.MockMseaUniEvcServiceManager;
@@ -31,6 +32,7 @@
import org.onosproject.drivers.netconf.MockNetconfController;
import org.onosproject.drivers.netconf.MockNetconfDevice;
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.driver.Behaviour;
import org.onosproject.net.driver.DefaultDriver;
@@ -59,6 +61,7 @@
private MockMseaUniEvcServiceManager mseaUniEvcService;
private MockMseaCfmManager mseaCfmService;
private MockCfmMdService mockMdService;
+ private MockCfmMepService mockMepService;
private CoreService coreService;
public MockEa1000DriverHandler() throws NetconfException {
@@ -92,6 +95,9 @@
mockMdService = new MockCfmMdService();
mockMdService.activate();
+ mockMepService = new MockCfmMepService();
+ mockMepService.activate();
+
coreService = new MockCoreService();
coreService.registerApplication(MICROSEMI_DRIVERS);
}
@@ -131,6 +137,10 @@
} else if (serviceClass.equals(CfmMdService.class)) {
return (T) mockMdService;
+
+ } else if (serviceClass.equals(CfmMepService.class)) {
+ return (T) mockMepService;
+
}
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
index ba6d656..3d0fb5f 100644
--- 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
@@ -15,6 +15,8 @@
*/
package org.onosproject.drivers.microsemi.yang;
+import org.onlab.packet.VlanId;
+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;
@@ -22,6 +24,7 @@
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.identifier.MepId;
import org.onosproject.incubator.net.l2monitoring.cfm.impl.CfmMdManager;
import static org.easymock.EasyMock.*;
import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmConfigException;
@@ -29,6 +32,9 @@
import java.util.Optional;
+/**
+ * Supports testing of services that reply on the CfmMdService.
+ */
public class MockCfmMdService extends CfmMdManager {
@Override
@@ -40,6 +46,11 @@
.builder(MaIdCharStr.asMaId("ma-1-1"), 6)
.maNumericId((short) 1)
.ccmInterval(MaintenanceAssociation.CcmInterval.INTERVAL_3MS)
+ .addToRemoteMepIdList(MepId.valueOf((short) 10))
+ .addToRemoteMepIdList(MepId.valueOf((short) 20))
+ .addToComponentList(
+ DefaultComponent.builder(1)
+ .addToVidList(VlanId.vlanId((short) 101)).build())
.build();
MdId md1Name = MdIdCharStr.asMdId("md-1");
@@ -50,14 +61,25 @@
.addToMaList(ma)
.build();
+ MdId md2Name = MdIdCharStr.asMdId("md-2");
+ MaintenanceDomain md2 = DefaultMaintenanceDomain
+ .builder(md1Name)
+ .mdNumericId((short) 2)
+ .mdLevel(MaintenanceDomain.MdLevel.LEVEL2)
+ .build();
+
expect(store.createUpdateMaintenanceDomain(md1))
.andReturn(true);
+ expect(store.createUpdateMaintenanceDomain(md2))
+ .andReturn(true);
expect(store.getMaintenanceDomain(md1Name))
.andReturn(Optional.of(md1)).anyTimes();
+ expect(store.getMaintenanceDomain(md2Name))
+ .andReturn(Optional.of(md2)).anyTimes();
replay(store);
} catch (CfmConfigException e) {
- throw new IllegalArgumentException("Error creating Md md-1 for test");
+ throw new IllegalArgumentException("Error creating MDs for test", e);
}
}
}
diff --git a/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockCfmMepService.java b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockCfmMepService.java
new file mode 100644
index 0000000..c00fc4e
--- /dev/null
+++ b/drivers/microsemi/src/test/java/org/onosproject/drivers/microsemi/yang/MockCfmMepService.java
@@ -0,0 +1,137 @@
+/*
+ * 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.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.DefaultMep;
+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.MdIdCharStr;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepKeyId;
+import org.onosproject.incubator.net.l2monitoring.cfm.impl.CfmMdManager;
+import org.onosproject.incubator.net.l2monitoring.cfm.impl.CfmMepManager;
+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.CfmMepProgrammable;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.MepStore;
+import org.onosproject.incubator.net.l2monitoring.soam.SoamDmProgrammable;
+import org.onosproject.incubator.net.l2monitoring.soam.impl.TestSoamDmProgrammable;
+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.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.atomic.AtomicLong;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.onosproject.net.NetTestTools.injectEventDispatcher;
+
+/**
+ * Supports testing of services that reply on the CfmMepService.
+ */
+public class MockCfmMepService extends CfmMepManager {
+ 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";
+ protected static final DeviceId DEVICE_ID1 = DeviceId.deviceId("netconf:1.2.3.4:830");
+
+
+ private final DriverService driverService = createMock(DriverService.class);
+
+ private Device device1;
+ private Driver testDriver;
+
+
+ @Override
+ public void activate() {
+ mepStore = createMock(MepStore.class);
+ cfmMdService = new MockCfmMdService();
+ deviceService = createMock(DeviceService.class);
+ ((CfmMdManager) cfmMdService).activate();
+
+ 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());
+
+ Map<Class<? extends Behaviour>, Class<? extends Behaviour>> behaviours = new HashMap<>();
+ behaviours.put(DeviceDescriptionDiscovery.class, TestDeviceDiscoveryBehavior.class);
+ behaviours.put(CfmMepProgrammable.class, TestCfmMepProgrammable.class);
+ behaviours.put(SoamDmProgrammable.class, TestSoamDmProgrammable.class);
+
+ TestUtils.setField(this, "coreService", new TestCoreService());
+ TestUtils.setField(this, "deviceService", deviceService);
+ injectEventDispatcher(this, new TestEventDispatcher());
+
+ testDriver = new DefaultDriver(
+ TEST_DRIVER, new ArrayList<Driver>(),
+ TEST_MFR, TEST_HW_VERSION, TEST_SW_VERSION,
+ behaviours, new HashMap<>());
+
+ try {
+ Mep mep1 = DefaultMep.builder(
+ MepId.valueOf((short) 10),
+ DEVICE_ID1,
+ PortNumber.P0,
+ Mep.MepDirection.UP_MEP,
+ MdIdCharStr.asMdId("md-1"),
+ MaIdCharStr.asMaId("ma-1-1"))
+ .build();
+
+ expect(mepStore.getMep(new MepKeyId(mep1))).andReturn(Optional.of(mep1)).anyTimes();
+ } catch (CfmConfigException e) {
+ throw new IllegalArgumentException("Error creating MEPs for test", e);
+ }
+ }
+
+ 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/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 b9d4342..6bf67c0 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
@@ -478,11 +478,12 @@
+ "(<config xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
+ "(<mef-cfm).*"
+ "(<maintenance-domain>)\\R?"
- + "(<id/>)?\\R?"
- + "(<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>)\\R?"
+ + "(<id>[0-9]{1,5}</id>)?\\R?"
+ + "((<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>))?\\R?"
+ "(<maintenance-association>)\\R?"
- + "(<id/>)?\\R?"
- + "(<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>)\\R?"
+ + "(<id>[0-9]{1,5}</id>)?\\R?"
+ + "((<name>[a-zA-Z0-9\\-:\\.]{1,48}</name>)|"
+ + "(<name-primary-vid>[0-9]{1,4}</name-primary-vid>))?\\R?"
+ "(<maintenance-association-end-point nc:operation=\"delete\">)\\R?"
+ "(<mep-identifier>)[0-9]{1,4}(</mep-identifier>)\\R?"
+ "(</maintenance-association-end-point>)\\R?"
@@ -492,6 +493,85 @@
+ "(</config>)\\R?"
+ "(</edit-config>)\\R?(</rpc>)\\R?(]]>){2}", Pattern.DOTALL);
+ //For testGetConfigMseaCfmEssentials
+ private Pattern sampleXmlRegexCreateMseaCfmMa =
+ Pattern.compile("(<\\?xml).*(<rpc).*(<edit-config>)\\R?"
+ + "(<target>\\R?<running/>\\R?</target>)\\R?"
+ + "(<config xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
+ + "(<mef-cfm).*"
+ + "(<maintenance-domain>)\\R?"
+ + "(<id>)([0-9]){1,4}(</id>)\\R?"
+ + "((<md-level>)([0-9]){1}(</md-level>))?\\R?"
+ + "((<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>))?\\R?"
+ + "((<maintenance-association>)\\R?"
+ + "(<id>)([0-9]){1,4}(</id>)\\R?"
+ + "((<ccm-interval>)(3.3ms)(</ccm-interval>))?\\R?"
+ + "((<remote-meps>)([0-9]){1,4}(</remote-meps>))*\\R?"
+ + "(((<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>))|"
+ + "((<name-primary-vid>)([0-9]){1,4}(</name-primary-vid>)))?\\R?"
+ + "((<component-list>)\\R?"
+ + "(<vid>)([0-9]){1,4}(</vid>)\\R?"
+ + "(</component-list>))?\\R?"
+ + "(</maintenance-association>))*\\R?"
+ + "(</maintenance-domain>)\\R?"
+ + "(</mef-cfm>)\\R?"
+ + "(</config>)\\R?"
+ + "(</edit-config>)\\R?(</rpc>)\\R?(]]>){2}", Pattern.DOTALL);
+
+ //For testGetConfigMseaCfmEssentials
+ private Pattern sampleXmlRegexDeleteMseaCfmMa =
+ Pattern.compile("(<\\?xml).*(<rpc).*(<edit-config>)\\R?"
+ + "(<target>\\R?<running/>\\R?</target>)\\R?"
+ + "(<config xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
+ + "(<mef-cfm).*"
+ + "(<maintenance-domain>)\\R?"
+ + "((<id/>)|((<id>)([0-9]){1,4}(</id>)))?\\R?"
+ + "((<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>))?\\R?"
+ + "(<maintenance-association nc:operation=\"delete\">)\\R?"
+ + "((<id/>)|((<id>)([0-9]){1,4}(</id>)))?\\R?"
+ + "(((<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>))|"
+ + "((<name-primary-vid>)([0-9]){1,4}(</name-primary-vid>)))?\\R?"
+ + "(</maintenance-association>)\\R?"
+ + "(</maintenance-domain>)\\R?"
+ + "(</mef-cfm>)\\R?"
+ + "(</config>)\\R?"
+ + "(</edit-config>)\\R?(</rpc>)\\R?(]]>){2}", Pattern.DOTALL);
+
+ //For testDeleteMseaMepRemoteMep
+ private Pattern sampleXmlRegexDeleteMseaCfmRmep =
+ Pattern.compile("(<\\?xml).*(<rpc).*(<edit-config>)\\R?"
+ + "(<target>\\R?<running/>\\R?</target>)\\R?"
+ + "(<config xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
+ + "(<mef-cfm).*"
+ + "(<maintenance-domain>)\\R?"
+ + "((<id>)[0-9]{1,4}(</id>))?\\R?"
+ + "((<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>))?\\R?"
+ + "(<maintenance-association>)\\R?"
+ + "((<id>)[0-9]{1,4}(</id>))?\\R?"
+ + "((<remote-meps nc:operation=\"delete\">)([0-9]){1,4}(</remote-meps>))*\\R?"
+ + "(((<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>))|"
+ + "((<name-primary-vid>)([0-9]){1,4}(</name-primary-vid>)))?\\R?"
+ + "(</maintenance-association>)\\R?"
+ + "(</maintenance-domain>)\\R?"
+ + "(</mef-cfm>)\\R?"
+ + "(</config>)\\R?"
+ + "(</edit-config>)\\R?(</rpc>)\\R?(]]>){2}", Pattern.DOTALL);
+
+ //For testDeleteMseaMd
+ private Pattern sampleXmlRegexDeleteMseaCfmMd =
+ Pattern.compile("(<\\?xml).*(<rpc).*(<edit-config>)\\R?"
+ + "(<target>\\R?<running/>\\R?</target>)\\R?"
+ + "(<config xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">)\\R?"
+ + "(<mef-cfm).*"
+ + "(<maintenance-domain nc:operation=\"delete\">)\\R?"
+ + "((<id/>)|(<id>([0-9]){1,4}(</id>)))?\\R?"
+ + "(((<name>)([a-zA-Z0-9\\-:\\.]){1,48}(</name>))|\\R?"
+ + "((<name-domain-name>)([a-zA-Z0-9\\-\\.]){1,48}(</name-domain-name>)))?\\R?"
+ + "(</maintenance-domain>)\\R?"
+ + "(</mef-cfm>)\\R?"
+ + "(</config>)\\R?"
+ + "(</edit-config>)\\R?(</rpc>)\\R?(]]>){2}", Pattern.DOTALL);
+
private Pattern sampleXmlRegexTransmitLoopback =
Pattern.compile("(<\\?xml).*(<rpc).*\\R?"
@@ -1310,6 +1390,18 @@
} else if (sampleXmlRegexDeleteMseaCfmMep.matcher(request).matches()) {
return SAMPLE_REPLY_OK;
+ } else if (sampleXmlRegexCreateMseaCfmMa.matcher(request).matches()) {
+ return SAMPLE_REPLY_OK;
+
+ } else if (sampleXmlRegexDeleteMseaCfmMa.matcher(request).matches()) {
+ return SAMPLE_REPLY_OK;
+
+ } else if (sampleXmlRegexDeleteMseaCfmRmep.matcher(request).matches()) {
+ return SAMPLE_REPLY_OK;
+
+ } else if (sampleXmlRegexDeleteMseaCfmMd.matcher(request).matches()) {
+ return SAMPLE_REPLY_OK;
+
} else if (sampleXmlRegexGetMseaDelay.matcher(request).matches()) {
return SAMPLE_MSEACFM_DELAY_MEASUREMENT_FULL_REPLY;
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 fe99bf3..bb65a4d 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
@@ -36,20 +36,31 @@
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.DatastoreId;
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.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.mefcfm.DefaultMaintenanceDomain;
import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.MaintenanceDomain;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.DefaultMaintenanceAssociation;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.MaintenanceAssociation;
+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.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.manameandtypecombo.DefaultNamePrimaryVid;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.manameandtypecombo.NamePrimaryVid;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.maintenanceassociation.manameandtypecombo.nameprimaryvid.NamePrimaryVidUnion;
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.NameCharacterString;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.NameDomainName;
+import org.onosproject.yang.gen.v1.mseacfm.rev20160229.mseacfm.mefcfm.maintenancedomain.mdnameandtypecombo.namedomainname.NameDomainNameUnion;
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;
@@ -194,10 +205,173 @@
// mseaCfmService.setMseaCfm(mseaCfmOpParam, session, NcDsType.running);
}
+ /**
+ * Using mep Id 10.
+ */
@Test
+ public void testDeleteMseaMep() {
+ MaintenanceAssociationEndPoint mep10 = new DefaultMaintenanceAssociationEndPoint();
+ mep10.mepIdentifier(MepIdType.of(10));
+
+ MaintenanceAssociation ma1100 = new DefaultMaintenanceAssociation();
+ NamePrimaryVid pvid1100Name = new DefaultNamePrimaryVid();
+ pvid1100Name.namePrimaryVid(NamePrimaryVidUnion.fromString("1100"));
+ ma1100.maNameAndTypeCombo(pvid1100Name);
+ ma1100.id((short) 1100);
+ ma1100.addToMaintenanceAssociationEndPoint(mep10);
+
+ MaintenanceDomain md = new DefaultMaintenanceDomain();
+ NameCharacterString mdName = new DefaultNameCharacterString();
+ mdName.name(new Identifier45("md-1"));
+ md.mdNameAndTypeCombo(mdName);
+ md.id((short) 1);
+ md.addToMaintenanceAssociation(ma1100);
+
+ MefCfm mefCfm = new DefaultMefCfm();
+ mefCfm.addToMaintenanceDomain(md);
+ MseaCfmOpParam mseaCfm = new MseaCfmOpParam();
+ mseaCfm.mefCfm(mefCfm);
+
+ try {
+ boolean deleted = mseaCfmService.deleteMseaMep(mseaCfm, session, DatastoreId.RUNNING);
+ assertTrue(deleted);
+ } catch (NetconfException e) {
+ e.printStackTrace();
+ fail();
+ } catch (CfmConfigException e) {
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+ /**
+ * Using mep Id 10.
+ */
+ @Test
+ public void testDeleteMseaMa() {
+ MaintenanceAssociation ma1300 = new DefaultMaintenanceAssociation();
+ NamePrimaryVid pvid1300Name = new DefaultNamePrimaryVid();
+ pvid1300Name.namePrimaryVid(NamePrimaryVidUnion.fromString("1300"));
+ ma1300.id((short) 1300);
+ ma1300.maNameAndTypeCombo(pvid1300Name);
+
+ MaintenanceDomain md = new DefaultMaintenanceDomain();
+ NameCharacterString mdName = new DefaultNameCharacterString();
+ mdName.name(new Identifier45("md-13"));
+ md.mdNameAndTypeCombo(mdName);
+ md.id((short) 13);
+ md.addToMaintenanceAssociation(ma1300);
+
+ MefCfm mefCfm = new DefaultMefCfm();
+ mefCfm.addToMaintenanceDomain(md);
+ MseaCfmOpParam mseaCfm = new MseaCfmOpParam();
+ mseaCfm.mefCfm(mefCfm);
+
+ try {
+ boolean deleted = mseaCfmService.deleteMseaMa(mseaCfm, session, DatastoreId.RUNNING);
+ assertTrue(deleted);
+ } catch (NetconfException e) {
+ e.printStackTrace();
+ fail();
+ } catch (CfmConfigException e) {
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+
+ @Test
+ public void testDeleteMseaRemoteMep() {
+ MaintenanceAssociation ma1100 = new DefaultMaintenanceAssociation();
+ NamePrimaryVid pvid1100Name = new DefaultNamePrimaryVid();
+ pvid1100Name.namePrimaryVid(NamePrimaryVidUnion.fromString("1100"));
+ ma1100.maNameAndTypeCombo(pvid1100Name);
+ ma1100.id((short) 1100);
+ ma1100.addToRemoteMeps(MepIdType.of(100));
+ ma1100.addToRemoteMeps(MepIdType.of(101));
+
+ MaintenanceDomain md = new DefaultMaintenanceDomain();
+ NameCharacterString mdName = new DefaultNameCharacterString();
+ mdName.name(new Identifier45("md-1"));
+ md.mdNameAndTypeCombo(mdName);
+ md.id((short) 1);
+ md.addToMaintenanceAssociation(ma1100);
+
+ MefCfm mefCfm = new DefaultMefCfm();
+ mefCfm.addToMaintenanceDomain(md);
+ MseaCfmOpParam mseaCfm = new MseaCfmOpParam();
+ mseaCfm.mefCfm(mefCfm);
+
+ try {
+ boolean deleted = mseaCfmService.deleteMseaMaRMep(mseaCfm, session, DatastoreId.RUNNING);
+ assertTrue(deleted);
+ } catch (NetconfException e) {
+ e.printStackTrace();
+ fail();
+ } catch (CfmConfigException e) {
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+ /**
+ * Using mep Id 10.
+ */
+ @Test
+ public void testDeleteMseaMdById() {
+
+ MaintenanceDomain md = new DefaultMaintenanceDomain();
+ NameDomainName mdName = new DefaultNameDomainName();
+ mdName.nameDomainName(NameDomainNameUnion.fromString("www.opennetworking.org"));
+ md.mdNameAndTypeCombo(mdName);
+ md.id((short) 10);
+
+ MefCfm mefCfm = new DefaultMefCfm();
+ mefCfm.addToMaintenanceDomain(md);
+ MseaCfmOpParam mseaCfm = new MseaCfmOpParam();
+ mseaCfm.mefCfm(mefCfm);
+
+ try {
+ boolean deleted = mseaCfmService.deleteMseaMd(mseaCfm, session, DatastoreId.RUNNING);
+ assertTrue(deleted);
+ } catch (NetconfException e) {
+ e.printStackTrace();
+ fail();
+ } catch (CfmConfigException e) {
+ e.printStackTrace();
+ fail();
+ }
+ }
+
+ /**
+ * Using mep Id 10.
+ */
+ @Test
+ public void testDeleteMseaMdByName() {
+
+ MaintenanceDomain md = new DefaultMaintenanceDomain();
+ NameDomainName mdName = new DefaultNameDomainName();
+ mdName.nameDomainName(NameDomainNameUnion.fromString("www.opennetworking.org"));
+ md.mdNameAndTypeCombo(mdName);
+
+ MefCfm mefCfm = new DefaultMefCfm();
+ mefCfm.addToMaintenanceDomain(md);
+ MseaCfmOpParam mseaCfm = new MseaCfmOpParam();
+ mseaCfm.mefCfm(mefCfm);
+
+ try {
+ mseaCfmService.deleteMseaMd(mseaCfm, session, DatastoreId.RUNNING);
+ fail("Should not have succeeded as no numeric id was given");
+ } catch (NetconfException | CfmConfigException e) {
+ assertEquals("An MD numeric ID must be given", e.getMessage());
+ }
+ }
+
+
/**
* Using Remote remote MEP ID and all arguments.
*/
+ @Test
public void testTransmitLoopback1() {
TransmitLoopbackInput lbTr1 = new DefaultTransmitLoopbackInput();
lbTr1.maintenanceDomain(Short.valueOf((short) 1));
@@ -221,10 +395,10 @@
}
}
- @Test
/**
* Using Remote Mac address in place of remote MEP ID and fewer arguments.
*/
+ @Test
public void testTransmitLoopback2() {
TransmitLoopbackInput lbTr2 = new DefaultTransmitLoopbackInput();
diff --git a/drivers/netconf/src/main/java/org/onosproject/drivers/netconf/NetconfControllerConfig.java b/drivers/netconf/src/main/java/org/onosproject/drivers/netconf/NetconfControllerConfig.java
index 70f01a6..c6a4134 100644
--- a/drivers/netconf/src/main/java/org/onosproject/drivers/netconf/NetconfControllerConfig.java
+++ b/drivers/netconf/src/main/java/org/onosproject/drivers/netconf/NetconfControllerConfig.java
@@ -96,6 +96,7 @@
);
} catch (NetconfException e) {
log.error("Cannot comunicate to device {} , exception {}", deviceId, e.getMessage());
+ return;
}
device.getSession().editConfig(config.substring(config.indexOf("-->") + 3));
} catch (NullPointerException e) {
diff --git a/drivers/optical/src/main/resources/optical-drivers.xml b/drivers/optical/src/main/resources/optical-drivers.xml
index 743cbd5..25be1a3 100644
--- a/drivers/optical/src/main/resources/optical-drivers.xml
+++ b/drivers/optical/src/main/resources/optical-drivers.xml
@@ -102,6 +102,7 @@
<!-- TODO use OF1.4 reported information when ready -->
<behaviour api="org.onosproject.net.behaviour.LambdaQuery"
impl="org.onosproject.driver.optical.query.ConfigLambdaQuery"/>
+ <property name="meterCapable">false</property>
</driver>
<driver name="optical-config" manufacturer="config" hwVersion="config" swVersion="config">
diff --git a/drivers/optical/src/test/java/org/onosproject/driver/optical/config/FlowTableConfigTest.java b/drivers/optical/src/test/java/org/onosproject/driver/optical/config/FlowTableConfigTest.java
index b6e6d95..0dbdbcc 100644
--- a/drivers/optical/src/test/java/org/onosproject/driver/optical/config/FlowTableConfigTest.java
+++ b/drivers/optical/src/test/java/org/onosproject/driver/optical/config/FlowTableConfigTest.java
@@ -51,11 +51,11 @@
private static final DeviceId DID = DeviceId.deviceId("of:0000000000000001");
private static final PortNumber PN_1 = portNumber(1);
private static final PortNumber PN_2 = portNumber(2);
- private static final int FLOW_ID_3 = 3;
+ private static final long FLOW_ID_3 = 3;
private static final int PRIO_4 = 4;
private static final DefaultApplicationId APP_ID =
- new DefaultApplicationId(FLOW_ID_3 >>> 48, "test");
+ new DefaultApplicationId((int) (FLOW_ID_3 >>> 48), "test");
private static final OchSignal LAMBDA_42 = OchSignal.newFlexGridSlot(42);
diff --git a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimePacketProgrammable.java b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimePacketProgrammable.java
index e21dd19..6c61148 100644
--- a/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimePacketProgrammable.java
+++ b/drivers/p4runtime/src/main/java/org/onosproject/drivers/p4runtime/P4RuntimePacketProgrammable.java
@@ -37,7 +37,7 @@
final PiPipelineInterpreter interpreter = device.is(PiPipelineInterpreter.class)
? device.as(PiPipelineInterpreter.class) : null;
- if (!device.is(PiPipelineInterpreter.class)) {
+ if (interpreter == null) {
log.warn("Device {} with pipeconf {} has no interpreter, aborting emit operation", deviceId, pipeconf.id());
return;
}
diff --git a/drivers/utilities/src/main/java/org/onosproject/drivers/utilities/YangXmlUtils.java b/drivers/utilities/src/main/java/org/onosproject/drivers/utilities/YangXmlUtils.java
index bb4dfa5..08ef181 100644
--- a/drivers/utilities/src/main/java/org/onosproject/drivers/utilities/YangXmlUtils.java
+++ b/drivers/utilities/src/main/java/org/onosproject/drivers/utilities/YangXmlUtils.java
@@ -195,7 +195,7 @@
*
* @return instance of YangXmlUtils
*/
- public static YangXmlUtils getInstance() {
+ public static synchronized YangXmlUtils getInstance() {
if (instance == null) {
instance = new YangXmlUtils();
}
diff --git a/features/features.xml b/features/features.xml
index d3f395e..567eda2 100644
--- a/features/features.xml
+++ b/features/features.xml
@@ -59,7 +59,7 @@
<bundle>mvn:com.typesafe/config/1.2.1</bundle>
<bundle>mvn:com.googlecode.concurrent-trees/concurrent-trees/2.6.0</bundle>
<bundle>mvn:commons-io/commons-io/2.4</bundle>
- <bundle>mvn:io.atomix/atomix/2.0.12</bundle>
+ <bundle>mvn:io.atomix/atomix/2.0.14</bundle>
<bundle>mvn:org.glassfish.jersey.core/jersey-client/2.25.1</bundle>
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/DefaultAlarm.java b/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/DefaultAlarm.java
index 1422dde..fd4bad0 100644
--- a/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/DefaultAlarm.java
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/faultmanagement/alarm/DefaultAlarm.java
@@ -427,8 +427,6 @@
checkNotNull(id, "Must specify an alarm id");
checkNotNull(deviceId, "Must specify a device");
checkNotNull(description, "Must specify a description");
- checkNotNull(timeRaised, "Must specify a time raised");
- checkNotNull(timeUpdated, "Must specify a time updated");
checkNotNull(severity, "Must specify a severity");
return new DefaultAlarm(id, deviceId, description, source, timeRaised, timeUpdated, timeCleared,
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
index 5d827f6..38c3d6f 100644
--- 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
@@ -213,6 +213,12 @@
}
@Override
+ public MaBuilder removeFromRemoteMepIdList(MepId remoteMep) {
+ this.remoteMepIdList.remove(remoteMep);
+ return this;
+ }
+
+ @Override
public MaBuilder ccmInterval(CcmInterval ccmInterval) {
this.ccmInterval = ccmInterval;
return 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
index f6e1f3c..37c1a84 100644
--- 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
@@ -113,6 +113,8 @@
MaBuilder addToRemoteMepIdList(MepId remoteMep);
+ MaBuilder removeFromRemoteMepIdList(MepId remoteMep);
+
MaBuilder addToComponentList(Component component);
MaBuilder maNumericId(short maNumericId);
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MepKeyId.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MepKeyId.java
new file mode 100644
index 0000000..afb337b
--- /dev/null
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/identifier/MepKeyId.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.identifier;
+
+import org.onosproject.incubator.net.l2monitoring.cfm.Mep;
+
+/**
+ * Immutable class to represent a unique identifier of a Mep.
+ */
+public class MepKeyId {
+ private MdId mdId;
+ private MaIdShort maId;
+ private MepId mepId;
+
+ public MepKeyId(MdId mdId, MaIdShort maId, MepId mepId) {
+ this.mdId = mdId;
+ this.maId = maId;
+ this.mepId = mepId;
+ if (mdId == null || maId == null || mepId == null) {
+ throw new IllegalArgumentException("Arguments to MepKeyId constructor cannot be null");
+ }
+ }
+
+ public MepKeyId(Mep mep) {
+ this.mdId = mep.mdId();
+ this.maId = mep.maId();
+ this.mepId = mep.mepId();
+ }
+
+ public MdId mdId() {
+ return mdId;
+ }
+
+ public MaIdShort maId() {
+ return maId;
+ }
+
+ public MepId mepId() {
+ return mepId;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ MepKeyId mepKeyId = (MepKeyId) o;
+
+ if (mdId != null ? !mdId.equals(mepKeyId.mdId) : mepKeyId.mdId != null) {
+ return false;
+ }
+ if (maId != null ? !maId.equals(mepKeyId.maId) : mepKeyId.maId != null) {
+ return false;
+ }
+ return mepId != null ? mepId.equals(mepKeyId.mepId) : mepKeyId.mepId == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = mdId != null ? mdId.hashCode() : 0;
+ result = 31 * result + (maId != null ? maId.hashCode() : 0);
+ result = 31 * result + (mepId != null ? mepId.hashCode() : 0);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return mdId.mdName() + "/" + maId.maName() + "/" + mepId();
+ }
+}
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
index 9c9aa46..b495eb9 100644
--- 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
@@ -18,6 +18,7 @@
import java.util.Collection;
import java.util.Optional;
+import org.onosproject.event.ListenerService;
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;
@@ -26,7 +27,7 @@
/**
* For the management of Maintenance Domains and Maintenance Associations.
*/
-public interface CfmMdService {
+public interface CfmMdService extends ListenerService<MdEvent, MdListener> {
/**
* Get a list of all of the Maintenance Domains on the system.
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
index 26abc45..cb96b52 100644
--- 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
@@ -16,12 +16,12 @@
package org.onosproject.incubator.net.l2monitoring.cfm.service;
import org.onosproject.event.AbstractEvent;
-import org.onosproject.incubator.net.l2monitoring.cfm.Mep;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepKeyId;
/**
* Event related to the maintenance of CFM MEPs.
*/
-public class CfmMepEvent extends AbstractEvent<CfmMepEvent.Type, Mep> {
+public class CfmMepEvent extends AbstractEvent<CfmMepEvent.Type, MepKeyId> {
/**
* Type of Mep events.
@@ -52,10 +52,9 @@
* 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
+ * @param mepKeyId event Mep subject
*/
- protected CfmMepEvent(Type type, Mep mep) {
- super(type, mep);
- // TODO Auto-generated constructor stub
+ public CfmMepEvent(Type type, MepKeyId mepKeyId) {
+ super(type, mepKeyId);
}
}
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
index b92777b..1b902cb 100644
--- 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
@@ -15,14 +15,95 @@
*/
package org.onosproject.incubator.net.l2monitoring.cfm.service;
+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.identifier.MepId;
import org.onosproject.net.driver.HandlerBehaviour;
+import java.util.Optional;
+
/**
* 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
+ * {@link CfmMepServiceBase} so reuse that
*/
-public interface CfmMepProgrammable extends HandlerBehaviour, CfmMepService {
+public interface CfmMepProgrammable extends HandlerBehaviour, CfmMepServiceBase {
+
+
+ /**
+ * Allows an MD and children MAs to be created on a device.
+ * A convenience method that allows an MD to be created on a device
+ * This is a preparation mechanism. If this was not called the MD would be created
+ * at the time of provisioning a MEP anyway
+ * @param mdId The ID of the MD to create - the details will be got from the CfmMdService
+ * @return true when created. false if it already existed
+ * @throws CfmConfigException If the MD already exists
+ */
+ boolean createMdOnDevice(MdId mdId) throws CfmConfigException;
+
+ /**
+ * Allows an MA to be created on an existing MD on a device.
+ * A convenience method that allows an MA to be created
+ * This is a preparation mechanism. If this was not called the MA would be created
+ * at the time of provisioning a MEP anyway. Also MAs can be created when they
+ * are contained in an MD using the createMdOnDevice method
+ * @param mdId The identifier of the MD to create the MA in
+ * @param maId The identifier of the MA to create - the details will be retrieved from the CfmMdService
+ * @return true when created. false if it already existed
+ * @throws CfmConfigException If the MD already exists
+ */
+ boolean createMaOnDevice(MdId mdId, MaIdShort maId) throws CfmConfigException;
+
+ /**
+ * Allows a MD and its MAs to be deleted from a device.
+ * A convenience method that allows an MD that has been provisioned on a
+ * device to be removed.
+ * All Meps must be removed first unless they are Meps unknown to ONOS.
+ * This is a cleanup mechanism. Deleting Meps in the normal way does not celan
+ * up MDs and MAs
+ * @param mdId The identifier of the MD
+ * @param oldMd The MaintenanceDomain that is being deleted
+ * @return true when deleted. false if it did not exist
+ * @throws CfmConfigException If the MD has any MAs that have MEPs then this will fail
+ */
+ boolean deleteMdOnDevice(MdId mdId, Optional<MaintenanceDomain> oldMd) throws CfmConfigException;
+
+ /**
+ * Allows an MA to be deleted from an MD on a device.
+ * A convenience method that allows an MA that has been provisioned on a
+ * device to be removed.
+ * All Meps must be removed first unless they are Meps unknown to ONOS.
+ * This is a cleanup mechanism. Deleting Meps in the normal way does not celan
+ * up MDs and MAs
+ * @param mdId The identifier of the MD
+ * @param maId The identifier of the MA
+ * @param oldMd The MaintenanceDomain from which the MA is being deleted
+ * @return true when deleted. false if it did not exist
+ * @throws CfmConfigException If the MA has any MEPs then this will fail
+ */
+ boolean deleteMaOnDevice(MdId mdId, MaIdShort maId,
+ Optional<MaintenanceDomain> oldMd) throws CfmConfigException;
+
+ /**
+ * Creates a Remote Mep entry on an MA.
+ * @param mdId The identifier of the MD
+ * @param maId The identifier of the MA
+ * @param remoteMep The remote Mep Id to remove from the MA
+ * @return true when deleted. false if it did not exist
+ * @throws CfmConfigException If the MA does not exist this will fail
+ */
+ boolean createMaRemoteMepOnDevice(MdId mdId, MaIdShort maId, MepId remoteMep) throws CfmConfigException;
+
+ /**
+ * Deletes a Remote Mep entry on an MA.
+ * @param mdId The identifier of the MD
+ * @param maId The identifier of the MA
+ * @param remoteMep The remote Mep Id to remove from the MA
+ * @return true when deleted. false if it did not exist
+ * @throws CfmConfigException If the MA does not exist this will fail
+ */
+ boolean deleteMaRemoteMepOnDevice(MdId mdId, MaIdShort maId, MepId remoteMep) throws CfmConfigException;
}
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
index c0c2f92..c774c65 100644
--- 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
@@ -17,13 +17,12 @@
import java.util.Collection;
+import org.onosproject.event.ListenerService;
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.net.DeviceId;
/**
* For the management of Maintenance Association Endpoints.
@@ -31,7 +30,8 @@
* These are dependent on the Maintenance Domain service which maintains the
* Maintenance Domain and Maintenance Associations
*/
-public interface CfmMepService {
+public interface CfmMepService
+ extends ListenerService<CfmMepEvent, CfmMepListener>, CfmMepServiceBase {
/**
* Retrieve all {@link org.onosproject.incubator.net.l2monitoring.cfm.MepEntry}(s) belonging to an MA.
* @param mdName A Maintenance Domain
@@ -43,67 +43,13 @@
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
+ * Retrieve all {@link org.onosproject.incubator.net.l2monitoring.cfm.Mep}(s) belonging to an MA.
+ * Note: This just returns the configuration part of the Mep, not the MepEntry
+ * which contains config and state
+ * @param deviceId A device id
+ * @return A collection of MEP Entries
* @throws CfmConfigException If there a problem with the MD or MA
*/
- boolean deleteMep(MdId mdName, MaIdShort maName, MepId mepId)
+ Collection<Mep> getAllMepsByDevice(DeviceId deviceId)
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/CfmMepServiceBase.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/CfmMepServiceBase.java
new file mode 100644
index 0000000..71e5611
--- /dev/null
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/CfmMepServiceBase.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.service;
+
+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.MaIdShort;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MdId;
+import org.onosproject.incubator.net.l2monitoring.cfm.identifier.MepId;
+
+import java.util.Optional;
+
+public interface CfmMepServiceBase {
+ /**
+ * 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
+ * @param oldMd The MaintenanceDomain from which the MEP is being deleted
+ * @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, Optional<MaintenanceDomain> oldMd)
+ 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 True if it was created successfully. False 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
index e3090f7..49023d4 100644
--- 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
@@ -15,24 +15,78 @@
*/
package org.onosproject.incubator.net.l2monitoring.cfm.service;
+import com.google.common.base.MoreObjects;
+import org.onlab.util.Tools;
import org.onosproject.event.AbstractEvent;
+import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMaintenanceDomain;
+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 java.util.Optional;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
/**
* Event related to the maintenance of CFM MDs.
*/
public class MdEvent extends AbstractEvent<MdEvent.Type, MdId> {
+ private MaIdShort maId;
+ private MaintenanceDomain oldMd;
/**
* MD Event types supported.
*/
public enum Type {
MD_ADDED,
MD_REMOVED,
- MD_UPDATED
+ MD_UPDATED,
+ MA_ADDED,
+ MA_REMOVED
}
public MdEvent(Type type, MdId mdId) {
super(type, mdId);
}
+
+ /**
+ * Constructor that allows the MD to be held in the event.
+ * This is useful if the MD had been deleted - it will be the only way of
+ * retrieving some of its attributes
+ * @param type The type of the event
+ * @param mdId The ID of the MD
+ * @param md The whole MD
+ * @throws CfmConfigException if there's a problem copying MD
+ */
+ public MdEvent(Type type, MdId mdId, MaintenanceDomain md) throws CfmConfigException {
+ super(type, mdId);
+ this.oldMd = DefaultMaintenanceDomain.builder(md).build();
+ }
+
+ public MdEvent(Type type, MdId mdId, MaintenanceDomain md, MaIdShort maId)
+ throws CfmConfigException {
+ super(type, mdId);
+ this.maId = maId;
+ this.oldMd = DefaultMaintenanceDomain.builder(md).build();
+ }
+
+ public Optional<MaIdShort> maId() {
+ return maId == null ? Optional.empty() : Optional.of(maId);
+ }
+
+ public Optional<MaintenanceDomain> md() {
+ return oldMd == null ? Optional.empty() : Optional.of(oldMd);
+ }
+
+ @Override
+ public String toString() {
+ MoreObjects.ToStringHelper helper = toStringHelper(this)
+ .add("time", Tools.defaultOffsetDataTime(time()))
+ .add("type", type())
+ .add("subject", subject());
+ if (maId != null) {
+ helper = helper.add("subject2", maId);
+ }
+ return helper.toString();
+ }
}
diff --git a/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/MepStore.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/MepStore.java
new file mode 100644
index 0000000..ed4bb35
--- /dev/null
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/MepStore.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2018-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.Mep;
+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.MepKeyId;
+import org.onosproject.net.DeviceId;
+import org.onosproject.store.Store;
+
+import java.util.Collection;
+import java.util.Optional;
+
+/**
+ * {@link org.onosproject.incubator.net.l2monitoring.cfm.Mep Maintenance Association Endpoint's} storage interface.
+ * Note: because the Mep is immutable if anything needs to be
+ * changed in it, then it must be replaced in the store.
+ */
+public interface MepStore extends Store<CfmMepEvent, MepStoreDelegate> {
+ /**
+ * Get a list of all of the Meps on the system.
+ * @return A collection Meps from the Mep Store.
+ */
+ Collection<Mep> getAllMeps();
+
+ /**
+ * Get all Meps by MD.
+ * @param mdName An identifier for the Maintenance Domain
+ * @return MEPs from the MEP Store. Empty if not found.
+ */
+ Collection<Mep> getMepsByMd(MdId mdName);
+
+ /**
+ * Get all Meps by MD, MA.
+ * @param mdName An identifier for the Maintenance Domain
+ * @param maName An identifier for the Maintenance Association
+ * @return MEPs from the MEP Store. Empty if not found.
+ */
+ Collection<Mep> getMepsByMdMa(MdId mdName, MaIdShort maName);
+
+ /**
+ * Get all Meps by DeviceId.
+ * @param deviceId An identifier for the Device
+ * @return MEPs from the MEP Store. Empty if not found.
+ */
+ Collection<Mep> getMepsByDeviceId(DeviceId deviceId);
+
+ /**
+ * Get a specific Mep by its Mep key id.
+ * @param mepKeyId An unique identifier for the MEP
+ * @return A MEP from the MEP Store. Empty if not found.
+ */
+ Optional<Mep> getMep(MepKeyId mepKeyId);
+
+ /**
+ * Delete a specific Mep by its identifier.
+ * @param mepKeyId An unique identifier for the MEP
+ * @return True if the Mep was found and deleted
+ */
+ boolean deleteMep(MepKeyId mepKeyId);
+
+ /**
+ * Create or replace a Mep.
+ * @param mepKeyId An unique identifier for the MEP
+ * @param mep The new MEP
+ * @return true if an Mep of this name already existed
+ */
+ boolean createUpdateMep(MepKeyId mepKeyId, Mep mep);
+
+}
diff --git a/apps/restconf/utils/src/main/java/org/onosproject/restconf/utils/exceptions/package-info.java b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/MepStoreDelegate.java
similarity index 68%
copy from apps/restconf/utils/src/main/java/org/onosproject/restconf/utils/exceptions/package-info.java
copy to incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/MepStoreDelegate.java
index a0fe88e..6d5dfd3 100644
--- a/apps/restconf/utils/src/main/java/org/onosproject/restconf/utils/exceptions/package-info.java
+++ b/incubator/api/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/service/MepStoreDelegate.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2017-present Open Networking Foundation
+ * Copyright 2018-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.
@@ -13,8 +13,12 @@
* 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;
/**
- * Parse utils custom exceptions.
+ * Delegate for MEP Store.
*/
-package org.onosproject.restconf.utils.exceptions;
\ No newline at end of file
+public interface MepStoreDelegate extends StoreDelegate<CfmMepEvent> {
+}
diff --git a/incubator/net/src/main/java/org/onosproject/incubator/net/dpi/impl/DpiStatisticsManager.java b/incubator/net/src/main/java/org/onosproject/incubator/net/dpi/impl/DpiStatisticsManager.java
index 10f82b4..b49c9cb 100644
--- a/incubator/net/src/main/java/org/onosproject/incubator/net/dpi/impl/DpiStatisticsManager.java
+++ b/incubator/net/src/main/java/org/onosproject/incubator/net/dpi/impl/DpiStatisticsManager.java
@@ -67,7 +67,7 @@
@Service
public class DpiStatisticsManager implements DpiStatisticsManagerService {
- private static ServerSocket serverSocket;
+ private ServerSocket serverSocket;
private static int port = 11990; // socket server listening port
private final Logger log = getLogger(getClass());
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
index 5a125f5..b18d2f6 100644
--- 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
@@ -65,10 +65,8 @@
@Activate
public void activate() {
appId = coreService.registerApplication(APP_ID);
-
eventDispatcher.addSink(MdEvent.class, listenerRegistry);
store.setDelegate(delegate);
-
log.info("CFM Service Started");
}
@@ -163,9 +161,8 @@
private class InternalStoreDelegate implements MdStoreDelegate {
@Override
public void notify(MdEvent event) {
- log.debug("New MD event: {}", event.subject());
+ log.debug("New MD event: {}", event);
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
index 5723466..e58a570 100644
--- 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
@@ -15,10 +15,21 @@
*/
package org.onosproject.incubator.net.l2monitoring.cfm.impl;
+import static org.onlab.util.Tools.groupedThreads;
import static org.slf4j.LoggerFactory.getLogger;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
@@ -29,6 +40,8 @@
import org.onosproject.core.CoreService;
import org.onosproject.core.IdGenerator;
import org.onosproject.event.AbstractListenerManager;
+import org.onosproject.event.Event;
+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;
@@ -36,12 +49,17 @@
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.identifier.MepKeyId;
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.incubator.net.l2monitoring.cfm.service.MdEvent;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.MdListener;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.MepStore;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.MepStoreDelegate;
import org.onosproject.mastership.MastershipService;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
@@ -61,7 +79,8 @@
private final Logger log = getLogger(getClass());
- private final DeviceListener deviceListener = new InternalDeviceListener();
+ private InternalDeviceListener deviceListener = null;
+ private InternalMdListener mdListener = null;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected DeviceService deviceService;
@@ -78,22 +97,39 @@
private static final int DEFAULT_POLL_FREQUENCY = 30;
private int fallbackMepPollFrequency = DEFAULT_POLL_FREQUENCY;
+ private InternalEventHandler eventHandler = new InternalEventHandler();
+ private static final Object THREAD_SCHED_LOCK = new Object();
+ private static int numOfEventsQueued = 0;
+ private static int numOfEventsExecuted = 0;
+ private static int numOfHandlerExecution = 0;
+ private static int numOfHandlerScheduled = 0;
+
+ private ScheduledExecutorService executorService = Executors
+ .newScheduledThreadPool(1,
+ groupedThreads("CfmMepManager", "event-%d", log));
+
+ @SuppressWarnings("unused")
+ private static ScheduledFuture<?> eventHandlerFuture = null;
+ @SuppressWarnings("rawtypes")
+ private ConcurrentLinkedQueue<Event> eventQueue = new ConcurrentLinkedQueue<>();
+
+
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<Mep> mepCollection;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected MepStore mepStore;
+ protected final MepStoreDelegate delegate = new InternalStoreDelegate();
@Activate
public void activate() {
- //FIXME Get rid of this local list
- mepCollection = new ArrayList<>();
+ mepStore.setDelegate(delegate);
- eventDispatcher.addSink(CfmMepEvent.class, listenerRegistry);
+ deviceListener = new InternalDeviceListener();
deviceService.addListener(deviceListener);
+ mdListener = new InternalMdListener();
+ cfmMdService.addListener(mdListener);
+ eventDispatcher.addSink(CfmMepEvent.class, listenerRegistry);
idGenerator = coreService.getIdGenerator("mep-ids");
log.info("CFM MEP Manager Started");
}
@@ -101,9 +137,12 @@
@Deactivate
public void deactivate() {
deviceService.removeListener(deviceListener);
+ cfmMdService.removeListener(mdListener);
eventDispatcher.removeSink(CfmMepEvent.class);
log.info("CFM MEP Manager Stopped");
- mepCollection.clear();
+ mepStore.unsetDelegate(delegate);
+ deviceListener = null;
+ mdListener = null;
}
@Override
@@ -112,27 +151,28 @@
//Will throw IllegalArgumentException if ma does not exist
cfmMdService.getMaintenanceAssociation(mdName, maName);
+ Collection<Mep> mepStoreCollection = mepStore.getAllMeps();
Collection<MepEntry> mepEntryCollection = new ArrayList<>();
- for (Mep mep:mepCollection) {
+ for (Mep mep : mepStoreCollection) {
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());
+ " for MEP: " + mdName + "/" + maName + "/" + mep.mepId());
continue;
} else if (!deviceService.getDevice(mepDeviceId)
- .is(CfmMepProgrammable.class)) {
+ .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);
+ + "on Device {}", mep.mepId(), mdName, maName, mepDeviceId);
mepEntryCollection.add(deviceService
- .getDevice(mepDeviceId)
- .as(CfmMepProgrammable.class)
- .getMep(mdName, maName, mep.mepId()));
+ .getDevice(mepDeviceId)
+ .as(CfmMepProgrammable.class)
+ .getMep(mdName, maName, mep.mepId()));
}
}
@@ -140,75 +180,116 @@
}
@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;
+ public Collection<Mep> getAllMepsByDevice(DeviceId deviceId) throws CfmConfigException {
+ return mepStore.getMepsByDeviceId(deviceId);
}
@Override
- public boolean deleteMep(MdId mdName, MaIdShort maName, MepId mepId) throws CfmConfigException {
+ public MepEntry getMep(MdId mdName, MaIdShort maName, MepId mepId) throws CfmConfigException {
+ MepKeyId key = new MepKeyId(mdName, maName, mepId);
+
//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;
+ Optional<Mep> mepOptional = mepStore.getMep(key);
+ if (mepOptional.isPresent()) {
+ Mep mep = mepOptional.get();
+ 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);
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public boolean deleteMep(MdId mdName, MaIdShort maName, MepId mepId,
+ Optional<MaintenanceDomain> oldMd) throws CfmConfigException {
+ MepKeyId key = new MepKeyId(mdName, maName, mepId);
+
+ //Will throw IllegalArgumentException if ma does not exist
+ cfmMdService.getMaintenanceAssociation(mdName, maName);
+
+ //Get the device ID from the MEP
+ Optional<Mep> deletedMep = mepStore.getMep(key);
+ if (!deletedMep.isPresent()) {
+ log.warn("MEP {} not found when deleting Mep", key);
+ return false;
+ }
+
+ DeviceId mepDeviceId = deletedMep.get().deviceId();
+ boolean deleted = mepStore.deleteMep(key);
+
+ Device mepDevice = deviceService.getDevice(mepDeviceId);
+ if (mepDevice == null || !mepDevice.is(CfmMepProgrammable.class)) {
+ throw new CfmConfigException("Unexpeced fault on device driver for "
+ + mepDeviceId);
+ }
+ try {
+ deleted = mepDevice.as(CfmMepProgrammable.class)
+ .deleteMep(mdName, maName, mepId, oldMd);
+ } catch (CfmConfigException e) {
+ log.warn("MEP could not be deleted on device - perhaps it "
+ + "does not exist. Continuing");
+ }
+
+ //Iterate through all other devices and remove as a Remote Mep
+ int mepsOnMdCount = 0;
+ int mepsOnMaCount = 0;
+ for (Mep mep : mepStore.getAllMeps()) {
+ if (mep.deviceId().equals(mepDeviceId) && mdName.equals(mep.mdId())) {
+ mepsOnMdCount++;
+ if (maName.equals(mep.maId())) {
+ mepsOnMaCount++;
}
}
+ List<DeviceId> alreadyHandledDevices = new ArrayList<>();
+ if (mep.deviceId().equals(mepDeviceId) || !mep.mdId().equals(mdName) ||
+ !mep.maId().equals(maName) ||
+ alreadyHandledDevices.contains(mep.deviceId())) {
+ continue;
+ }
+ deviceService.getDevice(mep.deviceId())
+ .as(CfmMepProgrammable.class)
+ .deleteMaRemoteMepOnDevice(mdName, maName, mepId);
+ alreadyHandledDevices.add(mep.deviceId());
+ log.info("Deleted RMep entry on {} on device {}",
+ mdName.mdName() + "/" + maName.maName(), mep.deviceId());
}
- return false;
+
+ //Also if this is the last MEP in this MA then delete this MA from device
+ //If this is the last MA in this MD on device, then delete the MD from the device
+ if (mepsOnMdCount == 0) {
+ boolean deletedMd = deviceService.getDevice(mepDeviceId)
+ .as(CfmMepProgrammable.class).deleteMdOnDevice(mdName, oldMd);
+ log.info("Deleted MD {} from Device {}", mdName.mdName(), mepDeviceId);
+ } else if (mepsOnMaCount == 0) {
+ boolean deletedMa = deviceService.getDevice(mepDeviceId)
+ .as(CfmMepProgrammable.class).deleteMaOnDevice(mdName, maName, oldMd);
+ log.info("Deleted MA {} from Device {}",
+ mdName.mdName() + "/" + maName.maName(), mepDeviceId);
+ }
+
+ return deleted;
}
@Override
public boolean createMep(MdId mdName, MaIdShort maName, Mep newMep) throws CfmConfigException {
+ MepKeyId key = new MepKeyId(mdName, maName, newMep.mepId());
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;
- }
+ if (mepStore.getMep(key).isPresent()) {
+ return false;
}
//Will throw IllegalArgumentException if ma does not exist
@@ -225,7 +306,24 @@
deviceService.getDevice(mepDeviceId).as(CfmMepProgrammable.class).createMep(mdName, maName, newMep);
log.debug("MEP created on {}", mepDeviceId);
if (deviceResult) {
- return mepCollection.add(newMep);
+ boolean alreadyExisted = mepStore.createUpdateMep(key, newMep);
+
+ //Add to other Remote Mep List on other devices
+ for (Mep mep:mepStore.getMepsByMdMa(mdName, maName)) {
+ List<DeviceId> alreadyHandledDevices = new ArrayList<>();
+ if (mep.deviceId().equals(mepDeviceId) ||
+ alreadyHandledDevices.contains(mep.deviceId())) {
+ continue;
+ }
+ boolean created = deviceService.getDevice(mep.deviceId())
+ .as(CfmMepProgrammable.class)
+ .createMaRemoteMepOnDevice(mdName, maName, newMep.mepId());
+ alreadyHandledDevices.add(mep.deviceId());
+ log.info("Created RMep entry on {} on device {}",
+ mdName.mdName() + "/" + maName.maName(), mep.deviceId());
+ }
+
+ return !alreadyExisted;
} else {
return deviceResult;
}
@@ -233,60 +331,253 @@
@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");
+ MepId mepId, MepLbCreate lbCreate) throws CfmConfigException {
+ MepKeyId key = new MepKeyId(mdName, maName, mepId);
+ Mep mep = mepStore.getMep(key)
+ .orElseThrow(() -> new CfmConfigException("Mep " + mdName + "/" + maName + "/"
+ + mepId + " not found when calling Transmit Loopback"));
+
+ log.debug("Transmitting Loopback on MEP {} on Device {}",
+ key, mep.deviceId());
+ deviceService.getDevice(mep.deviceId())
+ .as(CfmMepProgrammable.class)
+ .transmitLoopback(mdName, maName, mepId, lbCreate);
}
@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");
+
+ MepKeyId key = new MepKeyId(mdName, maName, mepId);
+ Mep mep = mepStore.getMep(key)
+ .orElseThrow(() -> new CfmConfigException("Mep " + mdName + "/" + maName + "/"
+ + mepId + " not found when calling Aborting Loopback"));
+
+ log.debug("Aborting Loopback on MEP {} on Device {}",
+ key, mep.deviceId());
+ deviceService.getDevice(mep.deviceId())
+ .as(CfmMepProgrammable.class)
+ .abortLoopback(mdName, maName, mepId);
}
@Override
public void transmitLinktrace(MdId mdName, MaIdShort maName, MepId mepId,
- MepLtCreate ltCreate) {
+ MepLtCreate ltCreate) {
throw new UnsupportedOperationException("Not yet implemented");
}
+ private class InternalMdListener implements MdListener {
+ @Override
+ public boolean isRelevant(MdEvent event) {
+ return event.type().equals(MdEvent.Type.MD_REMOVED) ||
+ event.type().equals(MdEvent.Type.MA_REMOVED);
+ }
+
+ @Override
+ public void event(MdEvent event) {
+ MdId mdName = event.subject();
+ switch (event.type()) {
+ case MA_REMOVED:
+ case MD_REMOVED:
+ log.trace("Event {} receieved from MD Service for {}", event.type(), mdName);
+ scheduleEventHandlerIfNotScheduled(event);
+ break;
+ default:
+ log.warn("Unhandled Event {} received from MD Service", event.type());
+ break;
+ }
+ }
+ }
+
private class InternalDeviceListener implements DeviceListener {
@Override
+ public boolean isRelevant(DeviceEvent event) {
+ return event.type().equals(DeviceEvent.Type.DEVICE_REMOVED);
+ }
+
+ @Override
public void event(DeviceEvent event) {
+ DeviceId deviceId = event.subject().id();
switch (event.type()) {
+ case DEVICE_ADDED:
+ case PORT_UPDATED:
+ case PORT_ADDED:
+ case DEVICE_UPDATED:
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);
- }
+ log.trace("Event {} received from Device Service", event.type());
+ scheduleEventHandlerIfNotScheduled(event);
break;
default:
+ log.warn("Unhandled Event {} received from Device Service", event.type());
break;
}
}
}
+
+ @SuppressWarnings("rawtypes")
+ private void scheduleEventHandlerIfNotScheduled(Event event) {
+ synchronized (THREAD_SCHED_LOCK) {
+ eventQueue.add(event);
+ numOfEventsQueued++;
+
+ if ((numOfHandlerScheduled - numOfHandlerExecution) == 0) {
+ //No pending scheduled event handling threads. So start a new one.
+ eventHandlerFuture = executorService
+ .schedule(eventHandler, 100, TimeUnit.MILLISECONDS);
+ numOfHandlerScheduled++;
+ }
+ log.trace("numOfEventsQueued {}, numOfEventHandlerScheduled {}",
+ numOfEventsQueued,
+ numOfHandlerScheduled);
+ }
+ }
+
+ private class InternalEventHandler implements Runnable {
+ @Override
+ public void run() {
+ try {
+ while (true) {
+ @SuppressWarnings("rawtypes")
+ Event event;
+ synchronized (THREAD_SCHED_LOCK) {
+ if (!eventQueue.isEmpty()) {
+ event = eventQueue.poll();
+ numOfEventsExecuted++;
+ } else {
+ numOfHandlerExecution++;
+ log.debug("numOfHandlerExecution {} numOfEventsExecuted {}",
+ numOfHandlerExecution, numOfEventsExecuted);
+ break;
+ }
+ }
+ if (event.type() == DeviceEvent.Type.DEVICE_REMOVED) {
+ DeviceId deviceId = ((Device) event.subject()).id();
+ log.info("Processing device removal event for unavailable device {}",
+ deviceId);
+ processDeviceRemoved((Device) event.subject());
+ } else if (event.type() == MdEvent.Type.MD_REMOVED) {
+ MdId mdName = (MdId) event.subject();
+ log.info("Processing MD removal event for MD {}",
+ mdName);
+ processMdRemoved(mdName, ((MdEvent) event).md().get());
+ } else if (event.type() == MdEvent.Type.MA_REMOVED) {
+ MdId mdName = (MdId) event.subject();
+ MaIdShort maName = ((MdEvent) event).maId().get();
+ log.info("Processing MA removal event for MA {}",
+ mdName.mdName() + "/" + maName.maName());
+ processMaRemoved(mdName, maName, ((MdEvent) event).md().get());
+ }
+ }
+ } catch (Exception e) {
+ log.error("CfmMepService event handler "
+ + "thread thrown an exception: {}", e);
+ }
+ }
+ }
+
+ /**
+ * This removes a MEP from the internal list of Meps, and updates remote meps list on other Meps.
+ * Note: This does not call the device's CfmMepProgrammable, because there
+ * would be no point as the device has already been removed from ONOS.
+ * The configuration for this MEP may still be present on the actual device, and
+ * any future config would have to be careful to wipe the Mep from the device
+ * before applying a Mep again
+ * @param removedDevice The device that has been removed
+ */
+ protected void processDeviceRemoved(Device removedDevice) {
+ log.warn("Remove Mep(s) associated with Device: " + removedDevice.id());
+ Collection<Mep> mepListForDevice = mepStore.getMepsByDeviceId(removedDevice.id());
+
+
+ for (Mep mep:mepStore.getAllMeps()) {
+ for (Mep mepForDevice:mepListForDevice) {
+ if (mep.mdId().equals(mepForDevice.mdId()) && mep.maId().equals(mepForDevice.maId())) {
+ Device mepDevice = deviceService.getDevice(mep.deviceId());
+ log.info("Removing Remote Mep {} from MA{} on device {}",
+ mepForDevice.mepId(),
+ mep.mdId().mdName() + "/" + mep.maId().maName(),
+ mepDevice.id());
+ try {
+ mepDevice.as(CfmMepProgrammable.class)
+ .deleteMaRemoteMepOnDevice(mep.mdId(), mep.maId(), mepForDevice.mepId());
+ } catch (CfmConfigException e) {
+ log.error("Error when removing Remote Mep {} from MA {}. Continuing.",
+ mep.mdId().mdName() + "/" + mep.maId().maName(),
+ mepForDevice.mepId());
+ }
+ }
+ }
+ }
+
+ for (Iterator<Mep> iter = mepListForDevice.iterator(); iter.hasNext();) {
+ mepStore.deleteMep(new MepKeyId(iter.next()));
+ }
+ }
+
+ protected void processMaRemoved(MdId mdId, MaIdShort maId, MaintenanceDomain oldMd) {
+ Set<DeviceId> deviceIdsRemoved = new HashSet<>();
+
+ for (Iterator<Mep> iter = mepStore.getMepsByMdMa(mdId, maId).iterator(); iter.hasNext();) {
+ Mep mepForMdMa = iter.next();
+ DeviceId mepDeviceId = mepForMdMa.deviceId();
+ try {
+ deviceService.getDevice(mepDeviceId).as(CfmMepProgrammable.class)
+ .deleteMep(mdId, maId, mepForMdMa.mepId(), Optional.of(oldMd));
+ deviceIdsRemoved.add(mepDeviceId);
+ } catch (CfmConfigException e) {
+ log.warn("Could not delete MEP {} from Device {}", mepForMdMa.mepId(), mepDeviceId, e);
+ }
+ iter.remove();
+
+ log.info("Removed MEP {} from Device {} because MA {} was deleted",
+ mepForMdMa.mepId(), mepDeviceId, mdId.mdName() + "/" + maId.maName());
+ }
+
+ deviceIdsRemoved.forEach(deviceId -> {
+ try {
+ deviceService.getDevice(deviceId).as(CfmMepProgrammable.class)
+ .deleteMaOnDevice(mdId, maId, Optional.of(oldMd));
+ } catch (CfmConfigException e) {
+ log.warn("Could not delete MA {} from Device {}",
+ mdId.mdName() + "/" + maId.maName(), deviceId, e);
+ }
+ });
+ }
+
+ protected void processMdRemoved(MdId mdId, MaintenanceDomain oldMd) {
+ Set<DeviceId> deviceIdsRemoved = new HashSet<>();
+ for (Iterator<Mep> iter = mepStore.getMepsByMd(mdId).iterator(); iter.hasNext();) {
+ Mep mep = iter.next();
+ DeviceId mepDeviceId = mep.deviceId();
+ try {
+ deviceService.getDevice(mepDeviceId).as(CfmMepProgrammable.class)
+ .deleteMep(mdId, mep.maId(), mep.mepId(), Optional.of(oldMd));
+ deviceIdsRemoved.add(mepDeviceId);
+ } catch (CfmConfigException e) {
+ log.warn("Could not delete MEP {} from Device {}", mep.mepId(), mepDeviceId, e);
+ }
+ iter.remove();
+ log.info("Removed MEP {} from Device {} because MD {} was deleted",
+ mep.mepId(), mepDeviceId, mdId.mdName());
+ }
+
+ deviceIdsRemoved.forEach(deviceId -> {
+ try {
+ deviceService.getDevice(deviceId).as(CfmMepProgrammable.class)
+ .deleteMdOnDevice(mdId, Optional.of(oldMd));
+ } catch (CfmConfigException e) {
+ log.warn("Could not delete MD {} from Device {}",
+ mdId.mdName(), deviceId, e);
+ }
+ });
+ }
+
+ private class InternalStoreDelegate implements MepStoreDelegate {
+ @Override
+ public void notify(CfmMepEvent event) {
+ log.debug("New Mep event: {}", event);
+ eventDispatcher.post(event);
+ }
+ }
}
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
index 964a56a..82c550d 100644
--- 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
@@ -19,6 +19,7 @@
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.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
@@ -42,6 +43,7 @@
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.MdEvent;
import org.onosproject.incubator.net.l2monitoring.cfm.service.MdStore;
import org.onosproject.incubator.net.l2monitoring.cfm.service.MdStoreDelegate;
@@ -58,6 +60,8 @@
import java.util.Collection;
import java.util.Map;
import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
/**
* Maintenance Domain Store implementation backed by consistent map.
@@ -75,7 +79,7 @@
private ConsistentMap<MdId, MaintenanceDomain> maintenanceDomainConsistentMap;
private Map<MdId, MaintenanceDomain> maintenanceDomainMap;
- private final InternalMdListener listener = new InternalMdListener();
+ private MapEventListener<MdId, MaintenanceDomain> mapListener = null;
@Activate
public void activate() {
@@ -112,8 +116,17 @@
.cfm.Component.TagType.class)
.build("md")))
.build();
+ mapListener = new InternalMdListener();
+ maintenanceDomainConsistentMap.addListener(mapListener);
maintenanceDomainMap = maintenanceDomainConsistentMap.asJavaMap();
+ log.info("MDStore started");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ maintenanceDomainConsistentMap.removeListener(mapListener);
+ log.info("Stopped");
}
@Override
@@ -141,19 +154,65 @@
@Override
public void event(MapEvent<MdId, MaintenanceDomain> mapEvent) {
final MdEvent.Type type;
+ MaIdShort maId = null;
switch (mapEvent.type()) {
case INSERT:
type = MdEvent.Type.MD_ADDED;
break;
case UPDATE:
- type = MdEvent.Type.MD_UPDATED;
+ // Examine the diff to see if it was a removal or addition of an MA caused it
+ if (mapEvent.oldValue().value().maintenanceAssociationList().size() >
+ mapEvent.newValue().value().maintenanceAssociationList().size()) {
+ Set<MaIdShort> newMaIds = mapEvent.newValue().value().maintenanceAssociationList()
+ .stream()
+ .map(MaintenanceAssociation::maId)
+ .collect(Collectors.toSet());
+ Optional<MaintenanceAssociation> removedMa =
+ mapEvent.oldValue().value().maintenanceAssociationList()
+ .stream()
+ .filter(maOld -> !newMaIds.contains(maOld.maId())).findFirst();
+ if (removedMa.isPresent()) {
+ maId = removedMa.get().maId();
+ }
+ type = MdEvent.Type.MA_REMOVED;
+ } else if (mapEvent.oldValue().value().maintenanceAssociationList().size() <
+ mapEvent.newValue().value().maintenanceAssociationList().size()) {
+ Set<MaIdShort> oldMaIds = mapEvent.oldValue().value().maintenanceAssociationList()
+ .stream()
+ .map(MaintenanceAssociation::maId)
+ .collect(Collectors.toSet());
+ Optional<MaintenanceAssociation> addedMa =
+ mapEvent.newValue().value().maintenanceAssociationList()
+ .stream()
+ .filter(maNew -> !oldMaIds.contains(maNew.maId())).findFirst();
+ if (addedMa.isPresent()) {
+ maId = addedMa.get().maId();
+ }
+ type = MdEvent.Type.MA_ADDED;
+ } else {
+ type = MdEvent.Type.MD_UPDATED;
+ }
break;
case REMOVE:
default:
type = MdEvent.Type.MD_REMOVED;
break;
}
- notifyDelegate(new MdEvent(type, mapEvent.key()));
+ if (mapEvent.oldValue() != null && mapEvent.oldValue().value() != null) {
+ MaintenanceDomain oldMd = mapEvent.oldValue().value();
+ try {
+ if (maId != null) {
+ notifyDelegate(new MdEvent(type, mapEvent.key(), oldMd, maId));
+ } else {
+ notifyDelegate(new MdEvent(type, mapEvent.key(), oldMd));
+ }
+ } catch (CfmConfigException e) {
+ log.warn("Unable to copy MD {}", oldMd);
+ notifyDelegate(new MdEvent(type, mapEvent.key()));
+ }
+ } else {
+ notifyDelegate(new MdEvent(type, mapEvent.key()));
+ }
}
}
}
diff --git a/incubator/net/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/impl/DistributedMepStore.java b/incubator/net/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/impl/DistributedMepStore.java
new file mode 100644
index 0000000..c21166a
--- /dev/null
+++ b/incubator/net/src/main/java/org/onosproject/incubator/net/l2monitoring/cfm/impl/DistributedMepStore.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.incubator.net.l2monitoring.cfm.impl;
+
+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.onlab.packet.IpAddress;
+import org.onlab.packet.VlanId;
+import org.onlab.util.KryoNamespace;
+import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMep;
+import org.onosproject.incubator.net.l2monitoring.cfm.Mep;
+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.identifier.MepKeyId;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepEvent;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.MepStore;
+import org.onosproject.incubator.net.l2monitoring.cfm.service.MepStoreDelegate;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.NetworkResource;
+import org.onosproject.net.PortNumber;
+import org.onosproject.store.AbstractStore;
+import org.onosproject.store.serializers.KryoNamespaces;
+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.time.Duration;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+/**
+ * MEP Store implementation backed by consistent map.
+ */
+@Component(immediate = true)
+@Service
+public class DistributedMepStore extends AbstractStore<CfmMepEvent, MepStoreDelegate>
+ implements MepStore {
+
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected StorageService storageService;
+
+ private ConsistentMap<MepKeyId, Mep> mepConsistentMap;
+ private Map<MepKeyId, Mep> mepMap;
+
+ private MapEventListener<MepKeyId, Mep> mapListener = null;
+
+ @Activate
+ public void activate() {
+ mepConsistentMap = storageService
+ .<MepKeyId, Mep>consistentMapBuilder()
+ .withName("onos-cfm-mep-map")
+ .withSerializer(Serializer.using(new KryoNamespace.Builder()
+ .register(KryoNamespaces.API)
+ .register(DefaultMep.class)
+ .register(MepId.class)
+ .register(MepKeyId.class)
+ .register(NetworkResource.class)
+ .register(DeviceId.class)
+ .register(PortNumber.class)
+ .register(Mep.MepDirection.class)
+ .register(VlanId.class)
+ .register(Mep.Priority.class)
+ .register(Mep.FngAddress.class)
+ .register(Mep.FngAddressType.class)
+ .register(IpAddress.class)
+ .register(Mep.LowestFaultDefect.class)
+ .register(Duration.class)
+ .register(MdIdCharStr.class)
+ .register(MdIdDomainName.class)
+ .register(MdIdMacUint.class)
+ .register(MdIdNone.class)
+ .register(MaIdCharStr.class)
+ .register(MaIdShort.class)
+ .register(MaId2Octet.class)
+ .register(MaIdIccY1731.class)
+ .register(MaIdPrimaryVid.class)
+ .register(MaIdRfc2685VpnId.class)
+ .build("mep")))
+ .build();
+ mapListener = new InternalMepListener();
+ mepConsistentMap.addListener(mapListener);
+
+ mepMap = mepConsistentMap.asJavaMap();
+ log.info("MepStore started");
+ }
+
+ @Deactivate
+ public void deactivate() {
+ mepConsistentMap.removeListener(mapListener);
+ log.info("MepStore stopped");
+ }
+
+ @Override
+ public Collection<Mep> getAllMeps() {
+ return mepMap.values();
+ }
+
+ @Override
+ public Collection<Mep> getMepsByMd(MdId mdName) {
+ return mepMap.values().stream()
+ .filter(mep -> mep.mdId().equals(mdName))
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public Collection<Mep> getMepsByMdMa(MdId mdName, MaIdShort maName) {
+ return mepMap.values().stream()
+ .filter(mep -> mep.mdId().equals(mdName) && mep.maId().equals(maName))
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public Collection<Mep> getMepsByDeviceId(DeviceId deviceId) {
+ return mepMap.values().stream()
+ .filter(mep -> mep.deviceId().equals(deviceId))
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public Optional<Mep> getMep(MepKeyId mepKeyId) {
+ return mepMap.values().stream()
+ .filter(mep -> mep.mdId().equals(mepKeyId.mdId()) &&
+ mep.maId().equals(mepKeyId.maId()) &&
+ mep.mepId().equals(mepKeyId.mepId()))
+ .findFirst();
+ }
+
+ @Override
+ public boolean deleteMep(MepKeyId mepKeyId) {
+ return mepMap.remove(mepKeyId) == null ? false : true;
+ }
+
+ @Override
+ public boolean createUpdateMep(MepKeyId mepKeyId, Mep mep) {
+ return mepMap.put(mepKeyId, mep) == null ? false : true;
+ }
+
+ private class InternalMepListener implements MapEventListener<MepKeyId, Mep> {
+
+ @Override
+ public void event(MapEvent<MepKeyId, Mep> mapEvent) {
+ final CfmMepEvent.Type type;
+
+ switch (mapEvent.type()) {
+ case INSERT:
+ type = CfmMepEvent.Type.MEP_ADDED;
+ break;
+ case UPDATE:
+ type = CfmMepEvent.Type.MEP_UPDATED;
+ break;
+ default:
+ case REMOVE:
+ type = CfmMepEvent.Type.MEP_REMOVED;
+ }
+ notifyDelegate(new CfmMepEvent(type, mapEvent.key()));
+ }
+ }
+}
diff --git a/incubator/net/src/main/java/org/onosproject/incubator/net/resource/label/impl/LabelResourceManager.java b/incubator/net/src/main/java/org/onosproject/incubator/net/resource/label/impl/LabelResourceManager.java
index 259dce0..56c308e 100644
--- a/incubator/net/src/main/java/org/onosproject/incubator/net/resource/label/impl/LabelResourceManager.java
+++ b/incubator/net/src/main/java/org/onosproject/incubator/net/resource/label/impl/LabelResourceManager.java
@@ -130,13 +130,11 @@
public Collection<LabelResource> applyFromDevicePool(DeviceId deviceId,
long applyNum) {
checkNotNull(deviceId, "deviceId is not null");
- checkNotNull(applyNum, "applyNum is not null");
return store.applyFromDevicePool(deviceId, applyNum);
}
@Override
public Collection<LabelResource> applyFromGlobalPool(long applyNum) {
- checkNotNull(applyNum, "applyNum is not null");
return store.applyFromGlobalPool(applyNum);
}
diff --git a/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkFlowObjectiveManager.java b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkFlowObjectiveManager.java
index 1816bb4..2a5bc26 100644
--- a/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkFlowObjectiveManager.java
+++ b/incubator/net/src/main/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkFlowObjectiveManager.java
@@ -317,7 +317,7 @@
public ObjectiveInstaller(DeviceId deviceId, Objective objective, int attemps) {
this.deviceId = checkNotNull(deviceId);
this.objective = checkNotNull(objective);
- this.numAttempts = checkNotNull(attemps);
+ this.numAttempts = attemps;
}
@Override
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
index a0de513..fa79546 100644
--- 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
@@ -36,10 +36,13 @@
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 org.onosproject.incubator.net.l2monitoring.cfm.service.CfmMepService;
import org.onosproject.mastership.MastershipServiceAdapter;
import org.onosproject.net.DeviceId;
import org.onosproject.store.service.TestStorageService;
@@ -50,6 +53,7 @@
import java.util.concurrent.atomic.AtomicLong;
import static junit.framework.TestCase.assertFalse;
+import static org.easymock.EasyMock.createMock;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -61,6 +65,11 @@
public class CfmMdManagerTest {
private static final NodeId NID_LOCAL = new NodeId("local");
private static final IpAddress LOCALHOST = IpAddress.valueOf("127.0.0.1");
+ private static final MaIdShort MA_ID_1_1 = MaIdCharStr.asMaId("test-ma-1-1");
+ private static final MaIdShort MA_ID_1_2 = MaIdCharStr.asMaId("test-ma-1-2");
+ private static final MdId MD_ID_1 = MdIdCharStr.asMdId("test-md-1");
+
+ private final CfmMepService mepService = createMock(CfmMepService.class);
private DistributedMdStore mdStore;
private CfmMdService service;
@@ -71,7 +80,7 @@
mdStore = new DistributedMdStore();
MaintenanceAssociation maTest11 = DefaultMaintenanceAssociation
- .builder(MaIdCharStr.asMaId("test-ma-1-1"), 9)
+ .builder(MA_ID_1_1, MD_ID_1.getNameLength())
.ccmInterval(MaintenanceAssociation.CcmInterval.INTERVAL_10MIN)
.maNumericId((short) 1)
.addToRemoteMepIdList(MepId.valueOf((short) 101))
@@ -83,7 +92,7 @@
.build();
MaintenanceAssociation maTest12 = DefaultMaintenanceAssociation
- .builder(MaIdCharStr.asMaId("test-ma-1-2"), 9)
+ .builder(MA_ID_1_2, MD_ID_1.getNameLength())
.ccmInterval(MaintenanceAssociation.CcmInterval.INTERVAL_10MIN)
.maNumericId((short) 2)
.addToRemoteMepIdList(MepId.valueOf((short) 201))
@@ -95,7 +104,7 @@
.build();
MaintenanceDomain mdTest1 = DefaultMaintenanceDomain
- .builder(MdIdCharStr.asMdId("test-md-1"))
+ .builder(MD_ID_1)
.mdLevel(MaintenanceDomain.MdLevel.LEVEL1)
.mdNumericId((short) 1)
.addToMaList(maTest11)
@@ -105,6 +114,7 @@
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);
@@ -113,6 +123,7 @@
service = manager;
TestUtils.setField(manager, "storageService", new TestStorageService());
TestUtils.setField(manager, "coreService", new TestCoreService());
+ TestUtils.setField(manager, "mepService", mepService);
injectEventDispatcher(manager, new TestEventDispatcher());
manager.appId = new CfmMdManagerTest.TestApplicationId(0, "CfmMdManagerTest");
@@ -339,7 +350,6 @@
MdIdCharStr.asMdId("test-md-1")).size());
}
-
public class TestApplicationId extends DefaultApplicationId {
public TestApplicationId(int id, String name) {
super(id, name);
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
index a825858..5941f6f 100644
--- 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
@@ -37,10 +37,12 @@
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.identifier.MepKeyId;
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.cfm.service.MepStore;
import org.onosproject.incubator.net.l2monitoring.soam.SoamDmProgrammable;
import org.onosproject.incubator.net.l2monitoring.soam.impl.TestSoamDmProgrammable;
import org.onosproject.net.AbstractProjectableModel;
@@ -57,21 +59,30 @@
import org.onosproject.net.driver.Driver;
import org.onosproject.net.driver.DriverService;
import org.onosproject.net.provider.ProviderId;
+import org.onosproject.store.service.AsyncDocumentTree;
+import org.onosproject.store.service.DocumentTreeBuilder;
+import org.onosproject.store.service.Serializer;
+import org.onosproject.store.service.StorageService;
+import org.onosproject.store.service.TestAsyncDocumentTree;
+import org.onosproject.store.service.TestStorageService;
+import org.onosproject.store.service.TestTopic;
+import org.onosproject.store.service.Topic;
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.assertNull;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
import static org.onosproject.net.NetTestTools.injectEventDispatcher;
/**
@@ -91,18 +102,32 @@
private CfmMepService mepService;
private CfmMepManager mepManager;
+ private MepStore mepStore;
+ private StorageService storageService;
protected static final MdId MDNAME1 = MdIdCharStr.asMdId("md-1");
+ protected static final MdId MDNAME2 = MdIdCharStr.asMdId("md-2");
protected static final MaIdShort MANAME1 = MaIdCharStr.asMaId("ma-1-1");
+ protected static final MaIdShort MANAME2 = MaIdCharStr.asMaId("ma-2-2");
private MaintenanceAssociation ma1;
+ private MaintenanceAssociation ma2;
protected static final MepId MEPID1 = MepId.valueOf((short) 10);
+ protected static final MepId MEPID11 = MepId.valueOf((short) 11);
+ protected static final MepId MEPID12 = MepId.valueOf((short) 12);
protected static final MepId MEPID2 = MepId.valueOf((short) 20);
+ protected static final MepId MEPID21 = MepId.valueOf((short) 21);
+ protected static final MepId MEPID22 = MepId.valueOf((short) 22);
+
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 mep11;
+ private Mep mep12;
private Mep mep2;
+ private Mep mep21;
+ private Mep mep22;
private Device device1;
private Device device2;
@@ -112,12 +137,19 @@
@Before
public void setup() throws CfmConfigException {
mepManager = new CfmMepManager();
+ mepStore = new DistributedMepStore();
+ storageService = new MockStorageService();
ma1 = DefaultMaintenanceAssociation.builder(MANAME1, MDNAME1.getNameLength()).build();
+ ma2 = DefaultMaintenanceAssociation.builder(MANAME2, MDNAME2.getNameLength()).build();
+
+ TestUtils.setField(mepStore, "storageService", storageService);
+ ((DistributedMepStore) mepStore).activate();
TestUtils.setField(mepManager, "coreService", new TestCoreService());
TestUtils.setField(mepManager, "deviceService", deviceService);
TestUtils.setField(mepManager, "cfmMdService", mdService);
+ TestUtils.setField(mepManager, "mepStore", mepStore);
injectEventDispatcher(mepManager, new TestEventDispatcher());
mepService = mepManager;
@@ -125,12 +157,27 @@
mep1 = DefaultMep.builder(MEPID1, DEVICE_ID1, PortNumber.P0,
Mep.MepDirection.UP_MEP, MDNAME1, MANAME1).build();
+ mepStore.createUpdateMep(new MepKeyId(MDNAME1, MANAME1, MEPID1), mep1);
+
+ mep11 = DefaultMep.builder(MEPID11, DEVICE_ID1, PortNumber.P0,
+ Mep.MepDirection.UP_MEP, MDNAME1, MANAME1).build();
+ mepStore.createUpdateMep(new MepKeyId(MDNAME1, MANAME1, MEPID11), mep11);
+
+ mep12 = DefaultMep.builder(MEPID12, DEVICE_ID1, PortNumber.P0,
+ Mep.MepDirection.UP_MEP, MDNAME2, MANAME2).build();
+ mepStore.createUpdateMep(new MepKeyId(MDNAME2, MANAME2, MEPID12), mep12);
+
mep2 = DefaultMep.builder(MEPID2, DEVICE_ID2, PortNumber.portNumber(2),
Mep.MepDirection.UP_MEP, MDNAME1, MANAME1).build();
- List<Mep> mepList = new ArrayList<>();
- mepList.add(mep1);
- mepList.add(mep2);
- TestUtils.setField(mepManager, "mepCollection", mepList);
+ mepStore.createUpdateMep(new MepKeyId(MDNAME1, MANAME1, MEPID2), mep2);
+
+ mep21 = DefaultMep.builder(MEPID21, DEVICE_ID2, PortNumber.portNumber(2),
+ Mep.MepDirection.UP_MEP, MDNAME1, MANAME1).build();
+ mepStore.createUpdateMep(new MepKeyId(MDNAME1, MANAME1, MEPID21), mep21);
+
+ mep22 = DefaultMep.builder(MEPID22, DEVICE_ID2, PortNumber.portNumber(2),
+ Mep.MepDirection.UP_MEP, MDNAME2, MANAME2).build();
+ mepStore.createUpdateMep(new MepKeyId(MDNAME2, MANAME2, MEPID22), mep22);
device1 = new DefaultDevice(
ProviderId.NONE, DEVICE_ID1, Device.Type.SWITCH,
@@ -180,7 +227,7 @@
Collection<MepEntry> mepEntries = mepManager.getAllMeps(MDNAME1, MANAME1);
- assertEquals(2, mepEntries.size());
+ assertEquals(4, mepEntries.size());
}
@Test
@@ -232,12 +279,13 @@
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);
- assertTrue(mepManager.deleteMep(MDNAME1, MANAME1, MEPID1));
+ assertTrue(mepManager.deleteMep(MDNAME1, MANAME1, MEPID1, Optional.empty()));
}
@Test
@@ -248,6 +296,7 @@
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();
@@ -257,6 +306,7 @@
Mep mep3 = DefaultMep.builder(mepId3, DEVICE_ID1, PortNumber.portNumber(1),
Mep.MepDirection.UP_MEP, MDNAME1, MANAME1).build();
+ //Expecting false - since it was not found
assertTrue(mepManager.createMep(MDNAME1, MANAME1, mep3));
}
@@ -364,6 +414,56 @@
}
}
+ @Test
+ public void testDeviceRemoved() throws CfmConfigException {
+ expect(mdService.getMaintenanceAssociation(MDNAME1, MANAME1))
+ .andReturn(Optional.ofNullable(ma1))
+ .anyTimes();
+ expect(mdService.getMaintenanceAssociation(MDNAME2, MANAME2))
+ .andReturn(Optional.ofNullable(ma2))
+ .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);
+
+// This is arranged like
+// device1 device2
+// / \ / \
+// md-1 md-2 md-1 md-2
+// | | | |
+// ma-1-1 ma-2-2 ma-1-1 ma-2-2
+// / \ | / \ \
+// mep1 mep11 mep12 mep2 mep21 mep22
+ assertNotNull(mepService.getMep(MDNAME1, MANAME1, MEPID1));
+ assertNotNull(mepService.getMep(MDNAME1, MANAME1, MEPID11));
+ assertNotNull(mepService.getMep(MDNAME2, MANAME2, MEPID12));
+ assertNotNull(mepService.getMep(MDNAME1, MANAME1, MEPID2));
+ assertNotNull(mepService.getMep(MDNAME1, MANAME1, MEPID21));
+ assertNotNull(mepService.getMep(MDNAME2, MANAME2, MEPID22));
+
+ //By deleting Device2 we expect Mep2,21,22 to have been deleted but Mep1,11,12 to remain
+ ((CfmMepManager) mepService).processDeviceRemoved(device2);
+
+ assertNotNull(mepService.getMep(MDNAME1, MANAME1, MEPID1));
+ assertNotNull(mepService.getMep(MDNAME1, MANAME1, MEPID11));
+ assertNotNull(mepService.getMep(MDNAME2, MANAME2, MEPID12));
+ //The device 2 related ones are gone
+ assertNull(mepService.getMep(MDNAME1, MANAME1, MEPID2));
+ assertNull(mepService.getMep(MDNAME1, MANAME1, MEPID21));
+ assertNull(mepService.getMep(MDNAME2, MANAME2, MEPID22));
+
+ //Now delete device1
+ ((CfmMepManager) mepService).processDeviceRemoved(device1);
+ assertNull(mepService.getMep(MDNAME1, MANAME1, MEPID1));
+ assertNull(mepService.getMep(MDNAME1, MANAME1, MEPID11));
+ assertNull(mepService.getMep(MDNAME2, MANAME2, MEPID12));
+ }
+
private class TestCoreService extends CoreServiceAdapter {
@Override
@@ -378,4 +478,27 @@
};
}
}
+
+ private static class MockStorageService extends TestStorageService {
+ @Override
+ public <V> DocumentTreeBuilder<V> documentTreeBuilder() {
+ return new DocumentTreeBuilder<V>() {
+ @Override
+ public AsyncDocumentTree<V> buildDocumentTree() {
+ return build();
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public AsyncDocumentTree<V> build() {
+ return new TestAsyncDocumentTree<>(name());
+ }
+ };
+ }
+
+ @Override
+ public <T> Topic<T> getTopic(String name, Serializer serializer) {
+ return new TestTopic<>(name);
+ }
+ }
}
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
index 8d0f765..3f4be0e 100644
--- 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
@@ -17,6 +17,7 @@
import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMep;
import org.onosproject.incubator.net.l2monitoring.cfm.DefaultMepEntry;
+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;
@@ -30,8 +31,8 @@
import org.onosproject.net.driver.AbstractHandlerBehaviour;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
+import java.util.Optional;
import static org.onosproject.incubator.net.l2monitoring.cfm.impl.CfmMepManagerTest.*;
@@ -47,13 +48,16 @@
deviceMepList.add(DefaultMep.builder(MEPID1, DEVICE_ID1, PortNumber.P0,
Mep.MepDirection.UP_MEP, MDNAME1, MANAME1).build());
+ deviceMepList.add(DefaultMep.builder(MEPID11, DEVICE_ID1, PortNumber.P0,
+ Mep.MepDirection.UP_MEP, MDNAME1, MANAME1).build());
+ deviceMepList.add(DefaultMep.builder(MEPID12, DEVICE_ID1, PortNumber.P0,
+ Mep.MepDirection.UP_MEP, MDNAME2, MANAME2).build());
deviceMepList.add(DefaultMep.builder(MEPID2, DEVICE_ID2, PortNumber.portNumber(2),
Mep.MepDirection.UP_MEP, MDNAME1, MANAME1).build());
- }
-
- @Override
- public Collection<MepEntry> getAllMeps(MdId mdName, MaIdShort maName) throws CfmConfigException {
- return null;
+ deviceMepList.add(DefaultMep.builder(MEPID21, DEVICE_ID2, PortNumber.portNumber(2),
+ Mep.MepDirection.UP_MEP, MDNAME1, MANAME1).build());
+ deviceMepList.add(DefaultMep.builder(MEPID22, DEVICE_ID2, PortNumber.portNumber(2),
+ Mep.MepDirection.UP_MEP, MDNAME2, MANAME2).build());
}
@Override
@@ -67,7 +71,8 @@
}
@Override
- public boolean deleteMep(MdId mdName, MaIdShort maName, MepId mepId) throws CfmConfigException {
+ public boolean deleteMep(MdId mdName, MaIdShort maName, MepId mepId,
+ Optional<MaintenanceDomain> oldMd) throws CfmConfigException {
return true;
}
@@ -77,6 +82,37 @@
}
@Override
+ public boolean deleteMdOnDevice(MdId mdId, Optional<MaintenanceDomain> oldMd) throws CfmConfigException {
+ return false;
+ }
+
+ @Override
+ public boolean deleteMaOnDevice(MdId mdId, MaIdShort maId,
+ Optional<MaintenanceDomain> oldMd) throws CfmConfigException {
+ return false;
+ }
+
+ @Override
+ public boolean createMdOnDevice(MdId mdId) throws CfmConfigException {
+ return false;
+ }
+
+ @Override
+ public boolean createMaOnDevice(MdId mdId, MaIdShort maId) throws CfmConfigException {
+ return false;
+ }
+
+ @Override
+ public boolean createMaRemoteMepOnDevice(MdId mdId, MaIdShort maId, MepId remoteMep) throws CfmConfigException {
+ return false;
+ }
+
+ @Override
+ public boolean deleteMaRemoteMepOnDevice(MdId mdId, MaIdShort maId, MepId remoteMep) throws CfmConfigException {
+ return false;
+ }
+
+ @Override
public void transmitLoopback(MdId mdName, MaIdShort maName, MepId mepId, MepLbCreate lbCreate)
throws CfmConfigException {
diff --git a/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkIntentManagerTest.java b/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkIntentManagerTest.java
index 9d6e547..c7d21cc 100644
--- a/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkIntentManagerTest.java
+++ b/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkIntentManagerTest.java
@@ -25,7 +25,6 @@
import org.onlab.junit.TestUtils;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.TestServiceDirectory;
-import org.onlab.rest.BaseResource;
import org.onosproject.TestApplicationId;
import org.onosproject.common.event.impl.TestEventDispatcher;
import org.onosproject.core.ApplicationId;
@@ -76,7 +75,10 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
/**
* Junit tests for VirtualNetworkIntentService.
@@ -149,7 +151,6 @@
.add(VirtualNetworkStore.class, virtualNetworkManagerStore)
.add(IntentService.class, intentService)
.add(WorkPartitionService.class, workPartitionService);
- BaseResource.setServiceDirectory(testDirectory);
TestUtils.setField(manager, "serviceDirectory", testDirectory);
manager.activate();
diff --git a/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkTopologyManagerTest.java b/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkTopologyManagerTest.java
index 38d2e82..6218a15 100644
--- a/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkTopologyManagerTest.java
+++ b/incubator/net/src/test/java/org/onosproject/incubator/net/virtual/impl/VirtualNetworkTopologyManagerTest.java
@@ -21,7 +21,6 @@
import org.junit.Test;
import org.onlab.junit.TestUtils;
import org.onlab.osgi.TestServiceDirectory;
-import org.onlab.rest.BaseResource;
import org.onosproject.common.event.impl.TestEventDispatcher;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
@@ -55,7 +54,9 @@
import java.util.concurrent.atomic.AtomicLong;
import static junit.framework.TestCase.assertTrue;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
/**
* Junit tests for VirtualNetworkTopologyService.
@@ -77,7 +78,6 @@
TestUtils.setField(virtualNetworkManagerStore, "storageService", new TestStorageService());
virtualNetworkManagerStore.activate();
- BaseResource.setServiceDirectory(testDirectory);
manager = new VirtualNetworkManager();
manager.store = virtualNetworkManagerStore;
manager.coreService = coreService;
diff --git a/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbApplicationService.java b/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbApplicationService.java
index bce4406..7ec8ed1 100644
--- a/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbApplicationService.java
+++ b/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbApplicationService.java
@@ -59,7 +59,7 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ApplicationService applicationService;
- private static ApplicationServiceNbServerInternal instance = null;
+ private ApplicationServiceNbServerInternal instance = null;
@Activate
diff --git a/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbComponentConfigService.java b/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbComponentConfigService.java
index 8e0c2dd..673d126 100644
--- a/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbComponentConfigService.java
+++ b/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbComponentConfigService.java
@@ -62,7 +62,7 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected ComponentConfigService componentConfigService;
- private static ComponentConfigServiceNbServerInternal instance = null;
+ private ComponentConfigServiceNbServerInternal instance = null;
@Activate
public void activate() {
diff --git a/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbDeviceService.java b/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbDeviceService.java
index b583800..a06acf6 100644
--- a/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbDeviceService.java
+++ b/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbDeviceService.java
@@ -52,7 +52,7 @@
private final Logger log = getLogger(getClass());
- private static DeviceServiceNbServerInternal instance = null;
+ private DeviceServiceNbServerInternal instance = null;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected GrpcServiceRegistry registry;
diff --git a/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbHostService.java b/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbHostService.java
index d5e3660..2ad2bf6 100644
--- a/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbHostService.java
+++ b/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbHostService.java
@@ -74,7 +74,7 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected HostService hostService;
- private static HostServiceNBServerInternal instance = null;
+ private HostServiceNBServerInternal instance = null;
@Activate
public void activate() {
diff --git a/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbMastershipService.java b/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbMastershipService.java
index 1495467..34b8cd9 100644
--- a/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbMastershipService.java
+++ b/incubator/protobuf/services/nb/src/main/java/org/onosproject/incubator/protobuf/services/nb/GrpcNbMastershipService.java
@@ -63,7 +63,7 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected MastershipService mastershipService;
- private static MastershipServiceNbServerInternal instance = null;
+ private MastershipServiceNbServerInternal instance = null;
@Activate
public void activate() {
diff --git a/incubator/store/src/main/java/org/onosproject/incubator/store/tunnel/impl/DistributedTunnelStore.java b/incubator/store/src/main/java/org/onosproject/incubator/store/tunnel/impl/DistributedTunnelStore.java
index fd0e95d..82f0140 100644
--- a/incubator/store/src/main/java/org/onosproject/incubator/store/tunnel/impl/DistributedTunnelStore.java
+++ b/incubator/store/src/main/java/org/onosproject/incubator/store/tunnel/impl/DistributedTunnelStore.java
@@ -227,8 +227,7 @@
for (TunnelId id : idSet) {
deletedTunnel = tunnelIdAsKeyStore.get(id);
- if (producerName == null || (producerName != null
- && producerName.equals(deletedTunnel.providerId()))) {
+ if (producerName == null || producerName.equals(deletedTunnel.providerId())) {
tunnelIdAsKeyStore.remove(deletedTunnel.tunnelId());
event = new TunnelEvent(TunnelEvent.Type.TUNNEL_REMOVED,
@@ -256,8 +255,8 @@
for (TunnelId id : idSet) {
deletedTunnel = tunnelIdAsKeyStore.get(id);
- if (type.equals(deletedTunnel.type()) && (producerName == null || (producerName != null
- && producerName.equals(deletedTunnel.providerId())))) {
+ if (type.equals(deletedTunnel.type()) && (producerName == null ||
+ producerName.equals(deletedTunnel.providerId()))) {
tunnelIdAsKeyStore.remove(deletedTunnel.tunnelId());
event = new TunnelEvent(TunnelEvent.Type.TUNNEL_REMOVED,
diff --git a/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/DistributedVirtualNetworkStore.java b/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/DistributedVirtualNetworkStore.java
index 1eaf196..5209543 100644
--- a/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/DistributedVirtualNetworkStore.java
+++ b/incubator/store/src/main/java/org/onosproject/incubator/store/virtual/impl/DistributedVirtualNetworkStore.java
@@ -462,17 +462,15 @@
}
});
- if (hostIdSet != null) {
- networkIdHostIdSetMap.compute(networkId, (id, existingHostIds) -> {
- if (existingHostIds == null || existingHostIds.isEmpty()) {
- return new HashSet<>();
- } else {
- return new HashSet<>(Sets.difference(existingHostIds, hostIdSet));
- }
- });
+ networkIdHostIdSetMap.compute(networkId, (id, existingHostIds) -> {
+ if (existingHostIds == null || existingHostIds.isEmpty()) {
+ return new HashSet<>();
+ } else {
+ return new HashSet<>(Sets.difference(existingHostIds, hostIdSet));
+ }
+ });
- hostIdVirtualHostMap.remove(hostId);
- }
+ hostIdVirtualHostMap.remove(hostId);
}
/**
@@ -567,15 +565,13 @@
Set<VirtualLink> virtualLinkSet = new HashSet<>();
virtualLinkSet.add(virtualLink);
- if (virtualLinkSet != null) {
- networkIdVirtualLinkSetMap.compute(networkId, (id, existingVirtualLinks) -> {
- if (existingVirtualLinks == null || existingVirtualLinks.isEmpty()) {
- return new HashSet<>();
- } else {
- return new HashSet<>(Sets.difference(existingVirtualLinks, virtualLinkSet));
- }
- });
- }
+ networkIdVirtualLinkSetMap.compute(networkId, (id, existingVirtualLinks) -> {
+ if (existingVirtualLinks == null || existingVirtualLinks.isEmpty()) {
+ return new HashSet<>();
+ } else {
+ return new HashSet<>(Sets.difference(existingVirtualLinks, virtualLinkSet));
+ }
+ });
return virtualLink;
}
diff --git a/lib/BUCK b/lib/BUCK
index 2c60230..860b5de 100644
--- a/lib/BUCK
+++ b/lib/BUCK
@@ -1,4 +1,4 @@
-# ***** This file was auto-generated at Fri, 5 Jan 2018 21:10:43 GMT. Do not edit this file manually. *****
+# ***** This file was auto-generated at Tue, 23 Jan 2018 20:38:59 GMT. Do not edit this file manually. *****
# ***** Use onos-lib-gen *****
pass_thru_pom(
@@ -207,10 +207,10 @@
remote_jar (
name = 'atomix',
- out = 'atomix-2.0.12.jar',
- url = 'mvn:io.atomix:atomix:jar:2.0.12',
- sha1 = 'f2e814ea90812b843a1ad51b2003dda26267be17',
- maven_coords = 'io.atomix:atomix:2.0.12',
+ out = 'atomix-2.0.14.jar',
+ url = 'mvn:io.atomix:atomix:jar:2.0.14',
+ sha1 = 'b2deb5601c8385c0eaabc952a19241c772f0984c',
+ maven_coords = 'io.atomix:atomix:2.0.14',
visibility = [ 'PUBLIC' ],
)
diff --git a/lib/deps.json b/lib/deps.json
index 544bf8e..0d98ca2 100644
--- a/lib/deps.json
+++ b/lib/deps.json
@@ -116,7 +116,7 @@
"aopalliance-repackaged": "mvn:org.glassfish.hk2.external:aopalliance-repackaged:2.5.0-b32",
"amqp-client": "mvn:com.rabbitmq:amqp-client:jar:3.6.1",
"asm": "mvn:org.ow2.asm:asm:5.0.4",
- "atomix": "mvn:io.atomix:atomix:2.0.12",
+ "atomix": "mvn:io.atomix:atomix:2.0.14",
"commons-codec": "mvn:commons-codec:commons-codec:1.10",
"commons-collections": "mvn:commons-collections:commons-collections:3.2.2",
"commons-configuration": "mvn:commons-configuration:commons-configuration:1.10",
diff --git a/lib/pom.xml b/lib/pom.xml
index 7b8f528..8298544 100644
--- a/lib/pom.xml
+++ b/lib/pom.xml
@@ -704,19 +704,20 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
- <!-- TODO: update once following issue is fixed. -->
- <!-- https://jira.codehaus.org/browse/MCOMPILER-205 -->
- <version>2.5.1</version>
+ <version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
+ <compilerArgs>
+ <compilerArg>-Xpkginfo:always</compilerArg>
+ </compilerArgs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
- <version>2.20</version>
+ <version>2.20.1</version>
<configuration>
<redirectTestOutputToFile>true</redirectTestOutputToFile>
<printSummary>true</printSummary>
@@ -728,7 +729,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
- <version>2.10.4</version>
+ <version>3.0.0</version>
<configuration>
<tags>
<tag>
@@ -775,7 +776,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
- <version>3.0.0</version>
+ <version>3.1.0</version>
</plugin>
<plugin>
@@ -857,6 +858,14 @@
</execution>
</executions>
</plugin>
+
+ <plugin>
+ <groupId>org.apache.karaf.tooling</groupId>
+ <artifactId>karaf-maven-plugin</artifactId>
+ <version>${karaf.version}</version>
+ <extensions>true</extensions>
+ </plugin>
+
</plugins>
</pluginManagement>
@@ -869,7 +878,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
- <version>2.17</version>
+ <version>3.0.0</version>
<dependencies>
<dependency>
<groupId>org.onosproject</groupId>
@@ -883,12 +892,6 @@
</dependency>
</dependencies>
<configuration>
- <!-- begin: workaround for unexpected NullPointerException on Eclipse -->
- <sourceDirectory>${project.build.sourceDirectory}
- </sourceDirectory>
- <testSourceDirectory>${project.build.testSourceDirectory}
- </testSourceDirectory>
- <!-- end: workaround for unexpected NullPointerException on Eclipse -->
<configLocation>onos/checkstyle-mvn.xml</configLocation>
<suppressionsLocation>onos/suppressions.xml
</suppressionsLocation>
@@ -935,7 +938,7 @@
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
- <version>0.7.9</version>
+ <version>0.8.0</version>
<executions>
<execution>
<id>default-prepare-agent</id>
diff --git a/models/common/pom.xml b/models/common/pom.xml
index 18e4a22..030faf0 100644
--- a/models/common/pom.xml
+++ b/models/common/pom.xml
@@ -116,6 +116,17 @@
</executions>
</plugin>
+ <!-- FIXME: YANG tool generates problematic code -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <compilerArgs>
+ <arg>-XepDisableAllChecks</arg>
+ <arg>-Xep:BetaApi:OFF</arg>
+ </compilerArgs>
+ </configuration>
+ </plugin>
</plugins>
diff --git a/models/microsemi/pom.xml b/models/microsemi/pom.xml
index 858828d..7712145 100644
--- a/models/microsemi/pom.xml
+++ b/models/microsemi/pom.xml
@@ -123,6 +123,17 @@
</executions>
</plugin>
+ <!-- FIXME: YANG tool generates problematic code -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <compilerArgs>
+ <arg>-XepDisableAllChecks</arg>
+ <arg>-Xep:BetaApi:OFF</arg>
+ </compilerArgs>
+ </configuration>
+ </plugin>
</plugins>
diff --git a/models/openconfig/compile-yangs.sh b/models/openconfig/compile-yangs.sh
new file mode 100755
index 0000000..1d65364
--- /dev/null
+++ b/models/openconfig/compile-yangs.sh
@@ -0,0 +1,21 @@
+#!/usr/bin/env bash
+
+YANG_ROOT=$1
+
+CONFDC_ARGS=' -c'
+
+# YANGPATHS
+for path in $(find $YANG_ROOT -type d); do
+ CONFDC_ARGS+=" --yangpath $path"
+done
+
+# create output dir
+mkdir -p fxs
+
+# compile .yang s
+for yang in $(find $YANG_ROOT -type f -name '*.yang'); do
+ BASE=$(basename $yang)
+ OUT="${BASE%.yang}.fxs"
+ echo "Compiling..$yang"
+ confdc $CONFDC_ARGS -o fxs/$OUT -- $yang
+done
diff --git a/models/openconfig/pom.xml b/models/openconfig/pom.xml
index 008311a..8737789 100644
--- a/models/openconfig/pom.xml
+++ b/models/openconfig/pom.xml
@@ -117,6 +117,17 @@
</executions>
</plugin>
+ <!-- FIXME: YANG tool generates problematic code -->
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <compilerArgs>
+ <arg>-XepDisableAllChecks</arg>
+ <arg>-Xep:BetaApi:OFF</arg>
+ </compilerArgs>
+ </configuration>
+ </plugin>
</plugins>
diff --git a/modules.defs b/modules.defs
index 2ae8cfd..b090666 100644
--- a/modules.defs
+++ b/modules.defs
@@ -108,6 +108,7 @@
'//drivers/barefoot:onos-drivers-barefoot-oar',
'//drivers/hp:onos-drivers-hp-oar',
'//drivers/p4runtime:onos-drivers-p4runtime-oar',
+ '//drivers/gnmi:onos-drivers-gnmi-oar',
'//drivers/polatis/netconf:onos-drivers-polatis-netconf-oar',
]
diff --git a/pipelines/fabric/src/main/resources/Makefile b/pipelines/fabric/src/main/resources/Makefile
index f11de1b..e82fd31 100644
--- a/pipelines/fabric/src/main/resources/Makefile
+++ b/pipelines/fabric/src/main/resources/Makefile
@@ -12,6 +12,12 @@
mv p4c-out/bmv2/fabric.p4rt p4c-out/bmv2/fabric.p4info
rm -f p4c-out/bmv2/fabric.p4i
+bmv2-spgw:
+ p4c-bm2-ss -o p4c-out/bmv2/fabric-spgw.json \
+ $(BMV2_OPTIONS) -DWITH_SPGW \
+ --p4runtime-file p4c-out/bmv2/fabric-spgw.p4info \
+ --p4runtime-format text fabric.p4
+
custom:
p4c -v -x p4-16 -b $(BACKEND) \
$(BACKEND_OPTIONS) -o p4c-out/$(BACKEND) \
diff --git a/pipelines/fabric/src/main/resources/fabric.p4 b/pipelines/fabric/src/main/resources/fabric.p4
index d27ed87..56ab6e9 100644
--- a/pipelines/fabric/src/main/resources/fabric.p4
+++ b/pipelines/fabric/src/main/resources/fabric.p4
@@ -26,6 +26,10 @@
#include "include/checksum.p4"
#include "include/parser.p4"
+#ifdef WITH_SPGW
+#include "include/spgw.p4"
+#endif // WITH_SPGW
+
control FabricIngress (
inout parsed_headers_t hdr,
inout fabric_metadata_t fabric_metadata,
@@ -35,13 +39,23 @@
Forwarding() forwarding;
Next() next;
PortCountersControl() port_counters_control;
+ EgressNextControl() egress_next;
apply {
packet_io_ingress.apply(hdr, fabric_metadata, standard_metadata);
+#ifdef WITH_SPGW
+#ifdef WITH_SPGW_PCC_GATING
+ fabric_metadata.spgw.l4_src_port = fabric_metadata.l4_src_port;
+ fabric_metadata.spgw.l4_dst_port = fabric_metadata.l4_dst_port;
+#endif // WITH_SPGW_PCC_GATING
+ spgw_ingress.apply(hdr.gtpu_ipv4, hdr.gtpu_udp, hdr.gtpu,
+ hdr.ipv4, hdr.udp, fabric_metadata.spgw);
+#endif // WITH_SPGW
filtering.apply(hdr, fabric_metadata, standard_metadata);
forwarding.apply(hdr, fabric_metadata, standard_metadata);
next.apply(hdr, fabric_metadata, standard_metadata);
port_counters_control.apply(hdr, fabric_metadata, standard_metadata);
+ egress_next.apply(hdr, fabric_metadata, standard_metadata);
}
}
@@ -49,10 +63,12 @@
inout fabric_metadata_t fabric_metadata,
inout standard_metadata_t standard_metadata) {
PacketIoEgress() pkt_io_egress;
- EgressNextControl() egress_next;
apply {
- egress_next.apply(hdr, fabric_metadata, standard_metadata);
pkt_io_egress.apply(hdr, fabric_metadata, standard_metadata);
+#ifdef WITH_SPGW
+ spgw_egress.apply(hdr.gtpu_ipv4, hdr.gtpu_udp, hdr.gtpu,
+ fabric_metadata.spgw, standard_metadata);
+#endif // WITH_SPGW
}
}
diff --git a/pipelines/fabric/src/main/resources/include/checksum.p4 b/pipelines/fabric/src/main/resources/include/checksum.p4
index dfcadb6..d920235 100644
--- a/pipelines/fabric/src/main/resources/include/checksum.p4
+++ b/pipelines/fabric/src/main/resources/include/checksum.p4
@@ -17,11 +17,14 @@
#ifndef __CHECKSUM__
#define __CHECKSUM__
+#ifdef WITH_SPGW
+#include "spgw.p4"
+#endif // WITH_SPGW
+
control FabricComputeChecksum(inout parsed_headers_t hdr,
inout fabric_metadata_t meta)
{
apply {
-#ifdef TARGET_BMV2
update_checksum(hdr.ipv4.isValid(),
{
hdr.ipv4.version,
@@ -39,7 +42,10 @@
hdr.ipv4.hdr_checksum,
HashAlgorithm.csum16
);
-#endif
+#ifdef WITH_SPGW
+ update_gtpu_checksum.apply(hdr.gtpu_ipv4, hdr.gtpu_udp, hdr.gtpu,
+ hdr.ipv4, hdr.udp);
+#endif // WITH_SPGW
}
}
@@ -47,7 +53,6 @@
inout fabric_metadata_t meta)
{
apply {
-#ifdef TARGET_BMV2
verify_checksum(hdr.ipv4.isValid(),
{
hdr.ipv4.version,
@@ -65,7 +70,9 @@
hdr.ipv4.hdr_checksum,
HashAlgorithm.csum16
);
-#endif
+#ifdef WITH_SPGW
+ verify_gtpu_checksum.apply(hdr.gtpu_ipv4);
+#endif // WITH_SPGW
}
}
diff --git a/pipelines/fabric/src/main/resources/include/control/filtering.p4 b/pipelines/fabric/src/main/resources/include/control/filtering.p4
index 5a93e5b..58bf147 100644
--- a/pipelines/fabric/src/main/resources/include/control/filtering.p4
+++ b/pipelines/fabric/src/main/resources/include/control/filtering.p4
@@ -24,6 +24,8 @@
inout parsed_headers_t hdr,
inout fabric_metadata_t fabric_metadata,
inout standard_metadata_t standard_metadata) {
+ direct_counter(CounterType.packets_and_bytes) ingress_port_vlan_counter;
+ direct_counter(CounterType.packets_and_bytes) fwd_classifier_counter;
action drop() {
mark_to_drop();
@@ -65,7 +67,9 @@
nop;
drop;
}
- const default_action = drop();
+
+ const default_action = nop();
+ counters = ingress_port_vlan_counter;
}
// Originally TMAC table in OF-DPA pipeline
@@ -81,6 +85,7 @@
}
const default_action = set_forwarding_type(FWD_BRIDGING);
+ counters = fwd_classifier_counter;
}
apply {
diff --git a/pipelines/fabric/src/main/resources/include/control/forwarding.p4 b/pipelines/fabric/src/main/resources/include/control/forwarding.p4
index 4e9ada1..de46115 100644
--- a/pipelines/fabric/src/main/resources/include/control/forwarding.p4
+++ b/pipelines/fabric/src/main/resources/include/control/forwarding.p4
@@ -27,6 +27,12 @@
inout fabric_metadata_t fabric_metadata,
inout standard_metadata_t standard_metadata) {
+ direct_counter(CounterType.packets_and_bytes) bridging_counter;
+ direct_counter(CounterType.packets_and_bytes) mpls_counter;
+ direct_counter(CounterType.packets_and_bytes) unicast_v4_counter;
+ direct_counter(CounterType.packets_and_bytes) multicast_v4_counter;
+ direct_counter(CounterType.packets_and_bytes) acl_counter;
+
action drop() {
mark_to_drop();
}
@@ -53,6 +59,7 @@
actions = {
set_next_id;
}
+ counters = bridging_counter;
}
table mpls {
@@ -63,6 +70,7 @@
actions = {
pop_mpls_and_next;
}
+ counters = mpls_counter;
}
table unicast_v4 {
@@ -73,6 +81,7 @@
actions = {
set_next_id;
}
+ counters = unicast_v4_counter;
}
table multicast_v4 {
@@ -84,8 +93,13 @@
actions = {
set_next_id;
}
+ counters = multicast_v4_counter;
}
+#ifdef WITH_IPV6
+ direct_counter(CounterType.packets_and_bytes) unicast_v6_counter;
+ direct_counter(CounterType.packets_and_bytes) multicast_v6_counter;
+
table unicast_v6 {
key = {
hdr.ipv6.dst_addr: lpm;
@@ -94,6 +108,7 @@
actions = {
set_next_id;
}
+ counters = unicast_v6_counter;
}
table multicast_v6 {
@@ -105,7 +120,9 @@
actions = {
set_next_id;
}
+ counters = multicast_v6_counter;
}
+#endif // WITH_IPV6
table acl {
key = {
@@ -133,24 +150,24 @@
const default_action = nop();
size = 256;
+ counters = acl_counter;
}
apply {
if(fabric_metadata.fwd_type == FWD_BRIDGING) bridging.apply();
else if (fabric_metadata.fwd_type == FWD_MPLS) {
mpls.apply();
- if (hdr.ipv4.isValid()) {
- hdr.ethernet.ether_type = ETHERTYPE_IPV4;
- fabric_metadata.original_ether_type = ETHERTYPE_IPV4;
- } else {
- hdr.ethernet.ether_type = ETHERTYPE_IPV6;
- fabric_metadata.original_ether_type = ETHERTYPE_IPV6;
- }
+
+ // TODO: IPv6
+ hdr.vlan_tag.ether_type = ETHERTYPE_IPV4;
+ fabric_metadata.original_ether_type = ETHERTYPE_IPV4;
}
else if (fabric_metadata.fwd_type == FWD_IPV4_UNICAST) unicast_v4.apply();
else if (fabric_metadata.fwd_type == FWD_IPV4_MULTICAST) multicast_v4.apply();
+#ifdef WITH_IPV6
else if (fabric_metadata.fwd_type == FWD_IPV6_UNICAST) unicast_v6.apply();
else if (fabric_metadata.fwd_type == FWD_IPV6_MULTICAST) multicast_v6.apply();
+#endif // WITH_IPV6
acl.apply();
}
}
diff --git a/pipelines/fabric/src/main/resources/include/control/next.p4 b/pipelines/fabric/src/main/resources/include/control/next.p4
index a58e88e..e0ebbe8 100644
--- a/pipelines/fabric/src/main/resources/include/control/next.p4
+++ b/pipelines/fabric/src/main/resources/include/control/next.p4
@@ -25,6 +25,9 @@
inout fabric_metadata_t fabric_metadata,
inout standard_metadata_t standard_metadata) {
action_selector(HashAlgorithm.crc16, 32w64, 32w16) ecmp_selector;
+ direct_counter(CounterType.packets_and_bytes) simple_counter;
+ direct_counter(CounterType.packets_and_bytes) hashed_counter;
+ direct_counter(CounterType.packets_and_bytes) broadcast_counter;
action output(port_num_t port_num) {
standard_metadata.egress_spec = port_num;
@@ -60,7 +63,7 @@
action push_mpls (mpls_label_t label, bit<3> tc) {
// Suppose that the maximum number of label is one.
hdr.mpls.setValid();
- hdr.ethernet.ether_type = ETHERTYPE_MPLS;
+ hdr.vlan_tag.ether_type = ETHERTYPE_MPLS;
hdr.mpls.label = label;
hdr.mpls.tc = tc;
hdr.mpls.bos = 1w1; // BOS = TRUE
@@ -92,7 +95,9 @@
output;
set_vlan_output;
l3_routing;
+ mpls_routing_v4;
}
+ counters = simple_counter;
}
table hashed {
@@ -112,6 +117,7 @@
}
implementation = ecmp_selector;
+ counters = hashed_counter;
}
/*
@@ -124,6 +130,7 @@
actions = {
set_mcast_group;
}
+ counters = broadcast_counter;
}
apply {
@@ -132,9 +139,11 @@
if(hdr.ipv4.isValid()) {
hdr.ipv4.ttl = hdr.ipv4.ttl - 1;
}
+#ifdef WITH_IPV6
else if (hdr.ipv6.isValid()) {
hdr.ipv6.hop_limit = hdr.ipv6.hop_limit - 1;
}
+#endif // WITH_IPV6
}
}
hashed.apply();
@@ -150,11 +159,7 @@
apply {
// pop internal vlan if the meta is set
if (fabric_metadata.pop_vlan_at_egress) {
- if (hdr.mpls.isValid()) {
- hdr.ethernet.ether_type = ETHERTYPE_MPLS;
- } else {
- hdr.ethernet.ether_type = fabric_metadata.original_ether_type;
- }
+ hdr.ethernet.ether_type = hdr.vlan_tag.ether_type;
hdr.vlan_tag.setInvalid();
}
}
diff --git a/pipelines/fabric/src/main/resources/include/define.p4 b/pipelines/fabric/src/main/resources/include/define.p4
index 4765824..f4e5b56 100644
--- a/pipelines/fabric/src/main/resources/include/define.p4
+++ b/pipelines/fabric/src/main/resources/include/define.p4
@@ -44,6 +44,8 @@
const bit<8> PROTO_UDP = 17;
const bit<8> PROTO_ICMPV6 = 58;
+const bit<4> IPV4_MIN_IHL = 5;
+
#ifndef CPU_PORT
const port_num_t CPU_PORT = 255;
#endif
@@ -56,5 +58,30 @@
const fwd_type_t FWD_IPV6_MULTICAST = 5;
const bit<8> DEFAULT_MPLS_TTL = 64;
+const bit<8> DEFAULT_IPV4_TTL = 64;
+
+#define ETH_HDR_SIZE 14
+#define IPV4_HDR_SIZE 20
+#define UDP_HDR_SIZE 8
+#define GTP_HDR_SIZE 8
+
+#define UDP_PORT_GTPU 2152
+#define GTP_GPDU 0xff
+#define GTPU_VERSION 0x01
+#define GTP_PROTOCOL_TYPE_GTP 0x01
+
+typedef bit direction_t;
+typedef bit pcc_gate_status_t;
+typedef bit<32> sdf_rule_id_t;
+typedef bit<32> pcc_rule_id_t;
+
+const sdf_rule_id_t DEFAULT_SDF_RULE_ID = 0;
+const pcc_rule_id_t DEFAULT_PCC_RULE_ID = 0;
+
+const direction_t DIR_UPLINK = 1w0;
+const direction_t DIR_DOWNLINK = 1w1;
+
+const pcc_gate_status_t PCC_GATE_OPEN = 1w0;
+const pcc_gate_status_t PCC_GATE_CLOSED = 1w1;
#endif
diff --git a/pipelines/fabric/src/main/resources/include/header.p4 b/pipelines/fabric/src/main/resources/include/header.p4
index df9958b..0a0814e 100644
--- a/pipelines/fabric/src/main/resources/include/header.p4
+++ b/pipelines/fabric/src/main/resources/include/header.p4
@@ -115,6 +115,36 @@
bit<64> timestamp;
}
+#ifdef WITH_SPGW
+// GTPU v1
+header gtpu_t {
+ bit<3> version; /* version */
+ bit<1> pt; /* protocol type */
+ bit<1> spare; /* reserved */
+ bit<1> ex_flag; /* next extension hdr present? */
+ bit<1> seq_flag; /* sequence no. */
+ bit<1> npdu_flag; /* n-pdn number present ? */
+ bit<8> msgtype; /* message type */
+ bit<16> msglen; /* message length */
+ bit<32> teid; /* tunnel endpoint id */
+}
+
+struct spgw_meta_t {
+ bool do_spgw;
+ direction_t direction;
+ bit<32> teid;
+ bit<32> s1u_enb_addr;
+ bit<32> s1u_sgw_addr;
+#ifdef WITH_SPGW_PCC_GATING
+ bit<16> l4_src_port;
+ bit<16> l4_dst_port;
+ pcc_gate_status_t pcc_gate_status;
+ sdf_rule_id_t sdf_rule_id;
+ pcc_rule_id_t pcc_rule_id;
+#endif // WITH_SPGW_PCC_GATING
+}
+#endif // WITH_SPGW
+
//Custom metadata definition
struct fabric_metadata_t {
fwd_type_t fwd_type;
@@ -124,15 +154,24 @@
bit<16> l4_src_port;
bit<16> l4_dst_port;
bit<16> original_ether_type;
+#ifdef WITH_SPGW
+ spgw_meta_t spgw;
+#endif // WITH_SPGW
}
struct parsed_headers_t {
ethernet_t ethernet;
vlan_tag_t vlan_tag;
- vlan_tag_t inner_vlan_tag;
mpls_t mpls;
+#ifdef WITH_SPGW
+ ipv4_t gtpu_ipv4;
+ udp_t gtpu_udp;
+ gtpu_t gtpu;
+#endif // WITH_SPGW
ipv4_t ipv4;
+#ifdef WITH_IPV6
ipv6_t ipv6;
+#endif // WITH_IPV6
arp_t arp;
tcp_t tcp;
udp_t udp;
diff --git a/pipelines/fabric/src/main/resources/include/parser.p4 b/pipelines/fabric/src/main/resources/include/parser.p4
index b5eadbc..f4b3252 100644
--- a/pipelines/fabric/src/main/resources/include/parser.p4
+++ b/pipelines/fabric/src/main/resources/include/parser.p4
@@ -41,13 +41,13 @@
packet.extract(hdr.ethernet);
fabric_metadata.original_ether_type = hdr.ethernet.ether_type;
transition select(hdr.ethernet.ether_type){
- ETHERTYPE_QINQ_NON_STD: parse_vlan_tag;
- ETHERTYPE_QINQ: parse_vlan_tag;
ETHERTYPE_VLAN: parse_vlan_tag;
ETHERTYPE_MPLS: parse_mpls;
ETHERTYPE_ARP: parse_arp;
ETHERTYPE_IPV4: parse_ipv4;
+#ifdef WITH_IPV6
ETHERTYPE_IPV6: parse_ipv6;
+#endif // WITH_IPV6
default: accept;
}
}
@@ -55,20 +55,12 @@
state parse_vlan_tag {
packet.extract(hdr.vlan_tag);
transition select(hdr.vlan_tag.ether_type){
- ETHERTYPE_VLAN: parse_inner_vlan_tag;
ETHERTYPE_ARP: parse_arp;
ETHERTYPE_IPV4: parse_ipv4;
+#ifdef WITH_IPV6
ETHERTYPE_IPV6: parse_ipv6;
- default: accept;
- }
- }
-
- state parse_inner_vlan_tag {
- packet.extract(hdr.inner_vlan_tag);
- transition select(hdr.vlan_tag.ether_type){
- ETHERTYPE_ARP: parse_arp;
- ETHERTYPE_IPV4: parse_ipv4;
- ETHERTYPE_IPV6: parse_ipv6;
+#endif // WITH_IPV6
+ ETHERTYPE_MPLS: parse_mpls;
default: accept;
}
}
@@ -81,7 +73,9 @@
transition select(packet.lookahead<bit<4>>()) {
//The packet should be either IPv4 or IPv6.
IP_VERSION_4: parse_ipv4;
+#ifdef WITH_IPV6
IP_VERSION_6: parse_ipv6;
+#endif // WITH_IPV6
default: parse_ethernet;
}
}
@@ -98,6 +92,7 @@
}
}
+#ifdef WITH_IPV6
state parse_ipv6 {
packet.extract(hdr.ipv6);
fabric_metadata.ip_proto = hdr.ipv6.next_hdr;
@@ -108,6 +103,7 @@
default: accept;
}
}
+#endif // WITH_IPV6
state parse_arp {
packet.extract(hdr.arp);
@@ -125,13 +121,44 @@
packet.extract(hdr.udp);
fabric_metadata.l4_src_port = hdr.udp.src_port;
fabric_metadata.l4_dst_port = hdr.udp.dst_port;
+#ifdef WITH_SPGW
+ transition select(hdr.udp.dst_port) {
+ UDP_PORT_GTPU: parse_gtpu;
+ default: accept;
+ }
+#else
transition accept;
+#endif // WITH_SPGW
}
state parse_icmp {
packet.extract(hdr.icmp);
transition accept;
}
+
+#ifdef WITH_SPGW
+ state parse_gtpu {
+ packet.extract(hdr.gtpu);
+ transition parse_ipv4_inner;
+ }
+
+ state parse_ipv4_inner {
+ packet.extract(hdr.gtpu_ipv4);
+ transition select(hdr.gtpu_ipv4.protocol) {
+ PROTO_TCP: parse_tcp;
+ PROTO_UDP: parse_udp_inner;
+ PROTO_ICMP: parse_icmp;
+ default: accept;
+ }
+ }
+
+ state parse_udp_inner {
+ packet.extract(hdr.gtpu_udp);
+ fabric_metadata.l4_src_port = hdr.gtpu_udp.src_port;
+ fabric_metadata.l4_dst_port = hdr.gtpu_udp.dst_port;
+ transition accept;
+ }
+#endif // WITH_SPGW
}
control FabricDeparser(packet_out packet, in parsed_headers_t hdr) {
@@ -139,11 +166,17 @@
packet.emit(hdr.packet_in);
packet.emit(hdr.ethernet);
packet.emit(hdr.vlan_tag);
- packet.emit(hdr.inner_vlan_tag);
packet.emit(hdr.mpls);
packet.emit(hdr.arp);
+#ifdef WITH_SPGW
+ packet.emit(hdr.gtpu_ipv4);
+ packet.emit(hdr.gtpu_udp);
+ packet.emit(hdr.gtpu);
+#endif // WITH_SPGW
packet.emit(hdr.ipv4);
+#ifdef WITH_IPV6
packet.emit(hdr.ipv6);
+#endif // WITH_IPV6
packet.emit(hdr.tcp);
packet.emit(hdr.udp);
packet.emit(hdr.icmp);
diff --git a/pipelines/fabric/src/main/resources/include/spgw.p4 b/pipelines/fabric/src/main/resources/include/spgw.p4
new file mode 100644
index 0000000..3edca18
--- /dev/null
+++ b/pipelines/fabric/src/main/resources/include/spgw.p4
@@ -0,0 +1,333 @@
+/*
+ * 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.
+ */
+
+#ifndef __SPGW__
+#define __SPGW__
+
+
+control spgw_ingress(
+ inout ipv4_t gtpu_ipv4,
+ inout udp_t gtpu_udp,
+ inout gtpu_t gtpu,
+ inout ipv4_t ipv4,
+ inout udp_t udp,
+ inout spgw_meta_t spgw_meta
+ ) {
+
+ direct_counter(CounterType.packets_and_bytes) ue_counter;
+
+ action drop_now() {
+ mark_to_drop();
+ exit;
+ }
+
+ action gtpu_decap() {
+ gtpu_ipv4.setInvalid();
+ gtpu_udp.setInvalid();
+ gtpu.setInvalid();
+ }
+
+ action set_dl_sess_info(bit<32> teid,
+ bit<32> s1u_enb_addr,
+ bit<32> s1u_sgw_addr) {
+ spgw_meta.teid = teid;
+ spgw_meta.s1u_enb_addr = s1u_enb_addr;
+ spgw_meta.s1u_sgw_addr = s1u_sgw_addr;
+ }
+
+ action update_ue_cdr() {
+ ue_counter.count();
+ }
+
+ table ue_filter_table {
+ key = {
+ // IP prefixes of the UEs managed by this switch (when downlink)
+ ipv4.dst_addr : lpm;
+ }
+ actions = {
+ NoAction();
+ }
+ }
+
+ table s1u_filter_table {
+ key = {
+ // IP addresses of the S1U interfaces embodied by this switch.
+ spgw_meta.s1u_sgw_addr : exact;
+ }
+ actions = {
+ NoAction();
+ }
+ }
+
+#ifdef WITH_SPGW_PCC_GATING
+ action set_sdf_rule_id(sdf_rule_id_t id) {
+ spgw_meta.sdf_rule_id = id;
+ }
+
+ action set_pcc_rule_id(pcc_rule_id_t id) {
+ spgw_meta.pcc_rule_id = id;
+ }
+
+ action set_pcc_info(pcc_gate_status_t gate_status) {
+ spgw_meta.pcc_gate_status = gate_status;
+ }
+
+ table sdf_rule_lookup {
+ key = {
+ spgw_meta.direction : exact;
+ ipv4.src_addr : ternary;
+ ipv4.dst_addr : ternary;
+ ipv4.protocol : ternary;
+ spgw_meta.l4_src_port : ternary;
+ spgw_meta.l4_dst_port : ternary;
+ }
+ actions = {
+ set_sdf_rule_id();
+ }
+ const default_action = set_sdf_rule_id(DEFAULT_SDF_RULE_ID);
+ }
+
+ table pcc_rule_lookup {
+ key = {
+ spgw_meta.sdf_rule_id : exact;
+ }
+ actions = {
+ set_pcc_rule_id();
+ }
+ const default_action = set_pcc_rule_id(DEFAULT_PCC_RULE_ID);
+ }
+
+ table pcc_info_lookup {
+ key = {
+ spgw_meta.pcc_rule_id : exact;
+ }
+ actions = {
+ set_pcc_info();
+ }
+ const default_action = set_pcc_info(PCC_GATE_OPEN);
+ }
+#endif // WITH_SPGW_PCC_GATING
+
+ table dl_sess_lookup {
+ key = {
+ // UE addr for downlink
+ ipv4.dst_addr : exact;
+ }
+ actions = {
+ set_dl_sess_info();
+ }
+ }
+
+ table ue_cdr_table {
+ key = {
+ // UE addr for downlink
+ ipv4.dst_addr : exact;
+ }
+ actions = {
+ update_ue_cdr();
+ }
+ counters = ue_counter;
+ }
+
+ apply {
+ spgw_meta.do_spgw = false;
+ if (gtpu.isValid()) {
+ // If here, the parsed ipv4 header is the outer GTP one, but
+ // fabric needs to forward on the inner one, i.e. this.
+ // We store the outer values we need in the metadata, then replace
+ // the ipv4 header extracted before with this one.
+ spgw_meta.s1u_enb_addr = ipv4.src_addr;
+ spgw_meta.s1u_sgw_addr = ipv4.dst_addr;
+ ipv4 = gtpu_ipv4;
+ udp = gtpu_udp;
+
+ if (s1u_filter_table.apply().hit) {
+ // TODO: check also that gtpu.msgtype == GTP_GPDU
+ spgw_meta.do_spgw = true;
+ spgw_meta.direction = DIR_UPLINK;
+ }
+ } else if (ue_filter_table.apply().hit) {
+ spgw_meta.do_spgw = true;
+ spgw_meta.direction = DIR_DOWNLINK;
+ }
+
+ if (!spgw_meta.do_spgw) {
+ // Exit this control block.
+ return;
+ }
+
+ if (spgw_meta.direction == DIR_UPLINK) {
+ gtpu_decap();
+ }
+
+#ifdef WITH_SPGW_PCC_GATING
+ // Allow all traffic by default.
+ spgw_meta.pcc_gate_status = PCC_GATE_OPEN;
+
+ sdf_rule_lookup.apply();
+ pcc_rule_lookup.apply();
+ pcc_info_lookup.apply();
+
+ if (spgw_meta.pcc_gate_status == PCC_GATE_CLOSED) {
+ drop_now();
+ }
+#endif // WITH_SPGW_PCC_GATING
+
+ if (spgw_meta.direction == DIR_DOWNLINK) {
+ if (!dl_sess_lookup.apply().hit) {
+ // We have no other choice than drop, as we miss the session
+ // info necessary to properly GTPU encap the packet.
+ drop_now();
+ }
+ ue_cdr_table.apply();
+ }
+ }
+}
+
+
+control spgw_egress(
+ out ipv4_t gtpu_ipv4,
+ out udp_t gtpu_udp,
+ out gtpu_t gtpu,
+ in spgw_meta_t spgw_meta,
+ in standard_metadata_t std_meta
+ ) {
+
+ action gtpu_encap() {
+ gtpu_ipv4.setValid();
+ gtpu_ipv4.version = IP_VERSION_4;
+ gtpu_ipv4.ihl = IPV4_MIN_IHL;
+ gtpu_ipv4.diffserv = 0;
+ gtpu_ipv4.total_len = ((bit<16>)std_meta.packet_length
+ - ETH_HDR_SIZE + IPV4_HDR_SIZE + UDP_HDR_SIZE + GTP_HDR_SIZE);
+ gtpu_ipv4.identification = 0x1513; /* From NGIC */
+ gtpu_ipv4.flags = 0;
+ gtpu_ipv4.frag_offset = 0;
+ gtpu_ipv4.ttl = DEFAULT_IPV4_TTL;
+ gtpu_ipv4.protocol = PROTO_UDP;
+ gtpu_ipv4.dst_addr = spgw_meta.s1u_enb_addr;
+ gtpu_ipv4.src_addr = spgw_meta.s1u_sgw_addr;
+ gtpu_ipv4.hdr_checksum = 0; // Updated later
+
+ gtpu_udp.setValid();
+ gtpu_udp.src_port = UDP_PORT_GTPU;
+ gtpu_udp.dst_port = UDP_PORT_GTPU;
+ gtpu_udp.len = ((bit<16>)std_meta.packet_length
+ - ETH_HDR_SIZE + UDP_HDR_SIZE + GTP_HDR_SIZE);
+ gtpu_udp.checksum = 0; // Updated later
+
+ gtpu.setValid();
+ gtpu.version = GTPU_VERSION;
+ gtpu.pt = GTP_PROTOCOL_TYPE_GTP;
+ gtpu.spare = 0;
+ gtpu.ex_flag = 0;
+ gtpu.seq_flag = 0;
+ gtpu.npdu_flag = 0;
+ gtpu.msgtype = GTP_GPDU;
+ gtpu.msglen = ((bit<16>)std_meta.packet_length - ETH_HDR_SIZE);
+ gtpu.teid = spgw_meta.teid;
+ }
+
+ apply {
+ if (spgw_meta.do_spgw && spgw_meta.direction == DIR_DOWNLINK) {
+ gtpu_encap();
+ }
+ }
+}
+
+
+control verify_gtpu_checksum(
+ inout ipv4_t gtpu_ipv4
+ ) {
+ apply {
+ // TODO: re-enable gtpu_ipv4 verification
+ // with the current parser logic, gtpu_ip4 contains values of
+ // the inner header, which is already verified by include/checksum.p4.
+ // We need to modify the parser to copy the outer header somewhere
+ // else, and verify that here.
+
+ // verify_checksum(gtpu_ipv4.isValid(),
+ // {
+ // gtpu_ipv4.version,
+ // gtpu_ipv4.ihl,
+ // gtpu_ipv4.diffserv,
+ // gtpu_ipv4.total_len,
+ // gtpu_ipv4.identification,
+ // gtpu_ipv4.flags,
+ // gtpu_ipv4.frag_offset,
+ // gtpu_ipv4.ttl,
+ // gtpu_ipv4.protocol,
+ // gtpu_ipv4.src_addr,
+ // gtpu_ipv4.dst_addr
+ // },
+ // gtpu_ipv4.hdr_checksum,
+ // HashAlgorithm.csum16
+ // );
+ }
+}
+
+
+control update_gtpu_checksum(
+ inout ipv4_t gtpu_ipv4,
+ inout udp_t gtpu_udp,
+ in gtpu_t gtpu,
+ in ipv4_t ipv4,
+ in udp_t udp
+ ) {
+ apply {
+ // Compute outer IPv4 checksum.
+ update_checksum(gtpu_ipv4.isValid(),
+ {
+ gtpu_ipv4.version,
+ gtpu_ipv4.ihl,
+ gtpu_ipv4.diffserv,
+ gtpu_ipv4.total_len,
+ gtpu_ipv4.identification,
+ gtpu_ipv4.flags,
+ gtpu_ipv4.frag_offset,
+ gtpu_ipv4.ttl,
+ gtpu_ipv4.protocol,
+ gtpu_ipv4.src_addr,
+ gtpu_ipv4.dst_addr
+ },
+ gtpu_ipv4.hdr_checksum,
+ HashAlgorithm.csum16
+ );
+
+ // Compute outer UDP checksum.
+ update_checksum_with_payload(gtpu_udp.isValid(),
+ {
+ gtpu_ipv4.src_addr,
+ gtpu_ipv4.dst_addr,
+ 8w0,
+ gtpu_ipv4.protocol,
+ gtpu_udp.len,
+ gtpu_udp.src_port,
+ gtpu_udp.dst_port,
+ gtpu_udp.len,
+ gtpu,
+ ipv4,
+ // FIXME: we are assuming only UDP for downlink packets
+ // How to conditionally switch between UDP/TCP/ICMP?
+ udp
+ },
+ gtpu_udp.checksum,
+ HashAlgorithm.csum16
+ );
+ }
+}
+
+#endif
diff --git a/pipelines/fabric/src/main/resources/p4c-out/bmv2/fabric-spgw.json b/pipelines/fabric/src/main/resources/p4c-out/bmv2/fabric-spgw.json
new file mode 100644
index 0000000..81b13e5
--- /dev/null
+++ b/pipelines/fabric/src/main/resources/p4c-out/bmv2/fabric-spgw.json
@@ -0,0 +1,6244 @@
+{
+ "program" : "fabric.p4",
+ "__meta__" : {
+ "version" : [2, 7],
+ "compiler" : "https://github.com/p4lang/p4c"
+ },
+ "header_types" : [
+ {
+ "name" : "scalars_0",
+ "id" : 0,
+ "fields" : [
+ ["tmp", 4, false],
+ ["tmp_0", 32, false],
+ ["tmp_1", 32, false],
+ ["spgw_ingress_tmp_2", 1, false],
+ ["spgw_ingress_tmp_3", 1, false],
+ ["spgw_ingress_tmp_4", 1, false],
+ ["next_tmp_0", 1, false],
+ ["spgw_ingress_hasReturned_0", 1, false],
+ ["fabric_metadata_t.fwd_type", 3, false],
+ ["fabric_metadata_t.next_id", 32, false],
+ ["fabric_metadata_t.pop_vlan_at_egress", 1, false],
+ ["fabric_metadata_t.ip_proto", 8, false],
+ ["fabric_metadata_t.l4_src_port", 16, false],
+ ["fabric_metadata_t.l4_dst_port", 16, false],
+ ["fabric_metadata_t.original_ether_type", 16, false],
+ ["_padding_1", 3, false]
+ ]
+ },
+ {
+ "name" : "ethernet_t",
+ "id" : 1,
+ "fields" : [
+ ["dst_addr", 48, false],
+ ["src_addr", 48, false],
+ ["ether_type", 16, false]
+ ]
+ },
+ {
+ "name" : "vlan_tag_t",
+ "id" : 2,
+ "fields" : [
+ ["pri", 3, false],
+ ["cfi", 1, false],
+ ["vlan_id", 12, false],
+ ["ether_type", 16, false]
+ ]
+ },
+ {
+ "name" : "mpls_t",
+ "id" : 3,
+ "fields" : [
+ ["label", 20, false],
+ ["tc", 3, false],
+ ["bos", 1, false],
+ ["ttl", 8, false]
+ ]
+ },
+ {
+ "name" : "ipv4_t",
+ "id" : 4,
+ "fields" : [
+ ["version", 4, false],
+ ["ihl", 4, false],
+ ["diffserv", 8, false],
+ ["total_len", 16, false],
+ ["identification", 16, false],
+ ["flags", 3, false],
+ ["frag_offset", 13, false],
+ ["ttl", 8, false],
+ ["protocol", 8, false],
+ ["hdr_checksum", 16, false],
+ ["src_addr", 32, false],
+ ["dst_addr", 32, false]
+ ]
+ },
+ {
+ "name" : "udp_t",
+ "id" : 5,
+ "fields" : [
+ ["src_port", 16, false],
+ ["dst_port", 16, false],
+ ["len", 16, false],
+ ["checksum", 16, false]
+ ]
+ },
+ {
+ "name" : "gtpu_t",
+ "id" : 6,
+ "fields" : [
+ ["version", 3, false],
+ ["pt", 1, false],
+ ["spare", 1, false],
+ ["ex_flag", 1, false],
+ ["seq_flag", 1, false],
+ ["npdu_flag", 1, false],
+ ["msgtype", 8, false],
+ ["msglen", 16, false],
+ ["teid", 32, false]
+ ]
+ },
+ {
+ "name" : "arp_t",
+ "id" : 7,
+ "fields" : [
+ ["hw_type", 16, false],
+ ["proto_type", 16, false],
+ ["hw_addr_len", 8, false],
+ ["proto_addr_len", 8, false],
+ ["opcode", 16, false]
+ ]
+ },
+ {
+ "name" : "tcp_t",
+ "id" : 8,
+ "fields" : [
+ ["src_port", 16, false],
+ ["dst_port", 16, false],
+ ["seq_no", 32, false],
+ ["ack_no", 32, false],
+ ["data_offset", 4, false],
+ ["res", 3, false],
+ ["ecn", 3, false],
+ ["ctrl", 6, false],
+ ["window", 16, false],
+ ["checksum", 16, false],
+ ["urgent_ptr", 16, false]
+ ]
+ },
+ {
+ "name" : "icmp_t",
+ "id" : 9,
+ "fields" : [
+ ["icmp_type", 8, false],
+ ["icmp_code", 8, false],
+ ["checksum", 16, false],
+ ["identifier", 16, false],
+ ["sequence_number", 16, false],
+ ["timestamp", 64, false]
+ ]
+ },
+ {
+ "name" : "packet_out_header_t",
+ "id" : 10,
+ "fields" : [
+ ["egress_port", 9, false],
+ ["_pad", 7, false]
+ ]
+ },
+ {
+ "name" : "packet_in_header_t",
+ "id" : 11,
+ "fields" : [
+ ["ingress_port", 9, false],
+ ["_pad", 7, false]
+ ]
+ },
+ {
+ "name" : "spgw_meta_t",
+ "id" : 12,
+ "fields" : [
+ ["do_spgw", 1, 0],
+ ["direction", 1, false],
+ ["teid", 32, false],
+ ["s1u_enb_addr", 32, false],
+ ["s1u_sgw_addr", 32, false],
+ ["_padding", 6, false]
+ ]
+ },
+ {
+ "name" : "standard_metadata",
+ "id" : 13,
+ "fields" : [
+ ["ingress_port", 9, false],
+ ["egress_spec", 9, false],
+ ["egress_port", 9, false],
+ ["clone_spec", 32, false],
+ ["instance_type", 32, false],
+ ["drop", 1, false],
+ ["recirculate_port", 16, false],
+ ["packet_length", 32, false],
+ ["enq_timestamp", 32, false],
+ ["enq_qdepth", 19, false],
+ ["deq_timedelta", 32, false],
+ ["deq_qdepth", 19, false],
+ ["ingress_global_timestamp", 48, false],
+ ["lf_field_list", 32, false],
+ ["mcast_grp", 16, false],
+ ["resubmit_flag", 1, false],
+ ["egress_rid", 16, false],
+ ["checksum_error", 1, false],
+ ["_padding_0", 4, false]
+ ]
+ }
+ ],
+ "headers" : [
+ {
+ "name" : "scalars",
+ "id" : 0,
+ "header_type" : "scalars_0",
+ "metadata" : true,
+ "pi_omit" : true
+ },
+ {
+ "name" : "standard_metadata",
+ "id" : 1,
+ "header_type" : "standard_metadata",
+ "metadata" : true,
+ "pi_omit" : true
+ },
+ {
+ "name" : "ethernet",
+ "id" : 2,
+ "header_type" : "ethernet_t",
+ "metadata" : false,
+ "pi_omit" : true
+ },
+ {
+ "name" : "vlan_tag",
+ "id" : 3,
+ "header_type" : "vlan_tag_t",
+ "metadata" : false,
+ "pi_omit" : true
+ },
+ {
+ "name" : "mpls",
+ "id" : 4,
+ "header_type" : "mpls_t",
+ "metadata" : false,
+ "pi_omit" : true
+ },
+ {
+ "name" : "gtpu_ipv4",
+ "id" : 5,
+ "header_type" : "ipv4_t",
+ "metadata" : false,
+ "pi_omit" : true
+ },
+ {
+ "name" : "gtpu_udp",
+ "id" : 6,
+ "header_type" : "udp_t",
+ "metadata" : false,
+ "pi_omit" : true
+ },
+ {
+ "name" : "gtpu",
+ "id" : 7,
+ "header_type" : "gtpu_t",
+ "metadata" : false,
+ "pi_omit" : true
+ },
+ {
+ "name" : "ipv4",
+ "id" : 8,
+ "header_type" : "ipv4_t",
+ "metadata" : false,
+ "pi_omit" : true
+ },
+ {
+ "name" : "arp",
+ "id" : 9,
+ "header_type" : "arp_t",
+ "metadata" : false,
+ "pi_omit" : true
+ },
+ {
+ "name" : "tcp",
+ "id" : 10,
+ "header_type" : "tcp_t",
+ "metadata" : false,
+ "pi_omit" : true
+ },
+ {
+ "name" : "udp",
+ "id" : 11,
+ "header_type" : "udp_t",
+ "metadata" : false,
+ "pi_omit" : true
+ },
+ {
+ "name" : "icmp",
+ "id" : 12,
+ "header_type" : "icmp_t",
+ "metadata" : false,
+ "pi_omit" : true
+ },
+ {
+ "name" : "packet_out",
+ "id" : 13,
+ "header_type" : "packet_out_header_t",
+ "metadata" : false,
+ "pi_omit" : true
+ },
+ {
+ "name" : "packet_in",
+ "id" : 14,
+ "header_type" : "packet_in_header_t",
+ "metadata" : false,
+ "pi_omit" : true
+ },
+ {
+ "name" : "spgw",
+ "id" : 15,
+ "header_type" : "spgw_meta_t",
+ "metadata" : true,
+ "pi_omit" : true
+ }
+ ],
+ "header_stacks" : [],
+ "header_union_types" : [],
+ "header_unions" : [],
+ "header_union_stacks" : [],
+ "field_lists" : [],
+ "errors" : [
+ ["NoError", 1],
+ ["PacketTooShort", 2],
+ ["NoMatch", 3],
+ ["StackOutOfBounds", 4],
+ ["HeaderTooShort", 5],
+ ["ParserTimeout", 6]
+ ],
+ "enums" : [],
+ "parsers" : [
+ {
+ "name" : "parser",
+ "id" : 0,
+ "init_state" : "start",
+ "parse_states" : [
+ {
+ "name" : "start",
+ "id" : 0,
+ "parser_ops" : [],
+ "transitions" : [
+ {
+ "value" : "0x00ff",
+ "mask" : null,
+ "next_state" : "parse_packet_out"
+ },
+ {
+ "value" : "default",
+ "mask" : null,
+ "next_state" : "parse_ethernet"
+ }
+ ],
+ "transition_key" : [
+ {
+ "type" : "field",
+ "value" : ["standard_metadata", "ingress_port"]
+ }
+ ]
+ },
+ {
+ "name" : "parse_packet_out",
+ "id" : 1,
+ "parser_ops" : [
+ {
+ "parameters" : [
+ {
+ "type" : "regular",
+ "value" : "packet_out"
+ }
+ ],
+ "op" : "extract"
+ }
+ ],
+ "transitions" : [
+ {
+ "value" : "default",
+ "mask" : null,
+ "next_state" : "parse_ethernet"
+ }
+ ],
+ "transition_key" : []
+ },
+ {
+ "name" : "parse_ethernet",
+ "id" : 2,
+ "parser_ops" : [
+ {
+ "parameters" : [
+ {
+ "type" : "regular",
+ "value" : "ethernet"
+ }
+ ],
+ "op" : "extract"
+ },
+ {
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["scalars", "fabric_metadata_t.original_ether_type"]
+ },
+ {
+ "type" : "field",
+ "value" : ["ethernet", "ether_type"]
+ }
+ ],
+ "op" : "set"
+ }
+ ],
+ "transitions" : [
+ {
+ "value" : "0x8100",
+ "mask" : null,
+ "next_state" : "parse_vlan_tag"
+ },
+ {
+ "value" : "0x8847",
+ "mask" : null,
+ "next_state" : "parse_mpls"
+ },
+ {
+ "value" : "0x0806",
+ "mask" : null,
+ "next_state" : "parse_arp"
+ },
+ {
+ "value" : "0x0800",
+ "mask" : null,
+ "next_state" : "parse_ipv4"
+ },
+ {
+ "value" : "default",
+ "mask" : null,
+ "next_state" : null
+ }
+ ],
+ "transition_key" : [
+ {
+ "type" : "field",
+ "value" : ["ethernet", "ether_type"]
+ }
+ ]
+ },
+ {
+ "name" : "parse_vlan_tag",
+ "id" : 3,
+ "parser_ops" : [
+ {
+ "parameters" : [
+ {
+ "type" : "regular",
+ "value" : "vlan_tag"
+ }
+ ],
+ "op" : "extract"
+ }
+ ],
+ "transitions" : [
+ {
+ "value" : "0x0806",
+ "mask" : null,
+ "next_state" : "parse_arp"
+ },
+ {
+ "value" : "0x0800",
+ "mask" : null,
+ "next_state" : "parse_ipv4"
+ },
+ {
+ "value" : "0x8847",
+ "mask" : null,
+ "next_state" : "parse_mpls"
+ },
+ {
+ "value" : "default",
+ "mask" : null,
+ "next_state" : null
+ }
+ ],
+ "transition_key" : [
+ {
+ "type" : "field",
+ "value" : ["vlan_tag", "ether_type"]
+ }
+ ]
+ },
+ {
+ "name" : "parse_mpls",
+ "id" : 4,
+ "parser_ops" : [
+ {
+ "parameters" : [
+ {
+ "type" : "regular",
+ "value" : "mpls"
+ }
+ ],
+ "op" : "extract"
+ },
+ {
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["scalars", "tmp"]
+ },
+ {
+ "type" : "lookahead",
+ "value" : [0, 4]
+ }
+ ],
+ "op" : "set"
+ }
+ ],
+ "transitions" : [
+ {
+ "value" : "0x04",
+ "mask" : null,
+ "next_state" : "parse_ipv4"
+ },
+ {
+ "value" : "default",
+ "mask" : null,
+ "next_state" : "parse_ethernet"
+ }
+ ],
+ "transition_key" : [
+ {
+ "type" : "field",
+ "value" : ["scalars", "tmp"]
+ }
+ ]
+ },
+ {
+ "name" : "parse_ipv4",
+ "id" : 5,
+ "parser_ops" : [
+ {
+ "parameters" : [
+ {
+ "type" : "regular",
+ "value" : "ipv4"
+ }
+ ],
+ "op" : "extract"
+ },
+ {
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["scalars", "fabric_metadata_t.ip_proto"]
+ },
+ {
+ "type" : "field",
+ "value" : ["ipv4", "protocol"]
+ }
+ ],
+ "op" : "set"
+ }
+ ],
+ "transitions" : [
+ {
+ "value" : "0x06",
+ "mask" : null,
+ "next_state" : "parse_tcp"
+ },
+ {
+ "value" : "0x11",
+ "mask" : null,
+ "next_state" : "parse_udp"
+ },
+ {
+ "value" : "0x01",
+ "mask" : null,
+ "next_state" : "parse_icmp"
+ },
+ {
+ "value" : "default",
+ "mask" : null,
+ "next_state" : null
+ }
+ ],
+ "transition_key" : [
+ {
+ "type" : "field",
+ "value" : ["ipv4", "protocol"]
+ }
+ ]
+ },
+ {
+ "name" : "parse_arp",
+ "id" : 6,
+ "parser_ops" : [
+ {
+ "parameters" : [
+ {
+ "type" : "regular",
+ "value" : "arp"
+ }
+ ],
+ "op" : "extract"
+ }
+ ],
+ "transitions" : [
+ {
+ "value" : "default",
+ "mask" : null,
+ "next_state" : null
+ }
+ ],
+ "transition_key" : []
+ },
+ {
+ "name" : "parse_tcp",
+ "id" : 7,
+ "parser_ops" : [
+ {
+ "parameters" : [
+ {
+ "type" : "regular",
+ "value" : "tcp"
+ }
+ ],
+ "op" : "extract"
+ },
+ {
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["scalars", "fabric_metadata_t.l4_src_port"]
+ },
+ {
+ "type" : "field",
+ "value" : ["tcp", "src_port"]
+ }
+ ],
+ "op" : "set"
+ },
+ {
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["scalars", "fabric_metadata_t.l4_dst_port"]
+ },
+ {
+ "type" : "field",
+ "value" : ["tcp", "dst_port"]
+ }
+ ],
+ "op" : "set"
+ }
+ ],
+ "transitions" : [
+ {
+ "value" : "default",
+ "mask" : null,
+ "next_state" : null
+ }
+ ],
+ "transition_key" : []
+ },
+ {
+ "name" : "parse_udp",
+ "id" : 8,
+ "parser_ops" : [
+ {
+ "parameters" : [
+ {
+ "type" : "regular",
+ "value" : "udp"
+ }
+ ],
+ "op" : "extract"
+ },
+ {
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["scalars", "fabric_metadata_t.l4_src_port"]
+ },
+ {
+ "type" : "field",
+ "value" : ["udp", "src_port"]
+ }
+ ],
+ "op" : "set"
+ },
+ {
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["scalars", "fabric_metadata_t.l4_dst_port"]
+ },
+ {
+ "type" : "field",
+ "value" : ["udp", "dst_port"]
+ }
+ ],
+ "op" : "set"
+ }
+ ],
+ "transitions" : [
+ {
+ "value" : "0x0868",
+ "mask" : null,
+ "next_state" : "parse_gtpu"
+ },
+ {
+ "value" : "default",
+ "mask" : null,
+ "next_state" : null
+ }
+ ],
+ "transition_key" : [
+ {
+ "type" : "field",
+ "value" : ["udp", "dst_port"]
+ }
+ ]
+ },
+ {
+ "name" : "parse_icmp",
+ "id" : 9,
+ "parser_ops" : [
+ {
+ "parameters" : [
+ {
+ "type" : "regular",
+ "value" : "icmp"
+ }
+ ],
+ "op" : "extract"
+ }
+ ],
+ "transitions" : [
+ {
+ "value" : "default",
+ "mask" : null,
+ "next_state" : null
+ }
+ ],
+ "transition_key" : []
+ },
+ {
+ "name" : "parse_gtpu",
+ "id" : 10,
+ "parser_ops" : [
+ {
+ "parameters" : [
+ {
+ "type" : "regular",
+ "value" : "gtpu"
+ }
+ ],
+ "op" : "extract"
+ },
+ {
+ "parameters" : [
+ {
+ "type" : "regular",
+ "value" : "gtpu_ipv4"
+ }
+ ],
+ "op" : "extract"
+ }
+ ],
+ "transitions" : [
+ {
+ "value" : "0x06",
+ "mask" : null,
+ "next_state" : "parse_tcp"
+ },
+ {
+ "value" : "0x11",
+ "mask" : null,
+ "next_state" : "parse_udp_inner"
+ },
+ {
+ "value" : "0x01",
+ "mask" : null,
+ "next_state" : "parse_icmp"
+ },
+ {
+ "value" : "default",
+ "mask" : null,
+ "next_state" : null
+ }
+ ],
+ "transition_key" : [
+ {
+ "type" : "field",
+ "value" : ["gtpu_ipv4", "protocol"]
+ }
+ ]
+ },
+ {
+ "name" : "parse_udp_inner",
+ "id" : 11,
+ "parser_ops" : [
+ {
+ "parameters" : [
+ {
+ "type" : "regular",
+ "value" : "gtpu_udp"
+ }
+ ],
+ "op" : "extract"
+ },
+ {
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["scalars", "fabric_metadata_t.l4_src_port"]
+ },
+ {
+ "type" : "field",
+ "value" : ["gtpu_udp", "src_port"]
+ }
+ ],
+ "op" : "set"
+ },
+ {
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["scalars", "fabric_metadata_t.l4_dst_port"]
+ },
+ {
+ "type" : "field",
+ "value" : ["gtpu_udp", "dst_port"]
+ }
+ ],
+ "op" : "set"
+ }
+ ],
+ "transitions" : [
+ {
+ "value" : "default",
+ "mask" : null,
+ "next_state" : null
+ }
+ ],
+ "transition_key" : []
+ }
+ ]
+ }
+ ],
+ "deparsers" : [
+ {
+ "name" : "deparser",
+ "id" : 0,
+ "source_info" : {
+ "filename" : "include/parser.p4",
+ "line" : 164,
+ "column" : 8,
+ "source_fragment" : "FabricDeparser"
+ },
+ "order" : ["packet_in", "ethernet", "vlan_tag", "mpls", "arp", "gtpu_ipv4", "gtpu_udp", "gtpu", "ipv4", "tcp", "udp", "icmp"]
+ }
+ ],
+ "meter_arrays" : [],
+ "counter_arrays" : [
+ {
+ "name" : "spgw_ingress.ue_counter",
+ "id" : 0,
+ "is_direct" : true,
+ "binding" : "spgw_ingress.ue_cdr_table"
+ },
+ {
+ "name" : "filtering.ingress_port_vlan_counter",
+ "id" : 1,
+ "is_direct" : true,
+ "binding" : "filtering.ingress_port_vlan"
+ },
+ {
+ "name" : "filtering.fwd_classifier_counter",
+ "id" : 2,
+ "is_direct" : true,
+ "binding" : "filtering.fwd_classifier"
+ },
+ {
+ "name" : "forwarding.bridging_counter",
+ "id" : 3,
+ "is_direct" : true,
+ "binding" : "forwarding.bridging"
+ },
+ {
+ "name" : "forwarding.mpls_counter",
+ "id" : 4,
+ "is_direct" : true,
+ "binding" : "forwarding.mpls"
+ },
+ {
+ "name" : "forwarding.unicast_v4_counter",
+ "id" : 5,
+ "is_direct" : true,
+ "binding" : "forwarding.unicast_v4"
+ },
+ {
+ "name" : "forwarding.multicast_v4_counter",
+ "id" : 6,
+ "is_direct" : true,
+ "binding" : "forwarding.multicast_v4"
+ },
+ {
+ "name" : "forwarding.acl_counter",
+ "id" : 7,
+ "is_direct" : true,
+ "binding" : "forwarding.acl"
+ },
+ {
+ "name" : "next.simple_counter",
+ "id" : 8,
+ "is_direct" : true,
+ "binding" : "next.simple"
+ },
+ {
+ "name" : "next.hashed_counter",
+ "id" : 9,
+ "is_direct" : true,
+ "binding" : "next.hashed"
+ },
+ {
+ "name" : "next.broadcast_counter",
+ "id" : 10,
+ "is_direct" : true,
+ "binding" : "next.broadcast"
+ },
+ {
+ "name" : "port_counters_control.egress_port_counter",
+ "id" : 11,
+ "source_info" : {
+ "filename" : "include/control/port_counter.p4",
+ "line" : 23,
+ "column" : 38,
+ "source_fragment" : "egress_port_counter"
+ },
+ "size" : 511,
+ "is_direct" : false
+ },
+ {
+ "name" : "port_counters_control.ingress_port_counter",
+ "id" : 12,
+ "source_info" : {
+ "filename" : "include/control/port_counter.p4",
+ "line" : 24,
+ "column" : 38,
+ "source_fragment" : "ingress_port_counter"
+ },
+ "size" : 511,
+ "is_direct" : false
+ }
+ ],
+ "register_arrays" : [],
+ "calculations" : [
+ {
+ "name" : "calc",
+ "id" : 0,
+ "source_info" : {
+ "filename" : "include/checksum.p4",
+ "line" : 56,
+ "column" : 8,
+ "source_fragment" : "verify_checksum(hdr.ipv4.isValid(), ..."
+ },
+ "algo" : "csum16",
+ "input" : [
+ {
+ "type" : "field",
+ "value" : ["ipv4", "version"]
+ },
+ {
+ "type" : "field",
+ "value" : ["ipv4", "ihl"]
+ },
+ {
+ "type" : "field",
+ "value" : ["ipv4", "diffserv"]
+ },
+ {
+ "type" : "field",
+ "value" : ["ipv4", "total_len"]
+ },
+ {
+ "type" : "field",
+ "value" : ["ipv4", "identification"]
+ },
+ {
+ "type" : "field",
+ "value" : ["ipv4", "flags"]
+ },
+ {
+ "type" : "field",
+ "value" : ["ipv4", "frag_offset"]
+ },
+ {
+ "type" : "field",
+ "value" : ["ipv4", "ttl"]
+ },
+ {
+ "type" : "field",
+ "value" : ["ipv4", "protocol"]
+ },
+ {
+ "type" : "field",
+ "value" : ["ipv4", "src_addr"]
+ },
+ {
+ "type" : "field",
+ "value" : ["ipv4", "dst_addr"]
+ }
+ ]
+ },
+ {
+ "name" : "calc_0",
+ "id" : 1,
+ "source_info" : {
+ "filename" : "include/checksum.p4",
+ "line" : 28,
+ "column" : 8,
+ "source_fragment" : "update_checksum(hdr.ipv4.isValid(), ..."
+ },
+ "algo" : "csum16",
+ "input" : [
+ {
+ "type" : "field",
+ "value" : ["ipv4", "version"]
+ },
+ {
+ "type" : "field",
+ "value" : ["ipv4", "ihl"]
+ },
+ {
+ "type" : "field",
+ "value" : ["ipv4", "diffserv"]
+ },
+ {
+ "type" : "field",
+ "value" : ["ipv4", "total_len"]
+ },
+ {
+ "type" : "field",
+ "value" : ["ipv4", "identification"]
+ },
+ {
+ "type" : "field",
+ "value" : ["ipv4", "flags"]
+ },
+ {
+ "type" : "field",
+ "value" : ["ipv4", "frag_offset"]
+ },
+ {
+ "type" : "field",
+ "value" : ["ipv4", "ttl"]
+ },
+ {
+ "type" : "field",
+ "value" : ["ipv4", "protocol"]
+ },
+ {
+ "type" : "field",
+ "value" : ["ipv4", "src_addr"]
+ },
+ {
+ "type" : "field",
+ "value" : ["ipv4", "dst_addr"]
+ }
+ ]
+ },
+ {
+ "name" : "calc_1",
+ "id" : 2,
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 292,
+ "column" : 8,
+ "source_fragment" : "update_checksum(gtpu_ipv4.isValid(), ..."
+ },
+ "algo" : "csum16",
+ "input" : [
+ {
+ "type" : "field",
+ "value" : ["gtpu_ipv4", "version"]
+ },
+ {
+ "type" : "field",
+ "value" : ["gtpu_ipv4", "ihl"]
+ },
+ {
+ "type" : "field",
+ "value" : ["gtpu_ipv4", "diffserv"]
+ },
+ {
+ "type" : "field",
+ "value" : ["gtpu_ipv4", "total_len"]
+ },
+ {
+ "type" : "field",
+ "value" : ["gtpu_ipv4", "identification"]
+ },
+ {
+ "type" : "field",
+ "value" : ["gtpu_ipv4", "flags"]
+ },
+ {
+ "type" : "field",
+ "value" : ["gtpu_ipv4", "frag_offset"]
+ },
+ {
+ "type" : "field",
+ "value" : ["gtpu_ipv4", "ttl"]
+ },
+ {
+ "type" : "field",
+ "value" : ["gtpu_ipv4", "protocol"]
+ },
+ {
+ "type" : "field",
+ "value" : ["gtpu_ipv4", "src_addr"]
+ },
+ {
+ "type" : "field",
+ "value" : ["gtpu_ipv4", "dst_addr"]
+ }
+ ]
+ },
+ {
+ "name" : "calc_2",
+ "id" : 3,
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 311,
+ "column" : 8,
+ "source_fragment" : "update_checksum_with_payload(gtpu_udp.isValid(), ..."
+ },
+ "algo" : "csum16",
+ "input" : [
+ {
+ "type" : "field",
+ "value" : ["gtpu_ipv4", "src_addr"]
+ },
+ {
+ "type" : "field",
+ "value" : ["gtpu_ipv4", "dst_addr"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x00",
+ "bitwidth" : 8
+ },
+ {
+ "type" : "field",
+ "value" : ["gtpu_ipv4", "protocol"]
+ },
+ {
+ "type" : "field",
+ "value" : ["gtpu_udp", "len"]
+ },
+ {
+ "type" : "field",
+ "value" : ["gtpu_udp", "src_port"]
+ },
+ {
+ "type" : "field",
+ "value" : ["gtpu_udp", "dst_port"]
+ },
+ {
+ "type" : "field",
+ "value" : ["gtpu_udp", "len"]
+ },
+ {
+ "type" : "header",
+ "value" : "gtpu"
+ },
+ {
+ "type" : "header",
+ "value" : "ipv4"
+ },
+ {
+ "type" : "header",
+ "value" : "udp"
+ },
+ {
+ "type" : "payload",
+ "value" : null
+ }
+ ]
+ }
+ ],
+ "learn_lists" : [],
+ "actions" : [
+ {
+ "name" : "NoAction",
+ "id" : 0,
+ "runtime_data" : [],
+ "primitives" : []
+ },
+ {
+ "name" : "NoAction",
+ "id" : 1,
+ "runtime_data" : [],
+ "primitives" : []
+ },
+ {
+ "name" : "NoAction",
+ "id" : 2,
+ "runtime_data" : [],
+ "primitives" : []
+ },
+ {
+ "name" : "NoAction",
+ "id" : 3,
+ "runtime_data" : [],
+ "primitives" : []
+ },
+ {
+ "name" : "NoAction",
+ "id" : 4,
+ "runtime_data" : [],
+ "primitives" : []
+ },
+ {
+ "name" : "NoAction",
+ "id" : 5,
+ "runtime_data" : [],
+ "primitives" : []
+ },
+ {
+ "name" : "NoAction",
+ "id" : 6,
+ "runtime_data" : [],
+ "primitives" : []
+ },
+ {
+ "name" : "NoAction",
+ "id" : 7,
+ "runtime_data" : [],
+ "primitives" : []
+ },
+ {
+ "name" : "NoAction",
+ "id" : 8,
+ "runtime_data" : [],
+ "primitives" : []
+ },
+ {
+ "name" : "NoAction",
+ "id" : 9,
+ "runtime_data" : [],
+ "primitives" : []
+ },
+ {
+ "name" : "NoAction",
+ "id" : 10,
+ "runtime_data" : [],
+ "primitives" : []
+ },
+ {
+ "name" : "nop",
+ "id" : 11,
+ "runtime_data" : [],
+ "primitives" : []
+ },
+ {
+ "name" : "nop",
+ "id" : 12,
+ "runtime_data" : [],
+ "primitives" : []
+ },
+ {
+ "name" : "spgw_ingress.drop_now",
+ "id" : 13,
+ "runtime_data" : [],
+ "primitives" : [
+ {
+ "op" : "drop",
+ "parameters" : [],
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 33,
+ "column" : 8,
+ "source_fragment" : "mark_to_drop()"
+ }
+ },
+ {
+ "op" : "exit",
+ "parameters" : [],
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 34,
+ "column" : 8,
+ "source_fragment" : "exit"
+ }
+ }
+ ]
+ },
+ {
+ "name" : "spgw_ingress.gtpu_decap",
+ "id" : 14,
+ "runtime_data" : [],
+ "primitives" : [
+ {
+ "op" : "remove_header",
+ "parameters" : [
+ {
+ "type" : "header",
+ "value" : "gtpu_ipv4"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 38,
+ "column" : 8,
+ "source_fragment" : "gtpu_ipv4.setInvalid()"
+ }
+ },
+ {
+ "op" : "remove_header",
+ "parameters" : [
+ {
+ "type" : "header",
+ "value" : "gtpu_udp"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 39,
+ "column" : 8,
+ "source_fragment" : "gtpu_udp.setInvalid()"
+ }
+ },
+ {
+ "op" : "remove_header",
+ "parameters" : [
+ {
+ "type" : "header",
+ "value" : "gtpu"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 40,
+ "column" : 8,
+ "source_fragment" : "gtpu.setInvalid()"
+ }
+ }
+ ]
+ },
+ {
+ "name" : "spgw_ingress.set_dl_sess_info",
+ "id" : 15,
+ "runtime_data" : [
+ {
+ "name" : "teid",
+ "bitwidth" : 32
+ },
+ {
+ "name" : "s1u_enb_addr",
+ "bitwidth" : 32
+ },
+ {
+ "name" : "s1u_sgw_addr",
+ "bitwidth" : 32
+ }
+ ],
+ "primitives" : [
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["spgw", "teid"]
+ },
+ {
+ "type" : "runtime_data",
+ "value" : 0
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 46,
+ "column" : 8,
+ "source_fragment" : "spgw_meta.teid = teid"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["spgw", "s1u_enb_addr"]
+ },
+ {
+ "type" : "runtime_data",
+ "value" : 1
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 47,
+ "column" : 8,
+ "source_fragment" : "spgw_meta.s1u_enb_addr = s1u_enb_addr"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["spgw", "s1u_sgw_addr"]
+ },
+ {
+ "type" : "runtime_data",
+ "value" : 2
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 48,
+ "column" : 8,
+ "source_fragment" : "spgw_meta.s1u_sgw_addr = s1u_sgw_addr"
+ }
+ }
+ ]
+ },
+ {
+ "name" : "spgw_ingress.update_ue_cdr",
+ "id" : 16,
+ "runtime_data" : [],
+ "primitives" : []
+ },
+ {
+ "name" : "filtering.drop",
+ "id" : 17,
+ "runtime_data" : [],
+ "primitives" : [
+ {
+ "op" : "drop",
+ "parameters" : [],
+ "source_info" : {
+ "filename" : "include/control/filtering.p4",
+ "line" : 31,
+ "column" : 8,
+ "source_fragment" : "mark_to_drop()"
+ }
+ }
+ ]
+ },
+ {
+ "name" : "filtering.set_vlan",
+ "id" : 18,
+ "runtime_data" : [
+ {
+ "name" : "new_vlan_id",
+ "bitwidth" : 12
+ }
+ ],
+ "primitives" : [
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["vlan_tag", "vlan_id"]
+ },
+ {
+ "type" : "runtime_data",
+ "value" : 0
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/filtering.p4",
+ "line" : 35,
+ "column" : 8,
+ "source_fragment" : "hdr.vlan_tag.vlan_id = new_vlan_id"
+ }
+ }
+ ]
+ },
+ {
+ "name" : "filtering.push_internal_vlan",
+ "id" : 19,
+ "runtime_data" : [
+ {
+ "name" : "new_vlan_id",
+ "bitwidth" : 12
+ }
+ ],
+ "primitives" : [
+ {
+ "op" : "add_header",
+ "parameters" : [
+ {
+ "type" : "header",
+ "value" : "vlan_tag"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/filtering.p4",
+ "line" : 41,
+ "column" : 8,
+ "source_fragment" : "hdr.vlan_tag.setValid()"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["vlan_tag", "cfi"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x00"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/filtering.p4",
+ "line" : 42,
+ "column" : 8,
+ "source_fragment" : "hdr.vlan_tag.cfi = 0"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["vlan_tag", "pri"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x00"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/filtering.p4",
+ "line" : 43,
+ "column" : 8,
+ "source_fragment" : "hdr.vlan_tag.pri = 0"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["vlan_tag", "ether_type"]
+ },
+ {
+ "type" : "field",
+ "value" : ["ethernet", "ether_type"]
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/filtering.p4",
+ "line" : 44,
+ "column" : 8,
+ "source_fragment" : "hdr.vlan_tag.ether_type = hdr.ethernet.ether_type"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["ethernet", "ether_type"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x8100"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/../define.p4",
+ "line" : 32,
+ "column" : 31,
+ "source_fragment" : "0x8100; ..."
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["vlan_tag", "vlan_id"]
+ },
+ {
+ "type" : "runtime_data",
+ "value" : 0
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/filtering.p4",
+ "line" : 35,
+ "column" : 8,
+ "source_fragment" : "hdr.vlan_tag.vlan_id = new_vlan_id; ..."
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["scalars", "fabric_metadata_t.pop_vlan_at_egress"]
+ },
+ {
+ "type" : "expression",
+ "value" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "b2d",
+ "left" : null,
+ "right" : {
+ "type" : "bool",
+ "value" : true
+ }
+ }
+ }
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/filtering.p4",
+ "line" : 49,
+ "column" : 8,
+ "source_fragment" : "fabric_metadata.pop_vlan_at_egress = true"
+ }
+ }
+ ]
+ },
+ {
+ "name" : "filtering.set_forwarding_type",
+ "id" : 20,
+ "runtime_data" : [
+ {
+ "name" : "fwd_type",
+ "bitwidth" : 3
+ }
+ ],
+ "primitives" : [
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["scalars", "fabric_metadata_t.fwd_type"]
+ },
+ {
+ "type" : "runtime_data",
+ "value" : 0
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/filtering.p4",
+ "line" : 53,
+ "column" : 8,
+ "source_fragment" : "fabric_metadata.fwd_type = fwd_type"
+ }
+ }
+ ]
+ },
+ {
+ "name" : "forwarding.drop",
+ "id" : 21,
+ "runtime_data" : [],
+ "primitives" : [
+ {
+ "op" : "drop",
+ "parameters" : [],
+ "source_info" : {
+ "filename" : "include/control/forwarding.p4",
+ "line" : 37,
+ "column" : 8,
+ "source_fragment" : "mark_to_drop()"
+ }
+ }
+ ]
+ },
+ {
+ "name" : "forwarding.set_next_id",
+ "id" : 22,
+ "runtime_data" : [
+ {
+ "name" : "next_id",
+ "bitwidth" : 32
+ }
+ ],
+ "primitives" : [
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["scalars", "fabric_metadata_t.next_id"]
+ },
+ {
+ "type" : "runtime_data",
+ "value" : 0
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/forwarding.p4",
+ "line" : 41,
+ "column" : 8,
+ "source_fragment" : "fabric_metadata.next_id = next_id"
+ }
+ }
+ ]
+ },
+ {
+ "name" : "forwarding.set_next_id",
+ "id" : 23,
+ "runtime_data" : [
+ {
+ "name" : "next_id",
+ "bitwidth" : 32
+ }
+ ],
+ "primitives" : [
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["scalars", "fabric_metadata_t.next_id"]
+ },
+ {
+ "type" : "runtime_data",
+ "value" : 0
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/forwarding.p4",
+ "line" : 41,
+ "column" : 8,
+ "source_fragment" : "fabric_metadata.next_id = next_id"
+ }
+ }
+ ]
+ },
+ {
+ "name" : "forwarding.set_next_id",
+ "id" : 24,
+ "runtime_data" : [
+ {
+ "name" : "next_id",
+ "bitwidth" : 32
+ }
+ ],
+ "primitives" : [
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["scalars", "fabric_metadata_t.next_id"]
+ },
+ {
+ "type" : "runtime_data",
+ "value" : 0
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/forwarding.p4",
+ "line" : 41,
+ "column" : 8,
+ "source_fragment" : "fabric_metadata.next_id = next_id"
+ }
+ }
+ ]
+ },
+ {
+ "name" : "forwarding.set_next_id",
+ "id" : 25,
+ "runtime_data" : [
+ {
+ "name" : "next_id",
+ "bitwidth" : 32
+ }
+ ],
+ "primitives" : [
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["scalars", "fabric_metadata_t.next_id"]
+ },
+ {
+ "type" : "runtime_data",
+ "value" : 0
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/forwarding.p4",
+ "line" : 41,
+ "column" : 8,
+ "source_fragment" : "fabric_metadata.next_id = next_id"
+ }
+ }
+ ]
+ },
+ {
+ "name" : "forwarding.pop_mpls_and_next",
+ "id" : 26,
+ "runtime_data" : [
+ {
+ "name" : "next_id",
+ "bitwidth" : 32
+ }
+ ],
+ "primitives" : [
+ {
+ "op" : "remove_header",
+ "parameters" : [
+ {
+ "type" : "header",
+ "value" : "mpls"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/forwarding.p4",
+ "line" : 45,
+ "column" : 8,
+ "source_fragment" : "hdr.mpls.setInvalid()"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["scalars", "fabric_metadata_t.next_id"]
+ },
+ {
+ "type" : "runtime_data",
+ "value" : 0
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/forwarding.p4",
+ "line" : 46,
+ "column" : 8,
+ "source_fragment" : "fabric_metadata.next_id = next_id"
+ }
+ }
+ ]
+ },
+ {
+ "name" : "forwarding.duplicate_to_controller",
+ "id" : 27,
+ "runtime_data" : [],
+ "primitives" : [
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["standard_metadata", "egress_spec"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x00ff"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/../define.p4",
+ "line" : 50,
+ "column" : 28,
+ "source_fragment" : "255; ..."
+ }
+ }
+ ]
+ },
+ {
+ "name" : "next.output",
+ "id" : 28,
+ "runtime_data" : [
+ {
+ "name" : "port_num",
+ "bitwidth" : 9
+ }
+ ],
+ "primitives" : [
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["standard_metadata", "egress_spec"]
+ },
+ {
+ "type" : "runtime_data",
+ "value" : 0
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 33,
+ "column" : 8,
+ "source_fragment" : "standard_metadata.egress_spec = port_num"
+ }
+ }
+ ]
+ },
+ {
+ "name" : "next.set_vlan_output",
+ "id" : 29,
+ "runtime_data" : [
+ {
+ "name" : "new_vlan_id",
+ "bitwidth" : 12
+ },
+ {
+ "name" : "port_num",
+ "bitwidth" : 9
+ }
+ ],
+ "primitives" : [
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["vlan_tag", "vlan_id"]
+ },
+ {
+ "type" : "runtime_data",
+ "value" : 0
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 37,
+ "column" : 8,
+ "source_fragment" : "hdr.vlan_tag.vlan_id = new_vlan_id"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["scalars", "fabric_metadata_t.pop_vlan_at_egress"]
+ },
+ {
+ "type" : "expression",
+ "value" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "b2d",
+ "left" : null,
+ "right" : {
+ "type" : "bool",
+ "value" : false
+ }
+ }
+ }
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 40,
+ "column" : 8,
+ "source_fragment" : "fabric_metadata.pop_vlan_at_egress = false"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["standard_metadata", "egress_spec"]
+ },
+ {
+ "type" : "runtime_data",
+ "value" : 1
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 33,
+ "column" : 8,
+ "source_fragment" : "standard_metadata.egress_spec = port_num; ..."
+ }
+ }
+ ]
+ },
+ {
+ "name" : "next.l3_routing",
+ "id" : 30,
+ "runtime_data" : [
+ {
+ "name" : "port_num",
+ "bitwidth" : 9
+ },
+ {
+ "name" : "smac",
+ "bitwidth" : 48
+ },
+ {
+ "name" : "dmac",
+ "bitwidth" : 48
+ }
+ ],
+ "primitives" : [
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["ethernet", "src_addr"]
+ },
+ {
+ "type" : "runtime_data",
+ "value" : 1
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 45,
+ "column" : 8,
+ "source_fragment" : "hdr.ethernet.src_addr = smac; ..."
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["ethernet", "dst_addr"]
+ },
+ {
+ "type" : "runtime_data",
+ "value" : 2
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 49,
+ "column" : 8,
+ "source_fragment" : "hdr.ethernet.dst_addr = dmac; ..."
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["standard_metadata", "egress_spec"]
+ },
+ {
+ "type" : "runtime_data",
+ "value" : 0
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 33,
+ "column" : 8,
+ "source_fragment" : "standard_metadata.egress_spec = port_num; ..."
+ }
+ }
+ ]
+ },
+ {
+ "name" : "next.l3_routing",
+ "id" : 31,
+ "runtime_data" : [
+ {
+ "name" : "port_num",
+ "bitwidth" : 9
+ },
+ {
+ "name" : "smac",
+ "bitwidth" : 48
+ },
+ {
+ "name" : "dmac",
+ "bitwidth" : 48
+ }
+ ],
+ "primitives" : [
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["ethernet", "src_addr"]
+ },
+ {
+ "type" : "runtime_data",
+ "value" : 1
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 45,
+ "column" : 8,
+ "source_fragment" : "hdr.ethernet.src_addr = smac; ..."
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["ethernet", "dst_addr"]
+ },
+ {
+ "type" : "runtime_data",
+ "value" : 2
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 49,
+ "column" : 8,
+ "source_fragment" : "hdr.ethernet.dst_addr = dmac; ..."
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["standard_metadata", "egress_spec"]
+ },
+ {
+ "type" : "runtime_data",
+ "value" : 0
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 33,
+ "column" : 8,
+ "source_fragment" : "standard_metadata.egress_spec = port_num; ..."
+ }
+ }
+ ]
+ },
+ {
+ "name" : "next.set_mcast_group",
+ "id" : 32,
+ "runtime_data" : [
+ {
+ "name" : "gid",
+ "bitwidth" : 16
+ },
+ {
+ "name" : "smac",
+ "bitwidth" : 48
+ }
+ ],
+ "primitives" : [
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["standard_metadata", "mcast_grp"]
+ },
+ {
+ "type" : "runtime_data",
+ "value" : 0
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 59,
+ "column" : 8,
+ "source_fragment" : "standard_metadata.mcast_grp = gid"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["ethernet", "src_addr"]
+ },
+ {
+ "type" : "runtime_data",
+ "value" : 1
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 45,
+ "column" : 8,
+ "source_fragment" : "hdr.ethernet.src_addr = smac; ..."
+ }
+ }
+ ]
+ },
+ {
+ "name" : "next.mpls_routing_v4",
+ "id" : 33,
+ "runtime_data" : [
+ {
+ "name" : "port_num",
+ "bitwidth" : 9
+ },
+ {
+ "name" : "smac",
+ "bitwidth" : 48
+ },
+ {
+ "name" : "dmac",
+ "bitwidth" : 48
+ },
+ {
+ "name" : "label",
+ "bitwidth" : 20
+ }
+ ],
+ "primitives" : [
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["ethernet", "src_addr"]
+ },
+ {
+ "type" : "runtime_data",
+ "value" : 1
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 45,
+ "column" : 8,
+ "source_fragment" : "hdr.ethernet.src_addr = smac; ..."
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["ethernet", "dst_addr"]
+ },
+ {
+ "type" : "runtime_data",
+ "value" : 2
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 49,
+ "column" : 8,
+ "source_fragment" : "hdr.ethernet.dst_addr = dmac; ..."
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["standard_metadata", "egress_spec"]
+ },
+ {
+ "type" : "runtime_data",
+ "value" : 0
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 33,
+ "column" : 8,
+ "source_fragment" : "standard_metadata.egress_spec = port_num; ..."
+ }
+ },
+ {
+ "op" : "add_header",
+ "parameters" : [
+ {
+ "type" : "header",
+ "value" : "mpls"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 65,
+ "column" : 8,
+ "source_fragment" : "hdr.mpls.setValid()"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["vlan_tag", "ether_type"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x8847"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/../define.p4",
+ "line" : 33,
+ "column" : 31,
+ "source_fragment" : "0x8847; ..."
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["mpls", "label"]
+ },
+ {
+ "type" : "runtime_data",
+ "value" : 3
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 67,
+ "column" : 8,
+ "source_fragment" : "hdr.mpls.label = label; ..."
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["mpls", "tc"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x00"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 68,
+ "column" : 8,
+ "source_fragment" : "hdr.mpls.tc = tc; ..."
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["mpls", "bos"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x01"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 69,
+ "column" : 8,
+ "source_fragment" : "hdr.mpls.bos = 1w1"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["mpls", "ttl"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x40"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/../define.p4",
+ "line" : 60,
+ "column" : 32,
+ "source_fragment" : "64; ..."
+ }
+ }
+ ]
+ },
+ {
+ "name" : "next.mpls_routing_v4",
+ "id" : 34,
+ "runtime_data" : [
+ {
+ "name" : "port_num",
+ "bitwidth" : 9
+ },
+ {
+ "name" : "smac",
+ "bitwidth" : 48
+ },
+ {
+ "name" : "dmac",
+ "bitwidth" : 48
+ },
+ {
+ "name" : "label",
+ "bitwidth" : 20
+ }
+ ],
+ "primitives" : [
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["ethernet", "src_addr"]
+ },
+ {
+ "type" : "runtime_data",
+ "value" : 1
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 45,
+ "column" : 8,
+ "source_fragment" : "hdr.ethernet.src_addr = smac; ..."
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["ethernet", "dst_addr"]
+ },
+ {
+ "type" : "runtime_data",
+ "value" : 2
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 49,
+ "column" : 8,
+ "source_fragment" : "hdr.ethernet.dst_addr = dmac; ..."
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["standard_metadata", "egress_spec"]
+ },
+ {
+ "type" : "runtime_data",
+ "value" : 0
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 33,
+ "column" : 8,
+ "source_fragment" : "standard_metadata.egress_spec = port_num; ..."
+ }
+ },
+ {
+ "op" : "add_header",
+ "parameters" : [
+ {
+ "type" : "header",
+ "value" : "mpls"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 65,
+ "column" : 8,
+ "source_fragment" : "hdr.mpls.setValid()"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["vlan_tag", "ether_type"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x8847"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/../define.p4",
+ "line" : 33,
+ "column" : 31,
+ "source_fragment" : "0x8847; ..."
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["mpls", "label"]
+ },
+ {
+ "type" : "runtime_data",
+ "value" : 3
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 67,
+ "column" : 8,
+ "source_fragment" : "hdr.mpls.label = label; ..."
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["mpls", "tc"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x00"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 68,
+ "column" : 8,
+ "source_fragment" : "hdr.mpls.tc = tc; ..."
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["mpls", "bos"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x01"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 69,
+ "column" : 8,
+ "source_fragment" : "hdr.mpls.bos = 1w1"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["mpls", "ttl"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x40"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/../define.p4",
+ "line" : 60,
+ "column" : 32,
+ "source_fragment" : "64; ..."
+ }
+ }
+ ]
+ },
+ {
+ "name" : "next.mpls_routing_v6",
+ "id" : 35,
+ "runtime_data" : [
+ {
+ "name" : "port_num",
+ "bitwidth" : 9
+ },
+ {
+ "name" : "smac",
+ "bitwidth" : 48
+ },
+ {
+ "name" : "dmac",
+ "bitwidth" : 48
+ },
+ {
+ "name" : "label",
+ "bitwidth" : 20
+ }
+ ],
+ "primitives" : [
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["ethernet", "src_addr"]
+ },
+ {
+ "type" : "runtime_data",
+ "value" : 1
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 45,
+ "column" : 8,
+ "source_fragment" : "hdr.ethernet.src_addr = smac; ..."
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["ethernet", "dst_addr"]
+ },
+ {
+ "type" : "runtime_data",
+ "value" : 2
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 49,
+ "column" : 8,
+ "source_fragment" : "hdr.ethernet.dst_addr = dmac; ..."
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["standard_metadata", "egress_spec"]
+ },
+ {
+ "type" : "runtime_data",
+ "value" : 0
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 33,
+ "column" : 8,
+ "source_fragment" : "standard_metadata.egress_spec = port_num; ..."
+ }
+ },
+ {
+ "op" : "add_header",
+ "parameters" : [
+ {
+ "type" : "header",
+ "value" : "mpls"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 65,
+ "column" : 8,
+ "source_fragment" : "hdr.mpls.setValid()"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["vlan_tag", "ether_type"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x8847"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/../define.p4",
+ "line" : 33,
+ "column" : 31,
+ "source_fragment" : "0x8847; ..."
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["mpls", "label"]
+ },
+ {
+ "type" : "runtime_data",
+ "value" : 3
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 67,
+ "column" : 8,
+ "source_fragment" : "hdr.mpls.label = label; ..."
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["mpls", "tc"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x00"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 68,
+ "column" : 8,
+ "source_fragment" : "hdr.mpls.tc = tc; ..."
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["mpls", "bos"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x01"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 69,
+ "column" : 8,
+ "source_fragment" : "hdr.mpls.bos = 1w1"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["mpls", "ttl"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x40"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/../define.p4",
+ "line" : 60,
+ "column" : 32,
+ "source_fragment" : "64; ..."
+ }
+ }
+ ]
+ },
+ {
+ "name" : "act",
+ "id" : 36,
+ "runtime_data" : [],
+ "primitives" : [
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["standard_metadata", "egress_spec"]
+ },
+ {
+ "type" : "field",
+ "value" : ["packet_out", "egress_port"]
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/packetio.p4",
+ "line" : 26,
+ "column" : 12,
+ "source_fragment" : "standard_metadata.egress_spec = hdr.packet_out.egress_port"
+ }
+ },
+ {
+ "op" : "remove_header",
+ "parameters" : [
+ {
+ "type" : "header",
+ "value" : "packet_out"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/packetio.p4",
+ "line" : 27,
+ "column" : 12,
+ "source_fragment" : "hdr.packet_out.setInvalid()"
+ }
+ }
+ ]
+ },
+ {
+ "name" : "act_0",
+ "id" : 37,
+ "runtime_data" : [],
+ "primitives" : [
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["scalars", "spgw_ingress_tmp_2"]
+ },
+ {
+ "type" : "expression",
+ "value" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "b2d",
+ "left" : null,
+ "right" : {
+ "type" : "bool",
+ "value" : true
+ }
+ }
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name" : "act_1",
+ "id" : 38,
+ "runtime_data" : [],
+ "primitives" : [
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["scalars", "spgw_ingress_tmp_2"]
+ },
+ {
+ "type" : "expression",
+ "value" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "b2d",
+ "left" : null,
+ "right" : {
+ "type" : "bool",
+ "value" : false
+ }
+ }
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name" : "act_2",
+ "id" : 39,
+ "runtime_data" : [],
+ "primitives" : [
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["spgw", "s1u_enb_addr"]
+ },
+ {
+ "type" : "field",
+ "value" : ["ipv4", "src_addr"]
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 152,
+ "column" : 12,
+ "source_fragment" : "spgw_meta.s1u_enb_addr = ipv4.src_addr"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["spgw", "s1u_sgw_addr"]
+ },
+ {
+ "type" : "field",
+ "value" : ["ipv4", "dst_addr"]
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 153,
+ "column" : 12,
+ "source_fragment" : "spgw_meta.s1u_sgw_addr = ipv4.dst_addr"
+ }
+ },
+ {
+ "op" : "assign_header",
+ "parameters" : [
+ {
+ "type" : "header",
+ "value" : "ipv4"
+ },
+ {
+ "type" : "header",
+ "value" : "gtpu_ipv4"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 154,
+ "column" : 17,
+ "source_fragment" : "= gtpu_ipv4; ..."
+ }
+ },
+ {
+ "op" : "assign_header",
+ "parameters" : [
+ {
+ "type" : "header",
+ "value" : "udp"
+ },
+ {
+ "type" : "header",
+ "value" : "gtpu_udp"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 155,
+ "column" : 16,
+ "source_fragment" : "= gtpu_udp; ..."
+ }
+ }
+ ]
+ },
+ {
+ "name" : "act_3",
+ "id" : 40,
+ "runtime_data" : [],
+ "primitives" : [
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["spgw", "do_spgw"]
+ },
+ {
+ "type" : "expression",
+ "value" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "b2d",
+ "left" : null,
+ "right" : {
+ "type" : "bool",
+ "value" : true
+ }
+ }
+ }
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 159,
+ "column" : 16,
+ "source_fragment" : "spgw_meta.do_spgw = true"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["spgw", "direction"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x00"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/../define.p4",
+ "line" : 81,
+ "column" : 31,
+ "source_fragment" : "1w0; ..."
+ }
+ }
+ ]
+ },
+ {
+ "name" : "act_4",
+ "id" : 41,
+ "runtime_data" : [],
+ "primitives" : [
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["scalars", "spgw_ingress_tmp_3"]
+ },
+ {
+ "type" : "expression",
+ "value" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "b2d",
+ "left" : null,
+ "right" : {
+ "type" : "bool",
+ "value" : true
+ }
+ }
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name" : "act_5",
+ "id" : 42,
+ "runtime_data" : [],
+ "primitives" : [
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["scalars", "spgw_ingress_tmp_3"]
+ },
+ {
+ "type" : "expression",
+ "value" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "b2d",
+ "left" : null,
+ "right" : {
+ "type" : "bool",
+ "value" : false
+ }
+ }
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name" : "act_6",
+ "id" : 43,
+ "runtime_data" : [],
+ "primitives" : [
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["spgw", "do_spgw"]
+ },
+ {
+ "type" : "expression",
+ "value" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "b2d",
+ "left" : null,
+ "right" : {
+ "type" : "bool",
+ "value" : true
+ }
+ }
+ }
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 163,
+ "column" : 12,
+ "source_fragment" : "spgw_meta.do_spgw = true"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["spgw", "direction"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x01"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/../define.p4",
+ "line" : 82,
+ "column" : 33,
+ "source_fragment" : "1w1; ..."
+ }
+ }
+ ]
+ },
+ {
+ "name" : "act_7",
+ "id" : 44,
+ "runtime_data" : [],
+ "primitives" : [
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["scalars", "spgw_ingress_hasReturned_0"]
+ },
+ {
+ "type" : "expression",
+ "value" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "b2d",
+ "left" : null,
+ "right" : {
+ "type" : "bool",
+ "value" : false
+ }
+ }
+ }
+ }
+ ]
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["spgw", "do_spgw"]
+ },
+ {
+ "type" : "expression",
+ "value" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "b2d",
+ "left" : null,
+ "right" : {
+ "type" : "bool",
+ "value" : false
+ }
+ }
+ }
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 146,
+ "column" : 8,
+ "source_fragment" : "spgw_meta.do_spgw = false"
+ }
+ }
+ ]
+ },
+ {
+ "name" : "act_8",
+ "id" : 45,
+ "runtime_data" : [],
+ "primitives" : [
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["scalars", "spgw_ingress_hasReturned_0"]
+ },
+ {
+ "type" : "expression",
+ "value" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "b2d",
+ "left" : null,
+ "right" : {
+ "type" : "bool",
+ "value" : true
+ }
+ }
+ }
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 169,
+ "column" : 12,
+ "source_fragment" : "return"
+ }
+ }
+ ]
+ },
+ {
+ "name" : "act_9",
+ "id" : 46,
+ "runtime_data" : [],
+ "primitives" : [
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["scalars", "spgw_ingress_tmp_4"]
+ },
+ {
+ "type" : "expression",
+ "value" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "b2d",
+ "left" : null,
+ "right" : {
+ "type" : "bool",
+ "value" : true
+ }
+ }
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name" : "act_10",
+ "id" : 47,
+ "runtime_data" : [],
+ "primitives" : [
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["scalars", "spgw_ingress_tmp_4"]
+ },
+ {
+ "type" : "expression",
+ "value" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "b2d",
+ "left" : null,
+ "right" : {
+ "type" : "bool",
+ "value" : false
+ }
+ }
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name" : "act_11",
+ "id" : 48,
+ "runtime_data" : [],
+ "primitives" : [
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["vlan_tag", "ether_type"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x0800"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/../define.p4",
+ "line" : 35,
+ "column" : 31,
+ "source_fragment" : "0x0800; ..."
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["scalars", "fabric_metadata_t.original_ether_type"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x0800"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/../define.p4",
+ "line" : 35,
+ "column" : 31,
+ "source_fragment" : "0x0800; ..."
+ }
+ }
+ ]
+ },
+ {
+ "name" : "act_12",
+ "id" : 49,
+ "runtime_data" : [],
+ "primitives" : [
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["scalars", "next_tmp_0"]
+ },
+ {
+ "type" : "expression",
+ "value" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "b2d",
+ "left" : null,
+ "right" : {
+ "type" : "bool",
+ "value" : true
+ }
+ }
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name" : "act_13",
+ "id" : 50,
+ "runtime_data" : [],
+ "primitives" : [
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["scalars", "next_tmp_0"]
+ },
+ {
+ "type" : "expression",
+ "value" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "b2d",
+ "left" : null,
+ "right" : {
+ "type" : "bool",
+ "value" : false
+ }
+ }
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "name" : "act_14",
+ "id" : 51,
+ "runtime_data" : [],
+ "primitives" : [
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["ipv4", "ttl"]
+ },
+ {
+ "type" : "expression",
+ "value" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "&",
+ "left" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "+",
+ "left" : {
+ "type" : "field",
+ "value" : ["ipv4", "ttl"]
+ },
+ "right" : {
+ "type" : "hexstr",
+ "value" : "0xff"
+ }
+ }
+ },
+ "right" : {
+ "type" : "hexstr",
+ "value" : "0xff"
+ }
+ }
+ }
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 140,
+ "column" : 20,
+ "source_fragment" : "hdr.ipv4.ttl = hdr.ipv4.ttl - 1"
+ }
+ }
+ ]
+ },
+ {
+ "name" : "act_15",
+ "id" : 52,
+ "runtime_data" : [],
+ "primitives" : [
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["scalars", "tmp_0"]
+ },
+ {
+ "type" : "expression",
+ "value" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "&",
+ "left" : {
+ "type" : "field",
+ "value" : ["standard_metadata", "egress_spec"]
+ },
+ "right" : {
+ "type" : "hexstr",
+ "value" : "0xffffffff"
+ }
+ }
+ }
+ }
+ ]
+ },
+ {
+ "op" : "count",
+ "parameters" : [
+ {
+ "type" : "counter_array",
+ "value" : "port_counters_control.egress_port_counter"
+ },
+ {
+ "type" : "field",
+ "value" : ["scalars", "tmp_0"]
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/port_counter.p4",
+ "line" : 28,
+ "column" : 12,
+ "source_fragment" : "egress_port_counter.count((bit<32>)standard_metadata.egress_spec)"
+ }
+ }
+ ]
+ },
+ {
+ "name" : "act_16",
+ "id" : 53,
+ "runtime_data" : [],
+ "primitives" : [
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["scalars", "tmp_1"]
+ },
+ {
+ "type" : "expression",
+ "value" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "&",
+ "left" : {
+ "type" : "field",
+ "value" : ["standard_metadata", "ingress_port"]
+ },
+ "right" : {
+ "type" : "hexstr",
+ "value" : "0xffffffff"
+ }
+ }
+ }
+ }
+ ]
+ },
+ {
+ "op" : "count",
+ "parameters" : [
+ {
+ "type" : "counter_array",
+ "value" : "port_counters_control.ingress_port_counter"
+ },
+ {
+ "type" : "field",
+ "value" : ["scalars", "tmp_1"]
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/port_counter.p4",
+ "line" : 31,
+ "column" : 12,
+ "source_fragment" : "ingress_port_counter.count((bit<32>)standard_metadata.ingress_port)"
+ }
+ }
+ ]
+ },
+ {
+ "name" : "act_17",
+ "id" : 54,
+ "runtime_data" : [],
+ "primitives" : [
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["ethernet", "ether_type"]
+ },
+ {
+ "type" : "field",
+ "value" : ["vlan_tag", "ether_type"]
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 162,
+ "column" : 12,
+ "source_fragment" : "hdr.ethernet.ether_type = hdr.vlan_tag.ether_type"
+ }
+ },
+ {
+ "op" : "remove_header",
+ "parameters" : [
+ {
+ "type" : "header",
+ "value" : "vlan_tag"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 163,
+ "column" : 12,
+ "source_fragment" : "hdr.vlan_tag.setInvalid()"
+ }
+ }
+ ]
+ },
+ {
+ "name" : "spgw_egress.gtpu_encap",
+ "id" : 55,
+ "runtime_data" : [],
+ "primitives" : [
+ {
+ "op" : "add_header",
+ "parameters" : [
+ {
+ "type" : "header",
+ "value" : "gtpu_ipv4"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 210,
+ "column" : 8,
+ "source_fragment" : "gtpu_ipv4.setValid()"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["gtpu_ipv4", "version"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x04"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/../define.p4",
+ "line" : 39,
+ "column" : 28,
+ "source_fragment" : "4; ..."
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["gtpu_ipv4", "ihl"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x05"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/../define.p4",
+ "line" : 47,
+ "column" : 28,
+ "source_fragment" : "5; ..."
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["gtpu_ipv4", "diffserv"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x00"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 213,
+ "column" : 8,
+ "source_fragment" : "gtpu_ipv4.diffserv = 0"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["gtpu_ipv4", "total_len"]
+ },
+ {
+ "type" : "expression",
+ "value" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "&",
+ "left" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "+",
+ "left" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "&",
+ "left" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "+",
+ "left" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "&",
+ "left" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "+",
+ "left" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "&",
+ "left" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "+",
+ "left" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "&",
+ "left" : {
+ "type" : "field",
+ "value" : ["standard_metadata", "packet_length"]
+ },
+ "right" : {
+ "type" : "hexstr",
+ "value" : "0xffff"
+ }
+ }
+ },
+ "right" : {
+ "type" : "hexstr",
+ "value" : "0xfff2"
+ }
+ }
+ },
+ "right" : {
+ "type" : "hexstr",
+ "value" : "0xffff"
+ }
+ }
+ },
+ "right" : {
+ "type" : "hexstr",
+ "value" : "0x0014"
+ }
+ }
+ },
+ "right" : {
+ "type" : "hexstr",
+ "value" : "0xffff"
+ }
+ }
+ },
+ "right" : {
+ "type" : "hexstr",
+ "value" : "0x0008"
+ }
+ }
+ },
+ "right" : {
+ "type" : "hexstr",
+ "value" : "0xffff"
+ }
+ }
+ },
+ "right" : {
+ "type" : "hexstr",
+ "value" : "0x0008"
+ }
+ }
+ },
+ "right" : {
+ "type" : "hexstr",
+ "value" : "0xffff"
+ }
+ }
+ }
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 214,
+ "column" : 8,
+ "source_fragment" : "gtpu_ipv4.total_len = ((bit<16>)std_meta.packet_length ..."
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["gtpu_ipv4", "identification"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x1513"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 216,
+ "column" : 8,
+ "source_fragment" : "gtpu_ipv4.identification = 0x1513"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["gtpu_ipv4", "flags"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x00"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 217,
+ "column" : 8,
+ "source_fragment" : "gtpu_ipv4.flags = 0"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["gtpu_ipv4", "frag_offset"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x0000"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 218,
+ "column" : 8,
+ "source_fragment" : "gtpu_ipv4.frag_offset = 0"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["gtpu_ipv4", "ttl"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x40"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/../define.p4",
+ "line" : 71,
+ "column" : 32,
+ "source_fragment" : "64; ..."
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["gtpu_ipv4", "protocol"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x11"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/../define.p4",
+ "line" : 44,
+ "column" : 25,
+ "source_fragment" : "17; ..."
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["gtpu_ipv4", "dst_addr"]
+ },
+ {
+ "type" : "field",
+ "value" : ["spgw", "s1u_enb_addr"]
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 221,
+ "column" : 8,
+ "source_fragment" : "gtpu_ipv4.dst_addr = spgw_meta.s1u_enb_addr"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["gtpu_ipv4", "src_addr"]
+ },
+ {
+ "type" : "field",
+ "value" : ["spgw", "s1u_sgw_addr"]
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 222,
+ "column" : 8,
+ "source_fragment" : "gtpu_ipv4.src_addr = spgw_meta.s1u_sgw_addr"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["gtpu_ipv4", "hdr_checksum"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x0000"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 223,
+ "column" : 8,
+ "source_fragment" : "gtpu_ipv4.hdr_checksum = 0"
+ }
+ },
+ {
+ "op" : "add_header",
+ "parameters" : [
+ {
+ "type" : "header",
+ "value" : "gtpu_udp"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 225,
+ "column" : 8,
+ "source_fragment" : "gtpu_udp.setValid()"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["gtpu_udp", "src_port"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x0868"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 226,
+ "column" : 8,
+ "source_fragment" : "gtpu_udp.src_port = 2152"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["gtpu_udp", "dst_port"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x0868"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 227,
+ "column" : 8,
+ "source_fragment" : "gtpu_udp.dst_port = 2152"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["gtpu_udp", "len"]
+ },
+ {
+ "type" : "expression",
+ "value" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "&",
+ "left" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "+",
+ "left" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "&",
+ "left" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "+",
+ "left" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "&",
+ "left" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "+",
+ "left" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "&",
+ "left" : {
+ "type" : "field",
+ "value" : ["standard_metadata", "packet_length"]
+ },
+ "right" : {
+ "type" : "hexstr",
+ "value" : "0xffff"
+ }
+ }
+ },
+ "right" : {
+ "type" : "hexstr",
+ "value" : "0xfff2"
+ }
+ }
+ },
+ "right" : {
+ "type" : "hexstr",
+ "value" : "0xffff"
+ }
+ }
+ },
+ "right" : {
+ "type" : "hexstr",
+ "value" : "0x0008"
+ }
+ }
+ },
+ "right" : {
+ "type" : "hexstr",
+ "value" : "0xffff"
+ }
+ }
+ },
+ "right" : {
+ "type" : "hexstr",
+ "value" : "0x0008"
+ }
+ }
+ },
+ "right" : {
+ "type" : "hexstr",
+ "value" : "0xffff"
+ }
+ }
+ }
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 228,
+ "column" : 8,
+ "source_fragment" : "gtpu_udp.len = ((bit<16>)std_meta.packet_length ..."
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["gtpu_udp", "checksum"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x0000"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 230,
+ "column" : 8,
+ "source_fragment" : "gtpu_udp.checksum = 0"
+ }
+ },
+ {
+ "op" : "add_header",
+ "parameters" : [
+ {
+ "type" : "header",
+ "value" : "gtpu"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 232,
+ "column" : 8,
+ "source_fragment" : "gtpu.setValid()"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["gtpu", "version"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x01"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 233,
+ "column" : 8,
+ "source_fragment" : "gtpu.version = 0x01"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["gtpu", "pt"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x01"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 234,
+ "column" : 8,
+ "source_fragment" : "gtpu.pt = 0x01"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["gtpu", "spare"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x00"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 235,
+ "column" : 8,
+ "source_fragment" : "gtpu.spare = 0"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["gtpu", "ex_flag"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x00"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 236,
+ "column" : 8,
+ "source_fragment" : "gtpu.ex_flag = 0"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["gtpu", "seq_flag"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x00"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 237,
+ "column" : 8,
+ "source_fragment" : "gtpu.seq_flag = 0"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["gtpu", "npdu_flag"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x00"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 238,
+ "column" : 8,
+ "source_fragment" : "gtpu.npdu_flag = 0"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["gtpu", "msgtype"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0xff"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 239,
+ "column" : 8,
+ "source_fragment" : "gtpu.msgtype = 0xff"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["gtpu", "msglen"]
+ },
+ {
+ "type" : "expression",
+ "value" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "&",
+ "left" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "+",
+ "left" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "&",
+ "left" : {
+ "type" : "field",
+ "value" : ["standard_metadata", "packet_length"]
+ },
+ "right" : {
+ "type" : "hexstr",
+ "value" : "0xffff"
+ }
+ }
+ },
+ "right" : {
+ "type" : "hexstr",
+ "value" : "0xfff2"
+ }
+ }
+ },
+ "right" : {
+ "type" : "hexstr",
+ "value" : "0xffff"
+ }
+ }
+ }
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 240,
+ "column" : 8,
+ "source_fragment" : "gtpu.msglen = ((bit<16>)std_meta.packet_length - 14"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["gtpu", "teid"]
+ },
+ {
+ "type" : "field",
+ "value" : ["spgw", "teid"]
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 241,
+ "column" : 8,
+ "source_fragment" : "gtpu.teid = spgw_meta.teid"
+ }
+ }
+ ]
+ },
+ {
+ "name" : "act_18",
+ "id" : 56,
+ "runtime_data" : [],
+ "primitives" : [
+ {
+ "op" : "add_header",
+ "parameters" : [
+ {
+ "type" : "header",
+ "value" : "packet_in"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/packetio.p4",
+ "line" : 39,
+ "column" : 12,
+ "source_fragment" : "hdr.packet_in.setValid()"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["packet_in", "ingress_port"]
+ },
+ {
+ "type" : "field",
+ "value" : ["standard_metadata", "ingress_port"]
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/packetio.p4",
+ "line" : 40,
+ "column" : 12,
+ "source_fragment" : "hdr.packet_in.ingress_port = standard_metadata.ingress_port"
+ }
+ }
+ ]
+ },
+ {
+ "name" : "act_19",
+ "id" : 57,
+ "runtime_data" : [],
+ "primitives" : [
+ {
+ "op" : "remove_header",
+ "parameters" : [
+ {
+ "type" : "header",
+ "value" : "gtpu_ipv4"
+ }
+ ],
+ "source_info" : {
+ "filename" : "fabric.p4",
+ "line" : 69,
+ "column" : 26,
+ "source_fragment" : "hdr.gtpu_ipv4"
+ }
+ },
+ {
+ "op" : "remove_header",
+ "parameters" : [
+ {
+ "type" : "header",
+ "value" : "gtpu_udp"
+ }
+ ],
+ "source_info" : {
+ "filename" : "fabric.p4",
+ "line" : 69,
+ "column" : 41,
+ "source_fragment" : "hdr.gtpu_udp"
+ }
+ },
+ {
+ "op" : "remove_header",
+ "parameters" : [
+ {
+ "type" : "header",
+ "value" : "gtpu"
+ }
+ ],
+ "source_info" : {
+ "filename" : "fabric.p4",
+ "line" : 69,
+ "column" : 55,
+ "source_fragment" : "hdr.gtpu"
+ }
+ }
+ ]
+ }
+ ],
+ "pipelines" : [
+ {
+ "name" : "ingress",
+ "id" : 0,
+ "source_info" : {
+ "filename" : "fabric.p4",
+ "line" : 33,
+ "column" : 8,
+ "source_fragment" : "FabricIngress"
+ },
+ "init_table" : "node_2",
+ "tables" : [
+ {
+ "name" : "tbl_act",
+ "id" : 0,
+ "key" : [],
+ "match_type" : "exact",
+ "type" : "simple",
+ "max_size" : 1024,
+ "with_counters" : false,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [36],
+ "actions" : ["act"],
+ "base_default_next" : null,
+ "next_tables" : {
+ "act" : null
+ },
+ "default_entry" : {
+ "action_id" : 36,
+ "action_const" : true,
+ "action_data" : [],
+ "action_entry_const" : true
+ }
+ },
+ {
+ "name" : "tbl_act_0",
+ "id" : 1,
+ "key" : [],
+ "match_type" : "exact",
+ "type" : "simple",
+ "max_size" : 1024,
+ "with_counters" : false,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [44],
+ "actions" : ["act_7"],
+ "base_default_next" : "node_5",
+ "next_tables" : {
+ "act_7" : "node_5"
+ },
+ "default_entry" : {
+ "action_id" : 44,
+ "action_const" : true,
+ "action_data" : [],
+ "action_entry_const" : true
+ }
+ },
+ {
+ "name" : "tbl_act_1",
+ "id" : 2,
+ "key" : [],
+ "match_type" : "exact",
+ "type" : "simple",
+ "max_size" : 1024,
+ "with_counters" : false,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [39],
+ "actions" : ["act_2"],
+ "base_default_next" : "spgw_ingress.s1u_filter_table",
+ "next_tables" : {
+ "act_2" : "spgw_ingress.s1u_filter_table"
+ },
+ "default_entry" : {
+ "action_id" : 39,
+ "action_const" : true,
+ "action_data" : [],
+ "action_entry_const" : true
+ }
+ },
+ {
+ "name" : "spgw_ingress.s1u_filter_table",
+ "id" : 3,
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 65,
+ "column" : 10,
+ "source_fragment" : "s1u_filter_table"
+ },
+ "key" : [
+ {
+ "match_type" : "exact",
+ "target" : ["spgw", "s1u_sgw_addr"],
+ "mask" : null
+ }
+ ],
+ "match_type" : "exact",
+ "type" : "simple",
+ "max_size" : 1024,
+ "with_counters" : false,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [1],
+ "actions" : ["NoAction"],
+ "base_default_next" : null,
+ "next_tables" : {
+ "__HIT__" : "tbl_act_2",
+ "__MISS__" : "tbl_act_3"
+ },
+ "default_entry" : {
+ "action_id" : 1,
+ "action_const" : false,
+ "action_data" : [],
+ "action_entry_const" : false
+ }
+ },
+ {
+ "name" : "tbl_act_2",
+ "id" : 4,
+ "key" : [],
+ "match_type" : "exact",
+ "type" : "simple",
+ "max_size" : 1024,
+ "with_counters" : false,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [37],
+ "actions" : ["act_0"],
+ "base_default_next" : "node_10",
+ "next_tables" : {
+ "act_0" : "node_10"
+ },
+ "default_entry" : {
+ "action_id" : 37,
+ "action_const" : true,
+ "action_data" : [],
+ "action_entry_const" : true
+ }
+ },
+ {
+ "name" : "tbl_act_3",
+ "id" : 5,
+ "key" : [],
+ "match_type" : "exact",
+ "type" : "simple",
+ "max_size" : 1024,
+ "with_counters" : false,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [38],
+ "actions" : ["act_1"],
+ "base_default_next" : "node_10",
+ "next_tables" : {
+ "act_1" : "node_10"
+ },
+ "default_entry" : {
+ "action_id" : 38,
+ "action_const" : true,
+ "action_data" : [],
+ "action_entry_const" : true
+ }
+ },
+ {
+ "name" : "tbl_act_4",
+ "id" : 6,
+ "key" : [],
+ "match_type" : "exact",
+ "type" : "simple",
+ "max_size" : 1024,
+ "with_counters" : false,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [40],
+ "actions" : ["act_3"],
+ "base_default_next" : "node_17",
+ "next_tables" : {
+ "act_3" : "node_17"
+ },
+ "default_entry" : {
+ "action_id" : 40,
+ "action_const" : true,
+ "action_data" : [],
+ "action_entry_const" : true
+ }
+ },
+ {
+ "name" : "spgw_ingress.ue_filter_table",
+ "id" : 7,
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 55,
+ "column" : 10,
+ "source_fragment" : "ue_filter_table"
+ },
+ "key" : [
+ {
+ "match_type" : "lpm",
+ "target" : ["ipv4", "dst_addr"],
+ "mask" : null
+ }
+ ],
+ "match_type" : "lpm",
+ "type" : "simple",
+ "max_size" : 1024,
+ "with_counters" : false,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [0],
+ "actions" : ["NoAction"],
+ "base_default_next" : null,
+ "next_tables" : {
+ "__HIT__" : "tbl_act_5",
+ "__MISS__" : "tbl_act_6"
+ },
+ "default_entry" : {
+ "action_id" : 0,
+ "action_const" : false,
+ "action_data" : [],
+ "action_entry_const" : false
+ }
+ },
+ {
+ "name" : "tbl_act_5",
+ "id" : 8,
+ "key" : [],
+ "match_type" : "exact",
+ "type" : "simple",
+ "max_size" : 1024,
+ "with_counters" : false,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [41],
+ "actions" : ["act_4"],
+ "base_default_next" : "node_15",
+ "next_tables" : {
+ "act_4" : "node_15"
+ },
+ "default_entry" : {
+ "action_id" : 41,
+ "action_const" : true,
+ "action_data" : [],
+ "action_entry_const" : true
+ }
+ },
+ {
+ "name" : "tbl_act_6",
+ "id" : 9,
+ "key" : [],
+ "match_type" : "exact",
+ "type" : "simple",
+ "max_size" : 1024,
+ "with_counters" : false,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [42],
+ "actions" : ["act_5"],
+ "base_default_next" : "node_15",
+ "next_tables" : {
+ "act_5" : "node_15"
+ },
+ "default_entry" : {
+ "action_id" : 42,
+ "action_const" : true,
+ "action_data" : [],
+ "action_entry_const" : true
+ }
+ },
+ {
+ "name" : "tbl_act_7",
+ "id" : 10,
+ "key" : [],
+ "match_type" : "exact",
+ "type" : "simple",
+ "max_size" : 1024,
+ "with_counters" : false,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [43],
+ "actions" : ["act_6"],
+ "base_default_next" : "node_17",
+ "next_tables" : {
+ "act_6" : "node_17"
+ },
+ "default_entry" : {
+ "action_id" : 43,
+ "action_const" : true,
+ "action_data" : [],
+ "action_entry_const" : true
+ }
+ },
+ {
+ "name" : "tbl_act_8",
+ "id" : 11,
+ "key" : [],
+ "match_type" : "exact",
+ "type" : "simple",
+ "max_size" : 1024,
+ "with_counters" : false,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [45],
+ "actions" : ["act_8"],
+ "base_default_next" : "node_19",
+ "next_tables" : {
+ "act_8" : "node_19"
+ },
+ "default_entry" : {
+ "action_id" : 45,
+ "action_const" : true,
+ "action_data" : [],
+ "action_entry_const" : true
+ }
+ },
+ {
+ "name" : "tbl_spgw_ingress_gtpu_decap",
+ "id" : 12,
+ "key" : [],
+ "match_type" : "exact",
+ "type" : "simple",
+ "max_size" : 1024,
+ "with_counters" : false,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [14],
+ "actions" : ["spgw_ingress.gtpu_decap"],
+ "base_default_next" : "node_22",
+ "next_tables" : {
+ "spgw_ingress.gtpu_decap" : "node_22"
+ },
+ "default_entry" : {
+ "action_id" : 14,
+ "action_const" : true,
+ "action_data" : [],
+ "action_entry_const" : true
+ }
+ },
+ {
+ "name" : "spgw_ingress.dl_sess_lookup",
+ "id" : 13,
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 124,
+ "column" : 10,
+ "source_fragment" : "dl_sess_lookup"
+ },
+ "key" : [
+ {
+ "match_type" : "exact",
+ "target" : ["ipv4", "dst_addr"],
+ "mask" : null
+ }
+ ],
+ "match_type" : "exact",
+ "type" : "simple",
+ "max_size" : 1024,
+ "with_counters" : false,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [15, 2],
+ "actions" : ["spgw_ingress.set_dl_sess_info", "NoAction"],
+ "base_default_next" : null,
+ "next_tables" : {
+ "__HIT__" : "tbl_act_9",
+ "__MISS__" : "tbl_act_10"
+ },
+ "default_entry" : {
+ "action_id" : 2,
+ "action_const" : false,
+ "action_data" : [],
+ "action_entry_const" : false
+ }
+ },
+ {
+ "name" : "tbl_act_9",
+ "id" : 14,
+ "key" : [],
+ "match_type" : "exact",
+ "type" : "simple",
+ "max_size" : 1024,
+ "with_counters" : false,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [46],
+ "actions" : ["act_9"],
+ "base_default_next" : "node_26",
+ "next_tables" : {
+ "act_9" : "node_26"
+ },
+ "default_entry" : {
+ "action_id" : 46,
+ "action_const" : true,
+ "action_data" : [],
+ "action_entry_const" : true
+ }
+ },
+ {
+ "name" : "tbl_act_10",
+ "id" : 15,
+ "key" : [],
+ "match_type" : "exact",
+ "type" : "simple",
+ "max_size" : 1024,
+ "with_counters" : false,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [47],
+ "actions" : ["act_10"],
+ "base_default_next" : "node_26",
+ "next_tables" : {
+ "act_10" : "node_26"
+ },
+ "default_entry" : {
+ "action_id" : 47,
+ "action_const" : true,
+ "action_data" : [],
+ "action_entry_const" : true
+ }
+ },
+ {
+ "name" : "tbl_spgw_ingress_drop_now",
+ "id" : 16,
+ "key" : [],
+ "match_type" : "exact",
+ "type" : "simple",
+ "max_size" : 1024,
+ "with_counters" : false,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [13],
+ "actions" : ["spgw_ingress.drop_now"],
+ "base_default_next" : "spgw_ingress.ue_cdr_table",
+ "next_tables" : {
+ "spgw_ingress.drop_now" : "spgw_ingress.ue_cdr_table"
+ },
+ "default_entry" : {
+ "action_id" : 13,
+ "action_const" : true,
+ "action_data" : [],
+ "action_entry_const" : true
+ }
+ },
+ {
+ "name" : "spgw_ingress.ue_cdr_table",
+ "id" : 17,
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 134,
+ "column" : 10,
+ "source_fragment" : "ue_cdr_table"
+ },
+ "key" : [
+ {
+ "match_type" : "exact",
+ "target" : ["ipv4", "dst_addr"],
+ "mask" : null
+ }
+ ],
+ "match_type" : "exact",
+ "type" : "simple",
+ "max_size" : 1024,
+ "with_counters" : true,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [16, 3],
+ "actions" : ["spgw_ingress.update_ue_cdr", "NoAction"],
+ "base_default_next" : "filtering.ingress_port_vlan",
+ "next_tables" : {
+ "spgw_ingress.update_ue_cdr" : "filtering.ingress_port_vlan",
+ "NoAction" : "filtering.ingress_port_vlan"
+ },
+ "default_entry" : {
+ "action_id" : 3,
+ "action_const" : false,
+ "action_data" : [],
+ "action_entry_const" : false
+ }
+ },
+ {
+ "name" : "filtering.ingress_port_vlan",
+ "id" : 18,
+ "source_info" : {
+ "filename" : "include/control/filtering.p4",
+ "line" : 57,
+ "column" : 10,
+ "source_fragment" : "ingress_port_vlan"
+ },
+ "key" : [
+ {
+ "match_type" : "exact",
+ "target" : ["standard_metadata", "ingress_port"],
+ "mask" : null
+ },
+ {
+ "match_type" : "exact",
+ "target" : ["vlan_tag", "$valid$"],
+ "mask" : null
+ },
+ {
+ "match_type" : "ternary",
+ "target" : ["vlan_tag", "vlan_id"],
+ "mask" : null
+ }
+ ],
+ "match_type" : "ternary",
+ "type" : "simple",
+ "max_size" : 1024,
+ "with_counters" : true,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [19, 18, 11, 17],
+ "actions" : ["filtering.push_internal_vlan", "filtering.set_vlan", "nop", "filtering.drop"],
+ "base_default_next" : "filtering.fwd_classifier",
+ "next_tables" : {
+ "filtering.push_internal_vlan" : "filtering.fwd_classifier",
+ "filtering.set_vlan" : "filtering.fwd_classifier",
+ "nop" : "filtering.fwd_classifier",
+ "filtering.drop" : "filtering.fwd_classifier"
+ },
+ "default_entry" : {
+ "action_id" : 11,
+ "action_const" : true,
+ "action_data" : [],
+ "action_entry_const" : true
+ }
+ },
+ {
+ "name" : "filtering.fwd_classifier",
+ "id" : 19,
+ "source_info" : {
+ "filename" : "include/control/filtering.p4",
+ "line" : 76,
+ "column" : 10,
+ "source_fragment" : "fwd_classifier"
+ },
+ "key" : [
+ {
+ "match_type" : "exact",
+ "target" : ["standard_metadata", "ingress_port"],
+ "mask" : null
+ },
+ {
+ "match_type" : "exact",
+ "target" : ["ethernet", "dst_addr"],
+ "mask" : null
+ },
+ {
+ "match_type" : "exact",
+ "target" : ["scalars", "fabric_metadata_t.original_ether_type"],
+ "mask" : null
+ }
+ ],
+ "match_type" : "exact",
+ "type" : "simple",
+ "max_size" : 1024,
+ "with_counters" : true,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [20],
+ "actions" : ["filtering.set_forwarding_type"],
+ "base_default_next" : "node_31",
+ "next_tables" : {
+ "filtering.set_forwarding_type" : "node_31"
+ },
+ "default_entry" : {
+ "action_id" : 20,
+ "action_const" : true,
+ "action_data" : ["0x0"],
+ "action_entry_const" : true
+ }
+ },
+ {
+ "name" : "forwarding.bridging",
+ "id" : 20,
+ "source_info" : {
+ "filename" : "include/control/forwarding.p4",
+ "line" : 53,
+ "column" : 10,
+ "source_fragment" : "bridging"
+ },
+ "key" : [
+ {
+ "match_type" : "exact",
+ "target" : ["vlan_tag", "vlan_id"],
+ "mask" : null
+ },
+ {
+ "match_type" : "ternary",
+ "target" : ["ethernet", "dst_addr"],
+ "mask" : null
+ }
+ ],
+ "match_type" : "ternary",
+ "type" : "simple",
+ "max_size" : 1024,
+ "with_counters" : true,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [22, 4],
+ "actions" : ["forwarding.set_next_id", "NoAction"],
+ "base_default_next" : "forwarding.acl",
+ "next_tables" : {
+ "forwarding.set_next_id" : "forwarding.acl",
+ "NoAction" : "forwarding.acl"
+ },
+ "default_entry" : {
+ "action_id" : 4,
+ "action_const" : false,
+ "action_data" : [],
+ "action_entry_const" : false
+ }
+ },
+ {
+ "name" : "forwarding.mpls",
+ "id" : 21,
+ "source_info" : {
+ "filename" : "include/control/forwarding.p4",
+ "line" : 65,
+ "column" : 10,
+ "source_fragment" : "mpls"
+ },
+ "key" : [
+ {
+ "match_type" : "exact",
+ "target" : ["mpls", "label"],
+ "mask" : null
+ }
+ ],
+ "match_type" : "exact",
+ "type" : "simple",
+ "max_size" : 1024,
+ "with_counters" : true,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [26, 5],
+ "actions" : ["forwarding.pop_mpls_and_next", "NoAction"],
+ "base_default_next" : "tbl_act_11",
+ "next_tables" : {
+ "forwarding.pop_mpls_and_next" : "tbl_act_11",
+ "NoAction" : "tbl_act_11"
+ },
+ "default_entry" : {
+ "action_id" : 5,
+ "action_const" : false,
+ "action_data" : [],
+ "action_entry_const" : false
+ }
+ },
+ {
+ "name" : "tbl_act_11",
+ "id" : 22,
+ "key" : [],
+ "match_type" : "exact",
+ "type" : "simple",
+ "max_size" : 1024,
+ "with_counters" : false,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [48],
+ "actions" : ["act_11"],
+ "base_default_next" : "forwarding.acl",
+ "next_tables" : {
+ "act_11" : "forwarding.acl"
+ },
+ "default_entry" : {
+ "action_id" : 48,
+ "action_const" : true,
+ "action_data" : [],
+ "action_entry_const" : true
+ }
+ },
+ {
+ "name" : "forwarding.unicast_v4",
+ "id" : 23,
+ "source_info" : {
+ "filename" : "include/control/forwarding.p4",
+ "line" : 76,
+ "column" : 10,
+ "source_fragment" : "unicast_v4"
+ },
+ "key" : [
+ {
+ "match_type" : "lpm",
+ "target" : ["ipv4", "dst_addr"],
+ "mask" : null
+ }
+ ],
+ "match_type" : "lpm",
+ "type" : "simple",
+ "max_size" : 1024,
+ "with_counters" : true,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [23, 6],
+ "actions" : ["forwarding.set_next_id", "NoAction"],
+ "base_default_next" : "forwarding.acl",
+ "next_tables" : {
+ "forwarding.set_next_id" : "forwarding.acl",
+ "NoAction" : "forwarding.acl"
+ },
+ "default_entry" : {
+ "action_id" : 6,
+ "action_const" : false,
+ "action_data" : [],
+ "action_entry_const" : false
+ }
+ },
+ {
+ "name" : "forwarding.multicast_v4",
+ "id" : 24,
+ "source_info" : {
+ "filename" : "include/control/forwarding.p4",
+ "line" : 87,
+ "column" : 10,
+ "source_fragment" : "multicast_v4"
+ },
+ "key" : [
+ {
+ "match_type" : "exact",
+ "target" : ["vlan_tag", "vlan_id"],
+ "mask" : null
+ },
+ {
+ "match_type" : "lpm",
+ "target" : ["ipv4", "dst_addr"],
+ "mask" : null
+ }
+ ],
+ "match_type" : "lpm",
+ "type" : "simple",
+ "max_size" : 1024,
+ "with_counters" : true,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [24, 7],
+ "actions" : ["forwarding.set_next_id", "NoAction"],
+ "base_default_next" : "forwarding.acl",
+ "next_tables" : {
+ "forwarding.set_next_id" : "forwarding.acl",
+ "NoAction" : "forwarding.acl"
+ },
+ "default_entry" : {
+ "action_id" : 7,
+ "action_const" : false,
+ "action_data" : [],
+ "action_entry_const" : false
+ }
+ },
+ {
+ "name" : "forwarding.acl",
+ "id" : 25,
+ "source_info" : {
+ "filename" : "include/control/forwarding.p4",
+ "line" : 127,
+ "column" : 10,
+ "source_fragment" : "acl"
+ },
+ "key" : [
+ {
+ "match_type" : "ternary",
+ "target" : ["standard_metadata", "ingress_port"],
+ "mask" : null
+ },
+ {
+ "match_type" : "ternary",
+ "target" : ["scalars", "fabric_metadata_t.ip_proto"],
+ "mask" : null
+ },
+ {
+ "match_type" : "ternary",
+ "target" : ["scalars", "fabric_metadata_t.l4_src_port"],
+ "mask" : null
+ },
+ {
+ "match_type" : "ternary",
+ "target" : ["scalars", "fabric_metadata_t.l4_dst_port"],
+ "mask" : null
+ },
+ {
+ "match_type" : "ternary",
+ "target" : ["scalars", "fabric_metadata_t.original_ether_type"],
+ "mask" : null
+ },
+ {
+ "match_type" : "ternary",
+ "target" : ["ethernet", "dst_addr"],
+ "mask" : null
+ },
+ {
+ "match_type" : "ternary",
+ "target" : ["ethernet", "src_addr"],
+ "mask" : null
+ },
+ {
+ "match_type" : "ternary",
+ "target" : ["vlan_tag", "vlan_id"],
+ "mask" : null
+ },
+ {
+ "match_type" : "ternary",
+ "target" : ["ipv4", "src_addr"],
+ "mask" : null
+ },
+ {
+ "match_type" : "ternary",
+ "target" : ["ipv4", "dst_addr"],
+ "mask" : null
+ },
+ {
+ "match_type" : "ternary",
+ "target" : ["icmp", "icmp_type"],
+ "mask" : null
+ },
+ {
+ "match_type" : "ternary",
+ "target" : ["icmp", "icmp_code"],
+ "mask" : null
+ }
+ ],
+ "match_type" : "ternary",
+ "type" : "simple",
+ "max_size" : 256,
+ "with_counters" : true,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [25, 27, 21, 12],
+ "actions" : ["forwarding.set_next_id", "forwarding.duplicate_to_controller", "forwarding.drop", "nop"],
+ "base_default_next" : "next.simple",
+ "next_tables" : {
+ "forwarding.set_next_id" : "next.simple",
+ "forwarding.duplicate_to_controller" : "next.simple",
+ "forwarding.drop" : "next.simple",
+ "nop" : "next.simple"
+ },
+ "default_entry" : {
+ "action_id" : 12,
+ "action_const" : true,
+ "action_data" : [],
+ "action_entry_const" : true
+ }
+ },
+ {
+ "name" : "next.simple",
+ "id" : 26,
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 89,
+ "column" : 10,
+ "source_fragment" : "simple"
+ },
+ "key" : [
+ {
+ "match_type" : "exact",
+ "target" : ["scalars", "fabric_metadata_t.next_id"],
+ "mask" : null
+ }
+ ],
+ "match_type" : "exact",
+ "type" : "simple",
+ "max_size" : 1024,
+ "with_counters" : true,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [28, 29, 30, 33, 8],
+ "actions" : ["next.output", "next.set_vlan_output", "next.l3_routing", "next.mpls_routing_v4", "NoAction"],
+ "base_default_next" : null,
+ "next_tables" : {
+ "__HIT__" : "tbl_act_12",
+ "__MISS__" : "tbl_act_13"
+ },
+ "default_entry" : {
+ "action_id" : 8,
+ "action_const" : false,
+ "action_data" : [],
+ "action_entry_const" : false
+ }
+ },
+ {
+ "name" : "tbl_act_12",
+ "id" : 27,
+ "key" : [],
+ "match_type" : "exact",
+ "type" : "simple",
+ "max_size" : 1024,
+ "with_counters" : false,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [49],
+ "actions" : ["act_12"],
+ "base_default_next" : "node_44",
+ "next_tables" : {
+ "act_12" : "node_44"
+ },
+ "default_entry" : {
+ "action_id" : 49,
+ "action_const" : true,
+ "action_data" : [],
+ "action_entry_const" : true
+ }
+ },
+ {
+ "name" : "tbl_act_13",
+ "id" : 28,
+ "key" : [],
+ "match_type" : "exact",
+ "type" : "simple",
+ "max_size" : 1024,
+ "with_counters" : false,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [50],
+ "actions" : ["act_13"],
+ "base_default_next" : "node_44",
+ "next_tables" : {
+ "act_13" : "node_44"
+ },
+ "default_entry" : {
+ "action_id" : 50,
+ "action_const" : true,
+ "action_data" : [],
+ "action_entry_const" : true
+ }
+ },
+ {
+ "name" : "tbl_act_14",
+ "id" : 29,
+ "key" : [],
+ "match_type" : "exact",
+ "type" : "simple",
+ "max_size" : 1024,
+ "with_counters" : false,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [51],
+ "actions" : ["act_14"],
+ "base_default_next" : "next.hashed",
+ "next_tables" : {
+ "act_14" : "next.hashed"
+ },
+ "default_entry" : {
+ "action_id" : 51,
+ "action_const" : true,
+ "action_data" : [],
+ "action_entry_const" : true
+ }
+ },
+ {
+ "name" : "next.hashed",
+ "id" : 30,
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 103,
+ "column" : 10,
+ "source_fragment" : "hashed"
+ },
+ "key" : [
+ {
+ "match_type" : "exact",
+ "target" : ["scalars", "fabric_metadata_t.next_id"],
+ "mask" : null
+ }
+ ],
+ "match_type" : "exact",
+ "type" : "indirect_ws",
+ "action_profile" : "next.ecmp_selector",
+ "max_size" : 1024,
+ "with_counters" : true,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [31, 34, 35, 9],
+ "actions" : ["next.l3_routing", "next.mpls_routing_v4", "next.mpls_routing_v6", "NoAction"],
+ "base_default_next" : "next.broadcast",
+ "next_tables" : {
+ "next.l3_routing" : "next.broadcast",
+ "next.mpls_routing_v4" : "next.broadcast",
+ "next.mpls_routing_v6" : "next.broadcast",
+ "NoAction" : "next.broadcast"
+ }
+ },
+ {
+ "name" : "next.broadcast",
+ "id" : 31,
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 126,
+ "column" : 10,
+ "source_fragment" : "broadcast"
+ },
+ "key" : [
+ {
+ "match_type" : "exact",
+ "target" : ["scalars", "fabric_metadata_t.next_id"],
+ "mask" : null
+ }
+ ],
+ "match_type" : "exact",
+ "type" : "simple",
+ "max_size" : 1024,
+ "with_counters" : true,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [32, 10],
+ "actions" : ["next.set_mcast_group", "NoAction"],
+ "base_default_next" : "node_50",
+ "next_tables" : {
+ "next.set_mcast_group" : "node_50",
+ "NoAction" : "node_50"
+ },
+ "default_entry" : {
+ "action_id" : 10,
+ "action_const" : false,
+ "action_data" : [],
+ "action_entry_const" : false
+ }
+ },
+ {
+ "name" : "tbl_act_15",
+ "id" : 32,
+ "key" : [],
+ "match_type" : "exact",
+ "type" : "simple",
+ "max_size" : 1024,
+ "with_counters" : false,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [52],
+ "actions" : ["act_15"],
+ "base_default_next" : "node_52",
+ "next_tables" : {
+ "act_15" : "node_52"
+ },
+ "default_entry" : {
+ "action_id" : 52,
+ "action_const" : true,
+ "action_data" : [],
+ "action_entry_const" : true
+ }
+ },
+ {
+ "name" : "tbl_act_16",
+ "id" : 33,
+ "key" : [],
+ "match_type" : "exact",
+ "type" : "simple",
+ "max_size" : 1024,
+ "with_counters" : false,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [53],
+ "actions" : ["act_16"],
+ "base_default_next" : "node_54",
+ "next_tables" : {
+ "act_16" : "node_54"
+ },
+ "default_entry" : {
+ "action_id" : 53,
+ "action_const" : true,
+ "action_data" : [],
+ "action_entry_const" : true
+ }
+ },
+ {
+ "name" : "tbl_act_17",
+ "id" : 34,
+ "key" : [],
+ "match_type" : "exact",
+ "type" : "simple",
+ "max_size" : 1024,
+ "with_counters" : false,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [54],
+ "actions" : ["act_17"],
+ "base_default_next" : null,
+ "next_tables" : {
+ "act_17" : null
+ },
+ "default_entry" : {
+ "action_id" : 54,
+ "action_const" : true,
+ "action_data" : [],
+ "action_entry_const" : true
+ }
+ }
+ ],
+ "action_profiles" : [
+ {
+ "name" : "next.ecmp_selector",
+ "id" : 0,
+ "max_size" : 64,
+ "selector" : {
+ "algo" : "crc16",
+ "input" : [
+ {
+ "type" : "field",
+ "value" : ["ethernet", "dst_addr"]
+ },
+ {
+ "type" : "field",
+ "value" : ["ethernet", "src_addr"]
+ },
+ {
+ "type" : "field",
+ "value" : ["scalars", "fabric_metadata_t.ip_proto"]
+ },
+ {
+ "type" : "field",
+ "value" : ["scalars", "fabric_metadata_t.l4_src_port"]
+ },
+ {
+ "type" : "field",
+ "value" : ["scalars", "fabric_metadata_t.l4_dst_port"]
+ }
+ ]
+ }
+ }
+ ],
+ "conditionals" : [
+ {
+ "name" : "node_2",
+ "id" : 0,
+ "source_info" : {
+ "filename" : "include/control/packetio.p4",
+ "line" : 25,
+ "column" : 12,
+ "source_fragment" : "hdr.packet_out.isValid()"
+ },
+ "expression" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "d2b",
+ "left" : null,
+ "right" : {
+ "type" : "field",
+ "value" : ["packet_out", "$valid$"]
+ }
+ }
+ },
+ "true_next" : "tbl_act",
+ "false_next" : "tbl_act_0"
+ },
+ {
+ "name" : "node_5",
+ "id" : 1,
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 147,
+ "column" : 12,
+ "source_fragment" : "gtpu.isValid()"
+ },
+ "expression" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "d2b",
+ "left" : null,
+ "right" : {
+ "type" : "field",
+ "value" : ["gtpu", "$valid$"]
+ }
+ }
+ },
+ "true_next" : "tbl_act_1",
+ "false_next" : "spgw_ingress.ue_filter_table"
+ },
+ {
+ "name" : "node_10",
+ "id" : 2,
+ "expression" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "d2b",
+ "left" : null,
+ "right" : {
+ "type" : "field",
+ "value" : ["scalars", "spgw_ingress_tmp_2"]
+ }
+ }
+ },
+ "true_next" : "tbl_act_4",
+ "false_next" : "node_17"
+ },
+ {
+ "name" : "node_15",
+ "id" : 3,
+ "expression" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "d2b",
+ "left" : null,
+ "right" : {
+ "type" : "field",
+ "value" : ["scalars", "spgw_ingress_tmp_3"]
+ }
+ }
+ },
+ "true_next" : "tbl_act_7",
+ "false_next" : "node_17"
+ },
+ {
+ "name" : "node_17",
+ "id" : 4,
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 167,
+ "column" : 12,
+ "source_fragment" : "!spgw_meta.do_spgw"
+ },
+ "expression" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "not",
+ "left" : null,
+ "right" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "d2b",
+ "left" : null,
+ "right" : {
+ "type" : "field",
+ "value" : ["spgw", "do_spgw"]
+ }
+ }
+ }
+ }
+ },
+ "true_next" : "tbl_act_8",
+ "false_next" : "node_19"
+ },
+ {
+ "name" : "node_19",
+ "id" : 5,
+ "expression" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "not",
+ "left" : null,
+ "right" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "d2b",
+ "left" : null,
+ "right" : {
+ "type" : "field",
+ "value" : ["scalars", "spgw_ingress_hasReturned_0"]
+ }
+ }
+ }
+ }
+ },
+ "true_next" : "node_20",
+ "false_next" : "filtering.ingress_port_vlan"
+ },
+ {
+ "name" : "node_20",
+ "id" : 6,
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 172,
+ "column" : 12,
+ "source_fragment" : "spgw_meta.direction == DIR_UPLINK"
+ },
+ "expression" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "==",
+ "left" : {
+ "type" : "field",
+ "value" : ["spgw", "direction"]
+ },
+ "right" : {
+ "type" : "hexstr",
+ "value" : "0x00"
+ }
+ }
+ },
+ "true_next" : "tbl_spgw_ingress_gtpu_decap",
+ "false_next" : "node_22"
+ },
+ {
+ "name" : "node_22",
+ "id" : 7,
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 189,
+ "column" : 12,
+ "source_fragment" : "spgw_meta.direction == DIR_DOWNLINK"
+ },
+ "expression" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "==",
+ "left" : {
+ "type" : "field",
+ "value" : ["spgw", "direction"]
+ },
+ "right" : {
+ "type" : "hexstr",
+ "value" : "0x01"
+ }
+ }
+ },
+ "true_next" : "spgw_ingress.dl_sess_lookup",
+ "false_next" : "filtering.ingress_port_vlan"
+ },
+ {
+ "name" : "node_26",
+ "id" : 8,
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 190,
+ "column" : 16,
+ "source_fragment" : "!dl_sess_lookup.apply().hit"
+ },
+ "expression" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "not",
+ "left" : null,
+ "right" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "d2b",
+ "left" : null,
+ "right" : {
+ "type" : "field",
+ "value" : ["scalars", "spgw_ingress_tmp_4"]
+ }
+ }
+ }
+ }
+ },
+ "true_next" : "tbl_spgw_ingress_drop_now",
+ "false_next" : "spgw_ingress.ue_cdr_table"
+ },
+ {
+ "name" : "node_31",
+ "id" : 9,
+ "source_info" : {
+ "filename" : "include/control/forwarding.p4",
+ "line" : 157,
+ "column" : 11,
+ "source_fragment" : "fabric_metadata.fwd_type == FWD_BRIDGING"
+ },
+ "expression" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "==",
+ "left" : {
+ "type" : "field",
+ "value" : ["scalars", "fabric_metadata_t.fwd_type"]
+ },
+ "right" : {
+ "type" : "hexstr",
+ "value" : "0x00"
+ }
+ }
+ },
+ "true_next" : "forwarding.bridging",
+ "false_next" : "node_33"
+ },
+ {
+ "name" : "node_33",
+ "id" : 10,
+ "source_info" : {
+ "filename" : "include/control/forwarding.p4",
+ "line" : 158,
+ "column" : 17,
+ "source_fragment" : "fabric_metadata.fwd_type == FWD_MPLS"
+ },
+ "expression" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "==",
+ "left" : {
+ "type" : "field",
+ "value" : ["scalars", "fabric_metadata_t.fwd_type"]
+ },
+ "right" : {
+ "type" : "hexstr",
+ "value" : "0x01"
+ }
+ }
+ },
+ "true_next" : "forwarding.mpls",
+ "false_next" : "node_36"
+ },
+ {
+ "name" : "node_36",
+ "id" : 11,
+ "source_info" : {
+ "filename" : "include/control/forwarding.p4",
+ "line" : 165,
+ "column" : 17,
+ "source_fragment" : "fabric_metadata.fwd_type == FWD_IPV4_UNICAST"
+ },
+ "expression" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "==",
+ "left" : {
+ "type" : "field",
+ "value" : ["scalars", "fabric_metadata_t.fwd_type"]
+ },
+ "right" : {
+ "type" : "hexstr",
+ "value" : "0x02"
+ }
+ }
+ },
+ "true_next" : "forwarding.unicast_v4",
+ "false_next" : "node_38"
+ },
+ {
+ "name" : "node_38",
+ "id" : 12,
+ "source_info" : {
+ "filename" : "include/control/forwarding.p4",
+ "line" : 166,
+ "column" : 17,
+ "source_fragment" : "fabric_metadata.fwd_type == FWD_IPV4_MULTICAST"
+ },
+ "expression" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "==",
+ "left" : {
+ "type" : "field",
+ "value" : ["scalars", "fabric_metadata_t.fwd_type"]
+ },
+ "right" : {
+ "type" : "hexstr",
+ "value" : "0x03"
+ }
+ }
+ },
+ "true_next" : "forwarding.multicast_v4",
+ "false_next" : "forwarding.acl"
+ },
+ {
+ "name" : "node_44",
+ "id" : 13,
+ "expression" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "d2b",
+ "left" : null,
+ "right" : {
+ "type" : "field",
+ "value" : ["scalars", "next_tmp_0"]
+ }
+ }
+ },
+ "true_next" : "node_45",
+ "false_next" : "next.hashed"
+ },
+ {
+ "name" : "node_45",
+ "id" : 14,
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 138,
+ "column" : 16,
+ "source_fragment" : "!hdr.mpls.isValid()"
+ },
+ "expression" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "not",
+ "left" : null,
+ "right" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "d2b",
+ "left" : null,
+ "right" : {
+ "type" : "field",
+ "value" : ["mpls", "$valid$"]
+ }
+ }
+ }
+ }
+ },
+ "true_next" : "node_46",
+ "false_next" : "next.hashed"
+ },
+ {
+ "name" : "node_46",
+ "id" : 15,
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 139,
+ "column" : 19,
+ "source_fragment" : "hdr.ipv4.isValid()"
+ },
+ "expression" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "d2b",
+ "left" : null,
+ "right" : {
+ "type" : "field",
+ "value" : ["ipv4", "$valid$"]
+ }
+ }
+ },
+ "true_next" : "tbl_act_14",
+ "false_next" : "next.hashed"
+ },
+ {
+ "name" : "node_50",
+ "id" : 16,
+ "source_info" : {
+ "filename" : "include/control/port_counter.p4",
+ "line" : 27,
+ "column" : 12,
+ "source_fragment" : "standard_metadata.egress_spec < 511"
+ },
+ "expression" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "<",
+ "left" : {
+ "type" : "field",
+ "value" : ["standard_metadata", "egress_spec"]
+ },
+ "right" : {
+ "type" : "hexstr",
+ "value" : "0x01ff"
+ }
+ }
+ },
+ "true_next" : "tbl_act_15",
+ "false_next" : "node_52"
+ },
+ {
+ "name" : "node_52",
+ "id" : 17,
+ "source_info" : {
+ "filename" : "include/control/port_counter.p4",
+ "line" : 30,
+ "column" : 12,
+ "source_fragment" : "standard_metadata.ingress_port < 511"
+ },
+ "expression" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "<",
+ "left" : {
+ "type" : "field",
+ "value" : ["standard_metadata", "ingress_port"]
+ },
+ "right" : {
+ "type" : "hexstr",
+ "value" : "0x01ff"
+ }
+ }
+ },
+ "true_next" : "tbl_act_16",
+ "false_next" : "node_54"
+ },
+ {
+ "name" : "node_54",
+ "id" : 18,
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 161,
+ "column" : 12,
+ "source_fragment" : "fabric_metadata.pop_vlan_at_egress"
+ },
+ "expression" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "d2b",
+ "left" : null,
+ "right" : {
+ "type" : "field",
+ "value" : ["scalars", "fabric_metadata_t.pop_vlan_at_egress"]
+ }
+ }
+ },
+ "false_next" : null,
+ "true_next" : "tbl_act_17"
+ }
+ ]
+ },
+ {
+ "name" : "egress",
+ "id" : 1,
+ "source_info" : {
+ "filename" : "fabric.p4",
+ "line" : 62,
+ "column" : 8,
+ "source_fragment" : "FabricEgress"
+ },
+ "init_table" : "node_58",
+ "tables" : [
+ {
+ "name" : "tbl_act_18",
+ "id" : 35,
+ "key" : [],
+ "match_type" : "exact",
+ "type" : "simple",
+ "max_size" : 1024,
+ "with_counters" : false,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [56],
+ "actions" : ["act_18"],
+ "base_default_next" : "tbl_act_19",
+ "next_tables" : {
+ "act_18" : "tbl_act_19"
+ },
+ "default_entry" : {
+ "action_id" : 56,
+ "action_const" : true,
+ "action_data" : [],
+ "action_entry_const" : true
+ }
+ },
+ {
+ "name" : "tbl_act_19",
+ "id" : 36,
+ "key" : [],
+ "match_type" : "exact",
+ "type" : "simple",
+ "max_size" : 1024,
+ "with_counters" : false,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [57],
+ "actions" : ["act_19"],
+ "base_default_next" : "node_61",
+ "next_tables" : {
+ "act_19" : "node_61"
+ },
+ "default_entry" : {
+ "action_id" : 57,
+ "action_const" : true,
+ "action_data" : [],
+ "action_entry_const" : true
+ }
+ },
+ {
+ "name" : "tbl_spgw_egress_gtpu_encap",
+ "id" : 37,
+ "key" : [],
+ "match_type" : "exact",
+ "type" : "simple",
+ "max_size" : 1024,
+ "with_counters" : false,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [55],
+ "actions" : ["spgw_egress.gtpu_encap"],
+ "base_default_next" : null,
+ "next_tables" : {
+ "spgw_egress.gtpu_encap" : null
+ },
+ "default_entry" : {
+ "action_id" : 55,
+ "action_const" : true,
+ "action_data" : [],
+ "action_entry_const" : true
+ }
+ }
+ ],
+ "action_profiles" : [],
+ "conditionals" : [
+ {
+ "name" : "node_58",
+ "id" : 19,
+ "source_info" : {
+ "filename" : "include/control/packetio.p4",
+ "line" : 38,
+ "column" : 12,
+ "source_fragment" : "standard_metadata.egress_port == CPU_PORT"
+ },
+ "expression" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "==",
+ "left" : {
+ "type" : "field",
+ "value" : ["standard_metadata", "egress_port"]
+ },
+ "right" : {
+ "type" : "hexstr",
+ "value" : "0x00ff"
+ }
+ }
+ },
+ "true_next" : "tbl_act_18",
+ "false_next" : "tbl_act_19"
+ },
+ {
+ "name" : "node_61",
+ "id" : 20,
+ "source_info" : {
+ "filename" : "include/spgw.p4",
+ "line" : 245,
+ "column" : 12,
+ "source_fragment" : "spgw_meta.do_spgw && spgw_meta.direction == DIR_DOWNLINK"
+ },
+ "expression" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "and",
+ "left" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "d2b",
+ "left" : null,
+ "right" : {
+ "type" : "field",
+ "value" : ["spgw", "do_spgw"]
+ }
+ }
+ },
+ "right" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "==",
+ "left" : {
+ "type" : "field",
+ "value" : ["spgw", "direction"]
+ },
+ "right" : {
+ "type" : "hexstr",
+ "value" : "0x01"
+ }
+ }
+ }
+ }
+ },
+ "false_next" : null,
+ "true_next" : "tbl_spgw_egress_gtpu_encap"
+ }
+ ]
+ }
+ ],
+ "checksums" : [
+ {
+ "name" : "cksum",
+ "id" : 0,
+ "target" : ["ipv4", "hdr_checksum"],
+ "type" : "generic",
+ "calculation" : "calc",
+ "if_cond" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "d2b",
+ "left" : null,
+ "right" : {
+ "type" : "field",
+ "value" : ["ipv4", "$valid$"]
+ }
+ }
+ }
+ },
+ {
+ "name" : "cksum_0",
+ "id" : 1,
+ "target" : ["ipv4", "hdr_checksum"],
+ "type" : "generic",
+ "calculation" : "calc_0",
+ "if_cond" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "d2b",
+ "left" : null,
+ "right" : {
+ "type" : "field",
+ "value" : ["ipv4", "$valid$"]
+ }
+ }
+ }
+ },
+ {
+ "name" : "cksum_1",
+ "id" : 2,
+ "target" : ["gtpu_ipv4", "hdr_checksum"],
+ "type" : "generic",
+ "calculation" : "calc_1",
+ "if_cond" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "d2b",
+ "left" : null,
+ "right" : {
+ "type" : "field",
+ "value" : ["gtpu_ipv4", "$valid$"]
+ }
+ }
+ }
+ },
+ {
+ "name" : "cksum_2",
+ "id" : 3,
+ "target" : ["gtpu_udp", "checksum"],
+ "type" : "generic",
+ "calculation" : "calc_2",
+ "if_cond" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "d2b",
+ "left" : null,
+ "right" : {
+ "type" : "field",
+ "value" : ["gtpu_udp", "$valid$"]
+ }
+ }
+ }
+ }
+ ],
+ "force_arith" : [],
+ "extern_instances" : [],
+ "field_aliases" : [
+ [
+ "queueing_metadata.enq_timestamp",
+ ["standard_metadata", "enq_timestamp"]
+ ],
+ [
+ "queueing_metadata.enq_qdepth",
+ ["standard_metadata", "enq_qdepth"]
+ ],
+ [
+ "queueing_metadata.deq_timedelta",
+ ["standard_metadata", "deq_timedelta"]
+ ],
+ [
+ "queueing_metadata.deq_qdepth",
+ ["standard_metadata", "deq_qdepth"]
+ ],
+ [
+ "intrinsic_metadata.ingress_global_timestamp",
+ ["standard_metadata", "ingress_global_timestamp"]
+ ],
+ [
+ "intrinsic_metadata.lf_field_list",
+ ["standard_metadata", "lf_field_list"]
+ ],
+ [
+ "intrinsic_metadata.mcast_grp",
+ ["standard_metadata", "mcast_grp"]
+ ],
+ [
+ "intrinsic_metadata.resubmit_flag",
+ ["standard_metadata", "resubmit_flag"]
+ ],
+ [
+ "intrinsic_metadata.egress_rid",
+ ["standard_metadata", "egress_rid"]
+ ]
+ ]
+}
\ No newline at end of file
diff --git a/pipelines/fabric/src/main/resources/p4c-out/bmv2/fabric-spgw.p4info b/pipelines/fabric/src/main/resources/p4c-out/bmv2/fabric-spgw.p4info
new file mode 100644
index 0000000..73ad2f9
--- /dev/null
+++ b/pipelines/fabric/src/main/resources/p4c-out/bmv2/fabric-spgw.p4info
@@ -0,0 +1,878 @@
+tables {
+ preamble {
+ id: 33574964
+ name: "spgw_ingress.ue_filter_table"
+ alias: "ue_filter_table"
+ }
+ match_fields {
+ id: 1
+ name: "ipv4.dst_addr"
+ bitwidth: 32
+ match_type: LPM
+ }
+ action_refs {
+ id: 16800567
+ }
+ size: 1024
+}
+tables {
+ preamble {
+ id: 33570382
+ name: "spgw_ingress.s1u_filter_table"
+ alias: "s1u_filter_table"
+ }
+ match_fields {
+ id: 1
+ name: "spgw_meta.s1u_sgw_addr"
+ bitwidth: 32
+ match_type: EXACT
+ }
+ action_refs {
+ id: 16800567
+ }
+ size: 1024
+}
+tables {
+ preamble {
+ id: 33590421
+ name: "spgw_ingress.dl_sess_lookup"
+ alias: "dl_sess_lookup"
+ }
+ match_fields {
+ id: 1
+ name: "ipv4.dst_addr"
+ bitwidth: 32
+ match_type: EXACT
+ }
+ action_refs {
+ id: 16784665
+ }
+ action_refs {
+ id: 16800567
+ annotations: "@defaultonly()"
+ }
+ size: 1024
+}
+tables {
+ preamble {
+ id: 33594626
+ name: "spgw_ingress.ue_cdr_table"
+ alias: "ue_cdr_table"
+ }
+ match_fields {
+ id: 1
+ name: "ipv4.dst_addr"
+ bitwidth: 32
+ match_type: EXACT
+ }
+ action_refs {
+ id: 16800269
+ }
+ action_refs {
+ id: 16800567
+ annotations: "@defaultonly()"
+ }
+ direct_resource_ids: 302053240
+ size: 1024
+}
+tables {
+ preamble {
+ id: 33578399
+ name: "filtering.ingress_port_vlan"
+ alias: "ingress_port_vlan"
+ }
+ match_fields {
+ id: 1
+ name: "standard_metadata.ingress_port"
+ bitwidth: 9
+ match_type: EXACT
+ }
+ match_fields {
+ id: 2
+ name: "hdr.vlan_tag.is_valid"
+ bitwidth: 1
+ match_type: EXACT
+ }
+ match_fields {
+ id: 3
+ name: "hdr.vlan_tag.vlan_id"
+ bitwidth: 12
+ match_type: TERNARY
+ }
+ action_refs {
+ id: 16794505
+ }
+ action_refs {
+ id: 16782367
+ }
+ action_refs {
+ id: 16819938
+ }
+ action_refs {
+ id: 16826365
+ }
+ const_default_action_id: 16819938
+ direct_resource_ids: 302015144
+ size: 1024
+}
+tables {
+ preamble {
+ id: 33619540
+ name: "filtering.fwd_classifier"
+ alias: "fwd_classifier"
+ }
+ match_fields {
+ id: 1
+ name: "standard_metadata.ingress_port"
+ bitwidth: 9
+ match_type: EXACT
+ }
+ match_fields {
+ id: 2
+ name: "hdr.ethernet.dst_addr"
+ bitwidth: 48
+ match_type: EXACT
+ }
+ match_fields {
+ id: 3
+ name: "fabric_metadata.original_ether_type"
+ bitwidth: 16
+ match_type: EXACT
+ }
+ action_refs {
+ id: 16838162
+ }
+ const_default_action_id: 16838162
+ direct_resource_ids: 302033694
+ size: 1024
+}
+tables {
+ preamble {
+ id: 33569146
+ name: "forwarding.bridging"
+ alias: "bridging"
+ }
+ match_fields {
+ id: 1
+ name: "hdr.vlan_tag.vlan_id"
+ bitwidth: 12
+ match_type: EXACT
+ }
+ match_fields {
+ id: 2
+ name: "hdr.ethernet.dst_addr"
+ bitwidth: 48
+ match_type: TERNARY
+ }
+ action_refs {
+ id: 16829931
+ }
+ action_refs {
+ id: 16800567
+ annotations: "@defaultonly()"
+ }
+ direct_resource_ids: 302047449
+ size: 1024
+}
+tables {
+ preamble {
+ id: 33565386
+ name: "forwarding.mpls"
+ alias: "mpls"
+ }
+ match_fields {
+ id: 1
+ name: "hdr.mpls.label"
+ bitwidth: 20
+ match_type: EXACT
+ }
+ action_refs {
+ id: 16842717
+ }
+ action_refs {
+ id: 16800567
+ annotations: "@defaultonly()"
+ }
+ direct_resource_ids: 302001577
+ size: 1024
+}
+tables {
+ preamble {
+ id: 33589684
+ name: "forwarding.unicast_v4"
+ alias: "unicast_v4"
+ }
+ match_fields {
+ id: 1
+ name: "hdr.ipv4.dst_addr"
+ bitwidth: 32
+ match_type: LPM
+ }
+ action_refs {
+ id: 16829931
+ }
+ action_refs {
+ id: 16800567
+ annotations: "@defaultonly()"
+ }
+ direct_resource_ids: 302038636
+ size: 1024
+}
+tables {
+ preamble {
+ id: 33615204
+ name: "forwarding.multicast_v4"
+ alias: "multicast_v4"
+ }
+ match_fields {
+ id: 1
+ name: "hdr.vlan_tag.vlan_id"
+ bitwidth: 12
+ match_type: EXACT
+ }
+ match_fields {
+ id: 2
+ name: "hdr.ipv4.dst_addr"
+ bitwidth: 32
+ match_type: LPM
+ }
+ action_refs {
+ id: 16829931
+ }
+ action_refs {
+ id: 16800567
+ annotations: "@defaultonly()"
+ }
+ direct_resource_ids: 302009236
+ size: 1024
+}
+tables {
+ preamble {
+ id: 33587782
+ name: "forwarding.acl"
+ alias: "acl"
+ }
+ match_fields {
+ id: 1
+ name: "standard_metadata.ingress_port"
+ bitwidth: 9
+ match_type: TERNARY
+ }
+ match_fields {
+ id: 2
+ name: "fabric_metadata.ip_proto"
+ bitwidth: 8
+ match_type: TERNARY
+ }
+ match_fields {
+ id: 3
+ name: "fabric_metadata.l4_src_port"
+ bitwidth: 16
+ match_type: TERNARY
+ }
+ match_fields {
+ id: 4
+ name: "fabric_metadata.l4_dst_port"
+ bitwidth: 16
+ match_type: TERNARY
+ }
+ match_fields {
+ id: 5
+ name: "fabric_metadata.original_ether_type"
+ bitwidth: 16
+ match_type: TERNARY
+ }
+ match_fields {
+ id: 6
+ name: "hdr.ethernet.dst_addr"
+ bitwidth: 48
+ match_type: TERNARY
+ }
+ match_fields {
+ id: 7
+ name: "hdr.ethernet.src_addr"
+ bitwidth: 48
+ match_type: TERNARY
+ }
+ match_fields {
+ id: 8
+ name: "hdr.vlan_tag.vlan_id"
+ bitwidth: 12
+ match_type: TERNARY
+ }
+ match_fields {
+ id: 9
+ name: "hdr.ipv4.src_addr"
+ bitwidth: 32
+ match_type: TERNARY
+ }
+ match_fields {
+ id: 10
+ name: "hdr.ipv4.dst_addr"
+ bitwidth: 32
+ match_type: TERNARY
+ }
+ match_fields {
+ id: 11
+ name: "hdr.icmp.icmp_type"
+ bitwidth: 8
+ match_type: TERNARY
+ }
+ match_fields {
+ id: 12
+ name: "hdr.icmp.icmp_code"
+ bitwidth: 8
+ match_type: TERNARY
+ }
+ action_refs {
+ id: 16829931
+ }
+ action_refs {
+ id: 16805452
+ }
+ action_refs {
+ id: 16815978
+ }
+ action_refs {
+ id: 16819938
+ }
+ const_default_action_id: 16819938
+ direct_resource_ids: 302000008
+ size: 256
+}
+tables {
+ preamble {
+ id: 33615740
+ name: "next.simple"
+ alias: "simple"
+ }
+ match_fields {
+ id: 1
+ name: "fabric_metadata.next_id"
+ bitwidth: 32
+ match_type: EXACT
+ }
+ action_refs {
+ id: 16818315
+ }
+ action_refs {
+ id: 16837690
+ }
+ action_refs {
+ id: 16804266
+ }
+ action_refs {
+ id: 16841192
+ }
+ action_refs {
+ id: 16800567
+ annotations: "@defaultonly()"
+ }
+ direct_resource_ids: 301991179
+ size: 1024
+}
+tables {
+ preamble {
+ id: 33569488
+ name: "next.hashed"
+ alias: "hashed"
+ }
+ match_fields {
+ id: 1
+ name: "fabric_metadata.next_id"
+ bitwidth: 32
+ match_type: EXACT
+ }
+ action_refs {
+ id: 16804266
+ }
+ action_refs {
+ id: 16841192
+ }
+ action_refs {
+ id: 16788519
+ }
+ action_refs {
+ id: 16800567
+ annotations: "@defaultonly()"
+ }
+ implementation_id: 285225078
+ direct_resource_ids: 301993193
+ size: 1024
+}
+tables {
+ preamble {
+ id: 33608545
+ name: "next.broadcast"
+ alias: "broadcast"
+ }
+ match_fields {
+ id: 1
+ name: "fabric_metadata.next_id"
+ bitwidth: 32
+ match_type: EXACT
+ }
+ action_refs {
+ id: 16778974
+ }
+ action_refs {
+ id: 16800567
+ annotations: "@defaultonly()"
+ }
+ direct_resource_ids: 301995093
+ size: 1024
+}
+actions {
+ preamble {
+ id: 16800567
+ name: "NoAction"
+ alias: "NoAction"
+ }
+}
+actions {
+ preamble {
+ id: 16819938
+ name: "nop"
+ alias: "nop"
+ }
+}
+actions {
+ preamble {
+ id: 16840488
+ name: "spgw_ingress.drop_now"
+ alias: "drop_now"
+ }
+}
+actions {
+ preamble {
+ id: 16808035
+ name: "spgw_ingress.gtpu_decap"
+ alias: "gtpu_decap"
+ }
+}
+actions {
+ preamble {
+ id: 16784665
+ name: "spgw_ingress.set_dl_sess_info"
+ alias: "set_dl_sess_info"
+ }
+ params {
+ id: 1
+ name: "teid"
+ bitwidth: 32
+ }
+ params {
+ id: 2
+ name: "s1u_enb_addr"
+ bitwidth: 32
+ }
+ params {
+ id: 3
+ name: "s1u_sgw_addr"
+ bitwidth: 32
+ }
+}
+actions {
+ preamble {
+ id: 16800269
+ name: "spgw_ingress.update_ue_cdr"
+ alias: "update_ue_cdr"
+ }
+}
+actions {
+ preamble {
+ id: 16826365
+ name: "filtering.drop"
+ alias: "filtering.drop"
+ }
+}
+actions {
+ preamble {
+ id: 16782367
+ name: "filtering.set_vlan"
+ alias: "set_vlan"
+ }
+ params {
+ id: 1
+ name: "new_vlan_id"
+ bitwidth: 12
+ }
+}
+actions {
+ preamble {
+ id: 16794505
+ name: "filtering.push_internal_vlan"
+ alias: "push_internal_vlan"
+ }
+ params {
+ id: 1
+ name: "new_vlan_id"
+ bitwidth: 12
+ }
+}
+actions {
+ preamble {
+ id: 16838162
+ name: "filtering.set_forwarding_type"
+ alias: "set_forwarding_type"
+ }
+ params {
+ id: 1
+ name: "fwd_type"
+ bitwidth: 3
+ }
+}
+actions {
+ preamble {
+ id: 16815978
+ name: "forwarding.drop"
+ alias: "forwarding.drop"
+ }
+}
+actions {
+ preamble {
+ id: 16829931
+ name: "forwarding.set_next_id"
+ alias: "set_next_id"
+ }
+ params {
+ id: 1
+ name: "next_id"
+ bitwidth: 32
+ }
+}
+actions {
+ preamble {
+ id: 16842717
+ name: "forwarding.pop_mpls_and_next"
+ alias: "pop_mpls_and_next"
+ }
+ params {
+ id: 1
+ name: "next_id"
+ bitwidth: 32
+ }
+}
+actions {
+ preamble {
+ id: 16805452
+ name: "forwarding.duplicate_to_controller"
+ alias: "duplicate_to_controller"
+ }
+}
+actions {
+ preamble {
+ id: 16818315
+ name: "next.output"
+ alias: "output"
+ }
+ params {
+ id: 1
+ name: "port_num"
+ bitwidth: 9
+ }
+}
+actions {
+ preamble {
+ id: 16837690
+ name: "next.set_vlan_output"
+ alias: "set_vlan_output"
+ }
+ params {
+ id: 1
+ name: "new_vlan_id"
+ bitwidth: 12
+ }
+ params {
+ id: 2
+ name: "port_num"
+ bitwidth: 9
+ }
+}
+actions {
+ preamble {
+ id: 16804266
+ name: "next.l3_routing"
+ alias: "l3_routing"
+ }
+ params {
+ id: 1
+ name: "port_num"
+ bitwidth: 9
+ }
+ params {
+ id: 2
+ name: "smac"
+ bitwidth: 48
+ }
+ params {
+ id: 3
+ name: "dmac"
+ bitwidth: 48
+ }
+}
+actions {
+ preamble {
+ id: 16778974
+ name: "next.set_mcast_group"
+ alias: "set_mcast_group"
+ }
+ params {
+ id: 1
+ name: "gid"
+ bitwidth: 16
+ }
+ params {
+ id: 2
+ name: "smac"
+ bitwidth: 48
+ }
+}
+actions {
+ preamble {
+ id: 16841192
+ name: "next.mpls_routing_v4"
+ alias: "mpls_routing_v4"
+ }
+ params {
+ id: 1
+ name: "port_num"
+ bitwidth: 9
+ }
+ params {
+ id: 2
+ name: "smac"
+ bitwidth: 48
+ }
+ params {
+ id: 3
+ name: "dmac"
+ bitwidth: 48
+ }
+ params {
+ id: 4
+ name: "label"
+ bitwidth: 20
+ }
+}
+actions {
+ preamble {
+ id: 16788519
+ name: "next.mpls_routing_v6"
+ alias: "mpls_routing_v6"
+ }
+ params {
+ id: 1
+ name: "port_num"
+ bitwidth: 9
+ }
+ params {
+ id: 2
+ name: "smac"
+ bitwidth: 48
+ }
+ params {
+ id: 3
+ name: "dmac"
+ bitwidth: 48
+ }
+ params {
+ id: 4
+ name: "label"
+ bitwidth: 20
+ }
+}
+actions {
+ preamble {
+ id: 16839213
+ name: "spgw_egress.gtpu_encap"
+ alias: "gtpu_encap"
+ }
+}
+action_profiles {
+ preamble {
+ id: 285225078
+ name: "next.ecmp_selector"
+ alias: "ecmp_selector"
+ }
+ table_ids: 33569488
+ with_selector: true
+ size: 64
+}
+counters {
+ preamble {
+ id: 302025528
+ name: "port_counters_control.egress_port_counter"
+ alias: "egress_port_counter"
+ }
+ spec {
+ unit: PACKETS
+ }
+ size: 511
+}
+counters {
+ preamble {
+ id: 301999025
+ name: "port_counters_control.ingress_port_counter"
+ alias: "ingress_port_counter"
+ }
+ spec {
+ unit: PACKETS
+ }
+ size: 511
+}
+direct_counters {
+ preamble {
+ id: 302053240
+ name: "spgw_ingress.ue_counter"
+ alias: "ue_counter"
+ }
+ spec {
+ unit: BOTH
+ }
+ direct_table_id: 33594626
+}
+direct_counters {
+ preamble {
+ id: 302015144
+ name: "filtering.ingress_port_vlan_counter"
+ alias: "ingress_port_vlan_counter"
+ }
+ spec {
+ unit: BOTH
+ }
+ direct_table_id: 33578399
+}
+direct_counters {
+ preamble {
+ id: 302033694
+ name: "filtering.fwd_classifier_counter"
+ alias: "fwd_classifier_counter"
+ }
+ spec {
+ unit: BOTH
+ }
+ direct_table_id: 33619540
+}
+direct_counters {
+ preamble {
+ id: 302047449
+ name: "forwarding.bridging_counter"
+ alias: "bridging_counter"
+ }
+ spec {
+ unit: BOTH
+ }
+ direct_table_id: 33569146
+}
+direct_counters {
+ preamble {
+ id: 302001577
+ name: "forwarding.mpls_counter"
+ alias: "mpls_counter"
+ }
+ spec {
+ unit: BOTH
+ }
+ direct_table_id: 33565386
+}
+direct_counters {
+ preamble {
+ id: 302038636
+ name: "forwarding.unicast_v4_counter"
+ alias: "unicast_v4_counter"
+ }
+ spec {
+ unit: BOTH
+ }
+ direct_table_id: 33589684
+}
+direct_counters {
+ preamble {
+ id: 302009236
+ name: "forwarding.multicast_v4_counter"
+ alias: "multicast_v4_counter"
+ }
+ spec {
+ unit: BOTH
+ }
+ direct_table_id: 33615204
+}
+direct_counters {
+ preamble {
+ id: 302000008
+ name: "forwarding.acl_counter"
+ alias: "acl_counter"
+ }
+ spec {
+ unit: BOTH
+ }
+ direct_table_id: 33587782
+}
+direct_counters {
+ preamble {
+ id: 301991179
+ name: "next.simple_counter"
+ alias: "simple_counter"
+ }
+ spec {
+ unit: BOTH
+ }
+ direct_table_id: 33615740
+}
+direct_counters {
+ preamble {
+ id: 301993193
+ name: "next.hashed_counter"
+ alias: "hashed_counter"
+ }
+ spec {
+ unit: BOTH
+ }
+ direct_table_id: 33569488
+}
+direct_counters {
+ preamble {
+ id: 301995093
+ name: "next.broadcast_counter"
+ alias: "broadcast_counter"
+ }
+ spec {
+ unit: BOTH
+ }
+ direct_table_id: 33608545
+}
+controller_packet_metadata {
+ preamble {
+ id: 2868941301
+ name: "packet_in"
+ annotations: "@controller_header(\"packet_in\")"
+ }
+ metadata {
+ id: 1
+ name: "ingress_port"
+ bitwidth: 9
+ }
+ metadata {
+ id: 2
+ name: "_pad"
+ bitwidth: 7
+ }
+}
+controller_packet_metadata {
+ preamble {
+ id: 2868916615
+ name: "packet_out"
+ annotations: "@controller_header(\"packet_out\")"
+ }
+ metadata {
+ id: 1
+ name: "egress_port"
+ bitwidth: 9
+ }
+ metadata {
+ id: 2
+ name: "_pad"
+ bitwidth: 7
+ }
+}
diff --git a/pipelines/fabric/src/main/resources/p4c-out/bmv2/fabric.json b/pipelines/fabric/src/main/resources/p4c-out/bmv2/fabric.json
index 5c6e645..cdaefbc 100644
--- a/pipelines/fabric/src/main/resources/p4c-out/bmv2/fabric.json
+++ b/pipelines/fabric/src/main/resources/p4c-out/bmv2/fabric.json
@@ -206,71 +206,64 @@
"pi_omit" : true
},
{
- "name" : "inner_vlan_tag",
- "id" : 4,
- "header_type" : "vlan_tag_t",
- "metadata" : false,
- "pi_omit" : true
- },
- {
"name" : "mpls",
- "id" : 5,
+ "id" : 4,
"header_type" : "mpls_t",
"metadata" : false,
"pi_omit" : true
},
{
"name" : "ipv4",
- "id" : 6,
+ "id" : 5,
"header_type" : "ipv4_t",
"metadata" : false,
"pi_omit" : true
},
{
"name" : "ipv6",
- "id" : 7,
+ "id" : 6,
"header_type" : "ipv6_t",
"metadata" : false,
"pi_omit" : true
},
{
"name" : "arp",
- "id" : 8,
+ "id" : 7,
"header_type" : "arp_t",
"metadata" : false,
"pi_omit" : true
},
{
"name" : "tcp",
- "id" : 9,
+ "id" : 8,
"header_type" : "tcp_t",
"metadata" : false,
"pi_omit" : true
},
{
"name" : "udp",
- "id" : 10,
+ "id" : 9,
"header_type" : "udp_t",
"metadata" : false,
"pi_omit" : true
},
{
"name" : "icmp",
- "id" : 11,
+ "id" : 10,
"header_type" : "icmp_t",
"metadata" : false,
"pi_omit" : true
},
{
"name" : "packet_out",
- "id" : 12,
+ "id" : 11,
"header_type" : "packet_out_header_t",
"metadata" : false,
"pi_omit" : true
},
{
"name" : "packet_in",
- "id" : 13,
+ "id" : 12,
"header_type" : "packet_in_header_t",
"metadata" : false,
"pi_omit" : true
@@ -282,12 +275,12 @@
"header_union_stacks" : [],
"field_lists" : [],
"errors" : [
- ["NoError", 0],
- ["PacketTooShort", 1],
- ["NoMatch", 2],
- ["StackOutOfBounds", 3],
- ["HeaderTooShort", 4],
- ["ParserTimeout", 5]
+ ["NoError", 1],
+ ["PacketTooShort", 2],
+ ["NoMatch", 3],
+ ["StackOutOfBounds", 4],
+ ["HeaderTooShort", 5],
+ ["ParserTimeout", 6]
],
"enums" : [],
"parsers" : [
@@ -371,16 +364,6 @@
],
"transitions" : [
{
- "value" : "0x9100",
- "mask" : null,
- "next_state" : "parse_vlan_tag"
- },
- {
- "value" : "0x88a8",
- "mask" : null,
- "next_state" : "parse_vlan_tag"
- },
- {
"value" : "0x8100",
"mask" : null,
"next_state" : "parse_vlan_tag"
@@ -401,11 +384,6 @@
"next_state" : "parse_ipv4"
},
{
- "value" : "0x86dd",
- "mask" : null,
- "next_state" : "parse_ipv6"
- },
- {
"value" : "default",
"mask" : null,
"next_state" : null
@@ -434,11 +412,6 @@
],
"transitions" : [
{
- "value" : "0x8100",
- "mask" : null,
- "next_state" : "parse_inner_vlan_tag"
- },
- {
"value" : "0x0806",
"mask" : null,
"next_state" : "parse_arp"
@@ -449,52 +422,9 @@
"next_state" : "parse_ipv4"
},
{
- "value" : "0x86dd",
+ "value" : "0x8847",
"mask" : null,
- "next_state" : "parse_ipv6"
- },
- {
- "value" : "default",
- "mask" : null,
- "next_state" : null
- }
- ],
- "transition_key" : [
- {
- "type" : "field",
- "value" : ["vlan_tag", "ether_type"]
- }
- ]
- },
- {
- "name" : "parse_inner_vlan_tag",
- "id" : 4,
- "parser_ops" : [
- {
- "parameters" : [
- {
- "type" : "regular",
- "value" : "inner_vlan_tag"
- }
- ],
- "op" : "extract"
- }
- ],
- "transitions" : [
- {
- "value" : "0x0806",
- "mask" : null,
- "next_state" : "parse_arp"
- },
- {
- "value" : "0x0800",
- "mask" : null,
- "next_state" : "parse_ipv4"
- },
- {
- "value" : "0x86dd",
- "mask" : null,
- "next_state" : "parse_ipv6"
+ "next_state" : "parse_mpls"
},
{
"value" : "default",
@@ -511,7 +441,7 @@
},
{
"name" : "parse_mpls",
- "id" : 5,
+ "id" : 4,
"parser_ops" : [
{
"parameters" : [
@@ -543,11 +473,6 @@
"next_state" : "parse_ipv4"
},
{
- "value" : "0x06",
- "mask" : null,
- "next_state" : "parse_ipv6"
- },
- {
"value" : "default",
"mask" : null,
"next_state" : "parse_ethernet"
@@ -562,7 +487,7 @@
},
{
"name" : "parse_ipv4",
- "id" : 6,
+ "id" : 5,
"parser_ops" : [
{
"parameters" : [
@@ -617,64 +542,8 @@
]
},
{
- "name" : "parse_ipv6",
- "id" : 7,
- "parser_ops" : [
- {
- "parameters" : [
- {
- "type" : "regular",
- "value" : "ipv6"
- }
- ],
- "op" : "extract"
- },
- {
- "parameters" : [
- {
- "type" : "field",
- "value" : ["scalars", "fabric_metadata_t.ip_proto"]
- },
- {
- "type" : "field",
- "value" : ["ipv6", "next_hdr"]
- }
- ],
- "op" : "set"
- }
- ],
- "transitions" : [
- {
- "value" : "0x06",
- "mask" : null,
- "next_state" : "parse_tcp"
- },
- {
- "value" : "0x11",
- "mask" : null,
- "next_state" : "parse_udp"
- },
- {
- "value" : "0x3a",
- "mask" : null,
- "next_state" : "parse_icmp"
- },
- {
- "value" : "default",
- "mask" : null,
- "next_state" : null
- }
- ],
- "transition_key" : [
- {
- "type" : "field",
- "value" : ["ipv6", "next_hdr"]
- }
- ]
- },
- {
"name" : "parse_arp",
- "id" : 8,
+ "id" : 6,
"parser_ops" : [
{
"parameters" : [
@@ -697,7 +566,7 @@
},
{
"name" : "parse_tcp",
- "id" : 9,
+ "id" : 7,
"parser_ops" : [
{
"parameters" : [
@@ -746,7 +615,7 @@
},
{
"name" : "parse_udp",
- "id" : 10,
+ "id" : 8,
"parser_ops" : [
{
"parameters" : [
@@ -795,7 +664,7 @@
},
{
"name" : "parse_icmp",
- "id" : 11,
+ "id" : 9,
"parser_ops" : [
{
"parameters" : [
@@ -824,21 +693,81 @@
"name" : "deparser",
"id" : 0,
"source_info" : {
- "filename" : "./include/parser.p4",
- "line" : 137,
+ "filename" : "include/parser.p4",
+ "line" : 166,
"column" : 8,
"source_fragment" : "FabricDeparser"
},
- "order" : ["packet_in", "ethernet", "vlan_tag", "inner_vlan_tag", "mpls", "arp", "ipv4", "ipv6", "tcp", "udp", "icmp"]
+ "order" : ["packet_in", "ethernet", "vlan_tag", "mpls", "arp", "ipv4", "tcp", "udp", "icmp"]
}
],
"meter_arrays" : [],
"counter_arrays" : [
{
- "name" : "port_counters_control.egress_port_counter",
+ "name" : "filtering.ingress_port_vlan_counter",
"id" : 0,
+ "is_direct" : true,
+ "binding" : "filtering.ingress_port_vlan"
+ },
+ {
+ "name" : "filtering.fwd_classifier_counter",
+ "id" : 1,
+ "is_direct" : true,
+ "binding" : "filtering.fwd_classifier"
+ },
+ {
+ "name" : "forwarding.bridging_counter",
+ "id" : 2,
+ "is_direct" : true,
+ "binding" : "forwarding.bridging"
+ },
+ {
+ "name" : "forwarding.mpls_counter",
+ "id" : 3,
+ "is_direct" : true,
+ "binding" : "forwarding.mpls"
+ },
+ {
+ "name" : "forwarding.unicast_v4_counter",
+ "id" : 4,
+ "is_direct" : true,
+ "binding" : "forwarding.unicast_v4"
+ },
+ {
+ "name" : "forwarding.multicast_v4_counter",
+ "id" : 5,
+ "is_direct" : true,
+ "binding" : "forwarding.multicast_v4"
+ },
+ {
+ "name" : "forwarding.acl_counter",
+ "id" : 6,
+ "is_direct" : true,
+ "binding" : "forwarding.acl"
+ },
+ {
+ "name" : "next.simple_counter",
+ "id" : 7,
+ "is_direct" : true,
+ "binding" : "next.simple"
+ },
+ {
+ "name" : "next.hashed_counter",
+ "id" : 8,
+ "is_direct" : true,
+ "binding" : "next.hashed"
+ },
+ {
+ "name" : "next.broadcast_counter",
+ "id" : 9,
+ "is_direct" : true,
+ "binding" : "next.broadcast"
+ },
+ {
+ "name" : "port_counters_control.egress_port_counter",
+ "id" : 10,
"source_info" : {
- "filename" : "./include/control/port_counter.p4",
+ "filename" : "include/control/port_counter.p4",
"line" : 23,
"column" : 38,
"source_fragment" : "egress_port_counter"
@@ -848,9 +777,9 @@
},
{
"name" : "port_counters_control.ingress_port_counter",
- "id" : 1,
+ "id" : 11,
"source_info" : {
- "filename" : "./include/control/port_counter.p4",
+ "filename" : "include/control/port_counter.p4",
"line" : 24,
"column" : 38,
"source_fragment" : "ingress_port_counter"
@@ -865,8 +794,8 @@
"name" : "calc",
"id" : 0,
"source_info" : {
- "filename" : "./include/checksum.p4",
- "line" : 51,
+ "filename" : "include/checksum.p4",
+ "line" : 56,
"column" : 8,
"source_fragment" : "verify_checksum(hdr.ipv4.isValid(), ..."
},
@@ -922,8 +851,8 @@
"name" : "calc_0",
"id" : 1,
"source_info" : {
- "filename" : "./include/checksum.p4",
- "line" : 25,
+ "filename" : "include/checksum.p4",
+ "line" : 28,
"column" : 8,
"source_fragment" : "update_checksum(hdr.ipv4.isValid(), ..."
},
@@ -1033,28 +962,16 @@
"primitives" : []
},
{
- "name" : "NoAction",
- "id" : 9,
- "runtime_data" : [],
- "primitives" : []
- },
- {
- "name" : "NoAction",
- "id" : 10,
- "runtime_data" : [],
- "primitives" : []
- },
- {
"name" : "filtering.drop",
- "id" : 11,
+ "id" : 9,
"runtime_data" : [],
"primitives" : [
{
"op" : "drop",
"parameters" : [],
"source_info" : {
- "filename" : "./include/control/filtering.p4",
- "line" : 29,
+ "filename" : "include/control/filtering.p4",
+ "line" : 31,
"column" : 8,
"source_fragment" : "mark_to_drop()"
}
@@ -1063,7 +980,7 @@
},
{
"name" : "filtering.set_vlan",
- "id" : 12,
+ "id" : 10,
"runtime_data" : [
{
"name" : "new_vlan_id",
@@ -1084,8 +1001,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/filtering.p4",
- "line" : 33,
+ "filename" : "include/control/filtering.p4",
+ "line" : 35,
"column" : 8,
"source_fragment" : "hdr.vlan_tag.vlan_id = new_vlan_id"
}
@@ -1094,7 +1011,7 @@
},
{
"name" : "filtering.push_internal_vlan",
- "id" : 13,
+ "id" : 11,
"runtime_data" : [
{
"name" : "new_vlan_id",
@@ -1111,8 +1028,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/filtering.p4",
- "line" : 39,
+ "filename" : "include/control/filtering.p4",
+ "line" : 41,
"column" : 8,
"source_fragment" : "hdr.vlan_tag.setValid()"
}
@@ -1130,8 +1047,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/filtering.p4",
- "line" : 40,
+ "filename" : "include/control/filtering.p4",
+ "line" : 42,
"column" : 8,
"source_fragment" : "hdr.vlan_tag.cfi = 0"
}
@@ -1149,8 +1066,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/filtering.p4",
- "line" : 41,
+ "filename" : "include/control/filtering.p4",
+ "line" : 43,
"column" : 8,
"source_fragment" : "hdr.vlan_tag.pri = 0"
}
@@ -1168,8 +1085,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/filtering.p4",
- "line" : 42,
+ "filename" : "include/control/filtering.p4",
+ "line" : 44,
"column" : 8,
"source_fragment" : "hdr.vlan_tag.ether_type = hdr.ethernet.ether_type"
}
@@ -1187,7 +1104,7 @@
}
],
"source_info" : {
- "filename" : "./include/control/../define.p4",
+ "filename" : "include/control/../define.p4",
"line" : 32,
"column" : 31,
"source_fragment" : "0x8100; ..."
@@ -1206,8 +1123,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/filtering.p4",
- "line" : 33,
+ "filename" : "include/control/filtering.p4",
+ "line" : 35,
"column" : 8,
"source_fragment" : "hdr.vlan_tag.vlan_id = new_vlan_id; ..."
}
@@ -1235,8 +1152,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/filtering.p4",
- "line" : 47,
+ "filename" : "include/control/filtering.p4",
+ "line" : 49,
"column" : 8,
"source_fragment" : "fabric_metadata.pop_vlan_at_egress = true"
}
@@ -1245,7 +1162,7 @@
},
{
"name" : "filtering.set_forwarding_type",
- "id" : 14,
+ "id" : 12,
"runtime_data" : [
{
"name" : "fwd_type",
@@ -1266,8 +1183,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/filtering.p4",
- "line" : 51,
+ "filename" : "include/control/filtering.p4",
+ "line" : 53,
"column" : 8,
"source_fragment" : "fabric_metadata.fwd_type = fwd_type"
}
@@ -1276,15 +1193,15 @@
},
{
"name" : "forwarding.drop",
- "id" : 15,
+ "id" : 13,
"runtime_data" : [],
"primitives" : [
{
"op" : "drop",
"parameters" : [],
"source_info" : {
- "filename" : "./include/control/forwarding.p4",
- "line" : 31,
+ "filename" : "include/control/forwarding.p4",
+ "line" : 37,
"column" : 8,
"source_fragment" : "mark_to_drop()"
}
@@ -1293,6 +1210,68 @@
},
{
"name" : "forwarding.set_next_id",
+ "id" : 14,
+ "runtime_data" : [
+ {
+ "name" : "next_id",
+ "bitwidth" : 32
+ }
+ ],
+ "primitives" : [
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["scalars", "fabric_metadata_t.next_id"]
+ },
+ {
+ "type" : "runtime_data",
+ "value" : 0
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/forwarding.p4",
+ "line" : 41,
+ "column" : 8,
+ "source_fragment" : "fabric_metadata.next_id = next_id"
+ }
+ }
+ ]
+ },
+ {
+ "name" : "forwarding.set_next_id",
+ "id" : 15,
+ "runtime_data" : [
+ {
+ "name" : "next_id",
+ "bitwidth" : 32
+ }
+ ],
+ "primitives" : [
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["scalars", "fabric_metadata_t.next_id"]
+ },
+ {
+ "type" : "runtime_data",
+ "value" : 0
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/forwarding.p4",
+ "line" : 41,
+ "column" : 8,
+ "source_fragment" : "fabric_metadata.next_id = next_id"
+ }
+ }
+ ]
+ },
+ {
+ "name" : "forwarding.set_next_id",
"id" : 16,
"runtime_data" : [
{
@@ -1314,8 +1293,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/forwarding.p4",
- "line" : 35,
+ "filename" : "include/control/forwarding.p4",
+ "line" : 41,
"column" : 8,
"source_fragment" : "fabric_metadata.next_id = next_id"
}
@@ -1345,132 +1324,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/forwarding.p4",
- "line" : 35,
- "column" : 8,
- "source_fragment" : "fabric_metadata.next_id = next_id"
- }
- }
- ]
- },
- {
- "name" : "forwarding.set_next_id",
- "id" : 18,
- "runtime_data" : [
- {
- "name" : "next_id",
- "bitwidth" : 32
- }
- ],
- "primitives" : [
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["scalars", "fabric_metadata_t.next_id"]
- },
- {
- "type" : "runtime_data",
- "value" : 0
- }
- ],
- "source_info" : {
- "filename" : "./include/control/forwarding.p4",
- "line" : 35,
- "column" : 8,
- "source_fragment" : "fabric_metadata.next_id = next_id"
- }
- }
- ]
- },
- {
- "name" : "forwarding.set_next_id",
- "id" : 19,
- "runtime_data" : [
- {
- "name" : "next_id",
- "bitwidth" : 32
- }
- ],
- "primitives" : [
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["scalars", "fabric_metadata_t.next_id"]
- },
- {
- "type" : "runtime_data",
- "value" : 0
- }
- ],
- "source_info" : {
- "filename" : "./include/control/forwarding.p4",
- "line" : 35,
- "column" : 8,
- "source_fragment" : "fabric_metadata.next_id = next_id"
- }
- }
- ]
- },
- {
- "name" : "forwarding.set_next_id",
- "id" : 20,
- "runtime_data" : [
- {
- "name" : "next_id",
- "bitwidth" : 32
- }
- ],
- "primitives" : [
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["scalars", "fabric_metadata_t.next_id"]
- },
- {
- "type" : "runtime_data",
- "value" : 0
- }
- ],
- "source_info" : {
- "filename" : "./include/control/forwarding.p4",
- "line" : 35,
- "column" : 8,
- "source_fragment" : "fabric_metadata.next_id = next_id"
- }
- }
- ]
- },
- {
- "name" : "forwarding.set_next_id",
- "id" : 21,
- "runtime_data" : [
- {
- "name" : "next_id",
- "bitwidth" : 32
- }
- ],
- "primitives" : [
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["scalars", "fabric_metadata_t.next_id"]
- },
- {
- "type" : "runtime_data",
- "value" : 0
- }
- ],
- "source_info" : {
- "filename" : "./include/control/forwarding.p4",
- "line" : 35,
+ "filename" : "include/control/forwarding.p4",
+ "line" : 41,
"column" : 8,
"source_fragment" : "fabric_metadata.next_id = next_id"
}
@@ -1479,7 +1334,7 @@
},
{
"name" : "forwarding.pop_mpls_and_next",
- "id" : 22,
+ "id" : 18,
"runtime_data" : [
{
"name" : "next_id",
@@ -1496,8 +1351,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/forwarding.p4",
- "line" : 39,
+ "filename" : "include/control/forwarding.p4",
+ "line" : 45,
"column" : 8,
"source_fragment" : "hdr.mpls.setInvalid()"
}
@@ -1515,8 +1370,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/forwarding.p4",
- "line" : 40,
+ "filename" : "include/control/forwarding.p4",
+ "line" : 46,
"column" : 8,
"source_fragment" : "fabric_metadata.next_id = next_id"
}
@@ -1525,7 +1380,7 @@
},
{
"name" : "forwarding.duplicate_to_controller",
- "id" : 23,
+ "id" : 19,
"runtime_data" : [],
"primitives" : [
{
@@ -1541,8 +1396,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/../define.p4",
- "line" : 48,
+ "filename" : "include/control/../define.p4",
+ "line" : 50,
"column" : 28,
"source_fragment" : "255; ..."
}
@@ -1551,7 +1406,7 @@
},
{
"name" : "next.output",
- "id" : 24,
+ "id" : 20,
"runtime_data" : [
{
"name" : "port_num",
@@ -1572,8 +1427,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/next.p4",
- "line" : 30,
+ "filename" : "include/control/next.p4",
+ "line" : 33,
"column" : 8,
"source_fragment" : "standard_metadata.egress_spec = port_num"
}
@@ -1582,7 +1437,7 @@
},
{
"name" : "next.set_vlan_output",
- "id" : 25,
+ "id" : 21,
"runtime_data" : [
{
"name" : "new_vlan_id",
@@ -1607,8 +1462,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/next.p4",
- "line" : 34,
+ "filename" : "include/control/next.p4",
+ "line" : 37,
"column" : 8,
"source_fragment" : "hdr.vlan_tag.vlan_id = new_vlan_id"
}
@@ -1636,8 +1491,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/next.p4",
- "line" : 37,
+ "filename" : "include/control/next.p4",
+ "line" : 40,
"column" : 8,
"source_fragment" : "fabric_metadata.pop_vlan_at_egress = false"
}
@@ -1655,8 +1510,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/next.p4",
- "line" : 30,
+ "filename" : "include/control/next.p4",
+ "line" : 33,
"column" : 8,
"source_fragment" : "standard_metadata.egress_spec = port_num; ..."
}
@@ -1665,7 +1520,7 @@
},
{
"name" : "next.l3_routing",
- "id" : 26,
+ "id" : 22,
"runtime_data" : [
{
"name" : "port_num",
@@ -1694,8 +1549,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/next.p4",
- "line" : 42,
+ "filename" : "include/control/next.p4",
+ "line" : 45,
"column" : 8,
"source_fragment" : "hdr.ethernet.src_addr = smac; ..."
}
@@ -1713,8 +1568,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/next.p4",
- "line" : 46,
+ "filename" : "include/control/next.p4",
+ "line" : 49,
"column" : 8,
"source_fragment" : "hdr.ethernet.dst_addr = dmac; ..."
}
@@ -1732,8 +1587,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/next.p4",
- "line" : 30,
+ "filename" : "include/control/next.p4",
+ "line" : 33,
"column" : 8,
"source_fragment" : "standard_metadata.egress_spec = port_num; ..."
}
@@ -1742,7 +1597,7 @@
},
{
"name" : "next.l3_routing",
- "id" : 27,
+ "id" : 23,
"runtime_data" : [
{
"name" : "port_num",
@@ -1771,8 +1626,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/next.p4",
- "line" : 42,
+ "filename" : "include/control/next.p4",
+ "line" : 45,
"column" : 8,
"source_fragment" : "hdr.ethernet.src_addr = smac; ..."
}
@@ -1790,8 +1645,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/next.p4",
- "line" : 46,
+ "filename" : "include/control/next.p4",
+ "line" : 49,
"column" : 8,
"source_fragment" : "hdr.ethernet.dst_addr = dmac; ..."
}
@@ -1809,8 +1664,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/next.p4",
- "line" : 30,
+ "filename" : "include/control/next.p4",
+ "line" : 33,
"column" : 8,
"source_fragment" : "standard_metadata.egress_spec = port_num; ..."
}
@@ -1819,7 +1674,7 @@
},
{
"name" : "next.set_mcast_group",
- "id" : 28,
+ "id" : 24,
"runtime_data" : [
{
"name" : "gid",
@@ -1844,8 +1699,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/next.p4",
- "line" : 56,
+ "filename" : "include/control/next.p4",
+ "line" : 59,
"column" : 8,
"source_fragment" : "standard_metadata.mcast_grp = gid"
}
@@ -1863,8 +1718,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/next.p4",
- "line" : 42,
+ "filename" : "include/control/next.p4",
+ "line" : 45,
"column" : 8,
"source_fragment" : "hdr.ethernet.src_addr = smac; ..."
}
@@ -1873,7 +1728,7 @@
},
{
"name" : "next.mpls_routing_v4",
- "id" : 29,
+ "id" : 25,
"runtime_data" : [
{
"name" : "port_num",
@@ -1906,8 +1761,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/next.p4",
- "line" : 42,
+ "filename" : "include/control/next.p4",
+ "line" : 45,
"column" : 8,
"source_fragment" : "hdr.ethernet.src_addr = smac; ..."
}
@@ -1925,8 +1780,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/next.p4",
- "line" : 46,
+ "filename" : "include/control/next.p4",
+ "line" : 49,
"column" : 8,
"source_fragment" : "hdr.ethernet.dst_addr = dmac; ..."
}
@@ -1944,8 +1799,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/next.p4",
- "line" : 30,
+ "filename" : "include/control/next.p4",
+ "line" : 33,
"column" : 8,
"source_fragment" : "standard_metadata.egress_spec = port_num; ..."
}
@@ -1959,8 +1814,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/next.p4",
- "line" : 62,
+ "filename" : "include/control/next.p4",
+ "line" : 65,
"column" : 8,
"source_fragment" : "hdr.mpls.setValid()"
}
@@ -1970,7 +1825,7 @@
"parameters" : [
{
"type" : "field",
- "value" : ["ethernet", "ether_type"]
+ "value" : ["vlan_tag", "ether_type"]
},
{
"type" : "hexstr",
@@ -1978,7 +1833,7 @@
}
],
"source_info" : {
- "filename" : "./include/control/../define.p4",
+ "filename" : "include/control/../define.p4",
"line" : 33,
"column" : 31,
"source_fragment" : "0x8847; ..."
@@ -1997,8 +1852,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/next.p4",
- "line" : 64,
+ "filename" : "include/control/next.p4",
+ "line" : 67,
"column" : 8,
"source_fragment" : "hdr.mpls.label = label; ..."
}
@@ -2016,8 +1871,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/next.p4",
- "line" : 65,
+ "filename" : "include/control/next.p4",
+ "line" : 68,
"column" : 8,
"source_fragment" : "hdr.mpls.tc = tc; ..."
}
@@ -2035,8 +1890,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/next.p4",
- "line" : 66,
+ "filename" : "include/control/next.p4",
+ "line" : 69,
"column" : 8,
"source_fragment" : "hdr.mpls.bos = 1w1"
}
@@ -2054,8 +1909,199 @@
}
],
"source_info" : {
- "filename" : "./include/control/../header.p4",
- "line" : 19,
+ "filename" : "include/control/../define.p4",
+ "line" : 60,
+ "column" : 32,
+ "source_fragment" : "64; ..."
+ }
+ }
+ ]
+ },
+ {
+ "name" : "next.mpls_routing_v4",
+ "id" : 26,
+ "runtime_data" : [
+ {
+ "name" : "port_num",
+ "bitwidth" : 9
+ },
+ {
+ "name" : "smac",
+ "bitwidth" : 48
+ },
+ {
+ "name" : "dmac",
+ "bitwidth" : 48
+ },
+ {
+ "name" : "label",
+ "bitwidth" : 20
+ }
+ ],
+ "primitives" : [
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["ethernet", "src_addr"]
+ },
+ {
+ "type" : "runtime_data",
+ "value" : 1
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 45,
+ "column" : 8,
+ "source_fragment" : "hdr.ethernet.src_addr = smac; ..."
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["ethernet", "dst_addr"]
+ },
+ {
+ "type" : "runtime_data",
+ "value" : 2
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 49,
+ "column" : 8,
+ "source_fragment" : "hdr.ethernet.dst_addr = dmac; ..."
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["standard_metadata", "egress_spec"]
+ },
+ {
+ "type" : "runtime_data",
+ "value" : 0
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 33,
+ "column" : 8,
+ "source_fragment" : "standard_metadata.egress_spec = port_num; ..."
+ }
+ },
+ {
+ "op" : "add_header",
+ "parameters" : [
+ {
+ "type" : "header",
+ "value" : "mpls"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 65,
+ "column" : 8,
+ "source_fragment" : "hdr.mpls.setValid()"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["vlan_tag", "ether_type"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x8847"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/../define.p4",
+ "line" : 33,
+ "column" : 31,
+ "source_fragment" : "0x8847; ..."
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["mpls", "label"]
+ },
+ {
+ "type" : "runtime_data",
+ "value" : 3
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 67,
+ "column" : 8,
+ "source_fragment" : "hdr.mpls.label = label; ..."
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["mpls", "tc"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x00"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 68,
+ "column" : 8,
+ "source_fragment" : "hdr.mpls.tc = tc; ..."
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["mpls", "bos"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x01"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 69,
+ "column" : 8,
+ "source_fragment" : "hdr.mpls.bos = 1w1"
+ }
+ },
+ {
+ "op" : "assign",
+ "parameters" : [
+ {
+ "type" : "field",
+ "value" : ["mpls", "ttl"]
+ },
+ {
+ "type" : "hexstr",
+ "value" : "0x40"
+ }
+ ],
+ "source_info" : {
+ "filename" : "include/control/../define.p4",
+ "line" : 60,
"column" : 32,
"source_fragment" : "64; ..."
}
@@ -2064,7 +2110,7 @@
},
{
"name" : "next.mpls_routing_v6",
- "id" : 30,
+ "id" : 27,
"runtime_data" : [
{
"name" : "port_num",
@@ -2097,8 +2143,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/next.p4",
- "line" : 42,
+ "filename" : "include/control/next.p4",
+ "line" : 45,
"column" : 8,
"source_fragment" : "hdr.ethernet.src_addr = smac; ..."
}
@@ -2116,8 +2162,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/next.p4",
- "line" : 46,
+ "filename" : "include/control/next.p4",
+ "line" : 49,
"column" : 8,
"source_fragment" : "hdr.ethernet.dst_addr = dmac; ..."
}
@@ -2135,8 +2181,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/next.p4",
- "line" : 30,
+ "filename" : "include/control/next.p4",
+ "line" : 33,
"column" : 8,
"source_fragment" : "standard_metadata.egress_spec = port_num; ..."
}
@@ -2150,8 +2196,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/next.p4",
- "line" : 62,
+ "filename" : "include/control/next.p4",
+ "line" : 65,
"column" : 8,
"source_fragment" : "hdr.mpls.setValid()"
}
@@ -2161,7 +2207,7 @@
"parameters" : [
{
"type" : "field",
- "value" : ["ethernet", "ether_type"]
+ "value" : ["vlan_tag", "ether_type"]
},
{
"type" : "hexstr",
@@ -2169,7 +2215,7 @@
}
],
"source_info" : {
- "filename" : "./include/control/../define.p4",
+ "filename" : "include/control/../define.p4",
"line" : 33,
"column" : 31,
"source_fragment" : "0x8847; ..."
@@ -2188,8 +2234,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/next.p4",
- "line" : 64,
+ "filename" : "include/control/next.p4",
+ "line" : 67,
"column" : 8,
"source_fragment" : "hdr.mpls.label = label; ..."
}
@@ -2207,8 +2253,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/next.p4",
- "line" : 65,
+ "filename" : "include/control/next.p4",
+ "line" : 68,
"column" : 8,
"source_fragment" : "hdr.mpls.tc = tc; ..."
}
@@ -2226,8 +2272,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/next.p4",
- "line" : 66,
+ "filename" : "include/control/next.p4",
+ "line" : 69,
"column" : 8,
"source_fragment" : "hdr.mpls.bos = 1w1"
}
@@ -2245,8 +2291,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/../header.p4",
- "line" : 19,
+ "filename" : "include/control/../define.p4",
+ "line" : 60,
"column" : 32,
"source_fragment" : "64; ..."
}
@@ -2255,7 +2301,7 @@
},
{
"name" : "act",
- "id" : 31,
+ "id" : 28,
"runtime_data" : [],
"primitives" : [
{
@@ -2271,7 +2317,7 @@
}
],
"source_info" : {
- "filename" : "./include/control/packetio.p4",
+ "filename" : "include/control/packetio.p4",
"line" : 26,
"column" : 12,
"source_fragment" : "standard_metadata.egress_spec = hdr.packet_out.egress_port"
@@ -2286,7 +2332,7 @@
}
],
"source_info" : {
- "filename" : "./include/control/packetio.p4",
+ "filename" : "include/control/packetio.p4",
"line" : 27,
"column" : 12,
"source_fragment" : "hdr.packet_out.setInvalid()"
@@ -2296,7 +2342,7 @@
},
{
"name" : "act_0",
- "id" : 32,
+ "id" : 29,
"runtime_data" : [],
"primitives" : [
{
@@ -2304,7 +2350,7 @@
"parameters" : [
{
"type" : "field",
- "value" : ["ethernet", "ether_type"]
+ "value" : ["vlan_tag", "ether_type"]
},
{
"type" : "hexstr",
@@ -2312,7 +2358,7 @@
}
],
"source_info" : {
- "filename" : "./include/control/../define.p4",
+ "filename" : "include/control/../define.p4",
"line" : 35,
"column" : 31,
"source_fragment" : "0x0800; ..."
@@ -2331,7 +2377,7 @@
}
],
"source_info" : {
- "filename" : "./include/control/../define.p4",
+ "filename" : "include/control/../define.p4",
"line" : 35,
"column" : 31,
"source_fragment" : "0x0800; ..."
@@ -2341,52 +2387,7 @@
},
{
"name" : "act_1",
- "id" : 33,
- "runtime_data" : [],
- "primitives" : [
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["ethernet", "ether_type"]
- },
- {
- "type" : "hexstr",
- "value" : "0x86dd"
- }
- ],
- "source_info" : {
- "filename" : "./include/control/../define.p4",
- "line" : 36,
- "column" : 31,
- "source_fragment" : "0x86dd; ..."
- }
- },
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["scalars", "fabric_metadata_t.original_ether_type"]
- },
- {
- "type" : "hexstr",
- "value" : "0x86dd"
- }
- ],
- "source_info" : {
- "filename" : "./include/control/../define.p4",
- "line" : 36,
- "column" : 31,
- "source_fragment" : "0x86dd; ..."
- }
- }
- ]
- },
- {
- "name" : "act_2",
- "id" : 34,
+ "id" : 30,
"runtime_data" : [],
"primitives" : [
{
@@ -2415,8 +2416,8 @@
]
},
{
- "name" : "act_3",
- "id" : 35,
+ "name" : "act_2",
+ "id" : 31,
"runtime_data" : [],
"primitives" : [
{
@@ -2445,8 +2446,8 @@
]
},
{
- "name" : "act_4",
- "id" : 36,
+ "name" : "act_3",
+ "id" : 32,
"runtime_data" : [],
"primitives" : [
{
@@ -2485,8 +2486,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/next.p4",
- "line" : 133,
+ "filename" : "include/control/next.p4",
+ "line" : 140,
"column" : 20,
"source_fragment" : "hdr.ipv4.ttl = hdr.ipv4.ttl - 1"
}
@@ -2494,57 +2495,8 @@
]
},
{
- "name" : "act_5",
- "id" : 37,
- "runtime_data" : [],
- "primitives" : [
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["ipv6", "hop_limit"]
- },
- {
- "type" : "expression",
- "value" : {
- "type" : "expression",
- "value" : {
- "op" : "&",
- "left" : {
- "type" : "expression",
- "value" : {
- "op" : "+",
- "left" : {
- "type" : "field",
- "value" : ["ipv6", "hop_limit"]
- },
- "right" : {
- "type" : "hexstr",
- "value" : "0xff"
- }
- }
- },
- "right" : {
- "type" : "hexstr",
- "value" : "0xff"
- }
- }
- }
- }
- ],
- "source_info" : {
- "filename" : "./include/control/next.p4",
- "line" : 136,
- "column" : 20,
- "source_fragment" : "hdr.ipv6.hop_limit = hdr.ipv6.hop_limit - 1"
- }
- }
- ]
- },
- {
- "name" : "act_6",
- "id" : 38,
+ "name" : "act_4",
+ "id" : 33,
"runtime_data" : [],
"primitives" : [
{
@@ -2586,7 +2538,7 @@
}
],
"source_info" : {
- "filename" : "./include/control/port_counter.p4",
+ "filename" : "include/control/port_counter.p4",
"line" : 28,
"column" : 12,
"source_fragment" : "egress_port_counter.count((bit<32>)standard_metadata.egress_spec)"
@@ -2595,8 +2547,8 @@
]
},
{
- "name" : "act_7",
- "id" : 39,
+ "name" : "act_5",
+ "id" : 34,
"runtime_data" : [],
"primitives" : [
{
@@ -2638,7 +2590,7 @@
}
],
"source_info" : {
- "filename" : "./include/control/port_counter.p4",
+ "filename" : "include/control/port_counter.p4",
"line" : 31,
"column" : 12,
"source_fragment" : "ingress_port_counter.count((bit<32>)standard_metadata.ingress_port)"
@@ -2647,34 +2599,8 @@
]
},
{
- "name" : "act_8",
- "id" : 40,
- "runtime_data" : [],
- "primitives" : [
- {
- "op" : "assign",
- "parameters" : [
- {
- "type" : "field",
- "value" : ["ethernet", "ether_type"]
- },
- {
- "type" : "hexstr",
- "value" : "0x8847"
- }
- ],
- "source_info" : {
- "filename" : "./include/control/../define.p4",
- "line" : 33,
- "column" : 31,
- "source_fragment" : "0x8847; ..."
- }
- }
- ]
- },
- {
- "name" : "act_9",
- "id" : 41,
+ "name" : "act_6",
+ "id" : 35,
"runtime_data" : [],
"primitives" : [
{
@@ -2686,23 +2612,16 @@
},
{
"type" : "field",
- "value" : ["scalars", "fabric_metadata_t.original_ether_type"]
+ "value" : ["vlan_tag", "ether_type"]
}
],
"source_info" : {
- "filename" : "./include/control/next.p4",
- "line" : 156,
- "column" : 16,
- "source_fragment" : "hdr.ethernet.ether_type = fabric_metadata.original_ether_type"
+ "filename" : "include/control/next.p4",
+ "line" : 162,
+ "column" : 12,
+ "source_fragment" : "hdr.ethernet.ether_type = hdr.vlan_tag.ether_type"
}
- }
- ]
- },
- {
- "name" : "act_10",
- "id" : 42,
- "runtime_data" : [],
- "primitives" : [
+ },
{
"op" : "remove_header",
"parameters" : [
@@ -2712,8 +2631,8 @@
}
],
"source_info" : {
- "filename" : "./include/control/next.p4",
- "line" : 158,
+ "filename" : "include/control/next.p4",
+ "line" : 163,
"column" : 12,
"source_fragment" : "hdr.vlan_tag.setInvalid()"
}
@@ -2721,8 +2640,8 @@
]
},
{
- "name" : "act_11",
- "id" : 43,
+ "name" : "act_7",
+ "id" : 36,
"runtime_data" : [],
"primitives" : [
{
@@ -2734,7 +2653,7 @@
}
],
"source_info" : {
- "filename" : "./include/control/packetio.p4",
+ "filename" : "include/control/packetio.p4",
"line" : 39,
"column" : 12,
"source_fragment" : "hdr.packet_in.setValid()"
@@ -2753,7 +2672,7 @@
}
],
"source_info" : {
- "filename" : "./include/control/packetio.p4",
+ "filename" : "include/control/packetio.p4",
"line" : 40,
"column" : 12,
"source_fragment" : "hdr.packet_in.ingress_port = standard_metadata.ingress_port"
@@ -2768,7 +2687,7 @@
"id" : 0,
"source_info" : {
"filename" : "fabric.p4",
- "line" : 29,
+ "line" : 33,
"column" : 8,
"source_fragment" : "FabricIngress"
},
@@ -2784,14 +2703,14 @@
"with_counters" : false,
"support_timeout" : false,
"direct_meters" : null,
- "action_ids" : [31],
+ "action_ids" : [28],
"actions" : ["act"],
"base_default_next" : null,
"next_tables" : {
"act" : null
},
"default_entry" : {
- "action_id" : 31,
+ "action_id" : 28,
"action_const" : true,
"action_data" : [],
"action_entry_const" : true
@@ -2801,8 +2720,8 @@
"name" : "filtering.ingress_port_vlan",
"id" : 1,
"source_info" : {
- "filename" : "./include/control/filtering.p4",
- "line" : 55,
+ "filename" : "include/control/filtering.p4",
+ "line" : 57,
"column" : 10,
"source_fragment" : "ingress_port_vlan"
},
@@ -2826,10 +2745,10 @@
"match_type" : "ternary",
"type" : "simple",
"max_size" : 1024,
- "with_counters" : false,
+ "with_counters" : true,
"support_timeout" : false,
"direct_meters" : null,
- "action_ids" : [13, 12, 0, 11],
+ "action_ids" : [11, 10, 0, 9],
"actions" : ["filtering.push_internal_vlan", "filtering.set_vlan", "nop", "filtering.drop"],
"base_default_next" : "filtering.fwd_classifier",
"next_tables" : {
@@ -2839,7 +2758,7 @@
"filtering.drop" : "filtering.fwd_classifier"
},
"default_entry" : {
- "action_id" : 11,
+ "action_id" : 0,
"action_const" : true,
"action_data" : [],
"action_entry_const" : true
@@ -2849,8 +2768,8 @@
"name" : "filtering.fwd_classifier",
"id" : 2,
"source_info" : {
- "filename" : "./include/control/filtering.p4",
- "line" : 72,
+ "filename" : "include/control/filtering.p4",
+ "line" : 76,
"column" : 10,
"source_fragment" : "fwd_classifier"
},
@@ -2874,17 +2793,17 @@
"match_type" : "exact",
"type" : "simple",
"max_size" : 1024,
- "with_counters" : false,
+ "with_counters" : true,
"support_timeout" : false,
"direct_meters" : null,
- "action_ids" : [14],
+ "action_ids" : [12],
"actions" : ["filtering.set_forwarding_type"],
"base_default_next" : "node_6",
"next_tables" : {
"filtering.set_forwarding_type" : "node_6"
},
"default_entry" : {
- "action_id" : 14,
+ "action_id" : 12,
"action_const" : true,
"action_data" : ["0x0"],
"action_entry_const" : true
@@ -2894,8 +2813,8 @@
"name" : "forwarding.bridging",
"id" : 3,
"source_info" : {
- "filename" : "./include/control/forwarding.p4",
- "line" : 47,
+ "filename" : "include/control/forwarding.p4",
+ "line" : 53,
"column" : 10,
"source_fragment" : "bridging"
},
@@ -2914,10 +2833,10 @@
"match_type" : "ternary",
"type" : "simple",
"max_size" : 1024,
- "with_counters" : false,
+ "with_counters" : true,
"support_timeout" : false,
"direct_meters" : null,
- "action_ids" : [16, 2],
+ "action_ids" : [14, 2],
"actions" : ["forwarding.set_next_id", "NoAction"],
"base_default_next" : "forwarding.acl",
"next_tables" : {
@@ -2935,8 +2854,8 @@
"name" : "forwarding.mpls",
"id" : 4,
"source_info" : {
- "filename" : "./include/control/forwarding.p4",
- "line" : 58,
+ "filename" : "include/control/forwarding.p4",
+ "line" : 65,
"column" : 10,
"source_fragment" : "mpls"
},
@@ -2950,15 +2869,15 @@
"match_type" : "exact",
"type" : "simple",
"max_size" : 1024,
- "with_counters" : false,
+ "with_counters" : true,
"support_timeout" : false,
"direct_meters" : null,
- "action_ids" : [22, 3],
+ "action_ids" : [18, 3],
"actions" : ["forwarding.pop_mpls_and_next", "NoAction"],
- "base_default_next" : "node_10",
+ "base_default_next" : "tbl_act_0",
"next_tables" : {
- "forwarding.pop_mpls_and_next" : "node_10",
- "NoAction" : "node_10"
+ "forwarding.pop_mpls_and_next" : "tbl_act_0",
+ "NoAction" : "tbl_act_0"
},
"default_entry" : {
"action_id" : 3,
@@ -2977,37 +2896,14 @@
"with_counters" : false,
"support_timeout" : false,
"direct_meters" : null,
- "action_ids" : [32],
+ "action_ids" : [29],
"actions" : ["act_0"],
"base_default_next" : "forwarding.acl",
"next_tables" : {
"act_0" : "forwarding.acl"
},
"default_entry" : {
- "action_id" : 32,
- "action_const" : true,
- "action_data" : [],
- "action_entry_const" : true
- }
- },
- {
- "name" : "tbl_act_1",
- "id" : 6,
- "key" : [],
- "match_type" : "exact",
- "type" : "simple",
- "max_size" : 1024,
- "with_counters" : false,
- "support_timeout" : false,
- "direct_meters" : null,
- "action_ids" : [33],
- "actions" : ["act_1"],
- "base_default_next" : "forwarding.acl",
- "next_tables" : {
- "act_1" : "forwarding.acl"
- },
- "default_entry" : {
- "action_id" : 33,
+ "action_id" : 29,
"action_const" : true,
"action_data" : [],
"action_entry_const" : true
@@ -3015,10 +2911,10 @@
},
{
"name" : "forwarding.unicast_v4",
- "id" : 7,
+ "id" : 6,
"source_info" : {
- "filename" : "./include/control/forwarding.p4",
- "line" : 68,
+ "filename" : "include/control/forwarding.p4",
+ "line" : 76,
"column" : 10,
"source_fragment" : "unicast_v4"
},
@@ -3032,10 +2928,10 @@
"match_type" : "lpm",
"type" : "simple",
"max_size" : 1024,
- "with_counters" : false,
+ "with_counters" : true,
"support_timeout" : false,
"direct_meters" : null,
- "action_ids" : [17, 4],
+ "action_ids" : [15, 4],
"actions" : ["forwarding.set_next_id", "NoAction"],
"base_default_next" : "forwarding.acl",
"next_tables" : {
@@ -3051,10 +2947,10 @@
},
{
"name" : "forwarding.multicast_v4",
- "id" : 8,
+ "id" : 7,
"source_info" : {
- "filename" : "./include/control/forwarding.p4",
- "line" : 78,
+ "filename" : "include/control/forwarding.p4",
+ "line" : 87,
"column" : 10,
"source_fragment" : "multicast_v4"
},
@@ -3073,10 +2969,10 @@
"match_type" : "lpm",
"type" : "simple",
"max_size" : 1024,
- "with_counters" : false,
+ "with_counters" : true,
"support_timeout" : false,
"direct_meters" : null,
- "action_ids" : [18, 5],
+ "action_ids" : [16, 5],
"actions" : ["forwarding.set_next_id", "NoAction"],
"base_default_next" : "forwarding.acl",
"next_tables" : {
@@ -3091,88 +2987,11 @@
}
},
{
- "name" : "forwarding.unicast_v6",
- "id" : 9,
- "source_info" : {
- "filename" : "./include/control/forwarding.p4",
- "line" : 89,
- "column" : 10,
- "source_fragment" : "unicast_v6"
- },
- "key" : [
- {
- "match_type" : "lpm",
- "target" : ["ipv6", "dst_addr"],
- "mask" : null
- }
- ],
- "match_type" : "lpm",
- "type" : "simple",
- "max_size" : 1024,
- "with_counters" : false,
- "support_timeout" : false,
- "direct_meters" : null,
- "action_ids" : [19, 6],
- "actions" : ["forwarding.set_next_id", "NoAction"],
- "base_default_next" : "forwarding.acl",
- "next_tables" : {
- "forwarding.set_next_id" : "forwarding.acl",
- "NoAction" : "forwarding.acl"
- },
- "default_entry" : {
- "action_id" : 6,
- "action_const" : false,
- "action_data" : [],
- "action_entry_const" : false
- }
- },
- {
- "name" : "forwarding.multicast_v6",
- "id" : 10,
- "source_info" : {
- "filename" : "./include/control/forwarding.p4",
- "line" : 99,
- "column" : 10,
- "source_fragment" : "multicast_v6"
- },
- "key" : [
- {
- "match_type" : "exact",
- "target" : ["vlan_tag", "vlan_id"],
- "mask" : null
- },
- {
- "match_type" : "lpm",
- "target" : ["ipv6", "dst_addr"],
- "mask" : null
- }
- ],
- "match_type" : "lpm",
- "type" : "simple",
- "max_size" : 1024,
- "with_counters" : false,
- "support_timeout" : false,
- "direct_meters" : null,
- "action_ids" : [20, 7],
- "actions" : ["forwarding.set_next_id", "NoAction"],
- "base_default_next" : "forwarding.acl",
- "next_tables" : {
- "forwarding.set_next_id" : "forwarding.acl",
- "NoAction" : "forwarding.acl"
- },
- "default_entry" : {
- "action_id" : 7,
- "action_const" : false,
- "action_data" : [],
- "action_entry_const" : false
- }
- },
- {
"name" : "forwarding.acl",
- "id" : 11,
+ "id" : 8,
"source_info" : {
- "filename" : "./include/control/forwarding.p4",
- "line" : 110,
+ "filename" : "include/control/forwarding.p4",
+ "line" : 127,
"column" : 10,
"source_fragment" : "acl"
},
@@ -3241,10 +3060,10 @@
"match_type" : "ternary",
"type" : "simple",
"max_size" : 256,
- "with_counters" : false,
+ "with_counters" : true,
"support_timeout" : false,
"direct_meters" : null,
- "action_ids" : [21, 23, 15, 1],
+ "action_ids" : [17, 19, 13, 1],
"actions" : ["forwarding.set_next_id", "forwarding.duplicate_to_controller", "forwarding.drop", "nop"],
"base_default_next" : "next.simple",
"next_tables" : {
@@ -3262,10 +3081,10 @@
},
{
"name" : "next.simple",
- "id" : 12,
+ "id" : 9,
"source_info" : {
- "filename" : "./include/control/next.p4",
- "line" : 86,
+ "filename" : "include/control/next.p4",
+ "line" : 89,
"column" : 10,
"source_fragment" : "simple"
},
@@ -3279,26 +3098,26 @@
"match_type" : "exact",
"type" : "simple",
"max_size" : 1024,
- "with_counters" : false,
+ "with_counters" : true,
"support_timeout" : false,
"direct_meters" : null,
- "action_ids" : [24, 25, 26, 8],
- "actions" : ["next.output", "next.set_vlan_output", "next.l3_routing", "NoAction"],
+ "action_ids" : [20, 21, 22, 25, 6],
+ "actions" : ["next.output", "next.set_vlan_output", "next.l3_routing", "next.mpls_routing_v4", "NoAction"],
"base_default_next" : null,
"next_tables" : {
- "__HIT__" : "tbl_act_2",
- "__MISS__" : "tbl_act_3"
+ "__HIT__" : "tbl_act_1",
+ "__MISS__" : "tbl_act_2"
},
"default_entry" : {
- "action_id" : 8,
+ "action_id" : 6,
"action_const" : false,
"action_data" : [],
"action_entry_const" : false
}
},
{
- "name" : "tbl_act_2",
- "id" : 13,
+ "name" : "tbl_act_1",
+ "id" : 10,
"key" : [],
"match_type" : "exact",
"type" : "simple",
@@ -3306,14 +3125,37 @@
"with_counters" : false,
"support_timeout" : false,
"direct_meters" : null,
- "action_ids" : [34],
- "actions" : ["act_2"],
- "base_default_next" : "node_25",
+ "action_ids" : [30],
+ "actions" : ["act_1"],
+ "base_default_next" : "node_19",
"next_tables" : {
- "act_2" : "node_25"
+ "act_1" : "node_19"
},
"default_entry" : {
- "action_id" : 34,
+ "action_id" : 30,
+ "action_const" : true,
+ "action_data" : [],
+ "action_entry_const" : true
+ }
+ },
+ {
+ "name" : "tbl_act_2",
+ "id" : 11,
+ "key" : [],
+ "match_type" : "exact",
+ "type" : "simple",
+ "max_size" : 1024,
+ "with_counters" : false,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [31],
+ "actions" : ["act_2"],
+ "base_default_next" : "node_19",
+ "next_tables" : {
+ "act_2" : "node_19"
+ },
+ "default_entry" : {
+ "action_id" : 31,
"action_const" : true,
"action_data" : [],
"action_entry_const" : true
@@ -3321,7 +3163,7 @@
},
{
"name" : "tbl_act_3",
- "id" : 14,
+ "id" : 12,
"key" : [],
"match_type" : "exact",
"type" : "simple",
@@ -3329,20 +3171,89 @@
"with_counters" : false,
"support_timeout" : false,
"direct_meters" : null,
- "action_ids" : [35],
+ "action_ids" : [32],
"actions" : ["act_3"],
- "base_default_next" : "node_25",
+ "base_default_next" : "next.hashed",
"next_tables" : {
- "act_3" : "node_25"
+ "act_3" : "next.hashed"
},
"default_entry" : {
- "action_id" : 35,
+ "action_id" : 32,
"action_const" : true,
"action_data" : [],
"action_entry_const" : true
}
},
{
+ "name" : "next.hashed",
+ "id" : 13,
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 103,
+ "column" : 10,
+ "source_fragment" : "hashed"
+ },
+ "key" : [
+ {
+ "match_type" : "exact",
+ "target" : ["scalars", "fabric_metadata_t.next_id"],
+ "mask" : null
+ }
+ ],
+ "match_type" : "exact",
+ "type" : "indirect_ws",
+ "action_profile" : "next.ecmp_selector",
+ "max_size" : 1024,
+ "with_counters" : true,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [23, 26, 27, 7],
+ "actions" : ["next.l3_routing", "next.mpls_routing_v4", "next.mpls_routing_v6", "NoAction"],
+ "base_default_next" : "next.broadcast",
+ "next_tables" : {
+ "next.l3_routing" : "next.broadcast",
+ "next.mpls_routing_v4" : "next.broadcast",
+ "next.mpls_routing_v6" : "next.broadcast",
+ "NoAction" : "next.broadcast"
+ }
+ },
+ {
+ "name" : "next.broadcast",
+ "id" : 14,
+ "source_info" : {
+ "filename" : "include/control/next.p4",
+ "line" : 126,
+ "column" : 10,
+ "source_fragment" : "broadcast"
+ },
+ "key" : [
+ {
+ "match_type" : "exact",
+ "target" : ["scalars", "fabric_metadata_t.next_id"],
+ "mask" : null
+ }
+ ],
+ "match_type" : "exact",
+ "type" : "simple",
+ "max_size" : 1024,
+ "with_counters" : true,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [24, 8],
+ "actions" : ["next.set_mcast_group", "NoAction"],
+ "base_default_next" : "node_25",
+ "next_tables" : {
+ "next.set_mcast_group" : "node_25",
+ "NoAction" : "node_25"
+ },
+ "default_entry" : {
+ "action_id" : 8,
+ "action_const" : false,
+ "action_data" : [],
+ "action_entry_const" : false
+ }
+ },
+ {
"name" : "tbl_act_4",
"id" : 15,
"key" : [],
@@ -3352,14 +3263,14 @@
"with_counters" : false,
"support_timeout" : false,
"direct_meters" : null,
- "action_ids" : [36],
+ "action_ids" : [33],
"actions" : ["act_4"],
- "base_default_next" : "next.hashed",
+ "base_default_next" : "node_27",
"next_tables" : {
- "act_4" : "next.hashed"
+ "act_4" : "node_27"
},
"default_entry" : {
- "action_id" : 36,
+ "action_id" : 33,
"action_const" : true,
"action_data" : [],
"action_entry_const" : true
@@ -3375,91 +3286,22 @@
"with_counters" : false,
"support_timeout" : false,
"direct_meters" : null,
- "action_ids" : [37],
+ "action_ids" : [34],
"actions" : ["act_5"],
- "base_default_next" : "next.hashed",
+ "base_default_next" : "node_29",
"next_tables" : {
- "act_5" : "next.hashed"
+ "act_5" : "node_29"
},
"default_entry" : {
- "action_id" : 37,
+ "action_id" : 34,
"action_const" : true,
"action_data" : [],
"action_entry_const" : true
}
},
{
- "name" : "next.hashed",
- "id" : 17,
- "source_info" : {
- "filename" : "./include/control/next.p4",
- "line" : 98,
- "column" : 10,
- "source_fragment" : "hashed"
- },
- "key" : [
- {
- "match_type" : "exact",
- "target" : ["scalars", "fabric_metadata_t.next_id"],
- "mask" : null
- }
- ],
- "match_type" : "exact",
- "type" : "indirect_ws",
- "action_profile" : "next.ecmp_selector",
- "max_size" : 1024,
- "with_counters" : false,
- "support_timeout" : false,
- "direct_meters" : null,
- "action_ids" : [27, 29, 30, 9],
- "actions" : ["next.l3_routing", "next.mpls_routing_v4", "next.mpls_routing_v6", "NoAction"],
- "base_default_next" : "next.broadcast",
- "next_tables" : {
- "next.l3_routing" : "next.broadcast",
- "next.mpls_routing_v4" : "next.broadcast",
- "next.mpls_routing_v6" : "next.broadcast",
- "NoAction" : "next.broadcast"
- }
- },
- {
- "name" : "next.broadcast",
- "id" : 18,
- "source_info" : {
- "filename" : "./include/control/next.p4",
- "line" : 120,
- "column" : 10,
- "source_fragment" : "broadcast"
- },
- "key" : [
- {
- "match_type" : "exact",
- "target" : ["scalars", "fabric_metadata_t.next_id"],
- "mask" : null
- }
- ],
- "match_type" : "exact",
- "type" : "simple",
- "max_size" : 1024,
- "with_counters" : false,
- "support_timeout" : false,
- "direct_meters" : null,
- "action_ids" : [28, 10],
- "actions" : ["next.set_mcast_group", "NoAction"],
- "base_default_next" : "node_33",
- "next_tables" : {
- "next.set_mcast_group" : "node_33",
- "NoAction" : "node_33"
- },
- "default_entry" : {
- "action_id" : 10,
- "action_const" : false,
- "action_data" : [],
- "action_entry_const" : false
- }
- },
- {
"name" : "tbl_act_6",
- "id" : 19,
+ "id" : 17,
"key" : [],
"match_type" : "exact",
"type" : "simple",
@@ -3467,37 +3309,14 @@
"with_counters" : false,
"support_timeout" : false,
"direct_meters" : null,
- "action_ids" : [38],
+ "action_ids" : [35],
"actions" : ["act_6"],
- "base_default_next" : "node_35",
- "next_tables" : {
- "act_6" : "node_35"
- },
- "default_entry" : {
- "action_id" : 38,
- "action_const" : true,
- "action_data" : [],
- "action_entry_const" : true
- }
- },
- {
- "name" : "tbl_act_7",
- "id" : 20,
- "key" : [],
- "match_type" : "exact",
- "type" : "simple",
- "max_size" : 1024,
- "with_counters" : false,
- "support_timeout" : false,
- "direct_meters" : null,
- "action_ids" : [39],
- "actions" : ["act_7"],
"base_default_next" : null,
"next_tables" : {
- "act_7" : null
+ "act_6" : null
},
"default_entry" : {
- "action_id" : 39,
+ "action_id" : 35,
"action_const" : true,
"action_data" : [],
"action_entry_const" : true
@@ -3541,7 +3360,7 @@
"name" : "node_2",
"id" : 0,
"source_info" : {
- "filename" : "./include/control/packetio.p4",
+ "filename" : "include/control/packetio.p4",
"line" : 25,
"column" : 12,
"source_fragment" : "hdr.packet_out.isValid()"
@@ -3549,14 +3368,11 @@
"expression" : {
"type" : "expression",
"value" : {
- "op" : "==",
- "left" : {
+ "op" : "d2b",
+ "left" : null,
+ "right" : {
"type" : "field",
"value" : ["packet_out", "$valid$"]
- },
- "right" : {
- "type" : "hexstr",
- "value" : "0x01"
}
}
},
@@ -3567,8 +3383,8 @@
"name" : "node_6",
"id" : 1,
"source_info" : {
- "filename" : "./include/control/forwarding.p4",
- "line" : 139,
+ "filename" : "include/control/forwarding.p4",
+ "line" : 157,
"column" : 11,
"source_fragment" : "fabric_metadata.fwd_type == FWD_BRIDGING"
},
@@ -3593,8 +3409,8 @@
"name" : "node_8",
"id" : 2,
"source_info" : {
- "filename" : "./include/control/forwarding.p4",
- "line" : 140,
+ "filename" : "include/control/forwarding.p4",
+ "line" : 158,
"column" : 17,
"source_fragment" : "fabric_metadata.fwd_type == FWD_MPLS"
},
@@ -3613,40 +3429,14 @@
}
},
"true_next" : "forwarding.mpls",
- "false_next" : "node_13"
+ "false_next" : "node_11"
},
{
- "name" : "node_10",
+ "name" : "node_11",
"id" : 3,
"source_info" : {
- "filename" : "./include/control/forwarding.p4",
- "line" : 142,
- "column" : 16,
- "source_fragment" : "hdr.ipv4.isValid()"
- },
- "expression" : {
- "type" : "expression",
- "value" : {
- "op" : "==",
- "left" : {
- "type" : "field",
- "value" : ["ipv4", "$valid$"]
- },
- "right" : {
- "type" : "hexstr",
- "value" : "0x01"
- }
- }
- },
- "true_next" : "tbl_act_0",
- "false_next" : "tbl_act_1"
- },
- {
- "name" : "node_13",
- "id" : 4,
- "source_info" : {
- "filename" : "./include/control/forwarding.p4",
- "line" : 150,
+ "filename" : "include/control/forwarding.p4",
+ "line" : 165,
"column" : 17,
"source_fragment" : "fabric_metadata.fwd_type == FWD_IPV4_UNICAST"
},
@@ -3665,14 +3455,14 @@
}
},
"true_next" : "forwarding.unicast_v4",
- "false_next" : "node_15"
+ "false_next" : "node_13"
},
{
- "name" : "node_15",
- "id" : 5,
+ "name" : "node_13",
+ "id" : 4,
"source_info" : {
- "filename" : "./include/control/forwarding.p4",
- "line" : 151,
+ "filename" : "include/control/forwarding.p4",
+ "line" : 166,
"column" : 17,
"source_fragment" : "fabric_metadata.fwd_type == FWD_IPV4_MULTICAST"
},
@@ -3691,63 +3481,11 @@
}
},
"true_next" : "forwarding.multicast_v4",
- "false_next" : "node_17"
- },
- {
- "name" : "node_17",
- "id" : 6,
- "source_info" : {
- "filename" : "./include/control/forwarding.p4",
- "line" : 152,
- "column" : 17,
- "source_fragment" : "fabric_metadata.fwd_type == FWD_IPV6_UNICAST"
- },
- "expression" : {
- "type" : "expression",
- "value" : {
- "op" : "==",
- "left" : {
- "type" : "field",
- "value" : ["scalars", "fabric_metadata_t.fwd_type"]
- },
- "right" : {
- "type" : "hexstr",
- "value" : "0x04"
- }
- }
- },
- "true_next" : "forwarding.unicast_v6",
- "false_next" : "node_19"
- },
- {
- "name" : "node_19",
- "id" : 7,
- "source_info" : {
- "filename" : "./include/control/forwarding.p4",
- "line" : 153,
- "column" : 17,
- "source_fragment" : "fabric_metadata.fwd_type == FWD_IPV6_MULTICAST"
- },
- "expression" : {
- "type" : "expression",
- "value" : {
- "op" : "==",
- "left" : {
- "type" : "field",
- "value" : ["scalars", "fabric_metadata_t.fwd_type"]
- },
- "right" : {
- "type" : "hexstr",
- "value" : "0x05"
- }
- }
- },
- "true_next" : "forwarding.multicast_v6",
"false_next" : "forwarding.acl"
},
{
- "name" : "node_25",
- "id" : 8,
+ "name" : "node_19",
+ "id" : 5,
"expression" : {
"type" : "expression",
"value" : {
@@ -3759,92 +3497,67 @@
}
}
},
- "true_next" : "node_26",
+ "true_next" : "node_20",
"false_next" : "next.hashed"
},
{
- "name" : "node_26",
- "id" : 9,
+ "name" : "node_20",
+ "id" : 6,
"source_info" : {
- "filename" : "./include/control/next.p4",
- "line" : 131,
- "column" : 17,
- "source_fragment" : "hdr.mpls.isValid()"
+ "filename" : "include/control/next.p4",
+ "line" : 138,
+ "column" : 16,
+ "source_fragment" : "!hdr.mpls.isValid()"
},
"expression" : {
"type" : "expression",
"value" : {
- "op" : "!=",
- "left" : {
- "type" : "field",
- "value" : ["mpls", "$valid$"]
- },
+ "op" : "not",
+ "left" : null,
"right" : {
- "type" : "hexstr",
- "value" : "0x01"
+ "type" : "expression",
+ "value" : {
+ "op" : "d2b",
+ "left" : null,
+ "right" : {
+ "type" : "field",
+ "value" : ["mpls", "$valid$"]
+ }
+ }
}
}
},
- "true_next" : "node_27",
+ "true_next" : "node_21",
"false_next" : "next.hashed"
},
{
- "name" : "node_27",
- "id" : 10,
+ "name" : "node_21",
+ "id" : 7,
"source_info" : {
- "filename" : "./include/control/next.p4",
- "line" : 132,
+ "filename" : "include/control/next.p4",
+ "line" : 139,
"column" : 19,
"source_fragment" : "hdr.ipv4.isValid()"
},
"expression" : {
"type" : "expression",
"value" : {
- "op" : "==",
- "left" : {
+ "op" : "d2b",
+ "left" : null,
+ "right" : {
"type" : "field",
"value" : ["ipv4", "$valid$"]
- },
- "right" : {
- "type" : "hexstr",
- "value" : "0x01"
}
}
},
- "true_next" : "tbl_act_4",
- "false_next" : "node_29"
- },
- {
- "name" : "node_29",
- "id" : 11,
- "source_info" : {
- "filename" : "./include/control/next.p4",
- "line" : 135,
- "column" : 25,
- "source_fragment" : "hdr.ipv6.isValid()"
- },
- "expression" : {
- "type" : "expression",
- "value" : {
- "op" : "==",
- "left" : {
- "type" : "field",
- "value" : ["ipv6", "$valid$"]
- },
- "right" : {
- "type" : "hexstr",
- "value" : "0x01"
- }
- }
- },
- "true_next" : "tbl_act_5",
+ "true_next" : "tbl_act_3",
"false_next" : "next.hashed"
},
{
- "name" : "node_33",
- "id" : 12,
+ "name" : "node_25",
+ "id" : 8,
"source_info" : {
- "filename" : "./include/control/port_counter.p4",
+ "filename" : "include/control/port_counter.p4",
"line" : 27,
"column" : 12,
"source_fragment" : "standard_metadata.egress_spec < 511"
@@ -3863,14 +3576,14 @@
}
}
},
- "true_next" : "tbl_act_6",
- "false_next" : "node_35"
+ "true_next" : "tbl_act_4",
+ "false_next" : "node_27"
},
{
- "name" : "node_35",
- "id" : 13,
+ "name" : "node_27",
+ "id" : 9,
"source_info" : {
- "filename" : "./include/control/port_counter.p4",
+ "filename" : "include/control/port_counter.p4",
"line" : 30,
"column" : 12,
"source_fragment" : "standard_metadata.ingress_port < 511"
@@ -3889,123 +3602,15 @@
}
}
},
- "false_next" : null,
- "true_next" : "tbl_act_7"
- }
- ]
- },
- {
- "name" : "egress",
- "id" : 1,
- "source_info" : {
- "filename" : "fabric.p4",
- "line" : 48,
- "column" : 8,
- "source_fragment" : "FabricEgress"
- },
- "init_table" : "node_39",
- "tables" : [
- {
- "name" : "tbl_act_8",
- "id" : 21,
- "key" : [],
- "match_type" : "exact",
- "type" : "simple",
- "max_size" : 1024,
- "with_counters" : false,
- "support_timeout" : false,
- "direct_meters" : null,
- "action_ids" : [40],
- "actions" : ["act_8"],
- "base_default_next" : "tbl_act_10",
- "next_tables" : {
- "act_8" : "tbl_act_10"
- },
- "default_entry" : {
- "action_id" : 40,
- "action_const" : true,
- "action_data" : [],
- "action_entry_const" : true
- }
+ "true_next" : "tbl_act_5",
+ "false_next" : "node_29"
},
{
- "name" : "tbl_act_9",
- "id" : 22,
- "key" : [],
- "match_type" : "exact",
- "type" : "simple",
- "max_size" : 1024,
- "with_counters" : false,
- "support_timeout" : false,
- "direct_meters" : null,
- "action_ids" : [41],
- "actions" : ["act_9"],
- "base_default_next" : "tbl_act_10",
- "next_tables" : {
- "act_9" : "tbl_act_10"
- },
- "default_entry" : {
- "action_id" : 41,
- "action_const" : true,
- "action_data" : [],
- "action_entry_const" : true
- }
- },
- {
- "name" : "tbl_act_10",
- "id" : 23,
- "key" : [],
- "match_type" : "exact",
- "type" : "simple",
- "max_size" : 1024,
- "with_counters" : false,
- "support_timeout" : false,
- "direct_meters" : null,
- "action_ids" : [42],
- "actions" : ["act_10"],
- "base_default_next" : "node_44",
- "next_tables" : {
- "act_10" : "node_44"
- },
- "default_entry" : {
- "action_id" : 42,
- "action_const" : true,
- "action_data" : [],
- "action_entry_const" : true
- }
- },
- {
- "name" : "tbl_act_11",
- "id" : 24,
- "key" : [],
- "match_type" : "exact",
- "type" : "simple",
- "max_size" : 1024,
- "with_counters" : false,
- "support_timeout" : false,
- "direct_meters" : null,
- "action_ids" : [43],
- "actions" : ["act_11"],
- "base_default_next" : null,
- "next_tables" : {
- "act_11" : null
- },
- "default_entry" : {
- "action_id" : 43,
- "action_const" : true,
- "action_data" : [],
- "action_entry_const" : true
- }
- }
- ],
- "action_profiles" : [],
- "conditionals" : [
- {
- "name" : "node_39",
- "id" : 14,
+ "name" : "node_29",
+ "id" : 10,
"source_info" : {
- "filename" : "./include/control/next.p4",
- "line" : 152,
+ "filename" : "include/control/next.p4",
+ "line" : 161,
"column" : 12,
"source_fragment" : "fabric_metadata.pop_vlan_at_egress"
},
@@ -4020,40 +3625,53 @@
}
}
},
- "true_next" : "node_40",
- "false_next" : "node_44"
- },
+ "false_next" : null,
+ "true_next" : "tbl_act_6"
+ }
+ ]
+ },
+ {
+ "name" : "egress",
+ "id" : 1,
+ "source_info" : {
+ "filename" : "fabric.p4",
+ "line" : 60,
+ "column" : 8,
+ "source_fragment" : "FabricEgress"
+ },
+ "init_table" : "node_33",
+ "tables" : [
{
- "name" : "node_40",
- "id" : 15,
- "source_info" : {
- "filename" : "./include/control/next.p4",
- "line" : 153,
- "column" : 16,
- "source_fragment" : "hdr.mpls.isValid()"
+ "name" : "tbl_act_7",
+ "id" : 18,
+ "key" : [],
+ "match_type" : "exact",
+ "type" : "simple",
+ "max_size" : 1024,
+ "with_counters" : false,
+ "support_timeout" : false,
+ "direct_meters" : null,
+ "action_ids" : [36],
+ "actions" : ["act_7"],
+ "base_default_next" : null,
+ "next_tables" : {
+ "act_7" : null
},
- "expression" : {
- "type" : "expression",
- "value" : {
- "op" : "==",
- "left" : {
- "type" : "field",
- "value" : ["mpls", "$valid$"]
- },
- "right" : {
- "type" : "hexstr",
- "value" : "0x01"
- }
- }
- },
- "true_next" : "tbl_act_8",
- "false_next" : "tbl_act_9"
- },
+ "default_entry" : {
+ "action_id" : 36,
+ "action_const" : true,
+ "action_data" : [],
+ "action_entry_const" : true
+ }
+ }
+ ],
+ "action_profiles" : [],
+ "conditionals" : [
{
- "name" : "node_44",
- "id" : 16,
+ "name" : "node_33",
+ "id" : 11,
"source_info" : {
- "filename" : "./include/control/packetio.p4",
+ "filename" : "include/control/packetio.p4",
"line" : 38,
"column" : 12,
"source_fragment" : "standard_metadata.egress_port == CPU_PORT"
@@ -4073,7 +3691,7 @@
}
},
"false_next" : null,
- "true_next" : "tbl_act_11"
+ "true_next" : "tbl_act_7"
}
]
}
@@ -4084,14 +3702,36 @@
"id" : 0,
"target" : ["ipv4", "hdr_checksum"],
"type" : "generic",
- "calculation" : "calc"
+ "calculation" : "calc",
+ "if_cond" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "d2b",
+ "left" : null,
+ "right" : {
+ "type" : "field",
+ "value" : ["ipv4", "$valid$"]
+ }
+ }
+ }
},
{
"name" : "cksum_0",
"id" : 1,
"target" : ["ipv4", "hdr_checksum"],
"type" : "generic",
- "calculation" : "calc_0"
+ "calculation" : "calc_0",
+ "if_cond" : {
+ "type" : "expression",
+ "value" : {
+ "op" : "d2b",
+ "left" : null,
+ "right" : {
+ "type" : "field",
+ "value" : ["ipv4", "$valid$"]
+ }
+ }
+ }
}
],
"force_arith" : [],
diff --git a/pipelines/fabric/src/main/resources/p4c-out/bmv2/fabric.p4info b/pipelines/fabric/src/main/resources/p4c-out/bmv2/fabric.p4info
index 20c0dad..80e0880 100644
--- a/pipelines/fabric/src/main/resources/p4c-out/bmv2/fabric.p4info
+++ b/pipelines/fabric/src/main/resources/p4c-out/bmv2/fabric.p4info
@@ -34,7 +34,8 @@
action_refs {
id: 16826365
}
- const_default_action_id: 16826365
+ const_default_action_id: 16819938
+ direct_resource_ids: 302015144
size: 1024
}
tables {
@@ -65,6 +66,7 @@
id: 16838162
}
const_default_action_id: 16838162
+ direct_resource_ids: 302033694
size: 1024
}
tables {
@@ -92,6 +94,7 @@
id: 16800567
annotations: "@defaultonly()"
}
+ direct_resource_ids: 302047449
size: 1024
}
tables {
@@ -113,6 +116,7 @@
id: 16800567
annotations: "@defaultonly()"
}
+ direct_resource_ids: 302001577
size: 1024
}
tables {
@@ -134,6 +138,7 @@
id: 16800567
annotations: "@defaultonly()"
}
+ direct_resource_ids: 302038636
size: 1024
}
tables {
@@ -161,54 +166,7 @@
id: 16800567
annotations: "@defaultonly()"
}
- size: 1024
-}
-tables {
- preamble {
- id: 33608345
- name: "forwarding.unicast_v6"
- alias: "unicast_v6"
- }
- match_fields {
- id: 1
- name: "hdr.ipv6.dst_addr"
- bitwidth: 128
- match_type: LPM
- }
- action_refs {
- id: 16829931
- }
- action_refs {
- id: 16800567
- annotations: "@defaultonly()"
- }
- size: 1024
-}
-tables {
- preamble {
- id: 33592333
- name: "forwarding.multicast_v6"
- alias: "multicast_v6"
- }
- match_fields {
- id: 1
- name: "hdr.vlan_tag.vlan_id"
- bitwidth: 12
- match_type: EXACT
- }
- match_fields {
- id: 2
- name: "hdr.ipv6.dst_addr"
- bitwidth: 128
- match_type: LPM
- }
- action_refs {
- id: 16829931
- }
- action_refs {
- id: 16800567
- annotations: "@defaultonly()"
- }
+ direct_resource_ids: 302009236
size: 1024
}
tables {
@@ -302,6 +260,7 @@
id: 16819938
}
const_default_action_id: 16819938
+ direct_resource_ids: 302000008
size: 256
}
tables {
@@ -326,9 +285,13 @@
id: 16804266
}
action_refs {
+ id: 16841192
+ }
+ action_refs {
id: 16800567
annotations: "@defaultonly()"
}
+ direct_resource_ids: 301991179
size: 1024
}
tables {
@@ -357,6 +320,7 @@
annotations: "@defaultonly()"
}
implementation_id: 285225078
+ direct_resource_ids: 301993193
size: 1024
}
tables {
@@ -378,6 +342,7 @@
id: 16800567
annotations: "@defaultonly()"
}
+ direct_resource_ids: 301995093
size: 1024
}
actions {
@@ -629,6 +594,116 @@
}
size: 511
}
+direct_counters {
+ preamble {
+ id: 302015144
+ name: "filtering.ingress_port_vlan_counter"
+ alias: "ingress_port_vlan_counter"
+ }
+ spec {
+ unit: BOTH
+ }
+ direct_table_id: 33578399
+}
+direct_counters {
+ preamble {
+ id: 302033694
+ name: "filtering.fwd_classifier_counter"
+ alias: "fwd_classifier_counter"
+ }
+ spec {
+ unit: BOTH
+ }
+ direct_table_id: 33619540
+}
+direct_counters {
+ preamble {
+ id: 302047449
+ name: "forwarding.bridging_counter"
+ alias: "bridging_counter"
+ }
+ spec {
+ unit: BOTH
+ }
+ direct_table_id: 33569146
+}
+direct_counters {
+ preamble {
+ id: 302001577
+ name: "forwarding.mpls_counter"
+ alias: "mpls_counter"
+ }
+ spec {
+ unit: BOTH
+ }
+ direct_table_id: 33565386
+}
+direct_counters {
+ preamble {
+ id: 302038636
+ name: "forwarding.unicast_v4_counter"
+ alias: "unicast_v4_counter"
+ }
+ spec {
+ unit: BOTH
+ }
+ direct_table_id: 33589684
+}
+direct_counters {
+ preamble {
+ id: 302009236
+ name: "forwarding.multicast_v4_counter"
+ alias: "multicast_v4_counter"
+ }
+ spec {
+ unit: BOTH
+ }
+ direct_table_id: 33615204
+}
+direct_counters {
+ preamble {
+ id: 302000008
+ name: "forwarding.acl_counter"
+ alias: "acl_counter"
+ }
+ spec {
+ unit: BOTH
+ }
+ direct_table_id: 33587782
+}
+direct_counters {
+ preamble {
+ id: 301991179
+ name: "next.simple_counter"
+ alias: "simple_counter"
+ }
+ spec {
+ unit: BOTH
+ }
+ direct_table_id: 33615740
+}
+direct_counters {
+ preamble {
+ id: 301993193
+ name: "next.hashed_counter"
+ alias: "hashed_counter"
+ }
+ spec {
+ unit: BOTH
+ }
+ direct_table_id: 33569488
+}
+direct_counters {
+ preamble {
+ id: 301995093
+ name: "next.broadcast_counter"
+ alias: "broadcast_counter"
+ }
+ spec {
+ unit: BOTH
+ }
+ direct_table_id: 33608545
+}
controller_packet_metadata {
preamble {
id: 2868941301
diff --git a/pipelines/fabric/src/test/p4/fabric-spgw/.gitignore b/pipelines/fabric/src/test/p4/fabric-spgw/.gitignore
new file mode 100644
index 0000000..16efdec
--- /dev/null
+++ b/pipelines/fabric/src/test/p4/fabric-spgw/.gitignore
@@ -0,0 +1,3 @@
+main.json
+main.p4info
+entries.txt
diff --git a/pipelines/fabric/src/test/p4/fabric-spgw/Makefile b/pipelines/fabric/src/test/p4/fabric-spgw/Makefile
new file mode 100644
index 0000000..71dc23c
--- /dev/null
+++ b/pipelines/fabric/src/test/p4/fabric-spgw/Makefile
@@ -0,0 +1,5 @@
+all:
+ p4c-bm2-ss -o main.json \
+ -DWITH_SPGW -I ../../../main/resources/ \
+ --p4runtime-file main.p4info \
+ --p4runtime-format text ../../../main/resources/fabric.p4
diff --git a/pipelines/fabric/src/test/p4/fabric-spgw/downlink-post.pcap b/pipelines/fabric/src/test/p4/fabric-spgw/downlink-post.pcap
new file mode 100644
index 0000000..a3b76a7d
--- /dev/null
+++ b/pipelines/fabric/src/test/p4/fabric-spgw/downlink-post.pcap
Binary files differ
diff --git a/pipelines/fabric/src/test/p4/fabric-spgw/downlink-pre.pcap b/pipelines/fabric/src/test/p4/fabric-spgw/downlink-pre.pcap
new file mode 100644
index 0000000..465ab03
--- /dev/null
+++ b/pipelines/fabric/src/test/p4/fabric-spgw/downlink-pre.pcap
Binary files differ
diff --git a/pipelines/fabric/src/test/p4/fabric-spgw/entries.json b/pipelines/fabric/src/test/p4/fabric-spgw/entries.json
new file mode 100644
index 0000000..77baf91
--- /dev/null
+++ b/pipelines/fabric/src/test/p4/fabric-spgw/entries.json
@@ -0,0 +1,105 @@
+{
+ "fabric-spgw": {
+ "addr": "localhost:5051",
+ "flows": [
+ {
+ "table_name": "filtering.fwd_classifier",
+ "match_fields": {
+ "standard_metadata.ingress_port": 1,
+ "hdr.ethernet.dst_addr": "c2:42:59:2d:3a:84",
+ "fabric_metadata.original_ether_type": 2048
+ },
+ "action_name": "filtering.set_forwarding_type",
+ "action_params": {
+ "fwd_type": 2
+ }
+ },
+ {
+ "table_name": "forwarding.unicast_v4",
+ "match_fields": {
+ "hdr.ipv4.dst_addr": ["192.168.103.11", 32]
+ },
+ "action_name": "forwarding.set_next_id",
+ "action_params": {
+ "next_id": 1
+ }
+ },
+ {
+ "table_name": "next.simple",
+ "match_fields": {
+ "fabric_metadata.next_id": 1
+ },
+ "action_name": "next.l3_routing",
+ "action_params": {
+ "port_num": 2,
+ "smac": "3a:c1:e2:53:e1:50",
+ "dmac": "52:54:00:29:c9:b7"
+ }
+ },
+ {
+ "table_name": "filtering.fwd_classifier",
+ "match_fields": {
+ "standard_metadata.ingress_port": 2,
+ "hdr.ethernet.dst_addr": "3a:c1:e2:53:e1:50",
+ "fabric_metadata.original_ether_type": 2048
+ },
+ "action_name": "filtering.set_forwarding_type",
+ "action_params": {
+ "fwd_type": 2
+ }
+ },
+ {
+ "table_name": "forwarding.unicast_v4",
+ "match_fields": {
+ "hdr.ipv4.dst_addr": ["16.255.255.252", 32]
+ },
+ "action_name": "forwarding.set_next_id",
+ "action_params": {
+ "next_id": 2
+ }
+ },
+ {
+ "table_name": "next.simple",
+ "match_fields": {
+ "fabric_metadata.next_id": 2
+ },
+ "action_name": "next.l3_routing",
+ "action_params": {
+ "port_num": 1,
+ "smac": "c2:42:59:2d:3a:84",
+ "dmac": "52:54:00:05:7b:59"
+ }
+ },
+ {
+ "table_name": "spgw_ingress.ue_filter_table",
+ "match_fields": {
+ "ipv4.dst_addr": ["16.255.255.252", 32]
+ },
+ "action_name": "NoAction",
+ "action_params": {
+ }
+ },
+ {
+ "table_name": "spgw_ingress.s1u_filter_table",
+ "match_fields": {
+ "spgw_meta.s1u_sgw_addr": "192.168.102.13"
+ },
+ "action_name": "NoAction",
+ "action_params": {
+ }
+ },
+ {
+ "table_name": "spgw_ingress.dl_sess_lookup",
+ "match_fields": {
+ "ipv4.dst_addr": "16.255.255.252"
+ },
+ "action_name": "spgw_ingress.set_dl_sess_info",
+ "action_params": {
+ "teid": 1,
+ "s1u_enb_addr": "192.168.102.11",
+ "s1u_sgw_addr": "192.168.102.13"
+ }
+ }
+ ]
+ }
+}
diff --git a/pipelines/fabric/src/test/p4/fabric-spgw/uplink-post.pcap b/pipelines/fabric/src/test/p4/fabric-spgw/uplink-post.pcap
new file mode 100644
index 0000000..c02e7c6
--- /dev/null
+++ b/pipelines/fabric/src/test/p4/fabric-spgw/uplink-post.pcap
Binary files differ
diff --git a/pipelines/fabric/src/test/p4/fabric-spgw/uplink-pre.pcap b/pipelines/fabric/src/test/p4/fabric-spgw/uplink-pre.pcap
new file mode 100644
index 0000000..78064fa
--- /dev/null
+++ b/pipelines/fabric/src/test/p4/fabric-spgw/uplink-pre.pcap
Binary files differ
diff --git a/pipelines/fabric/src/test/p4/spgw/.gitignore b/pipelines/fabric/src/test/p4/spgw/.gitignore
new file mode 100644
index 0000000..43474cc
--- /dev/null
+++ b/pipelines/fabric/src/test/p4/spgw/.gitignore
@@ -0,0 +1,2 @@
+main.json
+main.p4info
diff --git a/pipelines/fabric/src/test/p4/spgw/Makefile b/pipelines/fabric/src/test/p4/spgw/Makefile
new file mode 100644
index 0000000..6b1e705
--- /dev/null
+++ b/pipelines/fabric/src/test/p4/spgw/Makefile
@@ -0,0 +1,5 @@
+all:
+ p4c-bm2-ss -o main.json \
+ -DWITH_SPGW -I ../../../main/resources/ \
+ --p4runtime-file main.p4info \
+ --p4runtime-format text main.p4
diff --git a/pipelines/fabric/src/test/p4/spgw/downlink-post.pcap b/pipelines/fabric/src/test/p4/spgw/downlink-post.pcap
new file mode 100644
index 0000000..a3b76a7d
--- /dev/null
+++ b/pipelines/fabric/src/test/p4/spgw/downlink-post.pcap
Binary files differ
diff --git a/pipelines/fabric/src/test/p4/spgw/downlink-pre.pcap b/pipelines/fabric/src/test/p4/spgw/downlink-pre.pcap
new file mode 100644
index 0000000..465ab03
--- /dev/null
+++ b/pipelines/fabric/src/test/p4/spgw/downlink-pre.pcap
Binary files differ
diff --git a/pipelines/fabric/src/test/p4/spgw/entries.json b/pipelines/fabric/src/test/p4/spgw/entries.json
new file mode 100644
index 0000000..ea3d201
--- /dev/null
+++ b/pipelines/fabric/src/test/p4/spgw/entries.json
@@ -0,0 +1,37 @@
+{
+ "spgw": {
+ "addr": "localhost:5051",
+ "flows": [
+ {
+ "table_name": "spgw_ingress.ue_filter_table",
+ "match_fields": {
+ "ipv4.dst_addr": ["16.255.255.252", 32]
+ },
+ "action_name": "NoAction",
+ "action_params": {
+ }
+ },
+ {
+ "table_name": "spgw_ingress.s1u_filter_table",
+ "match_fields": {
+ "spgw_meta.s1u_sgw_addr": "192.168.102.13"
+ },
+ "action_name": "NoAction",
+ "action_params": {
+ }
+ },
+ {
+ "table_name": "spgw_ingress.dl_sess_lookup",
+ "match_fields": {
+ "ipv4.dst_addr": "16.255.255.252"
+ },
+ "action_name": "spgw_ingress.set_dl_sess_info",
+ "action_params": {
+ "teid": 1,
+ "s1u_enb_addr": "192.168.102.11",
+ "s1u_sgw_addr": "192.168.102.13"
+ }
+ }
+ ]
+ }
+}
diff --git a/pipelines/fabric/src/test/p4/spgw/main.p4 b/pipelines/fabric/src/test/p4/spgw/main.p4
new file mode 100644
index 0000000..916412c
--- /dev/null
+++ b/pipelines/fabric/src/test/p4/spgw/main.p4
@@ -0,0 +1,148 @@
+/*
+ * 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.
+ *
+ */
+
+#define S1U_PORT 1
+#define SGI_PORT 2
+#define AS_MAC_ADDR 0x52540029c9b7
+#define S1U_MAC_ADDR 0xc242592d3a84
+#define SGI_MAC_ADDR 0x3ac1e253e150
+#define ENB_MAC_ADDR 0x525400057b59
+
+#include <core.p4>
+#include <v1model.p4>
+
+#include "include/define.p4"
+#include "include/header.p4"
+#include "include/checksum.p4"
+#include "include/parser.p4"
+#include "include/control/packetio.p4"
+
+#include "include/spgw.p4"
+
+control table0_control(inout parsed_headers_t hdr,
+ inout fabric_metadata_t fabric_metadata,
+ inout standard_metadata_t standard_metadata) {
+
+ action send_to_cpu() {
+ standard_metadata.egress_spec = CPU_PORT;
+ exit;
+ }
+
+ table table0 {
+ key = {
+ standard_metadata.ingress_port : ternary;
+ hdr.ethernet.src_addr : ternary;
+ hdr.ethernet.dst_addr : ternary;
+ hdr.ethernet.ether_type : ternary;
+ hdr.ipv4.src_addr : ternary;
+ hdr.ipv4.dst_addr : ternary;
+ hdr.ipv4.protocol : ternary;
+ fabric_metadata.l4_src_port : ternary;
+ fabric_metadata.l4_dst_port : ternary;
+ }
+ actions = {
+ send_to_cpu();
+ NoAction();
+ }
+ const default_action = NoAction();
+ }
+
+ apply {
+ table0.apply();
+ }
+}
+
+//------------------------------------------------------------------------------
+// INGRESS PIPELINE
+//------------------------------------------------------------------------------
+
+control ingress_impl(inout parsed_headers_t hdr,
+ inout fabric_metadata_t fabric_metadata,
+ inout standard_metadata_t standard_metadata) {
+
+ apply {
+
+ PacketIoIngress.apply(hdr, fabric_metadata, standard_metadata);
+
+ // Drop garbage, so we get a clean pcap.
+ if (standard_metadata.ingress_port == S1U_PORT
+ && hdr.ethernet.src_addr != ENB_MAC_ADDR) {
+ mark_to_drop();
+ exit;
+ } else if (standard_metadata.ingress_port == SGI_PORT
+ && hdr.ethernet.src_addr != AS_MAC_ADDR) {
+ mark_to_drop();
+ exit;
+ }
+
+ table0_control.apply(hdr, fabric_metadata, standard_metadata);
+
+ if (standard_metadata.egress_spec == CPU_PORT) {
+ return;
+ }
+
+ if (standard_metadata.ingress_port == S1U_PORT) {
+ if (hdr.ethernet.dst_addr != S1U_MAC_ADDR) {
+ mark_to_drop();
+ exit;
+ }
+ standard_metadata.egress_spec = SGI_PORT;
+ hdr.ethernet.src_addr = SGI_MAC_ADDR;
+ hdr.ethernet.dst_addr = AS_MAC_ADDR;
+ } else if (standard_metadata.ingress_port == SGI_PORT) {
+ if (hdr.ethernet.dst_addr != SGI_MAC_ADDR) {
+ mark_to_drop();
+ exit;
+ }
+ standard_metadata.egress_spec = S1U_PORT;
+ hdr.ethernet.src_addr = S1U_MAC_ADDR;
+ hdr.ethernet.dst_addr = ENB_MAC_ADDR;
+ }
+
+#ifdef WITH_SPGW_PCC_GATING
+ fabric_metadata.spgw.l4_src_port = fabric_metadata.l4_src_port;
+ fabric_metadata.spgw.l4_dst_port = fabric_metadata.l4_dst_port;
+#endif // WITH_SPGW_PCC_GATING
+ spgw_ingress.apply(hdr.gtpu_ipv4, hdr.gtpu_udp, hdr.gtpu,
+ hdr.ipv4, hdr.udp, fabric_metadata.spgw);
+ }
+}
+
+//------------------------------------------------------------------------------
+// EGRESS PIPELINE
+//------------------------------------------------------------------------------
+
+control egress_impl(inout parsed_headers_t hdr,
+ inout fabric_metadata_t fabric_metadata,
+ inout standard_metadata_t standard_metadata) {
+ apply {
+ PacketIoEgress.apply(hdr, fabric_metadata, standard_metadata);
+ spgw_egress.apply(hdr.gtpu_ipv4, hdr.gtpu_udp, hdr.gtpu,
+ fabric_metadata.spgw, standard_metadata);
+ }
+}
+
+//------------------------------------------------------------------------------
+// SWITCH INSTANTIATION
+//------------------------------------------------------------------------------
+
+V1Switch(FabricParser(),
+ FabricVerifyChecksum(),
+ ingress_impl(),
+ egress_impl(),
+ FabricComputeChecksum(),
+ FabricDeparser()) main;
diff --git a/pipelines/fabric/src/test/p4/spgw/uplink-post.pcap b/pipelines/fabric/src/test/p4/spgw/uplink-post.pcap
new file mode 100644
index 0000000..c02e7c6
--- /dev/null
+++ b/pipelines/fabric/src/test/p4/spgw/uplink-post.pcap
Binary files differ
diff --git a/pipelines/fabric/src/test/p4/spgw/uplink-pre.pcap b/pipelines/fabric/src/test/p4/spgw/uplink-pre.pcap
new file mode 100644
index 0000000..78064fa
--- /dev/null
+++ b/pipelines/fabric/src/test/p4/spgw/uplink-pre.pcap
Binary files differ
diff --git a/pom.xml b/pom.xml
index 6523be9..9b68af7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -240,4 +240,67 @@
</dependencies>
</dependencyManagement>
+ <properties>
+ <errorprone.version>2.2.0</errorprone.version>
+ <betachecker.version>1.0</betachecker.version>
+ </properties>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.7.0</version>
+ <configuration>
+ <source>1.8</source>
+ <target>1.8</target>
+ <compilerId>javac-with-errorprone</compilerId>
+ <forceJavacCompilerUse>true</forceJavacCompilerUse>
+ <annotationProcessorPaths>
+ <path>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava-beta-checker</artifactId>
+ <version>${betachecker.version}</version>
+ </path>
+ </annotationProcessorPaths>
+ <compilerArgs>
+ <arg>-Xep:BetaApi:WARN</arg>
+ <!-- <arg>-Xep:BetaApi:ERROR</arg> -->
+ <!-- Add following to disable error-prone -->
+ <!-- <arg>-XepDisableAllChecks</arg> -->
+ </compilerArgs>
+ </configuration>
+ <executions>
+ <execution>
+ <id>default-testCompile</id>
+ <phase>test-compile</phase>
+ <goals>
+ <goal>testCompile</goal>
+ </goals>
+ <configuration>
+ <!-- Disable Beta Checker for tests -->
+ <compilerArgs>
+ <arg>-Xep:BetaApi:OFF</arg>
+ </compilerArgs>
+ </configuration>
+ </execution>
+ </executions>
+ <dependencies>
+ <dependency>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-compiler-javac-errorprone</artifactId>
+ <version>2.8.2</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.errorprone</groupId>
+ <artifactId>error_prone_core</artifactId>
+ <!-- override plexus-compiler-javac-errorprone's dependency with the
+ latest Error Prone version -->
+ <version>${errorprone.version}</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ </plugins>
+ </build>
+
</project>
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpPathAttributes.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpPathAttributes.java
index 6d6455b..f03cdda 100644
--- a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpPathAttributes.java
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/protocol/ver4/BgpPathAttributes.java
@@ -274,7 +274,7 @@
BgpErrorType.MISSING_WELLKNOWN_ATTRIBUTE,
AsPath.ASPATH_TYPE);
}
- if (!isMpUnReach && !isMpReach && !isNextHop) {
+ if (!isMpReach && !isNextHop) {
log.debug("Mandatory attributes not Present");
Validation.validateType(BgpErrorType.UPDATE_MESSAGE_ERROR,
BgpErrorType.MISSING_WELLKNOWN_ATTRIBUTE,
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpEvpnEsi.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpEvpnEsi.java
index b6816e8..883be89 100644
--- a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpEvpnEsi.java
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpEvpnEsi.java
@@ -16,7 +16,7 @@
package org.onosproject.bgpio.types;
-import java.util.Objects;
+import java.util.Arrays;
import org.jboss.netty.buffer.ChannelBuffer;
import com.google.common.base.MoreObjects;
@@ -78,7 +78,7 @@
@Override
public int hashCode() {
- return Objects.hash(ethernetSegmentidentifier);
+ return Arrays.hashCode(ethernetSegmentidentifier);
};
@Override
@@ -89,9 +89,7 @@
if (obj instanceof BgpEvpnEsi) {
BgpEvpnEsi that = (BgpEvpnEsi) obj;
- if (this.ethernetSegmentidentifier == that.ethernetSegmentidentifier) {
- return true;
- }
+ return Arrays.equals(this.ethernetSegmentidentifier, that.ethernetSegmentidentifier);
}
return false;
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpEvpnLabel.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpEvpnLabel.java
index 60348ac..b6a2e87 100644
--- a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpEvpnLabel.java
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/BgpEvpnLabel.java
@@ -16,7 +16,7 @@
package org.onosproject.bgpio.types;
-import java.util.Objects;
+import java.util.Arrays;
import org.jboss.netty.buffer.ChannelBuffer;
import com.google.common.base.MoreObjects;
@@ -87,9 +87,7 @@
BgpEvpnLabel that = (BgpEvpnLabel) obj;
- if (this.mplsLabel == that.mplsLabel) {
- return true;
- }
+ return Arrays.equals(this.mplsLabel, that.mplsLabel);
}
return false;
@@ -97,7 +95,7 @@
@Override
public int hashCode() {
- return Objects.hashCode(mplsLabel);
+ return Arrays.hashCode(mplsLabel);
}
@Override
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpReachNlri.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpReachNlri.java
index 106c4bb..578f4fe 100644
--- a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpReachNlri.java
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpReachNlri.java
@@ -447,7 +447,7 @@
if (listIterator.hasNext()) {
tlv1 = listIterator.next();
}
- while (listIterator.hasNext()) {
+ while (tlv1 != null && listIterator.hasNext()) {
BgpValueType tlv = listIterator.next();
if (tlv.getType() != tlv1.getType()) {
isAllFlowTypesIdentical = false;
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpUnReachNlri.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpUnReachNlri.java
index e06fb0a..ac63ba7 100644
--- a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpUnReachNlri.java
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/MpUnReachNlri.java
@@ -402,7 +402,7 @@
if (listIterator.hasNext()) {
tlv1 = listIterator.next();
}
- while (listIterator.hasNext()) {
+ while (tlv1 != null && listIterator.hasNext()) {
BgpValueType tlv = listIterator.next();
if (tlv.getType() != tlv1.getType()) {
isAllFlowTypesIdentical = false;
diff --git a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/RouteTarget.java b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/RouteTarget.java
index 5a009f9..2d48788 100644
--- a/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/RouteTarget.java
+++ b/protocols/bgp/bgpio/src/main/java/org/onosproject/bgpio/types/RouteTarget.java
@@ -17,7 +17,10 @@
package org.onosproject.bgpio.types;
import com.google.common.base.MoreObjects;
-import com.google.common.base.Objects;
+
+import java.util.Arrays;
+import java.util.Objects;
+
import org.jboss.netty.buffer.ChannelBuffer;
/**
@@ -107,7 +110,7 @@
if (obj instanceof RouteTarget) {
RouteTarget that = (RouteTarget) obj;
if (this.type == that.type
- && this.routeTarget == that.routeTarget) {
+ && Arrays.equals(this.routeTarget, that.routeTarget)) {
return true;
}
}
@@ -116,7 +119,7 @@
@Override
public int hashCode() {
- return Objects.hashCode(routeTarget);
+ return Objects.hash(type, Arrays.hashCode(routeTarget));
}
@Override
diff --git a/protocols/gnmi/stub/src/main/proto/COMMIT_ID b/protocols/gnmi/stub/src/main/proto/COMMIT_ID
index 0ac43f2..acf773d 100644
--- a/protocols/gnmi/stub/src/main/proto/COMMIT_ID
+++ b/protocols/gnmi/stub/src/main/proto/COMMIT_ID
@@ -1,2 +1,2 @@
https://github.com/openconfig/gnmi/blob/master/proto/gnmi/gnmi.proto
-8a14ac0e9ed67e08988f9913243d89f398454824
+9c8d9e965b3e854107ea02c12ab11b70717456f2
diff --git a/protocols/gnmi/stub/src/main/proto/gnmi.proto b/protocols/gnmi/stub/src/main/proto/gnmi.proto
index d497dc0..1f3bb7c 100644
--- a/protocols/gnmi/stub/src/main/proto/gnmi.proto
+++ b/protocols/gnmi/stub/src/main/proto/gnmi.proto
@@ -25,7 +25,7 @@
// tree supported by a device ("target").
//
// This document references the gNMI Specification which can be found at
-// http://github.com/openconfig/reference/blob/master/rpc/gnmi/gnmi.md
+// http://github.com/openconfig/reference/blob/master/rpc/gnmi
package gnmi;
// Define a protobuf FileOption that defines the gNMI service version.
@@ -36,7 +36,7 @@
// gNMI_service is the current version of the gNMI service, returned through
// the Capabilities RPC.
-option (gnmi_service) = "0.4.0";
+option (gnmi_service) = "0.5.0";
service gNMI {
// Capabilities allows the client to retrieve the set of capabilities that
@@ -90,6 +90,7 @@
Path path = 1; // The path (key) for the update.
Value value = 2 [deprecated=true]; // The value (value) for the update.
TypedValue val = 3; // The explicitly typed update value.
+ uint32 duplicates = 4; // Number of coalesced duplicates.
}
// TypedValue is used to encode a value being sent between the client and
@@ -126,6 +127,8 @@
repeated string element = 1 [deprecated=true];
string origin = 2; // Label to disambiguate path.
repeated PathElem elem = 3; // Elements of the path.
+ string target = 4; // The name of the target
+ // (Sec. 2.2.2.1)
}
// PathElem encodes an element of a gNMI path, along ith any attributes (keys)
@@ -173,7 +176,7 @@
// is expressed as a set of digits with the precision specifying the
// number of digits following the decimal point in the digit set.
message Decimal64 {
- uint64 digits = 1; // Set of digits.
+ int64 digits = 1; // Set of digits.
uint32 precision = 2; // Number of digits following the decimal point.
}
@@ -250,6 +253,12 @@
// The encoding that the target should use within the Notifications generated
// corresponding to the SubscriptionList.
Encoding encoding = 8;
+ // An optional field to specify that only updates to current state should be
+ // sent to a client. If set, the initial state is not sent to the client but
+ // rather only the sync message followed by any subsequent updates to the
+ // current state. For ONCE and POLL modes, this causes the server to send only
+ // the sync message (Sec. 3.5.2.3).
+ bool updates_only = 9;
}
// Subscription is a single request within a SubscriptionList. The path
diff --git a/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/IsisChannelHandler.java b/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/IsisChannelHandler.java
index b25c2ef..da0c946 100644
--- a/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/IsisChannelHandler.java
+++ b/protocols/isis/ctl/src/main/java/org/onosproject/isis/controller/impl/IsisChannelHandler.java
@@ -217,12 +217,9 @@
if (message instanceof List) {
List<IsisMessage> isisMessageList = (List<IsisMessage>) message;
log.debug("IsisChannelHandler::List of IsisMessages Size {}", isisMessageList.size());
- if (isisMessageList != null) {
- for (IsisMessage isisMessage : isisMessageList) {
- processIsisMessage(isisMessage, ctx);
- }
- } else {
- log.debug("IsisChannelHandler::IsisMessages Null List...!!");
+
+ for (IsisMessage isisMessage : isisMessageList) {
+ processIsisMessage(isisMessage, ctx);
}
}
if (message instanceof IsisMessage) {
diff --git a/protocols/isis/isisio/src/main/java/org/onosproject/isis/io/util/ChecksumCalculator.java b/protocols/isis/isisio/src/main/java/org/onosproject/isis/io/util/ChecksumCalculator.java
index c4dbd90..0671eed 100644
--- a/protocols/isis/isisio/src/main/java/org/onosproject/isis/io/util/ChecksumCalculator.java
+++ b/protocols/isis/isisio/src/main/java/org/onosproject/isis/io/util/ChecksumCalculator.java
@@ -57,14 +57,12 @@
tempLsaByte[lspChecksumPos1] = 0;
tempLsaByte[lspChecksumPos2] = 0;
byte[] byteCheckSum = {0, 0};
- if (lspBytes != null) {
- for (int i = 12; i < tempLsaByte.length; i++) {
- checksumOut[0] = checksumOut[0] + ((int) tempLsaByte[i] & 0xFF);
- checksumOut[1] = checksumOut[1] + checksumOut[0];
- }
- checksumOut[0] = checksumOut[0] % 255;
- checksumOut[1] = checksumOut[1] % 255;
+ for (int i = 12; i < tempLsaByte.length; i++) {
+ checksumOut[0] = checksumOut[0] + ((int) tempLsaByte[i] & 0xFF);
+ checksumOut[1] = checksumOut[1] + checksumOut[0];
}
+ checksumOut[0] = checksumOut[0] % 255;
+ checksumOut[1] = checksumOut[1] % 255;
int byte1 = (int) ((tempLsaByte.length - lspChecksumPos1 - 1) * checksumOut[0] - checksumOut[1]) % 255;
if (byte1 <= 0) {
byte1 += 255;
diff --git a/protocols/lisp/msg/src/test/java/org/onosproject/lisp/msg/protocols/DefaultLispMapReplyTest.java b/protocols/lisp/msg/src/test/java/org/onosproject/lisp/msg/protocols/DefaultLispMapReplyTest.java
index e984ced..8bd7b2e 100644
--- a/protocols/lisp/msg/src/test/java/org/onosproject/lisp/msg/protocols/DefaultLispMapReplyTest.java
+++ b/protocols/lisp/msg/src/test/java/org/onosproject/lisp/msg/protocols/DefaultLispMapReplyTest.java
@@ -27,6 +27,8 @@
import org.onosproject.lisp.msg.exceptions.LispWriterException;
import org.onosproject.lisp.msg.protocols.DefaultLispMapReply.ReplyReader;
import org.onosproject.lisp.msg.protocols.DefaultLispMapReply.ReplyWriter;
+import org.onosproject.lisp.msg.protocols.LispMapRecord.MapRecordBuilder;
+import org.onosproject.lisp.msg.protocols.LispMapReply.ReplyBuilder;
import org.onosproject.lisp.msg.types.LispIpv4Address;
import java.util.List;
@@ -34,9 +36,7 @@
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
import static org.onosproject.lisp.msg.protocols.DefaultLispMapRecord.DefaultMapRecordBuilder;
-import static org.onosproject.lisp.msg.protocols.DefaultLispMapRecord.MapRecordBuilder;
import static org.onosproject.lisp.msg.protocols.DefaultLispMapReply.DefaultReplyBuilder;
-import static org.onosproject.lisp.msg.protocols.DefaultLispMapReply.ReplyBuilder;
/**
* Unit tests for DefaultLispMapReply class.
diff --git a/protocols/netconf/api/src/main/java/org/onosproject/netconf/NetconfDeviceInfo.java b/protocols/netconf/api/src/main/java/org/onosproject/netconf/NetconfDeviceInfo.java
index d05acc3..3ebb982 100644
--- a/protocols/netconf/api/src/main/java/org/onosproject/netconf/NetconfDeviceInfo.java
+++ b/protocols/netconf/api/src/main/java/org/onosproject/netconf/NetconfDeviceInfo.java
@@ -67,7 +67,7 @@
public NetconfDeviceInfo(String name, String password, IpAddress ipAddress,
int port) {
checkArgument(!name.equals(""), "Empty device username");
- checkNotNull(port > 0, "Negative port");
+ checkArgument(port > 0, "Negative port");
checkNotNull(ipAddress, "Null ip address");
this.name = name;
this.password = password;
@@ -96,7 +96,7 @@
public NetconfDeviceInfo(String name, String password, IpAddress ipAddress,
int port, String keyString) {
checkArgument(!name.equals(""), "Empty device name");
- checkNotNull(port > 0, "Negative port");
+ checkArgument(port > 0, "Negative port");
checkNotNull(ipAddress, "Null ip address");
this.name = name;
this.password = password;
@@ -116,7 +116,7 @@
*/
public NetconfDeviceInfo(NetconfDeviceConfig netconfConfig) {
checkArgument(!netconfConfig.username().isEmpty(), "Empty device name");
- checkNotNull(netconfConfig.port() > 0, "Negative port");
+ checkArgument(netconfConfig.port() > 0, "Negative port");
checkNotNull(netconfConfig.ip(), "Null ip address");
this.name = netconfConfig.username();
diff --git a/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/DefaultOpenFlowPacketContext.java b/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/DefaultOpenFlowPacketContext.java
index 9bd2146..ac9ed82 100644
--- a/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/DefaultOpenFlowPacketContext.java
+++ b/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/DefaultOpenFlowPacketContext.java
@@ -105,13 +105,17 @@
checkPermission(PACKET_READ);
try {
- return Ethernet.deserializer().deserialize(pktin.getData(), 0, pktin.getData().length);
+ return Ethernet.deserializer().deserialize(
+ pktin.getData(), 0, pktin.getData().length);
} catch (BufferUnderflowException | NullPointerException |
DeserializationException e) {
Logger log = LoggerFactory.getLogger(getClass());
- log.error("packet deserialization problem : {}", e.getMessage());
- return null;
+ log.error("Packet deserialization problem", e);
+ } catch (Exception e) {
+ Logger log = LoggerFactory.getLogger(getClass());
+ log.error("Unexpected packet deserialization problem", e);
}
+ return null;
}
@Override
diff --git a/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowOpticalSwitch.java b/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowOpticalSwitch.java
index eac7dc2..d3b11bb 100644
--- a/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowOpticalSwitch.java
+++ b/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/OpenFlowOpticalSwitch.java
@@ -31,7 +31,7 @@
public interface OpenFlowOpticalSwitch extends OpenFlowSwitch, WithTypedPorts {
// OpenFlowOpticalSwitch only returns Ethernet ports.
- // This is a limitation due to issue described in ONOS-3796.
+ // This is a limitation due to issue described in ONOS-3736.
// This method should return all port type once the limitation is fixed.
/**
* Returns a list of standard (Ethernet) ports.
@@ -40,7 +40,7 @@
*/
@Beta
@Override
- abstract List<OFPortDesc> getPorts();
+ List<OFPortDesc> getPorts();
/**
* Returns updated PortDescriptions built from experimenter message
diff --git a/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/ThirdPartyMessage.java b/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/ThirdPartyMessage.java
index b00da85..dbb1d53 100644
--- a/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/ThirdPartyMessage.java
+++ b/protocols/openflow/api/src/main/java/org/onosproject/openflow/controller/ThirdPartyMessage.java
@@ -75,7 +75,7 @@
@Override
public int hashCodeIgnoreXid() {
- return payLoad.hashCode();
+ return Arrays.hashCode(payLoad);
}
@Override
diff --git a/protocols/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OFChannelHandler.java b/protocols/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OFChannelHandler.java
index 769fa2d..414bd89 100644
--- a/protocols/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OFChannelHandler.java
+++ b/protocols/openflow/ctl/src/main/java/org/onosproject/openflow/controller/impl/OFChannelHandler.java
@@ -380,8 +380,9 @@
h.portDescReplies.add((OFPortDescStatsReply) m);
}
//h.portDescReply = (OFPortDescStatsReply) m; // temp store
- log.info("Received port desc reply for switch at {}",
- h.getSwitchInfoString());
+ log.debug("Received port desc reply for switch at {}: {}",
+ h.getSwitchInfoString(),
+ ((OFPortDescStatsReply) m).getEntries());
try {
h.sendHandshakeSetConfig();
} catch (IOException e) {
@@ -780,6 +781,9 @@
void processOFStatisticsReply(OFChannelHandler h,
OFStatsReply m) {
if (m.getStatsType().equals(OFStatsType.PORT_DESC)) {
+ log.debug("Received port desc message from {}: {}",
+ h.sw.getDpid(),
+ ((OFPortDescStatsReply) m).getEntries());
h.sw.setPortDescReply((OFPortDescStatsReply) m);
}
h.dispatchMessage(m);
@@ -1443,7 +1447,7 @@
if (dispatcherHandle.isDone()) {
// dispatcher terminated for some reason, restart
- dispatcherHandle = dispatcher.submit(() -> {
+ dispatcherHandle = dispatcher.submit((Runnable) () -> {
try {
List<OFMessage> msgs = new ArrayList<>();
for (;;) {
diff --git a/protocols/ospf/ctl/src/main/java/org/onosproject/ospf/controller/area/OspfInterfaceImpl.java b/protocols/ospf/ctl/src/main/java/org/onosproject/ospf/controller/area/OspfInterfaceImpl.java
index 79b613a..7c1626b 100644
--- a/protocols/ospf/ctl/src/main/java/org/onosproject/ospf/controller/area/OspfInterfaceImpl.java
+++ b/protocols/ospf/ctl/src/main/java/org/onosproject/ospf/controller/area/OspfInterfaceImpl.java
@@ -138,6 +138,7 @@
*
* @return OSPF area instance
*/
+ @Override
public OspfArea ospfArea() {
return ospfArea;
}
@@ -156,6 +157,7 @@
*
* @param ospfArea OSPF area instance
*/
+ @Override
public void setOspfArea(OspfArea ospfArea) {
this.ospfArea = ospfArea;
}
@@ -188,6 +190,7 @@
*
* @return network mask
*/
+ @Override
public Ip4Address ipNetworkMask() {
return ipNetworkMask;
}
@@ -207,6 +210,7 @@
*
* @param ospfNbr ospfNbr instance
*/
+ @Override
public void addNeighbouringRouter(OspfNbr ospfNbr) {
listOfNeighbors.put(ospfNbr.neighborId().toString(), ospfNbr);
}
@@ -217,6 +221,7 @@
* @param neighborId neighbors id
* @return ospfNbr neighbor instance
*/
+ @Override
public OspfNbr neighbouringRouter(String neighborId) {
return listOfNeighbors.get(neighborId);
}
@@ -224,6 +229,7 @@
/**
* Removes all the neighbors.
*/
+ @Override
public void removeNeighbors() {
Set<String> neighbors = listOfNeighbors.keySet();
for (String neighborId : neighbors) {
@@ -245,7 +251,7 @@
ospfNeighbor.stopRxMtDdTimer();
ospfNeighbor.stopRxMtLsrTimer();
- listOfNeighbors.remove(ospfNeighbor.neighborId());
+ listOfNeighbors.remove(ospfNeighbor.neighborId().toString());
}
@@ -274,6 +280,7 @@
*
* @param lsaKey key used to store LSA in map
*/
+ @Override
public void removeLsaFromNeighborMap(String lsaKey) {
listOfNeighborMap.remove(lsaKey);
}
@@ -284,6 +291,7 @@
* @param neighborId neighbors id
* @return true if neighbor in list else false
*/
+ @Override
public boolean isNeighborInList(String neighborId) {
return listOfNeighbors.containsKey(neighborId);
}
@@ -293,6 +301,7 @@
*
* @return listOfNeighbors as key value pair
*/
+ @Override
public Map<String, OspfNbr> listOfNeighbors() {
return listOfNeighbors;
}
@@ -311,6 +320,7 @@
*
* @return interface index
*/
+ @Override
public int interfaceIndex() {
return interfaceIndex;
}
@@ -320,6 +330,7 @@
*
* @param interfaceIndex interface index
*/
+ @Override
public void setInterfaceIndex(int interfaceIndex) {
this.interfaceIndex = interfaceIndex;
}
@@ -329,6 +340,7 @@
*
* @return IP address
*/
+ @Override
public Ip4Address ipAddress() {
return ipAddress;
}
@@ -338,6 +350,7 @@
*
* @param ipAddress interface IP address
*/
+ @Override
public void setIpAddress(Ip4Address ipAddress) {
this.ipAddress = ipAddress;
}
@@ -347,6 +360,7 @@
*
* @return routerPriority value
*/
+ @Override
public int routerPriority() {
return routerPriority;
}
@@ -356,6 +370,7 @@
*
* @param routerPriority value
*/
+ @Override
public void setRouterPriority(int routerPriority) {
this.routerPriority = routerPriority;
}
@@ -365,6 +380,7 @@
*
* @return hello interval time
*/
+ @Override
public int helloIntervalTime() {
return helloIntervalTime;
}
@@ -374,6 +390,7 @@
*
* @param helloIntervalTime an integer interval time
*/
+ @Override
public void setHelloIntervalTime(int helloIntervalTime) {
this.helloIntervalTime = helloIntervalTime;
}
@@ -383,6 +400,7 @@
*
* @return router dead interval time
*/
+ @Override
public int routerDeadIntervalTime() {
return routerDeadIntervalTime;
}
@@ -392,6 +410,7 @@
*
* @param routerDeadIntervalTime router dead interval time
*/
+ @Override
public void setRouterDeadIntervalTime(int routerDeadIntervalTime) {
this.routerDeadIntervalTime = routerDeadIntervalTime;
}
@@ -401,6 +420,7 @@
*
* @return interfaceType an integer represents interface type
*/
+ @Override
public int interfaceType() {
return interfaceType;
}
@@ -410,6 +430,7 @@
*
* @param interfaceType interface type
*/
+ @Override
public void setInterfaceType(int interfaceType) {
this.interfaceType = interfaceType;
}
@@ -419,6 +440,7 @@
*
* @return mtu an integer represents max transfer unit
*/
+ @Override
public int mtu() {
return mtu;
}
@@ -428,6 +450,7 @@
*
* @param mtu max transfer unit
*/
+ @Override
public void setMtu(int mtu) {
this.mtu = mtu;
}
@@ -437,6 +460,7 @@
*
* @return retransmit interval
*/
+ @Override
public int reTransmitInterval() {
return reTransmitInterval;
}
@@ -446,6 +470,7 @@
*
* @param reTransmitInterval retransmit interval
*/
+ @Override
public void setReTransmitInterval(int reTransmitInterval) {
this.reTransmitInterval = reTransmitInterval;
}
@@ -455,6 +480,7 @@
*
* @return dr designated routers IP address
*/
+ @Override
public Ip4Address dr() {
return dr;
}
@@ -464,6 +490,7 @@
*
* @param dr designated routers IP address
*/
+ @Override
public void setDr(Ip4Address dr) {
this.dr = dr;
}
@@ -473,6 +500,7 @@
*
* @return bdr backup designated routers IP address
*/
+ @Override
public Ip4Address bdr() {
return bdr;
}
@@ -482,6 +510,7 @@
*
* @param bdr backup designated routers IP address
*/
+ @Override
public void setBdr(Ip4Address bdr) {
this.bdr = bdr;
}
@@ -491,6 +520,7 @@
*
* @throws Exception might throws exception
*/
+ @Override
public void interfaceUp() throws Exception {
log.debug("OSPFInterfaceChannelHandler::interfaceUp...!!!");
if (interfaceType() == OspfInterfaceType.POINT_TO_POINT.value()) {
@@ -578,6 +608,7 @@
* All interface variables are reset, and interface timers disabled.
* Also all neighbor connections associated with the interface are destroyed.
*/
+ @Override
public void interfaceDown() {
log.debug("OSPFInterfaceChannelHandler::interfaceDown ");
stopHelloTimer();
@@ -594,6 +625,7 @@
* @param ctx channel handler context instance.
* @throws Exception might throws exception
*/
+ @Override
public void processOspfMessage(OspfMessage ospfMessage, ChannelHandlerContext ctx) throws Exception {
log.debug("OspfChannelHandler::processOspfMessage...!!!");
@@ -1078,7 +1110,7 @@
OspfUtil.LSA_HEADER_LENGTH; // subtract a normal IP header.
int noLsa = 0;
while (listItr.hasNext()) {
- LsRequestPacket lsRequest = (LsRequestPacket) listItr.next();
+ LsRequestPacket lsRequest = listItr.next();
// to verify length of the LSA
LsaWrapper wrapper = ospfArea.getLsa(lsRequest.lsType(), lsRequest.linkStateId(),
lsRequest.ownRouterId());
@@ -1168,7 +1200,7 @@
LsaHeader lsRequest = (LsaHeader) itr.next();
OspfLsa ospfLsa =
- (OspfLsa) nbr.getPendingReTxList().get(((OspfAreaImpl) ospfArea).getLsaKey(lsRequest));
+ nbr.getPendingReTxList().get(((OspfAreaImpl) ospfArea).getLsaKey(lsRequest));
if (ospfLsa != null) {
String isSame = ((OspfLsdbImpl) ospfArea.database()).isNewerOrSameLsa(
lsRequest, (LsaHeader) ospfLsa);
@@ -1206,6 +1238,7 @@
/**
* Starts the hello timer which sends hello packet every configured seconds.
*/
+ @Override
public void startHelloTimer() {
log.debug("OSPFInterfaceChannelHandler::startHelloTimer");
exServiceHello = Executors.newSingleThreadScheduledExecutor();
@@ -1217,6 +1250,7 @@
/**
* Stops the hello timer.
*/
+ @Override
public void stopHelloTimer() {
log.debug("OSPFInterfaceChannelHandler::stopHelloTimer ");
exServiceHello.shutdown();
@@ -1244,6 +1278,7 @@
/**
* Starts the timer which waits for configured seconds and sends Delayed Ack Packet.
*/
+ @Override
public void startDelayedAckTimer() {
if (!isDelayedAckTimerScheduled) {
log.debug("Started DelayedAckTimer...!!!");
@@ -1259,6 +1294,7 @@
/**
* Stops the delayed acknowledge timer.
*/
+ @Override
public void stopDelayedAckTimer() {
if (isDelayedAckTimerScheduled) {
log.debug("Stopped DelayedAckTimer...!!!");
diff --git a/protocols/ospf/ctl/src/main/java/org/onosproject/ospf/controller/impl/OspfInterfaceChannelHandler.java b/protocols/ospf/ctl/src/main/java/org/onosproject/ospf/controller/impl/OspfInterfaceChannelHandler.java
index bba5c77..1a47a0c 100644
--- a/protocols/ospf/ctl/src/main/java/org/onosproject/ospf/controller/impl/OspfInterfaceChannelHandler.java
+++ b/protocols/ospf/ctl/src/main/java/org/onosproject/ospf/controller/impl/OspfInterfaceChannelHandler.java
@@ -220,12 +220,9 @@
if (message instanceof List) {
List<OspfMessage> ospfMessageList = (List<OspfMessage>) message;
log.debug("OspfChannelHandler::List of IsisMessages Size {}", ospfMessageList.size());
- if (ospfMessageList != null) {
- for (OspfMessage ospfMessage : ospfMessageList) {
- processOspfMessage(ospfMessage, ctx);
- }
- } else {
- log.debug("OspfChannelHandler::OspfMessages Null List...!!");
+
+ for (OspfMessage ospfMessage : ospfMessageList) {
+ processOspfMessage(ospfMessage, ctx);
}
}
if (message instanceof OspfMessage) {
diff --git a/protocols/ospf/ctl/src/main/java/org/onosproject/ospf/controller/impl/OspfNbrImpl.java b/protocols/ospf/ctl/src/main/java/org/onosproject/ospf/controller/impl/OspfNbrImpl.java
index 68ff4fc..ff3f75b 100644
--- a/protocols/ospf/ctl/src/main/java/org/onosproject/ospf/controller/impl/OspfNbrImpl.java
+++ b/protocols/ospf/ctl/src/main/java/org/onosproject/ospf/controller/impl/OspfNbrImpl.java
@@ -218,6 +218,7 @@
*
* @return the IP address of this neighbor
*/
+ @Override
public Ip4Address neighborIpAddr() {
return neighborIpAddr;
}
@@ -227,6 +228,7 @@
*
* @return true if the neighbor is opaque enabled else false.
*/
+ @Override
public boolean isOpaqueCapable() {
return isOpaqueCapable;
}
@@ -236,6 +238,7 @@
*
* @param isOpaqueCapable true if the neighbor is opaque enabledelse false
*/
+ @Override
public void setIsOpaqueCapable(boolean isOpaqueCapable) {
this.isOpaqueCapable = isOpaqueCapable;
}
@@ -245,6 +248,7 @@
*
* @param routerDeadInterval router dead interval
*/
+ @Override
public void setRouterDeadInterval(int routerDeadInterval) {
this.routerDeadInterval = routerDeadInterval;
}
@@ -386,7 +390,7 @@
state = OspfNeighborState.EXCHANGE;
boolean excludeMaxAgeLsa = true;
//list of contents of area wise LSA
- ddSummaryList = (CopyOnWriteArrayList) ospfArea.getLsaHeaders(excludeMaxAgeLsa, isOpaqueCapable);
+ ddSummaryList = ospfArea.getLsaHeaders(excludeMaxAgeLsa, isOpaqueCapable);
if (neighborIsMaster) {
processLsas(payload);
@@ -558,6 +562,7 @@
* @param ch netty channel instance
* @throws Exception on error
*/
+ @Override
public void badLSReq(Channel ch) throws Exception {
log.debug("OSPFNbr::badLSReq...!!!");
@@ -837,6 +842,7 @@
*
* @param ch netty channel instance
*/
+ @Override
public void adjOk(Channel ch) {
log.debug("OSPFNbr::adjOk...!!!");
if (ospfInterface.interfaceType() != OspfInterfaceType.POINT_TO_POINT.value()) {
@@ -1176,7 +1182,7 @@
}
}
// RFC 2328 Section 13 (6)
- if (lsReqList.contains(key)) {
+ if (lsReqList.containsValue(key)) {
badLSReq(ch);
}
if (status.equals("same")) { //13 (7)
@@ -1397,6 +1403,7 @@
/**
* Starts the inactivity timer.
*/
+ @Override
public void startInactivityTimeCheck() {
if (!inActivityTimerScheduled) {
log.debug("OSPFNbr::startInactivityTimeCheck");
@@ -1411,6 +1418,7 @@
/**
* Stops the inactivity timer.
*/
+ @Override
public void stopInactivityTimeCheck() {
if (inActivityTimerScheduled) {
log.debug("OSPFNbr::stopInactivityTimeCheck ");
@@ -1440,6 +1448,7 @@
/**
* Stops the flooding timer.
*/
+ @Override
public void stopFloodingTimer() {
if (floodingTimerScheduled) {
log.debug("OSPFNbr::stopFloodingTimer ");
@@ -1467,6 +1476,7 @@
/**
* Stops the Dd Retransmission executor task.
*/
+ @Override
public void stopRxMtDdTimer() {
if (rxmtDdPacketTimerScheduled) {
exServiceRxmtDDPacket.shutdown();
@@ -1494,6 +1504,7 @@
/**
* Stops Ls request retransmission executor task.
*/
+ @Override
public void stopRxMtLsrTimer() {
if (rxmtLsrTimerScheduled) {
exServiceRxmtLsr.shutdown();
@@ -1524,6 +1535,7 @@
*
* @return neighbor id
*/
+ @Override
public Ip4Address neighborId() {
return neighborId;
}
@@ -1533,6 +1545,7 @@
*
* @param neighborId neighbor id
*/
+ @Override
public void setNeighborId(Ip4Address neighborId) {
this.neighborId = neighborId;
}
@@ -1542,6 +1555,7 @@
*
* @return neighbor DR address
*/
+ @Override
public Ip4Address neighborDr() {
return neighborDr;
}
@@ -1551,6 +1565,7 @@
*
* @param neighborDr neighbor DR address
*/
+ @Override
public void setNeighborDr(Ip4Address neighborDr) {
this.neighborDr = neighborDr;
}
@@ -1560,6 +1575,7 @@
*
* @return neighbor BDR address
*/
+ @Override
public Ip4Address neighborBdr() {
return neighborBdr;
}
@@ -1569,6 +1585,7 @@
*
* @param neighborBdr neighbor BDR address
*/
+ @Override
public void setNeighborBdr(Ip4Address neighborBdr) {
this.neighborBdr = neighborBdr;
}
@@ -1578,6 +1595,7 @@
*
* @return router priority
*/
+ @Override
public int routerPriority() {
return routerPriority;
}
@@ -1587,6 +1605,7 @@
*
* @param routerPriority router priority
*/
+ @Override
public void setRouterPriority(int routerPriority) {
this.routerPriority = routerPriority;
}
@@ -1596,6 +1615,7 @@
*
* @return options value
*/
+ @Override
public int options() {
return options;
}
@@ -1605,6 +1625,7 @@
*
* @param options options value
*/
+ @Override
public void setOptions(int options) {
this.options = options;
}
@@ -1614,6 +1635,7 @@
*
* @return DD sequence number
*/
+ @Override
public long ddSeqNum() {
return ddSeqNum;
}
@@ -1623,6 +1645,7 @@
*
* @param ddSeqNum DD sequence number
*/
+ @Override
public void setDdSeqNum(long ddSeqNum) {
this.ddSeqNum = ddSeqNum;
}
@@ -1632,6 +1655,7 @@
*
* @return true if neighbor is master else false
*/
+ @Override
public int isMaster() {
return isMaster;
}
@@ -1677,6 +1701,7 @@
*
* @return neighbors state
*/
+ @Override
public OspfNeighborState getState() {
return state;
}
@@ -1695,6 +1720,7 @@
*
* @param isMaster neighbor is master or not
*/
+ @Override
public void setIsMaster(int isMaster) {
this.isMaster = isMaster;
}
@@ -1704,6 +1730,7 @@
*
* @return ls request list
*/
+ @Override
public Hashtable getLsReqList() {
return lsReqList;
}
@@ -1713,6 +1740,7 @@
*
* @return reTxList instance
*/
+ @Override
public Map getReTxList() {
return reTxList;
}
@@ -1722,6 +1750,7 @@
*
* @return pendingReTxList instance
*/
+ @Override
public Map<String, OspfLsa> getPendingReTxList() {
return pendingReTxList;
}
diff --git a/protocols/ospf/ctl/src/main/java/org/onosproject/ospf/controller/lsdb/LsdbAgeImpl.java b/protocols/ospf/ctl/src/main/java/org/onosproject/ospf/controller/lsdb/LsdbAgeImpl.java
index 636e75c..794d623 100644
--- a/protocols/ospf/ctl/src/main/java/org/onosproject/ospf/controller/lsdb/LsdbAgeImpl.java
+++ b/protocols/ospf/ctl/src/main/java/org/onosproject/ospf/controller/lsdb/LsdbAgeImpl.java
@@ -80,7 +80,7 @@
return Objects.equal(ageBins, that.ageBins) &&
Objects.equal(ageCounter, that.ageCounter) &&
Objects.equal(ageCounterRollOver, that.ageCounterRollOver) &&
- Objects.equal(lsaQueue, lsaQueue);
+ Objects.equal(lsaQueue, that.lsaQueue);
}
@Override
@@ -94,6 +94,7 @@
* @param binKey key to store in bin
* @param lsaBin LSA bin instance
*/
+ @Override
public void addLsaBin(Integer binKey, LsaBin lsaBin) {
if (!ageBins.containsKey(binKey)) {
ageBins.put(binKey, lsaBin);
@@ -106,6 +107,7 @@
* @param binKey key
* @return bin instance
*/
+ @Override
public LsaBin getLsaBin(Integer binKey) {
return ageBins.get(binKey);
@@ -117,6 +119,7 @@
* @param key key
* @param wrapper wrapper instance
*/
+ @Override
public void addLsaToMaxAgeBin(String key, LsaWrapper wrapper) {
maxAgeBin.addOspfLsa(key, wrapper);
}
@@ -126,6 +129,7 @@
*
* @param lsaWrapper wrapper instance
*/
+ @Override
public void removeLsaFromBin(LsaWrapper lsaWrapper) {
if (ageBins.containsKey(lsaWrapper.binNumber())) {
LsaBin lsaBin = ageBins.get(lsaWrapper.binNumber());
@@ -137,6 +141,7 @@
/**
* Starts the aging timer and queue consumer.
*/
+ @Override
public void startDbAging() {
startDbAgeTimer();
queueConsumer = new LsaQueueConsumer(lsaQueue, channel, ospfArea);
@@ -147,6 +152,7 @@
/**
* Gets called every 1 second as part of the timer.
*/
+ @Override
public void ageLsaAndFlood() {
//every 5 mins checksum validation
checkAges();
@@ -167,6 +173,7 @@
/**
* If the LSA have completed the MaxAge - they are moved called stop aging and flooded.
*/
+ @Override
public void maxAgeLsa() {
if (ageCounter == 0) {
return;
@@ -178,7 +185,7 @@
}
Map lsaBinMap = lsaBin.listOfLsa();
for (Object key : lsaBinMap.keySet()) {
- LsaWrapper lsa = (LsaWrapper) lsaBinMap.get((String) key);
+ LsaWrapper lsa = (LsaWrapper) lsaBinMap.get(key);
if (lsa.currentAge() == OspfParameters.MAXAGE) {
lsa.setLsaProcessing(OspfParameters.MAXAGELSA);
log.debug("Lsa picked for maxage flooding. Age Counter: {}, AgeCounterRollover: {}, " +
@@ -198,7 +205,7 @@
//Get from maxAgeBin
Map lsaMaxAgeBinMap = maxAgeBin.listOfLsa();
for (Object key : lsaMaxAgeBinMap.keySet()) {
- LsaWrapper lsa = (LsaWrapper) lsaMaxAgeBinMap.get((String) key);
+ LsaWrapper lsa = (LsaWrapper) lsaMaxAgeBinMap.get(key);
lsa.setLsaProcessing(OspfParameters.MAXAGELSA);
log.debug("Lsa picked for maxage flooding. Age Counter: {}, LSA Type: {}, LSA Key: {}",
ageCounter, lsa.lsaType(), key);
@@ -217,6 +224,7 @@
/*
* If the LSA is in age bin of 1800 - it's pushed into refresh list.
*/
+ @Override
public void refreshLsa() {
int binNumber;
if (ageCounter < OspfParameters.LSREFRESHTIME) {
@@ -230,7 +238,7 @@
}
Map lsaBinMap = lsaBin.listOfLsa();
for (Object key : lsaBinMap.keySet()) {
- LsaWrapper lsa = (LsaWrapper) lsaBinMap.get((String) key);
+ LsaWrapper lsa = (LsaWrapper) lsaBinMap.get(key);
try {
if (lsa.isSelfOriginated()) {
log.debug("Lsa picked for refreshLsa. binNumber: {}, LSA Type: {}, LSA Key: {}",
@@ -259,7 +267,7 @@
}
Map lsaBinMap = lsaBin.listOfLsa();
for (Object key : lsaBinMap.keySet()) {
- LsaWrapper lsa = (LsaWrapper) lsaBinMap.get((String) key);
+ LsaWrapper lsa = (LsaWrapper) lsaBinMap.get(key);
lsa.setLsaProcessing(OspfParameters.VERIFYCHECKSUM);
try {
lsaQueue.put(lsa);
@@ -319,6 +327,7 @@
*
* @return ageCounter
*/
+ @Override
public int getAgeCounter() {
return ageCounter;
}
@@ -328,6 +337,7 @@
*
* @return the age counter roll over value
*/
+ @Override
public int getAgeCounterRollOver() {
return ageCounterRollOver;
}
@@ -337,6 +347,7 @@
*
* @return lsa bin instance
*/
+ @Override
public LsaBin getMaxAgeBin() {
return maxAgeBin;
}
@@ -347,6 +358,7 @@
* @param x Can be either age or ageCounter
* @return bin number.
*/
+ @Override
public int age2Bin(int x) {
if (x <= ageCounter) {
return (ageCounter - x);
diff --git a/protocols/ospf/protocol/src/main/java/org/onosproject/ospf/protocol/util/ChecksumCalculator.java b/protocols/ospf/protocol/src/main/java/org/onosproject/ospf/protocol/util/ChecksumCalculator.java
index ee2e712..f346f45 100644
--- a/protocols/ospf/protocol/src/main/java/org/onosproject/ospf/protocol/util/ChecksumCalculator.java
+++ b/protocols/ospf/protocol/src/main/java/org/onosproject/ospf/protocol/util/ChecksumCalculator.java
@@ -186,14 +186,12 @@
tempLsaByte[lsaChecksumPos1] = 0;
tempLsaByte[lsaChecksumPos2] = 0;
byte[] byteCheckSum = {0, 0};
- if (lsaBytes != null) {
- for (int i = 2; i < tempLsaByte.length; i++) {
- checksumOut[0] = checksumOut[0] + ((int) tempLsaByte[i] & 0xFF);
- checksumOut[1] = checksumOut[1] + checksumOut[0];
- }
- checksumOut[0] = checksumOut[0] % 255;
- checksumOut[1] = checksumOut[1] % 255;
+ for (int i = 2; i < tempLsaByte.length; i++) {
+ checksumOut[0] = checksumOut[0] + ((int) tempLsaByte[i] & 0xFF);
+ checksumOut[1] = checksumOut[1] + checksumOut[0];
}
+ checksumOut[0] = checksumOut[0] % 255;
+ checksumOut[1] = checksumOut[1] % 255;
int byte1 = (int) ((tempLsaByte.length - lsaChecksumPos1 - 1) * checksumOut[0] - checksumOut[1]) % 255;
if (byte1 <= 0) {
byte1 += 255;
diff --git a/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/TableEntryEncoder.java b/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/TableEntryEncoder.java
index a6318de..b61ae69 100644
--- a/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/TableEntryEncoder.java
+++ b/protocols/p4runtime/ctl/src/main/java/org/onosproject/p4runtime/ctl/TableEntryEncoder.java
@@ -220,8 +220,7 @@
// Priority.
// FIXME: check on P4Runtime if/what is the default priority.
- int priority = piTableEntry.priority().orElse(0);
- tableEntryMsgBuilder.setPriority(priority);
+ piTableEntry.priority().ifPresent(tableEntryMsgBuilder::setPriority);
// Controller metadata (cookie)
tableEntryMsgBuilder.setControllerMetadata(piTableEntry.cookie());
@@ -448,6 +447,10 @@
case ACTION:
Action actionMsg = tableActionMsg.getAction();
return decodeActionMsg(actionMsg, browser);
+ case ACTION_PROFILE_GROUP_ID:
+ return PiActionGroupId.of(tableActionMsg.getActionProfileGroupId());
+ case ACTION_PROFILE_MEMBER_ID:
+ return PiActionGroupMemberId.of(tableActionMsg.getActionProfileMemberId());
default:
throw new EncodeException(
format("Decoding of table action type %s not implemented", typeCase.name()));
diff --git a/protocols/p4runtime/ctl/src/test/java/org/onosproject/p4runtime/ctl/TableEntryEncoderTest.java b/protocols/p4runtime/ctl/src/test/java/org/onosproject/p4runtime/ctl/TableEntryEncoderTest.java
index b805aa9..149eae0 100644
--- a/protocols/p4runtime/ctl/src/test/java/org/onosproject/p4runtime/ctl/TableEntryEncoderTest.java
+++ b/protocols/p4runtime/ctl/src/test/java/org/onosproject/p4runtime/ctl/TableEntryEncoderTest.java
@@ -30,7 +30,9 @@
import org.onosproject.net.pi.model.PiPipelineModel;
import org.onosproject.net.pi.model.PiTableId;
import org.onosproject.net.pi.runtime.PiAction;
+import org.onosproject.net.pi.runtime.PiActionGroupId;
import org.onosproject.net.pi.runtime.PiActionParam;
+import org.onosproject.net.pi.runtime.PiExactFieldMatch;
import org.onosproject.net.pi.runtime.PiMatchKey;
import org.onosproject.net.pi.runtime.PiTableEntry;
import org.onosproject.net.pi.runtime.PiTernaryFieldMatch;
@@ -57,15 +59,20 @@
public class TableEntryEncoderTest {
private static final String DOT = ".";
private static final String TABLE_0 = "table0";
+ private static final String TABLE_ECMP = "ecmp";
private static final String SET_EGRESS_PORT = "set_egress_port";
private static final String PORT = "port";
private static final String HDR = "hdr";
+ private static final String META = "meta";
private static final String ETHERNET = "ethernet";
private static final String DST_ADDR = "dstAddr";
private static final String SRC_ADDR = "srcAddr";
private static final String STANDARD_METADATA = "standard_metadata";
+ private static final String ECMP_METADATA = "ecmp_metadata";
private static final String INGRESS_PORT = "ingress_port";
private static final String ETHER_TYPE = "etherType";
+ private static final String ECMP_GROUP_ID = "ecmp_group_id";
+ private static final String ECMP_ACT_PROFILE = "ecmp_selector";
private final Random rand = new Random();
private final URL p4InfoUrl = this.getClass().getResource("/test.p4info");
@@ -83,9 +90,12 @@
private final PiMatchFieldId ethSrcAddrFieldId = PiMatchFieldId.of(HDR + DOT + ETHERNET + DOT + SRC_ADDR);
private final PiMatchFieldId inPortFieldId = PiMatchFieldId.of(STANDARD_METADATA + DOT + INGRESS_PORT);
private final PiMatchFieldId ethTypeFieldId = PiMatchFieldId.of(HDR + DOT + ETHERNET + DOT + ETHER_TYPE);
+ private final PiMatchFieldId ecmpGroupFieldId =
+ PiMatchFieldId.of(META + DOT + ECMP_METADATA + DOT + ECMP_GROUP_ID);
private final PiActionParamId portParamId = PiActionParamId.of(PORT);
private final PiActionId outActionId = PiActionId.of(SET_EGRESS_PORT);
private final PiTableId tableId = PiTableId.of(TABLE_0);
+ private final PiTableId ecmpTableId = PiTableId.of(TABLE_ECMP);
private final PiTableEntry piTableEntry = PiTableEntry
.builder()
@@ -105,6 +115,17 @@
.withCookie(2)
.build();
+ private final PiTableEntry piTableEntryWithGroupAction = PiTableEntry
+ .builder()
+ .forTable(ecmpTableId)
+ .withMatchKey(PiMatchKey.builder()
+ .addFieldMatch(new PiExactFieldMatch(ecmpGroupFieldId, ofOnes(1)))
+ .build())
+ .withAction(PiActionGroupId.of(1))
+ .withPriority(1)
+ .withCookie(2)
+ .build();
+
public TableEntryEncoderTest() throws ImmutableByteSequence.ByteSequenceTrimException {
}
@@ -126,8 +147,7 @@
}
@Test
- public void testTableEntryEncoder()
- throws P4InfoBrowser.NotFoundException, ImmutableByteSequence.ByteSequenceTrimException {
+ public void testTableEntryEncoder() throws P4InfoBrowser.NotFoundException {
Collection<TableEntry> result = encode(Lists.newArrayList(piTableEntry), defaultPipeconf);
assertThat(result, hasSize(1));
@@ -169,4 +189,33 @@
// TODO: improve, assert other field match types (ternary, LPM)
}
+
+ @Test
+ public void testActopProfileGroup() throws P4InfoBrowser.NotFoundException {
+ Collection<TableEntry> result = encode(Lists.newArrayList(piTableEntryWithGroupAction), defaultPipeconf);
+ assertThat(result, hasSize(1));
+
+ TableEntry tableEntryMsg = result.iterator().next();
+
+ Collection<PiTableEntry> decodedResults = decode(Lists.newArrayList(tableEntryMsg), defaultPipeconf);
+ PiTableEntry decodedPiTableEntry = decodedResults.iterator().next();
+
+ // Test equality for decoded entry.
+ new EqualsTester()
+ .addEqualityGroup(piTableEntryWithGroupAction, decodedPiTableEntry)
+ .testEquals();
+
+ // Table ID.
+ int p4InfoTableId = browser.tables().getByName(ecmpTableId.id()).getPreamble().getId();
+ int encodedTableId = tableEntryMsg.getTableId();
+ assertThat(encodedTableId, is(p4InfoTableId));
+
+ // Exact match.
+ byte[] encodedTernaryMatchValue = tableEntryMsg.getMatch(0).getExact().getValue().toByteArray();
+ assertThat(encodedTernaryMatchValue, is(new byte[]{(byte) 0xff}));
+
+ // Action profile group id
+ int actionProfileGroupId = tableEntryMsg.getAction().getActionProfileGroupId();
+ assertThat(actionProfileGroupId, is(1));
+ }
}
diff --git a/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/protocol/ver1/PcepLabelUpdateVer1.java b/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/protocol/ver1/PcepLabelUpdateVer1.java
index 8603146..a6aa667 100644
--- a/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/protocol/ver1/PcepLabelUpdateVer1.java
+++ b/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/protocol/ver1/PcepLabelUpdateVer1.java
@@ -118,10 +118,7 @@
if (isLabelMapSet) {
return new PcepLabelUpdateVer1(labelMap);
}
- if (!isLabelDownloadSet && !isLabelMapSet) {
- throw new PcepParseException(
- "Label Download or Label Map is not set while building PcepLabelUpdate Message");
- }
+
return new PcepLabelUpdateVer1();
}
diff --git a/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/types/IPv6InterfaceAddressSubTlv.java b/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/types/IPv6InterfaceAddressSubTlv.java
index 934c786..d318ca3 100644
--- a/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/types/IPv6InterfaceAddressSubTlv.java
+++ b/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/types/IPv6InterfaceAddressSubTlv.java
@@ -80,7 +80,7 @@
boolean bFoundNoMask = true;
//value starts from 3rd byte.
for (int i = 2; i < 20; ++i) {
- if (0xFF != raw[i]) {
+ if ((byte) 0xFF != raw[i]) {
bFoundNoMask = false;
}
}
diff --git a/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/types/IPv6NeighborAddressSubTlv.java b/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/types/IPv6NeighborAddressSubTlv.java
index 6eedfa5..7b2f5e5 100644
--- a/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/types/IPv6NeighborAddressSubTlv.java
+++ b/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/types/IPv6NeighborAddressSubTlv.java
@@ -78,7 +78,7 @@
boolean bFoundNoMask = true;
//value starts from 3rd byte.
for (int i = 2; i < 20; ++i) {
- if (0xFF != raw[i]) {
+ if ((byte) 0xFF != raw[i]) {
bFoundNoMask = false;
}
}
diff --git a/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/types/IPv6RouterIdofLocalNodeSubTlv.java b/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/types/IPv6RouterIdofLocalNodeSubTlv.java
index b269803..186f56d 100644
--- a/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/types/IPv6RouterIdofLocalNodeSubTlv.java
+++ b/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/types/IPv6RouterIdofLocalNodeSubTlv.java
@@ -78,7 +78,7 @@
boolean bFoundNoMask = true;
//value starts from 3rd byte.
for (int i = 2; i < 20; ++i) {
- if (0xFF != raw[i]) {
+ if ((byte) 0xFF != raw[i]) {
bFoundNoMask = false;
}
}
diff --git a/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/types/IPv6RouterIdofRemoteNodeSubTlv.java b/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/types/IPv6RouterIdofRemoteNodeSubTlv.java
index 1512aa2..021da71 100644
--- a/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/types/IPv6RouterIdofRemoteNodeSubTlv.java
+++ b/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/types/IPv6RouterIdofRemoteNodeSubTlv.java
@@ -79,7 +79,7 @@
boolean bFoundNoMask = true;
//value starts from 3rd byte.
for (int i = 2; i < 20; ++i) {
- if (0xFF != raw[i]) {
+ if ((byte) 0xFF != raw[i]) {
bFoundNoMask = false;
}
}
diff --git a/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/types/IPv6SubObject.java b/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/types/IPv6SubObject.java
index e570255..808b1e8 100644
--- a/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/types/IPv6SubObject.java
+++ b/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/types/IPv6SubObject.java
@@ -130,7 +130,7 @@
boolean bFoundNoMask = true;
//value starts from 3rd byte.
for (int i = 2; i < 20; ++i) {
- if (0xFF != raw[i]) {
+ if ((byte) 0xFF != raw[i]) {
bFoundNoMask = false;
}
}
diff --git a/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/types/NexthopIPv6addressTlv.java b/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/types/NexthopIPv6addressTlv.java
index fdcf9e7..2c031ab 100644
--- a/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/types/NexthopIPv6addressTlv.java
+++ b/protocols/pcep/pcepio/src/main/java/org/onosproject/pcepio/types/NexthopIPv6addressTlv.java
@@ -99,7 +99,7 @@
boolean bFoundNoMask = true;
//value starts from 3rd byte.
for (int i = 5; i < 20; ++i) {
- if (0xFF != raw[i]) {
+ if ((byte) 0xFF != raw[i]) {
bFoundNoMask = false;
}
}
diff --git a/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/BasicPceccHandler.java b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/BasicPceccHandler.java
index c547b35..7376c14 100644
--- a/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/BasicPceccHandler.java
+++ b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/BasicPceccHandler.java
@@ -113,7 +113,7 @@
*
* @return this class single instance
*/
- public static BasicPceccHandler getInstance() {
+ public static synchronized BasicPceccHandler getInstance() {
if (crHandlerInstance == null) {
crHandlerInstance = new BasicPceccHandler();
}
diff --git a/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PceccSrTeBeHandler.java b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PceccSrTeBeHandler.java
index 8d50149..682f242 100644
--- a/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PceccSrTeBeHandler.java
+++ b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PceccSrTeBeHandler.java
@@ -96,7 +96,7 @@
*
* @return this class single instance
*/
- public static PceccSrTeBeHandler getInstance() {
+ public static synchronized PceccSrTeBeHandler getInstance() {
if (srTeHandlerInstance == null) {
srTeHandlerInstance = new PceccSrTeBeHandler();
}
diff --git a/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PcepChannelHandler.java b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PcepChannelHandler.java
index dce5fa0..596a633 100644
--- a/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PcepChannelHandler.java
+++ b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PcepChannelHandler.java
@@ -485,9 +485,8 @@
* @throws PcepParseException while building pcep error message
*/
public void processUnknownMsg() throws PcepParseException {
- Date now = null;
+ Date now = new Date();
if (pcepPacketStats.wrongPacketCount() == 0) {
- now = new Date();
pcepPacketStats.setTime(now.getTime());
pcepPacketStats.addWrongPacket();
sendErrMsgForInvalidMsg();
diff --git a/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PcepClientControllerImpl.java b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PcepClientControllerImpl.java
index 2ddc819..1bb5610 100644
--- a/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PcepClientControllerImpl.java
+++ b/protocols/pcep/server/ctl/src/main/java/org/onosproject/pcep/server/impl/PcepClientControllerImpl.java
@@ -1005,6 +1005,10 @@
}
}
+ if (ipv4LspIdenTlv == null) {
+ return false;
+ }
+
LspKey lspKeyOfRpt = new LspKey(lspObj.getPlspId(), ipv4LspIdenTlv.getLspId());
tunnel = preSyncLspDbByKey.get(lspKeyOfRpt);
// PCE tunnel is matched with PCRpt LSP. Now delete it from the preSyncLspDb list as the residual
@@ -1059,7 +1063,8 @@
// State different for PCC sent LSP and PCE known LSP, send PCUpd msg.
State tunnelState = PcepLspStatus
.getTunnelStatusFromLspStatus(PcepLspStatus.values()[lspObj.getOFlag()]);
- if (tunnelState != tunnel.state()) {
+
+ if (tunnel != null && tunnelState != tunnel.state()) {
for (PcepEventListener l : pcepEventListener) {
l.handleEndOfSyncAction(tunnel, SEND_UPDATE);
}
diff --git a/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/TestEventuallyConsistentMap.java b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/TestEventuallyConsistentMap.java
index 6c34554..9184352 100644
--- a/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/TestEventuallyConsistentMap.java
+++ b/protocols/pcep/server/ctl/src/test/java/org/onosproject/pcelabelstore/util/TestEventuallyConsistentMap.java
@@ -90,6 +90,7 @@
return map.get(key);
}
+ @SuppressWarnings("ReturnValueIgnored")
@Override
public void put(K key, V value) {
map.put(key, value);
diff --git a/protocols/restconf/server/rpp/BUCK b/protocols/restconf/server/rpp/BUCK
index 8f7bb52..faeeb6f 100644
--- a/protocols/restconf/server/rpp/BUCK
+++ b/protocols/restconf/server/rpp/BUCK
@@ -9,7 +9,14 @@
'//apps/restconf/api:onos-apps-restconf-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/restconf',
)
diff --git a/protocols/restconf/server/rpp/pom.xml b/protocols/restconf/server/rpp/pom.xml
index 6f88aaf..07e2f8b 100644
--- a/protocols/restconf/server/rpp/pom.xml
+++ b/protocols/restconf/server/rpp/pom.xml
@@ -95,6 +95,18 @@
<version>2.25.1</version>
</dependency>
<dependency>
+ <groupId>org.glassfish.jersey.test-framework</groupId>
+ <artifactId>jersey-test-framework-core</artifactId>
+ <version>${jersey.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.test-framework.providers</groupId>
+ <artifactId>jersey-test-framework-provider-jetty</artifactId>
+ <version>${jersey.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>org.onosproject</groupId>
<artifactId>onlab-misc</artifactId>
<version>${project.version}</version>
@@ -109,6 +121,19 @@
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onos-rest</artifactId>
+ <version>${project.version}</version>
+ <classifier>tests</classifier>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onosproject</groupId>
+ <artifactId>onlab-osgi</artifactId>
+ <classifier>tests</classifier>
+ <scope>test</scope>
+ </dependency>
</dependencies>
<build>
diff --git a/protocols/restconf/server/rpp/src/main/java/org/onosproject/protocol/restconf/server/rpp/RestconfWebResource.java b/protocols/restconf/server/rpp/src/main/java/org/onosproject/protocol/restconf/server/rpp/RestconfWebResource.java
index ba11421..36eb3a2 100644
--- a/protocols/restconf/server/rpp/src/main/java/org/onosproject/protocol/restconf/server/rpp/RestconfWebResource.java
+++ b/protocols/restconf/server/rpp/src/main/java/org/onosproject/protocol/restconf/server/rpp/RestconfWebResource.java
@@ -20,6 +20,7 @@
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.glassfish.jersey.server.ChunkedOutput;
import org.onosproject.rest.AbstractWebResource;
+import org.onosproject.restconf.api.RestconfError;
import org.onosproject.restconf.api.RestconfException;
import org.onosproject.restconf.api.RestconfRpcOutput;
import org.onosproject.restconf.api.RestconfService;
@@ -42,6 +43,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
+import java.util.Arrays;
import java.util.concurrent.CompletableFuture;
import static javax.ws.rs.core.Response.Status.BAD_REQUEST;
@@ -68,22 +70,19 @@
@Context
UriInfo uriInfo;
- private static final String NOT_EXIST = "Requested data resource does not exist";
-
private final RestconfService service = get(RestconfService.class);
private final Logger log = getLogger(getClass());
/**
* Handles a RESTCONF GET operation against a target data resource. If the
* operation is successful, the JSON presentation of the resource plus HTTP
- * status code "200 OK" is returned. Otherwise, HTTP error status code
- * "400 Bad Request" is returned.
+ * status code "200 OK" is returned. If it is not found then "404 Not Found"
+ * is returned. On internal error "500 Internal Server Error" is returned.
*
* @param uriString URI of the data resource.
- * @return HTTP response
+ * @return HTTP response - 200, 404 or 500
*/
@GET
- @Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("data/{identifier : .+}")
public Response handleGetRequest(@PathParam("identifier") String uriString) {
@@ -94,13 +93,27 @@
try {
ObjectNode node = service.runGetOperationOnDataResource(uri);
if (node == null) {
- return Response.status(NOT_FOUND).entity(NOT_EXIST).build();
+ RestconfError error =
+ RestconfError.builder(RestconfError.ErrorType.PROTOCOL,
+ RestconfError.ErrorTag.INVALID_VALUE)
+ .errorMessage("Resource not found")
+ .errorPath(uriString)
+ .errorAppTag("handleGetRequest")
+ .build();
+ return Response.status(NOT_FOUND)
+ .entity(RestconfError.wrapErrorAsJson(Arrays.asList(error))).build();
}
return ok(node).build();
} catch (RestconfException e) {
log.error("ERROR: handleGetRequest: {}", e.getMessage());
log.debug("Exception in handleGetRequest:", e);
- return e.getResponse();
+ return Response.status(e.getResponse().getStatus()).entity(e.toRestconfErrorJson()).build();
+ } catch (Exception e) {
+ RestconfError error = RestconfError
+ .builder(RestconfError.ErrorType.APPLICATION, RestconfError.ErrorTag.OPERATION_FAILED)
+ .errorMessage(e.getMessage()).errorAppTag("handlePostRequest").build();
+ return Response.status(INTERNAL_SERVER_ERROR)
+ .entity(RestconfError.wrapErrorAsJson(Arrays.asList(error))).build();
}
}
@@ -186,14 +199,23 @@
return Response.created(uriInfo.getRequestUri()).build();
} catch (JsonProcessingException e) {
log.error("ERROR: handlePostRequest ", e);
- return Response.status(BAD_REQUEST).build();
+ RestconfError error = RestconfError
+ .builder(RestconfError.ErrorType.APPLICATION, RestconfError.ErrorTag.MALFORMED_MESSAGE)
+ .errorMessage(e.getMessage()).errorAppTag("handlePostRequest").build();
+ return Response.status(BAD_REQUEST)
+ .entity(RestconfError.wrapErrorAsJson(Arrays.asList(error))).build();
} catch (RestconfException e) {
log.error("ERROR: handlePostRequest: {}", e.getMessage());
log.debug("Exception in handlePostRequest:", e);
- return e.getResponse();
+ return Response.status(e.getResponse().getStatus())
+ .entity(e.toRestconfErrorJson()).build();
} catch (IOException ex) {
log.error("ERROR: handlePostRequest ", ex);
- return Response.status(INTERNAL_SERVER_ERROR).build();
+ RestconfError error = RestconfError
+ .builder(RestconfError.ErrorType.APPLICATION, RestconfError.ErrorTag.OPERATION_FAILED)
+ .errorMessage(ex.getMessage()).errorAppTag("handlePostRequest").build();
+ return Response.status(INTERNAL_SERVER_ERROR)
+ .entity(RestconfError.wrapErrorAsJson(Arrays.asList(error))).build();
}
}
@@ -230,14 +252,23 @@
return ok(node).build();
} catch (JsonProcessingException e) {
log.error("ERROR: handleRpcRequest", e);
- return Response.status(BAD_REQUEST).build();
+ RestconfError error = RestconfError
+ .builder(RestconfError.ErrorType.APPLICATION, RestconfError.ErrorTag.MALFORMED_MESSAGE)
+ .errorMessage(e.getMessage()).errorAppTag("handleRpcRequest").build();
+ return Response.status(BAD_REQUEST)
+ .entity(RestconfError.wrapErrorAsJson(Arrays.asList(error))).build();
} catch (RestconfException e) {
log.error("ERROR: handleRpcRequest: {}", e.getMessage());
log.debug("Exception in handleRpcRequest:", e);
- return e.getResponse();
+ return Response.status(e.getResponse().getStatus())
+ .entity(e.toRestconfErrorJson()).build();
} catch (Exception e) {
log.error("ERROR: handleRpcRequest ", e);
- return Response.status(INTERNAL_SERVER_ERROR).build();
+ RestconfError error = RestconfError
+ .builder(RestconfError.ErrorType.APPLICATION, RestconfError.ErrorTag.OPERATION_FAILED)
+ .errorMessage(e.getMessage()).errorAppTag("handleRpcRequest").build();
+ return Response.status(INTERNAL_SERVER_ERROR)
+ .entity(RestconfError.wrapErrorAsJson(Arrays.asList(error))).build();
}
}
@@ -272,14 +303,23 @@
return Response.created(uriInfo.getRequestUri()).build();
} catch (JsonProcessingException e) {
log.error("ERROR: handlePutRequest ", e);
- return Response.status(BAD_REQUEST).build();
+ RestconfError error = RestconfError
+ .builder(RestconfError.ErrorType.APPLICATION, RestconfError.ErrorTag.MALFORMED_MESSAGE)
+ .errorMessage(e.getMessage()).errorAppTag("handlePutRequest").build();
+ return Response.status(BAD_REQUEST)
+ .entity(RestconfError.wrapErrorAsJson(Arrays.asList(error))).build();
} catch (RestconfException e) {
log.error("ERROR: handlePutRequest: {}", e.getMessage());
log.debug("Exception in handlePutRequest:", e);
- return e.getResponse();
+ return Response.status(e.getResponse().getStatus())
+ .entity(e.toRestconfErrorJson()).build();
} catch (IOException ex) {
log.error("ERROR: handlePutRequest ", ex);
- return Response.status(INTERNAL_SERVER_ERROR).build();
+ RestconfError error = RestconfError
+ .builder(RestconfError.ErrorType.APPLICATION, RestconfError.ErrorTag.OPERATION_FAILED)
+ .errorMessage(ex.getMessage()).errorAppTag("handlePutRequest").build();
+ return Response.status(INTERNAL_SERVER_ERROR)
+ .entity(RestconfError.wrapErrorAsJson(Arrays.asList(error))).build();
}
}
@@ -294,7 +334,6 @@
* @return HTTP response
*/
@DELETE
- @Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("data/{identifier : .+}")
public Response handleDeleteRequest(@PathParam("identifier") String uriString) {
@@ -308,7 +347,8 @@
} catch (RestconfException e) {
log.error("ERROR: handleDeleteRequest: {}", e.getMessage());
log.debug("Exception in handleDeleteRequest:", e);
- return e.getResponse();
+ return Response.status(e.getResponse().getStatus())
+ .entity(e.toRestconfErrorJson()).build();
}
}
@@ -340,14 +380,23 @@
return Response.ok().build();
} catch (JsonProcessingException e) {
log.error("ERROR: handlePatchRequest ", e);
- return Response.status(BAD_REQUEST).build();
+ RestconfError error = RestconfError
+ .builder(RestconfError.ErrorType.APPLICATION, RestconfError.ErrorTag.MALFORMED_MESSAGE)
+ .errorMessage(e.getMessage()).errorAppTag("handlePatchRequest").build();
+ return Response.status(BAD_REQUEST)
+ .entity(RestconfError.wrapErrorAsJson(Arrays.asList(error))).build();
} catch (RestconfException e) {
log.error("ERROR: handlePatchRequest: {}", e.getMessage());
log.debug("Exception in handlePatchRequest:", e);
- return e.getResponse();
+ return Response.status(e.getResponse().getStatus())
+ .entity(e.toRestconfErrorJson()).build();
} catch (IOException ex) {
log.error("ERROR: handlePatchRequest ", ex);
- return Response.status(INTERNAL_SERVER_ERROR).build();
+ RestconfError error = RestconfError
+ .builder(RestconfError.ErrorType.APPLICATION, RestconfError.ErrorTag.OPERATION_FAILED)
+ .errorMessage(ex.getMessage()).errorAppTag("handlePatchRequest").build();
+ return Response.status(INTERNAL_SERVER_ERROR)
+ .entity(RestconfError.wrapErrorAsJson(Arrays.asList(error))).build();
}
}
diff --git a/protocols/restconf/server/rpp/src/test/java/org/onosproject/protocol/restconf/server/rpp/RestconfWebResourceTest.java b/protocols/restconf/server/rpp/src/test/java/org/onosproject/protocol/restconf/server/rpp/RestconfWebResourceTest.java
new file mode 100644
index 0000000..603bbf6
--- /dev/null
+++ b/protocols/restconf/server/rpp/src/test/java/org/onosproject/protocol/restconf/server/rpp/RestconfWebResourceTest.java
@@ -0,0 +1,222 @@
+/*
+ * 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.protocol.restconf.server.rpp;
+
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.easymock.EasyMock;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.osgi.ServiceDirectory;
+import org.onlab.osgi.TestServiceDirectory;
+import org.onosproject.rest.resources.ResourceTest;
+import org.onosproject.restconf.api.RestconfError;
+import org.onosproject.restconf.api.RestconfException;
+import org.onosproject.restconf.api.RestconfService;
+
+import javax.ws.rs.InternalServerErrorException;
+import javax.ws.rs.NotFoundException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Response;
+
+import java.io.ByteArrayInputStream;
+import java.net.URI;
+import java.nio.charset.StandardCharsets;
+import java.util.Optional;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static javax.ws.rs.core.Response.Status.CONFLICT;
+import static javax.ws.rs.core.Response.Status.INTERNAL_SERVER_ERROR;
+import static junit.framework.TestCase.assertTrue;
+import static junit.framework.TestCase.fail;
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * Test the RestconfWebResource.
+ */
+public class RestconfWebResourceTest extends ResourceTest {
+
+ public static final String DATA_IETF_SYSTEM_SYSTEM = "data/ietf-system:system";
+
+ private static final Pattern RESTCONF_ERROR_REGEXP =
+ Pattern.compile("(\\{\"ietf-restconf:errors\":\\[)\\R?"
+ + "((\\{\"error\":)\\R?"
+ + "(\\{\"error-type\":\")((protocol)|(transport)|(rpc)|(application))(\",)\\R?"
+ + "(\"error-tag\":\")[a-z\\-]*(\",)\\R?"
+ + "((\"error-app-tag\":\").*(\",))?\\R?"
+ + "((\"error-path\":\").*(\",))?\\R?"
+ + "((\"error-message\":\").*(\"))?(\\}\\},?))*(\\]\\})", Pattern.DOTALL);
+
+ private RestconfService restconfService = createMock(RestconfService.class);
+
+ public RestconfWebResourceTest() {
+ super(ResourceConfig.forApplicationClass(RestconfProtocolProxy.class));
+ }
+
+ @Before
+ public void setup() {
+ ServiceDirectory testDirectory = new TestServiceDirectory()
+ .add(RestconfService.class, restconfService);
+ setServiceDirectory(testDirectory);
+ }
+
+ /**
+ * Test handleGetRequest when an Json object is returned.
+ */
+ @Test
+ public void testHandleGetRequest() {
+ ObjectMapper mapper = new ObjectMapper();
+ ObjectNode node = mapper.createObjectNode();
+ expect(restconfService
+ .runGetOperationOnDataResource(URI.create(getBaseUri() + DATA_IETF_SYSTEM_SYSTEM)))
+ .andReturn(node).anyTimes();
+ replay(restconfService);
+
+ WebTarget wt = target();
+ String response = wt.path("/" + DATA_IETF_SYSTEM_SYSTEM).request().get(String.class);
+ assertNotNull(response);
+ }
+
+ /**
+ * Test handleGetRequest when nothing is returned.
+ */
+ @Test
+ public void testHandleGetRequestNotFound() {
+ expect(restconfService
+ .runGetOperationOnDataResource(URI.create(getBaseUri() + DATA_IETF_SYSTEM_SYSTEM)))
+ .andReturn(null).anyTimes();
+ replay(restconfService);
+
+ WebTarget wt = target();
+ try {
+ String response = wt.path("/" + DATA_IETF_SYSTEM_SYSTEM).request().get(String.class);
+ fail("Expecting fail as response is none");
+ } catch (NotFoundException e) {
+ assertNotNull(e.getResponse());
+ assertRestconfErrorJson(e.getResponse());
+ }
+ }
+
+ /**
+ * Test handleGetRequest when an RestconfException is thrown.
+ */
+ @Test
+ public void testHandleGetRequestRestconfException() {
+ expect(restconfService
+ .runGetOperationOnDataResource(URI.create(getBaseUri() + DATA_IETF_SYSTEM_SYSTEM)))
+ .andThrow(new RestconfException("Suitable error message",
+ RestconfError.ErrorTag.OPERATION_FAILED, INTERNAL_SERVER_ERROR,
+ Optional.of("/" + DATA_IETF_SYSTEM_SYSTEM),
+ Optional.of("More info about the error")))
+ .anyTimes();
+ replay(restconfService);
+
+ WebTarget wt = target();
+ try {
+ String response = wt.path("/" + DATA_IETF_SYSTEM_SYSTEM).request().get(String.class);
+ fail("Expecting fail as response is RestconfException");
+ } catch (InternalServerErrorException e) {
+ assertNotNull(e.getResponse());
+ assertRestconfErrorJson(e.getResponse());
+ }
+ }
+
+ /**
+ * Test handleGetRequest when an Exception is thrown.
+ */
+ @Test
+ public void testHandleGetRequestIoException() {
+ expect(restconfService
+ .runGetOperationOnDataResource(URI.create(getBaseUri() + DATA_IETF_SYSTEM_SYSTEM)))
+ .andThrow(new IllegalArgumentException("A test exception"))
+ .anyTimes();
+ replay(restconfService);
+
+ WebTarget wt = target();
+ try {
+ String response = wt.path("/" + DATA_IETF_SYSTEM_SYSTEM).request().get(String.class);
+ fail("Expecting fail as response is IllegalArgumentException");
+ } catch (InternalServerErrorException e) {
+ assertNotNull(e.getResponse());
+ assertRestconfErrorJson(e.getResponse());
+ }
+ }
+
+ /**
+ * Test handlePostRequest with no exception.
+ */
+ @Test
+ public void testHandlePostRequest() {
+ ObjectMapper mapper = new ObjectMapper();
+ ObjectNode ietfSystemSubNode = mapper.createObjectNode();
+ ietfSystemSubNode.put("contact", "Open Networking Foundation");
+ ietfSystemSubNode.put("hostname", "host1");
+ ietfSystemSubNode.put("location", "The moon");
+
+ ObjectNode ietfSystemNode = mapper.createObjectNode();
+ ietfSystemNode.put("ietf-system:system", ietfSystemSubNode);
+
+ WebTarget wt = target();
+ Response response = wt.path("/" + DATA_IETF_SYSTEM_SYSTEM)
+ .request()
+ .post(Entity.json(ietfSystemNode.toString()));
+ assertEquals(201, response.getStatus());
+ }
+
+ /**
+ * Test handlePostRequest with 'already exists' exception.
+ */
+ @Test
+ public void testHandlePostRequestAlreadyExists() {
+ ObjectMapper mapper = new ObjectMapper();
+ ObjectNode ietfSystemSubNode = mapper.createObjectNode();
+ ietfSystemSubNode.put("contact", "Open Networking Foundation");
+ ietfSystemSubNode.put("hostname", "host1");
+ ietfSystemSubNode.put("location", "The moon");
+
+ ObjectNode ietfSystemNode = mapper.createObjectNode();
+ ietfSystemNode.put("ietf-system:system", ietfSystemSubNode);
+
+ restconfService.runPostOperationOnDataResource(
+ EasyMock.<URI>anyObject(), EasyMock.<ObjectNode>anyObject());
+ expectLastCall().andThrow(new RestconfException("Requested node already present", null,
+ RestconfError.ErrorTag.DATA_EXISTS, CONFLICT,
+ Optional.of("/" + DATA_IETF_SYSTEM_SYSTEM)));
+ replay(restconfService);
+
+ WebTarget wt = target();
+ Response response = wt.path("/" + DATA_IETF_SYSTEM_SYSTEM)
+ .request()
+ .post(Entity.json(ietfSystemNode.toString()));
+ assertEquals(409, response.getStatus());
+ }
+
+ private static void assertRestconfErrorJson(Response errorResponse) {
+ ByteArrayInputStream in = (ByteArrayInputStream) errorResponse.getEntity();
+ int n = in.available();
+ byte[] bytes = new byte[n];
+ in.read(bytes, 0, n);
+
+ Matcher m = RESTCONF_ERROR_REGEXP.matcher(new String(bytes, StandardCharsets.UTF_8));
+ assertTrue(m.matches());
+ }
+}
diff --git a/protocols/snmp/ctl/src/main/java/org/onosproject/snmp/ctl/DefaultSnmpDevice.java b/protocols/snmp/ctl/src/main/java/org/onosproject/snmp/ctl/DefaultSnmpDevice.java
index 5e1f867..b15277c 100644
--- a/protocols/snmp/ctl/src/main/java/org/onosproject/snmp/ctl/DefaultSnmpDevice.java
+++ b/protocols/snmp/ctl/src/main/java/org/onosproject/snmp/ctl/DefaultSnmpDevice.java
@@ -50,7 +50,7 @@
public DefaultSnmpDevice(String snmpHost, int snmpPort, String username, String community) {
this.snmpHost = checkNotNull(snmpHost, "SNMP Device IP cannot be null");
- this.snmpPort = checkNotNull(snmpPort, "SNMP Device port cannot be null");
+ this.snmpPort = snmpPort;
this.username = username;
this.community = community;
this.deviceId = createDeviceId();
diff --git a/providers/general/device/src/main/java/org/onosproject/provider/general/device/impl/GeneralDeviceProvider.java b/providers/general/device/src/main/java/org/onosproject/provider/general/device/impl/GeneralDeviceProvider.java
index f309497..c439094 100644
--- a/providers/general/device/src/main/java/org/onosproject/provider/general/device/impl/GeneralDeviceProvider.java
+++ b/providers/general/device/src/main/java/org/onosproject/provider/general/device/impl/GeneralDeviceProvider.java
@@ -441,15 +441,17 @@
//Empty list of ports
List<PortDescription> ports = new ArrayList<>();
- if (driver.hasBehaviour(DeviceDescriptionDiscovery.class)) {
- DeviceDescriptionDiscovery deviceDiscovery = driver
- .createBehaviour(driverData, DeviceDescriptionDiscovery.class);
-
+ DeviceDescriptionDiscovery deviceDiscovery = getBehaviour(driver,
+ DeviceDescriptionDiscovery.class, driverData);
+ if (deviceDiscovery != null) {
DeviceDescription newdescription = deviceDiscovery.discoverDeviceDetails();
if (newdescription != null) {
description = newdescription;
}
ports = deviceDiscovery.discoverPortDetails();
+ } else {
+ log.info("No Device Description Discovery for device {}, no update for " +
+ "description or ports.", deviceId);
}
if (!handlePipeconf(deviceId, driver, driverData, true)) {
diff --git a/providers/host/src/main/java/org/onosproject/provider/host/impl/HostLocationProvider.java b/providers/host/src/main/java/org/onosproject/provider/host/impl/HostLocationProvider.java
index eadb4cf..0633d12 100644
--- a/providers/host/src/main/java/org/onosproject/provider/host/impl/HostLocationProvider.java
+++ b/providers/host/src/main/java/org/onosproject/provider/host/impl/HostLocationProvider.java
@@ -418,6 +418,7 @@
// IPv6: Use Neighbor Discovery
//TODO need to implement ndp probe
log.info("Triggering probe on device {} ", host);
+ return;
}
TrafficTreatment treatment = DefaultTrafficTreatment.builder().setOutput(host.location().port()).build();
diff --git a/providers/link/src/test/java/org/onosproject/provider/linkdiscovery/impl/LinkDiscoveryProviderTest.java b/providers/link/src/test/java/org/onosproject/provider/linkdiscovery/impl/LinkDiscoveryProviderTest.java
index a1872c8..30ddf2a 100644
--- a/providers/link/src/test/java/org/onosproject/provider/linkdiscovery/impl/LinkDiscoveryProviderTest.java
+++ b/providers/link/src/test/java/org/onosproject/provider/linkdiscovery/impl/LinkDiscoveryProviderTest.java
@@ -149,7 +149,7 @@
@Test
public void activate() throws Exception {
- assertFalse("Provider should be registered", linkRegistry.getProviders().contains(provider));
+ assertTrue("Provider should be registered", linkRegistry.getProviders().contains(provider.id()));
assertEquals("Device service should be registered", provider.deviceService, deviceService);
assertEquals("Device listener should be added", 1, deviceListeners.size());
assertNotNull("Registration expected", providerService);
@@ -177,7 +177,7 @@
public void deactivate() throws Exception {
provider.deactivate();
assertEquals("Device listener should be removed", 0, deviceListeners.size());
- assertFalse("Provider should not be registered", linkRegistry.getProviders().contains(provider));
+ assertFalse("Provider should not be registered", linkRegistry.getProviders().contains(provider.id()));
assertTrue(provider.executor.isShutdown());
assertNull(provider.providerService);
}
diff --git a/providers/lisp/device/src/test/java/org/onosproject/provider/lisp/device/impl/LispDeviceProviderTest.java b/providers/lisp/device/src/test/java/org/onosproject/provider/lisp/device/impl/LispDeviceProviderTest.java
index 74a28f0..90a15fa 100644
--- a/providers/lisp/device/src/test/java/org/onosproject/provider/lisp/device/impl/LispDeviceProviderTest.java
+++ b/providers/lisp/device/src/test/java/org/onosproject/provider/lisp/device/impl/LispDeviceProviderTest.java
@@ -97,7 +97,7 @@
provider.deactivate();
assertFalse("Provider should not be registered",
- providerRegistry.getProviders().contains(provider));
+ providerRegistry.getProviders().contains(provider.id()));
assertNull("Provider service should be null",
provider.providerService);
assertEquals("Controller listener should be removed", 0,
diff --git a/providers/lisp/mapping/src/test/java/org/onosproject/provider/lisp/mapping/impl/LispMappingProviderTest.java b/providers/lisp/mapping/src/test/java/org/onosproject/provider/lisp/mapping/impl/LispMappingProviderTest.java
index 17c758c..8424454 100644
--- a/providers/lisp/mapping/src/test/java/org/onosproject/provider/lisp/mapping/impl/LispMappingProviderTest.java
+++ b/providers/lisp/mapping/src/test/java/org/onosproject/provider/lisp/mapping/impl/LispMappingProviderTest.java
@@ -78,7 +78,7 @@
provider.deactivate();
assertFalse("Provider should not be registered",
- providerRegistry.getProviders().contains(provider));
+ providerRegistry.getProviders().contains(provider.id()));
assertNull("Provider service should be null",
provider.providerService);
assertEquals("Controller listener should be removed", 0,
diff --git a/providers/netconf/device/src/test/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProviderTest.java b/providers/netconf/device/src/test/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProviderTest.java
index f37d41e..802c002 100644
--- a/providers/netconf/device/src/test/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProviderTest.java
+++ b/providers/netconf/device/src/test/java/org/onosproject/provider/netconf/device/impl/NetconfDeviceProviderTest.java
@@ -225,7 +225,7 @@
public void deactivate() throws Exception {
provider.deactivate();
assertNull("Device listener should be removed", deviceService.listener);
- assertFalse("Provider should not be registered", deviceRegistry.getProviders().contains(provider));
+ assertFalse("Provider should not be registered", deviceRegistry.getProviders().contains(provider.id()));
assertTrue("Thread to connect device should be shutdown", provider.executor.isShutdown());
assertTrue("Scheduled task to update device should be shutdown", provider.scheduledTask.isCancelled());
assertNull("Provider service should be null", provider.providerService);
diff --git a/providers/openflow/device/src/main/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceProvider.java b/providers/openflow/device/src/main/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceProvider.java
index f3dd6e0..b489c52 100644
--- a/providers/openflow/device/src/main/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceProvider.java
+++ b/providers/openflow/device/src/main/java/org/onosproject/provider/of/device/impl/OpenFlowDeviceProvider.java
@@ -86,6 +86,7 @@
import org.projectfloodlight.openflow.protocol.OFObject;
import org.projectfloodlight.openflow.protocol.OFPortConfig;
import org.projectfloodlight.openflow.protocol.OFPortDesc;
+import org.projectfloodlight.openflow.protocol.OFPortDescProp;
import org.projectfloodlight.openflow.protocol.OFPortDescPropEthernet;
import org.projectfloodlight.openflow.protocol.OFPortDescPropOptical;
import org.projectfloodlight.openflow.protocol.OFPortDescPropOpticalTransport;
@@ -156,54 +157,115 @@
public static final String AK_MIN_FREQ_HZ = "minFrequency";
/**
+ * Annotation key for minimum lambda in nm.
+ * Value is expected to be an integer.
+ */
+ public static final String AK_MIN_LMDA_NM = "minLambda";
+
+ /**
* Annotation key for maximum frequency in Hz.
* Value is expected be an integer.
*/
public static final String AK_MAX_FREQ_HZ = "maxFrequency";
/**
- * Annotation key for grid in Hz.
+ * Annotation key for maximum lambda in nm.
+ * Value is expected be an integer.
+ */
+ public static final String AK_MAX_LMDA_NM = "maxLambda";
+
+ /**
+ * Annotation key for grid frequency in Hz.
* Value is expected to be an integer.
*/
public static final String AK_GRID_HZ = "grid";
/**
+ * Annotation key for grid lambda in nm.
+ * Value is expected to be an integer.
+ */
+ public static final String AK_GRID_LMDA_NM = "gridLambda";
+
+ /**
* Annotation key for minimum frequency in Hz.
* Value is expected to be an integer.
*/
public static final String AK_TX_MIN_FREQ_HZ = "txMinFrequency";
/**
+ * Annotation key for minimum lambda in nm.
+ * Value is expected to be an integer.
+ */
+ public static final String AK_TX_MIN_LMDA_NM = "txMinLambda";
+
+ /**
* Annotation key for maximum frequency in Hz.
* Value is expected be an integer.
*/
public static final String AK_TX_MAX_FREQ_HZ = "txMaxFrequency";
/**
- * Annotation key for grid in Hz.
+ * Annotation key for maximum lambda in nm.
+ * Value is expected be an integer.
+ */
+ public static final String AK_TX_MAX_LMDA_NM = "txMaxLambda";
+
+ /**
+ * Annotation key for grid frequency in Hz.
* Value is expected to be an integer.
*/
public static final String AK_TX_GRID_HZ = "txGrid";
/**
+ * Annotation key for grid lambda in nm.
+ * Value is expected to be an integer.
+ */
+ public static final String AK_TX_GRID_LMDA_NM = "txGridLambda";
+
+ /**
* Annotation key for minimum frequency in Hz.
* Value is expected to be an integer.
*/
public static final String AK_RX_MIN_FREQ_HZ = "rxMinFrequency";
/**
+ * Annotation key for minimum lambda in nm.
+ * Value is expected to be an integer.
+ */
+ public static final String AK_RX_MIN_LMDA_NM = "rxMinLambda";
+
+ /**
* Annotation key for maximum frequency in Hz.
* Value is expected be an integer.
*/
public static final String AK_RX_MAX_FREQ_HZ = "rxMaxFrequency";
/**
- * Annotation key for grid in Hz.
+ * Annotation key for maximum lambda in nm.
+ * Value is expected be an integer.
+ */
+ public static final String AK_RX_MAX_LMDA_NM = "rxMaxLambda";
+
+ /**
+ * Annotation key for grid frequency in Hz.
* Value is expected to be an integer.
*/
public static final String AK_RX_GRID_HZ = "rxGrid";
/**
+ * Annotation key for grid lambda in nm.
+ * Value is expected to be an integer.
+ */
+ public static final String AK_RX_GRID_LMDA_NM = "rxGridLambda";
+
+ /**
+ * Annotation key for indicating frequency must be used instead of
+ * wavelength for port tuning.
+ * Value is expected to be "enabled" or "disabled"
+ */
+ public static final String AK_USE_FREQ_FEATURE = "useFreqFeature";
+
+ /**
* Annotation key for minimum transmit power in dBm*10.
* Value is expected to be an integer.
*/
@@ -226,35 +288,71 @@
public static final String AK_TX_FREQ_HZ = "txFrequency";
/**
- * Annotation key for transmit offset in Hz.
+ * Annotation key for transmit lambda in nm.
+ * Value is expected be an integer.
+ */
+ public static final String AK_TX_LMDA_NM = "txLambda";
+
+ /**
+ * Annotation key for transmit offset frequency in Hz.
* Value is expected be an integer.
*/
public static final String AK_TX_OFFSET_HZ = "txOffset";
/**
- * Annotation key for transmit grid spacing in Hz.
+ * Annotation key for transmit offset in nm.
+ * Value is expected be an integer.
+ */
+ public static final String AK_TX_OFFSET_LMDA_NM = "txOffsetLambda";
+
+ /**
+ * Annotation key for transmit grid spacing frequency in Hz.
* Value is expected be an integer.
*/
public static final String AK_TX_GRID_SPAN_HZ = "txGridSpan";
/**
+ * Annotation key for transmit grid spacing lambda in nm.
+ * Value is expected be an integer.
+ */
+ public static final String AK_TX_GRID_SPAN_LMDA_NM = "txGridSpanLambda";
+
+ /**
* Annotation key for receive frequency in Hz.
* Value is expected be an integer.
*/
public static final String AK_RX_FREQ_HZ = "rxFrequency";
/**
- * Annotation key for receive offset in Hz.
+ * Annotation key for receive lambda in nm.
+ * Value is expected be an integer.
+ */
+ public static final String AK_RX_LMDA_NM = "rxLambda";
+
+ /**
+ * Annotation key for receive offset frequency in Hz.
* Value is expected be an integer.
*/
public static final String AK_RX_OFFSET_HZ = "rxOffset";
/**
- * Annotation key for receive grid spacing in Hz.
+ * Annotation key for receive offset lambda in nm.
+ * Value is expected be an integer.
+ */
+ public static final String AK_RX_OFFSET_LMDA_NM = "rxOffsetLambda";
+
+ /**
+ * Annotation key for receive grid spacing frequency in Hz.
* Value is expected be an integer.
*/
public static final String AK_RX_GRID_SPAN_HZ = "rxGridSpan";
+ /**
+ * Annotation key for receive grid spacing lambda in nm.
+ * Value is expected be an integer.
+ */
+ public static final String AK_RX_GRID_SPAN_LMDA_NM = "rxGridSpanLambda";
+
/**
* Annotation key for transmit power in dBm*10.
* Value is expected to be an integer.
@@ -326,6 +424,8 @@
private static final Frequency FREQ191_7 = Frequency.ofGHz(191_700);
private static final Frequency FREQ4_4 = Frequency.ofGHz(4_400);
+ private static final long C = 299792458; // speed of light in m/s
+
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected DeviceProviderRegistry providerRegistry;
@@ -348,6 +448,12 @@
label = "Frequency (in seconds) for polling switch Port statistics")
private int portStatsPollFrequency = POLL_INTERVAL;
+ private static final String PROP_FREQ = "propertyFrequency";
+ private static final boolean DEFAULT_PROP_FREQ = true;
+ @Property(name = PROP_FREQ, boolValue = DEFAULT_PROP_FREQ,
+ label = "It indicates frequency must be used instead of wavelength for port tuning.")
+ private static boolean propFreq = DEFAULT_PROP_FREQ;
+
private final Timer timer = new Timer("onos-openflow-portstats-collector");
private HashMap<Dpid, PortStatsCollector> collectors = Maps.newHashMap();
@@ -509,14 +615,45 @@
providerService.updatePortStatistics(deviceId, stats);
}
+ private static String lambdaToAnnotationHz(long lambda) {
+ // ref. OF1.5: wavelength (lambda) as nm * 100
+
+ // f = c / λ
+ // (m/s) * (nm/m) / (nm * 100) * 100
+ // annotations is in Hz
+ return Long.toString(lambda == 0 ? lambda : (C * 1_000_000_000 / lambda * 100));
+ }
+
+ private static String mhzToAnnotationNm(long freqMhz) {
+ // λ = c / f
+ // (m/s) * (nm/m) / (1000000 * 1/s)
+ // annotations is in nm
+ return Long.toString(freqMhz == 0 ? freqMhz : (C * 1_000_000_000 / Frequency.ofMHz(freqMhz).asHz()));
+ }
+
private static String mhzToAnnotation(long freqMhz) {
return Long.toString(Frequency.ofMHz(freqMhz).asHz());
}
+ private static String freqLmdaToAnnotation(long freqLmda, boolean useFreq) {
+ if (useFreq) {
+ if (propFreq) {
+ mhzToAnnotation(freqLmda);
+ } else {
+ mhzToAnnotationNm(freqLmda);
+ }
+ } else if (propFreq) {
+ lambdaToAnnotationHz(freqLmda);
+ }
+ return Double.toString(freqLmda / 100.0);
+ }
+
private Collection<PortStatistics> buildPortStatistics(DeviceId deviceId,
List<OFPortStatsEntry> entries) {
HashSet<PortStatistics> stats = Sets.newHashSet();
+ final Dpid dpid = dpid(deviceId.uri());
+ OpenFlowSwitch sw = controller.getSwitch(dpid);
for (OFPortStatsEntry entry : entries) {
try {
@@ -533,23 +670,46 @@
if (optical.isPresent()) {
long flags = optical.get().getFlags();
+ boolean useFreq = false;
+ for (OFPortDesc pd : sw.getPorts()) {
+ if (pd.getPortNo().equals(entry.getPortNo())) {
+ for (OFPortDescProp prop : pd.getProperties()) {
+ if (prop instanceof OFPortDescPropOptical) {
+ OFPortDescPropOptical oprop = (OFPortDescPropOptical) prop;
+ long supported = oprop.getSupported();
+ int useFreqVal = OFOpticalPortFeaturesSerializerVer14.USE_FREQ_VAL;
+ if ((supported & useFreqVal) != 0) {
+ useFreq = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+
int txTune = OFPortStatsOpticalFlagsSerializerVer14.TX_TUNE_VAL;
long txFreq = optical.get().getTxFreqLmda();
long txOffset = optical.get().getTxOffset();
long txGridSpan = optical.get().getTxGridSpan();
annotations.set(AK_TX_TUNE_FEATURE, ((flags & txTune) != 0) ? "enabled" : "disabled");
- annotations.set(AK_TX_FREQ_HZ, mhzToAnnotation(txFreq));
- annotations.set(AK_TX_OFFSET_HZ, mhzToAnnotation(txOffset));
- annotations.set(AK_TX_GRID_SPAN_HZ, mhzToAnnotation(txGridSpan));
+ annotations.set(propFreq ? AK_TX_FREQ_HZ : AK_TX_LMDA_NM,
+ freqLmdaToAnnotation(txFreq, useFreq));
+ annotations.set(propFreq ? AK_TX_OFFSET_HZ : AK_TX_OFFSET_LMDA_NM,
+ freqLmdaToAnnotation(txOffset, useFreq));
+ annotations.set(propFreq ? AK_TX_GRID_SPAN_HZ : AK_TX_GRID_SPAN_LMDA_NM,
+ freqLmdaToAnnotation(txGridSpan, useFreq));
int rxTune = OFPortStatsOpticalFlagsSerializerVer14.RX_TUNE_VAL;
long rxFreq = optical.get().getRxFreqLmda();
long rxOffset = optical.get().getRxOffset();
long rxGridSpan = optical.get().getRxGridSpan();
annotations.set(AK_RX_TUNE_FEATURE, ((flags & rxTune) != 0) ? "enabled" : "disabled");
- annotations.set(AK_RX_FREQ_HZ, mhzToAnnotation(rxFreq));
- annotations.set(AK_RX_OFFSET_HZ, mhzToAnnotation(rxOffset));
- annotations.set(AK_RX_GRID_SPAN_HZ, mhzToAnnotation(rxGridSpan));
+ annotations.set(propFreq ? AK_RX_FREQ_HZ : AK_RX_LMDA_NM,
+ freqLmdaToAnnotation(rxFreq, useFreq));
+ annotations.set(propFreq ? AK_RX_OFFSET_HZ : AK_RX_OFFSET_LMDA_NM,
+ freqLmdaToAnnotation(rxOffset, useFreq));
+ annotations.set(propFreq ? AK_RX_GRID_SPAN_HZ : AK_RX_GRID_SPAN_LMDA_NM,
+ freqLmdaToAnnotation(rxGridSpan, useFreq));
int txPwrVal = OFPortStatsOpticalFlagsSerializerVer14.TX_PWR_VAL;
int txPwr = optical.get().getTxPwr();
@@ -986,20 +1146,6 @@
return builder;
}
- private String mhzToAnnotation(long freqMhz) {
- return OpenFlowDeviceProvider.mhzToAnnotation(freqMhz);
- }
-
- private String lambdaToAnnotationHz(long lambda) {
- // ref. OF1.5: wavelength (lambda) as nm * 100
-
- long c = 299792458; // speed of light in m/s
- // f = c / λ
- // (m/s) * (nm/m) / (nm * 100) * 100
- // annotations is in Hz
- return Long.toString(lambda == 0 ? lambda : (c * 1_000_000_000 / lambda * 100));
- }
-
private PortDescription buildPortDescription14(OFPortDesc port) {
PortNumber portNo = PortNumber.portNumber(port.getPortNo().getPortNumber());
boolean enabled =
@@ -1050,57 +1196,36 @@
((supported & rxTune) != 0) ? "enabled" : "disabled");
// wire value for OFOpticalPortFeatures.USE_FREQ
- long useFreq = OFOpticalPortFeaturesSerializerVer14.USE_FREQ_VAL;
- if ((supported & useFreq) != 0) {
- // unit is in Frequency Mhz
- annotations.set(AK_RX_MIN_FREQ_HZ, mhzToAnnotation(rxMin));
- annotations.set(AK_RX_MAX_FREQ_HZ, mhzToAnnotation(rxMax));
- annotations.set(AK_RX_GRID_HZ, mhzToAnnotation(rxGrid));
+ boolean useFreq = (supported & OFOpticalPortFeaturesSerializerVer14.USE_FREQ_VAL) != 0;
+ annotations.set(AK_USE_FREQ_FEATURE, useFreq ? "enabled" : "disabled");
- annotations.set(AK_TX_MIN_FREQ_HZ, mhzToAnnotation(txMin));
- annotations.set(AK_TX_MAX_FREQ_HZ, mhzToAnnotation(txMax));
- annotations.set(AK_TX_GRID_HZ, mhzToAnnotation(txGrid));
+ annotations.set(propFreq ? AK_RX_MIN_FREQ_HZ : AK_RX_MIN_LMDA_NM,
+ freqLmdaToAnnotation(rxMin, useFreq));
+ annotations.set(propFreq ? AK_RX_MAX_FREQ_HZ : AK_RX_MAX_LMDA_NM,
+ freqLmdaToAnnotation(rxMax, useFreq));
+ annotations.set(propFreq ? AK_RX_GRID_HZ : AK_RX_GRID_LMDA_NM,
+ freqLmdaToAnnotation(rxGrid, useFreq));
- // FIXME pretty confident this is not going to happen
- // unless Device models Tx/Rx ports as separate port
- if (rxMin == txMin) {
- annotations.set(AK_MIN_FREQ_HZ,
- mhzToAnnotation(rxMin));
- }
- if (rxMax == txMax) {
- annotations.set(AK_MAX_FREQ_HZ,
- mhzToAnnotation(rxMax));
- }
- if (rxGrid == txGrid) {
- annotations.set(AK_GRID_HZ,
- mhzToAnnotation(rxGrid));
- }
+ annotations.set(propFreq ? AK_TX_MIN_FREQ_HZ : AK_TX_MIN_LMDA_NM,
+ freqLmdaToAnnotation(txMin, useFreq));
+ annotations.set(propFreq ? AK_TX_MAX_FREQ_HZ : AK_TX_MAX_LMDA_NM,
+ freqLmdaToAnnotation(txMax, useFreq));
+ annotations.set(propFreq ? AK_TX_GRID_HZ : AK_TX_GRID_LMDA_NM,
+ freqLmdaToAnnotation(txGrid, useFreq));
- } else {
- // unit is in Lambda nm * 100
- annotations.set(AK_RX_MIN_FREQ_HZ, lambdaToAnnotationHz(rxMin));
- annotations.set(AK_RX_MAX_FREQ_HZ, lambdaToAnnotationHz(rxMax));
- annotations.set(AK_RX_GRID_HZ, lambdaToAnnotationHz(rxGrid));
-
- annotations.set(AK_TX_MIN_FREQ_HZ, lambdaToAnnotationHz(txMin));
- annotations.set(AK_TX_MAX_FREQ_HZ, lambdaToAnnotationHz(txMax));
- annotations.set(AK_TX_GRID_HZ, lambdaToAnnotationHz(txGrid));
-
- // FIXME pretty confident this is not going to happen
- // unless Device models Tx/Rx ports as separate port
- if (rxMin == txMin) {
- annotations.set(AK_MIN_FREQ_HZ,
- lambdaToAnnotationHz(rxMin));
- }
- if (rxMax == txMax) {
- annotations.set(AK_MAX_FREQ_HZ,
- lambdaToAnnotationHz(rxMax));
- }
- if (rxGrid == txGrid) {
- annotations.set(AK_GRID_HZ,
- lambdaToAnnotationHz(rxGrid));
- }
-
+ // FIXME pretty confident this is not going to happen
+ // unless Device models Tx/Rx ports as separate port
+ if (rxMin == txMin) {
+ annotations.set(propFreq ? AK_MIN_FREQ_HZ : AK_MIN_LMDA_NM,
+ freqLmdaToAnnotation(rxMin, useFreq));
+ }
+ if (rxMax == txMax) {
+ annotations.set(propFreq ? AK_MAX_FREQ_HZ : AK_MAX_LMDA_NM,
+ freqLmdaToAnnotation(rxMax, useFreq));
+ }
+ if (rxGrid == txGrid) {
+ annotations.set(propFreq ? AK_GRID_HZ : AK_GRID_LMDA_NM,
+ freqLmdaToAnnotation(rxGrid, useFreq));
}
int txPwr = OFOpticalPortFeaturesSerializerVer14.TX_PWR_VAL;
diff --git a/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/GroupStatsCollector.java b/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/GroupStatsCollector.java
index 5433a4d..4a5c872 100644
--- a/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/GroupStatsCollector.java
+++ b/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/GroupStatsCollector.java
@@ -19,6 +19,7 @@
import org.onlab.util.Timer;
import org.onosproject.openflow.controller.OpenFlowSwitch;
import org.onosproject.openflow.controller.RoleState;
+import org.projectfloodlight.openflow.protocol.OFCapabilities;
import org.projectfloodlight.openflow.protocol.OFGroupDescStatsRequest;
import org.projectfloodlight.openflow.protocol.OFGroupStatsRequest;
import org.projectfloodlight.openflow.types.OFGroup;
@@ -59,7 +60,7 @@
public void run(Timeout timeout) throws Exception {
log.trace("Collecting stats for {}", sw.getStringId());
- sendGroupStatisticRequest();
+ sendGroupStatisticRequests();
if (!this.stopTimer) {
log.trace("Scheduling stats collection in {} seconds for {}",
@@ -69,7 +70,23 @@
}
}
- private void sendGroupStatisticRequest() {
+ private void sendGroupDescStatisticRequest(long xid) {
+ OFGroupDescStatsRequest descStatsRequest =
+ sw.factory().buildGroupDescStatsRequest()
+ .setXid(xid)
+ .build();
+ sw.sendMsg(descStatsRequest);
+ }
+
+ private void sendGroupStatisticRequest(long xid) {
+ OFGroupStatsRequest statsRequest = sw.factory().buildGroupStatsRequest()
+ .setGroup(OFGroup.ALL)
+ .setXid(xid)
+ .build();
+ sw.sendMsg(statsRequest);
+ }
+
+ private void sendGroupStatisticRequests() {
if (log.isTraceEnabled()) {
log.trace("sendGroupStatistics {}:{}", sw.getStringId(), sw.getRole());
}
@@ -79,19 +96,15 @@
if (!sw.isConnected()) {
return;
}
- long statsXid = OpenFlowGroupProvider.getXidAndAdd(2);
- OFGroupStatsRequest statsRequest = sw.factory().buildGroupStatsRequest()
- .setGroup(OFGroup.ALL)
- .setXid(statsXid)
- .build();
- sw.sendMsg(statsRequest);
- long descXid = statsXid + 1;
- OFGroupDescStatsRequest descStatsRequest =
- sw.factory().buildGroupDescStatsRequest()
- .setXid(descXid)
- .build();
- sw.sendMsg(descStatsRequest);
+ if (sw.features().getCapabilities().contains(OFCapabilities.GROUP_STATS)) {
+ long xid = OpenFlowGroupProvider.getXidAndAdd(2);
+ sendGroupDescStatisticRequest(xid);
+ sendGroupStatisticRequest(xid + 1);
+ } else {
+ long xid = OpenFlowGroupProvider.getXidAndAdd(1);
+ sendGroupDescStatisticRequest(xid);
+ }
}
public void adjustRate(int pollInterval) {
diff --git a/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProvider.java b/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProvider.java
index 0f55b41..b536fda 100644
--- a/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProvider.java
+++ b/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/OpenFlowGroupProvider.java
@@ -65,7 +65,6 @@
import org.onosproject.openflow.controller.RoleState;
import org.osgi.service.component.ComponentContext;
import org.projectfloodlight.openflow.protocol.OFBucketCounter;
-import org.projectfloodlight.openflow.protocol.OFCapabilities;
import org.projectfloodlight.openflow.protocol.OFErrorMsg;
import org.projectfloodlight.openflow.protocol.OFErrorType;
import org.projectfloodlight.openflow.protocol.OFGroupDescStatsEntry;
@@ -413,7 +412,7 @@
if (sw == null) {
return;
}
- if (isGroupSupported(sw) && sw.features().getCapabilities().contains(OFCapabilities.GROUP_STATS)) {
+ if (isGroupSupported(sw)) {
GroupStatsCollector gsc = new GroupStatsCollector(sw, groupPollInterval);
stopCollectorIfNeeded(collectors.put(dpid, gsc));
gsc.start();
diff --git a/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelProvider.java b/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelProvider.java
index a2d21bc..d1afdc6 100644
--- a/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelProvider.java
+++ b/providers/pcep/tunnel/src/main/java/org/onosproject/provider/pcep/tunnel/impl/PcepTunnelProvider.java
@@ -217,7 +217,7 @@
TunnelProviderService service;
- HashMap<String, TunnelId> tunnelMap = new HashMap<String, TunnelId>();
+ HashMap<String, TunnelId> tunnelMap = new HashMap<>();
HashMap<TunnelId, TunnelStatistics> tunnelStatisticsMap = new HashMap<>();
private HashMap<String, TunnelStatsCollector> collectors = Maps.newHashMap();
@@ -885,7 +885,7 @@
* @return list of ERO subobjects
*/
private LinkedList<PcepValueType> createPcepPath(Path path) {
- LinkedList<PcepValueType> llSubObjects = new LinkedList<PcepValueType>();
+ LinkedList<PcepValueType> llSubObjects = new LinkedList<>();
List<Link> listLink = path.links();
ConnectPoint source = null;
ConnectPoint destination = null;
@@ -952,7 +952,7 @@
return null;
}
- LinkedList<PcepValueType> llOptionalTlv = new LinkedList<PcepValueType>();
+ LinkedList<PcepValueType> llOptionalTlv = new LinkedList<>();
// set PathSetupTypeTlv of SRP object
tlv = new PathSetupTypeTlv(lspType.type());
@@ -962,8 +962,8 @@
PcepSrpObject srpobj = pc.factory().buildSrpObject().setSrpID(srpId).setRFlag(false)
.setOptionalTlv(llOptionalTlv).build();
- llOptionalTlv = new LinkedList<PcepValueType>();
- LinkedList<PcInitiatedLspRequest> llPcInitiatedLspRequestList = new LinkedList<PcInitiatedLspRequest>();
+ llOptionalTlv = new LinkedList<>();
+ LinkedList<PcInitiatedLspRequest> llPcInitiatedLspRequestList = new LinkedList<>();
// set LSP identifiers TLV
short localLspId = 0;
@@ -1089,7 +1089,7 @@
int srpId = SrpIdGenerators.create();
PcepValueType tlv;
- LinkedList<PcepValueType> llOptionalTlv = new LinkedList<PcepValueType>();
+ LinkedList<PcepValueType> llOptionalTlv = new LinkedList<>();
// set PathSetupTypeTlv of SRP object
tlv = new PathSetupTypeTlv(LspType.valueOf(tunnel.annotations().value(LSP_SIG_TYPE))
@@ -1100,8 +1100,8 @@
PcepSrpObject srpobj = pc.factory().buildSrpObject().setSrpID(srpId).setRFlag(true)
.setOptionalTlv(llOptionalTlv).build();
- llOptionalTlv = new LinkedList<PcepValueType>();
- LinkedList<PcInitiatedLspRequest> llPcInitiatedLspRequestList = new LinkedList<PcInitiatedLspRequest>();
+ llOptionalTlv = new LinkedList<>();
+ LinkedList<PcInitiatedLspRequest> llPcInitiatedLspRequestList = new LinkedList<>();
tlv = new SymbolicPathNameTlv(tunnel.tunnelName().value().getBytes());
llOptionalTlv.add(tlv);
@@ -1183,8 +1183,8 @@
llSubObjects = createPcepPath(path);
}
- LinkedList<PcepValueType> llOptionalTlv = new LinkedList<PcepValueType>();
- LinkedList<PcepUpdateRequest> llUpdateRequestList = new LinkedList<PcepUpdateRequest>();
+ LinkedList<PcepValueType> llOptionalTlv = new LinkedList<>();
+ LinkedList<PcepUpdateRequest> llUpdateRequestList = new LinkedList<>();
// set PathSetupTypeTlv of SRP object
tlv = new PathSetupTypeTlv(lspSigType.type());
@@ -1194,7 +1194,7 @@
PcepSrpObject srpobj = pc.factory().buildSrpObject().setSrpID(srpId).setRFlag(false)
.setOptionalTlv(llOptionalTlv).build();
- llOptionalTlv = new LinkedList<PcepValueType>();
+ llOptionalTlv = new LinkedList<>();
// Lsp Identifier tlv is required for all modes of lsp
String localLspIdString = tunnel.annotations().value(LOCAL_LSP_ID);
@@ -1609,7 +1609,7 @@
DefaultTunnelDescription td;
SparseAnnotations annotations = null;
State tunnelState = PcepLspStatus.getTunnelStatusFromLspStatus(PcepLspStatus.values()[lspObj.getOFlag()]);
- if (tunnel == null) {
+ if (tunnel == null && pathNameTlv != null) {
if (lspObj.getRFlag()) {
/*
* If PCC sends remove message and for any reason PCE does not have that entry, simply discard the
@@ -1661,7 +1661,7 @@
if (mastershipService.isLocalMaster(deviceId)) {
TunnelId tId = tunnelAdded(td, tunnelState);
Tunnel tunnelInserted = new DefaultTunnel(providerId, tunnelEndPointSrc, tunnelEndPointDst, MPLS,
- tunnelState, new GroupId(0), tId, TunnelName.tunnelName(String.valueOf(pathNameTlv
+ tunnelState, new GroupId(0), tId, TunnelName.tunnelName(Arrays.toString(pathNameTlv
.getValue())), path, labelStack, annotations);
PcepTunnelData pcepTunnelData = new PcepTunnelData(tunnelInserted, path, LSP_STATE_RPT);
diff --git a/providers/rest/device/src/main/java/org/onosproject/provider/rest/device/impl/RestDeviceProvider.java b/providers/rest/device/src/main/java/org/onosproject/provider/rest/device/impl/RestDeviceProvider.java
index 3e97a3d..5e33c1d 100644
--- a/providers/rest/device/src/main/java/org/onosproject/provider/rest/device/impl/RestDeviceProvider.java
+++ b/providers/rest/device/src/main/java/org/onosproject/provider/rest/device/impl/RestDeviceProvider.java
@@ -164,7 +164,6 @@
@Deactivate
public void deactivate() {
cfgService.removeListener(configListener);
- controller.getDevices().keySet().forEach(this::deviceRemoved);
providerRegistry.unregister(this);
providerService = null;
factories.forEach(cfgService::unregisterConfigFactory);
diff --git a/tools/build/conf/src/main/java/org/onosproject/buckdaemon/BuckDaemon.java b/tools/build/conf/src/main/java/org/onosproject/buckdaemon/BuckDaemon.java
index 56deadd..f3166b1 100644
--- a/tools/build/conf/src/main/java/org/onosproject/buckdaemon/BuckDaemon.java
+++ b/tools/build/conf/src/main/java/org/onosproject/buckdaemon/BuckDaemon.java
@@ -175,7 +175,11 @@
try {
try {
socket.setSoTimeout(1_000); //reads should time out after 1 second
- BuckTaskContext context = new BuckTaskContext(socket.getInputStream());
+ BuckTaskContext context = BuckTaskContext.createBuckTaskContext(socket.getInputStream());
+ if (context == null) {
+ socket.close();
+ return;
+ }
String taskName = context.taskName();
BuckTask task = tasks.get(taskName);
diff --git a/tools/build/conf/src/main/java/org/onosproject/buckdaemon/BuckTaskContext.java b/tools/build/conf/src/main/java/org/onosproject/buckdaemon/BuckTaskContext.java
index b8d189c..2cfb35d 100644
--- a/tools/build/conf/src/main/java/org/onosproject/buckdaemon/BuckTaskContext.java
+++ b/tools/build/conf/src/main/java/org/onosproject/buckdaemon/BuckTaskContext.java
@@ -36,10 +36,16 @@
private final ImmutableList<String> input;
private final List<String> output;
- BuckTaskContext(InputStream inputStream) throws IOException {
+ public static BuckTaskContext createBuckTaskContext(InputStream inputStream) throws IOException {
ImmutableList<String> lines = slurpInput(inputStream);
- checkArgument(lines.size() >= 1 && !lines.get(0).isEmpty(),
- "Request must contain at least task type");
+ if (lines.size() == 0) {
+ return null;
+ } else {
+ return new BuckTaskContext(lines);
+ }
+ }
+
+ BuckTaskContext(ImmutableList<String> lines) {
this.taskName = lines.get(0);
this.input = lines.subList(1, lines.size());
this.output = Lists.newArrayList();
@@ -55,7 +61,7 @@
private static ImmutableList<String> slurpInput(InputStream stream) throws IOException {
ImmutableList.Builder<String> lines = ImmutableList.builder();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(stream));
- while(true) {
+ while (true) {
String line = bufferedReader.readLine();
if (line == null || line.trim().length() == 0) {
// Empty line or EOF
diff --git a/tools/build/onos-buck b/tools/build/onos-buck
index b44dc17..7312f72 100755
--- a/tools/build/onos-buck
+++ b/tools/build/onos-buck
@@ -5,8 +5,8 @@
set -e
-BUCK_URL="http://repo1.maven.org/maven2/org/onosproject/onos-buck/v2018.01.10.02/buck-v2018.01.10.02.zip"
-BUCK_SHA="04ac8754c6ca5957ac68a75544d1bd0c9d17b908"
+BUCK_URL="http://repo1.maven.org/maven2/org/onosproject/onos-buck/v2018.01.17.01/buck-v2018.01.17.01.zip"
+BUCK_SHA="4a70a84ef40a06762a7248db25590696e80af9fe"
[ "-U" = "$1" ] && shift && FORCE_UPDATE=True
diff --git a/tools/build/onos-upload-bits b/tools/build/onos-upload-bits
index 367fc1d..d74deb8 100755
--- a/tools/build/onos-upload-bits
+++ b/tools/build/onos-upload-bits
@@ -8,8 +8,6 @@
[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
. $ONOS_ROOT/tools/build/envDefaults
-#FIXME need to export s3Creds
-
# Stage the onos tar in /tmp
rm -f $ONOS_TAR
cp $(onos-buck build onos --show-output | tail -1 | cut -d\ -f2) $ONOS_TAR
@@ -25,4 +23,15 @@
rm -f $ONOS_TEST_TAR
cp $(onos-buck build //:onos-test --show-output | tail -1 | cut -d\ -f2) $ONOS_TEST_TAR
-onosUploadBits.py ${ONOS_VERSION%-*}
+# use this to upload to AWS
+# onosUploadBits.py ${ONOS_VERSION%-*}
+
+# use this to upload to maven central
+if echo $ONOS_VERSION | grep '-'; then
+ echo "ONOS version $ONOS_VERSION is a beta or RC. Skipping publishing .tar.gz files"
+ exit 0
+fi
+UPLOAD_BASE="https://oss.sonatype.org/service/local/staging/deploy/maven2/org/onosproject/onos-releases/$ONOS_VERSION"
+curl -v -u "$SONATYPE_USER:$SONATYPE_PASSWORD" --upload-file $ONOS_TAR $UPLOAD_BASE/onos-$ONOS_VERSION.tar.gz
+curl -v -u "$SONATYPE_USER:$SONATYPE_PASSWORD" --upload-file $ONOS_TEST_TAR $UPLOAD_BASE/onos-test-$ONOS_VERSION.tar.gz
+curl -v -u "$SONATYPE_USER:$SONATYPE_PASSWORD" --upload-file $ONOS_ZIP $UPLOAD_BASE/onos-$ONOS_VERSION.zip
\ No newline at end of file
diff --git a/tools/build/onos-upload-docs b/tools/build/onos-upload-docs
index 79986b6..1dc750a 100755
--- a/tools/build/onos-upload-docs
+++ b/tools/build/onos-upload-docs
@@ -13,6 +13,24 @@
docs=$(onos-buck build //docs:external --show-output 2>/dev/null | tail -1 | cut -d\ -f2)
+ONOS_VERSION_STRING=$ONOS_VERSION
+if echo $ONOS_VERSION_STRING | grep '-'; then
+ echo "ONOS version $ONOS_VERSION_STRING is a beta or RC. Skipping"
+ exit 0
+fi
+
+scp $remote:/var/www/api/index.html /tmp/index.html
+CURRENT_VERSION_STRING=`grep URL /tmp/index.html | sed "s%.*URL=/%%" | sed "s%/.*%%"`
+CURRENT_VERSION_SPLIT=(${CURRENT_VERSION_STRING//\./ })
+ONOS_VERSION_SPLIT=(${ONOS_VERSION_STRING//\./ })
+
+if (( ${ONOS_VERSION_SPLIT[1]} >= ${CURRENT_VERSION_SPLIT[1]} )); then
+ echo "Should replace current version $CURRENT_VERSION_STRING with new ONOS version $ONOS_VERSION_STRING"
+else
+ echo "Not replacing current version $CURRENT_VERSION_STRING with ONOS version $ONOS_VERSION_STRING"
+ exit 0
+fi
+
scp $docs $remote:/tmp/onos-apidocs-$ONOS_VERSION.tar.gz
ssh $remote "
mkdir -p /var/www/api/$ONOS_VERSION
diff --git a/tools/dev/bash_profile b/tools/dev/bash_profile
index 6d38269..3dc3f89 100644
--- a/tools/dev/bash_profile
+++ b/tools/dev/bash_profile
@@ -195,7 +195,11 @@
# ON.Lab shared test cell warden address
export CELL_WARDEN="10.192.19.72"
-export CELL_SLAVES="$CELL_WARDEN 10.192.19.71 10.192.19.70"
+export CELL_SLAVE_1=$CELL_WARDEN
+export CELL_SLAVE_2="10.192.19.71"
+export CELL_SLAVE_3="10.192.19.70"
+export CELL_SLAVE_4="10.192.19.77"
+export CELL_SLAVES="$CELL_SLAVE_1 $CELL_SLAVE_2 $CELL_SLAVE_3 $CELL_SLAVE_4"
# Clears cell environment
function clearCell {
diff --git a/tools/dev/mininet/bmv2.py b/tools/dev/mininet/bmv2.py
index b1824a3..87ed1ba 100644
--- a/tools/dev/mininet/bmv2.py
+++ b/tools/dev/mininet/bmv2.py
@@ -2,9 +2,11 @@
import socket
import re
import json
+import threading
import urllib2
import time
+from contextlib import closing
from mininet.log import info, warn, error
from mininet.node import Switch, Host
@@ -13,12 +15,13 @@
error("ERROR: environment var $ONOS_ROOT not set")
exit()
-BMV2_TARGET = 'simple_switch_grpc'
+SIMPLE_SWITCH_GRPC = 'simple_switch_grpc'
ONOS_ROOT = os.environ["ONOS_ROOT"]
-CPU_PORT = 255
PKT_BYTES_TO_DUMP = 80
VALGRIND_PREFIX = 'valgrind --leak-check=yes'
-SWITCH_START_TIMEOUT = 5 #seconds
+SWITCH_START_TIMEOUT = 5 # seconds
+BMV2_LOG_LINES = 5
+
def parseBoolean(value):
if value in ['1', 1, 'true', 'True']:
@@ -27,6 +30,34 @@
return False
+def pickUnusedPort():
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ s.bind(('localhost', 0))
+ addr, port = s.getsockname()
+ s.close()
+ return port
+
+
+def writeToFile(path, value):
+ with open(path, "w") as f:
+ f.write(str(value))
+
+
+def watchDog(sw):
+ while True:
+ if sw.stopped:
+ return
+ with closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as s:
+ if s.connect_ex(('127.0.0.1', sw.grpcPort)) == 0:
+ time.sleep(1)
+ else:
+ warn("\n*** WARN: BMv2 instance %s (%s) died!\n"
+ % (sw.deviceId, sw.name))
+ sw.printBmv2Log()
+ print ("-" * 80) + "\n"
+ return
+
+
class ONOSHost(Host):
def __init__(self, name, inNamespace=True, **params):
Host.__init__(self, name, inNamespace=inNamespace, **params)
@@ -34,7 +65,7 @@
def config(self, **params):
r = super(Host, self).config(**params)
for off in ["rx", "tx", "sg"]:
- cmd = "/sbin/ethtool --offload %s %s off"\
+ cmd = "/sbin/ethtool --offload %s %s off" \
% (self.defaultIntf(), off)
self.cmd(cmd)
# disable IPv6
@@ -48,83 +79,58 @@
"""BMv2 software switch with gRPC server"""
deviceId = 0
- instanceCount = 0
- def __init__(self, name, json=None, debugger=False, loglevel="warn", elogger=False,
- persistent=False, grpcPort=None, thriftPort=None, netcfg=True, dryrun=False,
- pipeconfId="", pktdump=False, valgrind=False, netcfgDelay=0,
- **kwargs):
+ def __init__(self, name, json=None, debugger=False, loglevel="warn",
+ elogger=False, grpcPort=None, cpuPort=255,
+ thriftPort=None, netcfg=True, dryrun=False, pipeconfId="",
+ pktdump=False, valgrind=False, injectPorts=False, **kwargs):
Switch.__init__(self, name, **kwargs)
- self.grpcPort = ONOSBmv2Switch.pickUnusedPort() if not grpcPort else grpcPort
- self.thriftPort = ONOSBmv2Switch.pickUnusedPort() if not thriftPort else thriftPort
+ self.grpcPort = pickUnusedPort() if not grpcPort else grpcPort
+ self.thriftPort = pickUnusedPort() if not thriftPort else thriftPort
if self.dpid:
self.deviceId = int(self.dpid, 0 if 'x' in self.dpid else 16)
else:
self.deviceId = ONOSBmv2Switch.deviceId
ONOSBmv2Switch.deviceId += 1
+ self.cpuPort = cpuPort
self.json = json
self.debugger = parseBoolean(debugger)
self.loglevel = loglevel
- self.logfile = '/tmp/bmv2-%d.log' % self.deviceId
+ # Important: Mininet removes all /tmp/*.log files in case of exceptions.
+ # We want to be able to see the bmv2 log if anything goes wrong, hence
+ # avoid the .log extension.
+ self.logfile = '/tmp/bmv2-%d-log' % self.deviceId
self.elogger = parseBoolean(elogger)
self.pktdump = parseBoolean(pktdump)
- self.persistent = parseBoolean(persistent)
self.netcfg = parseBoolean(netcfg)
self.dryrun = parseBoolean(dryrun)
self.valgrind = parseBoolean(valgrind)
- self.netcfgDelay = netcfgDelay
self.netcfgfile = '/tmp/bmv2-%d-netcfg.json' % self.deviceId
self.pipeconfId = pipeconfId
- if persistent:
- self.exectoken = "/tmp/bmv2-%d-exec-token" % self.deviceId
- self.cmd("touch %s" % self.exectoken)
- # Store thrift port for future uses.
- self.cmd("echo %d > /tmp/bmv2-%d-grpc-port" % (self.grpcPort, self.deviceId))
-
- if 'longitude' in kwargs:
- self.longitude = kwargs['longitude']
- else:
- self.longitude = None
-
- if 'latitude' in kwargs:
- self.latitude = kwargs['latitude']
- else:
- self.latitude = None
-
+ self.injectPorts = parseBoolean(injectPorts)
+ self.longitude = kwargs['longitude'] if 'longitude' in kwargs else None
+ self.latitude = kwargs['latitude'] if 'latitude' in kwargs else None
self.onosDeviceId = "device:bmv2:%d" % self.deviceId
+ self.logfd = None
+ self.bmv2popen = None
+ self.stopped = False
- @classmethod
- def pickUnusedPort(cls):
- s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- s.bind(('localhost', 0))
- addr, port = s.getsockname()
- s.close()
- return port
+ # Remove files from previous executions
+ self.cleanupTmpFiles()
+
+ writeToFile("/tmp/bmv2-%d-grpc-port" % self.deviceId, self.grpcPort)
+ writeToFile("/tmp/bmv2-%d-thrift-port" % self.deviceId, self.thriftPort)
def getSourceIp(self, dstIP):
"""
- Queries the Linux routing table to get the source IP that can talk with dstIP, and vice
- versa.
+ Queries the Linux routing table to get the source IP that can talk with
+ dstIP, and vice versa.
"""
ipRouteOut = self.cmd('ip route get %s' % dstIP)
r = re.search(r"src (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})", ipRouteOut)
return r.group(1) if r else None
def getDeviceConfig(self, srcIP):
- portData = {}
- portId = 1
- for intfName in self.intfNames():
- if intfName == 'lo':
- continue
- portData[str(portId)] = {
- "number": portId,
- "name": intfName,
- "enabled": True,
- "removed": False,
- "type": "copper",
- "speed": 10000
- }
- portId += 1
basicCfg = {
"driver": "bmv2"
@@ -141,15 +147,36 @@
"port": self.grpcPort,
"deviceId": self.deviceId,
"deviceKeyId": "p4runtime:%s" % self.onosDeviceId
+ },
+ "gnmi": {
+ "ip": srcIP,
+ "port": self.grpcPort
}
},
"piPipeconf": {
"piPipeconfId": self.pipeconfId
},
- "basic": basicCfg,
- "ports": portData
+ "basic": basicCfg
}
+ if(self.injectPorts):
+ portData = {}
+ portId = 1
+ for intfName in self.intfNames():
+ if intfName == 'lo':
+ continue
+ portData[str(portId)] = {
+ "number": portId,
+ "name": intfName,
+ "enabled": True,
+ "removed": False,
+ "type": "copper",
+ "speed": 10000
+ }
+ portId += 1
+
+ cfgData['ports'] = portData
+
return cfgData
def doOnosNetcfg(self, controllerIP):
@@ -158,7 +185,7 @@
"""
srcIP = self.getSourceIp(controllerIP)
if not srcIP:
- warn("WARN: unable to get device IP address, won't do onos-netcfg")
+ warn("*** WARN: unable to get switch IP address, won't do netcfg\n")
return
cfgData = {
@@ -177,19 +204,52 @@
url = 'http://%s:8181/onos/v1/network/configuration/' % controllerIP
# Instantiate password manager for HTTP auth
pm = urllib2.HTTPPasswordMgrWithDefaultRealm()
- pm.add_password(None, url, os.environ['ONOS_WEB_USER'], os.environ['ONOS_WEB_PASS'])
- urllib2.install_opener(urllib2.build_opener(urllib2.HTTPBasicAuthHandler(pm)))
+ pm.add_password(None, url,
+ os.environ['ONOS_WEB_USER'],
+ os.environ['ONOS_WEB_PASS'])
+ urllib2.install_opener(urllib2.build_opener(
+ urllib2.HTTPBasicAuthHandler(pm)))
# Push config data to controller
- req = urllib2.Request(url, json.dumps(cfgData), {'Content-Type': 'application/json'})
+ req = urllib2.Request(url, json.dumps(cfgData),
+ {'Content-Type': 'application/json'})
try:
f = urllib2.urlopen(req)
print f.read()
f.close()
except urllib2.URLError as e:
- warn("WARN: unable to push config to ONOS (%s)" % e.reason)
+ warn("*** WARN: unable to push config to ONOS (%s)\n" % e.reason)
def start(self, controllers):
- args = [BMV2_TARGET, '--device-id %s' % str(self.deviceId)]
+ bmv2Args = [SIMPLE_SWITCH_GRPC] + self.grpcTargetArgs()
+ if self.valgrind:
+ bmv2Args = VALGRIND_PREFIX.split() + bmv2Args
+
+ cmdString = " ".join(bmv2Args)
+
+ if self.dryrun:
+ info("\n*** DRY RUN (not executing bmv2)")
+
+ info("\nStarting BMv2 target: %s\n" % cmdString)
+
+ try:
+ if not self.dryrun:
+ # Start the switch
+ self.logfd = open(self.logfile, "w")
+ self.bmv2popen = self.popen(cmdString,
+ stdout=self.logfd,
+ stderr=self.logfd)
+ self.waitBmv2Start()
+ # We want to be notified if BMv2 dies...
+ threading.Thread(target=watchDog, args=[self]).start()
+
+ self.doOnosNetcfg(self.controllerIp(controllers))
+ except Exception as ex:
+ self.killBmv2()
+ self.printBmv2Log()
+ raise ex
+
+ def grpcTargetArgs(self):
+ args = ['--device-id %s' % str(self.deviceId)]
for port, intf in self.intfs.items():
if not intf.IP():
args.append('-i %d@%s' % (port, intf.name))
@@ -200,74 +260,73 @@
args.append('--debugger')
args.append('--log-console')
if self.pktdump:
- args.append('--pcap --dump-packet-data %d' % PKT_BYTES_TO_DUMP)
+ args.append('--pcap --dump-packet-data %s' % PKT_BYTES_TO_DUMP)
args.append('-L%s' % self.loglevel)
- args.append('--thrift-port %d' % self.thriftPort)
+ args.append('--thrift-port %s' % self.thriftPort)
if not self.json:
args.append('--no-p4')
else:
args.append(self.json)
-
- # gRPC target-specific options.
+ # gRPC target-specific options
args.append('--')
- args.append('--cpu-port %d' % CPU_PORT)
- args.append('--grpc-server-addr 0.0.0.0:%d' % self.grpcPort)
+ args.append('--cpu-port %s' % self.cpuPort)
+ args.append('--grpc-server-addr 0.0.0.0:%s' % self.grpcPort)
+ return args
- bmv2cmd = " ".join(args)
- if self.valgrind:
- bmv2cmd = "%s %s" % (VALGRIND_PREFIX, bmv2cmd)
- if self.dryrun:
- info("\n*** DRY RUN (not executing bmv2)")
- info("\nStarting BMv2 target: %s\n" % bmv2cmd)
+ def waitBmv2Start(self):
+ # Wait for switch to open gRPC port, before sending ONOS the netcfg.
+ # Include time-out just in case something hangs.
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ endtime = time.time() + SWITCH_START_TIMEOUT
+ while True:
+ result = sock.connect_ex(('127.0.0.1', self.grpcPort))
+ if result == 0:
+ # The port is open. Let's go! (Close socket first)
+ sock.close()
+ break
+ # Port is not open yet. If there is time, we wait a bit.
+ if endtime > time.time():
+ time.sleep(0.2)
+ else:
+ # Time's up.
+ raise Exception("Switch did not start before timeout")
- if self.persistent:
- # Bash loop to re-exec the switch if it crashes.
- bmv2cmd = "(while [ -e {} ]; do {} ; sleep 1; done;)".format(self.exectoken, bmv2cmd)
+ def printBmv2Log(self):
+ if os.path.isfile(self.logfile):
+ print "-" * 80
+ print "BMv2 %d log (from %s):" % (self.deviceId, self.logfile)
+ with open(self.logfile, 'r') as f:
+ lines = f.readlines()
+ if len(lines) > BMV2_LOG_LINES:
+ print "..."
+ for line in lines[-BMV2_LOG_LINES:]:
+ print line.rstrip()
- cmdStr = "{} > {} 2>&1 &".format(bmv2cmd, self.logfile)
-
- # Starts the switch.
- if not self.dryrun:
- out = self.cmd(cmdStr)
- if out:
- print out
- if self.netcfg:
- time.sleep(self.netcfgDelay)
-
- try: # onos.py
+ @staticmethod
+ def controllerIp(controllers):
+ try:
+ # onos.py
clist = controllers[0].nodes()
except AttributeError:
clist = controllers
assert len(clist) > 0
- cip = clist[0].IP()
+ return clist[0].IP()
- # Wait for switch to open gRPC port, before sending ONOS the netcfg.json.
- # Include time-out just in case something hangs.
- if not self.dryrun:
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- endtime = time.time() + SWITCH_START_TIMEOUT
- while True:
- result = sock.connect_ex(('127.0.0.1', self.grpcPort))
- if result == 0:
- # The port is open. Let's go! (Close socket first)
- sock.close()
- break
- # Port is not open yet. If there is time, we wait a bit.
- if endtime > time.time():
- time.sleep(0.2)
- else:
- # Time's up.
- raise Exception("Switch did not start before {} second timeout. Exiting.\n"
- .format(SWITCH_START_TIMEOUT))
- exit()
+ def killBmv2(self, log=False):
+ if self.bmv2popen is not None:
+ self.bmv2popen.kill()
+ if self.logfd is not None:
+ if log:
+ self.logfd.write("*** PROCESS TERMINATED BY MININET ***\n")
+ self.logfd.close()
- self.doOnosNetcfg(cip)
+ def cleanupTmpFiles(self):
+ self.cmd("rm -f /tmp/bmv2-%d-*" % self.deviceId)
def stop(self, deleteIntfs=True):
"""Terminate switch."""
- self.cmd("rm -f /tmp/bmv2-%d-*" % self.deviceId)
- self.cmd("rm -f /tmp/bmv2-%d.log*" % self.deviceId)
- self.cmd('kill %' + BMV2_TARGET)
+ self.stopped = True
+ self.killBmv2(log=True)
Switch.stop(self, deleteIntfs)
diff --git a/tools/dev/p4vm/bm-commands.sh b/tools/dev/p4vm/bm-commands.sh
new file mode 100644
index 0000000..ee96f22
--- /dev/null
+++ b/tools/dev/p4vm/bm-commands.sh
@@ -0,0 +1,52 @@
+#!/usr/bin/env bash
+
+BUILD_DIR=~/p4tools
+
+export BMV2_PATH=${BUILD_DIR}/bmv2
+export P4RUNTIME_PATH=${BUILD_DIR}/p4runtime
+
+bm-cli () {
+ if [ -z "$1" ]; then
+ echo "No argument supplied. Usage: bm-cli <BMV2 DEVICE ID>"
+ return
+ fi
+ tport=$(head -n 1 /tmp/bmv2-$1-thrift-port)
+ echo "Starting CLI for BMv2 instance $1 (Thrift port $tport)..."
+ sudo ${BMV2_PATH}/tools/runtime_CLI.py --thrift-port ${tport} ${@:2}
+}
+
+bm-dbg () {
+ if [ -z "$1" ]; then
+ echo "No argument supplied. Usage: bm-dbg <BMV2 DEVICE ID>"
+ return
+ fi
+ tport=$(head -n 1 /tmp/bmv2-$1-thrift-port)
+ echo "Starting debugger for BMv2 instance $1 (Thrift port $tport)..."
+ sudo ${BMV2_PATH}/tools/p4dbg.py --thrift-port ${tport} ${@:2}
+}
+
+bm-nmsg () {
+ if [ -z "$1" ]; then
+ echo "No argument supplied. Usage: bm-nmsg <BMV2 DEVICE ID>"
+ return
+ fi
+ tport=$(head -n 1 /tmp/bmv2-$1-thrift-port)
+ echo "Starting nanomsg event listener for BMv2 instance $1 (Thrift port $tport)..."
+ sudo ${BMV2_PATH}/tools/nanomsg_client.py --thrift-port ${tport} ${@:2}
+}
+
+bm-log () {
+ if [ -z "$1" ]; then
+ echo "No argument supplied. Usage: bm-log <BMV2 DEVICE ID>"
+ return
+ fi
+ echo "Showing log for BMv2 instance $1..."
+ echo "---"
+ tail -f /tmp/bmv2-$1-log
+}
+
+bm-sysrepo-reset () {
+ echo "Resetting sysrepo data store..."
+ sudo rm -rf /etc/sysrepo/data/*
+ sudo ${P4RUNTIME_PATH}/proto/sysrepo/install_yangs.sh
+}
diff --git a/tools/dev/p4vm/root-bootstrap.sh b/tools/dev/p4vm/root-bootstrap.sh
index 3f1b8e6..ff23fc5 100755
--- a/tools/dev/p4vm/root-bootstrap.sh
+++ b/tools/dev/p4vm/root-bootstrap.sh
@@ -7,6 +7,7 @@
echo "sdn ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/99_sdn
chmod 440 /etc/sudoers.d/99_sdn
usermod -aG vboxsf sdn
+update-locale LC_ALL="en_US.UTF-8"
# Java 8
apt-get install software-properties-common -y
@@ -17,7 +18,11 @@
apt-get -y install \
oracle-java8-installer oracle-java8-set-default \
zip unzip \
- bridge-utils
+ bridge-utils \
+ avahi-daemon \
+ htop \
+ valgrind \
+ git-review
tee -a /etc/ssh/sshd_config <<EOF
diff --git a/tools/dev/p4vm/user-bootstrap.sh b/tools/dev/p4vm/user-bootstrap.sh
index 9b19f26..b7a7739 100755
--- a/tools/dev/p4vm/user-bootstrap.sh
+++ b/tools/dev/p4vm/user-bootstrap.sh
@@ -12,6 +12,7 @@
# ONOS
export ONOS_ROOT=~/onos
source ~/onos/tools/dev/bash_profile
+source ~/onos/tools/dev/p4vm/bm-commands.sh
EOF
source ~/.profile
diff --git a/tools/test/bin/onos-fetch-db b/tools/test/bin/onos-fetch-db
new file mode 100755
index 0000000..0073465
--- /dev/null
+++ b/tools/test/bin/onos-fetch-db
@@ -0,0 +1,43 @@
+#!/bin/bash
+# -----------------------------------------------------------------------------
+# Collect ONOS data from a single node or the current ONOS cell.
+# -----------------------------------------------------------------------------
+
+[ ! -d "$ONOS_ROOT" ] && echo "ONOS_ROOT is not defined" >&2 && exit 1
+. $ONOS_ROOT/tools/build/envDefaults
+
+function print_usage {
+ command_name=`basename $0`
+ echo "Collect ONOS data from a single node or the current ONOS cell."
+ echo
+ echo "Usage: $command_name <TARGET> "
+ echo " $command_name [-h | --help]"
+ echo "Options:"
+ echo " TARGET The target of the command"
+ echo " [-h | --help] Print this help"
+ echo ""
+ echo "TARGET: <hostname | --cell>"
+ echo " hostname Execute on the specified host name"
+ echo " --cell Execute on the current ONOS cell"
+ echo ""
+}
+
+# Print usage
+if [ "${1}" = "-h" -o "${1}" = "--help" ]; then
+ print_usage
+ exit 0
+fi
+
+# Select the target
+if [ "${1}" = "--cell" ]; then
+ nodes=$(env | sort | egrep "^OC[0-9]+" | cut -d= -f2)
+else
+ nodes=${1:-$OCI}
+fi
+
+# Execute the remote commands
+for node in $nodes; do
+ echo "fetching from ${node}..."
+ mkdir -p ${node}
+ scp -p -r $ONOS_USER@${node}:$ONOS_INSTALL_DIR/karaf/data/db/partitions/* ./${node}/
+done
diff --git a/tools/test/bin/onos-verify-cell b/tools/test/bin/onos-verify-cell
index 33f9565..7361616 100755
--- a/tools/test/bin/onos-verify-cell
+++ b/tools/test/bin/onos-verify-cell
@@ -7,5 +7,5 @@
. $ONOS_ROOT/tools/build/envDefaults
for node in $OCT $OCN $(env | sort | egrep "^OC[0-9]+" | cut -d= -f2); do
- printf "%s: " $node; ssh -n -o StrictHostKeyChecking=no -o PasswordAuthentication=no $ONOS_USER@$node hostname
+ printf "%s: " $node; ssh -n -q -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o PasswordAuthentication=no $ONOS_USER@$node hostname
done
diff --git a/tools/test/topos/geant.py b/tools/test/topos/geant.py
index e2e6fb7..6eedd29 100644
--- a/tools/test/topos/geant.py
+++ b/tools/test/topos/geant.py
@@ -15,6 +15,11 @@
class GeantMplsTopo( Topo ):
"Internet Topology Zoo Specimen."
+ def addSwitch( self, name, **opts ):
+ kwargs = { 'protocols' : 'OpenFlow13' }
+ kwargs.update( opts )
+ return super(GeantMplsTopo, self).addSwitch( name, **kwargs )
+
def __init__( self ):
"Create a topology."
@@ -23,14 +28,14 @@
# add nodes, switches first...
ATH = self.addSwitch( 's1' )
- LIS = self.addSwitch( 's2', protocols='OpenFlow13' )
+ LIS = self.addSwitch( 's2' )
LON = self.addSwitch( 's3' )
BRU = self.addSwitch( 's4' )
PAR = self.addSwitch( 's5' )
DUB = self.addSwitch( 's6' )
MAD = self.addSwitch( 's7' )
GEN = self.addSwitch( 's8' )
- MIL = self.addSwitch( 's9', protocols='OpenFlow13' )
+ MIL = self.addSwitch( 's9' )
SOF = self.addSwitch( 's10' )
BUC = self.addSwitch( 's11' )
VIE = self.addSwitch( 's12' )
@@ -43,7 +48,7 @@
PRA = self.addSwitch( 's19' )
BRA = self.addSwitch( 's20' )
ZAG = self.addSwitch( 's21' )
- LJU = self.addSwitch( 's22', protocols='OpenFlow13' )
+ LJU = self.addSwitch( 's22' )
BUD = self.addSwitch( 's23' )
MLT = self.addSwitch( 's24' )
LUX = self.addSwitch( 's25' )
@@ -122,62 +127,62 @@
self.addLink( HEL , HEL_host )
# add edges between switches
- self.addLink( ATH , MIL, bw=10 )
- self.addLink( MIL , ATH, bw=10 )
- self.addLink( MIL , VIE, bw=10 )
- self.addLink( MIL , MAR, bw=10 )
- self.addLink( MIL , GEN, bw=10 )
- self.addLink( GEN , MIL, bw=10 )
- self.addLink( MIL , MLT, bw=10 )
- self.addLink( GEN , FRA, bw=10 )
- self.addLink( FRA , GEN, bw=10 )
- self.addLink( GEN , PAR, bw=10 )
- self.addLink( PAR , GEN, bw=10 )
- self.addLink( GEN , PAR, bw=10 )
- self.addLink( FRA , POZ, bw=10 )
- self.addLink( GEN , MAR, bw=10 )
- self.addLink( MAR , MAD, bw=10 )
- self.addLink( MAD , PAR, bw=10 )
- self.addLink( MAD , LIS, bw=10 )
- self.addLink( LIS , LON, bw=10 )
- self.addLink( LON , LIS, bw=10 )
- self.addLink( LON , PAR, bw=10 )
- self.addLink( LON , DUB, bw=10 )
- self.addLink( DUB , LON, bw=10 )
- self.addLink( LON , BRU, bw=10 )
- self.addLink( BRU , AMS, bw=10 )
- self.addLink( AMS , LUX, bw=10 )
- self.addLink( LUX , FRA, bw=10 )
- self.addLink( AMS , HAM, bw=10 )
- self.addLink( HAM , FRA, bw=10 )
- self.addLink( HAM , COP, bw=10 )
- self.addLink( COP , AMS, bw=10 )
- self.addLink( FRA , POZ, bw=10 )
- self.addLink( FRA , PRA, bw=10 )
- self.addLink( FRA , BUD, bw=10 )
- self.addLink( FRA , VIE, bw=10 )
- self.addLink( POZ , PRA, bw=10 )
- self.addLink( POZ , KAU, bw=10 )
- self.addLink( KAU , RIG, bw=10 )
- self.addLink( ZAG , VIE, bw=10 )
- self.addLink( ZAG , BUD, bw=10 )
- self.addLink( BUD , PRA, bw=10 )
- self.addLink( BUD , BRA, bw=10 )
- self.addLink( BUD , BUC, bw=10 )
- self.addLink( BUD , SOF, bw=10 )
- self.addLink( BUD , LJU, bw=10 )
- self.addLink( BUC , SOF, bw=10 )
- self.addLink( BUC , VIE, bw=10 )
- self.addLink( VIE , BRA, bw=10 )
- self.addLink( RIG , TLN, bw=10 )
- self.addLink( TLN , HAM, bw=10 )
- self.addLink( OSL , STO, bw=10 )
- self.addLink( STO , HEL, bw=10 )
- self.addLink( STO , COP, bw=10 )
- self.addLink( OSL , COP, bw=10 )
- self.addLink( TLN , HEL, bw=10 )
+ self.addLink( ATH , MIL )
+ self.addLink( MIL , ATH )
+ self.addLink( MIL , VIE )
+ self.addLink( MIL , MAR )
+ self.addLink( MIL , GEN )
+ self.addLink( GEN , MIL )
+ self.addLink( MIL , MLT )
+ self.addLink( GEN , FRA )
+ self.addLink( FRA , GEN )
+ self.addLink( GEN , PAR )
+ self.addLink( PAR , GEN )
+ self.addLink( GEN , PAR )
+ self.addLink( FRA , POZ )
+ self.addLink( GEN , MAR )
+ self.addLink( MAR , MAD )
+ self.addLink( MAD , PAR )
+ self.addLink( MAD , LIS )
+ self.addLink( LIS , LON )
+ self.addLink( LON , LIS )
+ self.addLink( LON , PAR )
+ self.addLink( LON , DUB )
+ self.addLink( DUB , LON )
+ self.addLink( LON , BRU )
+ self.addLink( BRU , AMS )
+ self.addLink( AMS , LUX )
+ self.addLink( LUX , FRA )
+ self.addLink( AMS , HAM )
+ self.addLink( HAM , FRA )
+ self.addLink( HAM , COP )
+ self.addLink( COP , AMS )
+ self.addLink( FRA , POZ )
+ self.addLink( FRA , PRA )
+ self.addLink( FRA , BUD )
+ self.addLink( FRA , VIE )
+ self.addLink( POZ , PRA )
+ self.addLink( POZ , KAU )
+ self.addLink( KAU , RIG )
+ self.addLink( ZAG , VIE )
+ self.addLink( ZAG , BUD )
+ self.addLink( BUD , PRA )
+ self.addLink( BUD , BRA )
+ self.addLink( BUD , BUC )
+ self.addLink( BUD , SOF )
+ self.addLink( BUD , LJU )
+ self.addLink( BUC , SOF )
+ self.addLink( BUC , VIE )
+ self.addLink( VIE , BRA )
+ self.addLink( RIG , TLN )
+ self.addLink( TLN , HAM )
+ self.addLink( OSL , STO )
+ self.addLink( STO , HEL )
+ self.addLink( STO , COP )
+ self.addLink( OSL , COP )
+ self.addLink( TLN , HEL )
-topos = { 'att': ( lambda: GeantMplsTopo() ) }
+topos = { 'geant': ( lambda: GeantMplsTopo() ) }
if __name__ == '__main__':
from onosnet import run
diff --git a/utils/junit/pom.xml b/utils/junit/pom.xml
index e0846ed..c30eaf2 100644
--- a/utils/junit/pom.xml
+++ b/utils/junit/pom.xml
@@ -53,4 +53,20 @@
</dependency>
</dependencies>
+ <build>
+ <plugins>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <compilerArgs>
+ <arg>-Xep:BetaApi:OFF</arg>
+ </compilerArgs>
+ </configuration>
+ </plugin>
+
+ </plugins>
+ </build>
+
</project>
diff --git a/utils/misc/pom.xml b/utils/misc/pom.xml
index 653ed4a..1bfc038 100644
--- a/utils/misc/pom.xml
+++ b/utils/misc/pom.xml
@@ -31,7 +31,6 @@
<description>Miscellaneous ON.Lab utilities</description>
<properties>
- <metrics.version>3.1.2</metrics.version>
</properties>
<dependencies>
@@ -77,12 +76,10 @@
<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-core</artifactId>
- <version>${metrics.version}</version>
</dependency>
<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-json</artifactId>
- <version>${metrics.version}</version>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
diff --git a/utils/misc/src/main/java/org/onlab/packet/DHCP6.java b/utils/misc/src/main/java/org/onlab/packet/DHCP6.java
index 054552c..8dbd1dc 100644
--- a/utils/misc/src/main/java/org/onlab/packet/DHCP6.java
+++ b/utils/misc/src/main/java/org/onlab/packet/DHCP6.java
@@ -79,6 +79,70 @@
public byte value() {
return this.value;
}
+ public static MsgType getType(final int value) {
+ switch (value) {
+ case 1:
+ return SOLICIT;
+ case 2:
+ return ADVERTISE;
+ case 3:
+ return REQUEST;
+ case 4:
+ return CONFIRM;
+ case 5:
+ return RENEW;
+ case 6:
+ return REBIND;
+ case 7:
+ return REPLY;
+ case 8:
+ return RELEASE;
+ case 9:
+ return DECLINE;
+ case 10:
+ return RECONFIGURE;
+ case 11:
+ return INFORMATION_REQUEST;
+ case 12:
+ return RELAY_FORW;
+ case 13:
+ return RELAY_REPL;
+ default:
+ return null;
+ }
+ }
+ public static String getMsgTypeStr(final MsgType msgType) {
+ switch (msgType) {
+ case SOLICIT:
+ return "SOLICIT";
+ case ADVERTISE:
+ return "ADVERTISE";
+ case REQUEST:
+ return "REQUEST";
+ case CONFIRM:
+ return "CONFIRM";
+ case RENEW:
+ return "RENEW";
+ case REBIND:
+ return "REBIND";
+ case REPLY:
+ return "REPLY";
+ case RELEASE:
+ return "RELEASE";
+ case DECLINE:
+ return "DECLINE";
+ case RECONFIGURE:
+ return "RECONFIGURE";
+ case INFORMATION_REQUEST:
+ return "INFORMATION_REQUEST";
+ case RELAY_FORW:
+ return "RELAY_FORW";
+ case RELAY_REPL:
+ return "RELAY_REPL";
+ default:
+ return "NULL";
+ }
+ }
}
/**
diff --git a/utils/misc/src/main/java/org/onlab/packet/DHCPPacketType.java b/utils/misc/src/main/java/org/onlab/packet/DHCPPacketType.java
index 2dad848..c88b907 100644
--- a/utils/misc/src/main/java/org/onlab/packet/DHCPPacketType.java
+++ b/utils/misc/src/main/java/org/onlab/packet/DHCPPacketType.java
@@ -80,7 +80,7 @@
break;
}
- return null;
+ return "";
}
public static DHCPPacketType getType(final int value) {
diff --git a/utils/misc/src/main/java/org/onlab/packet/RIPngEntry.java b/utils/misc/src/main/java/org/onlab/packet/RIPngEntry.java
index acc500c..cfe3b62 100644
--- a/utils/misc/src/main/java/org/onlab/packet/RIPngEntry.java
+++ b/utils/misc/src/main/java/org/onlab/packet/RIPngEntry.java
@@ -33,13 +33,13 @@
public static final int OPT_CODE_LEN = 1;
public static final int ENTRY_LEN = 20;
public static final byte INFINITY_METRIC = 16;
- public static final byte NEXTHOP_METRIC = -128; // actually it is 0xFF
+ public static final int NEXTHOP_METRIC = 255; // actually it is 0xFF
private final Logger log = getLogger(getClass());
protected byte[] prefix; // 16 bytes
protected short routeTag;
- protected byte prefixLen;
- protected byte metric;
+ protected int prefixLen;
+ protected int metric;
@Override
public byte[] serialize() {
@@ -47,8 +47,8 @@
byteBuffer = ByteBuffer.allocate(ENTRY_LEN);
byteBuffer.put(prefix);
byteBuffer.putShort(routeTag);
- byteBuffer.put(prefixLen);
- byteBuffer.put(metric);
+ byteBuffer.put((byte) prefixLen);
+ byteBuffer.put((byte) metric);
return byteBuffer.array();
}
@@ -76,8 +76,8 @@
ripngEntry.prefix = new byte[IpAddress.INET6_BYTE_LENGTH];
bb.get(ripngEntry.prefix);
ripngEntry.routeTag = bb.getShort();
- ripngEntry.prefixLen = bb.get();
- ripngEntry.metric = bb.get();
+ ripngEntry.prefixLen = 0xFF & bb.get();
+ ripngEntry.metric = 0xFF & bb.get();
return ripngEntry;
};
}
@@ -148,7 +148,7 @@
/**
* @return the prefix length
*/
- public byte getPrefixLen() {
+ public int getPrefixLen() {
return this.prefixLen;
}
@@ -156,7 +156,7 @@
* @param prefixlen the prefix length to set
* @return this
*/
- public RIPngEntry setPrefixLen(final byte prefixlen) {
+ public RIPngEntry setPrefixLen(final int prefixlen) {
this.prefixLen = prefixlen;
return this;
}
@@ -164,7 +164,7 @@
/**
* @return the metric
*/
- public byte getMetric() {
+ public int getMetric() {
return this.metric;
}
@@ -172,7 +172,7 @@
* @param metric the route metric to set
* @return this
*/
- public RIPngEntry setMetric(final byte metric) {
+ public RIPngEntry setMetric(final int metric) {
this.metric = metric;
return this;
}
@@ -184,8 +184,7 @@
*/
@Override
public String toString() {
- return "RIPngEntry [prefix=" + Arrays.toString(this.prefix)
- + ", route tag=" + this.routeTag
+ return "RIPngEntry [prefix=" + Arrays.toString(this.prefix) + ", route tag=" + this.routeTag
+ ", prefix length=" + this.prefixLen
+ ", metric = " + this.metric + "]";
}
diff --git a/utils/misc/src/main/java/org/onlab/util/Tools.java b/utils/misc/src/main/java/org/onlab/util/Tools.java
index 0989010..bf9bea0 100644
--- a/utils/misc/src/main/java/org/onlab/util/Tools.java
+++ b/utils/misc/src/main/java/org/onlab/util/Tools.java
@@ -162,7 +162,7 @@
* @param collection collection to test
* @return true if null or empty; false otherwise
*/
- public static boolean isNullOrEmpty(Collection collection) {
+ public static boolean isNullOrEmpty(Collection<?> collection) {
return collection == null || collection.isEmpty();
}
diff --git a/utils/rest/src/main/java/org/onlab/rest/BaseResource.java b/utils/rest/src/main/java/org/onlab/rest/BaseResource.java
index 093220f..44d7c99 100644
--- a/utils/rest/src/main/java/org/onlab/rest/BaseResource.java
+++ b/utils/rest/src/main/java/org/onlab/rest/BaseResource.java
@@ -28,18 +28,6 @@
private static ServiceDirectory services = new DefaultServiceDirectory();
/**
- * Sets alternate service directory to be used for lookups.
- * <p>
- * Intended to ease unit testing and not intended for use in production.
- * </p>
- *
- * @param serviceDirectory alternate service directory
- */
- public static void setServiceDirectory(ServiceDirectory serviceDirectory) {
- services = serviceDirectory;
- }
-
- /**
* Returns reference to the specified service implementation.
*
* @param service service class
diff --git a/web/api/src/main/java/org/onosproject/rest/resources/FlowObjectiveWebResource.java b/web/api/src/main/java/org/onosproject/rest/resources/FlowObjectiveWebResource.java
index 4f186ef..e6f7e9c 100644
--- a/web/api/src/main/java/org/onosproject/rest/resources/FlowObjectiveWebResource.java
+++ b/web/api/src/main/java/org/onosproject/rest/resources/FlowObjectiveWebResource.java
@@ -75,22 +75,22 @@
try {
UriBuilder locationBuilder = null;
ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
- if (validateDeviceId(deviceId, jsonTree)) {
+ validateDeviceId(deviceId, jsonTree);
- if (appId != null) {
- jsonTree.put("appId", appId);
- }
-
- DeviceId did = DeviceId.deviceId(deviceId);
- FilteringObjective filteringObjective =
- codec(FilteringObjective.class).decode(jsonTree, this);
- flowObjectiveService.filter(did, filteringObjective);
- locationBuilder = uriInfo.getBaseUriBuilder()
- .path("flowobjectives")
- .path(did.toString())
- .path("filter")
- .path(Integer.toString(filteringObjective.id()));
+ if (appId != null) {
+ jsonTree.put("appId", appId);
}
+
+ DeviceId did = DeviceId.deviceId(deviceId);
+ FilteringObjective filteringObjective =
+ codec(FilteringObjective.class).decode(jsonTree, this);
+ flowObjectiveService.filter(did, filteringObjective);
+ locationBuilder = uriInfo.getBaseUriBuilder()
+ .path("flowobjectives")
+ .path(did.toString())
+ .path("filter")
+ .path(Integer.toString(filteringObjective.id()));
+
return Response
.created(locationBuilder.build())
.build();
@@ -119,22 +119,22 @@
try {
UriBuilder locationBuilder = null;
ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
- if (validateDeviceId(deviceId, jsonTree)) {
+ validateDeviceId(deviceId, jsonTree);
- if (appId != null) {
- jsonTree.put("appId", appId);
- }
-
- DeviceId did = DeviceId.deviceId(deviceId);
- ForwardingObjective forwardingObjective =
- codec(ForwardingObjective.class).decode(jsonTree, this);
- flowObjectiveService.forward(did, forwardingObjective);
- locationBuilder = uriInfo.getBaseUriBuilder()
- .path("flowobjectives")
- .path(did.toString())
- .path("forward")
- .path(Integer.toString(forwardingObjective.id()));
+ if (appId != null) {
+ jsonTree.put("appId", appId);
}
+
+ DeviceId did = DeviceId.deviceId(deviceId);
+ ForwardingObjective forwardingObjective =
+ codec(ForwardingObjective.class).decode(jsonTree, this);
+ flowObjectiveService.forward(did, forwardingObjective);
+ locationBuilder = uriInfo.getBaseUriBuilder()
+ .path("flowobjectives")
+ .path(did.toString())
+ .path("forward")
+ .path(Integer.toString(forwardingObjective.id()));
+
return Response
.created(locationBuilder.build())
.build();
@@ -163,22 +163,22 @@
try {
UriBuilder locationBuilder = null;
ObjectNode jsonTree = (ObjectNode) mapper().readTree(stream);
- if (validateDeviceId(deviceId, jsonTree)) {
+ validateDeviceId(deviceId, jsonTree);
- if (appId != null) {
- jsonTree.put("appId", appId);
- }
-
- DeviceId did = DeviceId.deviceId(deviceId);
- NextObjective nextObjective =
- codec(NextObjective.class).decode(jsonTree, this);
- flowObjectiveService.next(did, nextObjective);
- locationBuilder = uriInfo.getBaseUriBuilder()
- .path("flowobjectives")
- .path(did.toString())
- .path("next")
- .path(Integer.toString(nextObjective.id()));
+ if (appId != null) {
+ jsonTree.put("appId", appId);
}
+
+ DeviceId did = DeviceId.deviceId(deviceId);
+ NextObjective nextObjective =
+ codec(NextObjective.class).decode(jsonTree, this);
+ flowObjectiveService.next(did, nextObjective);
+ locationBuilder = uriInfo.getBaseUriBuilder()
+ .path("flowobjectives")
+ .path(did.toString())
+ .path("next")
+ .path(Integer.toString(nextObjective.id()));
+
return Response
.created(locationBuilder.build())
.build();
@@ -234,15 +234,14 @@
*
* @param deviceId device identifier
* @param node object node
- * @return validity
+ * @throws IllegalArgumentException if the device id is invalid
*/
- private boolean validateDeviceId(String deviceId, ObjectNode node) {
+ private void validateDeviceId(String deviceId, ObjectNode node) {
JsonNode specifiedDeviceId = node.get("deviceId");
if (specifiedDeviceId != null &&
!specifiedDeviceId.asText().equals(deviceId)) {
throw new IllegalArgumentException(DEVICE_INVALID);
}
- return true;
}
}
diff --git a/web/api/src/test/java/org/onosproject/rest/resources/ApplicationsResourceTest.java b/web/api/src/test/java/org/onosproject/rest/resources/ApplicationsResourceTest.java
index 48cbd2d..3de04ba 100644
--- a/web/api/src/test/java/org/onosproject/rest/resources/ApplicationsResourceTest.java
+++ b/web/api/src/test/java/org/onosproject/rest/resources/ApplicationsResourceTest.java
@@ -27,7 +27,6 @@
import org.junit.Test;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.TestServiceDirectory;
-import org.onlab.rest.BaseResource;
import org.onosproject.app.ApplicationAdminService;
import org.onosproject.app.ApplicationService;
import org.onosproject.app.ApplicationState;
@@ -295,7 +294,7 @@
.add(CoreService.class, coreService)
.add(CodecService.class, codecService);
- BaseResource.setServiceDirectory(testDirectory);
+ setServiceDirectory(testDirectory);
}
/**
diff --git a/web/api/src/test/java/org/onosproject/rest/resources/ComponentConfigWebResourceTest.java b/web/api/src/test/java/org/onosproject/rest/resources/ComponentConfigWebResourceTest.java
index d5621c9..6ff02e3 100644
--- a/web/api/src/test/java/org/onosproject/rest/resources/ComponentConfigWebResourceTest.java
+++ b/web/api/src/test/java/org/onosproject/rest/resources/ComponentConfigWebResourceTest.java
@@ -20,7 +20,6 @@
import org.junit.Test;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.TestServiceDirectory;
-import org.onlab.rest.BaseResource;
import org.onosproject.cfg.ComponentConfigAdapter;
import org.onosproject.cfg.ComponentConfigService;
import org.onosproject.cfg.ConfigProperty;
@@ -51,7 +50,7 @@
ServiceDirectory testDirectory =
new TestServiceDirectory()
.add(ComponentConfigService.class, service);
- BaseResource.setServiceDirectory(testDirectory);
+ setServiceDirectory(testDirectory);
}
@Test
diff --git a/web/api/src/test/java/org/onosproject/rest/resources/DeviceKeyWebResourceTest.java b/web/api/src/test/java/org/onosproject/rest/resources/DeviceKeyWebResourceTest.java
index 8ae7b3d..7ecaf38 100644
--- a/web/api/src/test/java/org/onosproject/rest/resources/DeviceKeyWebResourceTest.java
+++ b/web/api/src/test/java/org/onosproject/rest/resources/DeviceKeyWebResourceTest.java
@@ -26,7 +26,6 @@
import org.junit.Test;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.TestServiceDirectory;
-import org.onlab.rest.BaseResource;
import org.onosproject.codec.CodecService;
import org.onosproject.codec.impl.CodecManager;
import org.onosproject.net.key.DeviceKey;
@@ -109,7 +108,7 @@
.add(DeviceKeyAdminService.class, mockDeviceKeyAdminService)
.add(CodecService.class, codecService);
- BaseResource.setServiceDirectory(testDirectory);
+ setServiceDirectory(testDirectory);
}
/**
diff --git a/web/api/src/test/java/org/onosproject/rest/resources/DevicesResourceTest.java b/web/api/src/test/java/org/onosproject/rest/resources/DevicesResourceTest.java
index 169cb11..75d33a8 100644
--- a/web/api/src/test/java/org/onosproject/rest/resources/DevicesResourceTest.java
+++ b/web/api/src/test/java/org/onosproject/rest/resources/DevicesResourceTest.java
@@ -27,7 +27,6 @@
import org.junit.Test;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.TestServiceDirectory;
-import org.onlab.rest.BaseResource;
import org.onosproject.codec.CodecService;
import org.onosproject.codec.impl.CodecManager;
import org.onosproject.net.DefaultPort;
@@ -36,16 +35,15 @@
import org.onosproject.net.MastershipRole;
import org.onosproject.net.Port;
import org.onosproject.net.device.DeviceService;
-import org.onosproject.net.driver.DriverService;
import org.onosproject.net.driver.DefaultDriver;
-import org.onosproject.net.driver.TestBehaviourImpl;
+import org.onosproject.net.driver.DriverService;
import org.onosproject.net.driver.TestBehaviour;
+import org.onosproject.net.driver.TestBehaviourImpl;
import org.onosproject.net.driver.TestBehaviourTwo;
import org.onosproject.net.driver.TestBehaviourTwoImpl;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.client.WebTarget;
-
import java.util.ArrayList;
import java.util.List;
@@ -247,7 +245,7 @@
.add(DriverService.class, mockDriverService)
.add(CodecService.class, codecService);
- BaseResource.setServiceDirectory(testDirectory);
+ setServiceDirectory(testDirectory);
}
/**
diff --git a/web/api/src/test/java/org/onosproject/rest/resources/FlowObjectiveResourceTest.java b/web/api/src/test/java/org/onosproject/rest/resources/FlowObjectiveResourceTest.java
index 6d858d5..eb99cff 100644
--- a/web/api/src/test/java/org/onosproject/rest/resources/FlowObjectiveResourceTest.java
+++ b/web/api/src/test/java/org/onosproject/rest/resources/FlowObjectiveResourceTest.java
@@ -23,7 +23,6 @@
import org.junit.Test;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.TestServiceDirectory;
-import org.onlab.rest.BaseResource;
import org.onosproject.codec.CodecService;
import org.onosproject.codec.impl.CodecManager;
import org.onosproject.core.CoreService;
@@ -79,7 +78,7 @@
.add(CodecService.class, codecService)
.add(CoreService.class, mockCoreService);
- BaseResource.setServiceDirectory(testDirectory);
+ setServiceDirectory(testDirectory);
}
/**
diff --git a/web/api/src/test/java/org/onosproject/rest/resources/FlowsResourceTest.java b/web/api/src/test/java/org/onosproject/rest/resources/FlowsResourceTest.java
index 6e8255c..72e9a00 100644
--- a/web/api/src/test/java/org/onosproject/rest/resources/FlowsResourceTest.java
+++ b/web/api/src/test/java/org/onosproject/rest/resources/FlowsResourceTest.java
@@ -15,19 +15,10 @@
*/
package org.onosproject.rest.resources;
-import java.io.InputStream;
-import java.net.HttpURLConnection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
-
-import javax.ws.rs.NotFoundException;
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.client.WebTarget;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
+import com.eclipsesource.json.Json;
+import com.eclipsesource.json.JsonArray;
+import com.eclipsesource.json.JsonObject;
+import com.google.common.collect.ImmutableSet;
import org.hamcrest.Description;
import org.hamcrest.Matchers;
import org.hamcrest.TypeSafeMatcher;
@@ -37,7 +28,6 @@
import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.TestServiceDirectory;
import org.onlab.packet.MacAddress;
-import org.onlab.rest.BaseResource;
import org.onosproject.app.ApplicationService;
import org.onosproject.codec.CodecService;
import org.onosproject.codec.impl.CodecManager;
@@ -61,10 +51,17 @@
import org.onosproject.net.flow.criteria.Criterion;
import org.onosproject.net.flow.instructions.Instruction;
-import com.eclipsesource.json.Json;
-import com.eclipsesource.json.JsonArray;
-import com.eclipsesource.json.JsonObject;
-import com.google.common.collect.ImmutableSet;
+import javax.ws.rs.NotFoundException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.easymock.EasyMock.anyObject;
@@ -276,7 +273,7 @@
.add(CoreService.class, mockCoreService)
.add(ApplicationService.class, mockApplicationService);
- BaseResource.setServiceDirectory(testDirectory);
+ setServiceDirectory(testDirectory);
}
/**
diff --git a/web/api/src/test/java/org/onosproject/rest/resources/GroupsResourceTest.java b/web/api/src/test/java/org/onosproject/rest/resources/GroupsResourceTest.java
index 1efbd33..ab4cf9d 100644
--- a/web/api/src/test/java/org/onosproject/rest/resources/GroupsResourceTest.java
+++ b/web/api/src/test/java/org/onosproject/rest/resources/GroupsResourceTest.java
@@ -28,7 +28,6 @@
import org.junit.Test;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.TestServiceDirectory;
-import org.onlab.rest.BaseResource;
import org.onosproject.codec.CodecService;
import org.onosproject.codec.impl.CodecManager;
import org.onosproject.codec.impl.GroupCodec;
@@ -241,7 +240,7 @@
.add(CodecService.class, codecService)
.add(CoreService.class, mockCoreService);
- BaseResource.setServiceDirectory(testDirectory);
+ setServiceDirectory(testDirectory);
}
/**
diff --git a/web/api/src/test/java/org/onosproject/rest/resources/HostResourceTest.java b/web/api/src/test/java/org/onosproject/rest/resources/HostResourceTest.java
index 99fa074..4bb9523 100644
--- a/web/api/src/test/java/org/onosproject/rest/resources/HostResourceTest.java
+++ b/web/api/src/test/java/org/onosproject/rest/resources/HostResourceTest.java
@@ -31,7 +31,6 @@
import org.onlab.osgi.TestServiceDirectory;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
-import org.onlab.rest.BaseResource;
import org.onosproject.codec.CodecService;
import org.onosproject.codec.impl.CodecManager;
import org.onosproject.net.DefaultHost;
@@ -99,7 +98,7 @@
.add(HostAdminService.class, mockHostService)
.add(CodecService.class, codecService)
.add(HostProviderRegistry.class, mockHostProviderRegistry);
- BaseResource.setServiceDirectory(testDirectory);
+ setServiceDirectory(testDirectory);
}
/**
diff --git a/web/api/src/test/java/org/onosproject/rest/resources/IntentsResourceTest.java b/web/api/src/test/java/org/onosproject/rest/resources/IntentsResourceTest.java
index b9b5dbd..e57af12 100644
--- a/web/api/src/test/java/org/onosproject/rest/resources/IntentsResourceTest.java
+++ b/web/api/src/test/java/org/onosproject/rest/resources/IntentsResourceTest.java
@@ -29,7 +29,6 @@
import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.TestServiceDirectory;
import org.onlab.packet.MacAddress;
-import org.onlab.rest.BaseResource;
import org.onosproject.codec.CodecService;
import org.onosproject.codec.impl.CodecManager;
import org.onosproject.codec.impl.MockCodecContext;
@@ -746,7 +745,7 @@
.add(CodecService.class, codecService)
.add(CoreService.class, mockCoreService);
- BaseResource.setServiceDirectory(testDirectory);
+ setServiceDirectory(testDirectory);
MockIdGenerator.cleanBind();
}
diff --git a/web/api/src/test/java/org/onosproject/rest/resources/LinksResourceTest.java b/web/api/src/test/java/org/onosproject/rest/resources/LinksResourceTest.java
index 1063002..e26bcee 100644
--- a/web/api/src/test/java/org/onosproject/rest/resources/LinksResourceTest.java
+++ b/web/api/src/test/java/org/onosproject/rest/resources/LinksResourceTest.java
@@ -27,7 +27,6 @@
import org.junit.Test;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.TestServiceDirectory;
-import org.onlab.rest.BaseResource;
import org.onosproject.codec.CodecService;
import org.onosproject.codec.impl.CodecManager;
import org.onosproject.net.ConnectPoint;
@@ -162,7 +161,7 @@
.add(LinkService.class, mockLinkService)
.add(CodecService.class, codecService);
- BaseResource.setServiceDirectory(testDirectory);
+ setServiceDirectory(testDirectory);
}
/**
diff --git a/web/api/src/test/java/org/onosproject/rest/resources/MastershipResourceTest.java b/web/api/src/test/java/org/onosproject/rest/resources/MastershipResourceTest.java
index 724075c..76d9a8d 100644
--- a/web/api/src/test/java/org/onosproject/rest/resources/MastershipResourceTest.java
+++ b/web/api/src/test/java/org/onosproject/rest/resources/MastershipResourceTest.java
@@ -28,7 +28,6 @@
import org.junit.Test;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.TestServiceDirectory;
-import org.onlab.rest.BaseResource;
import org.onosproject.cluster.NodeId;
import org.onosproject.cluster.RoleInfo;
import org.onosproject.codec.CodecService;
@@ -170,7 +169,7 @@
.add(DeviceService.class, mockDeviceService)
.add(CodecService.class, codecService);
- BaseResource.setServiceDirectory(testDirectory);
+ setServiceDirectory(testDirectory);
}
/**
diff --git a/web/api/src/test/java/org/onosproject/rest/resources/MetersResourceTest.java b/web/api/src/test/java/org/onosproject/rest/resources/MetersResourceTest.java
index e225cdd..235ca0f 100644
--- a/web/api/src/test/java/org/onosproject/rest/resources/MetersResourceTest.java
+++ b/web/api/src/test/java/org/onosproject/rest/resources/MetersResourceTest.java
@@ -28,7 +28,6 @@
import org.junit.Test;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.TestServiceDirectory;
-import org.onlab.rest.BaseResource;
import org.onosproject.codec.CodecService;
import org.onosproject.codec.impl.CodecManager;
import org.onosproject.codec.impl.MeterCodec;
@@ -239,7 +238,7 @@
.add(CodecService.class, codecService)
.add(CoreService.class, mockCoreService);
- BaseResource.setServiceDirectory(testDirectory);
+ setServiceDirectory(testDirectory);
}
/**
diff --git a/web/api/src/test/java/org/onosproject/rest/resources/MetricsResourceTest.java b/web/api/src/test/java/org/onosproject/rest/resources/MetricsResourceTest.java
index feac73f..75e7f02 100644
--- a/web/api/src/test/java/org/onosproject/rest/resources/MetricsResourceTest.java
+++ b/web/api/src/test/java/org/onosproject/rest/resources/MetricsResourceTest.java
@@ -31,7 +31,6 @@
import org.onlab.metrics.MetricsService;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.TestServiceDirectory;
-import org.onlab.rest.BaseResource;
import org.onosproject.codec.CodecService;
import org.onosproject.codec.impl.CodecManager;
@@ -68,7 +67,7 @@
new TestServiceDirectory()
.add(MetricsService.class, mockMetricsService)
.add(CodecService.class, codecService);
- BaseResource.setServiceDirectory(testDirectory);
+ setServiceDirectory(testDirectory);
}
/**
diff --git a/web/api/src/test/java/org/onosproject/rest/resources/MulticastRouteResourceTest.java b/web/api/src/test/java/org/onosproject/rest/resources/MulticastRouteResourceTest.java
index 33af8f4..64c13b4 100644
--- a/web/api/src/test/java/org/onosproject/rest/resources/MulticastRouteResourceTest.java
+++ b/web/api/src/test/java/org/onosproject/rest/resources/MulticastRouteResourceTest.java
@@ -27,7 +27,6 @@
import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.TestServiceDirectory;
import org.onlab.packet.IpAddress;
-import org.onlab.rest.BaseResource;
import org.onosproject.codec.CodecService;
import org.onosproject.codec.impl.CodecManager;
import org.onosproject.net.mcast.McastRoute;
@@ -85,7 +84,7 @@
new TestServiceDirectory()
.add(MulticastRouteService.class, mockMulticastRouteService)
.add(CodecService.class, codecService);
- BaseResource.setServiceDirectory(testDirectory);
+ setServiceDirectory(testDirectory);
}
/**
diff --git a/web/api/src/test/java/org/onosproject/rest/resources/NetworkConfigWebResourceTest.java b/web/api/src/test/java/org/onosproject/rest/resources/NetworkConfigWebResourceTest.java
index b02e1a6..b2fbf60 100644
--- a/web/api/src/test/java/org/onosproject/rest/resources/NetworkConfigWebResourceTest.java
+++ b/web/api/src/test/java/org/onosproject/rest/resources/NetworkConfigWebResourceTest.java
@@ -15,24 +15,18 @@
*/
package org.onosproject.rest.resources;
-import java.io.InputStream;
-import java.net.HttpURLConnection;
-import java.util.HashSet;
-import java.util.Set;
-
-import javax.ws.rs.NotFoundException;
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.client.WebTarget;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-
+import com.eclipsesource.json.Json;
+import com.eclipsesource.json.JsonObject;
+import com.eclipsesource.json.JsonValue;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.collect.ImmutableSet;
import org.eclipse.jetty.http.HttpStatus;
import org.junit.Assert;
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.net.DefaultDevice;
import org.onosproject.net.Device;
import org.onosproject.net.Link;
@@ -41,12 +35,15 @@
import org.onosproject.net.config.NetworkConfigServiceAdapter;
import org.onosproject.net.config.SubjectFactory;
-import com.eclipsesource.json.Json;
-import com.eclipsesource.json.JsonObject;
-import com.eclipsesource.json.JsonValue;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.google.common.collect.ImmutableSet;
+import javax.ws.rs.NotFoundException;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.util.HashSet;
+import java.util.Set;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.replay;
@@ -204,7 +201,7 @@
ServiceDirectory testDirectory =
new TestServiceDirectory()
.add(NetworkConfigService.class, mockNetworkConfigService);
- BaseResource.setServiceDirectory(testDirectory);
+ setServiceDirectory(testDirectory);
}
/**
diff --git a/web/api/src/test/java/org/onosproject/rest/resources/PathsResourceTest.java b/web/api/src/test/java/org/onosproject/rest/resources/PathsResourceTest.java
index 4d415f5..97d04bb 100644
--- a/web/api/src/test/java/org/onosproject/rest/resources/PathsResourceTest.java
+++ b/web/api/src/test/java/org/onosproject/rest/resources/PathsResourceTest.java
@@ -26,7 +26,6 @@
import org.junit.Test;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.TestServiceDirectory;
-import org.onlab.rest.BaseResource;
import org.onosproject.codec.CodecService;
import org.onosproject.codec.impl.CodecManager;
import org.onosproject.net.ElementId;
@@ -143,7 +142,7 @@
.add(PathService.class, mockPathService)
.add(CodecService.class, codecService);
- BaseResource.setServiceDirectory(testDirectory);
+ setServiceDirectory(testDirectory);
}
/**
diff --git a/web/api/src/test/java/org/onosproject/rest/resources/RegionsResourceTest.java b/web/api/src/test/java/org/onosproject/rest/resources/RegionsResourceTest.java
index 3a0300d..69894e4 100644
--- a/web/api/src/test/java/org/onosproject/rest/resources/RegionsResourceTest.java
+++ b/web/api/src/test/java/org/onosproject/rest/resources/RegionsResourceTest.java
@@ -28,7 +28,6 @@
import org.junit.Test;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.TestServiceDirectory;
-import org.onlab.rest.BaseResource;
import org.onosproject.cluster.NodeId;
import org.onosproject.codec.CodecService;
import org.onosproject.codec.impl.CodecManager;
@@ -142,7 +141,7 @@
.add(RegionService.class, mockRegionService)
.add(RegionAdminService.class, mockRegionAdminService)
.add(CodecService.class, codecService);
- BaseResource.setServiceDirectory(testDirectory);
+ setServiceDirectory(testDirectory);
}
/**
diff --git a/web/api/src/test/java/org/onosproject/rest/resources/ResourceTest.java b/web/api/src/test/java/org/onosproject/rest/resources/ResourceTest.java
index f032cd9..24036f6 100644
--- a/web/api/src/test/java/org/onosproject/rest/resources/ResourceTest.java
+++ b/web/api/src/test/java/org/onosproject/rest/resources/ResourceTest.java
@@ -21,6 +21,9 @@
import org.glassfish.jersey.test.jetty.JettyTestContainerFactory;
import org.glassfish.jersey.test.spi.TestContainerException;
import org.glassfish.jersey.test.spi.TestContainerFactory;
+import org.onlab.junit.TestUtils;
+import org.onlab.osgi.ServiceDirectory;
+import org.onlab.rest.BaseResource;
/**
* Base class for REST API tests.
@@ -58,4 +61,13 @@
protected TestContainerFactory getTestContainerFactory() throws TestContainerException {
return new JettyTestContainerFactory();
}
+
+ /**
+ * Sets up the test services directory in the base resource environment.
+ *
+ * @param testDirectory new test directory
+ */
+ protected void setServiceDirectory(ServiceDirectory testDirectory) {
+ TestUtils.setField(BaseResource.class, "services", testDirectory);
+ }
}
diff --git a/web/api/src/test/java/org/onosproject/rest/resources/StatisticsResourceTest.java b/web/api/src/test/java/org/onosproject/rest/resources/StatisticsResourceTest.java
index 66b6eb0..a1bbccb 100644
--- a/web/api/src/test/java/org/onosproject/rest/resources/StatisticsResourceTest.java
+++ b/web/api/src/test/java/org/onosproject/rest/resources/StatisticsResourceTest.java
@@ -24,7 +24,6 @@
import org.junit.Test;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.TestServiceDirectory;
-import org.onlab.rest.BaseResource;
import org.onosproject.codec.CodecService;
import org.onosproject.codec.impl.CodecManager;
import org.onosproject.net.Link;
@@ -92,7 +91,7 @@
.add(StatisticService.class, mockStatisticService)
.add(CodecService.class, codecService);
- BaseResource.setServiceDirectory(testDirectory);
+ setServiceDirectory(testDirectory);
}
/**
diff --git a/web/api/src/test/java/org/onosproject/rest/resources/TenantWebResourceTest.java b/web/api/src/test/java/org/onosproject/rest/resources/TenantWebResourceTest.java
index 69bd45b..781cfae 100644
--- a/web/api/src/test/java/org/onosproject/rest/resources/TenantWebResourceTest.java
+++ b/web/api/src/test/java/org/onosproject/rest/resources/TenantWebResourceTest.java
@@ -28,7 +28,6 @@
import org.junit.Test;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.TestServiceDirectory;
-import org.onlab.rest.BaseResource;
import org.onosproject.codec.CodecService;
import org.onosproject.codec.impl.CodecManager;
import org.onosproject.incubator.net.virtual.TenantId;
@@ -44,9 +43,19 @@
import java.net.HttpURLConnection;
import java.util.HashSet;
-import static org.easymock.EasyMock.*;
-import static org.hamcrest.Matchers.*;
-import static org.junit.Assert.*;
+import static org.easymock.EasyMock.anyObject;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
/**
* Unit tests for tenant REST APIs.
@@ -77,7 +86,7 @@
.add(VirtualNetworkAdminService.class, mockVnetAdminService)
.add(CodecService.class, codecService);
- BaseResource.setServiceDirectory(testDirectory);
+ setServiceDirectory(testDirectory);
}
/**
diff --git a/web/api/src/test/java/org/onosproject/rest/resources/TopologyResourceTest.java b/web/api/src/test/java/org/onosproject/rest/resources/TopologyResourceTest.java
index 95a7416..4499a25 100644
--- a/web/api/src/test/java/org/onosproject/rest/resources/TopologyResourceTest.java
+++ b/web/api/src/test/java/org/onosproject/rest/resources/TopologyResourceTest.java
@@ -23,16 +23,15 @@
import org.junit.Test;
import org.onlab.osgi.ServiceDirectory;
import org.onlab.osgi.TestServiceDirectory;
-import org.onlab.rest.BaseResource;
import org.onosproject.codec.CodecService;
import org.onosproject.codec.impl.CodecManager;
import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DefaultPort;
+import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
-import org.onosproject.net.Device;
-import org.onosproject.net.PortNumber;
-import org.onosproject.net.DefaultPort;
import org.onosproject.net.Port;
+import org.onosproject.net.PortNumber;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.device.DeviceServiceAdapter;
import org.onosproject.net.provider.ProviderId;
@@ -43,8 +42,10 @@
import org.onosproject.net.topology.TopologyCluster;
import org.onosproject.net.topology.TopologyService;
import org.onosproject.net.topology.TopologyServiceAdapter;
+
import javax.ws.rs.client.WebTarget;
import java.util.Set;
+
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
@@ -183,7 +184,7 @@
.add(DeviceService.class, mockDeviceService)
.add(TopologyService.class, topologyService)
.add(CodecService.class, codecService);
- BaseResource.setServiceDirectory(testDirectory);
+ setServiceDirectory(testDirectory);
}
/**
diff --git a/web/api/src/test/java/org/onosproject/rest/resources/VirtualNetworkWebResourceTest.java b/web/api/src/test/java/org/onosproject/rest/resources/VirtualNetworkWebResourceTest.java
index 97c703b..2ab185c 100644
--- a/web/api/src/test/java/org/onosproject/rest/resources/VirtualNetworkWebResourceTest.java
+++ b/web/api/src/test/java/org/onosproject/rest/resources/VirtualNetworkWebResourceTest.java
@@ -33,7 +33,6 @@
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onlab.packet.VlanId;
-import org.onlab.rest.BaseResource;
import org.onosproject.codec.CodecService;
import org.onosproject.codec.impl.CodecManager;
import org.onosproject.incubator.net.virtual.DefaultVirtualDevice;
@@ -75,8 +74,16 @@
import java.util.function.BiPredicate;
import java.util.function.Function;
-import static org.easymock.EasyMock.*;
-import static org.hamcrest.Matchers.*;
+import static org.easymock.EasyMock.anyObject;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
@@ -187,7 +194,7 @@
.add(VirtualNetworkService.class, mockVnetService)
.add(CodecService.class, codecService);
- BaseResource.setServiceDirectory(testDirectory);
+ setServiceDirectory(testDirectory);
}
/**
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/ApplicationResource.java b/web/gui/src/main/java/org/onosproject/ui/impl/ApplicationResource.java
index 16f288a..d8f5a44 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/ApplicationResource.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/ApplicationResource.java
@@ -41,7 +41,8 @@
@Path("applications")
public class ApplicationResource extends BaseResource {
- static String lastInstalledAppName = null;
+ private static String lastInstalledAppName = null;
+ private static final Object LAST_INSTALLED_APP_NAME_LOCK = new Object();
@Path("upload")
@@ -51,7 +52,9 @@
@FormDataParam("file") InputStream stream) throws IOException {
ApplicationAdminService service = get(ApplicationAdminService.class);
Application app = service.install(stream);
- lastInstalledAppName = app.id().name();
+ synchronized (LAST_INSTALLED_APP_NAME_LOCK) {
+ lastInstalledAppName = app.id().name();
+ }
if (Objects.equals(activate, "true")) {
service.activate(app.id());
}
@@ -87,4 +90,10 @@
Application app = service.getApplication(appId);
return Response.ok(app.icon()).build();
}
+
+ static String getLastInstalledAppName() {
+ synchronized (LAST_INSTALLED_APP_NAME_LOCK) {
+ return lastInstalledAppName;
+ }
+ }
}
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/ApplicationViewMessageHandler.java b/web/gui/src/main/java/org/onosproject/ui/impl/ApplicationViewMessageHandler.java
index 984dce2..6ed92a5 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/ApplicationViewMessageHandler.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/ApplicationViewMessageHandler.java
@@ -172,7 +172,7 @@
// If the ID was not specified in the payload, use the name of the
// most recently uploaded app.
if (isNullOrEmpty(id)) {
- id = ApplicationResource.lastInstalledAppName;
+ id = ApplicationResource.getLastInstalledAppName();
}
ApplicationId appId = as.getId(id);
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/UiWebSocket.java b/web/gui/src/main/java/org/onosproject/ui/impl/UiWebSocket.java
index 07a0b0d..ea7e5ed 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/UiWebSocket.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/UiWebSocket.java
@@ -218,15 +218,19 @@
@Override
public synchronized void onClose(int closeCode, String message) {
try {
- tokenService().revokeToken(sessionToken);
- log.info("Session token revoked");
- } catch (ServiceNotFoundException e) {
- log.error("Unable to reference UiTokenService");
- }
- sessionToken = null;
+ try {
+ tokenService().revokeToken(sessionToken);
+ log.info("Session token revoked");
+ } catch (ServiceNotFoundException e) {
+ log.error("Unable to reference UiTokenService");
+ }
+ sessionToken = null;
- topoSession.destroy();
- destroyHandlersAndOverlays();
+ topoSession.destroy();
+ destroyHandlersAndOverlays();
+ } catch (Exception e) {
+ log.warn("Unexpected error", e);
+ }
log.info("GUI client disconnected [close-code={}, message={}]",
closeCode, message);
}
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/UiWebSocketServlet.java b/web/gui/src/main/java/org/onosproject/ui/impl/UiWebSocketServlet.java
index 24e02e6..cfd2025 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/UiWebSocketServlet.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/UiWebSocketServlet.java
@@ -38,6 +38,7 @@
private static final long PING_DELAY_MS = 5000;
private static UiWebSocketServlet instance;
+ private static final Object INSTANCE_LOCK = new Object();
private ServiceDirectory directory = new DefaultServiceDirectory();
@@ -50,19 +51,23 @@
* Closes all currently open UI web-sockets.
*/
public static void closeAll() {
- if (instance != null) {
- instance.isStopped = true;
- instance.sockets.forEach(UiWebSocket::close);
- instance.sockets.clear();
- instance.pruner.cancel();
- instance.timer.cancel();
+ synchronized (INSTANCE_LOCK) {
+ if (instance != null) {
+ instance.isStopped = true;
+ instance.sockets.forEach(UiWebSocket::close);
+ instance.sockets.clear();
+ instance.pruner.cancel();
+ instance.timer.cancel();
+ }
}
}
@Override
public void init() throws ServletException {
super.init();
- instance = this;
+ synchronized (INSTANCE_LOCK) {
+ instance = this;
+ }
timer.schedule(pruner, PING_DELAY_MS, PING_DELAY_MS);
}
@@ -93,8 +98,10 @@
* @param payload message payload
*/
static void sendToAll(String type, ObjectNode payload) {
- if (instance != null) {
- instance.sockets.forEach(ws -> ws.sendMessage(type, payload));
+ synchronized (INSTANCE_LOCK) {
+ if (instance != null) {
+ instance.sockets.forEach(ws -> ws.sendMessage(type, payload));
+ }
}
}
@@ -106,9 +113,11 @@
* @param payload message payload
*/
static void sendToUser(String userName, String type, ObjectNode payload) {
- if (instance != null) {
- instance.sockets.stream().filter(ws -> userName.equals(ws.userName()))
- .forEach(ws -> ws.sendMessage(type, payload));
+ synchronized (INSTANCE_LOCK) {
+ if (instance != null) {
+ instance.sockets.stream().filter(ws -> userName.equals(ws.userName()))
+ .forEach(ws -> ws.sendMessage(type, payload));
+ }
}
}
diff --git a/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Action_el.properties b/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Action_el.properties
new file mode 100644
index 0000000..88b41c3
--- /dev/null
+++ b/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Action_el.properties
@@ -0,0 +1,25 @@
+#
+# Copyright 2017-present Open Networking Laboratory
+#
+# 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.
+#
+#
+
+install=Εγκατάσταση
+start=Εκκίνηση
+pause=Παύση
+resume=Επανέναρξη
+stop=Τερματισμός
+uninstall=Απεγκατάσταση
+activate=Ενεργοποίηση
+deactivate=Απενεργοποίηση
\ No newline at end of file
diff --git a/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Network_el.properties b/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Network_el.properties
new file mode 100644
index 0000000..b16f5ca
--- /dev/null
+++ b/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Network_el.properties
@@ -0,0 +1,49 @@
+#
+# Copyright 2017-present Open Networking Laboratory
+#
+# 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.
+#
+#
+# --- Elements (Singular)
+node=Κόμβος
+topology=Τοπολογία
+network=Δίκτυο
+region=Περιοχή
+device=Συσκευή
+host=Τερματικό
+link=Σύνδεσμος
+
+# --- Elements (Plural)
+nodes=Κόμβοι
+topologies=Τοπολογίες
+networks=Δίκτυα
+regions=Περιοχές
+devices=Συσκευές
+hosts=Τερματικά
+links=Σύνδεσμοι
+
+# --- Element IDs
+node_id=ID κόμβου
+region_id=ID περιοχής
+device_id=ID συσκευής
+host_id=ID τερματικού
+link_id=ID συνδέσμου
+
+# --- Protocol terms
+protocol=πρωτόκολλο
+ip=IP
+ip_address=IP διεύθυνση
+tcp_port=TCP θύρα
+mac=MAC
+mac_address=MAC διεύθυνση
+uri=URI
\ No newline at end of file
diff --git a/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Props_el.properties b/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Props_el.properties
new file mode 100644
index 0000000..18c56b0
--- /dev/null
+++ b/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Props_el.properties
@@ -0,0 +1,34 @@
+#
+# Copyright 2017-present Open Networking Laboratory
+#
+# 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.
+#
+#
+
+# Typically used as table column headers or property labels
+
+chassis_id=ID πλαισίου
+hw_version=Έκδοση υλικού
+sw_version=Έκδοση λογισμικού
+serial_number=Σειριακός αριθμός
+app_id=ID εφαρμογής
+
+type=Τύπος
+vendor=Προμηθευτής
+icon=Εικόνα
+title=Τίτλος
+state=Κατάσταση
+category=Κατηγορία
+version=Έκδοση
+origin=Προέλευση
+role=Ρόλος
\ No newline at end of file
diff --git a/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/State_el.properties b/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/State_el.properties
new file mode 100644
index 0000000..741d34c
--- /dev/null
+++ b/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/State_el.properties
@@ -0,0 +1,25 @@
+
+#
+# Copyright 2017-present Open Networking Laboratory
+#
+# 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.
+#
+#
+
+total=Σύνολο
+active=Ενεργά
+started=Ξεκίνησαν
+stopped=Σταμάτησαν
+
+last_updated=Τελευταία ενημέρωση
+last_modified=Τελευταία τροποποίηση
\ No newline at end of file
diff --git a/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Ui_el.properties b/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Ui_el.properties
new file mode 100644
index 0000000..7543ba7
--- /dev/null
+++ b/web/gui/src/main/resources/org/onosproject/ui/lion/core/common/Ui_el.properties
@@ -0,0 +1,27 @@
+#
+# Copyright 2017-present Open Networking Laboratory
+#
+# 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.
+#
+#
+
+# Common button text
+ok=Οκ
+cancel=Άκυρο
+
+# Gesture text
+click=Κάντε κλικ
+scroll_down=Μετακίνηση προς τα κάτω
+
+# Common control button tooltips
+tt_ctl_auto_refresh=Εναλλαγή αυτόματης ανανέωσης
\ No newline at end of file
diff --git a/web/gui/src/main/resources/org/onosproject/ui/lion/core/enums/DeviceEnums_el.properties b/web/gui/src/main/resources/org/onosproject/ui/lion/core/enums/DeviceEnums_el.properties
new file mode 100644
index 0000000..9c5b0cd
--- /dev/null
+++ b/web/gui/src/main/resources/org/onosproject/ui/lion/core/enums/DeviceEnums_el.properties
@@ -0,0 +1,34 @@
+#
+# 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.
+#
+
+# display names for Device.Type constants
+switch=μεταγωγέας
+router=δρομολογητής
+roadm=roadm
+otn=otn
+roadm_otn=roadm otn
+firewall=τείχος προστασίας
+balancer=εξισορροπιστής
+ips=ips
+ids=ids
+controller=ελεγχτής
+virtual=εικονικός
+fiber_switch=μεταγωγέας ίνας
+microwave=μικροκυματικός
+olt=olt
+onu=onu
+optical_amplifier=οπτικός ενισχυτής
+other=άλλο
\ No newline at end of file
diff --git a/web/gui/src/main/resources/org/onosproject/ui/lion/core/enums/LinkEnums_el.properties b/web/gui/src/main/resources/org/onosproject/ui/lion/core/enums/LinkEnums_el.properties
new file mode 100644
index 0000000..5817212
--- /dev/null
+++ b/web/gui/src/main/resources/org/onosproject/ui/lion/core/enums/LinkEnums_el.properties
@@ -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.
+#
+
+# display names for Link.Type constants
+direct=άμεση
+indirect=έμμεση
+edge=ακμή
+tunnel=σήραγγα
+optical=οπτικό
+virtual=εικονικό
+
+# display names for Link.State constants
+active=ενεργό
+inactive=ανενεργό
\ No newline at end of file
diff --git a/web/gui/src/main/resources/org/onosproject/ui/lion/core/fw/Mast_el.properties b/web/gui/src/main/resources/org/onosproject/ui/lion/core/fw/Mast_el.properties
new file mode 100644
index 0000000..2c22c2b
--- /dev/null
+++ b/web/gui/src/main/resources/org/onosproject/ui/lion/core/fw/Mast_el.properties
@@ -0,0 +1,32 @@
+#
+# Copyright 2017-present Open Networking Laboratory
+#
+# 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.
+#
+#
+# Localization strings for Masthead
+
+# Tooltip for context-sensitive help button [?]
+tt_help=Εμφάνιση βοήθειας
+
+# unknown user
+unknown_user=Άγνωστος χρήστης
+
+# Logout button
+logout=Έξοδος
+
+# UI components added/removed, etc.
+uicomp_added=Προστέθηκαν νέα στοιχεία GUI.
+uicomp_removed=Ορισμένα στοιχεία GUI καταργήθηκαν.
+ui_ok_to_update=Πατήστε OK για ενημέρωση του GUI.
+confirm_refresh_title=Επιβεβαίωση ανανέωσης GUI.
\ No newline at end of file
diff --git a/web/gui/src/main/resources/org/onosproject/ui/lion/core/fw/Nav_el.properties b/web/gui/src/main/resources/org/onosproject/ui/lion/core/fw/Nav_el.properties
new file mode 100644
index 0000000..29eede1
--- /dev/null
+++ b/web/gui/src/main/resources/org/onosproject/ui/lion/core/fw/Nav_el.properties
@@ -0,0 +1,29 @@
+#
+# Copyright 2017-present Open Networking Laboratory
+#
+# 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.
+#
+#
+# Localization strings for Navigation Panel
+
+# Category headers
+cat_platform=Πλατφόρμα
+cat_network=Δίκτυο
+cat_other=Άλλο
+
+# Note that contributed views will be adding their own localized titles
+# for their nav item, with a property key "nav_item_{viewID}".
+#
+# E.g. in the Device view properties bundle there will be:
+#
+# nav_item_device=Devices
\ No newline at end of file
diff --git a/web/gui/src/main/resources/org/onosproject/ui/lion/core/fw/QuickHelp_el.properties b/web/gui/src/main/resources/org/onosproject/ui/lion/core/fw/QuickHelp_el.properties
new file mode 100644
index 0000000..e053af5
--- /dev/null
+++ b/web/gui/src/main/resources/org/onosproject/ui/lion/core/fw/QuickHelp_el.properties
@@ -0,0 +1,32 @@
+#
+# Copyright 2017-present Open Networking Laboratory
+#
+# 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.
+#
+#
+# Common text in the Quick Help panel
+
+# Panel title
+qh_title=Γρήγορη βοήθεια
+
+# Hint for \ and / keys
+qh_hint_show_hide_qh=Εμφάνιση / Απόκρυψη Γρήγορης βοήθειας
+
+# Escape key hint
+qh_hint_esc=Διαγραφή διαλόγου ή ακύρωση επιλογών
+
+# T key hint : toggle the ui theme (between light / dark)
+qh_hint_t=Εναλλαγή θέματος
+
+# Common for a lot of views adding their own escape-key handler
+qh_hint_close_detail=Κλείσιμο πίνακα λεπτομερειών
\ No newline at end of file
diff --git a/web/gui/src/main/resources/org/onosproject/ui/lion/core/view/App_el.properties b/web/gui/src/main/resources/org/onosproject/ui/lion/core/view/App_el.properties
new file mode 100644
index 0000000..67547b0
--- /dev/null
+++ b/web/gui/src/main/resources/org/onosproject/ui/lion/core/view/App_el.properties
@@ -0,0 +1,45 @@
+#
+# Copyright 2017-present Open Networking Laboratory
+#
+# 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.
+#
+#
+
+# Text that appears in the navigation panel
+nav_item_app=Εφαρμογές
+
+# View title
+title_apps=Εφαρμογές
+
+# Control button tooltips
+tt_ctl_upload=Ανέβασμα εφαρμογής (.oar αρχείο)
+tt_ctl_activate=Ενεργοποίηση επιλεγμένης εφαρμογής
+tt_ctl_deactivate=Απενεργοποίηση επιλεγμένης εφαρμογής
+tt_ctl_uninstall=Απεγκατάσταση επιλεγμένης εφαρμογής
+
+# Quick-Help panel
+qh_hint_esc=Αποεπιλογή εφαρμογής
+qh_hint_click_row=Επιλογή / Αποεπιλογή εφαρμογής
+qh_hint_scroll_down=Περισσότερες εφαρμογές
+
+# App details panel
+dp_features=Χαρακτηριστικά
+dp_required_apps=Απαραίτητες εφαρμογές
+dp_permissions=Άδειες
+
+# App dialog panel
+dlg_confirm_action=Επιβεβαίωση Ενέργειας
+
+dlg_warn_deactivate=Απενεργοποίηση ή απεγκατάσταση αυτού του στοιχείου \
+ Μπορεί να έχει σοβαρές αρνητικές συνέπειες!
+dlg_warn_own_risk=** Ενεργείστε με δική σας ευθύνη **
\ No newline at end of file
diff --git a/web/gui/src/main/resources/org/onosproject/ui/lion/core/view/Cluster_el.properties b/web/gui/src/main/resources/org/onosproject/ui/lion/core/view/Cluster_el.properties
new file mode 100644
index 0000000..e10bbe6
--- /dev/null
+++ b/web/gui/src/main/resources/org/onosproject/ui/lion/core/view/Cluster_el.properties
@@ -0,0 +1,27 @@
+#
+# Copyright 2017-present Open Networking Laboratory
+#
+# 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.
+#
+#
+# Cluster view specific text
+
+# Text that appears in the navigation panel
+nav_item_cluster=Κόμβοι συστάδας
+
+# View title
+title_cluster_nodes=Κόμβοι συστάδας
+
+# Quick-Help panel
+qh_hint_click=Επιλέξτε μια γραμμή για να εμφανίσετε λεπτομέρειες κόμβου συστάδας
+qh_hint_scroll_down=Δείτε διαθέσιμους κόμβους στη συστάδα
\ No newline at end of file
diff --git a/web/gui/src/main/resources/org/onosproject/ui/lion/core/view/Topo_el.properties b/web/gui/src/main/resources/org/onosproject/ui/lion/core/view/Topo_el.properties
new file mode 100644
index 0000000..356592d9
--- /dev/null
+++ b/web/gui/src/main/resources/org/onosproject/ui/lion/core/view/Topo_el.properties
@@ -0,0 +1,143 @@
+#
+# 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.
+#
+#
+
+# Text that appears in the navigation panel
+nav_item_topo=Τοπολογία
+
+# Message when no devices are connected
+no_devices_are_connected=Δεν υπάρχουν συνδεδεμένες συσκευές
+
+# Action Key Toolbar Tooltips ...
+tbtt_tog_instances=Εναλλαγή πίνακα στιγμιοτύπων του ONOS
+tbtt_tog_summary=Εναλλαγή περιληπτικού πίνακα ONOS
+tbtt_tog_use_detail=Απενεργοποίηση / Ενεργοποίηση πίνακα λεπτομερειών
+tbtt_tog_host=Εναλλαγή ορατότητας υπολογιστών
+tbtt_tog_offline=Εναλλαγή ορατότητας εκτός σύνδεσης
+tbtt_tog_porthi=Εναλλαγή επισήμανσης θυρών
+tbtt_bad_links=Εμφάνιση κακών συνδέσμων
+tbtt_tog_map=Εναλλαγή γεωγραφικού χάρτη στο φόντο
+tbtt_sel_map=Επιλογή γεωγραφικού χάρτη στο φόντο
+tbtt_tog_sprite=Εναλλαγή επιπέδου sprite
+tbtt_reset_loc=Επαναφορά τοποθεσιών κόμβου
+tbtt_tog_oblique=Εναλλαγή πλάγιας προβολής (πειραματικά)
+tbtt_cyc_layers=Στρώμα κόμβων κύκλων
+tbtt_cyc_dev_labs=Κύκλος ετικετών συσκευής
+tbtt_cyc_host_labs=Κύκλος ετικετών υποδοχής
+tbtt_unpin_node=Αποσύνδεση κόμβου (μετακινήστε το ποντίκι πάνω)
+tbtt_reset_zoom=Επαναφορά πανοραμτικής όψης/ζουμ
+tbtt_tog_toolbar=Εναλλαγή γραμμής εργαλείων
+tbtt_eq_master=Εξίσωση ρόλων κυριότητας
+
+# Quick Help Gestures
+qh_gest_click=Επέλεξε το αντικείμενο και δείξε πληροφορίες
+qh_gest_shift_click=Εναλλαγή κατάστασης επιλογής
+qh_gest_drag=Επανατοποθέτηση και σήμανση της συσκευής/υπολογιστή
+qh_gest_cmd_scroll=Μεγένθυση / Σμίκρυνση
+qh_gest_cmd_drag=Πανοραμική όψη
+
+# Flash Messages
+fl_background_map=Χάρτης φόντου
+fl_sprite_layer=sprite επίπεδο
+fl_pan_zoom_reset=Επαναφορά πανοραμικής όψης και ζουμ
+fl_eq_masters=Εξισορρόπηση ρόλων κυριότητας
+
+fl_device_labels_hide=Απόκρυψη ετικετών συσκευών
+fl_device_labels_show_friendly=Εμφάνιση φιλικών ετικετών συσκευών
+fl_device_labels_show_id=Εμφάνιση ετικετών ταυτότητας συσκευής
+fl_host_labels_show_friendly=Εμφάνιση φιλικών ετικετών υπολογιστών
+fl_host_labels_show_ip=Εμφάνιση διευθύνσεων IP υπολογιστών
+fl_host_labels_show_mac=Εμφάνιση διευθύνσεων MAC υπολογιστών
+
+fl_offline_devices=Συσκευές εκτός σύνδεσης
+fl_bad_links=Κακοί σύνδεσμοι
+fl_reset_node_locations=Επαναφορά τοποθεσιών κόμβων
+
+fl_layer_all=Εμφάνιση όλων των επιπέδων
+fl_layer_pkt=Εμφάνιση επιπέδου πακέτων
+fl_layer_opt=Εμφάνιση οπτικού επιπέδου
+
+fl_panel_instances=Πίνακας στιγμιοτύπων
+fl_panel_summary=Πίνακας περίληψης
+fl_panel_details=Πίνακας λεπτομεριών
+
+fl_port_highlighting=Σήμανση θυρών
+
+fl_oblique_view=Πλάγια όψη
+fl_normal_view=Κανονική όψη
+
+fl_monitoring_canceled=Ακύρωση παρακολούθησης
+fl_selecting_intent=Επιλογή κατάστασης
+
+# Core Overlays
+ov_tt_protected_intents=Προστατευόμενη επικάλυψη καταστάσεων
+ov_tt_traffic=Επικάλυψη κίνησης
+ov_tt_none=Καμία επικάλυψη
+
+# Traffic Overlay
+tr_btn_create_h2h_flow=Δημιουργία ροής από υπολογιστή σε υπολογιστή
+tr_btn_create_msrc_flow=Δημιουργία ροής πολλαπλών πηγών
+tr_btn_show_device_flows=Εμφάνιση ροών συσκευών
+tr_btn_show_related_traffic=Εμφάνιση σχετικής κίνησης
+tr_btn_cancel_monitoring=Ακύρωση παρακολούθησης κίνησης
+tr_btn_monitor_all=Παρακολούθηση όλης της κίνησης
+tr_btn_show_dev_link_flows=Εμφάνιση των ροών συνδέσμων των συσκευών
+tr_btn_show_all_rel_intents=Εμφάνιση όλων των σχετικών καταστάσεων
+tr_btn_show_prev_rel_intent=Προηγούμενη σχετική κατάσταση
+tr_btn_show_next_rel_intent=Επόμενη σχετική κατάσταση
+tr_btn_monitor_sel_intent=Παρακολούθηση κίνησης ή επιλεγμένης κατάστασης
+tr_fl_fstats_bytes=Στατιστικά ροών (ψηφιολέξεις)
+tr_fl_pstats_bits=Στατιστικά θυρών (δυαδικά ψηφία / δευτερόλεπτο)
+tr_fl_pstats_pkts=Στατιστικά θυρών (πακέτα / δευτερόλεπτο)
+tr_fl_dev_flows=Ροές συσκευών
+tr_fl_rel_paths=Σχετικά μονοπάτια
+tr_fl_prev_rel_int=Προηγούμενη σχετική κατάσταση
+tr_fl_next_rel_int=Επόμενη σχετική κατάσταση
+tr_fl_traf_on_path=Κίνηση σε επιλεγμένο μονοπάτι
+tr_fl_h2h_flow_added=Προσθήκη ροής από υπολογιστή σε υπολογιστή
+tr_fl_multisrc_flow=Ροή πολλών πηγών
+
+# Button tooltips
+btn_show_view_device=Εμφανιση προβολής συσκευών
+btn_show_view_flow=Εμφάνιση προβολής ροών για τη συσκευή
+btn_show_view_port=Εμφάνιση προβολής θυρών για τη συσκευή
+btn_show_view_group=Εμφάνιση προβολής ομάδων για τη συσκευή
+btn_show_view_meter=Εμφάνιση προβολής μετρητών για τη συσκευή
+
+# Panel Titles
+title_select_map=Επιλογή χάρτη
+title_panel_summary=Περίληψη ONOS
+title_selected_items=Επιλεγμένα αντικείμενα
+title_edge_link=Συνδεσμός ακμής
+title_infra_link=Σύνδεσμος υποδομής
+
+# Custom Panel Labels / Values
+lp_label_friendly=Φιλική
+
+lp_label_a_type=A τύπος
+lp_label_a_id=A ταυτότητα
+lp_label_a_friendly=A όνομα
+lp_label_a_port=A θύρα
+
+lp_label_b_type=B τύπος
+lp_label_b_id=B ταυτότητα
+lp_label_b_friendly=B όνομα
+lp_label_b_port=B θύρα
+
+lp_label_a2b=A σε B
+lp_label_b2a=B σε A
+
+lp_value_no_link=[Κανένας σύνδεσμος]