From b731e2f1dd0972409b136aebc7b463dd72c9cfad Mon Sep 17 00:00:00 2001 From: CNlucius Date: Tue, 13 Sep 2016 11:40:12 +0800 Subject: ONOSFW-171 O/S-SFC-ONOS scenario documentation Change-Id: I51ae1cf736ea24ab6680f8edca1b2bf5dd598365 Signed-off-by: CNlucius --- .../org/onosproject/driver/DefaultDrivers.java | 69 - .../extensions/DefaultMoveExtensionTreatment.java | 146 -- .../driver/extensions/MoveExtensionTreatment.java | 59 - .../NiciraExtensionSelectorInterpreter.java | 102 -- .../NiciraExtensionTreatmentInterpreter.java | 186 -- .../extensions/NiciraMatchNshContextHeader.java | 95 -- .../driver/extensions/NiciraMatchNshSi.java | 91 - .../driver/extensions/NiciraMatchNshSpi.java | 91 - .../extensions/NiciraMoveTreatmentFactory.java | 100 -- .../driver/extensions/NiciraResubmit.java | 108 -- .../driver/extensions/NiciraResubmitTable.java | 114 -- .../extensions/NiciraSetNshContextHeader.java | 108 -- .../driver/extensions/NiciraSetNshSi.java | 101 -- .../driver/extensions/NiciraSetNshSpi.java | 101 -- .../driver/extensions/NiciraSetTunnelDst.java | 110 -- .../driver/extensions/package-info.java | 19 - .../handshaker/CalientFiberSwitchHandshaker.java | 221 --- .../driver/handshaker/CorsaSwitchHandshaker.java | 92 - .../driver/handshaker/DefaultSwitchHandshaker.java | 67 - .../driver/handshaker/NiciraSwitchHandshaker.java | 34 - .../driver/handshaker/OFOpticalSwitch13.java | 179 -- .../handshaker/OfOpticalSwitchImplLinc13.java | 385 ----- .../driver/handshaker/package-info.java | 20 - .../driver/netconf/NetconfControllerConfig.java | 89 - .../driver/netconf/XmlConfigParser.java | 126 -- .../onosproject/driver/netconf/package-info.java | 20 - .../driver/ovsdb/OvsdbBridgeConfig.java | 181 -- .../driver/ovsdb/OvsdbControllerConfig.java | 103 -- .../driver/ovsdb/OvsdbTunnelConfig.java | 142 -- .../org/onosproject/driver/ovsdb/package-info.java | 20 - .../java/org/onosproject/driver/package-info.java | 20 - .../driver/pipeline/CentecV350Pipeline.java | 640 ------- .../onosproject/driver/pipeline/CorsaPipeline.java | 76 - .../driver/pipeline/CpqdOFDPA2Pipeline.java | 497 ------ .../pipeline/DefaultSingleTablePipeline.java | 129 -- .../driver/pipeline/OFDPA2Pipeline.java | 1792 -------------------- .../driver/pipeline/OVSCorsaPipeline.java | 829 --------- .../onosproject/driver/pipeline/OltPipeline.java | 238 --- .../driver/pipeline/OpenVSwitchPipeline.java | 241 --- .../driver/pipeline/OpenstackPipeline.java | 286 ---- .../onosproject/driver/pipeline/PicaPipeline.java | 543 ------ .../driver/pipeline/SoftRouterPipeline.java | 544 ------ .../onosproject/driver/pipeline/SpringOpenTTP.java | 1101 ------------ .../driver/pipeline/SpringOpenTTPDell.java | 204 --- .../onosproject/driver/pipeline/package-info.java | 20 - 45 files changed, 10439 deletions(-) delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/DefaultDrivers.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/DefaultMoveExtensionTreatment.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/MoveExtensionTreatment.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraExtensionSelectorInterpreter.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraExtensionTreatmentInterpreter.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshContextHeader.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshSi.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshSpi.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMoveTreatmentFactory.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraResubmit.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraResubmitTable.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetNshContextHeader.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetNshSi.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetNshSpi.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetTunnelDst.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/package-info.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/CalientFiberSwitchHandshaker.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/CorsaSwitchHandshaker.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/DefaultSwitchHandshaker.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/NiciraSwitchHandshaker.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/OFOpticalSwitch13.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/OfOpticalSwitchImplLinc13.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/package-info.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/netconf/NetconfControllerConfig.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/netconf/XmlConfigParser.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/netconf/package-info.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/ovsdb/OvsdbBridgeConfig.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/ovsdb/OvsdbControllerConfig.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/ovsdb/OvsdbTunnelConfig.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/ovsdb/package-info.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/package-info.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CentecV350Pipeline.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CorsaPipeline.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CpqdOFDPA2Pipeline.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/DefaultSingleTablePipeline.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OFDPA2Pipeline.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OVSCorsaPipeline.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OltPipeline.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OpenVSwitchPipeline.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OpenstackPipeline.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/PicaPipeline.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SoftRouterPipeline.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTP.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTPDell.java delete mode 100644 framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/package-info.java (limited to 'framework/src/onos/drivers/src/main/java/org/onosproject/driver') diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/DefaultDrivers.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/DefaultDrivers.java deleted file mode 100644 index 83adcde7..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/DefaultDrivers.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2015 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. - */ -package org.onosproject.driver; - -import org.apache.felix.scr.annotations.Activate; -import org.apache.felix.scr.annotations.Component; -import org.apache.felix.scr.annotations.Deactivate; -import org.apache.felix.scr.annotations.Reference; -import org.apache.felix.scr.annotations.ReferenceCardinality; -import org.apache.felix.scr.annotations.Service; -import org.onosproject.net.driver.DefaultDriverProviderService; -import org.onosproject.net.driver.DriverAdminService; -import org.onosproject.net.driver.DriverProvider; -import org.onosproject.net.driver.XmlDriverLoader; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.InputStream; - -/** - * Bootstrap for built in drivers. - */ -@Service -@Component(immediate = false) -public class DefaultDrivers implements DefaultDriverProviderService { - - private final Logger log = LoggerFactory.getLogger(getClass()); - - private static final String DRIVERS_XML = "/onos-drivers.xml"; - - private DriverProvider provider; - - @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY) - protected DriverAdminService driverAdminService; - - @Activate - protected void activate() { - ClassLoader classLoader = getClass().getClassLoader(); - try { - InputStream stream = classLoader.getResourceAsStream(DRIVERS_XML); - provider = new XmlDriverLoader(classLoader) - .loadDrivers(stream, driverAdminService); - driverAdminService.registerProvider(provider); - } catch (Exception e) { - log.error("Unable to load default drivers", e); - } - log.info("Started"); - } - - @Deactivate - protected void deactivate() { - driverAdminService.unregisterProvider(provider); - log.info("Stopped"); - } - -} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/DefaultMoveExtensionTreatment.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/DefaultMoveExtensionTreatment.java deleted file mode 100644 index 140a8167..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/DefaultMoveExtensionTreatment.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright 2015 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. - */ -package org.onosproject.driver.extensions; - -import java.util.Map; -import java.util.Objects; - -import org.onlab.util.KryoNamespace; -import org.onosproject.net.flow.AbstractExtension; -import org.onosproject.net.flow.instructions.ExtensionTreatmentType; - -import com.google.common.base.MoreObjects; -import com.google.common.collect.Maps; - -/** - * Default implementation of Move treatment. - */ -public class DefaultMoveExtensionTreatment extends AbstractExtension - implements MoveExtensionTreatment { - - private int srcOfs; - private int dstOfs; - private int nBits; - private int src; - private int dst; - private ExtensionTreatmentType type; - - private final KryoNamespace appKryo = new KryoNamespace.Builder() - .register(byte[].class).register(Integer.class).register(Map.class) - .build(); - - /** - * Creates a new move Treatment. - * - * @param srcOfs source offset - * @param dstOfs destination offset - * @param nBits nbits - * @param src source - * @param dst destination - * @param type extension treatment type - */ - public DefaultMoveExtensionTreatment(int srcOfs, int dstOfs, int nBits, - int src, int dst, ExtensionTreatmentType type) { - this.srcOfs = srcOfs; - this.dstOfs = dstOfs; - this.nBits = nBits; - this.src = src; - this.dst = dst; - this.type = type; - } - - @Override - public ExtensionTreatmentType type() { - return type; - } - - @Override - public byte[] serialize() { - Map values = Maps.newHashMap(); - values.put("srcOfs", srcOfs); - values.put("dstOfs", dstOfs); - values.put("nBits", nBits); - values.put("src", src); - values.put("dst", dst); - values.put("type", ExtensionTreatmentType.ExtensionTreatmentTypes.valueOf(type.toString()).ordinal()); - return appKryo.serialize(values); - } - - @Override - public void deserialize(byte[] data) { - Map values = appKryo.deserialize(data); - srcOfs = values.get("srcOfs"); - dstOfs = values.get("dstOfs"); - nBits = values.get("nBits"); - src = values.get("src"); - dst = values.get("dst"); - type = new ExtensionTreatmentType(values.get("type").intValue()); - } - - @Override - public int srcOffset() { - return srcOfs; - } - - @Override - public int dstOffset() { - return dstOfs; - } - - @Override - public int src() { - return src; - } - - @Override - public int dst() { - return dst; - } - - @Override - public int nBits() { - return nBits; - } - - @Override - public int hashCode() { - return Objects.hash(srcOfs, dstOfs, src, dst, nBits); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof DefaultMoveExtensionTreatment) { - DefaultMoveExtensionTreatment that = (DefaultMoveExtensionTreatment) obj; - return Objects.equals(srcOfs, that.srcOfs) - && Objects.equals(dstOfs, that.dstOfs) - && Objects.equals(src, that.src) - && Objects.equals(dst, that.dst) - && Objects.equals(nBits, that.nBits); - - } - return false; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()).add("srcOfs", srcOfs) - .add("dstOfs", dstOfs).add("nBits", nBits).add("src", src) - .add("dst", dst).toString(); - } -} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/MoveExtensionTreatment.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/MoveExtensionTreatment.java deleted file mode 100644 index b67e1bed..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/MoveExtensionTreatment.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2015 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. - */ -package org.onosproject.driver.extensions; - -import org.onosproject.net.flow.instructions.ExtensionTreatment; - -/** - * The abstraction of Move Treatment. - */ -public interface MoveExtensionTreatment extends ExtensionTreatment { - - /** - * Returns SRC_OFS field of move extension action. - * - * @return SRC_OFS - */ - int srcOffset(); - - /** - * Returns DST_OFS field of move extension action. - * - * @return DST_OFS - */ - int dstOffset(); - - /** - * Returns SRC field of move extension action. - * - * @return SRC - */ - int src(); - - /** - * Returns DST field of move extension action. - * - * @return DST - */ - int dst(); - - /** - * Returns N_BITS field of move extension action. - * - * @return N_BITS - */ - int nBits(); -} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraExtensionSelectorInterpreter.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraExtensionSelectorInterpreter.java deleted file mode 100644 index 9f302991..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraExtensionSelectorInterpreter.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2015 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. - */ - -package org.onosproject.driver.extensions; - -import org.onosproject.net.behaviour.ExtensionSelectorResolver; -import org.onosproject.net.driver.AbstractHandlerBehaviour; -import org.onosproject.net.flow.criteria.ExtensionSelector; -import org.onosproject.net.flow.criteria.ExtensionSelectorType; -import org.onosproject.openflow.controller.ExtensionSelectorInterpreter; -import org.projectfloodlight.openflow.protocol.OFFactory; -import org.projectfloodlight.openflow.protocol.oxm.OFOxm; - -/** - * Interpreter for Nicira OpenFlow selector extensions. - */ -public class NiciraExtensionSelectorInterpreter - extends AbstractHandlerBehaviour - implements ExtensionSelectorInterpreter, ExtensionSelectorResolver { - - @Override - public boolean supported(ExtensionSelectorType extensionSelectorType) { - if (extensionSelectorType.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_SPI.type())) { - return true; - } - if (extensionSelectorType.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_SI.type())) { - return true; - } - if (extensionSelectorType.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH1.type())) { - return true; - } - if (extensionSelectorType.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH2.type())) { - return true; - } - if (extensionSelectorType.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH3.type())) { - return true; - } - if (extensionSelectorType.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH4.type())) { - return true; - } - return false; - } - - @Override - public OFOxm mapSelector(OFFactory factory, ExtensionSelector extensionSelector) { - ExtensionSelectorType type = extensionSelector.type(); - if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_SPI.type())) { - // TODO - } - if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_SI.type())) { - // TODO - } - if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH1.type())) { - // TODO - } - if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH2.type())) { - // TODO - } - if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH3.type())) { - // TODO - } - if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH4.type())) { - // TODO - } - return null; - } - - @Override - public ExtensionSelector mapOxm(OFOxm oxm) { - return null; - } - - @Override - public ExtensionSelector getExtensionSelector(ExtensionSelectorType type) { - if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_SPI.type())) { - return new NiciraMatchNshSpi(); - } - if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_SI.type())) { - return new NiciraMatchNshSi(); - } - if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH1.type()) - || type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH2.type()) - || type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH3.type()) - || type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH4.type())) { - return new NiciraMatchNshContextHeader(type); - } - return null; - } -} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraExtensionTreatmentInterpreter.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraExtensionTreatmentInterpreter.java deleted file mode 100644 index 5e374d9b..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraExtensionTreatmentInterpreter.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright 2015 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. - */ - -package org.onosproject.driver.extensions; - -import org.onlab.packet.Ip4Address; -import org.onosproject.net.behaviour.ExtensionTreatmentResolver; -import org.onosproject.net.driver.AbstractHandlerBehaviour; -import org.onosproject.net.flow.instructions.ExtensionTreatment; -import org.onosproject.net.flow.instructions.ExtensionTreatmentType; -import org.onosproject.openflow.controller.ExtensionTreatmentInterpreter; -import org.projectfloodlight.openflow.protocol.OFActionType; -import org.projectfloodlight.openflow.protocol.OFFactory; -import org.projectfloodlight.openflow.protocol.action.OFAction; -import org.projectfloodlight.openflow.protocol.action.OFActionSetField; -import org.projectfloodlight.openflow.protocol.oxm.OFOxm; -import org.projectfloodlight.openflow.protocol.oxm.OFOxmTunnelIpv4Dst; -import org.projectfloodlight.openflow.types.IPv4Address; - -/** - * Interpreter for Nicira OpenFlow treatment extensions. - */ -public class NiciraExtensionTreatmentInterpreter extends AbstractHandlerBehaviour - implements ExtensionTreatmentInterpreter, ExtensionTreatmentResolver { - - @Override - public boolean supported(ExtensionTreatmentType extensionTreatmentType) { - if (extensionTreatmentType.equals( - ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST.type())) { - return true; - } - if (extensionTreatmentType.equals( - ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_RESUBMIT.type())) { - return true; - } - if (extensionTreatmentType.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SPI.type())) { - return true; - } - if (extensionTreatmentType.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SI.type())) { - return true; - } - if (extensionTreatmentType.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH1.type())) { - return true; - } - if (extensionTreatmentType.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH2.type())) { - return true; - } - if (extensionTreatmentType.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH3.type())) { - return true; - } - if (extensionTreatmentType.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH4.type())) { - return true; - } - if (extensionTreatmentType.equals( - ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_RESUBMIT_TABLE.type())) { - return true; - } - if (extensionTreatmentType.equals( - ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ARP_SHA_TO_THA.type())) { - return true; - } - if (extensionTreatmentType.equals( - ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ARP_SPA_TO_TPA.type())) { - return true; - } - if (extensionTreatmentType.equals( - ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ETH_SRC_TO_DST.type())) { - return true; - } - if (extensionTreatmentType.equals( - ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_IP_SRC_TO_DST.type())) { - return true; - } - return false; - } - - @Override - public OFAction mapInstruction(OFFactory factory, ExtensionTreatment extensionTreatment) { - ExtensionTreatmentType type = extensionTreatment.type(); - if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST.type())) { - NiciraSetTunnelDst tunnelDst = (NiciraSetTunnelDst) extensionTreatment; - return factory.actions().setField(factory.oxms().tunnelIpv4Dst( - IPv4Address.of(tunnelDst.tunnelDst().toInt()))); - } - if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_RESUBMIT.type())) { - // TODO this will be implemented later - } - if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SPI.type())) { - // TODO this will be implemented later - } - if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_RESUBMIT_TABLE.type())) { - // TODO this will be implemented later - } - if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SI.type())) { - // TODO this will be implemented later - } - if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH1.type())) { - // TODO this will be implemented later - } - if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH2.type())) { - // TODO this will be implemented later - } - if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH3.type())) { - // TODO this will be implemented later - } - if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH4.type())) { - // TODO this will be implemented later - } - if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ETH_SRC_TO_DST.type()) - || type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ARP_SPA_TO_TPA.type()) - || type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ETH_SRC_TO_DST.type()) - || type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_IP_SRC_TO_DST.type())) { - // TODO this will be implemented later - } - return null; - } - - @Override - public ExtensionTreatment mapAction(OFAction action) { - if (action.getType().equals(OFActionType.SET_FIELD)) { - OFActionSetField setFieldAction = (OFActionSetField) action; - OFOxm oxm = setFieldAction.getField(); - switch (oxm.getMatchField().id) { - case TUNNEL_IPV4_DST: - OFOxmTunnelIpv4Dst tunnelIpv4Dst = (OFOxmTunnelIpv4Dst) oxm; - return new NiciraSetTunnelDst(Ip4Address.valueOf(tunnelIpv4Dst.getValue().getInt())); - default: - throw new UnsupportedOperationException( - "Driver does not support extension type " + oxm.getMatchField().id); - } - } - return null; - } - - @Override - public ExtensionTreatment getExtensionInstruction(ExtensionTreatmentType type) { - if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST.type())) { - return new NiciraSetTunnelDst(); - } - if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_RESUBMIT.type())) { - return new NiciraResubmit(); - } - if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_RESUBMIT_TABLE.type())) { - return new NiciraResubmitTable(); - } - if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SPI.type())) { - return new NiciraSetNshSpi(); - } - if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SI.type())) { - return new NiciraSetNshSi(); - } - if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH1.type()) - || type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH2.type()) - || type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH3.type()) - || type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH4.type())) { - return new NiciraSetNshContextHeader(type); - } - if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ARP_SHA_TO_THA.type())) { - return NiciraMoveTreatmentFactory.createNiciraMovArpShaToTha(); - } - if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ARP_SPA_TO_TPA.type())) { - return NiciraMoveTreatmentFactory.createNiciraMovArpSpaToTpa(); - } - if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ETH_SRC_TO_DST.type())) { - return NiciraMoveTreatmentFactory.createNiciraMovEthSrcToDst(); - } - if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_IP_SRC_TO_DST.type())) { - return NiciraMoveTreatmentFactory.createNiciraMovIpSrcToDst(); - } - throw new UnsupportedOperationException( - "Driver does not support extension type " + type.toString()); - } -} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshContextHeader.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshContextHeader.java deleted file mode 100644 index 5f37247f..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshContextHeader.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2015 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. - */ -package org.onosproject.driver.extensions; - -import static com.google.common.base.MoreObjects.toStringHelper; - -import java.util.Objects; - -import org.onlab.util.KryoNamespace; -import org.onosproject.net.NshContextHeader; -import org.onosproject.net.flow.AbstractExtension; -import org.onosproject.net.flow.criteria.ExtensionSelector; -import org.onosproject.net.flow.criteria.ExtensionSelectorType; -/** - * Implementation of Nsh context header criterion. - */ -public final class NiciraMatchNshContextHeader extends AbstractExtension implements ExtensionSelector { - private NshContextHeader nshContextHeader; - private ExtensionSelectorType type; - - private final KryoNamespace appKryo = new KryoNamespace.Builder().build(); - - /** - * Constructor to create Nsh context header. - * - * @param type extension selector type - */ - public NiciraMatchNshContextHeader(ExtensionSelectorType type) { - this.nshContextHeader = null; - this.type = type; - } - - /** - * Gets the nsh context header to match. - * - * @return the nsh context header to match - */ - public NshContextHeader nshContextHeader() { - return nshContextHeader; - } - - @Override - public byte[] serialize() { - return appKryo.serialize(nshContextHeader.nshContextHeader()); - } - - @Override - public void deserialize(byte[] data) { - nshContextHeader = nshContextHeader.of(appKryo.deserialize(data)); - - } - - @Override - public ExtensionSelectorType type() { - return type; - } - - @Override - public String toString() { - return toStringHelper(type().toString()) - .add("nshContextHeader", nshContextHeader.toString()) - .toString(); - } - - @Override - public int hashCode() { - return Objects.hash(type(), nshContextHeader); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof NiciraMatchNshContextHeader) { - NiciraMatchNshContextHeader that = (NiciraMatchNshContextHeader) obj; - return Objects.equals(nshContextHeader, that.nshContextHeader) && - Objects.equals(this.type(), that.type()); - } - return false; - } -} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshSi.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshSi.java deleted file mode 100644 index c98a584a..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshSi.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2015 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. - */ -package org.onosproject.driver.extensions; - -import static com.google.common.base.MoreObjects.toStringHelper; - -import java.util.Objects; - -import org.onlab.util.KryoNamespace; -import org.onosproject.net.NshServiceIndex; -import org.onosproject.net.flow.AbstractExtension; -import org.onosproject.net.flow.criteria.ExtensionSelector; -import org.onosproject.net.flow.criteria.ExtensionSelectorType; -/** - * Implementation of NSH Service Index(SI). - */ -public final class NiciraMatchNshSi extends AbstractExtension implements ExtensionSelector { - - private NshServiceIndex nshSi; - - private final KryoNamespace appKryo = new KryoNamespace.Builder().build(); - - /** - * Default constructor. - * - */ - public NiciraMatchNshSi() { - this.nshSi = null; - } - - /** - * Gets the nsh service index to match. - * - * @return the si to match - */ - public NshServiceIndex nshSi() { - return nshSi; - } - - @Override - public byte[] serialize() { - return appKryo.serialize(nshSi.serviceIndex()); - } - - @Override - public void deserialize(byte[] data) { - nshSi = NshServiceIndex.of(appKryo.deserialize(data)); - } - - @Override - public ExtensionSelectorType type() { - return ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_SI.type(); - } - - @Override - public String toString() { - return toStringHelper(type().toString()) - .add("nshSi", nshSi.toString()) - .toString(); - } - - @Override - public int hashCode() { - return Objects.hash(type(), nshSi); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof NiciraMatchNshSi) { - NiciraMatchNshSi that = (NiciraMatchNshSi) obj; - return Objects.equals(nshSi, that.nshSi); - } - return false; - } -} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshSpi.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshSpi.java deleted file mode 100644 index 42bb78d4..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshSpi.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2015 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. - */ -package org.onosproject.driver.extensions; - -import static com.google.common.base.MoreObjects.toStringHelper; - -import java.util.Objects; - -import org.onlab.util.KryoNamespace; -import org.onosproject.net.NshServicePathId; -import org.onosproject.net.flow.AbstractExtension; -import org.onosproject.net.flow.criteria.ExtensionSelector; -import org.onosproject.net.flow.criteria.ExtensionSelectorType; - -/** - * Implementation of NSH Service Path Id selector. - */ -public final class NiciraMatchNshSpi extends AbstractExtension implements ExtensionSelector { - private NshServicePathId nshSpi; - - private final KryoNamespace appKryo = new KryoNamespace.Builder().build(); - - /** - * Default constructor. - */ - public NiciraMatchNshSpi() { - this.nshSpi = null; - } - - /** - * Gets the network service path id to match. - * - * @return the nshSpi to match - */ - public NshServicePathId nshSpi() { - return nshSpi; - } - - @Override - public ExtensionSelectorType type() { - return ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_SPI.type(); - } - - @Override - public byte[] serialize() { - return appKryo.serialize(nshSpi); - } - - @Override - public void deserialize(byte[] data) { - nshSpi = NshServicePathId.of(appKryo.deserialize(data)); - } - - @Override - public String toString() { - return toStringHelper(type().toString()) - .add("nshSpi", nshSpi.toString()) - .toString(); - } - - @Override - public int hashCode() { - return Objects.hash(type(), nshSpi); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof NiciraMatchNshSpi) { - NiciraMatchNshSpi that = (NiciraMatchNshSpi) obj; - return Objects.equals(nshSpi, that.nshSpi) && - Objects.equals(this.type(), that.type()); - } - return false; - } -} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMoveTreatmentFactory.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMoveTreatmentFactory.java deleted file mode 100644 index ac42a3b2..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMoveTreatmentFactory.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2015 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. - */ -package org.onosproject.driver.extensions; - -import org.onosproject.net.flow.instructions.ExtensionTreatment; -import org.onosproject.net.flow.instructions.ExtensionTreatmentType; - -/** - * The factory of move treatment. - */ -public final class NiciraMoveTreatmentFactory { - - /** - * Public constructor is prohibited. - */ - private NiciraMoveTreatmentFactory() { - - } - - /** - * Creates a move treatment that move arp sha to tha. - * - * @return ExtensionTreatment - */ - public static ExtensionTreatment createNiciraMovArpShaToTha() { - int srcOfs = 0; - int dstOfs = 0; - int nBits = 48; - int srcSha = 0x00012206; - int dstTha = 0x00012406; - return new DefaultMoveExtensionTreatment(srcOfs, dstOfs, nBits, srcSha, - dstTha, - ExtensionTreatmentType.ExtensionTreatmentTypes - .NICIRA_MOV_ARP_SHA_TO_THA.type()); - } - - /** - * Creates a move treatment that move arp spa to tpa. - * - * @return ExtensionTreatment - */ - public static ExtensionTreatment createNiciraMovArpSpaToTpa() { - int srcOfs = 0; - int dstOfs = 0; - int nBits = 32; - int srcSpa = 0x00002004; - int dstTpa = 0x00002204; - return new DefaultMoveExtensionTreatment(srcOfs, dstOfs, nBits, srcSpa, - dstTpa, - ExtensionTreatmentType.ExtensionTreatmentTypes - .NICIRA_MOV_ARP_SPA_TO_TPA.type()); - } - - /** - * Creates a move treatment that move eth src to dst. - * - * @return ExtensionTreatment - */ - public static ExtensionTreatment createNiciraMovEthSrcToDst() { - int srcOfs = 0; - int dstOfs = 0; - int nBits = 48; - int srcEth = 0x00000406; - int dstEth = 0x00000206; - return new DefaultMoveExtensionTreatment(srcOfs, dstOfs, nBits, srcEth, - dstEth, - ExtensionTreatmentType.ExtensionTreatmentTypes - .NICIRA_MOV_ETH_SRC_TO_DST.type()); - } - - /** - * Creates a move treatment that move ip src to dst. - * - * @return ExtensionTreatment - */ - public static ExtensionTreatment createNiciraMovIpSrcToDst() { - int srcOfs = 0; - int dstOfs = 0; - int nBits = 32; - int srcIp = 0x00000e04; - int dstIp = 0x00001006; - return new DefaultMoveExtensionTreatment(srcOfs, dstOfs, nBits, srcIp, - dstIp, - ExtensionTreatmentType.ExtensionTreatmentTypes - .NICIRA_MOV_IP_SRC_TO_DST.type()); - } -} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraResubmit.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraResubmit.java deleted file mode 100644 index b85af4f2..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraResubmit.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2015 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. - */ - -package org.onosproject.driver.extensions; - -import com.google.common.base.MoreObjects; -import org.onlab.util.KryoNamespace; -import org.onosproject.net.PortNumber; -import org.onosproject.net.flow.AbstractExtension; -import org.onosproject.net.flow.instructions.ExtensionTreatment; -import org.onosproject.net.flow.instructions.ExtensionTreatmentType; -import org.onosproject.store.serializers.PortNumberSerializer; - -import java.util.Objects; - -import static com.google.common.base.Preconditions.checkNotNull; - -/** - * Nicira resubmit extension instruction. - */ -public class NiciraResubmit extends AbstractExtension implements ExtensionTreatment { - - private PortNumber inPort; - - private final KryoNamespace appKryo = new KryoNamespace.Builder() - .register(new PortNumberSerializer(), PortNumber.class) - .register(byte[].class) - .build(); - - /** - * Creates a new resubmit instruction. - */ - NiciraResubmit() { - inPort = null; - } - - /** - * Creates a new resubmit instruction with a particular inPort. - * - * @param inPort in port number - */ - public NiciraResubmit(PortNumber inPort) { - checkNotNull(inPort); - this.inPort = inPort; - } - - /** - * Gets the inPort. - * - * @return inPort - */ - public PortNumber inPort() { - return inPort; - } - - @Override - public ExtensionTreatmentType type() { - return ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_RESUBMIT.type(); - } - - @Override - public void deserialize(byte[] data) { - inPort = appKryo.deserialize(data); - } - - @Override - public byte[] serialize() { - return appKryo.serialize(inPort); - } - - @Override - public int hashCode() { - return Objects.hash(inPort); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof NiciraResubmit) { - NiciraResubmit that = (NiciraResubmit) obj; - return Objects.equals(inPort, that.inPort); - - } - return false; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("inPort", inPort) - .toString(); - } -} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraResubmitTable.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraResubmitTable.java deleted file mode 100644 index 4743d217..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraResubmitTable.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2015 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. - */ - -package org.onosproject.driver.extensions; - -import com.google.common.base.MoreObjects; - -import org.onlab.util.KryoNamespace; -import org.onosproject.net.PortNumber; -import org.onosproject.net.flow.AbstractExtension; -import org.onosproject.net.flow.instructions.ExtensionTreatment; -import org.onosproject.net.flow.instructions.ExtensionTreatmentType; -import org.onosproject.store.serializers.PortNumberSerializer; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -import static com.google.common.base.Preconditions.checkNotNull; - -/** - * Nicira resubmit-table extension instruction. - */ -public class NiciraResubmitTable extends AbstractExtension implements - ExtensionTreatment { - - //the list of the in port number(PortNumber) and the table(short) - private List inPortAndTable = new ArrayList(); - - private final KryoNamespace appKryo = new KryoNamespace.Builder() - .register(ArrayList.class) - .register(new PortNumberSerializer(), PortNumber.class) - .register(short.class) - .register(byte[].class) - .build(); - - /** - * Creates a new resubmit-table instruction. - */ - NiciraResubmitTable() { - inPortAndTable = null; - } - - /** - * Creates a new resubmit-table instruction with a particular inPort and table. - * - * @param inPortAndTable the list of in port number and table - */ - public NiciraResubmitTable(List inPortAndTable) { - checkNotNull(inPortAndTable); - this.inPortAndTable = inPortAndTable; - } - - /** - * Gets the inPortAndTable. - * - * @return inPortAndTable - */ - public List inPortAndTable() { - return inPortAndTable; - } - - @Override - public ExtensionTreatmentType type() { - return ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_RESUBMIT_TABLE.type(); - } - - @Override - public void deserialize(byte[] data) { - inPortAndTable = appKryo.deserialize(data); - } - - @Override - public byte[] serialize() { - return appKryo.serialize(inPortAndTable); - } - - @Override - public int hashCode() { - return Objects.hash(inPortAndTable); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof NiciraResubmitTable) { - NiciraResubmitTable that = (NiciraResubmitTable) obj; - return Objects.equals(inPortAndTable, that.inPortAndTable); - - } - return false; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("inPortAndTable", inPortAndTable).toString(); - } -} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetNshContextHeader.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetNshContextHeader.java deleted file mode 100644 index c8267984..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetNshContextHeader.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2015 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. - */ - -package org.onosproject.driver.extensions; - -import com.google.common.base.MoreObjects; -import org.onlab.util.KryoNamespace; -import org.onosproject.net.flow.AbstractExtension; -import org.onosproject.net.flow.instructions.ExtensionTreatment; -import org.onosproject.net.flow.instructions.ExtensionTreatmentType; - -import java.util.Objects; - -/** - * Nicira set NSH Context header extension instruction. - */ -public class NiciraSetNshContextHeader extends AbstractExtension implements - ExtensionTreatment { - - private int nshCh; - private ExtensionTreatmentType type; - - private final KryoNamespace appKryo = new KryoNamespace.Builder().build(); - - /** - * Creates a new set nsh context header instruction. - * - * @param type extension treatment type - */ - NiciraSetNshContextHeader(ExtensionTreatmentType type) { - this.nshCh = 0; - this.type = type; - } - - /** - * Creates a new set nsh context header instruction. - * - * @param nshCh nsh context header - * @param type extension treatment type - */ - NiciraSetNshContextHeader(int nshCh, ExtensionTreatmentType type) { - this.nshCh = nshCh; - this.type = type; - } - - /** - * Gets the nsh context header. - * - * @return nsh context header - */ - public int nshCh() { - return nshCh; - } - - @Override - public ExtensionTreatmentType type() { - return type; - } - - @Override - public void deserialize(byte[] data) { - nshCh = appKryo.deserialize(data); - } - - @Override - public byte[] serialize() { - return appKryo.serialize(nshCh); - } - - @Override - public int hashCode() { - return Objects.hash(nshCh, type); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof NiciraSetNshContextHeader) { - NiciraSetNshContextHeader that = (NiciraSetNshContextHeader) obj; - return Objects.equals(nshCh, that.nshCh) && Objects.equals(type, that.type); - - } - return false; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("nshCh", nshCh) - .add("type", type) - .toString(); - } -} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetNshSi.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetNshSi.java deleted file mode 100644 index 1480508e..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetNshSi.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2015 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. - */ - -package org.onosproject.driver.extensions; - -import com.google.common.base.MoreObjects; -import org.onlab.util.KryoNamespace; -import org.onosproject.net.flow.AbstractExtension; -import org.onosproject.net.flow.instructions.ExtensionTreatment; -import org.onosproject.net.flow.instructions.ExtensionTreatmentType; - -import java.util.Objects; - -/** - * Nicira set NSH SI extension instruction. - */ -public class NiciraSetNshSi extends AbstractExtension implements - ExtensionTreatment { - - private byte nshSi; - - private final KryoNamespace appKryo = new KryoNamespace.Builder().build(); - - /** - * Creates a new set nsh si instruction. - */ - NiciraSetNshSi() { - nshSi = 0; - } - - /** - * Creates a new set nsh si instruction with given si. - * - * @param nshSi nsh service index - */ - NiciraSetNshSi(byte nshSi) { - this.nshSi = nshSi; - } - - /** - * Gets the nsh service index. - * - * @return nsh service index - */ - public byte nshSi() { - return nshSi; - } - - @Override - public ExtensionTreatmentType type() { - return ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SI.type(); - } - - @Override - public void deserialize(byte[] data) { - nshSi = appKryo.deserialize(data); - } - - @Override - public byte[] serialize() { - return appKryo.serialize(nshSi); - } - - @Override - public int hashCode() { - return Objects.hash(nshSi); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof NiciraSetNshSi) { - NiciraSetNshSi that = (NiciraSetNshSi) obj; - return Objects.equals(nshSi, that.nshSi); - - } - return false; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("nshSi", nshSi) - .toString(); - } -} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetNshSpi.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetNshSpi.java deleted file mode 100644 index 1a47173e..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetNshSpi.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2015 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. - */ - -package org.onosproject.driver.extensions; - -import com.google.common.base.MoreObjects; -import org.onlab.util.KryoNamespace; -import org.onosproject.net.flow.AbstractExtension; -import org.onosproject.net.flow.instructions.ExtensionTreatment; -import org.onosproject.net.flow.instructions.ExtensionTreatmentType; - -import java.util.Objects; - -/** - * Nicira set NSH SPI extension instruction. - */ -public class NiciraSetNshSpi extends AbstractExtension implements - ExtensionTreatment { - - private int nshSpi; - - private final KryoNamespace appKryo = new KryoNamespace.Builder().build(); - - /** - * Creates a new set nsh spi instruction. - */ - NiciraSetNshSpi() { - nshSpi = 0; - } - - /** - * Creates a new set nsh spi instruction with given spi. - * - * @param nshSpi nsh service path index - */ - NiciraSetNshSpi(int nshSpi) { - this.nshSpi = nshSpi; - } - - /** - * Gets the nsh service path index. - * - * @return nsh service path index - */ - public int nshSpi() { - return nshSpi; - } - - @Override - public ExtensionTreatmentType type() { - return ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SPI.type(); - } - - @Override - public void deserialize(byte[] data) { - nshSpi = appKryo.deserialize(data); - } - - @Override - public byte[] serialize() { - return appKryo.serialize(nshSpi); - } - - @Override - public int hashCode() { - return Objects.hash(nshSpi); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof NiciraSetNshSpi) { - NiciraSetNshSpi that = (NiciraSetNshSpi) obj; - return Objects.equals(nshSpi, that.nshSpi); - - } - return false; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("nshSpi", nshSpi) - .toString(); - } -} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetTunnelDst.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetTunnelDst.java deleted file mode 100644 index e28a1e24..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetTunnelDst.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2015 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. - */ - -package org.onosproject.driver.extensions; - -import com.google.common.base.MoreObjects; -import org.onlab.packet.Ip4Address; -import org.onlab.util.KryoNamespace; -import org.onosproject.net.flow.AbstractExtension; -import org.onosproject.net.flow.instructions.ExtensionTreatment; -import org.onosproject.net.flow.instructions.ExtensionTreatmentType; -import org.onosproject.store.serializers.Ip4AddressSerializer; - -import java.util.Objects; - -import static com.google.common.base.Preconditions.checkNotNull; - -/** - * Nicira set tunnel destination extension instruction. - */ -public class NiciraSetTunnelDst extends AbstractExtension implements - ExtensionTreatment { - - private Ip4Address tunnelDst; - - private final KryoNamespace appKryo = new KryoNamespace.Builder() - .register(new Ip4AddressSerializer(), Ip4Address.class) - .register(byte[].class) - .build(); - - /** - * Creates a new set tunnel destination instruction. - */ - NiciraSetTunnelDst() { - tunnelDst = null; - } - - /** - * Creates a new set tunnel destination instruction with a particular IPv4 - * address. - * - * @param tunnelDst tunnel destination IPv4 address - */ - NiciraSetTunnelDst(Ip4Address tunnelDst) { - checkNotNull(tunnelDst); - this.tunnelDst = tunnelDst; - } - - /** - * Gets the tunnel destination IPv4 address. - * - * @return tunnel destination IPv4 address - */ - public Ip4Address tunnelDst() { - return tunnelDst; - } - - @Override - public ExtensionTreatmentType type() { - return ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_TUNNEL_DST.type(); - } - - @Override - public void deserialize(byte[] data) { - tunnelDst = appKryo.deserialize(data); - } - - @Override - public byte[] serialize() { - return appKryo.serialize(tunnelDst); - } - - @Override - public int hashCode() { - return Objects.hash(tunnelDst); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof NiciraSetTunnelDst) { - NiciraSetTunnelDst that = (NiciraSetTunnelDst) obj; - return Objects.equals(tunnelDst, that.tunnelDst); - - } - return false; - } - - @Override - public String toString() { - return MoreObjects.toStringHelper(getClass()) - .add("tunnelDst", tunnelDst) - .toString(); - } -} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/package-info.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/package-info.java deleted file mode 100644 index d9d2460d..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/package-info.java +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright 2015 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. - */ -/** - * Processing of Nicira extensions. - */ -package org.onosproject.driver.extensions; diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/CalientFiberSwitchHandshaker.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/CalientFiberSwitchHandshaker.java deleted file mode 100644 index 270008f3..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/CalientFiberSwitchHandshaker.java +++ /dev/null @@ -1,221 +0,0 @@ -/* - * Copyright 2015 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. - */ -package org.onosproject.driver.handshaker; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import org.onlab.util.Spectrum; -import org.onosproject.net.ChannelSpacing; -import org.onosproject.net.DefaultOchSignalComparator; -import org.onosproject.net.Device; -import org.onosproject.net.GridType; -import org.onosproject.net.OchSignal; -import org.onosproject.net.PortNumber; -import org.onosproject.net.behaviour.LambdaQuery; -import org.onosproject.openflow.controller.OpenFlowOpticalSwitch; -import org.onosproject.openflow.controller.PortDescPropertyType; -import org.onosproject.openflow.controller.driver.AbstractOpenFlowSwitch; -import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeAlreadyStarted; -import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeCompleted; -import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeNotStarted; -import org.projectfloodlight.openflow.protocol.OFCalientFlowStatsRequest; -import org.projectfloodlight.openflow.protocol.OFCalientPortDescStatsEntry; -import org.projectfloodlight.openflow.protocol.OFCalientPortDescStatsReply; -import org.projectfloodlight.openflow.protocol.OFCalientPortDescStatsRequest; -import org.projectfloodlight.openflow.protocol.OFFlowStatsRequest; -import org.projectfloodlight.openflow.protocol.OFMessage; -import org.projectfloodlight.openflow.protocol.OFObject; -import org.projectfloodlight.openflow.protocol.OFStatsReplyFlags; -import org.projectfloodlight.openflow.protocol.OFStatsRequest; -import org.projectfloodlight.openflow.protocol.OFType; -import org.projectfloodlight.openflow.types.OFPort; -import org.projectfloodlight.openflow.types.TableId; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import java.util.SortedSet; -import java.util.TreeSet; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -/** - * Driver for Calient S160 Optical Circuit Switch. Untested on Calient S320 but probably works ok. - * - * Driver implements custom handshaker, and rewrites flow stats as expected by the device. Port stats are currently - * not supported. - * - * The device consists of OMS ports only, and each port exposes lambda resources covering the whole - * usable optical spectrum (U to O band, see {@link Spectrum} for spectrum definitions). - */ -public class CalientFiberSwitchHandshaker - extends AbstractOpenFlowSwitch - implements OpenFlowOpticalSwitch, LambdaQuery { - - private final AtomicBoolean driverHandshakeComplete = new AtomicBoolean(false); - private List fiberPorts = new ArrayList<>(); - - - @Override - public Boolean supportNxRole() { - return false; - } - - @Override - public void startDriverHandshake() { - log.warn("Starting driver handshake for sw {}", getStringId()); - if (startDriverHandshakeCalled) { - throw new SwitchDriverSubHandshakeAlreadyStarted(); - } - startDriverHandshakeCalled = true; - try { - sendHandshakeOFExperimenterPortDescRequest(); - } catch (IOException e) { - log.error("Exception while sending experimenter port desc:", e.getMessage()); - e.printStackTrace(); - } - - } - - private void sendHandshakeOFExperimenterPortDescRequest() throws IOException { - // send multi part message for port description for optical switches - OFCalientPortDescStatsRequest portsRequest = factory() - .buildCalientPortDescStatsRequest() - .build(); - log.warn("Sending experimenter port description message {}", - portsRequest.toString()); - this.sendHandshakeMessage(portsRequest); - } - - @Override - public boolean isDriverHandshakeComplete() { - return driverHandshakeComplete.get(); - } - - @Override - public void processDriverHandshakeMessage(OFMessage m) { - if (!startDriverHandshakeCalled) { - throw new SwitchDriverSubHandshakeNotStarted(); - } - if (driverHandshakeComplete.get()) { - throw new SwitchDriverSubHandshakeCompleted(m); - } - - switch (m.getType()) { - case BARRIER_REPLY: - break; - case ERROR: - log.error("Switch Error {} {}", getStringId(), m); - break; - case FEATURES_REPLY: - break; - case FLOW_REMOVED: - break; - case GET_ASYNC_REPLY: - break; - case PACKET_IN: - break; - case PORT_STATUS: - break; - case QUEUE_GET_CONFIG_REPLY: - break; - case ROLE_REPLY: - break; - case STATS_REPLY: - log.warn("Received port desc reply"); - OFCalientPortDescStatsReply descStatsReply = (OFCalientPortDescStatsReply) m; - fiberPorts.addAll(descStatsReply.getPortDesc()); - // Multi-part message - if (!descStatsReply.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) { - driverHandshakeComplete.set(true); - } - break; - default: - log.warn("Received message {} during switch-driver " + - "subhandshake " + "from switch {} ... " + - "Ignoring message", m, - getStringId()); - - } - } - - @Override - public Device.Type deviceType() { - return Device.Type.FIBER_SWITCH; - } - - @Override - public List getPortsOf(PortDescPropertyType type) { - return ImmutableList.copyOf(fiberPorts); - } - - @Override - public Set getPortTypes() { - return ImmutableSet.of(PortDescPropertyType.OPTICAL_TRANSPORT); - } - - @Override - public final void sendMsg(OFMessage m) { - OFMessage newMsg = m; - - if (m.getType() == OFType.STATS_REQUEST) { - OFStatsRequest sr = (OFStatsRequest) m; - log.debug("Rebuilding stats request type {}", sr.getStatsType()); - switch (sr.getStatsType()) { - case FLOW: - OFCalientFlowStatsRequest request = this.factory().buildCalientFlowStatsRequest() - .setCookie(((OFFlowStatsRequest) sr).getCookie()) - .setCookieMask(((OFFlowStatsRequest) sr).getCookieMask()) - .setMatch(this.factory().matchWildcardAll()) - .setOutGroup(((OFFlowStatsRequest) sr).getOutGroup().getGroupNumber()) - .setOutPort(OFPort.ANY) - .setTableId(TableId.ALL) - .setXid(sr.getXid()) - .setFlags(sr.getFlags()) - .build(); - newMsg = request; - break; - case PORT: - // TODO - break; - default: - break; - } - } - - super.sendMsg(newMsg); - } - - @Override - public SortedSet queryLambdas(PortNumber port) { - // S160 data sheet - // Wavelength range: 1260 - 1630 nm - long startSpacingMultiplier = Spectrum.U_BAND_MIN.subtract(Spectrum.CENTER_FREQUENCY).asHz() / - ChannelSpacing.CHL_12P5GHZ.frequency().asHz(); - long stopSpacingMultiplier = Spectrum.O_BAND_MAX.subtract(Spectrum.CENTER_FREQUENCY).asHz() / - ChannelSpacing.CHL_12P5GHZ.frequency().asHz(); - List lambdas = IntStream.rangeClosed((int) startSpacingMultiplier, (int) stopSpacingMultiplier) - .mapToObj(x -> new OchSignal(GridType.FLEX, ChannelSpacing.CHL_12P5GHZ, x, 1)) - .collect(Collectors.toList()); - - SortedSet result = new TreeSet<>(new DefaultOchSignalComparator()); - result.addAll(lambdas); - - return result; - } -} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/CorsaSwitchHandshaker.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/CorsaSwitchHandshaker.java deleted file mode 100644 index 376b3985..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/CorsaSwitchHandshaker.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2015 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. - */ -package org.onosproject.driver.handshaker; - -import org.onosproject.openflow.controller.driver.AbstractOpenFlowSwitch; -import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeAlreadyStarted; -import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeCompleted; -import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeNotStarted; -import org.projectfloodlight.openflow.protocol.OFBarrierRequest; -import org.projectfloodlight.openflow.protocol.OFFlowMod; -import org.projectfloodlight.openflow.protocol.OFMessage; -import org.projectfloodlight.openflow.protocol.OFType; -import org.projectfloodlight.openflow.types.OFGroup; -import org.projectfloodlight.openflow.types.TableId; - -import java.util.Collections; -import java.util.concurrent.atomic.AtomicBoolean; - - -/** - * Corsa switch handshaker. - */ -public class CorsaSwitchHandshaker extends AbstractOpenFlowSwitch { - - private AtomicBoolean handshakeComplete = new AtomicBoolean(false); - - private int barrierXid; - - - @Override - public Boolean supportNxRole() { - return false; - } - - @Override - public void startDriverHandshake() { - if (startDriverHandshakeCalled) { - throw new SwitchDriverSubHandshakeAlreadyStarted(); - } - startDriverHandshakeCalled = true; - OFFlowMod fm = factory().buildFlowDelete() - .setTableId(TableId.ALL) - .setOutGroup(OFGroup.ANY) - .build(); - - sendMsg(Collections.singletonList(fm)); - - barrierXid = getNextTransactionId(); - OFBarrierRequest barrier = factory().buildBarrierRequest() - .setXid(barrierXid).build(); - - - sendHandshakeMessage(barrier); - - } - - @Override - public boolean isDriverHandshakeComplete() { - if (!startDriverHandshakeCalled) { - throw new SwitchDriverSubHandshakeAlreadyStarted(); - } - return handshakeComplete.get(); - } - - @Override - public void processDriverHandshakeMessage(OFMessage m) { - if (!startDriverHandshakeCalled) { - throw new SwitchDriverSubHandshakeNotStarted(); - } - if (handshakeComplete.get()) { - throw new SwitchDriverSubHandshakeCompleted(m); - } - if (m.getType() == OFType.BARRIER_REPLY && - m.getXid() == barrierXid) { - handshakeComplete.set(true); - } - } - -} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/DefaultSwitchHandshaker.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/DefaultSwitchHandshaker.java deleted file mode 100644 index fb789440..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/DefaultSwitchHandshaker.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2015 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. - */ -package org.onosproject.driver.handshaker; - -import org.onosproject.openflow.controller.driver.AbstractOpenFlowSwitch; -import org.projectfloodlight.openflow.protocol.OFFlowAdd; -import org.projectfloodlight.openflow.protocol.OFMessage; -import org.projectfloodlight.openflow.protocol.OFPortDesc; -import org.projectfloodlight.openflow.protocol.OFVersion; - -import java.util.Collections; -import java.util.List; -import java.util.stream.Collectors; - -/** - * Default driver to fallback on if no other driver is available. - */ -public class DefaultSwitchHandshaker extends AbstractOpenFlowSwitch { - - private static final int LOWEST_PRIORITY = 0; - - @Override - public Boolean supportNxRole() { - return false; - } - - @Override - public void startDriverHandshake() { - if (factory().getVersion() == OFVersion.OF_10) { - OFFlowAdd.Builder fmBuilder = factory().buildFlowAdd(); - fmBuilder.setPriority(LOWEST_PRIORITY); - sendHandshakeMessage(fmBuilder.build()); - } - } - - @Override - public void processDriverHandshakeMessage(OFMessage m) {} - - @Override - public boolean isDriverHandshakeComplete() { - return true; - } - - @Override - public List getPorts() { - if (this.factory().getVersion() == OFVersion.OF_10) { - return Collections.unmodifiableList(features.getPorts()); - } else { - return Collections.unmodifiableList( - ports.stream().flatMap(p -> p.getEntries().stream()) - .collect(Collectors.toList())); - } - } -} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/NiciraSwitchHandshaker.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/NiciraSwitchHandshaker.java deleted file mode 100644 index 4f61361f..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/NiciraSwitchHandshaker.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2015 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. - */ - -package org.onosproject.driver.handshaker; - -import org.projectfloodlight.openflow.protocol.OFVersion; - -/** - * Default driver to fallback on if no other driver is available. - */ -public class NiciraSwitchHandshaker extends DefaultSwitchHandshaker { - - @Override - public Boolean supportNxRole() { - if (this.factory().getVersion() == OFVersion.OF_10) { - return true; - } - return false; - } - -} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/OFOpticalSwitch13.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/OFOpticalSwitch13.java deleted file mode 100644 index 5c6ce360..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/OFOpticalSwitch13.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright 2015 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. - */ -package org.onosproject.driver.handshaker; - -import org.projectfloodlight.openflow.protocol.OFExpPort; -import org.projectfloodlight.openflow.protocol.OFExpPortDescReply; -import org.projectfloodlight.openflow.protocol.OFExpPortDescRequest; -import org.projectfloodlight.openflow.protocol.OFMessage; -import org.projectfloodlight.openflow.protocol.OFPortDesc; -import org.projectfloodlight.openflow.protocol.OFStatsReply; -import org.projectfloodlight.openflow.protocol.OFStatsReplyFlags; -import org.projectfloodlight.openflow.protocol.OFStatsType; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.stream.Collectors; - -import org.onosproject.net.Device; -import org.onosproject.openflow.controller.OpenFlowOpticalSwitch; -import org.onosproject.openflow.controller.PortDescPropertyType; -import org.onosproject.openflow.controller.driver.AbstractOpenFlowSwitch; -import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeAlreadyStarted; -import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeCompleted; -import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeNotStarted; -import org.projectfloodlight.openflow.protocol.OFObject; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; - - -/** - * Open Flow Optical Switch handshaker - for Open Flow 13. - */ -public class OFOpticalSwitch13 extends AbstractOpenFlowSwitch implements OpenFlowOpticalSwitch { - - private final AtomicBoolean driverHandshakeComplete = new AtomicBoolean(false); - private List expPortDes = new ArrayList<>(); - - @Override - public Boolean supportNxRole() { - return false; - } - - @Override - public void startDriverHandshake() { - log.info("Starting driver handshake for sw {}", getStringId()); - if (startDriverHandshakeCalled) { - throw new SwitchDriverSubHandshakeAlreadyStarted(); - } - startDriverHandshakeCalled = true; - - log.debug("sendHandshakeOFExperimenterPortDescRequest for sw {}", getStringId()); - - try { - sendHandshakeOFExperimenterPortDescRequest(); - } catch (IOException e) { - log.error("Failed to send handshaker message OFExperimenterPortDescRequestfor sw {}, {}", - getStringId(), e.getMessage()); - e.printStackTrace(); - } - } - - @Override - public void processDriverHandshakeMessage(OFMessage m) { - if (!startDriverHandshakeCalled) { - throw new SwitchDriverSubHandshakeNotStarted(); - } - if (driverHandshakeComplete.get()) { - throw new SwitchDriverSubHandshakeCompleted(m); - } - - log.debug("processDriverHandshakeMessage for sw {}", getStringId()); - - switch (m.getType()) { - case STATS_REPLY: // multipart message is reported as STAT - processOFMultipartReply((OFStatsReply) m); - break; - default: - log.warn("Received message {} during switch-driver " + - "subhandshake " + "from switch {} ... " + - "Ignoring message", m, - getStringId()); - } - } - - private void processOFMultipartReply(OFStatsReply stats) { - log.debug("Received message {} during switch-driver " + - "subhandshake " + "from switch {} ... " + - stats, - getStringId()); - - if (stats.getStatsType() == OFStatsType.EXPERIMENTER) { - try { - OFExpPortDescReply expPortDescReply = (OFExpPortDescReply) stats; - expPortDes.addAll(expPortDescReply.getEntries()); - if (!expPortDescReply.getFlags().contains(OFStatsReplyFlags.REPLY_MORE)) { - driverHandshakeComplete.set(true); - return; - } - } catch (ClassCastException e) { - log.error("Unexspected Experimenter Multipart message type {} " - , stats.getClass().getName()); - } - } - } - - - @Override - public boolean isDriverHandshakeComplete() { - return driverHandshakeComplete.get(); - } - - private void sendHandshakeOFExperimenterPortDescRequest() throws - IOException { - - OFExpPortDescRequest preq = factory() - .buildExpPortDescRequest() - .setXid(getNextTransactionId()) - .build(); - - log.debug("Sending experimented port description " + - "message " + - "{}", - preq.toString()); - - this.sendHandshakeMessage(preq); - } - - @Override - public Device.Type deviceType() { - String hwDesc = hardwareDescription(); - switch (hwDesc) { - case "Optical-ROADM": - return Device.Type.ROADM; - case "Optical-OTN": - return Device.Type.OTN; - default: - log.error("Unsupported hardwareDescription {}", hwDesc); - return Device.Type.OTHER; - } - } - - /* - * OduClt ports are reported as regular ETH ports. - */ - @Override - public List getPorts() { - return ImmutableList.copyOf( - ports.stream().flatMap(p -> p.getEntries().stream()) - .collect(Collectors.toList())); - } - - @Override - public List getPortsOf(PortDescPropertyType type) { - return ImmutableList.copyOf(expPortDes); - } - - @Override - public Set getPortTypes() { - return ImmutableSet.of(PortDescPropertyType.OPTICAL_TRANSPORT); - } - -} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/OfOpticalSwitchImplLinc13.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/OfOpticalSwitchImplLinc13.java deleted file mode 100644 index 23378e95..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/OfOpticalSwitchImplLinc13.java +++ /dev/null @@ -1,385 +0,0 @@ -/* - * Copyright 2015 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. - */ -package org.onosproject.driver.handshaker; - -import com.google.common.collect.ImmutableSet; -import org.onosproject.net.ChannelSpacing; -import org.onosproject.net.DefaultOchSignalComparator; -import org.onosproject.net.Device; -import org.onosproject.net.GridType; -import org.onosproject.net.OchSignal; -import org.onosproject.net.PortNumber; -import org.onosproject.net.behaviour.LambdaQuery; -import org.onosproject.openflow.controller.OpenFlowOpticalSwitch; -import org.onosproject.openflow.controller.PortDescPropertyType; -import org.onosproject.openflow.controller.driver.AbstractOpenFlowSwitch; -import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeAlreadyStarted; -import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeCompleted; -import org.onosproject.openflow.controller.driver.SwitchDriverSubHandshakeNotStarted; -import org.projectfloodlight.openflow.protocol.OFCircuitPortStatus; -import org.projectfloodlight.openflow.protocol.OFCircuitPortsReply; -import org.projectfloodlight.openflow.protocol.OFCircuitPortsRequest; -import org.projectfloodlight.openflow.protocol.OFFlowMod; -import org.projectfloodlight.openflow.protocol.OFFlowStatsRequest; -import org.projectfloodlight.openflow.protocol.OFMessage; -import org.projectfloodlight.openflow.protocol.OFObject; -import org.projectfloodlight.openflow.protocol.OFPortDesc; -import org.projectfloodlight.openflow.protocol.OFPortDescPropOpticalTransport; -import org.projectfloodlight.openflow.protocol.OFPortDescStatsReply; -import org.projectfloodlight.openflow.protocol.OFPortOptical; -import org.projectfloodlight.openflow.protocol.OFStatsReply; -import org.projectfloodlight.openflow.protocol.OFStatsType; -import org.projectfloodlight.openflow.protocol.action.OFAction; -import org.projectfloodlight.openflow.protocol.action.OFActionSetField; -import org.projectfloodlight.openflow.protocol.match.Match; -import org.projectfloodlight.openflow.protocol.match.MatchField; -import org.projectfloodlight.openflow.protocol.oxm.OFOxmExpOchSigId; -import org.projectfloodlight.openflow.types.CircuitSignalID; -import org.projectfloodlight.openflow.types.U8; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; -import java.util.SortedSet; -import java.util.TreeSet; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.stream.Collectors; -import java.util.stream.IntStream; - -/** - * LINC-OE Optical Emulator switch class. - * - * The LINC ROADM emulator exposes two types of ports: OCh ports connect to ports in the packet layer, - * while OMS ports connect to an OMS port on a neighbouring ROADM. - * - * LINC sends the tap ports (OCh for our purposes) in the regular port desc stats reply, - * while it sends *all* ports (both tap and WDM ports, i.e., OCh and OMS) in the experimenter port desc stats reply. - * - * As LINC implements custom OF optical extensions (in contrast to the final standard as specified in - * ONF TS-022 (March 15, 2015), we need to rewrite flow stat requests and flow mods in {@link #sendMsg(OFMessage)}. - * - * LINC exposes OchSignal resources: 80 lambdas of 50 GHz around ITU-T G.694.1 center frequency 193.1 GHz. - * - */ -public class OfOpticalSwitchImplLinc13 - extends AbstractOpenFlowSwitch implements OpenFlowOpticalSwitch, LambdaQuery { - - private static final int LAMBDA_COUNT = 80; - private final AtomicBoolean driverHandshakeComplete = new AtomicBoolean(false); - private long barrierXidToWaitFor = -1; - - private List opticalPorts; - - @Override - public void startDriverHandshake() { - log.warn("Starting driver handshake for sw {}", getStringId()); - if (startDriverHandshakeCalled) { - throw new SwitchDriverSubHandshakeAlreadyStarted(); - } - startDriverHandshakeCalled = true; - try { - sendHandshakeOFExperimenterPortDescRequest(); - } catch (IOException e) { - log.error("LINC-OE exception while sending experimenter port desc:", - e.getMessage()); - e.printStackTrace(); - } - } - - @Override - public boolean isDriverHandshakeComplete() { - return driverHandshakeComplete.get(); - } - - @Override - public void processDriverHandshakeMessage(OFMessage m) { - if (!startDriverHandshakeCalled) { - throw new SwitchDriverSubHandshakeNotStarted(); - } - if (driverHandshakeComplete.get()) { - throw new SwitchDriverSubHandshakeCompleted(m); - } - - switch (m.getType()) { - case BARRIER_REPLY: - if (m.getXid() == barrierXidToWaitFor) { - log.debug("LINC-OE Received barrier response"); - } - break; - case ERROR: - log.error("Switch {} Error {}", getStringId(), m); - break; - case FEATURES_REPLY: - break; - case FLOW_REMOVED: - break; - case GET_ASYNC_REPLY: - break; - case PACKET_IN: - break; - case PORT_STATUS: - log.warn("****LINC-OE Port Status {} {}", getStringId(), m); - processOFPortStatus((OFCircuitPortStatus) m); - break; - case QUEUE_GET_CONFIG_REPLY: - break; - case ROLE_REPLY: - break; - case STATS_REPLY: - OFStatsReply stats = (OFStatsReply) m; - if (stats.getStatsType() == OFStatsType.EXPERIMENTER) { - log.warn("LINC-OE : Received stats reply message {}", m); - createOpticalPortList((OFCircuitPortsReply) m); - driverHandshakeComplete.set(true); - } - break; - default: - log.warn("Received message {} during switch-driver " + - "subhandshake " + "from switch {} ... " + - "Ignoring message", m, - getStringId()); - - } - } - - public void processOFPortStatus(OFCircuitPortStatus ps) { - log.debug("LINC-OE ..OF Port Status :", ps); - } - - private void sendHandshakeOFExperimenterPortDescRequest() throws - IOException { - // send multi part message for port description for optical switches - OFCircuitPortsRequest circuitPortsRequest = factory() - .buildCircuitPortsRequest().setXid(getNextTransactionId()) - .build(); - log.warn("LINC-OE : Sending experimented circuit port stats " + - "message " + - "{}", - circuitPortsRequest.toString()); - this.sendHandshakeMessage(circuitPortsRequest); - } - - @Override - /** - * Returns a list of standard (Ethernet) ports. - * - * @return List of ports - */ - public List getPorts() { - return Collections.EMPTY_LIST; - } - - /** - * Rewrite match object to use LINC OF optical extensions. - * - * @param match original match - * @return rewritten match - */ - private Match rewriteMatch(Match match) { - Match.Builder mBuilder = factory().buildMatch(); - for (MatchField mf : match.getMatchFields()) { - if (mf == MatchField.EXP_OCH_SIG_ID) { - mBuilder.setExact(MatchField.OCH_SIGID, (CircuitSignalID) match.get(mf)); - continue; - } - if (mf == MatchField.EXP_OCH_SIGTYPE) { - mBuilder.setExact(MatchField.OCH_SIGTYPE, (U8) match.get(mf)); - continue; - } - mBuilder.setExact(mf, match.get(mf)); - } - - return mBuilder.build(); - } - - /** - * Rewrite actions to use LINC OF optical extensions. - * - * @param actions original actions - * @return rewritten actions - */ - private List rewriteActions(List actions) { - List newActions = new LinkedList<>(); - - for (OFAction action : actions) { - if (!(action instanceof OFActionSetField)) { - newActions.add(action); - continue; - } - - OFActionSetField sf = (OFActionSetField) action; - if (!(sf instanceof OFOxmExpOchSigId)) { - newActions.add(action); - } - - OFOxmExpOchSigId oxm = (OFOxmExpOchSigId) sf.getField(); - CircuitSignalID signalId = oxm.getValue(); - - newActions.add( - factory().actions().circuit(factory().oxms().ochSigid(signalId))); - } - - return newActions; - } - - @Override - public void sendMsg(OFMessage msg) { - // Ignore everything but flow mods and stat requests - if (!(msg instanceof OFFlowMod || msg instanceof OFFlowStatsRequest)) { - super.sendMsg(msg); - return; - } - - Match newMatch; - OFMessage newMsg = null; - - if (msg instanceof OFFlowStatsRequest) { - // Rewrite match only - OFFlowStatsRequest fsr = (OFFlowStatsRequest) msg; - newMatch = rewriteMatch(fsr.getMatch()); - newMsg = fsr.createBuilder().setMatch(newMatch).build(); - } else if (msg instanceof OFFlowMod) { - // Rewrite match and actions - OFFlowMod fm = (OFFlowMod) msg; - newMatch = rewriteMatch(fm.getMatch()); - List actions = rewriteActions(fm.getActions()); - - newMsg = fm.createBuilder().setMatch(newMatch).setActions(actions).build(); - } - - super.sendMsg(newMsg); - } - - @Override - public Boolean supportNxRole() { - return false; - } - - @Override - public Device.Type deviceType() { - return Device.Type.ROADM; - } - - /** - * Checks if given port is also part of the regular port desc stats, i.e., is the port a tap port. - * - * @param port given port number - * @return true if the port is a tap (OCh), false otherwise (OMS port) - */ - private boolean isOChPort(long port) { - for (OFPortDescStatsReply reply : this.ports) { - for (OFPortDesc p : reply.getEntries()) { - if (p.getPortNo().getPortNumber() == port) { - return true; - } - } - } - - return false; - } - - /** - * Creates an OpenFlow optical port based on the given port and transport type. - * - * @param port OpenFlow optical port - * @param type transport type - * @return OpenFlow optical port - */ - private OFPortOptical createOpticalPort(OFPortOptical port, short type) { - List descList = new ArrayList<>(port.getDesc().size()); - - for (OFPortDescPropOpticalTransport desc : port.getDesc()) { - OFPortDescPropOpticalTransport newDesc = desc.createBuilder() - .setType(desc.getType()) - .setPortSignalType(type) - .setPortType(desc.getPortType()) - .setReserved(desc.getReserved()) - .build(); - descList.add(newDesc); - } - - OFPortOptical newPort = port.createBuilder() - .setConfig(port.getConfig()) - .setDesc(descList) - .setHwAddr(port.getHwAddr()) - .setName(port.getName()) - .setPortNo(port.getPortNo()) - .setState(port.getState()) - .build(); - - return newPort; - } - - /** - * Builds list of OFPortOptical ports based on the multi-part circuit ports reply. - * - * Ensure the optical transport port's signal type is configured correctly. - * - * @param wPorts OF reply with circuit ports - */ - private void createOpticalPortList(OFCircuitPortsReply wPorts) { - opticalPorts = new ArrayList<>(wPorts.getEntries().size()); - - for (OFPortOptical p : wPorts.getEntries()) { - short signalType; - - // FIXME: use constants once loxi has full optical extensions - if (isOChPort(p.getPortNo().getPortNumber())) { - signalType = 5; // OCH port - } else { - signalType = 2; // OMS port - } - - opticalPorts.add(createOpticalPort(p, signalType)); - } - } - - @Override - public List getPortsOf(PortDescPropertyType type) { - if (!type.equals(PortDescPropertyType.OPTICAL_TRANSPORT)) { - return Collections.EMPTY_LIST; - } - - return opticalPorts; - } - - @Override - public Set getPortTypes() { - return ImmutableSet.of(PortDescPropertyType.OPTICAL_TRANSPORT); - } - - @Override - public SortedSet queryLambdas(PortNumber port) { - // OCh ports don't have lambdas - if (isOChPort(port.toLong())) { - return Collections.emptySortedSet(); - } - - // OMS ports expose 80 lambdas of 50GHz width, centered around the ITU-T center frequency. - // We report these with a spacing of 12.5 GHz. - List lambdas = IntStream.range(0, LAMBDA_COUNT) - .mapToObj(x -> new OchSignal(GridType.FLEX, ChannelSpacing.CHL_12P5GHZ, x - (LAMBDA_COUNT / 2), 1)) - .collect(Collectors.toList()); - - SortedSet result = new TreeSet<>(new DefaultOchSignalComparator()); - result.addAll(lambdas); - - return result; - } -} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/package-info.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/package-info.java deleted file mode 100644 index 754309eb..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2015 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. - */ - -/** - * Implementations of the OpenFlow handshake driver behaviours. - */ -package org.onosproject.driver.handshaker; \ No newline at end of file diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/netconf/NetconfControllerConfig.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/netconf/NetconfControllerConfig.java deleted file mode 100644 index 84043b5b..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/netconf/NetconfControllerConfig.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2015 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. - */ - -package org.onosproject.driver.netconf; - -import com.google.common.base.Preconditions; -import org.onosproject.net.DeviceId; -import org.onosproject.net.behaviour.ControllerConfig; -import org.onosproject.net.behaviour.ControllerInfo; -import org.onosproject.net.driver.AbstractHandlerBehaviour; -import org.onosproject.net.driver.DriverHandler; -import org.onosproject.netconf.NetconfController; -import org.onosproject.netconf.NetconfDevice; -import org.slf4j.Logger; - -import java.io.ByteArrayInputStream; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.List; - -import static org.slf4j.LoggerFactory.getLogger; - -/** - * Implementation of controller config which allows to get and set controllers - * through the Netconf protocol. - */ -public class NetconfControllerConfig extends AbstractHandlerBehaviour - implements ControllerConfig { - - private final Logger log = getLogger(NetconfControllerConfig.class); - - @Override - public List getControllers() { - DriverHandler handler = handler(); - NetconfController controller = handler.get(NetconfController.class); - DeviceId ofDeviceId = handler.data().deviceId(); - Preconditions.checkNotNull(controller, "Netconf controller is null"); - List controllers = new ArrayList<>(); - controllers.addAll(XmlConfigParser.parseStreamControllers(XmlConfigParser. - loadXml(new ByteArrayInputStream(controller. - getDevicesMap().get(ofDeviceId).getSession(). - getConfig("running").getBytes(StandardCharsets.UTF_8))))); - return controllers; - } - - @Override - public void setControllers(List controllers) { - DriverHandler handler = handler(); - NetconfController controller = handler.get(NetconfController.class); - DeviceId deviceId = handler.data().deviceId(); - Preconditions.checkNotNull(controller, "Netconf controller is null"); - try { - NetconfDevice device = controller.getNetconfDevice(deviceId); - log.warn("provider map {}", controller.getDevicesMap()); - String config = XmlConfigParser.createControllersConfig( - XmlConfigParser.loadXml(getClass().getResourceAsStream("controllers.xml")), - XmlConfigParser.loadXml( - new ByteArrayInputStream(device.getSession() - .getConfig("running") - .getBytes( - StandardCharsets.UTF_8))), - "running", "merge", "create", controllers - ); - device.getSession().editConfig(config.substring(config.indexOf("-->") + 3)); - } catch (NullPointerException e) { - log.warn("No NETCONF device with requested parameters " + e); - throw new NullPointerException("No NETCONF device with requested parameters " + e); - } - - } - - //TODO maybe put method getNetconfClientService like in ovsdb if we need it - -} - - diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/netconf/XmlConfigParser.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/netconf/XmlConfigParser.java deleted file mode 100644 index 55826a25..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/netconf/XmlConfigParser.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright 2015 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. - */ - -package org.onosproject.driver.netconf; - -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.HierarchicalConfiguration; -import org.apache.commons.configuration.XMLConfiguration; -import org.apache.commons.configuration.tree.ConfigurationNode; -import org.onlab.packet.IpAddress; -import org.onosproject.net.behaviour.ControllerInfo; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.InputStream; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.List; - -/** - * Parser for Netconf XML configurations and replys. - */ -final class XmlConfigParser { - public static final Logger log = LoggerFactory - .getLogger(XmlConfigParser.class); - - private XmlConfigParser() { - //not called, preventing any allocation - } - - - protected static HierarchicalConfiguration loadXml(InputStream xmlStream) { - XMLConfiguration cfg = new XMLConfiguration(); - try { - cfg.load(xmlStream); - return cfg; - } catch (ConfigurationException e) { - throw new IllegalArgumentException("Cannot load xml from Stream", e); - } - } - - protected static List parseStreamControllers(HierarchicalConfiguration cfg) { - List controllers = new ArrayList<>(); - List fields = - cfg.configurationsAt("data.capable-switch." + - "logical-switches." + - "switch.controllers.controller"); - for (HierarchicalConfiguration sub : fields) { - controllers.add(new ControllerInfo( - IpAddress.valueOf(sub.getString("ip-address")), - Integer.parseInt(sub.getString("port")), - sub.getString("protocol"))); - } - return controllers; - } - - protected static String parseSwitchId(HierarchicalConfiguration cfg) { - HierarchicalConfiguration field = - cfg.configurationAt("data.capable-switch." + - "logical-switches." + - "switch"); - return field.getProperty("id").toString(); - } - - protected static String parseCapableSwitchId(HierarchicalConfiguration cfg) { - HierarchicalConfiguration field = - cfg.configurationAt("data.capable-switch"); - return field.getProperty("id").toString(); - } - - protected static String createControllersConfig(HierarchicalConfiguration cfg, - HierarchicalConfiguration actualCfg, - String target, String netconfOperation, - String controllerOperation, - List controllers) { - //cfg.getKeys().forEachRemaining(key -> System.out.println(key)); - cfg.setProperty("edit-config.target", target); - cfg.setProperty("edit-config.default-operation", netconfOperation); - cfg.setProperty("edit-config.config.capable-switch.id", - parseCapableSwitchId(actualCfg)); - cfg.setProperty("edit-config.config.capable-switch." + - "logical-switches.switch.id", parseSwitchId(actualCfg)); - List newControllers = new ArrayList<>(); - for (ControllerInfo ci : controllers) { - XMLConfiguration controller = new XMLConfiguration(); - controller.setRoot(new HierarchicalConfiguration.Node("controller")); - String id = ci.type() + ":" + ci.ip() + ":" + ci.port(); - controller.setProperty("id", id); - controller.setProperty("ip-address", ci.ip()); - controller.setProperty("port", ci.port()); - controller.setProperty("protocol", ci.type()); - newControllers.add(controller.getRootNode()); - } - cfg.addNodes("edit-config.config.capable-switch.logical-switches." + - "switch.controllers", newControllers); - XMLConfiguration editcfg = (XMLConfiguration) cfg; - StringWriter stringWriter = new StringWriter(); - try { - editcfg.save(stringWriter); - } catch (ConfigurationException e) { - e.printStackTrace(); - } - String s = stringWriter.toString() - .replaceAll("", - ""); - s = s.replace("" + target + "", - "<" + target + "/>"); - return s; - - } - - //TODO implement mor methods for parsing configuration when you need them -} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/netconf/package-info.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/netconf/package-info.java deleted file mode 100644 index 200312b4..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/netconf/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2015 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. - */ - -/** - * Implementations of the Netconf driver behaviours. - */ -package org.onosproject.driver.netconf; \ No newline at end of file diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/ovsdb/OvsdbBridgeConfig.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/ovsdb/OvsdbBridgeConfig.java deleted file mode 100644 index 6451160a..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/ovsdb/OvsdbBridgeConfig.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright 2015 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. - */ -package org.onosproject.driver.ovsdb; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -import org.onlab.packet.IpAddress; -import org.onosproject.net.DefaultAnnotations; -import org.onosproject.net.DeviceId; -import org.onosproject.net.PortNumber; -import org.onosproject.net.behaviour.BridgeConfig; -import org.onosproject.net.behaviour.BridgeDescription; -import org.onosproject.net.behaviour.BridgeName; -import org.onosproject.net.behaviour.ControllerInfo; -import org.onosproject.net.behaviour.DefaultBridgeDescription; -import org.onosproject.net.device.DefaultPortDescription; -import org.onosproject.net.device.PortDescription; -import org.onosproject.net.driver.AbstractHandlerBehaviour; -import org.onosproject.net.driver.DriverHandler; -import org.onosproject.ovsdb.controller.OvsdbBridge; -import org.onosproject.ovsdb.controller.OvsdbClientService; -import org.onosproject.ovsdb.controller.OvsdbController; -import org.onosproject.ovsdb.controller.OvsdbNodeId; -import org.onosproject.ovsdb.controller.OvsdbPort; - -/** - * The implementation of BridageConfig. - */ -public class OvsdbBridgeConfig extends AbstractHandlerBehaviour - implements BridgeConfig { - - @Override - public void addBridge(BridgeName bridgeName) { - DriverHandler handler = handler(); - OvsdbClientService clientService = getOvsdbClientService(handler); - clientService.createBridge(bridgeName.name()); - } - - @Override - public void addBridge(BridgeName bridgeName, String dpid, String exPortName) { - DriverHandler handler = handler(); - OvsdbClientService clientService = getOvsdbClientService(handler); - clientService.createBridge(bridgeName.name(), dpid, exPortName); - } - - @Override - public boolean addBridge(BridgeName bridgeName, String dpid, List controllers) { - DriverHandler handler = handler(); - OvsdbClientService clientService = getOvsdbClientService(handler); - return clientService.createBridge(bridgeName.name(), dpid, controllers); - } - - @Override - public void deleteBridge(BridgeName bridgeName) { - DriverHandler handler = handler(); - OvsdbClientService clientService = getOvsdbClientService(handler); - clientService.dropBridge(bridgeName.name()); - } - - @Override - public Collection getBridges() { - DriverHandler handler = handler(); - DeviceId deviceId = handler.data().deviceId(); - OvsdbClientService clientService = getOvsdbClientService(handler); - Set bridges = clientService.getBridges(); - - return bridges.stream() - .map(x -> new DefaultBridgeDescription( - BridgeName.bridgeName(x.bridgeName().value()), - deviceId, - DeviceId.deviceId("of:" + x.datapathId().value()) - ) - ) - .collect(Collectors.toSet()); - } - - @Override - public void addPort(PortDescription port) { - DriverHandler handler = handler(); - OvsdbClientService clientService = getOvsdbClientService(handler); - Set ovsdbSet = clientService.getBridges(); - if (ovsdbSet != null && ovsdbSet.size() > 0) { - OvsdbBridge bridge = ovsdbSet.iterator().next(); - clientService.createPort(bridge.bridgeName().toString(), port - .portNumber().toString()); - } - } - - @Override - public void deletePort(PortDescription port) { - DriverHandler handler = handler(); - OvsdbClientService clientService = getOvsdbClientService(handler); - Set ovsdbSet = clientService.getBridges(); - if (ovsdbSet != null && ovsdbSet.size() > 0) { - OvsdbBridge bridge = ovsdbSet.iterator().next(); - clientService.dropPort(bridge.bridgeName().toString(), port - .portNumber().toString()); - } - } - - @Override - public Collection getPorts() { - DriverHandler handler = handler(); - OvsdbClientService clientService = getOvsdbClientService(handler); - Set ports = clientService.getPorts(); - - return ports.stream() - .map(x -> new DefaultPortDescription( - PortNumber.portNumber(x.portNumber().value()), - true, - DefaultAnnotations.builder() - .set("portName", x.portName().value()) - .build())) - .collect(Collectors.toSet()); - } - - // OvsdbNodeId(IP) is used in the adaptor while DeviceId(ovsdb:IP) - // is used in the core. So DeviceId need be changed to OvsdbNodeId. - private OvsdbNodeId changeDeviceIdToNodeId(DeviceId deviceId) { - String[] splits = deviceId.toString().split(":"); - if (splits == null || splits.length < 1) { - return null; - } - IpAddress ipAddress = IpAddress.valueOf(splits[1]); - return new OvsdbNodeId(ipAddress, 0); - } - - // Used for getting OvsdbClientService. - private OvsdbClientService getOvsdbClientService(DriverHandler handler) { - OvsdbController ovsController = handler.get(OvsdbController.class); - DeviceId deviceId = handler.data().deviceId(); - OvsdbNodeId nodeId = changeDeviceIdToNodeId(deviceId); - return ovsController.getOvsdbClient(nodeId); - } - - @Override - public Set getPortNumbers() { - DriverHandler handler = handler(); - OvsdbClientService clientService = getOvsdbClientService(handler); - Set ports = clientService.getPorts(); - - return ports.stream() - .map(x -> PortNumber.portNumber( - x.portNumber().value(), - x.portName().value() - ) - ) - .collect(Collectors.toSet()); - } - - @Override - public List getLocalPorts(Iterable ifaceIds) { - List ports = new ArrayList<>(); - DriverHandler handler = handler(); - OvsdbClientService clientService = getOvsdbClientService(handler); - Set ovsdbSet = clientService.getLocalPorts(ifaceIds); - ovsdbSet.forEach(o -> { - PortNumber port = PortNumber.portNumber(o.portNumber().value(), - o.portName().value()); - ports.add(port); - }); - return ports; - } -} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/ovsdb/OvsdbControllerConfig.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/ovsdb/OvsdbControllerConfig.java deleted file mode 100644 index f116ab84..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/ovsdb/OvsdbControllerConfig.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 2015 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. - */ - -package org.onosproject.driver.ovsdb; - -import com.google.common.collect.ImmutableSet; -import org.onlab.packet.IpAddress; -import org.onlab.packet.TpPort; -import org.onosproject.net.AnnotationKeys; -import org.onosproject.net.DeviceId; -import org.onosproject.net.behaviour.ControllerConfig; -import org.onosproject.net.behaviour.ControllerInfo; -import org.onosproject.net.device.DeviceService; -import org.onosproject.net.driver.AbstractHandlerBehaviour; -import org.onosproject.net.driver.DriverHandler; -import org.onosproject.ovsdb.controller.OvsdbBridge; -import org.onosproject.ovsdb.controller.OvsdbClientService; -import org.onosproject.ovsdb.controller.OvsdbController; -import org.onosproject.ovsdb.controller.OvsdbNodeId; - -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -import static com.google.common.base.Preconditions.checkState; -import static org.onlab.util.Tools.delay; - -/** - * Implementation of controller config which allows to get and set controllers. - */ -public class OvsdbControllerConfig extends AbstractHandlerBehaviour implements ControllerConfig { - @Override - public List getControllers() { - DriverHandler handler = handler(); - OvsdbClientService clientService = getOvsdbClientService(handler); - Set controllers = clientService.getControllers( - handler().data().deviceId()); - return new ArrayList<>(controllers); - } - - @Override - public void setControllers(List controllers) { - DriverHandler handler = handler(); - OvsdbClientService clientService = getOvsdbClientService(handler); - if (!clientService.getControllers(handler().data().deviceId()) - .equals(ImmutableSet.copyOf(controllers))) { - clientService.setControllersWithDeviceId(handler(). - data().deviceId(), controllers); - } - } - - // Used for getting OvsdbClientService. - private OvsdbClientService getOvsdbClientService(DriverHandler handler) { - OvsdbController ovsController = handler.get(OvsdbController.class); - DeviceService deviceService = handler.get(DeviceService.class); - DeviceId ofDeviceId = handler.data().deviceId(); - String[] mgmtAddress = deviceService.getDevice(ofDeviceId) - .annotations().value(AnnotationKeys.MANAGEMENT_ADDRESS).split(":"); - String targetIp = mgmtAddress[0]; - TpPort targetPort = null; - if (mgmtAddress.length > 1) { - targetPort = TpPort.tpPort(Integer.parseInt(mgmtAddress[1])); - } - - List nodeIds = ovsController.getNodeIds().stream() - .filter(nodeId -> nodeId.getIpAddress().equals(targetIp)) - .collect(Collectors.toList()); - if (nodeIds.size() == 0) { - //TODO decide what port? - ovsController.connect(IpAddress.valueOf(targetIp), - targetPort == null ? TpPort.tpPort(6640) : targetPort); - delay(1000); //FIXME... connect is async - } - List clientServices = ovsController.getNodeIds().stream() - .filter(nodeId -> nodeId.getIpAddress().equals(targetIp)) - .map(ovsController::getOvsdbClient) - .filter(cs -> cs.getBridges().stream().anyMatch(b -> dpidMatches(b, ofDeviceId))) - .collect(Collectors.toList()); - checkState(clientServices.size() > 0, "No clientServices found"); - //FIXME add connection to management address if null --> done ? - return clientServices.size() > 0 ? clientServices.get(0) : null; - } - - private static boolean dpidMatches(OvsdbBridge bridge, DeviceId deviceId) { - String bridgeDpid = "of:" + bridge.datapathId().value(); - String ofDpid = deviceId.toString(); - return bridgeDpid.equals(ofDpid); - } -} \ No newline at end of file diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/ovsdb/OvsdbTunnelConfig.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/ovsdb/OvsdbTunnelConfig.java deleted file mode 100644 index ad90ca44..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/ovsdb/OvsdbTunnelConfig.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2015 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. - */ -package org.onosproject.driver.ovsdb; - -import java.util.Collection; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -import org.onlab.packet.IpAddress; -import org.onosproject.net.DefaultAnnotations; -import org.onosproject.net.DeviceId; -import org.onosproject.net.behaviour.BridgeName; -import org.onosproject.net.behaviour.DefaultTunnelDescription; -import org.onosproject.net.behaviour.IpTunnelEndPoint; -import org.onosproject.net.behaviour.TunnelConfig; -import org.onosproject.net.behaviour.TunnelDescription; -import org.onosproject.net.behaviour.TunnelName; -import org.onosproject.net.driver.AbstractHandlerBehaviour; -import org.onosproject.net.driver.DriverHandler; -import org.onosproject.ovsdb.controller.OvsdbClientService; -import org.onosproject.ovsdb.controller.OvsdbController; -import org.onosproject.ovsdb.controller.OvsdbNodeId; -import org.onosproject.ovsdb.controller.OvsdbTunnel; - -/** - * OVSDB-based implementation of tunnel config behaviour. - */ -public class OvsdbTunnelConfig extends AbstractHandlerBehaviour - implements TunnelConfig { - - private static final String DEFAULT_ADDRESS = "0.0.0.0"; - private static final String OPTION_LOCAL_IP = "local_ip"; - private static final String OPTION_REMOTE_IP = "remote_ip"; - - @Override - public void createTunnel(TunnelDescription tunnel) { - DriverHandler handler = handler(); - OvsdbClientService ovsdbNode = getOvsdbNode(handler); - IpTunnelEndPoint ipSrc = IpTunnelEndPoint.ipTunnelPoint(IpAddress - .valueOf(DEFAULT_ADDRESS)); - IpTunnelEndPoint ipDst = IpTunnelEndPoint.ipTunnelPoint(IpAddress - .valueOf(DEFAULT_ADDRESS)); - if (tunnel.src() instanceof IpTunnelEndPoint) { - ipSrc = (IpTunnelEndPoint) tunnel.src(); - } - if (tunnel.dst() instanceof IpTunnelEndPoint) { - ipDst = (IpTunnelEndPoint) tunnel.dst(); - } - //Even if source point ip or destination point ip equals 0:0:0:0, it is still work-in-progress. - ovsdbNode.createTunnel(ipSrc.ip(), ipDst.ip()); - } - - @Override - public boolean createTunnelInterface(BridgeName bridgeName, TunnelDescription tunnel) { - Map options = ((DefaultAnnotations) tunnel.annotations()).asMap(); - if (tunnel.src() != null) { - options.put(OPTION_LOCAL_IP, ((IpTunnelEndPoint) tunnel.src()).ip().toString()); - } - if (tunnel.dst() != null) { - options.put(OPTION_REMOTE_IP, ((IpTunnelEndPoint) tunnel.dst()).ip().toString()); - } - - DriverHandler handler = handler(); - OvsdbClientService ovsdbClient = getOvsdbNode(handler); - return ovsdbClient.createTunnel(bridgeName.name(), tunnel.tunnelName().toString(), - tunnel.type().toString().toLowerCase(), options); - } - - @Override - public void removeTunnel(TunnelDescription tunnel) { - DriverHandler handler = handler(); - OvsdbClientService ovsdbNode = getOvsdbNode(handler); - IpTunnelEndPoint ipSrc = IpTunnelEndPoint.ipTunnelPoint(IpAddress - .valueOf(DEFAULT_ADDRESS)); - IpTunnelEndPoint ipDst = IpTunnelEndPoint.ipTunnelPoint(IpAddress - .valueOf(DEFAULT_ADDRESS)); - if (tunnel.src() instanceof IpTunnelEndPoint) { - ipSrc = (IpTunnelEndPoint) tunnel.src(); - } - if (tunnel.dst() instanceof IpTunnelEndPoint) { - ipDst = (IpTunnelEndPoint) tunnel.dst(); - } - //Even if source point ip or destination point ip equals 0:0:0:0, it is still work-in-progress. - ovsdbNode.dropTunnel(ipSrc.ip(), ipDst.ip()); - } - - @Override - public void updateTunnel(TunnelDescription tunnel) { - // TODO Auto-generated method stub - - } - - @Override - public Collection getTunnels() { - DriverHandler handler = handler(); - OvsdbClientService ovsdbNode = getOvsdbNode(handler); - Set tunnels = ovsdbNode.getTunnels(); - - return tunnels.stream() - .map(x -> - new DefaultTunnelDescription( - IpTunnelEndPoint.ipTunnelPoint(x.localIp()), - IpTunnelEndPoint.ipTunnelPoint(x.remoteIp()), - TunnelDescription.Type.VXLAN, - TunnelName.tunnelName(x.tunnelName().toString()) - ) - ) - .collect(Collectors.toSet()); - } - - // OvsdbNodeId(IP) is used in the adaptor while DeviceId(ovsdb:IP) - // is used in the core. So DeviceId need be changed to OvsdbNodeId. - private OvsdbNodeId changeDeviceIdToNodeId(DeviceId deviceId) { - String[] splits = deviceId.toString().split(":"); - if (splits == null || splits.length < 1) { - return null; - } - IpAddress ipAddress = IpAddress.valueOf(splits[1]); - return new OvsdbNodeId(ipAddress, 0); - } - - private OvsdbClientService getOvsdbNode(DriverHandler handler) { - OvsdbController ovsController = handler.get(OvsdbController.class); - DeviceId deviceId = handler.data().deviceId(); - OvsdbNodeId nodeId = changeDeviceIdToNodeId(deviceId); - return ovsController.getOvsdbClient(nodeId); - } -} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/ovsdb/package-info.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/ovsdb/package-info.java deleted file mode 100644 index 8d878a50..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/ovsdb/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2015 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. - */ - -/** - * Implementations of OVSDB protocol configurations. - */ -package org.onosproject.driver.ovsdb; \ No newline at end of file diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/package-info.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/package-info.java deleted file mode 100644 index 41a6a02f..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2015 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. - */ - -/** - * Bootstrap of built-in device drivers. - */ -package org.onosproject.driver; \ No newline at end of file diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CentecV350Pipeline.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CentecV350Pipeline.java deleted file mode 100644 index cd7a1b66..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CentecV350Pipeline.java +++ /dev/null @@ -1,640 +0,0 @@ -/* - * Copyright 2015 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. - */ -package org.onosproject.driver.pipeline; - - -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.RemovalCause; -import com.google.common.cache.RemovalNotification; - -import org.onlab.osgi.ServiceDirectory; -import org.onlab.packet.Ethernet; -import org.onlab.packet.IPv4; -import org.onlab.packet.TpPort; -import org.onlab.packet.VlanId; -import org.onlab.util.KryoNamespace; -import org.onosproject.core.ApplicationId; -import org.onosproject.core.CoreService; -import org.onosproject.net.DeviceId; -import org.onosproject.net.PortNumber; -import org.onosproject.net.behaviour.NextGroup; -import org.onosproject.net.behaviour.Pipeliner; -import org.onosproject.net.behaviour.PipelinerContext; -import org.onosproject.net.driver.AbstractHandlerBehaviour; -import org.onosproject.net.flow.DefaultFlowRule; -import org.onosproject.net.flow.DefaultTrafficSelector; -import org.onosproject.net.flow.DefaultTrafficTreatment; -import org.onosproject.net.flow.FlowRule; -import org.onosproject.net.flow.FlowRuleOperations; -import org.onosproject.net.flow.FlowRuleOperationsContext; -import org.onosproject.net.flow.FlowRuleService; -import org.onosproject.net.flow.TrafficSelector; -import org.onosproject.net.flow.TrafficTreatment; -import org.onosproject.net.flow.criteria.Criterion; -import org.onosproject.net.flow.criteria.Criteria; -import org.onosproject.net.flow.criteria.EthCriterion; -import org.onosproject.net.flow.criteria.PortCriterion; -import org.onosproject.net.flow.criteria.EthTypeCriterion; -import org.onosproject.net.flow.criteria.IPCriterion; -import org.onosproject.net.flow.criteria.VlanIdCriterion; -import org.onosproject.net.flow.instructions.Instruction; -import org.onosproject.net.flow.instructions.L2ModificationInstruction; -import org.onosproject.net.flowobjective.FilteringObjective; -import org.onosproject.net.flowobjective.FlowObjectiveStore; -import org.onosproject.net.flowobjective.ForwardingObjective; -import org.onosproject.net.flowobjective.NextObjective; -import org.onosproject.net.flowobjective.Objective; -import org.onosproject.net.flowobjective.ObjectiveError; -import org.onosproject.net.group.DefaultGroupBucket; -import org.onosproject.net.group.DefaultGroupDescription; -import org.onosproject.net.group.DefaultGroupKey; -import org.onosproject.net.group.Group; -import org.onosproject.net.group.GroupBucket; -import org.onosproject.net.group.GroupBuckets; -import org.onosproject.net.group.GroupDescription; -import org.onosproject.net.group.GroupEvent; -import org.onosproject.net.group.GroupKey; -import org.onosproject.net.group.GroupListener; -import org.onosproject.net.group.GroupService; -import org.slf4j.Logger; - -import java.util.Collection; -import java.util.Collections; -import java.util.Set; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - -import static org.onlab.util.Tools.groupedThreads; -import static org.slf4j.LoggerFactory.getLogger; - -/** - * Driver for Centec's V350 switches. - */ -public class CentecV350Pipeline extends AbstractHandlerBehaviour implements Pipeliner { - - protected static final int PORT_VLAN_TABLE = 0; - protected static final int FILTER_TABLE = 1; - // TMAC is configured in MAC Table to redirect packets to ROUTE_TABLE. - protected static final int MAC_TABLE = 2; - protected static final int ROUTE_TABLE = 3; - - private static final long DEFAULT_METADATA = 100; - private static final long DEFAULT_METADATA_MASK = 0xffffffffffffffffL; - - // Priority used in PORT_VLAN Table, the only priority accepted is PORT_VLAN_TABLE_PRIORITY. - // The packet passed PORT+VLAN check will goto FILTER Table. - private static final int PORT_VLAN_TABLE_PRIORITY = 0xffff; - - // Priority used in Filter Table. - private static final int FILTER_TABLE_CONTROLLER_PRIORITY = 500; - // TMAC priority should be lower than controller. - private static final int FILTER_TABLE_TMAC_PRIORITY = 200; - private static final int FILTER_TABLE_HIGHEST_PRIORITY = 0xffff; - - // Priority used in MAC Table. - // We do exact matching for DMAC+metadata, so priority is ignored and required to be set to 0xffff. - private static final int MAC_TABLE_PRIORITY = 0xffff; - - // Priority used in Route Table. - // We do LPM matching in Route Table, so priority is ignored and required to be set to 0xffff. - private static final int ROUTE_TABLE_PRIORITY = 0xffff; - - private static final short BGP_PORT = 179; - - private final Logger log = getLogger(getClass()); - - private ServiceDirectory serviceDirectory; - private FlowRuleService flowRuleService; - private CoreService coreService; - private GroupService groupService; - private FlowObjectiveStore flowObjectiveStore; - private DeviceId deviceId; - private ApplicationId appId; - - private KryoNamespace appKryo = new KryoNamespace.Builder() - .register(GroupKey.class) - .register(DefaultGroupKey.class) - .register(CentecV350Group.class) - .register(byte[].class) - .build(); - - private Cache pendingGroups; - - private ScheduledExecutorService groupChecker = - Executors.newScheduledThreadPool(2, groupedThreads("onos/pipeliner", - "centec-V350-%d")); - - @Override - public void init(DeviceId deviceId, PipelinerContext context) { - this.serviceDirectory = context.directory(); - this.deviceId = deviceId; - - pendingGroups = CacheBuilder.newBuilder() - .expireAfterWrite(20, TimeUnit.SECONDS) - .removalListener((RemovalNotification notification) -> { - if (notification.getCause() == RemovalCause.EXPIRED) { - fail(notification.getValue(), ObjectiveError.GROUPINSTALLATIONFAILED); - } - }).build(); - - groupChecker.scheduleAtFixedRate(new GroupChecker(), 0, 500, TimeUnit.MILLISECONDS); - - coreService = serviceDirectory.get(CoreService.class); - flowRuleService = serviceDirectory.get(FlowRuleService.class); - groupService = serviceDirectory.get(GroupService.class); - flowObjectiveStore = context.store(); - - groupService.addListener(new InnerGroupListener()); - - appId = coreService.registerApplication( - "org.onosproject.driver.CentecV350Pipeline"); - - initializePipeline(); - } - - @Override - public void filter(FilteringObjective filteringObjective) { - if (filteringObjective.type() == FilteringObjective.Type.PERMIT) { - processFilter(filteringObjective, - filteringObjective.op() == Objective.Operation.ADD, - filteringObjective.appId()); - } else { - fail(filteringObjective, ObjectiveError.UNSUPPORTED); - } - } - - @Override - public void forward(ForwardingObjective fwd) { - Collection rules; - FlowRuleOperations.Builder flowBuilder = FlowRuleOperations.builder(); - - rules = processForward(fwd); - switch (fwd.op()) { - case ADD: - rules.stream() - .filter(rule -> rule != null) - .forEach(flowBuilder::add); - break; - case REMOVE: - rules.stream() - .filter(rule -> rule != null) - .forEach(flowBuilder::remove); - break; - default: - fail(fwd, ObjectiveError.UNKNOWN); - log.warn("Unknown forwarding type {}", fwd.op()); - } - - - flowRuleService.apply(flowBuilder.build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - pass(fwd); - } - - @Override - public void onError(FlowRuleOperations ops) { - fail(fwd, ObjectiveError.FLOWINSTALLATIONFAILED); - } - })); - - } - - @Override - public void next(NextObjective nextObjective) { - switch (nextObjective.type()) { - case SIMPLE: - Collection treatments = nextObjective.next(); - if (treatments.size() == 1) { - TrafficTreatment treatment = treatments.iterator().next(); - - // Since we do not support strip_vlan in PORT_VLAN table, we use mod_vlan - // to modify the packet to desired vlan. - // Note: if we use push_vlan here, the switch will add a second VLAN tag to the outgoing - // packet, which is not what we want. - TrafficTreatment.Builder treatmentWithoutPushVlan = DefaultTrafficTreatment.builder(); - VlanId modVlanId; - for (Instruction ins : treatment.allInstructions()) { - if (ins.type() == Instruction.Type.L2MODIFICATION) { - L2ModificationInstruction l2ins = (L2ModificationInstruction) ins; - switch (l2ins.subtype()) { - case ETH_DST: - treatmentWithoutPushVlan.setEthDst( - ((L2ModificationInstruction.ModEtherInstruction) l2ins).mac()); - break; - case ETH_SRC: - treatmentWithoutPushVlan.setEthSrc( - ((L2ModificationInstruction.ModEtherInstruction) l2ins).mac()); - break; - case VLAN_ID: - modVlanId = ((L2ModificationInstruction.ModVlanIdInstruction) l2ins).vlanId(); - treatmentWithoutPushVlan.setVlanId(modVlanId); - break; - default: - break; - } - } else if (ins.type() == Instruction.Type.OUTPUT) { - //long portNum = ((Instructions.OutputInstruction) ins).port().toLong(); - treatmentWithoutPushVlan.add(ins); - } else { - // Ignore the vlan_pcp action since it's does matter much. - log.warn("Driver does not handle this type of TrafficTreatment" - + " instruction in nextObjectives: {}", ins.type()); - } - } - - GroupBucket bucket = - DefaultGroupBucket.createIndirectGroupBucket(treatmentWithoutPushVlan.build()); - final GroupKey key = new DefaultGroupKey(appKryo.serialize(nextObjective.id())); - GroupDescription groupDescription - = new DefaultGroupDescription(deviceId, - GroupDescription.Type.INDIRECT, - new GroupBuckets(Collections - .singletonList(bucket)), - key, - null, // let group service determine group id - nextObjective.appId()); - groupService.addGroup(groupDescription); - pendingGroups.put(key, nextObjective); - } - break; - case HASHED: - case BROADCAST: - case FAILOVER: - fail(nextObjective, ObjectiveError.UNSUPPORTED); - log.warn("Unsupported next objective type {}", nextObjective.type()); - break; - default: - fail(nextObjective, ObjectiveError.UNKNOWN); - log.warn("Unknown next objective type {}", nextObjective.type()); - } - - } - - private Collection processForward(ForwardingObjective fwd) { - switch (fwd.flag()) { - case SPECIFIC: - return processSpecific(fwd); - case VERSATILE: - return processVersatile(fwd); - default: - fail(fwd, ObjectiveError.UNKNOWN); - log.warn("Unknown forwarding flag {}", fwd.flag()); - } - return Collections.emptySet(); - } - - private Collection processVersatile(ForwardingObjective fwd) { - log.warn("Driver does not support versatile forwarding objective"); - fail(fwd, ObjectiveError.UNSUPPORTED); - return Collections.emptySet(); - } - - private Collection processSpecific(ForwardingObjective fwd) { - log.debug("Processing specific forwarding objective"); - TrafficSelector selector = fwd.selector(); - EthTypeCriterion ethType = - (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE); - if (ethType == null || ethType.ethType().toShort() != Ethernet.TYPE_IPV4) { - fail(fwd, ObjectiveError.UNSUPPORTED); - return Collections.emptySet(); - } - - // Must have metadata as key. - TrafficSelector filteredSelector = - DefaultTrafficSelector.builder() - .matchEthType(Ethernet.TYPE_IPV4) - .matchMetadata(DEFAULT_METADATA) - .matchIPDst( - ((IPCriterion) - selector.getCriterion(Criterion.Type.IPV4_DST)).ip()) - .build(); - - TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder(); - - if (fwd.nextId() != null) { - NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId()); - GroupKey key = appKryo.deserialize(next.data()); - Group group = groupService.getGroup(deviceId, key); - if (group == null) { - log.warn("The group left!"); - fail(fwd, ObjectiveError.GROUPMISSING); - return Collections.emptySet(); - } - tb.group(group.id()); - } - - FlowRule.Builder ruleBuilder = DefaultFlowRule.builder() - .fromApp(fwd.appId()) - .withPriority(ROUTE_TABLE_PRIORITY) - .forDevice(deviceId) - .withSelector(filteredSelector) - .withTreatment(tb.build()); - - if (fwd.permanent()) { - ruleBuilder.makePermanent(); - } else { - ruleBuilder.makeTemporary(fwd.timeout()); - } - - ruleBuilder.forTable(ROUTE_TABLE); - - return Collections.singletonList(ruleBuilder.build()); - - } - - private void processFilter(FilteringObjective filt, boolean install, - ApplicationId applicationId) { - PortCriterion p; - if (!filt.key().equals(Criteria.dummy()) && - filt.key().type() == Criterion.Type.IN_PORT) { - p = (PortCriterion) filt.key(); - } else { - log.warn("No key defined in filtering objective from app: {}. Not" - + "processing filtering objective", applicationId); - fail(filt, ObjectiveError.UNKNOWN); - return; - } - - // Convert filtering conditions for switch-intfs into flow rules. - FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); - - for (Criterion c : filt.conditions()) { - // Here we do a trick to install 2 flow rules to MAC_TABLE and ROUTE_TABLE. - if (c.type() == Criterion.Type.ETH_DST) { - EthCriterion e = (EthCriterion) c; - - // Install TMAC flow rule. - log.debug("adding rule for Termination MAC in Filter Table: {}", e.mac()); - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); - selector.matchEthDst(e.mac()); - // Add IPv4 matching explicitly since we will redirect it to ROUTE Table - // through MAC table. - selector.matchEthType(Ethernet.TYPE_IPV4); - treatment.transition(MAC_TABLE); - FlowRule rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(FILTER_TABLE_TMAC_PRIORITY) - .fromApp(applicationId) - .makePermanent() - .forTable(FILTER_TABLE).build(); - ops = install ? ops.add(rule) : ops.remove(rule); - - // Must install another rule to direct the IPv4 packets that hit TMAC to - // Route table. - log.debug("adding rule for Termination MAC in MAC Table: {}", e.mac()); - selector = DefaultTrafficSelector.builder(); - treatment = DefaultTrafficTreatment.builder(); - selector.matchEthDst(e.mac()); - // MAC_Table must have metadata matching configured, use the default metadata. - selector.matchMetadata(DEFAULT_METADATA); - treatment.transition(ROUTE_TABLE); - rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(MAC_TABLE_PRIORITY) - .fromApp(applicationId) - .makePermanent() - .forTable(MAC_TABLE).build(); - ops = install ? ops.add(rule) : ops.remove(rule); - } else if (c.type() == Criterion.Type.VLAN_VID) { - VlanIdCriterion v = (VlanIdCriterion) c; - log.debug("adding rule for VLAN: {}", v.vlanId()); - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); - selector.matchVlanId(v.vlanId()); - selector.matchInPort(p.port()); - // Although the accepted packets will be sent to filter table, we must - // explicitly set goto_table instruction here. - treatment.writeMetadata(DEFAULT_METADATA, DEFAULT_METADATA_MASK); - // set default metadata written by PORT_VLAN Table. - treatment.transition(FILTER_TABLE); - // We do not support strip vlan here, treatment.deferred().popVlan(); - // PORT_VLAN table only accept 0xffff priority since it does exact match only. - FlowRule rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(PORT_VLAN_TABLE_PRIORITY) - .fromApp(applicationId) - .makePermanent() - .forTable(PORT_VLAN_TABLE).build(); - ops = install ? ops.add(rule) : ops.remove(rule); - } else if (c.type() == Criterion.Type.IPV4_DST) { - IPCriterion ipaddr = (IPCriterion) c; - log.debug("adding IP filtering rules in FILTER table: {}", ipaddr.ip()); - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); - selector.matchEthType(Ethernet.TYPE_IPV4); - selector.matchIPDst(ipaddr.ip()); // router IPs to the controller - treatment.setOutput(PortNumber.CONTROLLER); - FlowRule rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(FILTER_TABLE_CONTROLLER_PRIORITY) - .fromApp(applicationId) - .makePermanent() - .forTable(FILTER_TABLE).build(); - ops = install ? ops.add(rule) : ops.remove(rule); - } else { - log.warn("Driver does not currently process filtering condition" - + " of type: {}", c.type()); - fail(filt, ObjectiveError.UNSUPPORTED); - } - } - - // apply filtering flow rules - flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - pass(filt); - log.info("Applied filtering rules"); - } - - @Override - public void onError(FlowRuleOperations ops) { - fail(filt, ObjectiveError.FLOWINSTALLATIONFAILED); - log.info("Failed to apply filtering rules"); - } - })); - } - - private void pass(Objective obj) { - if (obj.context().isPresent()) { - obj.context().get().onSuccess(obj); - } - } - - private void fail(Objective obj, ObjectiveError error) { - if (obj.context().isPresent()) { - obj.context().get().onError(obj, error); - } - } - - private void initializePipeline() { - // CENTEC_V350: PORT_VLAN_TABLE->FILTER_TABLE->MAC_TABLE(TMAC)->ROUTE_TABLE. - processPortVlanTable(true); - processFilterTable(true); - } - - private void processPortVlanTable(boolean install) { - // By default the packet are dropped, need install port+vlan by some ways. - - // XXX can we add table-miss-entry to drop? Code says drops by default - // XXX TTP description says default goes to table1. - // It also says that match is only on vlan -- not port-vlan -- which one is true? - } - - private void processFilterTable(boolean install) { - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); - TrafficTreatment.Builder treatment = DefaultTrafficTreatment - .builder(); - FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); - FlowRule rule; - - // Punt ARP packets to controller by default. - selector.matchEthType(Ethernet.TYPE_ARP); - treatment.punt(); - rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(FILTER_TABLE_CONTROLLER_PRIORITY) - .fromApp(appId) - .makePermanent() - .forTable(FILTER_TABLE).build(); - ops = install ? ops.add(rule) : ops.remove(rule); - - // Punt BGP packets to controller directly. - selector = DefaultTrafficSelector.builder(); - treatment = DefaultTrafficTreatment.builder(); - selector.matchEthType(Ethernet.TYPE_IPV4) - .matchIPProtocol(IPv4.PROTOCOL_TCP) - .matchTcpSrc(TpPort.tpPort(BGP_PORT)); - treatment.punt(); - rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withPriority(FILTER_TABLE_HIGHEST_PRIORITY) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .fromApp(appId) - .makePermanent() - .forTable(FILTER_TABLE).build(); - ops = install ? ops.add(rule) : ops.remove(rule); - - selector = DefaultTrafficSelector.builder(); - treatment = DefaultTrafficTreatment.builder(); - selector.matchEthType(Ethernet.TYPE_IPV4) - .matchIPProtocol(IPv4.PROTOCOL_TCP) - .matchTcpDst(TpPort.tpPort(BGP_PORT)); - treatment.punt(); - rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withPriority(FILTER_TABLE_HIGHEST_PRIORITY) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .fromApp(appId) - .makePermanent() - .forTable(FILTER_TABLE).build(); - - ops = install ? ops.add(rule) : ops.remove(rule); - - // Packet will be discard in PORT_VLAN table, no need to install rule in - // filter table. - - // XXX does not tell me if packets are going to be dropped by default in - // filter table or not? TTP says it will be dropped by default - - flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - log.info("Provisioned filter table"); - } - - @Override - public void onError(FlowRuleOperations ops) { - log.info("Failed to provision filter table"); - } - })); - } - - private class InnerGroupListener implements GroupListener { - @Override - public void event(GroupEvent event) { - if (event.type() == GroupEvent.Type.GROUP_ADDED) { - GroupKey key = event.subject().appCookie(); - - NextObjective obj = pendingGroups.getIfPresent(key); - if (obj != null) { - flowObjectiveStore.putNextGroup(obj.id(), new CentecV350Group(key)); - pass(obj); - pendingGroups.invalidate(key); - } - } - } - } - - - private class GroupChecker implements Runnable { - - @Override - public void run() { - Set keys = pendingGroups.asMap().keySet().stream() - .filter(key -> groupService.getGroup(deviceId, key) != null) - .collect(Collectors.toSet()); - - keys.stream().forEach(key -> { - NextObjective obj = pendingGroups.getIfPresent(key); - if (obj == null) { - return; - } - pass(obj); - pendingGroups.invalidate(key); - log.info("Heard back from group service for group {}. " - + "Applying pending forwarding objectives", obj.id()); - flowObjectiveStore.putNextGroup(obj.id(), new CentecV350Group(key)); - }); - } - } - - private class CentecV350Group implements NextGroup { - - private final GroupKey key; - - public CentecV350Group(GroupKey key) { - this.key = key; - } - - @SuppressWarnings("unused") - public GroupKey key() { - return key; - } - - @Override - public byte[] data() { - return appKryo.serialize(key); - } - - } -} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CorsaPipeline.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CorsaPipeline.java deleted file mode 100644 index ccf73079..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CorsaPipeline.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2015 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. - */ -package org.onosproject.driver.pipeline; - -import static org.slf4j.LoggerFactory.getLogger; - -import org.onlab.packet.Ethernet; -import org.onosproject.net.flow.DefaultFlowRule; -import org.onosproject.net.flow.DefaultTrafficSelector; -import org.onosproject.net.flow.DefaultTrafficTreatment; -import org.onosproject.net.flow.FlowRule; -import org.onosproject.net.flow.FlowRuleOperations; -import org.onosproject.net.flow.FlowRuleOperationsContext; -import org.onosproject.net.flow.TrafficSelector; -import org.onosproject.net.flow.TrafficTreatment; -import org.slf4j.Logger; - -/** - * Driver for Corsa TTP. - * - */ -public class CorsaPipeline extends OVSCorsaPipeline { - - private final Logger log = getLogger(getClass()); - - @Override - protected void processVlanMplsTable(boolean install) { - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); - TrafficTreatment.Builder treatment = DefaultTrafficTreatment - .builder(); - FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); - FlowRule rule; - // corsa uses non-OF-standard way to match on presence of VLAN tags - selector.matchEthType(Ethernet.TYPE_VLAN); - treatment.transition(VLAN_TABLE); - - rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(CONTROLLER_PRIORITY) - .fromApp(appId) - .makePermanent() - .forTable(VLAN_MPLS_TABLE).build(); - - ops = install ? ops.add(rule) : ops.remove(rule); - - flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - log.info("Provisioned vlan/mpls table"); - } - - @Override - public void onError(FlowRuleOperations ops) { - log.info( - "Failed to provision vlan/mpls table"); - } - })); - - } - -} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CpqdOFDPA2Pipeline.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CpqdOFDPA2Pipeline.java deleted file mode 100644 index 02522cf1..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CpqdOFDPA2Pipeline.java +++ /dev/null @@ -1,497 +0,0 @@ -/* - * Copyright 2015 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. - */ -package org.onosproject.driver.pipeline; - -import static org.slf4j.LoggerFactory.getLogger; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Deque; -import java.util.List; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -import org.onlab.packet.Ethernet; -import org.onlab.packet.VlanId; -import org.onosproject.core.ApplicationId; -import org.onosproject.net.Port; -import org.onosproject.net.PortNumber; -import org.onosproject.net.behaviour.NextGroup; -import org.onosproject.net.flow.DefaultFlowRule; -import org.onosproject.net.flow.DefaultTrafficSelector; -import org.onosproject.net.flow.DefaultTrafficTreatment; -import org.onosproject.net.flow.FlowRule; -import org.onosproject.net.flow.FlowRuleOperations; -import org.onosproject.net.flow.FlowRuleOperationsContext; -import org.onosproject.net.flow.TrafficSelector; -import org.onosproject.net.flow.TrafficTreatment; -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.criteria.MplsBosCriterion; -import org.onosproject.net.flow.criteria.MplsCriterion; -import org.onosproject.net.flow.criteria.PortCriterion; -import org.onosproject.net.flow.criteria.VlanIdCriterion; -import org.onosproject.net.flow.instructions.Instruction; -import org.onosproject.net.flowobjective.ForwardingObjective; -import org.onosproject.net.flowobjective.ObjectiveError; -import org.onosproject.net.group.Group; -import org.onosproject.net.group.GroupKey; -import org.slf4j.Logger; - - -/** - * Driver for software switch emulation of the OFDPA 2.0 pipeline. - * The software switch is the CPqD OF 1.3 switch. - */ -public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline { - - private final Logger log = getLogger(getClass()); - - /* - * Cpqd emulation does not require the non-OF standard rules for - * matching untagged packets. - * - * (non-Javadoc) - * @see org.onosproject.driver.pipeline.OFDPA2Pipeline#processVlanIdFilter - */ - - @Override - protected List processVlanIdFilter(PortCriterion portCriterion, - VlanIdCriterion vidCriterion, - VlanId assignedVlan, - ApplicationId applicationId) { - List rules = new ArrayList(); - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); - selector.matchVlanId(vidCriterion.vlanId()); - treatment.transition(TMAC_TABLE); - - VlanId storeVlan = null; - if (vidCriterion.vlanId() == VlanId.NONE) { - // untagged packets are assigned vlans - treatment.pushVlan().setVlanId(assignedVlan); - storeVlan = assignedVlan; - } else { - storeVlan = vidCriterion.vlanId(); - } - - // ofdpa cannot match on ALL portnumber, so we need to use separate - // rules for each port. - List portnums = new ArrayList(); - 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()); - } - - for (PortNumber pnum : portnums) { - // update storage - port2Vlan.put(pnum, storeVlan); - Set vlanPorts = vlan2Port.get(storeVlan); - if (vlanPorts == null) { - vlanPorts = Collections.newSetFromMap( - new ConcurrentHashMap()); - vlanPorts.add(pnum); - vlan2Port.put(storeVlan, vlanPorts); - } else { - vlanPorts.add(pnum); - } - // create rest of flowrule - selector.matchInPort(pnum); - FlowRule rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(DEFAULT_PRIORITY) - .fromApp(applicationId) - .makePermanent() - .forTable(VLAN_TABLE).build(); - rules.add(rule); - } - return rules; - } - - /* - * Cpqd emulation does not handle vlan tags and mpls labels correctly. - * Workaround requires popping off the VLAN tags in the TMAC table. - * - * (non-Javadoc) - * @see org.onosproject.driver.pipeline.OFDPA2Pipeline#processEthDstFilter - */ - @Override - protected List processEthDstFilter(PortCriterion portCriterion, - EthCriterion ethCriterion, - VlanIdCriterion vidCriterion, - VlanId assignedVlan, - ApplicationId applicationId) { - //handling untagged packets via assigned VLAN - if (vidCriterion.vlanId() == VlanId.NONE) { - vidCriterion = (VlanIdCriterion) Criteria.matchVlanId(assignedVlan); - } - // ofdpa cannot match on ALL portnumber, so we need to use separate - // rules for each port. - List portnums = new ArrayList(); - 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()); - } - - List rules = new ArrayList(); - for (PortNumber pnum : portnums) { - // for unicast IP packets - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); - selector.matchInPort(pnum); - selector.matchVlanId(vidCriterion.vlanId()); - selector.matchEthType(Ethernet.TYPE_IPV4); - selector.matchEthDst(ethCriterion.mac()); - /* - * Note: CpqD switches do not handle MPLS-related operation properly - * for a packet with VLAN tag. We pop VLAN here as a workaround. - * Side effect: HostService learns redundant hosts with same MAC but - * different VLAN. No known side effect on the network reachability. - */ - treatment.popVlan(); - treatment.transition(UNICAST_ROUTING_TABLE); - FlowRule rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(DEFAULT_PRIORITY) - .fromApp(applicationId) - .makePermanent() - .forTable(TMAC_TABLE).build(); - rules.add(rule); - //for MPLS packets - selector = DefaultTrafficSelector.builder(); - treatment = DefaultTrafficTreatment.builder(); - selector.matchInPort(pnum); - selector.matchVlanId(vidCriterion.vlanId()); - selector.matchEthType(Ethernet.MPLS_UNICAST); - selector.matchEthDst(ethCriterion.mac()); - // workaround here again - treatment.popVlan(); - treatment.transition(MPLS_TABLE_0); - rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(DEFAULT_PRIORITY) - .fromApp(applicationId) - .makePermanent() - .forTable(TMAC_TABLE).build(); - rules.add(rule); - } - return rules; - } - - /* - * Cpqd emulation allows MPLS ecmp. - * - * (non-Javadoc) - * @see org.onosproject.driver.pipeline.OFDPA2Pipeline#processEthTypeSpecific - */ - @Override - protected Collection processEthTypeSpecific(ForwardingObjective fwd) { - TrafficSelector selector = fwd.selector(); - EthTypeCriterion ethType = - (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE); - if ((ethType == null) || - (ethType.ethType().toShort() != Ethernet.TYPE_IPV4) && - (ethType.ethType().toShort() != Ethernet.MPLS_UNICAST)) { - log.warn("processSpecific: Unsupported forwarding objective criteria" - + "ethType:{} in dev:{}", ethType, deviceId); - fail(fwd, ObjectiveError.UNSUPPORTED); - return Collections.emptySet(); - } - - int forTableId = -1; - TrafficSelector.Builder filteredSelector = DefaultTrafficSelector.builder(); - if (ethType.ethType().toShort() == Ethernet.TYPE_IPV4) { - filteredSelector.matchEthType(Ethernet.TYPE_IPV4) - .matchIPDst(((IPCriterion) - selector.getCriterion(Criterion.Type.IPV4_DST)).ip()); - forTableId = UNICAST_ROUTING_TABLE; - log.debug("processing IPv4 specific forwarding objective {} -> next:{}" - + " in dev:{}", fwd.id(), fwd.nextId(), deviceId); - } else { - filteredSelector - .matchEthType(Ethernet.MPLS_UNICAST) - .matchMplsLabel(((MplsCriterion) - selector.getCriterion(Criterion.Type.MPLS_LABEL)).label()); - MplsBosCriterion bos = (MplsBosCriterion) selector - .getCriterion(Criterion.Type.MPLS_BOS); - if (bos != null) { - filteredSelector.matchMplsBos(bos.mplsBos()); - } - forTableId = MPLS_TABLE_1; - log.debug("processing MPLS specific forwarding objective {} -> next:{}" - + " in dev {}", fwd.id(), fwd.nextId(), deviceId); - } - - TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder(); - if (fwd.treatment() != null) { - for (Instruction i : fwd.treatment().allInstructions()) { - tb.add(i); - } - } - - if (fwd.nextId() != null) { - NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId()); - List> gkeys = appKryo.deserialize(next.data()); - // we only need the top level group's key to point the flow to it - Group group = groupService.getGroup(deviceId, gkeys.get(0).peekFirst()); - if (group == null) { - log.warn("The group left!"); - fail(fwd, ObjectiveError.GROUPMISSING); - return Collections.emptySet(); - } - tb.deferred().group(group.id()); - } - tb.transition(ACL_TABLE); - FlowRule.Builder ruleBuilder = DefaultFlowRule.builder() - .fromApp(fwd.appId()) - .withPriority(fwd.priority()) - .forDevice(deviceId) - .withSelector(filteredSelector.build()) - .withTreatment(tb.build()) - .forTable(forTableId); - - if (fwd.permanent()) { - ruleBuilder.makePermanent(); - } else { - ruleBuilder.makeTemporary(fwd.timeout()); - } - - return Collections.singletonList(ruleBuilder.build()); - } - - @Override - protected void initializePipeline() { - processPortTable(); - // vlan table processing not required, as default is to drop packets - // which can be accomplished without a table-miss-entry. - processTmacTable(); - processIpTable(); - processMplsTable(); - processBridgingTable(); - processAclTable(); - } - - protected void processPortTable() { - FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); - treatment.transition(VLAN_TABLE); - FlowRule tmisse = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(LOWEST_PRIORITY) - .fromApp(driverId) - .makePermanent() - .forTable(PORT_TABLE).build(); - ops = ops.add(tmisse); - - flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - log.info("Initialized port table"); - } - - @Override - public void onError(FlowRuleOperations ops) { - log.info("Failed to initialize port table"); - } - })); - } - - protected void processTmacTable() { - //table miss entry - FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); - selector = DefaultTrafficSelector.builder(); - treatment = DefaultTrafficTreatment.builder(); - treatment.transition(BRIDGING_TABLE); - FlowRule rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(LOWEST_PRIORITY) - .fromApp(driverId) - .makePermanent() - .forTable(TMAC_TABLE).build(); - ops = ops.add(rule); - flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - log.info("Initialized tmac table"); - } - - @Override - public void onError(FlowRuleOperations ops) { - log.info("Failed to initialize tmac table"); - } - })); - } - - protected void processIpTable() { - //table miss entry - FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); - selector = DefaultTrafficSelector.builder(); - treatment = DefaultTrafficTreatment.builder(); - treatment.deferred().setOutput(PortNumber.CONTROLLER); - treatment.transition(ACL_TABLE); - FlowRule rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(LOWEST_PRIORITY) - .fromApp(driverId) - .makePermanent() - .forTable(UNICAST_ROUTING_TABLE).build(); - ops = ops.add(rule); - flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - log.info("Initialized IP table"); - } - - @Override - public void onError(FlowRuleOperations ops) { - log.info("Failed to initialize unicast IP table"); - } - })); - } - - protected void processMplsTable() { - //table miss entry - FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); - selector = DefaultTrafficSelector.builder(); - treatment = DefaultTrafficTreatment.builder(); - treatment.transition(MPLS_TABLE_1); - FlowRule rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(LOWEST_PRIORITY) - .fromApp(driverId) - .makePermanent() - .forTable(MPLS_TABLE_0).build(); - ops = ops.add(rule); - - treatment.transition(ACL_TABLE); - rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(LOWEST_PRIORITY) - .fromApp(driverId) - .makePermanent() - .forTable(MPLS_TABLE_1).build(); - ops = ops.add(rule); - - flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - log.info("Initialized MPLS tables"); - } - - @Override - public void onError(FlowRuleOperations ops) { - log.info("Failed to initialize MPLS tables"); - } - })); - } - - private void processBridgingTable() { - //table miss entry - FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); - selector = DefaultTrafficSelector.builder(); - treatment = DefaultTrafficTreatment.builder(); - treatment.transition(ACL_TABLE); - FlowRule rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(LOWEST_PRIORITY) - .fromApp(driverId) - .makePermanent() - .forTable(BRIDGING_TABLE).build(); - ops = ops.add(rule); - flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - log.info("Initialized Bridging table"); - } - - @Override - public void onError(FlowRuleOperations ops) { - log.info("Failed to initialize Bridging table"); - } - })); - } - - protected void processAclTable() { - //table miss entry - catch all to executed action-set - FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); - selector = DefaultTrafficSelector.builder(); - treatment = DefaultTrafficTreatment.builder(); - FlowRule rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(LOWEST_PRIORITY) - .fromApp(driverId) - .makePermanent() - .forTable(ACL_TABLE).build(); - ops = ops.add(rule); - flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - log.info("Initialized Acl table"); - } - - @Override - public void onError(FlowRuleOperations ops) { - log.info("Failed to initialize Acl table"); - } - })); - } - -} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/DefaultSingleTablePipeline.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/DefaultSingleTablePipeline.java deleted file mode 100644 index d42650f5..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/DefaultSingleTablePipeline.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright 2015 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. - */ -package org.onosproject.driver.pipeline; - -import org.onlab.osgi.ServiceDirectory; -import org.onosproject.net.DeviceId; -import org.onosproject.net.behaviour.Pipeliner; -import org.onosproject.net.behaviour.PipelinerContext; -import org.onosproject.net.driver.AbstractHandlerBehaviour; -import org.onosproject.net.flow.DefaultFlowRule; -import org.onosproject.net.flow.DefaultTrafficTreatment; -import org.onosproject.net.flow.FlowRule; -import org.onosproject.net.flow.FlowRuleOperations; -import org.onosproject.net.flow.FlowRuleOperationsContext; -import org.onosproject.net.flow.FlowRuleService; -import org.onosproject.net.flow.TrafficSelector; -import org.onosproject.net.flow.TrafficTreatment; -import org.onosproject.net.flow.instructions.Instructions; -import org.onosproject.net.flowobjective.FilteringObjective; -import org.onosproject.net.flowobjective.ForwardingObjective; -import org.onosproject.net.flowobjective.NextObjective; -import org.onosproject.net.flowobjective.ObjectiveError; -import org.slf4j.Logger; - -import static org.slf4j.LoggerFactory.getLogger; - -/** - * Simple single table pipeline abstraction. - */ -public class DefaultSingleTablePipeline extends AbstractHandlerBehaviour implements Pipeliner { - - private final Logger log = getLogger(getClass()); - - private ServiceDirectory serviceDirectory; - private FlowRuleService flowRuleService; - private DeviceId deviceId; - - @Override - public void init(DeviceId deviceId, PipelinerContext context) { - this.serviceDirectory = context.directory(); - this.deviceId = deviceId; - - flowRuleService = serviceDirectory.get(FlowRuleService.class); - } - - @Override - public void filter(FilteringObjective filter) {} - - @Override - public void forward(ForwardingObjective fwd) { - FlowRuleOperations.Builder flowBuilder = FlowRuleOperations.builder(); - - if (fwd.flag() != ForwardingObjective.Flag.VERSATILE) { - throw new UnsupportedOperationException( - "Only VERSATILE is supported."); - } - - TrafficSelector selector = fwd.selector(); - TrafficTreatment treatment = fwd.treatment(); - if ((fwd.treatment().deferred().size() == 0) && - (fwd.treatment().immediate().size() == 0) && - (fwd.treatment().tableTransition() == null) && - (!fwd.treatment().clearedDeferred())) { - TrafficTreatment.Builder flowTreatment = DefaultTrafficTreatment.builder(); - flowTreatment.add(Instructions.createDrop()); - treatment = flowTreatment.build(); - } - - FlowRule.Builder ruleBuilder = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector) - .withTreatment(treatment) - .fromApp(fwd.appId()) - .withPriority(fwd.priority()); - - if (fwd.permanent()) { - ruleBuilder.makePermanent(); - } else { - ruleBuilder.makeTemporary(fwd.timeout()); - } - - - switch (fwd.op()) { - - case ADD: - flowBuilder.add(ruleBuilder.build()); - break; - case REMOVE: - flowBuilder.remove(ruleBuilder.build()); - break; - default: - log.warn("Unknown operation {}", fwd.op()); - } - - flowRuleService.apply(flowBuilder.build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - if (fwd.context().isPresent()) { - fwd.context().get().onSuccess(fwd); - } - } - - @Override - public void onError(FlowRuleOperations ops) { - if (fwd.context().isPresent()) { - fwd.context().get().onError(fwd, ObjectiveError.FLOWINSTALLATIONFAILED); - } - } - })); - - } - - @Override - public void next(NextObjective nextObjective) {} - -} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OFDPA2Pipeline.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OFDPA2Pipeline.java deleted file mode 100644 index 5f84b43a..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OFDPA2Pipeline.java +++ /dev/null @@ -1,1792 +0,0 @@ -/* - * Copyright 2015 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. - */ -package org.onosproject.driver.pipeline; - -import static org.onlab.util.Tools.groupedThreads; -import static org.slf4j.LoggerFactory.getLogger; - -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Deque; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.stream.Collectors; - -import org.onlab.osgi.ServiceDirectory; -import org.onlab.packet.Ethernet; -import org.onlab.packet.MacAddress; -import org.onlab.packet.MplsLabel; -import org.onlab.packet.VlanId; -import org.onlab.util.KryoNamespace; -import org.onosproject.core.ApplicationId; -import org.onosproject.core.CoreService; -import org.onosproject.core.DefaultGroupId; -import org.onosproject.net.DeviceId; -import org.onosproject.net.Port; -import org.onosproject.net.PortNumber; -import org.onosproject.net.behaviour.NextGroup; -import org.onosproject.net.behaviour.Pipeliner; -import org.onosproject.net.behaviour.PipelinerContext; -import org.onosproject.net.device.DeviceService; -import org.onosproject.net.driver.AbstractHandlerBehaviour; -import org.onosproject.net.flow.DefaultFlowRule; -import org.onosproject.net.flow.DefaultTrafficSelector; -import org.onosproject.net.flow.DefaultTrafficTreatment; -import org.onosproject.net.flow.FlowRule; -import org.onosproject.net.flow.FlowRuleOperations; -import org.onosproject.net.flow.FlowRuleOperationsContext; -import org.onosproject.net.flow.FlowRuleService; -import org.onosproject.net.flow.TrafficSelector; -import org.onosproject.net.flow.TrafficTreatment; -import org.onosproject.net.flow.criteria.Criteria; -import org.onosproject.net.flow.criteria.Criterion; -import org.onosproject.net.flow.criteria.Criterion.Type; -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.criteria.MplsBosCriterion; -import org.onosproject.net.flow.criteria.MplsCriterion; -import org.onosproject.net.flow.criteria.PortCriterion; -import org.onosproject.net.flow.criteria.VlanIdCriterion; -import org.onosproject.net.flow.instructions.Instruction; -import org.onosproject.net.flow.instructions.Instructions.OutputInstruction; -import org.onosproject.net.flow.instructions.L2ModificationInstruction; -import org.onosproject.net.flow.instructions.L2ModificationInstruction.L2SubType; -import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction; -import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsLabelInstruction; -import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction; -import org.onosproject.net.flowobjective.FilteringObjective; -import org.onosproject.net.flowobjective.FlowObjectiveStore; -import org.onosproject.net.flowobjective.ForwardingObjective; -import org.onosproject.net.flowobjective.NextObjective; -import org.onosproject.net.flowobjective.Objective; -import org.onosproject.net.flowobjective.ObjectiveError; -import org.onosproject.net.group.DefaultGroupBucket; -import org.onosproject.net.group.DefaultGroupDescription; -import org.onosproject.net.group.DefaultGroupKey; -import org.onosproject.net.group.Group; -import org.onosproject.net.group.GroupBucket; -import org.onosproject.net.group.GroupBuckets; -import org.onosproject.net.group.GroupDescription; -import org.onosproject.net.group.GroupEvent; -import org.onosproject.net.group.GroupKey; -import org.onosproject.net.group.GroupListener; -import org.onosproject.net.group.GroupService; -import org.onosproject.net.packet.PacketService; -import org.onosproject.store.serializers.KryoNamespaces; -import org.slf4j.Logger; - -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.RemovalCause; -import com.google.common.cache.RemovalNotification; - -/** - * Driver for Broadcom's OF-DPA v2.0 TTP. - * - */ -public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeliner { - - protected static final int PORT_TABLE = 0; - protected static final int VLAN_TABLE = 10; - protected static final int TMAC_TABLE = 20; - protected static final int UNICAST_ROUTING_TABLE = 30; - protected static final int MULTICAST_ROUTING_TABLE = 40; - protected static final int MPLS_TABLE_0 = 23; - protected static final int MPLS_TABLE_1 = 24; - protected static final int BRIDGING_TABLE = 50; - protected static final int ACL_TABLE = 60; - protected static final int MAC_LEARNING_TABLE = 254; - protected static final long OFPP_MAX = 0xffffff00L; - - private static final int HIGHEST_PRIORITY = 0xffff; - protected static final int DEFAULT_PRIORITY = 0x8000; - protected static final int LOWEST_PRIORITY = 0x0; - - /* - * OFDPA requires group-id's to have a certain form. - * L2 Interface Groups have <4bits-0><12bits-vlanid><16bits-portid> - * L3 Unicast Groups have <4bits-2><28bits-index> - * MPLS Interface Groups have <4bits-9><4bits:0><24bits-index> - * L3 ECMP Groups have <4bits-7><28bits-index> - * L2 Flood Groups have <4bits-4><12bits-vlanid><16bits-index> - * L3 VPN Groups have <4bits-9><4bits-2><24bits-index> - */ - private static final int L2INTERFACEMASK = 0x0; - private static final int L3UNICASTMASK = 0x20000000; - private static final int MPLSINTERFACEMASK = 0x90000000; - private static final int L3ECMPMASK = 0x70000000; - private static final int L2FLOODMASK = 0x40000000; - private static final int L3VPNMASK = 0x92000000; - - private final Logger log = getLogger(getClass()); - private ServiceDirectory serviceDirectory; - protected FlowRuleService flowRuleService; - private CoreService coreService; - protected GroupService groupService; - protected FlowObjectiveStore flowObjectiveStore; - protected DeviceId deviceId; - protected ApplicationId driverId; - protected PacketService packetService; - protected DeviceService deviceService; - protected KryoNamespace appKryo = new KryoNamespace.Builder() - .register(KryoNamespaces.API) - .register(GroupKey.class) - .register(DefaultGroupKey.class) - .register(OfdpaNextGroup.class) - .register(byte[].class) - .register(ArrayDeque.class) - .build(); - - private Cache> pendingNextObjectives; - private ConcurrentHashMap> pendingGroups; - - private ScheduledExecutorService groupChecker = - Executors.newScheduledThreadPool(2, groupedThreads("onos/pipeliner", - "ofdpa2-%d")); - private Set sentIpFilters = Collections.newSetFromMap( - new ConcurrentHashMap()); - - // local stores for port-vlan mapping - Map port2Vlan = new ConcurrentHashMap(); - Map> vlan2Port = new ConcurrentHashMap>(); - - // index number for group creation - AtomicInteger l3vpnindex = new AtomicInteger(0); - - - @Override - public void init(DeviceId deviceId, PipelinerContext context) { - this.serviceDirectory = context.directory(); - this.deviceId = deviceId; - - pendingNextObjectives = CacheBuilder.newBuilder() - .expireAfterWrite(20, TimeUnit.SECONDS) - .removalListener(( - RemovalNotification> notification) -> { - if (notification.getCause() == RemovalCause.EXPIRED) { - notification.getValue().forEach(ofdpaNextGrp -> - fail(ofdpaNextGrp.nextObj, - ObjectiveError.GROUPINSTALLATIONFAILED)); - - } - }).build(); - - groupChecker.scheduleAtFixedRate(new GroupChecker(), 0, 500, TimeUnit.MILLISECONDS); - pendingGroups = new ConcurrentHashMap>(); - - coreService = serviceDirectory.get(CoreService.class); - flowRuleService = serviceDirectory.get(FlowRuleService.class); - groupService = serviceDirectory.get(GroupService.class); - flowObjectiveStore = context.store(); - packetService = serviceDirectory.get(PacketService.class); - deviceService = serviceDirectory.get(DeviceService.class); - groupService.addListener(new InnerGroupListener()); - - driverId = coreService.registerApplication( - "org.onosproject.driver.OFDPA2Pipeline"); - - // OF-DPA does not require initializing the pipeline as it puts default - // rules automatically in the hardware. However emulation of OFDPA in - // software switches does require table-miss-entries. - initializePipeline(); - - } - - protected void initializePipeline() { - - } - - ////////////////////////////////////// - // Flow Objectives - ////////////////////////////////////// - - @Override - public void filter(FilteringObjective filteringObjective) { - if (filteringObjective.type() == FilteringObjective.Type.PERMIT) { - processFilter(filteringObjective, - filteringObjective.op() == Objective.Operation.ADD, - filteringObjective.appId()); - } else { - // Note that packets that don't match the PERMIT filter are - // automatically denied. The DENY filter is used to deny packets - // that are otherwise permitted by the PERMIT filter. - // Use ACL table flow rules here for DENY filtering objectives - log.debug("filter objective other than PERMIT currently not supported"); - fail(filteringObjective, ObjectiveError.UNSUPPORTED); - } - } - - @Override - public void forward(ForwardingObjective fwd) { - Collection rules; - FlowRuleOperations.Builder flowOpsBuilder = FlowRuleOperations.builder(); - - rules = processForward(fwd); - switch (fwd.op()) { - case ADD: - rules.stream() - .filter(rule -> rule != null) - .forEach(flowOpsBuilder::add); - break; - case REMOVE: - rules.stream() - .filter(rule -> rule != null) - .forEach(flowOpsBuilder::remove); - break; - default: - fail(fwd, ObjectiveError.UNKNOWN); - log.warn("Unknown forwarding type {}", fwd.op()); - } - - flowRuleService.apply(flowOpsBuilder.build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - pass(fwd); - } - - @Override - public void onError(FlowRuleOperations ops) { - fail(fwd, ObjectiveError.FLOWINSTALLATIONFAILED); - } - })); - } - - @Override - public void next(NextObjective nextObjective) { - NextGroup nextGroup = flowObjectiveStore.getNextGroup(nextObjective.id()); - switch (nextObjective.op()) { - case ADD: - if (nextGroup != null) { - log.warn("Cannot add next {} that already exists in device {}", - nextObjective.id(), deviceId); - return; - } - log.debug("Processing NextObjective id{} in dev{} - add group", - nextObjective.id(), deviceId); - addGroup(nextObjective); - break; - case ADD_TO_EXISTING: - if (nextGroup != null) { - log.debug("Processing NextObjective id{} in dev{} - add bucket", - nextObjective.id(), deviceId); - addBucketToGroup(nextObjective); - } else { - // it is possible that group-chain has not been fully created yet - waitToAddBucketToGroup(nextObjective); - } - break; - case REMOVE: - if (nextGroup == null) { - log.warn("Cannot remove next {} that does not exist in device {}", - nextObjective.id(), deviceId); - return; - } - log.debug("Processing NextObjective id{} in dev{} - remove group", - nextObjective.id(), deviceId); - removeGroup(nextObjective); - break; - case REMOVE_FROM_EXISTING: - if (nextGroup == null) { - log.warn("Cannot remove from next {} that does not exist in device {}", - nextObjective.id(), deviceId); - return; - } - log.debug("Processing NextObjective id{} in dev{} - remove bucket", - nextObjective.id(), deviceId); - removeBucketFromGroup(nextObjective); - break; - default: - log.warn("Unsupported operation {}", nextObjective.op()); - } - } - - ////////////////////////////////////// - // Flow handling - ////////////////////////////////////// - - /** - * As per OFDPA 2.0 TTP, filtering of VLAN ids, MAC addresses (for routing) - * and IP addresses configured on switch ports happen in different tables. - * Note that IP filtering rules need to be added to the ACL table, as there - * is no mechanism to send to controller via IP table. - * - * @param filt the filtering objective - * @param install indicates whether to add or remove the objective - * @param applicationId the application that sent this objective - */ - private void processFilter(FilteringObjective filt, - boolean install, ApplicationId applicationId) { - // This driver only processes filtering criteria defined with switch - // ports as the key - PortCriterion portCriterion = null; - EthCriterion ethCriterion = null; - VlanIdCriterion vidCriterion = null; - Collection ips = new ArrayList(); - if (!filt.key().equals(Criteria.dummy()) && - filt.key().type() == Criterion.Type.IN_PORT) { - portCriterion = (PortCriterion) filt.key(); - } else { - log.warn("No key defined in filtering objective from app: {}. Not" - + "processing filtering objective", applicationId); - fail(filt, ObjectiveError.UNKNOWN); - return; - } - // convert filtering conditions for switch-intfs into flowrules - FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); - for (Criterion criterion : filt.conditions()) { - if (criterion.type() == Criterion.Type.ETH_DST) { - ethCriterion = (EthCriterion) criterion; - } else if (criterion.type() == Criterion.Type.VLAN_VID) { - vidCriterion = (VlanIdCriterion) criterion; - } else if (criterion.type() == Criterion.Type.IPV4_DST) { - ips.add((IPCriterion) criterion); - } else { - log.error("Unsupported filter {}", criterion); - fail(filt, ObjectiveError.UNSUPPORTED); - return; - } - } - - VlanId assignedVlan = null; - if (vidCriterion != null && vidCriterion.vlanId() == VlanId.NONE) { - // untagged packets are assigned vlans in OF-DPA - if (filt.meta() == null) { - log.error("Missing metadata in filtering objective required " - + "for vlan assignment in dev {}", deviceId); - fail(filt, ObjectiveError.BADPARAMS); - return; - } - for (Instruction i : filt.meta().allInstructions()) { - if (i instanceof ModVlanIdInstruction) { - assignedVlan = ((ModVlanIdInstruction) i).vlanId(); - } - } - if (assignedVlan == null) { - log.error("Driver requires an assigned vlan-id to tag incoming " - + "untagged packets. Not processing vlan filters on " - + "device {}", deviceId); - fail(filt, ObjectiveError.BADPARAMS); - return; - } - } - - if (ethCriterion == null) { - log.debug("filtering objective missing dstMac, cannot program TMAC table"); - } else { - for (FlowRule tmacRule : processEthDstFilter(portCriterion, ethCriterion, - vidCriterion, assignedVlan, - applicationId)) { - log.debug("adding MAC filtering rules in TMAC table: {} for dev: {}", - tmacRule, deviceId); - ops = install ? ops.add(tmacRule) : ops.remove(tmacRule); - } - } - - if (ethCriterion == null || vidCriterion == null) { - log.debug("filtering objective missing dstMac or vlan, cannot program" - + "Vlan Table"); - } else { - for (FlowRule vlanRule : processVlanIdFilter(portCriterion, vidCriterion, - assignedVlan, - applicationId)) { - log.debug("adding VLAN filtering rule in VLAN table: {} for dev: {}", - vlanRule, deviceId); - ops = install ? ops.add(vlanRule) : ops.remove(vlanRule); - } - } - - for (IPCriterion ipaddr : ips) { - // since we ignore port information for IP rules, and the same (gateway) IP - // can be configured on multiple ports, we make sure that we send - // only a single rule to the switch. - if (!sentIpFilters.contains(ipaddr)) { - sentIpFilters.add(ipaddr); - log.debug("adding IP filtering rules in ACL table {} for dev: {}", - ipaddr, deviceId); - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); - selector.matchEthType(Ethernet.TYPE_IPV4); - selector.matchIPDst(ipaddr.ip()); - treatment.setOutput(PortNumber.CONTROLLER); - FlowRule rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(HIGHEST_PRIORITY) - .fromApp(applicationId) - .makePermanent() - .forTable(ACL_TABLE).build(); - ops = install ? ops.add(rule) : ops.remove(rule); - } - } - - // apply filtering flow rules - flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - log.info("Applied {} filtering rules in device {}", - ops.stages().get(0).size(), deviceId); - pass(filt); - } - - @Override - public void onError(FlowRuleOperations ops) { - log.info("Failed to apply all filtering rules in dev {}", deviceId); - fail(filt, ObjectiveError.FLOWINSTALLATIONFAILED); - } - })); - - } - - /** - * Allows untagged packets into pipeline by assigning a vlan id. - * Vlan assignment is done by the application. - * Allows tagged packets into pipeline as per configured port-vlan info. - * - * @param portCriterion port on device for which this filter is programmed - * @param vidCriterion vlan assigned to port, or NONE for untagged - * @param assignedVlan assigned vlan-id for untagged packets - * @param applicationId for application programming this filter - * @return list of FlowRule for port-vlan filters - */ - protected List processVlanIdFilter(PortCriterion portCriterion, - VlanIdCriterion vidCriterion, - VlanId assignedVlan, - ApplicationId applicationId) { - List rules = new ArrayList(); - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); - selector.matchVlanId(vidCriterion.vlanId()); - treatment.transition(TMAC_TABLE); - - VlanId storeVlan = null; - if (vidCriterion.vlanId() == VlanId.NONE) { - // untagged packets are assigned vlans - treatment.pushVlan().setVlanId(assignedVlan); - // XXX ofdpa will require an additional vlan match on the assigned vlan - // and it may not require the push. This is not in compliance with OF - // standard. Waiting on what the exact flows are going to look like. - storeVlan = assignedVlan; - } else { - storeVlan = vidCriterion.vlanId(); - } - - // ofdpa cannot match on ALL portnumber, so we need to use separate - // rules for each port. - List portnums = new ArrayList(); - 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()); - } - - for (PortNumber pnum : portnums) { - // update storage - port2Vlan.put(pnum, storeVlan); - Set vlanPorts = vlan2Port.get(storeVlan); - if (vlanPorts == null) { - vlanPorts = Collections.newSetFromMap( - new ConcurrentHashMap()); - vlanPorts.add(pnum); - vlan2Port.put(storeVlan, vlanPorts); - } else { - vlanPorts.add(pnum); - } - // create rest of flowrule - selector.matchInPort(pnum); - FlowRule rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(DEFAULT_PRIORITY) - .fromApp(applicationId) - .makePermanent() - .forTable(VLAN_TABLE).build(); - rules.add(rule); - } - return rules; - } - - /** - * Allows routed packets with correct destination MAC to be directed - * to unicast-IP routing table or MPLS forwarding table. - * - * @param portCriterion port on device for which this filter is programmed - * @param ethCriterion dstMac of device for which is filter is programmed - * @param vidCriterion vlan assigned to port, or NONE for untagged - * @param assignedVlan assigned vlan-id for untagged packets - * @param applicationId for application programming this filter - * @return list of FlowRule for port-vlan filters - - */ - protected List processEthDstFilter(PortCriterion portCriterion, - EthCriterion ethCriterion, - VlanIdCriterion vidCriterion, - VlanId assignedVlan, - ApplicationId applicationId) { - //handling untagged packets via assigned VLAN - if (vidCriterion.vlanId() == VlanId.NONE) { - vidCriterion = (VlanIdCriterion) Criteria.matchVlanId(assignedVlan); - } - // ofdpa cannot match on ALL portnumber, so we need to use separate - // rules for each port. - List portnums = new ArrayList(); - 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()); - } - - List rules = new ArrayList(); - for (PortNumber pnum : portnums) { - // for unicast IP packets - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); - selector.matchInPort(pnum); - selector.matchVlanId(vidCriterion.vlanId()); - selector.matchEthType(Ethernet.TYPE_IPV4); - selector.matchEthDst(ethCriterion.mac()); - treatment.transition(UNICAST_ROUTING_TABLE); - FlowRule rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(DEFAULT_PRIORITY) - .fromApp(applicationId) - .makePermanent() - .forTable(TMAC_TABLE).build(); - rules.add(rule); - //for MPLS packets - selector = DefaultTrafficSelector.builder(); - treatment = DefaultTrafficTreatment.builder(); - selector.matchInPort(pnum); - selector.matchVlanId(vidCriterion.vlanId()); - selector.matchEthType(Ethernet.MPLS_UNICAST); - selector.matchEthDst(ethCriterion.mac()); - treatment.transition(MPLS_TABLE_0); - rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(DEFAULT_PRIORITY) - .fromApp(applicationId) - .makePermanent() - .forTable(TMAC_TABLE).build(); - rules.add(rule); - } - return rules; - } - - private Collection processForward(ForwardingObjective fwd) { - switch (fwd.flag()) { - case SPECIFIC: - return processSpecific(fwd); - case VERSATILE: - return processVersatile(fwd); - default: - fail(fwd, ObjectiveError.UNKNOWN); - log.warn("Unknown forwarding flag {}", fwd.flag()); - } - return Collections.emptySet(); - } - - /** - * In the OF-DPA 2.0 pipeline, versatile forwarding objectives go to the - * ACL table. - * @param fwd the forwarding objective of type 'versatile' - * @return a collection of flow rules to be sent to the switch. An empty - * collection may be returned if there is a problem in processing - * the flow rule - */ - private Collection processVersatile(ForwardingObjective fwd) { - log.info("Processing versatile forwarding objective"); - TrafficSelector selector = fwd.selector(); - - EthTypeCriterion ethType = - (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE); - if (ethType == null) { - log.error("Versatile forwarding objective must include ethType"); - fail(fwd, ObjectiveError.BADPARAMS); - return Collections.emptySet(); - } - if (fwd.nextId() == null && fwd.treatment() == null) { - log.error("Forwarding objective {} from {} must contain " - + "nextId or Treatment", fwd.selector(), fwd.appId()); - return Collections.emptySet(); - } - // XXX driver does not currently do type checking as per Tables 65-67 in - // OFDPA 2.0 spec. The only allowed treatment is a punt to the controller. - if (fwd.treatment() != null && - fwd.treatment().allInstructions().size() == 1 && - fwd.treatment().allInstructions().get(0).type() == Instruction.Type.OUTPUT) { - OutputInstruction o = (OutputInstruction) fwd.treatment().allInstructions().get(0); - if (o.port() == PortNumber.CONTROLLER) { - FlowRule.Builder ruleBuilder = DefaultFlowRule.builder() - .fromApp(fwd.appId()) - .withPriority(fwd.priority()) - .forDevice(deviceId) - .withSelector(fwd.selector()) - .withTreatment(fwd.treatment()) - .makePermanent() - .forTable(ACL_TABLE); - return Collections.singletonList(ruleBuilder.build()); - } else { - log.warn("Only allowed treatments in versatile forwarding " - + "objectives are punts to the controller"); - return Collections.emptySet(); - } - } - - if (fwd.nextId() != null) { - // XXX overide case - log.warn("versatile objective --> next Id not yet implemeted"); - } - return Collections.emptySet(); - } - - /** - * In the OF-DPA 2.0 pipeline, specific forwarding refers to the IP table - * (unicast or multicast) or the L2 table (mac + vlan) or the MPLS table. - * - * @param fwd the forwarding objective of type 'specific' - * @return a collection of flow rules. Typically there will be only one - * for this type of forwarding objective. An empty set may be - * returned if there is an issue in processing the objective. - */ - protected Collection processSpecific(ForwardingObjective fwd) { - log.trace("Processing specific fwd objective:{} in dev:{} with next:{}", - fwd.id(), deviceId, fwd.nextId()); - boolean isEthTypeObj = isSupportedEthTypeObjective(fwd); - boolean isEthDstObj = isSupportedEthDstObjective(fwd); - - if (isEthTypeObj) { - return processEthTypeSpecific(fwd); - } else if (isEthDstObj) { - return processEthDstSpecific(fwd); - } else { - log.warn("processSpecific: Unsupported forwarding objective " - + "criteria fwd:{} in dev:{}", fwd.nextId(), deviceId); - fail(fwd, ObjectiveError.UNSUPPORTED); - return Collections.emptySet(); - } - } - - private boolean isSupportedEthTypeObjective(ForwardingObjective fwd) { - TrafficSelector selector = fwd.selector(); - EthTypeCriterion ethType = (EthTypeCriterion) selector - .getCriterion(Criterion.Type.ETH_TYPE); - if ((ethType == null) || - ((ethType.ethType().toShort() != Ethernet.TYPE_IPV4) && - (ethType.ethType().toShort() != Ethernet.MPLS_UNICAST))) { - return false; - } - return true; - } - - private boolean isSupportedEthDstObjective(ForwardingObjective fwd) { - TrafficSelector selector = fwd.selector(); - EthCriterion ethDst = (EthCriterion) selector - .getCriterion(Criterion.Type.ETH_DST); - VlanIdCriterion vlanId = (VlanIdCriterion) selector - .getCriterion(Criterion.Type.VLAN_VID); - if (ethDst == null && vlanId == null) { - return false; - } - return true; - } - - /** - * Handles forwarding rules to the IP and MPLS tables. - * - * @param fwd the forwarding objective - * @return A collection of flow rules, or an empty set - */ - protected Collection processEthTypeSpecific(ForwardingObjective fwd) { - TrafficSelector selector = fwd.selector(); - EthTypeCriterion ethType = - (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE); - - int forTableId = -1; - TrafficSelector.Builder filteredSelector = DefaultTrafficSelector.builder(); - if (ethType.ethType().toShort() == Ethernet.TYPE_IPV4) { - filteredSelector.matchEthType(Ethernet.TYPE_IPV4) - .matchIPDst(((IPCriterion) - selector.getCriterion(Criterion.Type.IPV4_DST)).ip()); - forTableId = UNICAST_ROUTING_TABLE; - log.debug("processing IPv4 specific forwarding objective {} -> next:{}" - + " in dev:{}", fwd.id(), fwd.nextId(), deviceId); - } else { - filteredSelector - .matchEthType(Ethernet.MPLS_UNICAST) - .matchMplsLabel(((MplsCriterion) - selector.getCriterion(Criterion.Type.MPLS_LABEL)).label()); - MplsBosCriterion bos = (MplsBosCriterion) selector - .getCriterion(Criterion.Type.MPLS_BOS); - if (bos != null) { - filteredSelector.matchMplsBos(bos.mplsBos()); - } - forTableId = MPLS_TABLE_1; - log.debug("processing MPLS specific forwarding objective {} -> next:{}" - + " in dev {}", fwd.id(), fwd.nextId(), deviceId); - } - - TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder(); - boolean popMpls = false; - if (fwd.treatment() != null) { - for (Instruction i : fwd.treatment().allInstructions()) { - tb.add(i); - if (i instanceof L2ModificationInstruction && - ((L2ModificationInstruction) i).subtype() == L2SubType.MPLS_POP) { - popMpls = true; - } - } - } - - if (fwd.nextId() != null) { - if (forTableId == MPLS_TABLE_1 && !popMpls) { - log.warn("SR CONTINUE case cannot be handled as MPLS ECMP " - + "is not implemented in OF-DPA yet. Aborting this flow " - + "in this device {}", deviceId); - // XXX We could convert to forwarding to a single-port, via a - // MPLS interface, or a MPLS SWAP (with-same) but that would - // have to be handled in the next-objective. Also the pop-mpls - // logic used here won't work in non-BoS case. - fail(fwd, ObjectiveError.FLOWINSTALLATIONFAILED); - return Collections.emptySet(); - } - - NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId()); - List> gkeys = appKryo.deserialize(next.data()); - // we only need the top level group's key to point the flow to it - Group group = groupService.getGroup(deviceId, gkeys.get(0).peekFirst()); - if (group == null) { - log.warn("Group with key:{} for next-id:{} not found in dev:{}", - gkeys.get(0).peekFirst(), fwd.nextId(), deviceId); - fail(fwd, ObjectiveError.GROUPMISSING); - return Collections.emptySet(); - } - tb.deferred().group(group.id()); - } - tb.transition(ACL_TABLE); - FlowRule.Builder ruleBuilder = DefaultFlowRule.builder() - .fromApp(fwd.appId()) - .withPriority(fwd.priority()) - .forDevice(deviceId) - .withSelector(filteredSelector.build()) - .withTreatment(tb.build()) - .forTable(forTableId); - - if (fwd.permanent()) { - ruleBuilder.makePermanent(); - } else { - ruleBuilder.makeTemporary(fwd.timeout()); - } - - return Collections.singletonList(ruleBuilder.build()); - } - - /** - * Handles forwarding rules to the L2 bridging table. Flow actions are not - * allowed in the bridging table - instead we use L2 Interface group or - * L2 flood group - * - * @param fwd the forwarding objective - * @return A collection of flow rules, or an empty set - */ - protected Collection processEthDstSpecific(ForwardingObjective fwd) { - List rules = new ArrayList<>(); - - // Build filtered selector - TrafficSelector selector = fwd.selector(); - EthCriterion ethCriterion = (EthCriterion) selector - .getCriterion(Criterion.Type.ETH_DST); - VlanIdCriterion vlanIdCriterion = (VlanIdCriterion) selector - .getCriterion(Criterion.Type.VLAN_VID); - - if (vlanIdCriterion == null) { - log.warn("Forwarding objective for bridging requires vlan. Not " - + "installing fwd:{} in dev:{}", fwd.id(), deviceId); - fail(fwd, ObjectiveError.BADPARAMS); - return Collections.emptySet(); - } - - TrafficSelector.Builder filteredSelectorBuilder = - DefaultTrafficSelector.builder(); - // Do not match MacAddress for subnet broadcast entry - if (!ethCriterion.mac().equals(MacAddress.NONE)) { - filteredSelectorBuilder.matchEthDst(ethCriterion.mac()); - log.debug("processing L2 forwarding objective:{} -> next:{} in dev:{}", - fwd.id(), fwd.nextId(), deviceId); - } else { - log.debug("processing L2 Broadcast forwarding objective:{} -> next:{} " - + "in dev:{} for vlan:{}", - fwd.id(), fwd.nextId(), deviceId, vlanIdCriterion.vlanId()); - } - filteredSelectorBuilder.matchVlanId(vlanIdCriterion.vlanId()); - TrafficSelector filteredSelector = filteredSelectorBuilder.build(); - - if (fwd.treatment() != null) { - log.warn("Ignoring traffic treatment in fwd rule {} meant for L2 table" - + "for dev:{}. Expecting only nextId", fwd.id(), deviceId); - } - - TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder(); - if (fwd.nextId() != null) { - NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId()); - if (next != null) { - List> gkeys = appKryo.deserialize(next.data()); - // we only need the top level group's key to point the flow to it - Group group = groupService.getGroup(deviceId, gkeys.get(0).peekFirst()); - if (group != null) { - treatmentBuilder.deferred().group(group.id()); - } else { - log.warn("Group with key:{} for next-id:{} not found in dev:{}", - gkeys.get(0).peekFirst(), fwd.nextId(), deviceId); - fail(fwd, ObjectiveError.GROUPMISSING); - return Collections.emptySet(); - } - } - } - treatmentBuilder.immediate().transition(ACL_TABLE); - TrafficTreatment filteredTreatment = treatmentBuilder.build(); - - // Build bridging table entries - FlowRule.Builder flowRuleBuilder = DefaultFlowRule.builder(); - flowRuleBuilder.fromApp(fwd.appId()) - .withPriority(fwd.priority()) - .forDevice(deviceId) - .withSelector(filteredSelector) - .withTreatment(filteredTreatment) - .forTable(BRIDGING_TABLE); - if (fwd.permanent()) { - flowRuleBuilder.makePermanent(); - } else { - flowRuleBuilder.makeTemporary(fwd.timeout()); - } - rules.add(flowRuleBuilder.build()); - return rules; - } - - private void pass(Objective obj) { - if (obj.context().isPresent()) { - obj.context().get().onSuccess(obj); - } - } - - protected void fail(Objective obj, ObjectiveError error) { - if (obj.context().isPresent()) { - obj.context().get().onError(obj, error); - } - } - - ////////////////////////////////////// - // Group handling - ////////////////////////////////////// - - private void addGroup(NextObjective nextObjective) { - switch (nextObjective.type()) { - case SIMPLE: - Collection treatments = nextObjective.next(); - if (treatments.size() != 1) { - log.error("Next Objectives of type Simple should only have a " - + "single Traffic Treatment. Next Objective Id:{}", - nextObjective.id()); - fail(nextObjective, ObjectiveError.BADPARAMS); - return; - } - processSimpleNextObjective(nextObjective); - break; - case BROADCAST: - processBroadcastNextObjective(nextObjective); - break; - case HASHED: - processHashedNextObjective(nextObjective); - break; - case FAILOVER: - fail(nextObjective, ObjectiveError.UNSUPPORTED); - log.warn("Unsupported next objective type {}", nextObjective.type()); - break; - default: - fail(nextObjective, ObjectiveError.UNKNOWN); - log.warn("Unknown next objective type {}", nextObjective.type()); - } - } - - /** - * As per the OFDPA 2.0 TTP, packets are sent out of ports by using - * a chain of groups. The simple Next Objective passed - * in by the application has to be broken up into a group chain - * comprising of an L3 Unicast Group that points to an L2 Interface - * Group which in-turn points to an output port. In some cases, the simple - * next Objective can just be an L2 interface without the need for chaining. - * - * @param nextObj the nextObjective of type SIMPLE - */ - private void processSimpleNextObjective(NextObjective nextObj) { - TrafficTreatment treatment = nextObj.next().iterator().next(); - // determine if plain L2 or L3->L2 - boolean plainL2 = true; - for (Instruction ins : treatment.allInstructions()) { - if (ins.type() == Instruction.Type.L2MODIFICATION) { - L2ModificationInstruction l2ins = (L2ModificationInstruction) ins; - if (l2ins.subtype() == L2SubType.ETH_DST || - l2ins.subtype() == L2SubType.ETH_SRC) { - plainL2 = false; - break; - } - } - } - - if (plainL2) { - createL2InterfaceGroup(nextObj); - return; - } - - // break up simple next objective to GroupChain objects - GroupInfo groupInfo = createL2L3Chain(treatment, nextObj.id(), - nextObj.appId(), false, - nextObj.meta()); - if (groupInfo == null) { - log.error("Could not process nextObj={} in dev:{}", nextObj.id(), deviceId); - return; - } - // create object for local and distributed storage - Deque gkeyChain = new ArrayDeque<>(); - gkeyChain.addFirst(groupInfo.innerGrpDesc.appCookie()); - gkeyChain.addFirst(groupInfo.outerGrpDesc.appCookie()); - OfdpaNextGroup ofdpaGrp = new OfdpaNextGroup( - Collections.singletonList(gkeyChain), - nextObj); - - // store l3groupkey with the ofdpaNextGroup for the nextObjective that depends on it - updatePendingNextObjective(groupInfo.outerGrpDesc.appCookie(), ofdpaGrp); - - // now we are ready to send the l2 groupDescription (inner), as all the stores - // that will get async replies have been updated. By waiting to update - // the stores, we prevent nasty race conditions. - groupService.addGroup(groupInfo.innerGrpDesc); - } - - private void updatePendingNextObjective(GroupKey key, OfdpaNextGroup value) { - List nextList = new CopyOnWriteArrayList(); - nextList.add(value); - List ret = pendingNextObjectives.asMap() - .putIfAbsent(key, nextList); - if (ret != null) { - ret.add(value); - } - } - - /** - * Creates a simple L2 Interface Group. - * - * @param nextObj the next Objective - */ - private void createL2InterfaceGroup(NextObjective nextObj) { - // only allowed actions are vlan pop and outport - TrafficTreatment.Builder ttb = DefaultTrafficTreatment.builder(); - PortNumber portNum = null; - for (Instruction ins : nextObj.next().iterator().next().allInstructions()) { - if (ins.type() == Instruction.Type.L2MODIFICATION) { - L2ModificationInstruction l2ins = (L2ModificationInstruction) ins; - switch (l2ins.subtype()) { - case VLAN_POP: - ttb.add(l2ins); - break; - default: - break; - } - } else if (ins.type() == Instruction.Type.OUTPUT) { - portNum = ((OutputInstruction) ins).port(); - ttb.add(ins); - } else { - log.warn("Driver does not handle this type of TrafficTreatment" - + " instruction in simple nextObjectives: {}", ins.type()); - } - } - //use the vlanid associated with the port - VlanId vlanid = port2Vlan.get(portNum); - - if (vlanid == null && nextObj.meta() != null) { - // use metadata vlan info if available - Criterion vidCriterion = nextObj.meta().getCriterion(Type.VLAN_VID); - if (vidCriterion != null) { - vlanid = ((VlanIdCriterion) vidCriterion).vlanId(); - } - } - - if (vlanid == null) { - log.error("Driver cannot process an L2/L3 group chain without " - + "egress vlan information for dev: {} port:{}", - deviceId, portNum); - return; - } - - // assemble information for ofdpa l2interface group - Integer l2groupId = L2INTERFACEMASK | (vlanid.toShort() << 16) | (int) portNum.toLong(); - // a globally unique groupkey that is different for ports in the same devices - // but different for the same portnumber on different devices. Also different - // for the various group-types created out of the same next objective. - int l2gk = 0x0ffffff & (deviceId.hashCode() << 8 | (int) portNum.toLong()); - final GroupKey l2groupkey = new DefaultGroupKey(appKryo.serialize(l2gk)); - - // create group description for the l2interfacegroup - GroupBucket l2interfaceGroupBucket = - DefaultGroupBucket.createIndirectGroupBucket(ttb.build()); - GroupDescription l2groupDescription = - new DefaultGroupDescription( - deviceId, - GroupDescription.Type.INDIRECT, - new GroupBuckets(Collections.singletonList( - l2interfaceGroupBucket)), - l2groupkey, - l2groupId, - nextObj.appId()); - log.debug("Trying L2Interface: device:{} gid:{} gkey:{} nextId:{}", - deviceId, Integer.toHexString(l2groupId), - l2groupkey, nextObj.id()); - - // create object for local and distributed storage - Deque singleKey = new ArrayDeque<>(); - singleKey.addFirst(l2groupkey); - OfdpaNextGroup ofdpaGrp = new OfdpaNextGroup( - Collections.singletonList(singleKey), - nextObj); - - // store l2groupkey for the nextObjective that depends on it - updatePendingNextObjective(l2groupkey, ofdpaGrp); - // send the group description to the group service - groupService.addGroup(l2groupDescription); - } - - /** - * Creates one of two possible group-chains from the treatment - * passed in. Depending on the MPLS boolean, this method either creates - * an L3Unicast Group --> L2Interface Group, if mpls is false; - * or MPLSInterface Group --> L2Interface Group, if mpls is true; - * The returned 'inner' group description is always the L2 Interface group. - * - * @param treatment that needs to be broken up to create the group chain - * @param nextId of the next objective that needs this group chain - * @param appId of the application that sent this next objective - * @param mpls determines if L3Unicast or MPLSInterface group is created - * @param meta metadata passed in by the application as part of the nextObjective - * @return GroupInfo containing the GroupDescription of the - * L2Interface group(inner) and the GroupDescription of the (outer) - * L3Unicast/MPLSInterface group. May return null if there is an - * error in processing the chain - */ - private GroupInfo createL2L3Chain(TrafficTreatment treatment, int nextId, - ApplicationId appId, boolean mpls, - TrafficSelector meta) { - // for the l2interface group, get vlan and port info - // for the outer group, get the src/dst mac, and vlan info - TrafficTreatment.Builder outerTtb = DefaultTrafficTreatment.builder(); - TrafficTreatment.Builder innerTtb = DefaultTrafficTreatment.builder(); - VlanId vlanid = null; - long portNum = 0; - boolean setVlan = false, popVlan = false; - for (Instruction ins : treatment.allInstructions()) { - if (ins.type() == Instruction.Type.L2MODIFICATION) { - L2ModificationInstruction l2ins = (L2ModificationInstruction) ins; - switch (l2ins.subtype()) { - case ETH_DST: - outerTtb.setEthDst(((ModEtherInstruction) l2ins).mac()); - break; - case ETH_SRC: - outerTtb.setEthSrc(((ModEtherInstruction) l2ins).mac()); - break; - case VLAN_ID: - vlanid = ((ModVlanIdInstruction) l2ins).vlanId(); - outerTtb.setVlanId(vlanid); - setVlan = true; - break; - case VLAN_POP: - innerTtb.popVlan(); - popVlan = true; - break; - case DEC_MPLS_TTL: - case MPLS_LABEL: - case MPLS_POP: - case MPLS_PUSH: - case VLAN_PCP: - case VLAN_PUSH: - default: - break; - } - } else if (ins.type() == Instruction.Type.OUTPUT) { - portNum = ((OutputInstruction) ins).port().toLong(); - innerTtb.add(ins); - } else { - log.warn("Driver does not handle this type of TrafficTreatment" - + " instruction in nextObjectives: {}", ins.type()); - } - } - - if (vlanid == null) { - //use the vlanid associated with the port - vlanid = port2Vlan.get(PortNumber.portNumber(portNum)); - } - - if (vlanid == null && meta != null) { - // use metadata if available - Criterion vidCriterion = meta.getCriterion(Type.VLAN_VID); - if (vidCriterion != null) { - vlanid = ((VlanIdCriterion) vidCriterion).vlanId(); - } - } - - if (vlanid == null) { - log.error("Driver cannot process an L2/L3 group chain without " - + "egress vlan information for dev: {} port:{}", - deviceId, portNum); - return null; - } - - if (!setVlan && !popVlan) { - // untagged outgoing port - TrafficTreatment.Builder temp = DefaultTrafficTreatment.builder(); - temp.popVlan(); - innerTtb.build().allInstructions().forEach(i -> temp.add(i)); - innerTtb = temp; - } - - // assemble information for ofdpa l2interface group - Integer l2groupId = L2INTERFACEMASK | (vlanid.toShort() << 16) | (int) portNum; - // a globally unique groupkey that is different for ports in the same devices - // but different for the same portnumber on different devices. Also different - // for the various group-types created out of the same next objective. - int l2gk = 0x0ffffff & (deviceId.hashCode() << 8 | (int) portNum); - final GroupKey l2groupkey = new DefaultGroupKey(appKryo.serialize(l2gk)); - - // assemble information for outer group - GroupDescription outerGrpDesc = null; - if (mpls) { - // outer group is MPLSInteface - Integer mplsgroupId = MPLSINTERFACEMASK | (int) portNum; - // using mplsinterfacemask in groupkey to differentiate from l2interface - int mplsgk = MPLSINTERFACEMASK | (0x0ffffff & (deviceId.hashCode() << 8 | (int) portNum)); - final GroupKey mplsgroupkey = new DefaultGroupKey(appKryo.serialize(mplsgk)); - outerTtb.group(new DefaultGroupId(l2groupId)); - // create the mpls-interface group description to wait for the - // l2 interface group to be processed - GroupBucket mplsinterfaceGroupBucket = - DefaultGroupBucket.createIndirectGroupBucket(outerTtb.build()); - outerGrpDesc = new DefaultGroupDescription( - deviceId, - GroupDescription.Type.INDIRECT, - new GroupBuckets(Collections.singletonList( - mplsinterfaceGroupBucket)), - mplsgroupkey, - mplsgroupId, - appId); - log.debug("Trying MPLS-Interface: device:{} gid:{} gkey:{} nextid:{}", - deviceId, Integer.toHexString(mplsgroupId), - mplsgroupkey, nextId); - } else { - // outer group is L3Unicast - Integer l3groupId = L3UNICASTMASK | (int) portNum; - int l3gk = L3UNICASTMASK | (0x0ffffff & (deviceId.hashCode() << 8 | (int) portNum)); - final GroupKey l3groupkey = new DefaultGroupKey(appKryo.serialize(l3gk)); - outerTtb.group(new DefaultGroupId(l2groupId)); - // create the l3unicast group description to wait for the - // l2 interface group to be processed - GroupBucket l3unicastGroupBucket = - DefaultGroupBucket.createIndirectGroupBucket(outerTtb.build()); - outerGrpDesc = new DefaultGroupDescription( - deviceId, - GroupDescription.Type.INDIRECT, - new GroupBuckets(Collections.singletonList( - l3unicastGroupBucket)), - l3groupkey, - l3groupId, - appId); - log.debug("Trying L3Unicast: device:{} gid:{} gkey:{} nextid:{}", - deviceId, Integer.toHexString(l3groupId), - l3groupkey, nextId); - } - - // store l2groupkey with the groupChainElem for the outer-group that depends on it - GroupChainElem gce = new GroupChainElem(outerGrpDesc, 1); - Set gceSet = Collections.newSetFromMap( - new ConcurrentHashMap()); - gceSet.add(gce); - Set retval = pendingGroups.putIfAbsent(l2groupkey, gceSet); - if (retval != null) { - retval.add(gce); - } - - // create group description for the inner l2interfacegroup - GroupBucket l2interfaceGroupBucket = - DefaultGroupBucket.createIndirectGroupBucket(innerTtb.build()); - GroupDescription l2groupDescription = - new DefaultGroupDescription( - deviceId, - GroupDescription.Type.INDIRECT, - new GroupBuckets(Collections.singletonList( - l2interfaceGroupBucket)), - l2groupkey, - l2groupId, - appId); - log.debug("Trying L2Interface: device:{} gid:{} gkey:{} nextId:{}", - deviceId, Integer.toHexString(l2groupId), - l2groupkey, nextId); - return new GroupInfo(l2groupDescription, outerGrpDesc); - - } - - /** - * As per the OFDPA 2.0 TTP, packets are sent out of ports by using - * a chain of groups. The broadcast Next Objective passed in by the application - * has to be broken up into a group chain comprising of an - * L2 Flood group whose buckets point to L2 Interface groups. - * - * @param nextObj the nextObjective of type BROADCAST - */ - private void processBroadcastNextObjective(NextObjective nextObj) { - // break up broadcast next objective to multiple groups - Collection buckets = nextObj.next(); - - // each treatment is converted to an L2 interface group - VlanId vlanid = null; - List l2interfaceGroupDescs = new ArrayList<>(); - List> allGroupKeys = new ArrayList<>(); - for (TrafficTreatment treatment : buckets) { - TrafficTreatment.Builder newTreatment = DefaultTrafficTreatment.builder(); - PortNumber portNum = null; - // ensure that the only allowed treatments are pop-vlan and output - for (Instruction ins : treatment.allInstructions()) { - if (ins.type() == Instruction.Type.L2MODIFICATION) { - L2ModificationInstruction l2ins = (L2ModificationInstruction) ins; - switch (l2ins.subtype()) { - case VLAN_POP: - newTreatment.add(l2ins); - break; - default: - log.debug("action {} not permitted for broadcast nextObj", - l2ins.subtype()); - break; - } - } else if (ins.type() == Instruction.Type.OUTPUT) { - portNum = ((OutputInstruction) ins).port(); - newTreatment.add(ins); - } else { - log.debug("TrafficTreatment of type {} not permitted in " - + " broadcast nextObjective", ins.type()); - } - } - - // also ensure that all ports are in the same vlan - // XXX maybe HA issue here? - VlanId thisvlanid = port2Vlan.get(portNum); - if (vlanid == null) { - vlanid = thisvlanid; - } else { - if (!vlanid.equals(thisvlanid)) { - log.error("Driver requires all ports in a broadcast nextObj " - + "to be in the same vlan. Different vlans found " - + "{} and {}. Aborting group creation", vlanid, thisvlanid); - return; - } - } - - // assemble info for l2 interface group - int l2gk = 0x0ffffff & (deviceId.hashCode() << 8 | (int) portNum.toLong()); - final GroupKey l2groupkey = new DefaultGroupKey(appKryo.serialize(l2gk)); - Integer l2groupId = L2INTERFACEMASK | (vlanid.toShort() << 16) | - (int) portNum.toLong(); - GroupBucket l2interfaceGroupBucket = - DefaultGroupBucket.createIndirectGroupBucket(newTreatment.build()); - GroupDescription l2interfaceGroupDescription = - new DefaultGroupDescription( - deviceId, - GroupDescription.Type.INDIRECT, - new GroupBuckets(Collections.singletonList( - l2interfaceGroupBucket)), - l2groupkey, - l2groupId, - nextObj.appId()); - log.debug("Trying L2-Interface: device:{} gid:{} gkey:{} nextid:{}", - deviceId, Integer.toHexString(l2groupId), - l2groupkey, nextObj.id()); - - Deque gkeyChain = new ArrayDeque<>(); - gkeyChain.addFirst(l2groupkey); - - // store the info needed to create this group - l2interfaceGroupDescs.add(l2interfaceGroupDescription); - allGroupKeys.add(gkeyChain); - } - - // assemble info for l2 flood group - Integer l2floodgroupId = L2FLOODMASK | (vlanid.toShort() << 16) | nextObj.id(); - int l2floodgk = L2FLOODMASK | nextObj.id() << 12; - final GroupKey l2floodgroupkey = new DefaultGroupKey(appKryo.serialize(l2floodgk)); - // collection of group buckets pointing to all the l2 interface groups - List l2floodBuckets = new ArrayList<>(); - for (GroupDescription l2intGrpDesc : l2interfaceGroupDescs) { - TrafficTreatment.Builder ttb = DefaultTrafficTreatment.builder(); - ttb.group(new DefaultGroupId(l2intGrpDesc.givenGroupId())); - GroupBucket abucket = DefaultGroupBucket.createAllGroupBucket(ttb.build()); - l2floodBuckets.add(abucket); - } - // create the l2flood group-description to wait for all the - // l2interface groups to be processed - GroupDescription l2floodGroupDescription = - new DefaultGroupDescription( - deviceId, - GroupDescription.Type.ALL, - new GroupBuckets(l2floodBuckets), - l2floodgroupkey, - l2floodgroupId, - nextObj.appId()); - GroupChainElem gce = new GroupChainElem(l2floodGroupDescription, - l2interfaceGroupDescs.size()); - log.debug("Trying L2-Flood: device:{} gid:{} gkey:{} nextid:{}", - deviceId, Integer.toHexString(l2floodgroupId), - l2floodgroupkey, nextObj.id()); - - // create objects for local and distributed storage - allGroupKeys.forEach(gkeyChain -> gkeyChain.addFirst(l2floodgroupkey)); - OfdpaNextGroup ofdpaGrp = new OfdpaNextGroup(allGroupKeys, nextObj); - - // store l2floodgroupkey with the ofdpaGroupChain for the nextObjective - // that depends on it - updatePendingNextObjective(l2floodgroupkey, ofdpaGrp); - - for (GroupDescription l2intGrpDesc : l2interfaceGroupDescs) { - // store all l2groupkeys with the groupChainElem for the l2floodgroup - // that depends on it - Set gceSet = Collections.newSetFromMap( - new ConcurrentHashMap()); - gceSet.add(gce); - Set retval = pendingGroups.putIfAbsent( - l2intGrpDesc.appCookie(), gceSet); - if (retval != null) { - retval.add(gce); - } - - // create and send groups for all l2 interface groups - groupService.addGroup(l2intGrpDesc); - } - } - - /** - * Utility class for moving group information around. - * - */ - private class GroupInfo { - private GroupDescription innerGrpDesc; - private GroupDescription outerGrpDesc; - - GroupInfo(GroupDescription innerGrpDesc, GroupDescription outerGrpDesc) { - this.innerGrpDesc = innerGrpDesc; - this.outerGrpDesc = outerGrpDesc; - } - } - - /** - * As per the OFDPA 2.0 TTP, packets are sent out of ports by using - * a chain of groups. The hashed Next Objective passed in by the application - * has to be broken up into a group chain comprising of an - * L3 ECMP group as the top level group. Buckets of this group can point - * to a variety of groups in a group chain, depending on the whether - * MPLS labels are being pushed or not. - *

- * NOTE: We do not create MPLS ECMP groups as they are unimplemented in - * OF-DPA 2.0 (even though it is in the spec). Therefore we do not - * check the nextObjective meta. - * - * @param nextObj the nextObjective of type HASHED - */ - private void processHashedNextObjective(NextObjective nextObj) { - // break up hashed next objective to multiple groups - Collection buckets = nextObj.next(); - - // storage for all group keys in the chain of groups created - List> allGroupKeys = new ArrayList<>(); - List unsentGroups = new ArrayList<>(); - for (TrafficTreatment bucket : buckets) { - //figure out how many labels are pushed in each bucket - int labelsPushed = 0; - MplsLabel innermostLabel = null; - for (Instruction ins : bucket.allInstructions()) { - if (ins.type() == Instruction.Type.L2MODIFICATION) { - L2ModificationInstruction l2ins = (L2ModificationInstruction) ins; - if (l2ins.subtype() == L2SubType.MPLS_PUSH) { - labelsPushed++; - } - if (l2ins.subtype() == L2SubType.MPLS_LABEL) { - if (innermostLabel == null) { - innermostLabel = ((ModMplsLabelInstruction) l2ins).mplsLabel(); - } - } - } - } - - Deque gkeyChain = new ArrayDeque<>(); - // XXX we only deal with 0 and 1 label push right now - if (labelsPushed == 0) { - GroupInfo nolabelGroupInfo = createL2L3Chain(bucket, nextObj.id(), - nextObj.appId(), false, - nextObj.meta()); - if (nolabelGroupInfo == null) { - log.error("Could not process nextObj={} in dev:{}", - nextObj.id(), deviceId); - return; - } - gkeyChain.addFirst(nolabelGroupInfo.innerGrpDesc.appCookie()); - gkeyChain.addFirst(nolabelGroupInfo.outerGrpDesc.appCookie()); - - // we can't send the inner group description yet, as we have to - // create the dependent ECMP group first. So we store.. - unsentGroups.add(nolabelGroupInfo); - - } else if (labelsPushed == 1) { - GroupInfo onelabelGroupInfo = createL2L3Chain(bucket, nextObj.id(), - nextObj.appId(), true, - nextObj.meta()); - if (onelabelGroupInfo == null) { - log.error("Could not process nextObj={} in dev:{}", - nextObj.id(), deviceId); - return; - } - // we need to add another group to this chain - the L3VPN group - TrafficTreatment.Builder l3vpnTtb = DefaultTrafficTreatment.builder(); - l3vpnTtb.pushMpls() - .setMpls(innermostLabel) - .setMplsBos(true) - .copyTtlOut() - .group(new DefaultGroupId( - onelabelGroupInfo.outerGrpDesc.givenGroupId())); - GroupBucket l3vpnGrpBkt = - DefaultGroupBucket.createIndirectGroupBucket(l3vpnTtb.build()); - int l3vpngroupId = L3VPNMASK | l3vpnindex.incrementAndGet(); - int l3vpngk = L3VPNMASK | nextObj.id() << 12 | l3vpnindex.get(); - GroupKey l3vpngroupkey = new DefaultGroupKey(appKryo.serialize(l3vpngk)); - GroupDescription l3vpnGroupDesc = - new DefaultGroupDescription( - deviceId, - GroupDescription.Type.INDIRECT, - new GroupBuckets(Collections.singletonList( - l3vpnGrpBkt)), - l3vpngroupkey, - l3vpngroupId, - nextObj.appId()); - GroupChainElem l3vpnGce = new GroupChainElem(l3vpnGroupDesc, 1); - Set gceSet = Collections.newSetFromMap( - new ConcurrentHashMap()); - gceSet.add(l3vpnGce); - Set retval = pendingGroups - .putIfAbsent(onelabelGroupInfo.outerGrpDesc.appCookie(), gceSet); - if (retval != null) { - retval.add(l3vpnGce); - } - - gkeyChain.addFirst(onelabelGroupInfo.innerGrpDesc.appCookie()); - gkeyChain.addFirst(onelabelGroupInfo.outerGrpDesc.appCookie()); - gkeyChain.addFirst(l3vpngroupkey); - - //now we can replace the outerGrpDesc with the one we just created - onelabelGroupInfo.outerGrpDesc = l3vpnGroupDesc; - - // we can't send the innermost group yet, as we have to create - // the dependent ECMP group first. So we store ... - unsentGroups.add(onelabelGroupInfo); - - log.debug("Trying L3VPN: device:{} gid:{} gkey:{} nextId:{}", - deviceId, Integer.toHexString(l3vpngroupId), - l3vpngroupkey, nextObj.id()); - - } else { - log.warn("Driver currently does not handle more than 1 MPLS " - + "labels. Not processing nextObjective {}", nextObj); - return; - } - - // all groups in this chain - allGroupKeys.add(gkeyChain); - } - - // now we can create the outermost L3 ECMP group - List l3ecmpGroupBuckets = new ArrayList<>(); - for (GroupInfo gi : unsentGroups) { - // create ECMP bucket to point to the outer group - TrafficTreatment.Builder ttb = DefaultTrafficTreatment.builder(); - ttb.group(new DefaultGroupId(gi.outerGrpDesc.givenGroupId())); - GroupBucket sbucket = DefaultGroupBucket - .createSelectGroupBucket(ttb.build()); - l3ecmpGroupBuckets.add(sbucket); - } - int l3ecmpGroupId = L3ECMPMASK | nextObj.id() << 12; - GroupKey l3ecmpGroupKey = new DefaultGroupKey(appKryo.serialize(l3ecmpGroupId)); - GroupDescription l3ecmpGroupDesc = - new DefaultGroupDescription( - deviceId, - GroupDescription.Type.SELECT, - new GroupBuckets(l3ecmpGroupBuckets), - l3ecmpGroupKey, - l3ecmpGroupId, - nextObj.appId()); - GroupChainElem l3ecmpGce = new GroupChainElem(l3ecmpGroupDesc, - l3ecmpGroupBuckets.size()); - - // create objects for local and distributed storage - allGroupKeys.forEach(gkeyChain -> gkeyChain.addFirst(l3ecmpGroupKey)); - OfdpaNextGroup ofdpaGrp = new OfdpaNextGroup(allGroupKeys, nextObj); - - // store l3ecmpGroupKey with the ofdpaGroupChain for the nextObjective - // that depends on it - updatePendingNextObjective(l3ecmpGroupKey, ofdpaGrp); - - log.debug("Trying L3ECMP: device:{} gid:{} gkey:{} nextId:{}", - deviceId, Integer.toHexString(l3ecmpGroupId), - l3ecmpGroupKey, nextObj.id()); - // finally we are ready to send the innermost groups - for (GroupInfo gi : unsentGroups) { - log.debug("Sending innermost group {} in group chain on device {} ", - Integer.toHexString(gi.innerGrpDesc.givenGroupId()), deviceId); - Set gceSet = Collections.newSetFromMap( - new ConcurrentHashMap()); - gceSet.add(l3ecmpGce); - Set retval = pendingGroups - .putIfAbsent(gi.outerGrpDesc.appCookie(), gceSet); - if (retval != null) { - retval.add(l3ecmpGce); - } - - groupService.addGroup(gi.innerGrpDesc); - } - - } - - private void addBucketToGroup(NextObjective nextObjective) { - // TODO Auto-generated method stub - } - - private void waitToAddBucketToGroup(NextObjective nextObjective) { - // TODO Auto-generated method stub - } - - private void removeBucketFromGroup(NextObjective nextObjective) { - // TODO Auto-generated method stub - } - - private void removeGroup(NextObjective nextObjective) { - // TODO Auto-generated method stub - } - - /** - * Processes next element of a group chain. Assumption is that if this - * group points to another group, the latter has already been created - * and this driver has received notification for it. A second assumption is - * that if there is another group waiting for this group then the appropriate - * stores already have the information to act upon the notification for the - * creating of this group. - *

- * The processing of the GroupChainElement depends on the number of groups - * this element is waiting on. For all group types other than SIMPLE, a - * GroupChainElement could be waiting on multiple groups. - * - * @param gce the group chain element to be processed next - */ - private void processGroupChain(GroupChainElem gce) { - int waitOnGroups = gce.decrementAndGetGroupsWaitedOn(); - if (waitOnGroups != 0) { - log.debug("GCE: {} not ready to be processed", gce); - return; - } - log.debug("GCE: {} ready to be processed", gce); - groupService.addGroup(gce.groupDescription); - } - - private class GroupChecker implements Runnable { - @Override - public void run() { - Set keys = pendingGroups.keySet().stream() - .filter(key -> groupService.getGroup(deviceId, key) != null) - .collect(Collectors.toSet()); - Set otherkeys = pendingNextObjectives.asMap().keySet().stream() - .filter(otherkey -> groupService.getGroup(deviceId, otherkey) != null) - .collect(Collectors.toSet()); - keys.addAll(otherkeys); - - keys.stream().forEach(key -> { - //first check for group chain - Set gceSet = pendingGroups.remove(key); - if (gceSet != null) { - for (GroupChainElem gce : gceSet) { - log.info("Group service processed group key {} in device {}. " - + "Processing next group in group chain with group id {}", - key, deviceId, - Integer.toHexString(gce.groupDescription.givenGroupId())); - processGroupChain(gce); - } - } else { - List objList = pendingNextObjectives.getIfPresent(key); - if (objList != null) { - pendingNextObjectives.invalidate(key); - objList.forEach(obj -> { - log.info("Group service processed group key {} in device:{}. " - + "Done implementing next objective: {} <<-->> gid:{}", - key, deviceId, obj.nextObjective().id(), - Integer.toHexString(groupService.getGroup(deviceId, key) - .givenGroupId())); - pass(obj.nextObjective()); - flowObjectiveStore.putNextGroup(obj.nextObjective().id(), obj); - }); - } - } - }); - } - } - - private class InnerGroupListener implements GroupListener { - @Override - public void event(GroupEvent event) { - log.trace("received group event of type {}", event.type()); - if (event.type() == GroupEvent.Type.GROUP_ADDED) { - GroupKey key = event.subject().appCookie(); - // first check for group chain - Set gceSet = pendingGroups.remove(key); - if (gceSet != null) { - for (GroupChainElem gce : gceSet) { - log.info("group ADDED with group key {} .. " - + "Processing next group in group chain with group key {}", - key, - gce.groupDescription.appCookie()); - processGroupChain(gce); - } - } else { - List objList = pendingNextObjectives.getIfPresent(key); - if (objList != null) { - pendingNextObjectives.invalidate(key); - objList.forEach(obj -> { - log.info("group ADDED with key {} in dev {}.. Done implementing next " - + "objective: {} <<-->> gid:{}", - key, deviceId, obj.nextObjective().id(), - Integer.toHexString(groupService.getGroup(deviceId, key) - .givenGroupId())); - pass(obj.nextObjective()); - flowObjectiveStore.putNextGroup(obj.nextObjective().id(), obj); - }); - } - } - } - } - } - - /** - * Represents an entire group-chain that implements a Next-Objective from - * the application. The objective is represented as a list of deques, where - * each deque can is a separate chain of groups. - *

- * For example, an ECMP group with 3 buckets, where each bucket points to - * a group chain of L3 Unicast and L2 interface groups will look like this: - *

    - *
  • List[0] is a Deque of GroupKeyECMP(first)-GroupKeyL3(middle)-GroupKeyL2(last) - *
  • List[1] is a Deque of GroupKeyECMP(first)-GroupKeyL3(middle)-GroupKeyL2(last) - *
  • List[2] is a Deque of GroupKeyECMP(first)-GroupKeyL3(middle)-GroupKeyL2(last) - *
- * where the first element of each deque is the same, representing the - * top level ECMP group, while every other element represents a unique groupKey. - *

- * Also includes information about the next objective that - * resulted in this group-chain. - * - */ - private class OfdpaNextGroup implements NextGroup { - private final NextObjective nextObj; - private final List> gkeys; - - public OfdpaNextGroup(List> gkeys, NextObjective nextObj) { - this.gkeys = gkeys; - this.nextObj = nextObj; - } - - @SuppressWarnings("unused") - public List> groupKey() { - return gkeys; - } - - public NextObjective nextObjective() { - return nextObj; - } - - @Override - public byte[] data() { - return appKryo.serialize(gkeys); - } - - } - - /** - * Represents a group element that is part of a chain of groups. - * Stores enough information to create a Group Description to add the group - * to the switch by requesting the Group Service. Objects instantiating this - * class are meant to be temporary and live as long as it is needed to wait for - * preceding groups in the group chain to be created. - */ - private class GroupChainElem { - private GroupDescription groupDescription; - private AtomicInteger waitOnGroups; - - GroupChainElem(GroupDescription groupDescription, int waitOnGroups) { - this.groupDescription = groupDescription; - this.waitOnGroups = new AtomicInteger(waitOnGroups); - } - - /** - * This methods atomically decrements the counter for the number of - * groups this GroupChainElement is waiting on, for notifications from - * the Group Service. When this method returns a value of 0, this - * GroupChainElement is ready to be processed. - * - * @return integer indication of the number of notifications being waited on - */ - int decrementAndGetGroupsWaitedOn() { - return waitOnGroups.decrementAndGet(); - } - - @Override - public String toString() { - return (Integer.toHexString(groupDescription.givenGroupId()) + - " groupKey: " + groupDescription.appCookie() + - " waiting-on-groups: " + waitOnGroups.get() + - " device: " + deviceId); - } - } - -} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OVSCorsaPipeline.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OVSCorsaPipeline.java deleted file mode 100644 index 5993d96e..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OVSCorsaPipeline.java +++ /dev/null @@ -1,829 +0,0 @@ -/* - * Copyright 2015 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. - */ -package org.onosproject.driver.pipeline; - -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.RemovalCause; -import com.google.common.cache.RemovalNotification; - -import org.onlab.osgi.ServiceDirectory; -import org.onlab.packet.Ethernet; -import org.onlab.packet.IPv4; -import org.onlab.packet.MacAddress; -import org.onlab.packet.VlanId; -import org.onlab.util.KryoNamespace; -import org.onosproject.core.ApplicationId; -import org.onosproject.core.CoreService; -import org.onosproject.net.DeviceId; -import org.onosproject.net.behaviour.NextGroup; -import org.onosproject.net.behaviour.Pipeliner; -import org.onosproject.net.behaviour.PipelinerContext; -import org.onosproject.net.driver.AbstractHandlerBehaviour; -import org.onosproject.net.flow.DefaultFlowRule; -import org.onosproject.net.flow.DefaultTrafficSelector; -import org.onosproject.net.flow.DefaultTrafficTreatment; -import org.onosproject.net.flow.FlowRule; -import org.onosproject.net.flow.FlowRuleOperations; -import org.onosproject.net.flow.FlowRuleOperationsContext; -import org.onosproject.net.flow.FlowRuleService; -import org.onosproject.net.flow.TrafficSelector; -import org.onosproject.net.flow.TrafficTreatment; -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.criteria.IPProtocolCriterion; -import org.onosproject.net.flow.criteria.PortCriterion; -import org.onosproject.net.flow.criteria.VlanIdCriterion; -import org.onosproject.net.flowobjective.FilteringObjective; -import org.onosproject.net.flowobjective.FlowObjectiveStore; -import org.onosproject.net.flowobjective.ForwardingObjective; -import org.onosproject.net.flowobjective.NextObjective; -import org.onosproject.net.flowobjective.Objective; -import org.onosproject.net.flowobjective.ObjectiveError; -import org.onosproject.net.group.DefaultGroupBucket; -import org.onosproject.net.group.DefaultGroupDescription; -import org.onosproject.net.group.DefaultGroupKey; -import org.onosproject.net.group.Group; -import org.onosproject.net.group.GroupBucket; -import org.onosproject.net.group.GroupBuckets; -import org.onosproject.net.group.GroupDescription; -import org.onosproject.net.group.GroupEvent; -import org.onosproject.net.group.GroupKey; -import org.onosproject.net.group.GroupListener; -import org.onosproject.net.group.GroupService; -import org.slf4j.Logger; - -import java.util.Collection; -import java.util.Collections; -import java.util.Set; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - -import static org.onlab.util.Tools.groupedThreads; -import static org.slf4j.LoggerFactory.getLogger; - -/** - * OpenvSwitch emulation of the Corsa pipeline handler. - */ -public class OVSCorsaPipeline extends AbstractHandlerBehaviour implements Pipeliner { - - protected static final int MAC_TABLE = 0; - protected static final int VLAN_MPLS_TABLE = 1; - protected static final int VLAN_TABLE = 2; - //protected static final int MPLS_TABLE = 3; - protected static final int ETHER_TABLE = 4; - protected static final int COS_MAP_TABLE = 5; - protected static final int FIB_TABLE = 6; - protected static final int LOCAL_TABLE = 9; - - - protected static final int CONTROLLER_PRIORITY = 255; - private static final int DROP_PRIORITY = 0; - private static final int HIGHEST_PRIORITY = 0xffff; - - private final Logger log = getLogger(getClass()); - - private ServiceDirectory serviceDirectory; - protected FlowRuleService flowRuleService; - private CoreService coreService; - private GroupService groupService; - private FlowObjectiveStore flowObjectiveStore; - protected DeviceId deviceId; - protected ApplicationId appId; - - private KryoNamespace appKryo = new KryoNamespace.Builder() - .register(GroupKey.class) - .register(DefaultGroupKey.class) - .register(CorsaGroup.class) - .register(byte[].class) - .build(); - - private Cache pendingGroups; - - private ScheduledExecutorService groupChecker = - Executors.newScheduledThreadPool(2, groupedThreads("onos/pipeliner", - "ovs-corsa-%d")); - - @Override - public void init(DeviceId deviceId, PipelinerContext context) { - this.serviceDirectory = context.directory(); - this.deviceId = deviceId; - - pendingGroups = CacheBuilder.newBuilder() - .expireAfterWrite(20, TimeUnit.SECONDS) - .removalListener((RemovalNotification notification) -> { - if (notification.getCause() == RemovalCause.EXPIRED) { - fail(notification.getValue(), ObjectiveError.GROUPINSTALLATIONFAILED); - } - }).build(); - - groupChecker.scheduleAtFixedRate(new GroupChecker(), 0, 500, TimeUnit.MILLISECONDS); - - coreService = serviceDirectory.get(CoreService.class); - flowRuleService = serviceDirectory.get(FlowRuleService.class); - groupService = serviceDirectory.get(GroupService.class); - flowObjectiveStore = context.store(); - - groupService.addListener(new InnerGroupListener()); - - appId = coreService.registerApplication( - "org.onosproject.driver.OVSCorsaPipeline"); - - initializePipeline(); - } - - @Override - public void filter(FilteringObjective filteringObjective) { - if (filteringObjective.type() == FilteringObjective.Type.PERMIT) { - processFilter(filteringObjective, - filteringObjective.op() == Objective.Operation.ADD, - filteringObjective.appId()); - } else { - fail(filteringObjective, ObjectiveError.UNSUPPORTED); - } - } - - @Override - public void forward(ForwardingObjective fwd) { - Collection rules; - FlowRuleOperations.Builder flowBuilder = FlowRuleOperations.builder(); - - rules = processForward(fwd); - switch (fwd.op()) { - case ADD: - rules.stream() - .filter(rule -> rule != null) - .forEach(flowBuilder::add); - break; - case REMOVE: - rules.stream() - .filter(rule -> rule != null) - .forEach(flowBuilder::remove); - break; - default: - fail(fwd, ObjectiveError.UNKNOWN); - log.warn("Unknown forwarding type {}", fwd.op()); - } - - - flowRuleService.apply(flowBuilder.build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - pass(fwd); - } - - @Override - public void onError(FlowRuleOperations ops) { - fail(fwd, ObjectiveError.FLOWINSTALLATIONFAILED); - } - })); - - } - - @Override - public void next(NextObjective nextObjective) { - switch (nextObjective.type()) { - case SIMPLE: - Collection treatments = nextObjective.next(); - if (treatments.size() == 1) { - TrafficTreatment treatment = treatments.iterator().next(); - GroupBucket bucket = - DefaultGroupBucket.createIndirectGroupBucket(treatment); - final GroupKey key = new DefaultGroupKey(appKryo.serialize(nextObjective.id())); - GroupDescription groupDescription - = new DefaultGroupDescription(deviceId, - GroupDescription.Type.INDIRECT, - new GroupBuckets(Collections - .singletonList(bucket)), - key, - null, // let group service determine group id - nextObjective.appId()); - groupService.addGroup(groupDescription); - pendingGroups.put(key, nextObjective); - } - break; - case HASHED: - case BROADCAST: - case FAILOVER: - fail(nextObjective, ObjectiveError.UNSUPPORTED); - log.warn("Unsupported next objective type {}", nextObjective.type()); - break; - default: - fail(nextObjective, ObjectiveError.UNKNOWN); - log.warn("Unknown next objective type {}", nextObjective.type()); - } - - } - - private Collection processForward(ForwardingObjective fwd) { - switch (fwd.flag()) { - case SPECIFIC: - return processSpecific(fwd); - case VERSATILE: - return processVersatile(fwd); - default: - fail(fwd, ObjectiveError.UNKNOWN); - log.warn("Unknown forwarding flag {}", fwd.flag()); - } - return Collections.emptySet(); - } - - private Collection processVersatile(ForwardingObjective fwd) { - log.debug("Processing versatile forwarding objective"); - TrafficSelector selector = fwd.selector(); - - EthTypeCriterion ethType = - (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE); - if (ethType == null) { - log.error("Versatile forwarding objective must include ethType"); - fail(fwd, ObjectiveError.UNKNOWN); - return Collections.emptySet(); - } - if (ethType.ethType().toShort() == Ethernet.TYPE_ARP) { - log.warn("Driver automatically handles ARP packets by punting to controller " - + " from ETHER table"); - pass(fwd); - return Collections.emptySet(); - } else if (ethType.ethType().toShort() == Ethernet.TYPE_LLDP || - ethType.ethType().toShort() == Ethernet.TYPE_BSN) { - log.warn("Driver currently does not currently handle LLDP packets"); - fail(fwd, ObjectiveError.UNSUPPORTED); - return Collections.emptySet(); - } else if (ethType.ethType().toShort() == Ethernet.TYPE_IPV4) { - IPCriterion ipSrc = (IPCriterion) selector - .getCriterion(Criterion.Type.IPV4_SRC); - IPCriterion ipDst = (IPCriterion) selector - .getCriterion(Criterion.Type.IPV4_DST); - IPProtocolCriterion ipProto = (IPProtocolCriterion) selector - .getCriterion(Criterion.Type.IP_PROTO); - if (ipSrc != null) { - log.warn("Driver does not currently handle matching Src IP"); - fail(fwd, ObjectiveError.UNSUPPORTED); - return Collections.emptySet(); - } - if (ipDst != null) { - log.error("Driver handles Dst IP matching as specific forwarding " - + "objective, not versatile"); - fail(fwd, ObjectiveError.UNSUPPORTED); - return Collections.emptySet(); - } - if (ipProto != null && ipProto.protocol() == IPv4.PROTOCOL_TCP) { - log.warn("Driver automatically punts all packets reaching the " - + "LOCAL table to the controller"); - pass(fwd); - return Collections.emptySet(); - } - } - - log.warn("Driver does not support given versatile forwarding objective"); - fail(fwd, ObjectiveError.UNSUPPORTED); - return Collections.emptySet(); - } - - private Collection processSpecific(ForwardingObjective fwd) { - log.debug("Processing specific forwarding objective"); - TrafficSelector selector = fwd.selector(); - EthTypeCriterion ethType = - (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE); - if (ethType == null || ethType.ethType().toShort() != Ethernet.TYPE_IPV4) { - fail(fwd, ObjectiveError.UNSUPPORTED); - return Collections.emptySet(); - } - - TrafficSelector filteredSelector = - DefaultTrafficSelector.builder() - .matchEthType(Ethernet.TYPE_IPV4) - .matchIPDst( - ((IPCriterion) - selector.getCriterion(Criterion.Type.IPV4_DST)).ip()) - .build(); - - TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder(); - - if (fwd.nextId() != null) { - NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId()); - GroupKey key = appKryo.deserialize(next.data()); - Group group = groupService.getGroup(deviceId, key); - if (group == null) { - log.warn("The group left!"); - fail(fwd, ObjectiveError.GROUPMISSING); - return Collections.emptySet(); - } - tb.group(group.id()); - } - - FlowRule.Builder ruleBuilder = DefaultFlowRule.builder() - .fromApp(fwd.appId()) - .withPriority(fwd.priority()) - .forDevice(deviceId) - .withSelector(filteredSelector) - .withTreatment(tb.build()); - - if (fwd.permanent()) { - ruleBuilder.makePermanent(); - } else { - ruleBuilder.makeTemporary(fwd.timeout()); - } - - ruleBuilder.forTable(FIB_TABLE); - - - return Collections.singletonList(ruleBuilder.build()); - - } - - private void processFilter(FilteringObjective filt, boolean install, - ApplicationId applicationId) { - // This driver only processes filtering criteria defined with switch - // ports as the key - PortCriterion p; - if (!filt.key().equals(Criteria.dummy()) && - filt.key().type() == Criterion.Type.IN_PORT) { - p = (PortCriterion) filt.key(); - } else { - log.warn("No key defined in filtering objective from app: {}. Not" - + "processing filtering objective", applicationId); - fail(filt, ObjectiveError.UNKNOWN); - return; - } - // convert filtering conditions for switch-intfs into flowrules - FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); - for (Criterion c : filt.conditions()) { - if (c.type() == Criterion.Type.ETH_DST) { - EthCriterion e = (EthCriterion) c; - log.debug("adding rule for MAC: {}", e.mac()); - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); - selector.matchEthDst(e.mac()); - treatment.transition(VLAN_MPLS_TABLE); - FlowRule rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(CONTROLLER_PRIORITY) - .fromApp(applicationId) - .makePermanent() - .forTable(MAC_TABLE).build(); - ops = install ? ops.add(rule) : ops.remove(rule); - } else if (c.type() == Criterion.Type.VLAN_VID) { - VlanIdCriterion v = (VlanIdCriterion) c; - log.debug("adding rule for VLAN: {}", v.vlanId()); - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); - selector.matchVlanId(v.vlanId()); - selector.matchInPort(p.port()); - treatment.transition(ETHER_TABLE); - treatment.deferred().popVlan(); - FlowRule rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(CONTROLLER_PRIORITY) - .fromApp(applicationId) - .makePermanent() - .forTable(VLAN_TABLE).build(); - ops = install ? ops.add(rule) : ops.remove(rule); - } else if (c.type() == Criterion.Type.IPV4_DST) { - IPCriterion ip = (IPCriterion) c; - log.debug("adding rule for IP: {}", ip.ip()); - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); - selector.matchEthType(Ethernet.TYPE_IPV4); - selector.matchIPDst(ip.ip()); - treatment.transition(LOCAL_TABLE); - FlowRule rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(HIGHEST_PRIORITY) - .fromApp(applicationId) - .makePermanent() - .forTable(FIB_TABLE).build(); - - ops = install ? ops.add(rule) : ops.remove(rule); - } else { - log.warn("Driver does not currently process filtering condition" - + " of type: {}", c.type()); - fail(filt, ObjectiveError.UNSUPPORTED); - } - } - // apply filtering flow rules - flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - pass(filt); - log.info("Applied filtering rules"); - } - - @Override - public void onError(FlowRuleOperations ops) { - fail(filt, ObjectiveError.FLOWINSTALLATIONFAILED); - log.info("Failed to apply filtering rules"); - } - })); - } - - private void pass(Objective obj) { - if (obj.context().isPresent()) { - obj.context().get().onSuccess(obj); - } - } - - private void fail(Objective obj, ObjectiveError error) { - if (obj.context().isPresent()) { - obj.context().get().onError(obj, error); - } - } - - private void initializePipeline() { - processMacTable(true); - processVlanMplsTable(true); - processVlanTable(true); - processEtherTable(true); - processCosTable(true); - processFibTable(true); - processLocalTable(true); - } - - private void processMacTable(boolean install) { - TrafficSelector.Builder selector; - TrafficTreatment.Builder treatment; - - // Bcast rule - selector = DefaultTrafficSelector.builder(); - treatment = DefaultTrafficTreatment.builder(); - - selector.matchEthDst(MacAddress.BROADCAST); - treatment.transition(VLAN_MPLS_TABLE); - - FlowRule rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(CONTROLLER_PRIORITY) - .fromApp(appId) - .makePermanent() - .forTable(MAC_TABLE).build(); - - - FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); - - ops = install ? ops.add(rule) : ops.remove(rule); - - - //Drop rule - selector = DefaultTrafficSelector.builder(); - treatment = DefaultTrafficTreatment.builder(); - - treatment.drop(); - - rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(DROP_PRIORITY) - .fromApp(appId) - .makePermanent() - .forTable(MAC_TABLE).build(); - - - ops = install ? ops.add(rule) : ops.remove(rule); - - flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - log.info("Provisioned mac table"); - } - - @Override - public void onError(FlowRuleOperations ops) { - log.info("Failed to provision mac table"); - } - })); - - } - - protected void processVlanMplsTable(boolean install) { - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); - TrafficTreatment.Builder treatment = DefaultTrafficTreatment - .builder(); - FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); - FlowRule rule; - - selector.matchVlanId(VlanId.ANY); - treatment.transition(VLAN_TABLE); - - rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(CONTROLLER_PRIORITY) - .fromApp(appId) - .makePermanent() - .forTable(VLAN_MPLS_TABLE).build(); - - - ops = install ? ops.add(rule) : ops.remove(rule); - - flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - log.info("Provisioned vlan/mpls table"); - } - - @Override - public void onError(FlowRuleOperations ops) { - log.info( - "Failed to provision vlan/mpls table"); - } - })); - - } - - private void processVlanTable(boolean install) { - TrafficSelector.Builder selector; - TrafficTreatment.Builder treatment; - FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); - FlowRule rule; - - - //Drop rule - selector = DefaultTrafficSelector.builder(); - treatment = DefaultTrafficTreatment.builder(); - - treatment.drop(); - - rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(DROP_PRIORITY) - .fromApp(appId) - .makePermanent() - .forTable(VLAN_TABLE).build(); - - ops = install ? ops.add(rule) : ops.remove(rule); - - flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - log.info("Provisioned vlan table"); - } - - @Override - public void onError(FlowRuleOperations ops) { - log.info("Failed to provision vlan table"); - } - })); - } - - private void processEtherTable(boolean install) { - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); - TrafficTreatment.Builder treatment = DefaultTrafficTreatment - .builder(); - FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); - FlowRule rule; - - selector.matchEthType(Ethernet.TYPE_ARP); - treatment.punt(); - - rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(CONTROLLER_PRIORITY) - .fromApp(appId) - .makePermanent() - .forTable(ETHER_TABLE).build(); - - ops = install ? ops.add(rule) : ops.remove(rule); - - selector = DefaultTrafficSelector.builder(); - treatment = DefaultTrafficTreatment.builder(); - - selector.matchEthType(Ethernet.TYPE_IPV4); - treatment.transition(COS_MAP_TABLE); - - rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withPriority(CONTROLLER_PRIORITY) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .fromApp(appId) - .makePermanent() - .forTable(ETHER_TABLE).build(); - - ops = install ? ops.add(rule) : ops.remove(rule); - - //Drop rule - selector = DefaultTrafficSelector.builder(); - treatment = DefaultTrafficTreatment.builder(); - - treatment.drop(); - - rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(DROP_PRIORITY) - .fromApp(appId) - .makePermanent() - .forTable(ETHER_TABLE).build(); - - - ops = install ? ops.add(rule) : ops.remove(rule); - - flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - log.info("Provisioned ether table"); - } - - @Override - public void onError(FlowRuleOperations ops) { - log.info("Failed to provision ether table"); - } - })); - - } - - private void processCosTable(boolean install) { - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); - TrafficTreatment.Builder treatment = DefaultTrafficTreatment - .builder(); - FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); - FlowRule rule; - - treatment.transition(FIB_TABLE); - - rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(DROP_PRIORITY) - .fromApp(appId) - .makePermanent() - .forTable(COS_MAP_TABLE).build(); - - ops = install ? ops.add(rule) : ops.remove(rule); - - flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - log.info("Provisioned cos table"); - } - - @Override - public void onError(FlowRuleOperations ops) { - log.info("Failed to provision cos table"); - } - })); - - } - - private void processFibTable(boolean install) { - TrafficSelector.Builder selector; - TrafficTreatment.Builder treatment; - FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); - FlowRule rule; - - //Drop rule - selector = DefaultTrafficSelector.builder(); - treatment = DefaultTrafficTreatment.builder(); - - treatment.drop(); - - rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(DROP_PRIORITY) - .fromApp(appId) - .makePermanent() - .forTable(FIB_TABLE).build(); - - ops = install ? ops.add(rule) : ops.remove(rule); - - flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - log.info("Provisioned FIB table"); - } - - @Override - public void onError(FlowRuleOperations ops) { - log.info("Failed to provision FIB table"); - } - })); - } - - private void processLocalTable(boolean install) { - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); - TrafficTreatment.Builder treatment = DefaultTrafficTreatment - .builder(); - FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); - FlowRule rule; - - treatment.punt(); - - rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(CONTROLLER_PRIORITY) - .fromApp(appId) - .makePermanent() - .forTable(LOCAL_TABLE).build(); - - ops = install ? ops.add(rule) : ops.remove(rule); - - flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - log.info("Provisioned Local table"); - } - - @Override - public void onError(FlowRuleOperations ops) { - log.info("Failed to provision Local table"); - } - })); - } - - private class InnerGroupListener implements GroupListener { - @Override - public void event(GroupEvent event) { - if (event.type() == GroupEvent.Type.GROUP_ADDED) { - GroupKey key = event.subject().appCookie(); - - NextObjective obj = pendingGroups.getIfPresent(key); - if (obj != null) { - flowObjectiveStore.putNextGroup(obj.id(), new CorsaGroup(key)); - pass(obj); - pendingGroups.invalidate(key); - } - } - } - } - - - private class GroupChecker implements Runnable { - - @Override - public void run() { - Set keys = pendingGroups.asMap().keySet().stream() - .filter(key -> groupService.getGroup(deviceId, key) != null) - .collect(Collectors.toSet()); - - keys.stream().forEach(key -> { - NextObjective obj = pendingGroups.getIfPresent(key); - if (obj == null) { - return; - } - pass(obj); - pendingGroups.invalidate(key); - log.info("Heard back from group service for group {}. " - + "Applying pending forwarding objectives", obj.id()); - flowObjectiveStore.putNextGroup(obj.id(), new CorsaGroup(key)); - }); - } - } - - private class CorsaGroup implements NextGroup { - - private final GroupKey key; - - public CorsaGroup(GroupKey key) { - this.key = key; - } - - @SuppressWarnings("unused") - public GroupKey key() { - return key; - } - - @Override - public byte[] data() { - return appKryo.serialize(key); - } - - } -} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OltPipeline.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OltPipeline.java deleted file mode 100644 index 8a7b22b8..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OltPipeline.java +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright 2015 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. - */ -package org.onosproject.driver.pipeline; - -import org.onlab.osgi.ServiceDirectory; -import org.onlab.packet.EthType; -import org.onosproject.core.ApplicationId; -import org.onosproject.core.CoreService; -import org.onosproject.net.DefaultAnnotations; -import org.onosproject.net.Device; -import org.onosproject.net.DeviceId; -import org.onosproject.net.MastershipRole; -import org.onosproject.net.PortNumber; -import org.onosproject.net.behaviour.Pipeliner; -import org.onosproject.net.behaviour.PipelinerContext; -import org.onosproject.net.device.DefaultDeviceDescription; -import org.onosproject.net.device.DeviceDescription; -import org.onosproject.net.device.DeviceProvider; -import org.onosproject.net.device.DeviceProviderRegistry; -import org.onosproject.net.device.DeviceService; -import org.onosproject.net.driver.AbstractHandlerBehaviour; -import org.onosproject.net.flow.DefaultFlowRule; -import org.onosproject.net.flow.DefaultTrafficSelector; -import org.onosproject.net.flow.DefaultTrafficTreatment; -import org.onosproject.net.flow.FlowRule; -import org.onosproject.net.flow.FlowRuleOperations; -import org.onosproject.net.flow.FlowRuleOperationsContext; -import org.onosproject.net.flow.FlowRuleService; -import org.onosproject.net.flow.TrafficSelector; -import org.onosproject.net.flow.TrafficTreatment; -import org.onosproject.net.flow.instructions.Instructions; -import org.onosproject.net.flowobjective.FilteringObjective; -import org.onosproject.net.flowobjective.ForwardingObjective; -import org.onosproject.net.flowobjective.NextObjective; -import org.onosproject.net.flowobjective.ObjectiveError; -import org.onosproject.net.packet.PacketPriority; -import org.onosproject.net.provider.AbstractProvider; -import org.onosproject.net.provider.ProviderId; -import org.slf4j.Logger; - -import static com.google.common.base.Preconditions.checkNotNull; -import static org.slf4j.LoggerFactory.getLogger; - -/** - * Pipeliner for OLT device. - */ -public class OltPipeline extends AbstractHandlerBehaviour implements Pipeliner { - - private final Logger log = getLogger(getClass()); - - static final ProviderId PID = new ProviderId("olt", "org.onosproject.olt", true); - - static final String DEVICE = "isAccess"; - static final String OLT = "true"; - - private ServiceDirectory serviceDirectory; - private FlowRuleService flowRuleService; - private DeviceId deviceId; - private CoreService coreService; - - private ApplicationId appId; - - private DeviceProvider provider = new AnnotationProvider(); - - - @Override - public void init(DeviceId deviceId, PipelinerContext context) { - this.serviceDirectory = context.directory(); - this.deviceId = deviceId; - DeviceProviderRegistry registry = - serviceDirectory.get(DeviceProviderRegistry.class); - flowRuleService = serviceDirectory.get(FlowRuleService.class); - coreService = serviceDirectory.get(CoreService.class); - - /*try { - DeviceProviderService providerService = registry.register(provider); - providerService.deviceConnected(deviceId, - description(deviceId, DEVICE, OLT)); - } finally { - registry.unregister(provider); - }*/ - - appId = coreService.registerApplication( - "org.onosproject.driver.OLTPipeline"); - - TrafficSelector selector = DefaultTrafficSelector.builder() - .matchEthType(EthType.EtherType.EAPOL.ethType().toShort()) - .build(); - - TrafficTreatment treatment = DefaultTrafficTreatment.builder() - .punt() - .build(); - - FlowRule flowRule = new DefaultFlowRule(deviceId, selector, treatment, - PacketPriority.CONTROL.priorityValue(), - appId, 0, true, null); - - //flowRuleService.applyFlowRules(flowRule); - } - - @Override - public void filter(FilteringObjective filter) { - throw new UnsupportedOperationException("OLT does not filter."); - } - - @Override - public void forward(ForwardingObjective fwd) { - FlowRuleOperations.Builder flowBuilder = FlowRuleOperations.builder(); - - if (fwd.flag() != ForwardingObjective.Flag.VERSATILE) { - throw new UnsupportedOperationException( - "Only VERSATILE is supported."); - } - - boolean isPunt = fwd.treatment().immediate().stream().anyMatch(i -> { - if (i instanceof Instructions.OutputInstruction) { - Instructions.OutputInstruction out = (Instructions.OutputInstruction) i; - return out.port().equals(PortNumber.CONTROLLER); - } - return false; - }); - - if (isPunt) { - return; - } - - TrafficSelector selector = fwd.selector(); - TrafficTreatment treatment = fwd.treatment(); - - FlowRule.Builder ruleBuilder = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector) - .withTreatment(treatment) - .fromApp(fwd.appId()) - .withPriority(fwd.priority()); - - if (fwd.permanent()) { - ruleBuilder.makePermanent(); - } else { - ruleBuilder.makeTemporary(fwd.timeout()); - } - - switch (fwd.op()) { - case ADD: - flowBuilder.add(ruleBuilder.build()); - break; - case REMOVE: - flowBuilder.remove(ruleBuilder.build()); - break; - default: - log.warn("Unknown operation {}", fwd.op()); - } - - flowRuleService.apply(flowBuilder.build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - if (fwd.context().isPresent()) { - fwd.context().get().onSuccess(fwd); - } - } - - @Override - public void onError(FlowRuleOperations ops) { - if (fwd.context().isPresent()) { - fwd.context().get().onError(fwd, ObjectiveError.FLOWINSTALLATIONFAILED); - } - } - })); - } - - @Override - public void next(NextObjective nextObjective) { - throw new UnsupportedOperationException("OLT does not next hop."); - } - - /** - * Build a device description. - * - * @param deviceId a deviceId - * @param key the key of the annotation - * @param value the value for the annotation - * @return a device description - */ - private DeviceDescription description(DeviceId deviceId, String key, String value) { - DeviceService deviceService = serviceDirectory.get(DeviceService.class); - Device device = deviceService.getDevice(deviceId); - - checkNotNull(device, "Device not found in device service."); - - DefaultAnnotations.Builder builder = DefaultAnnotations.builder(); - if (value != null) { - builder.set(key, value); - } else { - builder.remove(key); - } - return new DefaultDeviceDescription(device.id().uri(), device.type(), - device.manufacturer(), device.hwVersion(), - device.swVersion(), device.serialNumber(), - device.chassisId(), builder.build()); - } - - /** - * Simple ancillary provider used to annotate device. - */ - private static final class AnnotationProvider - extends AbstractProvider implements DeviceProvider { - private AnnotationProvider() { - super(PID); - } - - @Override - public void triggerProbe(DeviceId deviceId) { - } - - @Override - public void roleChanged(DeviceId deviceId, MastershipRole newRole) { - } - - @Override - public boolean isReachable(DeviceId deviceId) { - return false; - } - } - -} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OpenVSwitchPipeline.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OpenVSwitchPipeline.java deleted file mode 100644 index 5d098390..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OpenVSwitchPipeline.java +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright 2015 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. - */ -package org.onosproject.driver.pipeline; - -import static org.slf4j.LoggerFactory.getLogger; - -import java.util.Collection; -import java.util.Collections; - -import org.onlab.osgi.ServiceDirectory; -import org.onosproject.core.ApplicationId; -import org.onosproject.core.CoreService; -import org.onosproject.net.DeviceId; -import org.onosproject.net.behaviour.Pipeliner; -import org.onosproject.net.behaviour.PipelinerContext; -import org.onosproject.net.device.DeviceService; -import org.onosproject.net.flow.DefaultFlowRule; -import org.onosproject.net.flow.DefaultTrafficSelector; -import org.onosproject.net.flow.DefaultTrafficTreatment; -import org.onosproject.net.flow.FlowRule; -import org.onosproject.net.flow.FlowRuleOperations; -import org.onosproject.net.flow.FlowRuleOperationsContext; -import org.onosproject.net.flow.FlowRuleService; -import org.onosproject.net.flow.TrafficSelector; -import org.onosproject.net.flow.TrafficTreatment; -import org.onosproject.net.flow.criteria.Criterion.Type; -import org.onosproject.net.flow.instructions.Instructions; -import org.onosproject.net.flowobjective.FilteringObjective; -import org.onosproject.net.flowobjective.FlowObjectiveStore; -import org.onosproject.net.flowobjective.ForwardingObjective; -import org.onosproject.net.flowobjective.NextObjective; -import org.onosproject.net.flowobjective.Objective; -import org.onosproject.net.flowobjective.ObjectiveError; -import org.slf4j.Logger; - -/** - * Driver for standard OpenVSwitch. - */ -public class OpenVSwitchPipeline extends DefaultSingleTablePipeline - implements Pipeliner { - - private static final String VTN_APP_ID = "org.onosproject.app.vtn"; - private final Logger log = getLogger(getClass()); - private CoreService coreService; - private ServiceDirectory serviceDirectory; - protected FlowObjectiveStore flowObjectiveStore; - protected DeviceId deviceId; - protected ApplicationId appId; - protected FlowRuleService flowRuleService; - protected DeviceService deviceService; - private static final int TIME_OUT = 0; - private static final int CLASSIFIER_TABLE = 0; - private static final int MAC_TABLE = 50; - private static final int TABLE_MISS_PRIORITY = 0; - - @Override - public void init(DeviceId deviceId, PipelinerContext context) { - super.init(deviceId, context); - this.serviceDirectory = context.directory(); - this.deviceId = deviceId; - - coreService = serviceDirectory.get(CoreService.class); - flowRuleService = serviceDirectory.get(FlowRuleService.class); - flowObjectiveStore = context.store(); - appId = coreService - .registerApplication("org.onosproject.driver.OpenVSwitchPipeline"); - initializePipeline(); - } - - @Override - public void filter(FilteringObjective filteringObjective) { - super.filter(filteringObjective); - } - - @Override - public void forward(ForwardingObjective fwd) { - if (!VTN_APP_ID.equals(fwd.appId().name())) { - super.forward(fwd); - return; - } - Collection rules; - FlowRuleOperations.Builder flowOpsBuilder = FlowRuleOperations - .builder(); - - rules = processForward(fwd); - switch (fwd.op()) { - case ADD: - rules.stream().filter(rule -> rule != null) - .forEach(flowOpsBuilder::add); - break; - case REMOVE: - rules.stream().filter(rule -> rule != null) - .forEach(flowOpsBuilder::remove); - break; - default: - fail(fwd, ObjectiveError.UNKNOWN); - log.warn("Unknown forwarding type {}", fwd.op()); - } - - flowRuleService.apply(flowOpsBuilder - .build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - pass(fwd); - } - - @Override - public void onError(FlowRuleOperations ops) { - fail(fwd, ObjectiveError.FLOWINSTALLATIONFAILED); - } - })); - } - - @Override - public void next(NextObjective nextObjective) { - super.next(nextObjective); - } - - private void initializePipeline() { - processClassifierTable(true); - processMacTable(true); - } - - private void processClassifierTable(boolean install) { - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); - - treatment.transition(MAC_TABLE); - - FlowRule rule; - rule = DefaultFlowRule.builder().forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(TABLE_MISS_PRIORITY).fromApp(appId) - .makePermanent().forTable(CLASSIFIER_TABLE).build(); - - applyRules(install, rule); - } - - private void processMacTable(boolean install) { - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); - - treatment.drop(); - - FlowRule rule; - rule = DefaultFlowRule.builder().forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(TABLE_MISS_PRIORITY).fromApp(appId) - .makePermanent().forTable(MAC_TABLE).build(); - - applyRules(install, rule); - } - - private void applyRules(boolean install, FlowRule rule) { - FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); - - ops = install ? ops.add(rule) : ops.remove(rule); - flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - log.info("ONOSW provisioned " + rule.tableId() + " table"); - } - - @Override - public void onError(FlowRuleOperations ops) { - log.info("ONOSW failed to provision " + rule.tableId() + " table"); - } - })); - } - - private Collection processForward(ForwardingObjective fwd) { - switch (fwd.flag()) { - case SPECIFIC: - return processSpecific(fwd); - case VERSATILE: - return processVersatile(fwd); - default: - fail(fwd, ObjectiveError.UNKNOWN); - log.warn("Unknown forwarding flag {}", fwd.flag()); - } - return Collections.emptySet(); - } - - private Collection processVersatile(ForwardingObjective fwd) { - log.debug("Processing versatile forwarding objective"); - return Collections.emptyList(); - } - - private Collection processSpecific(ForwardingObjective fwd) { - log.debug("Processing specific forwarding objective"); - TrafficSelector selector = fwd.selector(); - TrafficTreatment tb = fwd.treatment(); - FlowRule.Builder ruleBuilder = DefaultFlowRule.builder() - .fromApp(fwd.appId()).withPriority(fwd.priority()) - .forDevice(deviceId).withSelector(selector) - .withTreatment(tb).makeTemporary(TIME_OUT); - ruleBuilder.withPriority(fwd.priority()); - if (fwd.permanent()) { - ruleBuilder.makePermanent(); - } - if (selector.getCriterion(Type.ETH_DST) != null - || tb.allInstructions().contains(Instructions.createDrop())) { - ruleBuilder.withTreatment(tb); - ruleBuilder.forTable(MAC_TABLE); - } else { - TrafficTreatment.Builder newTraffic = DefaultTrafficTreatment.builder(); - tb.allInstructions().forEach(t -> newTraffic.add(t)); - newTraffic.transition(MAC_TABLE); - ruleBuilder.withTreatment(newTraffic.build()); - ruleBuilder.forTable(CLASSIFIER_TABLE); - } - return Collections.singletonList(ruleBuilder.build()); - } - - private void fail(Objective obj, ObjectiveError error) { - if (obj.context().isPresent()) { - obj.context().get().onError(obj, error); - } - } - - private void pass(Objective obj) { - if (obj.context().isPresent()) { - obj.context().get().onSuccess(obj); - } - } -} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OpenstackPipeline.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OpenstackPipeline.java deleted file mode 100644 index 7a92b4fa..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OpenstackPipeline.java +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Copyright 2015 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. - */ -package org.onosproject.driver.pipeline; - -import org.onlab.osgi.ServiceDirectory; -import org.onlab.packet.Ethernet; -import org.onosproject.core.ApplicationId; -import org.onosproject.core.CoreService; -import org.onosproject.net.DeviceId; -import org.onosproject.net.behaviour.Pipeliner; -import org.onosproject.net.behaviour.PipelinerContext; -import org.onosproject.net.flow.DefaultFlowRule; -import org.onosproject.net.flow.DefaultTrafficSelector; -import org.onosproject.net.flow.DefaultTrafficTreatment; -import org.onosproject.net.flow.FlowRule; -import org.onosproject.net.flow.FlowRuleOperations; -import org.onosproject.net.flow.FlowRuleOperationsContext; -import org.onosproject.net.flow.FlowRuleService; -import org.onosproject.net.flow.TrafficSelector; -import org.onosproject.net.flow.TrafficTreatment; -import org.onosproject.net.flow.criteria.Criterion; -import org.onosproject.net.flow.criteria.EthTypeCriterion; -import org.onosproject.net.flow.criteria.UdpPortCriterion; -import org.onosproject.net.flowobjective.FilteringObjective; -import org.onosproject.net.flowobjective.FlowObjectiveStore; -import org.onosproject.net.flowobjective.ForwardingObjective; -import org.onosproject.net.flowobjective.NextObjective; -import org.onosproject.net.flowobjective.Objective; -import org.onosproject.net.flowobjective.ObjectiveError; -import org.slf4j.Logger; - -import java.util.Collection; -import java.util.Collections; - -import static org.slf4j.LoggerFactory.getLogger; - -/** - * Driver for OpenstackSwitching. - */ -public class OpenstackPipeline extends DefaultSingleTablePipeline - implements Pipeliner { - - private final Logger log = getLogger(getClass()); - private CoreService coreService; - private ServiceDirectory serviceDirectory; - protected FlowObjectiveStore flowObjectiveStore; - protected DeviceId deviceId; - protected ApplicationId appId; - protected FlowRuleService flowRuleService; - - protected static final int VNI_TABLE = 0; - protected static final int FORWARDING_TABLE = 1; - - private static final int DROP_PRIORITY = 0; - private static final int TIME_OUT = 0; - private static final int DHCP_SERVER_PORT = 67; - private static final int DHCP_CLIENT_PORT = 68; - - - @Override - public void init(DeviceId deviceId, PipelinerContext context) { - super.init(deviceId, context); - this.serviceDirectory = context.directory(); - this.deviceId = deviceId; - - coreService = serviceDirectory.get(CoreService.class); - flowRuleService = serviceDirectory.get(FlowRuleService.class); - flowObjectiveStore = context.store(); - - appId = coreService.registerApplication( - "org.onosproject.driver.OpenstackPipeline"); - - initializePipeline(); - } - - @Override - public void filter(FilteringObjective filteringObjective) { - super.filter(filteringObjective); - } - - @Override - public void next(NextObjective nextObjective) { - super.next(nextObjective); - } - - @Override - public void forward(ForwardingObjective forwardingObjective) { - Collection rules; - FlowRuleOperations.Builder flowOpsBuilder = FlowRuleOperations.builder(); - - rules = processForward(forwardingObjective); - - switch (forwardingObjective.op()) { - case ADD: - rules.stream() - .filter(rule -> rule != null) - .forEach(flowOpsBuilder::add); - break; - case REMOVE: - rules.stream() - .filter(rule -> rule != null) - .forEach(flowOpsBuilder::remove); - break; - default: - fail(forwardingObjective, ObjectiveError.UNKNOWN); - log.warn("Unknown forwarding type {}"); - } - - flowRuleService.apply(flowOpsBuilder.build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - pass(forwardingObjective); - } - - @Override - public void onError(FlowRuleOperations ops) { - fail(forwardingObjective, ObjectiveError.FLOWINSTALLATIONFAILED); - } - })); - } - - private void initializePipeline() { - processVNITable(true); - processForwardingTable(true); - } - - private void processVNITable(boolean install) { - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); - - treatment.transition(FORWARDING_TABLE); - - FlowRule flowRule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(DROP_PRIORITY) - .fromApp(appId) - .makePermanent() - .forTable(VNI_TABLE) - .build(); - - applyRules(install, flowRule); - } - - private void processForwardingTable(boolean install) { - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); - - treatment.drop(); - - FlowRule flowRule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(DROP_PRIORITY) - .fromApp(appId) - .makePermanent() - .forTable(FORWARDING_TABLE) - .build(); - - applyRules(install, flowRule); - } - - private void applyRules(boolean install, FlowRule flowRule) { - FlowRuleOperations.Builder flowOpsBuilder = FlowRuleOperations.builder(); - - flowOpsBuilder = install ? flowOpsBuilder.add(flowRule) : flowOpsBuilder.remove(flowRule); - - flowRuleService.apply(flowOpsBuilder.build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - log.debug("Provisioned vni or forwarding table"); - } - - @Override - public void onError(FlowRuleOperations ops) { - log.debug("Failed to privision vni or forwarding table"); - } - })); - } - - private Collection processForward(ForwardingObjective forwardingObjective) { - switch (forwardingObjective.flag()) { - case SPECIFIC: - return processSpecific(forwardingObjective); - case VERSATILE: - return processVersatile(forwardingObjective); - default: - fail(forwardingObjective, ObjectiveError.UNKNOWN); - log.warn("Unknown forwarding flag {}", forwardingObjective.flag()); - } - return Collections.emptySet(); - } - - private Collection processVersatile(ForwardingObjective forwardingObjective) { - log.debug("Processing versatile forwarding objective"); - - FlowRule.Builder ruleBuilder = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(forwardingObjective.selector()) - .withTreatment(forwardingObjective.treatment()) - .withPriority(forwardingObjective.priority()) - .fromApp(forwardingObjective.appId()); - - if (forwardingObjective.permanent()) { - ruleBuilder.makePermanent(); - } else { - ruleBuilder.makeTemporary(TIME_OUT); - } - - //ARP & DHCP Rule - EthTypeCriterion ethCriterion = - (EthTypeCriterion) forwardingObjective.selector().getCriterion(Criterion.Type.ETH_TYPE); - UdpPortCriterion udpPortCriterion = (UdpPortCriterion) forwardingObjective - .selector().getCriterion(Criterion.Type.UDP_DST); - if (ethCriterion != null) { - if (ethCriterion.ethType().toShort() == Ethernet.TYPE_ARP || - ethCriterion.ethType().toShort() == Ethernet.TYPE_LLDP) { - ruleBuilder.forTable(VNI_TABLE); - return Collections.singletonList(ruleBuilder.build()); - } else if (udpPortCriterion != null && udpPortCriterion.udpPort().toInt() == DHCP_SERVER_PORT) { - ruleBuilder.forTable(VNI_TABLE); - return Collections.singletonList(ruleBuilder.build()); - } - } - return Collections.emptySet(); - } - - private Collection processSpecific(ForwardingObjective forwardingObjective) { - log.debug("Processing specific forwarding objective"); - - FlowRule.Builder ruleBuilder = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(forwardingObjective.selector()) - .withTreatment(forwardingObjective.treatment()) - .withPriority(forwardingObjective.priority()) - .fromApp(forwardingObjective.appId()); - - if (forwardingObjective.permanent()) { - ruleBuilder.makePermanent(); - } else { - ruleBuilder.makeTemporary(TIME_OUT); - } - - //VNI Table Rule - if (forwardingObjective.selector().getCriterion(Criterion.Type.IN_PORT) != null) { - TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder(); - forwardingObjective.treatment().allInstructions().forEach(tBuilder::add); - tBuilder.transition(FORWARDING_TABLE); - ruleBuilder.withTreatment(tBuilder.build()); - ruleBuilder.forTable(VNI_TABLE); - } else { - ruleBuilder.forTable(FORWARDING_TABLE); - } - - return Collections.singletonList(ruleBuilder.build()); - } - - - private void pass(Objective obj) { - if (obj.context().isPresent()) { - obj.context().get().onSuccess(obj); - } - } - - private void fail(Objective obj, ObjectiveError error) { - if (obj.context().isPresent()) { - obj.context().get().onError(obj, error); - } - } -} - diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/PicaPipeline.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/PicaPipeline.java deleted file mode 100644 index 69d20835..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/PicaPipeline.java +++ /dev/null @@ -1,543 +0,0 @@ -/* - * Copyright 2015 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. - */ -package org.onosproject.driver.pipeline; - -import org.onlab.osgi.ServiceDirectory; -import org.onlab.packet.Ethernet; -import org.onlab.packet.MacAddress; -import org.onlab.packet.VlanId; -import org.onlab.util.KryoNamespace; -import org.onosproject.core.ApplicationId; -import org.onosproject.core.CoreService; -import org.onosproject.net.DeviceId; -import org.onosproject.net.PortNumber; -import org.onosproject.net.behaviour.NextGroup; -import org.onosproject.net.behaviour.Pipeliner; -import org.onosproject.net.behaviour.PipelinerContext; -import org.onosproject.net.driver.AbstractHandlerBehaviour; -import org.onosproject.net.flow.DefaultFlowRule; -import org.onosproject.net.flow.DefaultTrafficSelector; -import org.onosproject.net.flow.DefaultTrafficTreatment; -import org.onosproject.net.flow.FlowRule; -import org.onosproject.net.flow.FlowRuleOperations; -import org.onosproject.net.flow.FlowRuleOperationsContext; -import org.onosproject.net.flow.FlowRuleService; -import org.onosproject.net.flow.TrafficSelector; -import org.onosproject.net.flow.TrafficTreatment; -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.criteria.PortCriterion; -import org.onosproject.net.flow.criteria.VlanIdCriterion; -import org.onosproject.net.flow.instructions.Instruction; -import org.onosproject.net.flow.instructions.L2ModificationInstruction; -import org.onosproject.net.flowobjective.FilteringObjective; -import org.onosproject.net.flowobjective.FlowObjectiveStore; -import org.onosproject.net.flowobjective.ForwardingObjective; -import org.onosproject.net.flowobjective.NextObjective; -import org.onosproject.net.flowobjective.Objective; -import org.onosproject.net.flowobjective.ObjectiveError; -import org.onosproject.store.serializers.KryoNamespaces; -import org.slf4j.Logger; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.concurrent.ConcurrentHashMap; - -import static org.slf4j.LoggerFactory.getLogger; - -/** - * Pica pipeline handler. - */ -public class PicaPipeline extends AbstractHandlerBehaviour implements Pipeliner { - - protected static final int IP_UNICAST_TABLE = 252; - protected static final int ACL_TABLE = 0; - - //private static final int CONTROLLER_PRIORITY = 255; - private static final int DROP_PRIORITY = 0; - private static final int HIGHEST_PRIORITY = 0xffff; - - private final Logger log = getLogger(getClass()); - - private ServiceDirectory serviceDirectory; - private FlowRuleService flowRuleService; - private CoreService coreService; - private FlowObjectiveStore flowObjectiveStore; - private DeviceId deviceId; - private ApplicationId appId; - private Collection filters; - private Collection pendingVersatiles; - - private KryoNamespace appKryo = new KryoNamespace.Builder() - .register(KryoNamespaces.API) - .register(PicaGroup.class) - .register(byte[].class) - .build(); - - @Override - public void init(DeviceId deviceId, PipelinerContext context) { - this.serviceDirectory = context.directory(); - this.deviceId = deviceId; - - coreService = serviceDirectory.get(CoreService.class); - flowRuleService = serviceDirectory.get(FlowRuleService.class); - flowObjectiveStore = context.store(); - filters = Collections.newSetFromMap(new ConcurrentHashMap()); - pendingVersatiles = Collections.newSetFromMap( - new ConcurrentHashMap()); - appId = coreService.registerApplication( - "org.onosproject.driver.OVSPicaPipeline"); - - initializePipeline(); - } - - @Override - public void filter(FilteringObjective filteringObjective) { - if (filteringObjective.type() == FilteringObjective.Type.PERMIT) { - processFilter(filteringObjective, - filteringObjective.op() == Objective.Operation.ADD, - filteringObjective.appId()); - } else { - fail(filteringObjective, ObjectiveError.UNSUPPORTED); - } - } - - @Override - public void forward(ForwardingObjective fwd) { - Collection rules; - FlowRuleOperations.Builder flowBuilder = FlowRuleOperations.builder(); - - rules = processForward(fwd); - switch (fwd.op()) { - case ADD: - rules.stream() - .filter(rule -> rule != null) - .forEach(flowBuilder::add); - break; - case REMOVE: - rules.stream() - .filter(rule -> rule != null) - .forEach(flowBuilder::remove); - break; - default: - fail(fwd, ObjectiveError.UNKNOWN); - log.warn("Unknown forwarding type {}", fwd.op()); - } - - - flowRuleService.apply(flowBuilder.build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - pass(fwd); - } - - @Override - public void onError(FlowRuleOperations ops) { - fail(fwd, ObjectiveError.FLOWINSTALLATIONFAILED); - } - })); - - } - - @Override - public void next(NextObjective nextObjective) { - switch (nextObjective.type()) { - case SIMPLE: - Collection treatments = nextObjective.next(); - if (treatments.size() != 1) { - log.error("Next Objectives of type Simple should only have a " - + "single Traffic Treatment. Next Objective Id:{}", nextObjective.id()); - fail(nextObjective, ObjectiveError.BADPARAMS); - return; - } - TrafficTreatment treatment = treatments.iterator().next(); - TrafficTreatment.Builder filteredTreatment = DefaultTrafficTreatment.builder(); - VlanId modVlanId; - for (Instruction ins : treatment.allInstructions()) { - if (ins.type() == Instruction.Type.L2MODIFICATION) { - L2ModificationInstruction l2ins = (L2ModificationInstruction) ins; - switch (l2ins.subtype()) { - case ETH_DST: - filteredTreatment.setEthDst( - ((L2ModificationInstruction.ModEtherInstruction) l2ins).mac()); - break; - case ETH_SRC: - filteredTreatment.setEthSrc( - ((L2ModificationInstruction.ModEtherInstruction) l2ins).mac()); - break; - case VLAN_ID: - modVlanId = ((L2ModificationInstruction.ModVlanIdInstruction) l2ins).vlanId(); - filteredTreatment.setVlanId(modVlanId); - break; - default: - break; - } - } else if (ins.type() == Instruction.Type.OUTPUT) { - //long portNum = ((Instructions.OutputInstruction) ins).port().toLong(); - filteredTreatment.add(ins); - } else { - // Ignore the vlan_pcp action since it's does matter much. - log.warn("Driver does not handle this type of TrafficTreatment" - + " instruction in nextObjectives: {}", ins.type()); - } - } - // store for future use - flowObjectiveStore.putNextGroup(nextObjective.id(), - new PicaGroup(filteredTreatment.build())); - break; - case HASHED: - case BROADCAST: - case FAILOVER: - fail(nextObjective, ObjectiveError.UNSUPPORTED); - log.warn("Unsupported next objective type {}", nextObjective.type()); - break; - default: - fail(nextObjective, ObjectiveError.UNKNOWN); - log.warn("Unknown next objective type {}", nextObjective.type()); - } - - } - - private Collection processForward(ForwardingObjective fwd) { - switch (fwd.flag()) { - case SPECIFIC: - return processSpecific(fwd); - case VERSATILE: - return processVersatile(fwd); - default: - fail(fwd, ObjectiveError.UNKNOWN); - log.warn("Unknown forwarding flag {}", fwd.flag()); - } - return Collections.emptySet(); - } - - private Collection processVersatile(ForwardingObjective fwd) { - log.debug("Processing versatile forwarding objective"); - TrafficSelector selector = fwd.selector(); - TrafficTreatment treatment = fwd.treatment(); - Collection flowrules = new ArrayList(); - - // first add this rule for basic single-table operation - // or non-ARP related multi-table operation - FlowRule rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector) - .withTreatment(treatment) - .withPriority(fwd.priority()) - .fromApp(fwd.appId()) - .makePermanent() - .forTable(ACL_TABLE).build(); - flowrules.add(rule); - - EthTypeCriterion ethType = - (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE); - if (ethType == null) { - log.warn("No ethType in versatile forwarding obj. Not processing further."); - return flowrules; - } - - // now deal with possible mix of ARP with filtering objectives - // in multi-table scenarios - if (ethType.ethType().toShort() == Ethernet.TYPE_ARP) { - if (filters.isEmpty()) { - pendingVersatiles.add(fwd); - return flowrules; - } - for (Filter filter : filters) { - flowrules.addAll(processVersatilesWithFilters(filter, fwd)); - } - } - return flowrules; - } - - private Collection processVersatilesWithFilters( - Filter filt, ForwardingObjective fwd) { - Collection flows = new ArrayList(); - - // rule for ARP replies - log.debug("adding ARP rule in ACL table"); - TrafficSelector.Builder sel = DefaultTrafficSelector.builder(); - TrafficTreatment.Builder treat = DefaultTrafficTreatment.builder(); - sel.matchInPort(filt.port()); - sel.matchVlanId(filt.vlanId()); - sel.matchEthDst(filt.mac()); - sel.matchEthType(Ethernet.TYPE_ARP); - treat.setOutput(PortNumber.CONTROLLER); - FlowRule rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(sel.build()) - .withTreatment(treat.build()) - .withPriority(HIGHEST_PRIORITY) - .fromApp(appId) - .makePermanent() - .forTable(ACL_TABLE).build(); - flows.add(rule); - - // rule for ARP Broadcast - sel = DefaultTrafficSelector.builder(); - treat = DefaultTrafficTreatment.builder(); - sel.matchInPort(filt.port()); - sel.matchVlanId(filt.vlanId()); - sel.matchEthDst(MacAddress.BROADCAST); - sel.matchEthType(Ethernet.TYPE_ARP); - treat.setOutput(PortNumber.CONTROLLER); - rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(sel.build()) - .withTreatment(treat.build()) - .withPriority(HIGHEST_PRIORITY) - .fromApp(appId) - .makePermanent() - .forTable(ACL_TABLE).build(); - flows.add(rule); - - return flows; - } - - - private Collection processSpecific(ForwardingObjective fwd) { - log.debug("Processing specific forwarding objective"); - TrafficSelector selector = fwd.selector(); - EthTypeCriterion ethType = - (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE); - if (ethType == null || ethType.ethType().toShort() != Ethernet.TYPE_IPV4) { - fail(fwd, ObjectiveError.UNSUPPORTED); - return Collections.emptySet(); - } - - List ipflows = new ArrayList(); - for (Filter f: filters) { - TrafficSelector filteredSelector = - DefaultTrafficSelector.builder() - .matchEthType(Ethernet.TYPE_IPV4) - .matchIPDst( - ((IPCriterion) - selector.getCriterion(Criterion.Type.IPV4_DST)).ip()) - .matchEthDst(f.mac()) - .matchVlanId(f.vlanId()) - .build(); - TrafficTreatment tt = null; - if (fwd.nextId() != null) { - NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId()); - if (next == null) { - log.error("next-id {} does not exist in store", fwd.nextId()); - return Collections.emptySet(); - } - tt = appKryo.deserialize(next.data()); - if (tt == null) { - log.error("Error in deserializing next-id {}", fwd.nextId()); - return Collections.emptySet(); - } - } - - FlowRule.Builder ruleBuilder = DefaultFlowRule.builder() - .fromApp(fwd.appId()) - .withPriority(fwd.priority()) - .forDevice(deviceId) - .withSelector(filteredSelector) - .withTreatment(tt); - if (fwd.permanent()) { - ruleBuilder.makePermanent(); - } else { - ruleBuilder.makeTemporary(fwd.timeout()); - } - ruleBuilder.forTable(IP_UNICAST_TABLE); - ipflows.add(ruleBuilder.build()); - } - - return ipflows; - } - - private void processFilter(FilteringObjective filt, boolean install, - ApplicationId applicationId) { - // This driver only processes filtering criteria defined with switch - // ports as the key - PortCriterion p; - if (!filt.key().equals(Criteria.dummy()) && - filt.key().type() == Criterion.Type.IN_PORT) { - p = (PortCriterion) filt.key(); - } else { - log.warn("No key defined in filtering objective from app: {}. Not" - + "processing filtering objective", applicationId); - fail(filt, ObjectiveError.UNKNOWN); - return; - } - - EthCriterion e = null; VlanIdCriterion v = null; - Collection ips = new ArrayList(); - // convert filtering conditions for switch-intfs into flowrules - FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); - for (Criterion c : filt.conditions()) { - if (c.type() == Criterion.Type.ETH_DST) { - e = (EthCriterion) c; - } else if (c.type() == Criterion.Type.VLAN_VID) { - v = (VlanIdCriterion) c; - } else if (c.type() == Criterion.Type.IPV4_DST) { - ips.add((IPCriterion) c); - } else { - log.error("Unsupported filter {}", c); - fail(filt, ObjectiveError.UNSUPPORTED); - return; - } - } - - // cache for later use - Filter filter = new Filter(p, e, v, ips); - filters.add(filter); - - // apply any pending versatile forwarding objectives - for (ForwardingObjective fwd : pendingVersatiles) { - Collection ret = processVersatilesWithFilters(filter, fwd); - for (FlowRule fr : ret) { - ops.add(fr); - } - } - - for (IPCriterion ipaddr : ips) { - log.debug("adding IP filtering rules in ACL table: {}", ipaddr.ip()); - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); - selector.matchInPort(p.port()); - selector.matchVlanId(v.vlanId()); - selector.matchEthDst(e.mac()); - selector.matchEthType(Ethernet.TYPE_IPV4); - selector.matchIPDst(ipaddr.ip()); // router IPs to the controller - treatment.setOutput(PortNumber.CONTROLLER); - FlowRule rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(HIGHEST_PRIORITY) - .fromApp(applicationId) - .makePermanent() - .forTable(ACL_TABLE).build(); - ops = ops.add(rule); - } - - // apply filtering flow rules - flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - pass(filt); - log.info("Applied filtering rules"); - } - - @Override - public void onError(FlowRuleOperations ops) { - fail(filt, ObjectiveError.FLOWINSTALLATIONFAILED); - log.info("Failed to apply filtering rules"); - } - })); - } - - private void pass(Objective obj) { - if (obj.context().isPresent()) { - obj.context().get().onSuccess(obj); - } - } - - private void fail(Objective obj, ObjectiveError error) { - if (obj.context().isPresent()) { - obj.context().get().onError(obj, error); - } - } - - private void initializePipeline() { - //processIpUnicastTable(true); - processAclTable(true); - } - - private void processAclTable(boolean install) { - TrafficSelector.Builder selector; - TrafficTreatment.Builder treatment; - FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); - FlowRule rule; - - //Drop rule - selector = DefaultTrafficSelector.builder(); - treatment = DefaultTrafficTreatment.builder(); - - rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(DROP_PRIORITY) - .fromApp(appId) - .makePermanent() - .forTable(ACL_TABLE).build(); - - ops = install ? ops.add(rule) : ops.remove(rule); - - flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - log.info("Provisioned ACL table"); - } - - @Override - public void onError(FlowRuleOperations ops) { - log.info("Failed to provision ACL table"); - } - })); - } - - private class Filter { - private PortCriterion port; - private VlanIdCriterion vlan; - private EthCriterion eth; - - @SuppressWarnings("unused") - private Collection ips; - - public Filter(PortCriterion p, EthCriterion e, VlanIdCriterion v, - Collection ips) { - this.eth = e; - this.port = p; - this.vlan = v; - this.ips = ips; - } - - public PortNumber port() { - return port.port(); - } - - public VlanId vlanId() { - return vlan.vlanId(); - } - - public MacAddress mac() { - return eth.mac(); - } - } - - private class PicaGroup implements NextGroup { - TrafficTreatment nextActions; - - public PicaGroup(TrafficTreatment next) { - this.nextActions = next; - } - - @Override - public byte[] data() { - return appKryo.serialize(nextActions); - } - } -} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SoftRouterPipeline.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SoftRouterPipeline.java deleted file mode 100644 index bd49e688..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SoftRouterPipeline.java +++ /dev/null @@ -1,544 +0,0 @@ -/* - * Copyright 2015 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. - */ -package org.onosproject.driver.pipeline; - -import org.onlab.osgi.ServiceDirectory; -import org.onlab.packet.Ethernet; -import org.onlab.packet.MacAddress; -import org.onlab.packet.VlanId; -import org.onlab.util.KryoNamespace; -import org.onosproject.core.ApplicationId; -import org.onosproject.core.CoreService; -import org.onosproject.net.DeviceId; -import org.onosproject.net.PortNumber; -import org.onosproject.net.behaviour.NextGroup; -import org.onosproject.net.behaviour.Pipeliner; -import org.onosproject.net.behaviour.PipelinerContext; -import org.onosproject.net.driver.AbstractHandlerBehaviour; -import org.onosproject.net.flow.DefaultFlowRule; -import org.onosproject.net.flow.DefaultTrafficSelector; -import org.onosproject.net.flow.DefaultTrafficTreatment; -import org.onosproject.net.flow.FlowRule; -import org.onosproject.net.flow.FlowRuleOperations; -import org.onosproject.net.flow.FlowRuleOperationsContext; -import org.onosproject.net.flow.FlowRuleService; -import org.onosproject.net.flow.TrafficSelector; -import org.onosproject.net.flow.TrafficTreatment; -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.criteria.PortCriterion; -import org.onosproject.net.flow.criteria.VlanIdCriterion; -import org.onosproject.net.flowobjective.FilteringObjective; -import org.onosproject.net.flowobjective.FlowObjectiveStore; -import org.onosproject.net.flowobjective.ForwardingObjective; -import org.onosproject.net.flowobjective.NextObjective; -import org.onosproject.net.flowobjective.Objective; -import org.onosproject.net.flowobjective.ObjectiveError; -import org.onosproject.store.serializers.KryoNamespaces; -import org.slf4j.Logger; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.concurrent.ConcurrentHashMap; - -import static org.slf4j.LoggerFactory.getLogger; - -/** - * Simple 2-Table Pipeline for Software/NPU based routers. This pipeline - * does not forward IP traffic to next-hop groups. Instead it forwards traffic - * using OF FlowMod actions. - */ -public class SoftRouterPipeline extends AbstractHandlerBehaviour implements Pipeliner { - - protected static final int FILTER_TABLE = 0; - protected static final int FIB_TABLE = 1; - - private static final int DROP_PRIORITY = 0; - private static final int DEFAULT_PRIORITY = 0x8000; - private static final int HIGHEST_PRIORITY = 0xffff; - - private ServiceDirectory serviceDirectory; - protected FlowRuleService flowRuleService; - private CoreService coreService; - private FlowObjectiveStore flowObjectiveStore; - protected DeviceId deviceId; - protected ApplicationId appId; - private ApplicationId driverId; - private Collection filters; - private Collection pendingVersatiles; - - private KryoNamespace appKryo = new KryoNamespace.Builder() - .register(DummyGroup.class) - .register(KryoNamespaces.API) - .register(byte[].class) - .build(); - - private final Logger log = getLogger(getClass()); - - @Override - public void init(DeviceId deviceId, PipelinerContext context) { - this.serviceDirectory = context.directory(); - this.deviceId = deviceId; - coreService = serviceDirectory.get(CoreService.class); - flowRuleService = serviceDirectory.get(FlowRuleService.class); - flowObjectiveStore = context.store(); - driverId = coreService.registerApplication( - "org.onosproject.driver.SoftRouterPipeline"); - filters = Collections.newSetFromMap(new ConcurrentHashMap()); - pendingVersatiles = Collections.newSetFromMap( - new ConcurrentHashMap()); - initializePipeline(); - } - - @Override - public void filter(FilteringObjective filteringObjective) { - if (filteringObjective.type() == FilteringObjective.Type.PERMIT) { - processFilter(filteringObjective, - filteringObjective.op() == Objective.Operation.ADD, - filteringObjective.appId()); - } else { - fail(filteringObjective, ObjectiveError.UNSUPPORTED); - } - } - - @Override - public void forward(ForwardingObjective fwd) { - Collection rules; - FlowRuleOperations.Builder flowOpsBuilder = FlowRuleOperations.builder(); - - rules = processForward(fwd); - switch (fwd.op()) { - case ADD: - rules.stream() - .filter(rule -> rule != null) - .forEach(flowOpsBuilder::add); - break; - case REMOVE: - rules.stream() - .filter(rule -> rule != null) - .forEach(flowOpsBuilder::remove); - break; - default: - fail(fwd, ObjectiveError.UNKNOWN); - log.warn("Unknown forwarding type {}", fwd.op()); - } - - - flowRuleService.apply(flowOpsBuilder.build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - pass(fwd); - } - - @Override - public void onError(FlowRuleOperations ops) { - fail(fwd, ObjectiveError.FLOWINSTALLATIONFAILED); - } - })); - - } - - @Override - public void next(NextObjective nextObjective) { - switch (nextObjective.type()) { - case SIMPLE: - Collection treatments = nextObjective.next(); - if (treatments.size() != 1) { - log.error("Next Objectives of type Simple should only have a " - + "single Traffic Treatment. Next Objective Id:{}", nextObjective.id()); - fail(nextObjective, ObjectiveError.BADPARAMS); - return; - } - processSimpleNextObjective(nextObjective); - break; - case HASHED: - case BROADCAST: - case FAILOVER: - fail(nextObjective, ObjectiveError.UNSUPPORTED); - log.warn("Unsupported next objective type {}", nextObjective.type()); - break; - default: - fail(nextObjective, ObjectiveError.UNKNOWN); - log.warn("Unknown next objective type {}", nextObjective.type()); - } - } - - private void pass(Objective obj) { - if (obj.context().isPresent()) { - obj.context().get().onSuccess(obj); - } - } - - private void fail(Objective obj, ObjectiveError error) { - if (obj.context().isPresent()) { - obj.context().get().onError(obj, error); - } - } - - - private void initializePipeline() { - //Drop rules for both tables - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); - FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); - - treatment.drop(); - - FlowRule rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(DROP_PRIORITY) - .fromApp(driverId) - .makePermanent() - .forTable(FILTER_TABLE) - .build(); - ops = ops.add(rule); - - rule = DefaultFlowRule.builder().forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(DROP_PRIORITY) - .fromApp(driverId) - .makePermanent() - .forTable(FIB_TABLE) - .build(); - ops = ops.add(rule); - - flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - log.info("Provisioned drop rules in both tables"); - } - - @Override - public void onError(FlowRuleOperations ops) { - log.info("Failed to provision drop rules"); - } - })); - } - - private void processFilter(FilteringObjective filt, boolean install, - ApplicationId applicationId) { - // This driver only processes filtering criteria defined with switch - // ports as the key - PortCriterion p; EthCriterion e = null; VlanIdCriterion v = null; - Collection ips = new ArrayList(); - if (!filt.key().equals(Criteria.dummy()) && - filt.key().type() == Criterion.Type.IN_PORT) { - p = (PortCriterion) filt.key(); - } else { - log.warn("No key defined in filtering objective from app: {}. Not" - + "processing filtering objective", applicationId); - fail(filt, ObjectiveError.UNKNOWN); - return; - } - - // convert filtering conditions for switch-intfs into flowrules - FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); - for (Criterion c : filt.conditions()) { - if (c.type() == Criterion.Type.ETH_DST) { - e = (EthCriterion) c; - } else if (c.type() == Criterion.Type.VLAN_VID) { - v = (VlanIdCriterion) c; - } else if (c.type() == Criterion.Type.IPV4_DST) { - ips.add((IPCriterion) c); - } else { - log.error("Unsupported filter {}", c); - fail(filt, ObjectiveError.UNSUPPORTED); - return; - } - } - - log.debug("adding Port/VLAN/MAC filtering rules in filter table: {}/{}/{}", - p.port(), v.vlanId(), e.mac()); - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); - TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder(); - selector.matchInPort(p.port()); - selector.matchVlanId(v.vlanId()); - selector.matchEthDst(e.mac()); - selector.matchEthType(Ethernet.TYPE_IPV4); - treatment.popVlan(); - treatment.transition(FIB_TABLE); // all other IPs to the FIB table - FlowRule rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(DEFAULT_PRIORITY) - .fromApp(applicationId) - .makePermanent() - .forTable(FILTER_TABLE).build(); - ops = ops.add(rule); - - for (IPCriterion ipaddr : ips) { - log.debug("adding IP filtering rules in FILTER table: {}", ipaddr.ip()); - selector = DefaultTrafficSelector.builder(); - treatment = DefaultTrafficTreatment.builder(); - selector.matchInPort(p.port()); - selector.matchVlanId(v.vlanId()); - selector.matchEthDst(e.mac()); - selector.matchEthType(Ethernet.TYPE_IPV4); - selector.matchIPDst(ipaddr.ip()); // router IPs to the controller - treatment.setOutput(PortNumber.CONTROLLER); - rule = DefaultFlowRule.builder() - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(HIGHEST_PRIORITY) - .fromApp(applicationId) - .makePermanent() - .forTable(FILTER_TABLE).build(); - ops = ops.add(rule); - } - - // cache for later use - Filter filter = new Filter(p, e, v, ips); - filters.add(filter); - // apply any pending versatile forwarding objectives - for (ForwardingObjective fwd : pendingVersatiles) { - Collection ret = processVersatilesWithFilters(filter, fwd); - for (FlowRule fr : ret) { - ops.add(fr); - } - } - - ops = install ? ops.add(rule) : ops.remove(rule); - // apply filtering flow rules - flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - log.info("Applied filtering rules"); - pass(filt); - } - - @Override - public void onError(FlowRuleOperations ops) { - log.info("Failed to apply filtering rules"); - fail(filt, ObjectiveError.FLOWINSTALLATIONFAILED); - } - })); - } - - private Collection processForward(ForwardingObjective fwd) { - switch (fwd.flag()) { - case SPECIFIC: - return processSpecific(fwd); - case VERSATILE: - return processVersatile(fwd); - default: - fail(fwd, ObjectiveError.UNKNOWN); - log.warn("Unknown forwarding flag {}", fwd.flag()); - } - return Collections.emptySet(); - } - - /** - * SoftRouter has a single versatile table - the filter table. All versatile - * flow rules must include the filtering rules. - * - * @param fwd The forwarding objective of type versatile - * @return A collection of flow rules meant to be delivered to the flowrule - * subsystem. May return empty collection in case of failures. - */ - private Collection processVersatile(ForwardingObjective fwd) { - if (filters.isEmpty()) { - pendingVersatiles.add(fwd); - return Collections.emptySet(); - } - Collection flowrules = new ArrayList(); - for (Filter filter : filters) { - flowrules.addAll(processVersatilesWithFilters(filter, fwd)); - } - return flowrules; - } - - private Collection processVersatilesWithFilters( - Filter filt, ForwardingObjective fwd) { - log.info("Processing versatile forwarding objective"); - Collection flows = new ArrayList(); - TrafficSelector match = fwd.selector(); - EthTypeCriterion ethType = - (EthTypeCriterion) match.getCriterion(Criterion.Type.ETH_TYPE); - if (ethType == null) { - log.error("Versatile forwarding objective must include ethType"); - fail(fwd, ObjectiveError.UNKNOWN); - return Collections.emptySet(); - } - - if (ethType.ethType().toShort() == Ethernet.TYPE_ARP) { - // need to install ARP request & reply flow rules for each interface filter - - // rule for ARP replies - TrafficSelector.Builder selector = DefaultTrafficSelector.builder(); - selector.matchInPort(filt.port()); - selector.matchVlanId(filt.vlanId()); - selector.matchEthDst(filt.mac()); - selector.matchEthType(Ethernet.TYPE_ARP); - FlowRule.Builder ruleBuilder = DefaultFlowRule.builder() - .fromApp(fwd.appId()) - .withPriority(fwd.priority()) - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(fwd.treatment()) - .makePermanent() - .forTable(FILTER_TABLE); - flows.add(ruleBuilder.build()); - - //rule for ARP requests - selector = DefaultTrafficSelector.builder(); - selector.matchInPort(filt.port()); - selector.matchVlanId(filt.vlanId()); - selector.matchEthDst(MacAddress.BROADCAST); - selector.matchEthType(Ethernet.TYPE_ARP); - ruleBuilder = DefaultFlowRule.builder() - .fromApp(fwd.appId()) - .withPriority(fwd.priority()) - .forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(fwd.treatment()) - .makePermanent() - .forTable(FILTER_TABLE); - flows.add(ruleBuilder.build()); - - return flows; - } - // not handling other versatile flows - return Collections.emptySet(); - } - - /** - * SoftRouter has a single specific table - the FIB Table. It emulates - * LPM matching of dstIP by using higher priority flows for longer prefixes. - * Flows are forwarded using flow-actions - * - * @param fwd The forwarding objective of type simple - * @return A collection of flow rules meant to be delivered to the flowrule - * subsystem. Typically the returned collection has a single flowrule. - * May return empty collection in case of failures. - * - */ - private Collection processSpecific(ForwardingObjective fwd) { - log.debug("Processing specific forwarding objective"); - TrafficSelector selector = fwd.selector(); - EthTypeCriterion ethType = - (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE); - // XXX currently supporting only the L3 unicast table - if (ethType == null || ethType.ethType().toShort() != Ethernet.TYPE_IPV4) { - fail(fwd, ObjectiveError.UNSUPPORTED); - return Collections.emptySet(); - } - - TrafficSelector filteredSelector = - DefaultTrafficSelector.builder() - .matchEthType(Ethernet.TYPE_IPV4) - .matchIPDst(((IPCriterion) - selector.getCriterion(Criterion.Type.IPV4_DST)).ip()) - .build(); - - TrafficTreatment tt = null; - if (fwd.nextId() != null) { - NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId()); - if (next == null) { - log.error("next-id {} does not exist in store", fwd.nextId()); - return Collections.emptySet(); - } - tt = appKryo.deserialize(next.data()); - if (tt == null) { - log.error("Error in deserializing next-id {}", fwd.nextId()); - return Collections.emptySet(); - } - } - - FlowRule.Builder ruleBuilder = DefaultFlowRule.builder() - .fromApp(fwd.appId()) - .withPriority(fwd.priority()) - .forDevice(deviceId) - .withSelector(filteredSelector) - .withTreatment(tt); - - if (fwd.permanent()) { - ruleBuilder.makePermanent(); - } else { - ruleBuilder.makeTemporary(fwd.timeout()); - } - - ruleBuilder.forTable(FIB_TABLE); - return Collections.singletonList(ruleBuilder.build()); - } - - /** - * Next Objectives are stored as dummy groups for retrieval later - * when Forwarding Objectives reference the next objective id. At that point - * the dummy group is fetched from the distributed store and the enclosed - * treatment is applied as a flow rule action. - * - * @param nextObj the next objective of type simple - */ - private void processSimpleNextObjective(NextObjective nextObj) { - // Simple next objective has a single treatment (not a collection) - TrafficTreatment treatment = nextObj.next().iterator().next(); - flowObjectiveStore.putNextGroup(nextObj.id(), - new DummyGroup(treatment)); - } - - private class Filter { - private PortCriterion port; - private VlanIdCriterion vlan; - private EthCriterion eth; - - @SuppressWarnings("unused") - private Collection ips; - - public Filter(PortCriterion p, EthCriterion e, VlanIdCriterion v, - Collection ips) { - this.eth = e; - this.port = p; - this.vlan = v; - this.ips = ips; - } - - public PortNumber port() { - return port.port(); - } - - public VlanId vlanId() { - return vlan.vlanId(); - } - - public MacAddress mac() { - return eth.mac(); - } - } - - private class DummyGroup implements NextGroup { - TrafficTreatment nextActions; - - public DummyGroup(TrafficTreatment next) { - this.nextActions = next; - } - - @Override - public byte[] data() { - return appKryo.serialize(nextActions); - } - - } - -} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTP.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTP.java deleted file mode 100644 index dba4557a..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTP.java +++ /dev/null @@ -1,1101 +0,0 @@ -/* - * Copyright 2015 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. - */ -package org.onosproject.driver.pipeline; - -import static org.onlab.util.Tools.groupedThreads; -import static org.slf4j.LoggerFactory.getLogger; - -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.RemovalCause; -import com.google.common.cache.RemovalNotification; - -import org.onlab.osgi.ServiceDirectory; -import org.onlab.packet.Ethernet; -import org.onlab.packet.MacAddress; -import org.onlab.packet.VlanId; -import org.onlab.util.KryoNamespace; -import org.onosproject.core.ApplicationId; -import org.onosproject.core.CoreService; -import org.onosproject.net.DeviceId; -import org.onosproject.net.PortNumber; -import org.onosproject.net.behaviour.NextGroup; -import org.onosproject.net.behaviour.Pipeliner; -import org.onosproject.net.behaviour.PipelinerContext; -import org.onosproject.net.driver.AbstractHandlerBehaviour; -import org.onosproject.net.flow.DefaultFlowRule; -import org.onosproject.net.flow.DefaultTrafficSelector; -import org.onosproject.net.flow.DefaultTrafficTreatment; -import org.onosproject.net.flow.FlowRule; -import org.onosproject.net.flow.FlowRuleOperations; -import org.onosproject.net.flow.FlowRuleOperationsContext; -import org.onosproject.net.flow.FlowRuleService; -import org.onosproject.net.flow.TrafficSelector; -import org.onosproject.net.flow.TrafficTreatment; -import org.onosproject.net.flow.criteria.Criteria; -import org.onosproject.net.flow.criteria.Criterion; -import org.onosproject.net.flow.criteria.Criterion.Type; -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.criteria.MplsCriterion; -import org.onosproject.net.flow.criteria.PortCriterion; -import org.onosproject.net.flow.criteria.VlanIdCriterion; -import org.onosproject.net.flow.instructions.Instruction; -import org.onosproject.net.flow.instructions.Instructions.OutputInstruction; -import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction; -import org.onosproject.net.flowobjective.FilteringObjective; -import org.onosproject.net.flowobjective.FlowObjectiveStore; -import org.onosproject.net.flowobjective.ForwardingObjective; -import org.onosproject.net.flowobjective.NextObjective; -import org.onosproject.net.flowobjective.Objective; -import org.onosproject.net.flowobjective.ObjectiveError; -import org.onosproject.net.group.DefaultGroupBucket; -import org.onosproject.net.group.DefaultGroupDescription; -import org.onosproject.net.group.DefaultGroupKey; -import org.onosproject.net.group.Group; -import org.onosproject.net.group.GroupBucket; -import org.onosproject.net.group.GroupBuckets; -import org.onosproject.net.group.GroupDescription; -import org.onosproject.net.group.GroupEvent; -import org.onosproject.net.group.GroupKey; -import org.onosproject.net.group.GroupListener; -import org.onosproject.net.group.GroupService; -import org.onosproject.store.serializers.KryoNamespaces; -import org.slf4j.Logger; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Set; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; - -/** - * Driver for SPRING-OPEN pipeline. - */ -public class SpringOpenTTP extends AbstractHandlerBehaviour - implements Pipeliner { - - // Default table ID - compatible with CpqD switch - private static final int TABLE_VLAN = 0; - private static final int TABLE_TMAC = 1; - private static final int TABLE_IPV4_UNICAST = 2; - private static final int TABLE_MPLS = 3; - private static final int TABLE_DMAC = 4; - private static final int TABLE_ACL = 5; - private static final int TABLE_SMAC = 6; - - /** - * Set the default values. These variables will get overwritten based on the - * switch vendor type - */ - protected int vlanTableId = TABLE_VLAN; - protected int tmacTableId = TABLE_TMAC; - protected int ipv4UnicastTableId = TABLE_IPV4_UNICAST; - protected int mplsTableId = TABLE_MPLS; - protected int dstMacTableId = TABLE_DMAC; - protected int aclTableId = TABLE_ACL; - protected int srcMacTableId = TABLE_SMAC; - - protected final Logger log = getLogger(getClass()); - - private ServiceDirectory serviceDirectory; - private FlowRuleService flowRuleService; - private CoreService coreService; - protected GroupService groupService; - protected FlowObjectiveStore flowObjectiveStore; - protected DeviceId deviceId; - private ApplicationId appId; - - private Cache pendingGroups; - - private ScheduledExecutorService groupChecker = Executors - .newScheduledThreadPool(2, - groupedThreads("onos/pipeliner", - "spring-open-%d")); - protected KryoNamespace appKryo = new KryoNamespace.Builder() - .register(KryoNamespaces.API) - .register(GroupKey.class) - .register(DefaultGroupKey.class) - .register(TrafficTreatment.class) - .register(SpringOpenGroup.class) - .register(byte[].class) - .build(); - - @Override - public void init(DeviceId deviceId, PipelinerContext context) { - this.serviceDirectory = context.directory(); - this.deviceId = deviceId; - - pendingGroups = CacheBuilder - .newBuilder() - .expireAfterWrite(20, TimeUnit.SECONDS) - .removalListener((RemovalNotification notification) -> { - if (notification.getCause() == RemovalCause.EXPIRED) { - fail(notification.getValue(), - ObjectiveError.GROUPINSTALLATIONFAILED); - } - }).build(); - - groupChecker.scheduleAtFixedRate(new GroupChecker(), 0, 500, - TimeUnit.MILLISECONDS); - - coreService = serviceDirectory.get(CoreService.class); - flowRuleService = serviceDirectory.get(FlowRuleService.class); - groupService = serviceDirectory.get(GroupService.class); - flowObjectiveStore = context.store(); - - groupService.addListener(new InnerGroupListener()); - - appId = coreService - .registerApplication("org.onosproject.driver.SpringOpenTTP"); - - setTableMissEntries(); - log.info("Spring Open TTP driver initialized"); - } - - @Override - public void filter(FilteringObjective filteringObjective) { - if (filteringObjective.type() == FilteringObjective.Type.PERMIT) { - log.debug("processing PERMIT filter objective"); - processFilter(filteringObjective, - filteringObjective.op() == Objective.Operation.ADD, - filteringObjective.appId()); - } else { - log.debug("filter objective other than PERMIT not supported"); - fail(filteringObjective, ObjectiveError.UNSUPPORTED); - } - } - - @Override - public void forward(ForwardingObjective fwd) { - Collection rules; - FlowRuleOperations.Builder flowBuilder = FlowRuleOperations.builder(); - - rules = processForward(fwd); - switch (fwd.op()) { - case ADD: - rules.stream().filter(rule -> rule != null) - .forEach(flowBuilder::add); - break; - case REMOVE: - rules.stream().filter(rule -> rule != null) - .forEach(flowBuilder::remove); - break; - default: - fail(fwd, ObjectiveError.UNKNOWN); - log.warn("Unknown forwarding type {}", fwd.op()); - } - - flowRuleService.apply(flowBuilder - .build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - pass(fwd); - log.debug("Provisioned tables in {} successfully with " - + "forwarding rules", deviceId); - } - - @Override - public void onError(FlowRuleOperations ops) { - fail(fwd, ObjectiveError.FLOWINSTALLATIONFAILED); - log.warn("Failed to provision tables in {} with " - + "forwarding rules", deviceId); - } - })); - - } - - @Override - public void next(NextObjective nextObjective) { - NextGroup nextGroup = flowObjectiveStore.getNextGroup(nextObjective.id()); - switch (nextObjective.op()) { - case ADD: - if (nextGroup != null) { - log.warn("Cannot add next {} that already exists in device {}", - nextObjective.id(), deviceId); - return; - } - log.debug("Processing NextObjective id{} in dev{} - add group", - nextObjective.id(), deviceId); - addGroup(nextObjective); - break; - case ADD_TO_EXISTING: - if (nextGroup != null) { - log.debug("Processing NextObjective id{} in dev{} - add bucket", - nextObjective.id(), deviceId); - addBucketToGroup(nextObjective); - } else { - log.warn("Cannot add to group that does not exist"); - } - break; - case REMOVE: - if (nextGroup == null) { - log.warn("Cannot remove next {} that does not exist in device {}", - nextObjective.id(), deviceId); - return; - } - log.debug("Processing NextObjective id{} in dev{} - remove group", - nextObjective.id(), deviceId); - removeGroup(nextObjective); - break; - case REMOVE_FROM_EXISTING: - if (nextGroup == null) { - log.warn("Cannot remove from next {} that does not exist in device {}", - nextObjective.id(), deviceId); - return; - } - log.debug("Processing NextObjective id{} in dev{} - remove bucket", - nextObjective.id(), deviceId); - removeBucketFromGroup(nextObjective); - break; - default: - log.warn("Unsupported operation {}", nextObjective.op()); - } - } - - private void removeGroup(NextObjective nextObjective) { - log.debug("removeGroup in {}: for next objective id {}", - deviceId, nextObjective.id()); - final GroupKey key = new DefaultGroupKey( - appKryo.serialize(nextObjective.id())); - groupService.removeGroup(deviceId, key, appId); - } - - private void addGroup(NextObjective nextObjective) { - log.debug("addGroup with type{} for nextObjective id {}", - nextObjective.type(), nextObjective.id()); - List buckets; - switch (nextObjective.type()) { - case SIMPLE: - Collection treatments = nextObjective.next(); - if (treatments.size() == 1) { - // Spring Open TTP converts simple nextObjective to flow-actions - // in a dummy group - TrafficTreatment treatment = nextObjective.next().iterator().next(); - log.debug("Converting SIMPLE group for next objective id {} " + - "to {} flow-actions in device:{}", nextObjective.id(), - treatment.allInstructions().size(), deviceId); - flowObjectiveStore.putNextGroup(nextObjective.id(), - new SpringOpenGroup(null, treatment)); - } - break; - case HASHED: - // we convert MPLS ECMP groups to flow-actions for a single - // bucket(output port). - boolean mplsEcmp = false; - if (nextObjective.meta() != null) { - for (Criterion c : nextObjective.meta().criteria()) { - if (c.type() == Type.MPLS_LABEL) { - mplsEcmp = true; - } - } - } - if (mplsEcmp) { - // covert to flow-actions in a dummy group by choosing the first bucket - log.debug("Converting HASHED group for next objective id {} " + - "to flow-actions in device:{}", nextObjective.id(), - deviceId); - TrafficTreatment treatment = nextObjective.next().iterator().next(); - flowObjectiveStore.putNextGroup(nextObjective.id(), - new SpringOpenGroup(null, treatment)); - } else { - // process as ECMP group - buckets = nextObjective - .next() - .stream() - .map((treatment) -> DefaultGroupBucket - .createSelectGroupBucket(treatment)) - .collect(Collectors.toList()); - if (!buckets.isEmpty()) { - final GroupKey key = new DefaultGroupKey( - appKryo.serialize(nextObjective.id())); - GroupDescription groupDescription = new DefaultGroupDescription( - deviceId, - GroupDescription.Type.SELECT, - new GroupBuckets(buckets), - key, - null, - nextObjective.appId()); - log.debug("Creating HASHED group for next objective id {}" - + " in dev:{}", nextObjective.id(), deviceId); - pendingGroups.put(key, nextObjective); - groupService.addGroup(groupDescription); - } - } - break; - case BROADCAST: - buckets = nextObjective - .next() - .stream() - .map((treatment) -> DefaultGroupBucket - .createAllGroupBucket(treatment)) - .collect(Collectors.toList()); - if (!buckets.isEmpty()) { - final GroupKey key = new DefaultGroupKey( - appKryo.serialize(nextObjective - .id())); - GroupDescription groupDescription = new DefaultGroupDescription( - deviceId, - GroupDescription.Type.ALL, - new GroupBuckets(buckets), - key, - null, - nextObjective.appId()); - log.debug("Creating BROADCAST group for next objective id {} " - + "in device {}", nextObjective.id(), deviceId); - pendingGroups.put(key, nextObjective); - groupService.addGroup(groupDescription); - } - break; - case FAILOVER: - log.debug("FAILOVER next objectives not supported"); - fail(nextObjective, ObjectiveError.UNSUPPORTED); - log.warn("Unsupported next objective type {}", nextObjective.type()); - break; - default: - fail(nextObjective, ObjectiveError.UNKNOWN); - log.warn("Unknown next objective type {}", nextObjective.type()); - } - } - - private void addBucketToGroup(NextObjective nextObjective) { - log.debug("addBucketToGroup in {}: for next objective id {}", - deviceId, nextObjective.id()); - Collection treatments = nextObjective.next(); - TrafficTreatment treatment = treatments.iterator().next(); - final GroupKey key = new DefaultGroupKey( - appKryo.serialize(nextObjective - .id())); - Group group = groupService.getGroup(deviceId, key); - if (group == null) { - log.warn("Group is not found in {} for {}", deviceId, key); - return; - } - GroupBucket bucket; - if (group.type() == GroupDescription.Type.INDIRECT) { - bucket = DefaultGroupBucket.createIndirectGroupBucket(treatment); - } else if (group.type() == GroupDescription.Type.SELECT) { - bucket = DefaultGroupBucket.createSelectGroupBucket(treatment); - } else if (group.type() == GroupDescription.Type.ALL) { - bucket = DefaultGroupBucket.createAllGroupBucket(treatment); - } else { - log.warn("Unsupported Group type {}", group.type()); - return; - } - GroupBuckets bucketsToAdd = new GroupBuckets(Collections.singletonList(bucket)); - log.debug("Adding buckets to group id {} of next objective id {} in device {}", - group.id(), nextObjective.id(), deviceId); - groupService.addBucketsToGroup(deviceId, key, bucketsToAdd, key, appId); - } - - private void removeBucketFromGroup(NextObjective nextObjective) { - log.debug("removeBucketFromGroup in {}: for next objective id {}", - deviceId, nextObjective.id()); - NextGroup nextGroup = flowObjectiveStore.getNextGroup(nextObjective.id()); - if (nextGroup != null) { - Collection treatments = nextObjective.next(); - TrafficTreatment treatment = treatments.iterator().next(); - final GroupKey key = new DefaultGroupKey( - appKryo.serialize(nextObjective - .id())); - Group group = groupService.getGroup(deviceId, key); - if (group == null) { - log.warn("Group is not found in {} for {}", deviceId, key); - return; - } - GroupBucket bucket; - if (group.type() == GroupDescription.Type.INDIRECT) { - bucket = DefaultGroupBucket.createIndirectGroupBucket(treatment); - } else if (group.type() == GroupDescription.Type.SELECT) { - bucket = DefaultGroupBucket.createSelectGroupBucket(treatment); - } else if (group.type() == GroupDescription.Type.ALL) { - bucket = DefaultGroupBucket.createAllGroupBucket(treatment); - } else { - log.warn("Unsupported Group type {}", group.type()); - return; - } - GroupBuckets removeBuckets = new GroupBuckets(Collections.singletonList(bucket)); - log.debug("Removing buckets from group id {} of next objective id {} in device {}", - group.id(), nextObjective.id(), deviceId); - groupService.removeBucketsFromGroup(deviceId, key, removeBuckets, key, appId); - } - } - - private Collection processForward(ForwardingObjective fwd) { - switch (fwd.flag()) { - case SPECIFIC: - return processSpecific(fwd); - case VERSATILE: - return processVersatile(fwd); - default: - fail(fwd, ObjectiveError.UNKNOWN); - log.warn("Unknown forwarding flag {}", fwd.flag()); - } - return Collections.emptySet(); - } - - private Collection processVersatile(ForwardingObjective fwd) { - log.debug("Processing versatile forwarding objective in dev:{}", deviceId); - TrafficSelector selector = fwd.selector(); - EthTypeCriterion ethType = - (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE); - if (ethType == null) { - log.error("Versatile forwarding objective must include ethType"); - fail(fwd, ObjectiveError.UNKNOWN); - return Collections.emptySet(); - } - - if (fwd.treatment() == null && fwd.nextId() == null) { - log.error("VERSATILE forwarding objective needs next objective ID " - + "or treatment."); - return Collections.emptySet(); - } - // emulation of ACL table (for versatile fwd objective) requires - // overriding any previous instructions - TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment - .builder(); - treatmentBuilder.wipeDeferred(); - - if (fwd.nextId() != null) { - NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId()); - if (next != null) { - SpringOpenGroup soGroup = appKryo.deserialize(next.data()); - if (soGroup.dummy) { - // need to convert to flow-actions - for (Instruction ins : soGroup.treatment.allInstructions()) { - treatmentBuilder.add(ins); - } - } else { - GroupKey key = soGroup.key; - Group group = groupService.getGroup(deviceId, key); - if (group == null) { - log.warn("The group left!"); - fail(fwd, ObjectiveError.GROUPMISSING); - return Collections.emptySet(); - } - treatmentBuilder.deferred().group(group.id()); - log.debug("Adding OUTGROUP action"); - } - } - } - - if (fwd.treatment() != null) { - if (fwd.treatment().allInstructions().size() == 1 && - fwd.treatment().allInstructions().get(0).type() == Instruction.Type.OUTPUT) { - OutputInstruction o = (OutputInstruction) fwd.treatment().allInstructions().get(0); - if (o.port() == PortNumber.CONTROLLER) { - treatmentBuilder.punt(); - } else { - treatmentBuilder.add(o); - } - } else { - for (Instruction ins : fwd.treatment().allInstructions()) { - treatmentBuilder.add(ins); - } - } - } - - FlowRule.Builder ruleBuilder = DefaultFlowRule.builder() - .fromApp(fwd.appId()).withPriority(fwd.priority()) - .forDevice(deviceId).withSelector(fwd.selector()) - .withTreatment(treatmentBuilder.build()); - - if (fwd.permanent()) { - ruleBuilder.makePermanent(); - } else { - ruleBuilder.makeTemporary(fwd.timeout()); - } - - ruleBuilder.forTable(aclTableId); - return Collections.singletonList(ruleBuilder.build()); - } - - private boolean isSupportedEthTypeObjective(ForwardingObjective fwd) { - TrafficSelector selector = fwd.selector(); - EthTypeCriterion ethType = (EthTypeCriterion) selector - .getCriterion(Criterion.Type.ETH_TYPE); - if ((ethType == null) || - ((ethType.ethType().toShort() != Ethernet.TYPE_IPV4) && - (ethType.ethType().toShort() != Ethernet.MPLS_UNICAST))) { - return false; - } - return true; - } - - private boolean isSupportedEthDstObjective(ForwardingObjective fwd) { - TrafficSelector selector = fwd.selector(); - EthCriterion ethDst = (EthCriterion) selector - .getCriterion(Criterion.Type.ETH_DST); - VlanIdCriterion vlanId = (VlanIdCriterion) selector - .getCriterion(Criterion.Type.VLAN_VID); - if (ethDst == null && vlanId == null) { - return false; - } - return true; - } - - protected Collection processSpecific(ForwardingObjective fwd) { - log.debug("Processing specific fwd objective:{} in dev:{} with next:{}", - fwd.id(), deviceId, fwd.nextId()); - boolean isEthTypeObj = isSupportedEthTypeObjective(fwd); - boolean isEthDstObj = isSupportedEthDstObjective(fwd); - - if (isEthTypeObj) { - return processEthTypeSpecificObjective(fwd); - } else if (isEthDstObj) { - return processEthDstSpecificObjective(fwd); - } else { - log.warn("processSpecific: Unsupported " - + "forwarding objective criteria"); - fail(fwd, ObjectiveError.UNSUPPORTED); - return Collections.emptySet(); - } - } - - protected Collection - processEthTypeSpecificObjective(ForwardingObjective fwd) { - TrafficSelector selector = fwd.selector(); - EthTypeCriterion ethType = (EthTypeCriterion) selector - .getCriterion(Criterion.Type.ETH_TYPE); - - TrafficSelector.Builder filteredSelectorBuilder = - DefaultTrafficSelector.builder(); - int forTableId = -1; - if (ethType.ethType().toShort() == Ethernet.TYPE_IPV4) { - filteredSelectorBuilder = filteredSelectorBuilder - .matchEthType(Ethernet.TYPE_IPV4) - .matchIPDst(((IPCriterion) selector - .getCriterion(Criterion.Type.IPV4_DST)) - .ip()); - forTableId = ipv4UnicastTableId; - log.debug("processing IPv4 specific forwarding objective:{} in dev:{}", - fwd.id(), deviceId); - } else { - filteredSelectorBuilder = filteredSelectorBuilder - .matchEthType(Ethernet.MPLS_UNICAST) - .matchMplsLabel(((MplsCriterion) - selector.getCriterion(Criterion.Type.MPLS_LABEL)).label()); - //TODO: Add Match for BoS - //if (selector.getCriterion(Criterion.Type.MPLS_BOS) != null) { - //} - forTableId = mplsTableId; - log.debug("processing MPLS specific forwarding objective:{} in dev:{}", - fwd.id(), deviceId); - } - - TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment - .builder(); - if (fwd.treatment() != null) { - for (Instruction i : fwd.treatment().allInstructions()) { - treatmentBuilder.add(i); - } - } - - if (fwd.nextId() != null) { - NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId()); - if (next != null) { - SpringOpenGroup soGroup = appKryo.deserialize(next.data()); - if (soGroup.dummy) { - log.debug("Adding {} flow-actions for fwd. obj. {} -> next:{} " - + "in dev: {}", soGroup.treatment.allInstructions().size(), - fwd.id(), fwd.nextId(), deviceId); - for (Instruction ins : soGroup.treatment.allInstructions()) { - treatmentBuilder.add(ins); - } - } else { - GroupKey key = soGroup.key; - Group group = groupService.getGroup(deviceId, key); - if (group == null) { - log.warn("The group left!"); - fail(fwd, ObjectiveError.GROUPMISSING); - return Collections.emptySet(); - } - treatmentBuilder.deferred().group(group.id()); - log.debug("Adding OUTGROUP action to group:{} for fwd. obj. {} " - + "for next:{} in dev: {}", group.id(), fwd.id(), - fwd.nextId(), deviceId); - } - } else { - log.warn("processSpecific: No associated next objective object"); - fail(fwd, ObjectiveError.GROUPMISSING); - return Collections.emptySet(); - } - } - - TrafficSelector filteredSelector = filteredSelectorBuilder.build(); - TrafficTreatment treatment = treatmentBuilder.transition(aclTableId) - .build(); - - FlowRule.Builder ruleBuilder = DefaultFlowRule.builder() - .fromApp(fwd.appId()).withPriority(fwd.priority()) - .forDevice(deviceId).withSelector(filteredSelector) - .withTreatment(treatment); - - if (fwd.permanent()) { - ruleBuilder.makePermanent(); - } else { - ruleBuilder.makeTemporary(fwd.timeout()); - } - - ruleBuilder.forTable(forTableId); - return Collections.singletonList(ruleBuilder.build()); - - } - - protected Collection - processEthDstSpecificObjective(ForwardingObjective fwd) { - List rules = new ArrayList<>(); - - // Build filtered selector - TrafficSelector selector = fwd.selector(); - EthCriterion ethCriterion = (EthCriterion) selector - .getCriterion(Criterion.Type.ETH_DST); - VlanIdCriterion vlanIdCriterion = (VlanIdCriterion) selector - .getCriterion(Criterion.Type.VLAN_VID); - TrafficSelector.Builder filteredSelectorBuilder = - DefaultTrafficSelector.builder(); - // Do not match MacAddress for subnet broadcast entry - if (!ethCriterion.mac().equals(MacAddress.NONE)) { - filteredSelectorBuilder.matchEthDst(ethCriterion.mac()); - log.debug("processing L2 forwarding objective:{} in dev:{}", - fwd.id(), deviceId); - } else { - log.debug("processing L2 Broadcast forwarding objective:{} " - + "in dev:{} for vlan:{}", - fwd.id(), deviceId, vlanIdCriterion.vlanId()); - } - filteredSelectorBuilder.matchVlanId(vlanIdCriterion.vlanId()); - TrafficSelector filteredSelector = filteredSelectorBuilder.build(); - - // Build filtered treatment - TrafficTreatment.Builder treatmentBuilder = - DefaultTrafficTreatment.builder(); - if (fwd.treatment() != null) { - treatmentBuilder.deferred(); - fwd.treatment().allInstructions().forEach(treatmentBuilder::add); - } - if (fwd.nextId() != null) { - NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId()); - if (next != null) { - SpringOpenGroup soGrp = appKryo.deserialize(next.data()); - if (soGrp.dummy) { - log.debug("Adding {} flow-actions for fwd. obj. {} " - + "in dev: {}", soGrp.treatment.allInstructions().size(), - fwd.id(), deviceId); - for (Instruction ins : soGrp.treatment.allInstructions()) { - treatmentBuilder.deferred().add(ins); - } - } else { - GroupKey key = soGrp.key; - Group group = groupService.getGroup(deviceId, key); - if (group == null) { - log.warn("The group left!"); - fail(fwd, ObjectiveError.GROUPMISSING); - return Collections.emptySet(); - } - treatmentBuilder.deferred().group(group.id()); - log.debug("Adding OUTGROUP action to group:{} for fwd. obj. {} " - + "in dev: {}", group.id(), fwd.id(), deviceId); - } - } - } - treatmentBuilder.immediate().transition(aclTableId); - TrafficTreatment filteredTreatment = treatmentBuilder.build(); - - // Build bridging table entries - FlowRule.Builder flowRuleBuilder = DefaultFlowRule.builder(); - flowRuleBuilder.fromApp(fwd.appId()) - .withPriority(fwd.priority()) - .forDevice(deviceId) - .withSelector(filteredSelector) - .withTreatment(filteredTreatment) - .forTable(dstMacTableId); - if (fwd.permanent()) { - flowRuleBuilder.makePermanent(); - } else { - flowRuleBuilder.makeTemporary(fwd.timeout()); - } - rules.add(flowRuleBuilder.build()); - - /* - // TODO Emulate source MAC table behavior - // Do not install source MAC table entry for subnet broadcast - if (!ethCriterion.mac().equals(MacAddress.NONE)) { - // Build filtered selector - selector = fwd.selector(); - ethCriterion = (EthCriterion) selector.getCriterion(Criterion.Type.ETH_DST); - filteredSelectorBuilder = DefaultTrafficSelector.builder(); - filteredSelectorBuilder.matchEthSrc(ethCriterion.mac()); - filteredSelector = filteredSelectorBuilder.build(); - - // Build empty treatment. Apply existing instruction if match. - treatmentBuilder = DefaultTrafficTreatment.builder(); - filteredTreatment = treatmentBuilder.build(); - - // Build bridging table entries - flowRuleBuilder = DefaultFlowRule.builder(); - flowRuleBuilder.fromApp(fwd.appId()) - .withPriority(fwd.priority()) - .forDevice(deviceId) - .withSelector(filteredSelector) - .withTreatment(filteredTreatment) - .forTable(srcMacTableId) - .makePermanent(); - rules.add(flowRuleBuilder.build()); - } - */ - - return rules; - } - - /* - * Note: CpqD switches do not handle MPLS-related operation properly - * for a packet with VLAN tag. We pop VLAN here as a workaround. - * Side effect: HostService learns redundant hosts with same MAC but - * different VLAN. No known side effect on the network reachability. - */ - protected List processEthDstFilter(EthCriterion ethCriterion, - VlanIdCriterion vlanIdCriterion, - FilteringObjective filt, - VlanId assignedVlan, - ApplicationId applicationId) { - //handling untagged packets via assigned VLAN - if (vlanIdCriterion.vlanId() == VlanId.NONE) { - vlanIdCriterion = (VlanIdCriterion) Criteria.matchVlanId(assignedVlan); - } - - List rules = new ArrayList<>(); - TrafficSelector.Builder selectorIp = DefaultTrafficSelector - .builder(); - TrafficTreatment.Builder treatmentIp = DefaultTrafficTreatment - .builder(); - selectorIp.matchEthDst(ethCriterion.mac()); - selectorIp.matchEthType(Ethernet.TYPE_IPV4); - selectorIp.matchVlanId(vlanIdCriterion.vlanId()); - treatmentIp.popVlan(); - treatmentIp.transition(ipv4UnicastTableId); - FlowRule ruleIp = DefaultFlowRule.builder().forDevice(deviceId) - .withSelector(selectorIp.build()) - .withTreatment(treatmentIp.build()) - .withPriority(filt.priority()).fromApp(applicationId) - .makePermanent().forTable(tmacTableId).build(); - log.debug("adding IP ETH rule for MAC: {}", ethCriterion.mac()); - rules.add(ruleIp); - - TrafficSelector.Builder selectorMpls = DefaultTrafficSelector - .builder(); - TrafficTreatment.Builder treatmentMpls = DefaultTrafficTreatment - .builder(); - selectorMpls.matchEthDst(ethCriterion.mac()); - selectorMpls.matchEthType(Ethernet.MPLS_UNICAST); - selectorMpls.matchVlanId(vlanIdCriterion.vlanId()); - treatmentMpls.popVlan(); - treatmentMpls.transition(mplsTableId); - FlowRule ruleMpls = DefaultFlowRule.builder() - .forDevice(deviceId).withSelector(selectorMpls.build()) - .withTreatment(treatmentMpls.build()) - .withPriority(filt.priority()).fromApp(applicationId) - .makePermanent().forTable(tmacTableId).build(); - log.debug("adding MPLS ETH rule for MAC: {}", ethCriterion.mac()); - rules.add(ruleMpls); - - return rules; - } - - protected List processVlanIdFilter(VlanIdCriterion vlanIdCriterion, - FilteringObjective filt, - VlanId assignedVlan, - ApplicationId applicationId) { - List rules = new ArrayList<>(); - log.debug("adding rule for VLAN: {}", vlanIdCriterion.vlanId()); - TrafficSelector.Builder selector = DefaultTrafficSelector - .builder(); - TrafficTreatment.Builder treatment = DefaultTrafficTreatment - .builder(); - PortCriterion p = (PortCriterion) filt.key(); - if (vlanIdCriterion.vlanId() != VlanId.NONE) { - selector.matchVlanId(vlanIdCriterion.vlanId()); - selector.matchInPort(p.port()); - treatment.deferred().popVlan(); - } else { - selector.matchInPort(p.port()); - treatment.immediate().pushVlan().setVlanId(assignedVlan); - } - treatment.transition(tmacTableId); - FlowRule rule = DefaultFlowRule.builder().forDevice(deviceId) - .withSelector(selector.build()) - .withTreatment(treatment.build()) - .withPriority(filt.priority()).fromApp(applicationId) - .makePermanent().forTable(vlanTableId).build(); - rules.add(rule); - - return rules; - } - - private void processFilter(FilteringObjective filt, boolean install, - ApplicationId applicationId) { - // This driver only processes filtering criteria defined with switch - // ports as the key - if (filt.key().equals(Criteria.dummy()) - || filt.key().type() != Criterion.Type.IN_PORT) { - log.warn("No key defined in filtering objective from app: {}. Not" - + "processing filtering objective", applicationId); - fail(filt, ObjectiveError.UNKNOWN); - return; - } - - EthCriterion ethCriterion = null; - VlanIdCriterion vlanIdCriterion = null; - - // convert filtering conditions for switch-intfs into flowrules - FlowRuleOperations.Builder ops = FlowRuleOperations.builder(); - - for (Criterion criterion : filt.conditions()) { - if (criterion.type() == Criterion.Type.ETH_DST) { - ethCriterion = (EthCriterion) criterion; - } else if (criterion.type() == Criterion.Type.VLAN_VID) { - vlanIdCriterion = (VlanIdCriterion) criterion; - } else if (criterion.type() == Criterion.Type.IPV4_DST) { - log.debug("driver does not process IP filtering rules as it " + - "sends all misses in the IP table to the controller"); - } else { - log.warn("Driver does not currently process filtering condition" - + " of type: {}", criterion.type()); - fail(filt, ObjectiveError.UNSUPPORTED); - } - } - - VlanId assignedVlan = null; - if (vlanIdCriterion != null && vlanIdCriterion.vlanId() == VlanId.NONE) { - // Assign a VLAN ID to untagged packets - if (filt.meta() == null) { - log.error("Missing metadata in filtering objective required " - + "for vlan assignment in dev {}", deviceId); - fail(filt, ObjectiveError.BADPARAMS); - return; - } - for (Instruction i : filt.meta().allInstructions()) { - if (i instanceof ModVlanIdInstruction) { - assignedVlan = ((ModVlanIdInstruction) i).vlanId(); - } - } - if (assignedVlan == null) { - log.error("Driver requires an assigned vlan-id to tag incoming " - + "untagged packets. Not processing vlan filters on " - + "device {}", deviceId); - fail(filt, ObjectiveError.BADPARAMS); - return; - } - } - - if (ethCriterion == null) { - log.debug("filtering objective missing dstMac, cannot program TMAC table"); - } else { - for (FlowRule tmacRule : processEthDstFilter(ethCriterion, - vlanIdCriterion, - filt, - assignedVlan, - applicationId)) { - log.debug("adding MAC filtering rules in TMAC table: {} for dev: {}", - tmacRule, deviceId); - ops = install ? ops.add(tmacRule) : ops.remove(tmacRule); - } - } - - if (ethCriterion == null || vlanIdCriterion == null) { - log.debug("filtering objective missing dstMac or vlan, cannot program" - + "Vlan Table"); - } else { - for (FlowRule vlanRule : processVlanIdFilter(vlanIdCriterion, - filt, - assignedVlan, - applicationId)) { - log.debug("adding VLAN filtering rule in VLAN table: {} for dev: {}", - vlanRule, deviceId); - ops = install ? ops.add(vlanRule) : ops.remove(vlanRule); - } - } - - // apply filtering flow rules - flowRuleService.apply(ops.build(new FlowRuleOperationsContext() { - @Override - public void onSuccess(FlowRuleOperations ops) { - pass(filt); - log.debug("Provisioned tables in {} with fitering " - + "rules", deviceId); - } - - @Override - public void onError(FlowRuleOperations ops) { - fail(filt, ObjectiveError.FLOWINSTALLATIONFAILED); - log.warn("Failed to provision tables in {} with " - + "fitering rules", deviceId); - } - })); - } - - protected void setTableMissEntries() { - // set all table-miss-entries - populateTableMissEntry(vlanTableId, true, false, false, -1); - populateTableMissEntry(tmacTableId, false, false, true, dstMacTableId); - populateTableMissEntry(ipv4UnicastTableId, false, true, true, aclTableId); - populateTableMissEntry(mplsTableId, false, true, true, aclTableId); - populateTableMissEntry(dstMacTableId, false, false, true, aclTableId); - populateTableMissEntry(aclTableId, false, false, false, -1); - } - - protected void populateTableMissEntry(int tableToAdd, - boolean toControllerNow, - boolean toControllerWrite, - boolean toTable, int tableToSend) { - TrafficSelector selector = DefaultTrafficSelector.builder().build(); - TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder(); - - if (toControllerNow) { - tBuilder.setOutput(PortNumber.CONTROLLER); - } - - if (toControllerWrite) { - tBuilder.deferred().setOutput(PortNumber.CONTROLLER); - } - - if (toTable) { - tBuilder.transition(tableToSend); - } - - FlowRule flow = DefaultFlowRule.builder().forDevice(deviceId) - .withSelector(selector).withTreatment(tBuilder.build()) - .withPriority(0).fromApp(appId).makePermanent() - .forTable(tableToAdd).build(); - - flowRuleService.applyFlowRules(flow); - } - - private void pass(Objective obj) { - if (obj.context().isPresent()) { - obj.context().get().onSuccess(obj); - } - } - - protected void fail(Objective obj, ObjectiveError error) { - if (obj.context().isPresent()) { - obj.context().get().onError(obj, error); - } - } - - private class InnerGroupListener implements GroupListener { - @Override - public void event(GroupEvent event) { - if (event.type() == GroupEvent.Type.GROUP_ADDED) { - log.trace("InnerGroupListener: Group ADDED " - + "event received in device {}", deviceId); - GroupKey key = event.subject().appCookie(); - - NextObjective obj = pendingGroups.getIfPresent(key); - if (obj != null) { - log.debug("Group verified: dev:{} gid:{} <<->> nextId:{}", - deviceId, event.subject().id(), obj.id()); - flowObjectiveStore - .putNextGroup(obj.id(), - new SpringOpenGroup(key, null)); - pass(obj); - pendingGroups.invalidate(key); - } - } else if (event.type() == GroupEvent.Type.GROUP_ADD_FAILED) { - log.warn("InnerGroupListener: Group ADD " - + "failed event received in device {}", deviceId); - } - } - } - - private class GroupChecker implements Runnable { - - @Override - public void run() { - Set keys = pendingGroups - .asMap() - .keySet() - .stream() - .filter(key -> groupService.getGroup(deviceId, key) != null) - .collect(Collectors.toSet()); - - keys.stream() - .forEach(key -> { - NextObjective obj = pendingGroups - .getIfPresent(key); - if (obj == null) { - return; - } - log.debug("Group verified: dev:{} gid:{} <<->> nextId:{}", - deviceId, - groupService.getGroup(deviceId, key).id(), - obj.id()); - pass(obj); - pendingGroups.invalidate(key); - flowObjectiveStore.putNextGroup( - obj.id(), - new SpringOpenGroup(key, null)); - }); - } - } - - /** - * SpringOpenGroup can either serve as storage for a GroupKey which can be - * used to fetch the group from the Group Service, or it can be serve as storage - * for Traffic Treatments which can be used as flow actions. In the latter - * case, we refer to this as a dummy group. - * - */ - private class SpringOpenGroup implements NextGroup { - private final boolean dummy; - private final GroupKey key; - private final TrafficTreatment treatment; - - /** - * Storage for a GroupKey or a TrafficTreatment. One of the params - * to this constructor must be null. - * @param key represents a GroupKey - * @param treatment represents flow actions in a dummy group - */ - public SpringOpenGroup(GroupKey key, TrafficTreatment treatment) { - if (key == null) { - this.key = new DefaultGroupKey(new byte[]{0}); - this.treatment = treatment; - this.dummy = true; - } else { - this.key = key; - this.treatment = DefaultTrafficTreatment.builder().build(); - this.dummy = false; - } - } - - @SuppressWarnings("unused") - public GroupKey key() { - return key; - } - - @Override - public byte[] data() { - return appKryo.serialize(this); - } - - } -} diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTPDell.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTPDell.java deleted file mode 100644 index 91f2679c..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTPDell.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright 2015 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. - */ -package org.onosproject.driver.pipeline; - -import java.util.Collection; -import java.util.Collections; -import java.util.List; - -import org.onlab.packet.Ethernet; -import org.onlab.packet.MacAddress; -import org.onlab.packet.VlanId; -import org.onosproject.core.ApplicationId; -import org.onosproject.net.behaviour.NextGroup; -import org.onosproject.net.flow.DefaultFlowRule; -import org.onosproject.net.flow.DefaultTrafficSelector; -import org.onosproject.net.flow.DefaultTrafficTreatment; -import org.onosproject.net.flow.FlowRule; -import org.onosproject.net.flow.TrafficSelector; -import org.onosproject.net.flow.TrafficTreatment; -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.criteria.MplsCriterion; -import org.onosproject.net.flow.criteria.VlanIdCriterion; -import org.onosproject.net.flow.instructions.Instruction; -import org.onosproject.net.flowobjective.FilteringObjective; -import org.onosproject.net.flowobjective.ForwardingObjective; -import org.onosproject.net.flowobjective.ObjectiveError; -import org.onosproject.net.group.Group; -import org.onosproject.net.group.GroupKey; - -/** - * Spring-open driver implementation for Dell hardware switches. - */ -public class SpringOpenTTPDell extends SpringOpenTTP { - - /* Table IDs to be used for Dell Open Segment Routers*/ - private static final int DELL_TABLE_VLAN = 17; - private static final int DELL_TABLE_TMAC = 18; - private static final int DELL_TABLE_IPV4_UNICAST = 30; - private static final int DELL_TABLE_MPLS = 25; - private static final int DELL_TABLE_ACL = 40; - - //TODO: Store this info in the distributed store. - private MacAddress deviceTMac = null; - - public SpringOpenTTPDell() { - super(); - vlanTableId = DELL_TABLE_VLAN; - tmacTableId = DELL_TABLE_TMAC; - ipv4UnicastTableId = DELL_TABLE_IPV4_UNICAST; - mplsTableId = DELL_TABLE_MPLS; - aclTableId = DELL_TABLE_ACL; - } - - @Override - protected void setTableMissEntries() { - // No need to set table-miss-entries in Dell switches - return; - } - - @Override - //Dell switches need ETH_DST based match condition in all IP table entries. - //So this method overrides the default spring-open behavior and adds - //ETH_DST match condition while pushing IP table flow rules - protected Collection processSpecific(ForwardingObjective fwd) { - log.debug("Processing specific"); - TrafficSelector selector = fwd.selector(); - EthTypeCriterion ethType = (EthTypeCriterion) selector - .getCriterion(Criterion.Type.ETH_TYPE); - if ((ethType == null) || - (ethType.ethType().toShort() != Ethernet.TYPE_IPV4) && - (ethType.ethType().toShort() != Ethernet.MPLS_UNICAST)) { - log.debug("processSpecific: Unsupported " - + "forwarding objective criteraia"); - fail(fwd, ObjectiveError.UNSUPPORTED); - return Collections.emptySet(); - } - - TrafficSelector.Builder filteredSelectorBuilder = - DefaultTrafficSelector.builder(); - int forTableId = -1; - if (ethType.ethType().toShort() == Ethernet.TYPE_IPV4) { - if (deviceTMac == null) { - log.debug("processSpecific: ETH_DST filtering " - + "objective is not set which is required " - + "before sending a IPv4 forwarding objective"); - //TODO: Map the error to more appropriate error code. - fail(fwd, ObjectiveError.DEVICEMISSING); - return Collections.emptySet(); - } - filteredSelectorBuilder = filteredSelectorBuilder - .matchEthType(Ethernet.TYPE_IPV4) - .matchEthDst(deviceTMac) - .matchIPDst(((IPCriterion) selector - .getCriterion(Criterion.Type.IPV4_DST)) - .ip()); - forTableId = ipv4UnicastTableId; - log.debug("processing IPv4 specific forwarding objective"); - } else { - filteredSelectorBuilder = filteredSelectorBuilder - .matchEthType(Ethernet.MPLS_UNICAST) - .matchMplsLabel(((MplsCriterion) - selector.getCriterion(Criterion.Type.MPLS_LABEL)).label()); - //TODO: Add Match for BoS - //if (selector.getCriterion(Criterion.Type.MPLS_BOS) != null) { - //} - forTableId = mplsTableId; - log.debug("processing MPLS specific forwarding objective"); - } - - TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment - .builder(); - if (fwd.treatment() != null) { - for (Instruction i : fwd.treatment().allInstructions()) { - treatmentBuilder.add(i); - } - } - - if (fwd.nextId() != null) { - NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId()); - - if (next != null) { - GroupKey key = appKryo.deserialize(next.data()); - - Group group = groupService.getGroup(deviceId, key); - - if (group == null) { - log.warn("The group left!"); - fail(fwd, ObjectiveError.GROUPMISSING); - return Collections.emptySet(); - } - treatmentBuilder.group(group.id()); - log.debug("Adding OUTGROUP action"); - } else { - log.warn("processSpecific: No associated next objective object"); - fail(fwd, ObjectiveError.GROUPMISSING); - return Collections.emptySet(); - } - } - - TrafficSelector filteredSelector = filteredSelectorBuilder.build(); - TrafficTreatment treatment = treatmentBuilder.transition(aclTableId) - .build(); - - FlowRule.Builder ruleBuilder = DefaultFlowRule.builder() - .fromApp(fwd.appId()).withPriority(fwd.priority()) - .forDevice(deviceId).withSelector(filteredSelector) - .withTreatment(treatment); - - if (fwd.permanent()) { - ruleBuilder.makePermanent(); - } else { - ruleBuilder.makeTemporary(fwd.timeout()); - } - - ruleBuilder.forTable(forTableId); - return Collections.singletonList(ruleBuilder.build()); - - } - - @Override - //Dell switches need ETH_DST based match condition in all IP table entries. - //So while processing the ETH_DST based filtering objective, store - //the device MAC to be used locally to use it while pushing the IP rules. - protected List processEthDstFilter(EthCriterion ethCriterion, - VlanIdCriterion vlanIdCriterion, - FilteringObjective filt, - VlanId assignedVlan, - ApplicationId applicationId) { - // Store device termination Mac to be used in IP flow entries - deviceTMac = ethCriterion.mac(); - - log.debug("For now not adding any TMAC rules " - + "into Dell switches as it is ignoring"); - - return Collections.emptyList(); - } - - @Override - protected List processVlanIdFilter(VlanIdCriterion vlanIdCriterion, - FilteringObjective filt, - VlanId assignedVlan, - ApplicationId applicationId) { - log.debug("For now not adding any VLAN rules " - + "into Dell switches as it is ignoring"); - - return Collections.emptyList(); - } -} \ No newline at end of file diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/package-info.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/package-info.java deleted file mode 100644 index 880acf5d..00000000 --- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/package-info.java +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2015 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. - */ - -/** - * Implementations of the pipeline driver behaviours. - */ -package org.onosproject.driver.pipeline; \ No newline at end of file -- cgit 1.2.3-korg