[ONOS-5070] Adds mirroring functionality.
Changes:
- Adds mirroring behaviour;
- Adds mirroring description;
- Adds mirroring name;
- Implements for Ovsdb the mirroring;
- Adds OvsdbMirror entity;
- Adds constants related to Mirror table;
- Fix one issue related to Mirror table
- Extends OvsdbClientService introducing mirroring;
- Implements mirroring functionality in DefaulOvsdbClient;
- Support for different types of device id
Change-Id: Ie291f49b3c61b7998010f555ae11deb8c021063d
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/DefaultMirroringDescription.java b/core/api/src/main/java/org/onosproject/net/behaviour/DefaultMirroringDescription.java
new file mode 100644
index 0000000..f5295a4
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/DefaultMirroringDescription.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.behaviour;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.MoreObjects;
+import org.onlab.packet.VlanId;
+import org.onosproject.net.AbstractDescription;
+import org.onosproject.net.SparseAnnotations;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Default implementation of mirroring description entity.
+ */
+@Beta
+public class DefaultMirroringDescription extends AbstractDescription
+ implements MirroringDescription {
+
+ private final MirroringName mirroringName;
+ private final List<String> monitorSrcPorts;
+ private final List<String> monitorDstPorts;
+ private final List<VlanId> monitorVlans;
+ private final Optional<String> mirrorPort;
+ private final Optional<VlanId> mirrorVlan;
+
+ /**
+ * Creates a mirroring description using the supplied information.
+ *
+ * @param name the name of the mirroring
+ * @param monitorsrcports the monitored src ports
+ * @param monitordstports the monitored dst ports
+ * @param monitorvlans the monitored vlans
+ * @param mirrorport the mirror port
+ * @param mirrorvlan the mirror vlan
+ * @param annotations optional key/value annotations
+ */
+ public DefaultMirroringDescription(MirroringName name,
+ List<String> monitorsrcports,
+ List<String> monitordstports,
+ List<VlanId> monitorvlans,
+ Optional<String> mirrorport,
+ Optional<VlanId> mirrorvlan,
+ SparseAnnotations... annotations) {
+ super(annotations);
+ this.mirroringName = name;
+ this.monitorSrcPorts = monitorsrcports;
+ this.monitorDstPorts = monitordstports;
+ this.monitorVlans = monitorvlans;
+ this.mirrorPort = mirrorport;
+ this.mirrorVlan = mirrorvlan;
+ }
+
+
+ /**
+ * Returns mirroring name.
+ *
+ * @return mirroring name
+ */
+ @Override
+ public MirroringName name() {
+ return mirroringName;
+ }
+
+ /**
+ * Returns src ports to monitor.
+ * If it is empty, then no src port has
+ * to be monitored.
+ *
+ * @return set of src ports to monitor
+ */
+ @Override
+ public List<String> monitorSrcPorts() {
+ return monitorSrcPorts;
+ }
+
+ /**
+ * Returns dst ports to monitor.
+ * If it is empty, then no dst port has
+ * to be monitored.
+ *
+ * @return set of dst ports to monitor
+ */
+ @Override
+ public List<String> monitorDstPorts() {
+ return monitorDstPorts;
+ }
+
+ /**
+ * Returns vlans to monitor.
+ * If it is empty, then no vlan has
+ * to be monitored.
+ *
+ * @return monitored vlan
+ */
+ @Override
+ public List<VlanId> monitorVlans() {
+ return monitorVlans;
+ }
+
+ /**
+ * Returns mirror port.
+ * If it is not set, then no destination
+ * port for mirrored packets.
+ *
+ * @return mirror port
+ */
+ @Override
+ public Optional<String> mirrorPort() {
+ return mirrorPort;
+ }
+
+ /**
+ * Returns mirror vlan.
+ * If it is not set the no destination
+ * vlan for mirrored packets.
+ *
+ * @return mirror vlan
+ */
+ @Override
+ public Optional<VlanId> mirrorVlan() {
+ return mirrorVlan;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("name", name())
+ .add("monitorsrcports", monitorSrcPorts())
+ .add("monitordstports", monitorDstPorts())
+ .add("monitorvlans", monitorVlans())
+ .add("mirrorport", mirrorPort())
+ .add("mirrorvlan", mirrorVlan())
+ .toString();
+ }
+}
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/MirroringConfig.java b/core/api/src/main/java/org/onosproject/net/behaviour/MirroringConfig.java
new file mode 100644
index 0000000..7b749a2d
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/MirroringConfig.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.behaviour;
+
+import com.google.common.annotations.Beta;
+import org.onosproject.net.driver.HandlerBehaviour;
+
+import java.util.Collection;
+
+/**
+ * Behaviour for handling various drivers for mirroring configurations.
+ */
+@Beta
+public interface MirroringConfig extends HandlerBehaviour {
+
+ /**
+ * Adds a mirroring with a given description.
+ *
+ * @param bridge the bridge name
+ * @param mirroringDescription mirroring description
+ * @return true if succeeds, or false
+ */
+ boolean addMirroring(BridgeName bridge, MirroringDescription mirroringDescription);
+
+ /**
+ * Removes a mirroring.
+ *
+ * @param mirroringName mirroring name
+ */
+ void deleteMirroring(MirroringName mirroringName);
+
+ /**
+ * Returns a collection of MirroringStatistics.
+ *
+ * @return statistics collection
+ */
+ Collection<MirroringStatistics> getMirroringStatistics();
+
+}
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/MirroringDescription.java b/core/api/src/main/java/org/onosproject/net/behaviour/MirroringDescription.java
new file mode 100644
index 0000000..2870314
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/MirroringDescription.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.behaviour;
+
+import com.google.common.annotations.Beta;
+import org.onlab.packet.VlanId;
+import org.onosproject.net.Annotated;
+import org.onosproject.net.Description;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * The abstraction of a mirroring. Port mirroring is a method of monitoring
+ * network traffic that forwards a copy of each incoming or outgoing packet from
+ * one port (Monitor port) on a network switch to another port (Mirror port)
+ * where the packet can be analyzed.
+ */
+@Beta
+public interface MirroringDescription extends Description, Annotated {
+
+ /**
+ * Returns mirroring name.
+ *
+ * @return mirroring name
+ */
+ MirroringName name();
+
+ /**
+ * Returns src ports to monitor.
+ * If it is empty, then no src port has
+ * to be monitored.
+ *
+ * @return set of src ports to monitor
+ */
+ List<String> monitorSrcPorts();
+
+ /**
+ * Returns dst ports to monitor.
+ * If it is empty, then no dst port has
+ * to be monitored.
+ *
+ * @return set of dst ports to monitor
+ */
+ List<String> monitorDstPorts();
+
+ /**
+ * Returns vlans to monitor.
+ * If it is empty, then no vlan has
+ * to be monitored.
+ *
+ * @return monitored vlan
+ */
+ List<VlanId> monitorVlans();
+
+ /**
+ * Returns mirror port.
+ * If it is not set, then no destination
+ * port for mirrored packets.
+ *
+ * @return mirror port
+ */
+ Optional<String> mirrorPort();
+
+ /**
+ * Returns mirror vlan.
+ * If it is not set then no destination
+ * vlan for mirrored packets.
+ *
+ * @return mirror vlan
+ */
+ Optional<VlanId> mirrorVlan();
+
+}
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/MirroringName.java b/core/api/src/main/java/org/onosproject/net/behaviour/MirroringName.java
new file mode 100644
index 0000000..82b0eb7
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/MirroringName.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.behaviour;
+
+import com.google.common.base.MoreObjects;
+
+import java.util.Objects;
+
+/**
+ * Represents for a mirroring name.
+ */
+public final class MirroringName {
+
+ private final String name;
+
+ private MirroringName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Creates a mirroring name using the supplied string.
+ *
+ * @param name mirroring name
+ * @return a port mirroring name
+ */
+ public static MirroringName mirroringName(String name) {
+ return new MirroringName(name);
+ }
+
+ /**
+ * Returns the mirroring name string.
+ *
+ * @return name string
+ */
+ public String name() {
+ return name;
+ }
+
+ @Override
+ public int hashCode() {
+ return name.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof MirroringName) {
+ final MirroringName that = (MirroringName) obj;
+ return this.getClass() == that.getClass() &&
+ Objects.equals(this.name, that.name);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("name", name)
+ .toString();
+ }
+
+}
diff --git a/core/api/src/main/java/org/onosproject/net/behaviour/MirroringStatistics.java b/core/api/src/main/java/org/onosproject/net/behaviour/MirroringStatistics.java
new file mode 100644
index 0000000..bcbaf74
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/net/behaviour/MirroringStatistics.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.net.behaviour;
+
+import com.google.common.base.MoreObjects;
+
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * Represents statistics associated to a mirroring.
+ */
+public final class MirroringStatistics {
+
+ private MirroringName mirroringName;
+ private int txBytes;
+ private int txPackets;
+
+ /**
+ * Statistics associated to a named mirroring.
+ *
+ * @param name the name of the mirroring
+ * @param bytes transmitted bytes
+ * @param packets transmitted packets
+ */
+ private MirroringStatistics(String name, int bytes, int packets) {
+ this.mirroringName = MirroringName.mirroringName(name);
+ this.txBytes = bytes;
+ this.txPackets = packets;
+ }
+
+ /**
+ *
+ * Creates a MirroringStatistics using the supplied information.
+ *
+ * @param name the name of the mirroring
+ * @param statistics the associated statistics
+ * @return the MirroringStatistics object
+ */
+ public static MirroringStatistics mirroringStatistics(String name, Map<String, Integer> statistics) {
+ return new MirroringStatistics(name, statistics.get("tx_bytes"), statistics.get("tx_packets"));
+ }
+
+ /**
+ * Returns the mirroring name string.
+ *
+ * @return name string
+ */
+ public MirroringName name() {
+ return mirroringName;
+ }
+
+ /**
+ * Returns the transmitted bytes.
+ *
+ * @return the bytes
+ */
+ public long bytes() {
+ return txBytes;
+ }
+
+ /**
+ * Returns the transmitted packtes.
+ *
+ * @return the packets
+ */
+ public long packtes() {
+ return txPackets;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name().name(), txBytes, txPackets);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof MirroringStatistics) {
+ final MirroringStatistics that = (MirroringStatistics) obj;
+ return this.getClass() == that.getClass() &&
+ Objects.equals(this.mirroringName, that.mirroringName) &&
+ Objects.equals(this.txBytes, that.txBytes) &&
+ Objects.equals(this.txPackets, that.txPackets);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("name", name())
+ .add("tx_bytes", bytes())
+ .add("tx_packets", packtes())
+ .toString();
+ }
+
+}
diff --git a/drivers/ovsdb/src/main/java/org/onosproject/drivers/ovsdb/OvsdbControllerConfig.java b/drivers/ovsdb/src/main/java/org/onosproject/drivers/ovsdb/OvsdbControllerConfig.java
index 9597169..25210a2 100644
--- a/drivers/ovsdb/src/main/java/org/onosproject/drivers/ovsdb/OvsdbControllerConfig.java
+++ b/drivers/ovsdb/src/main/java/org/onosproject/drivers/ovsdb/OvsdbControllerConfig.java
@@ -28,6 +28,7 @@
import org.onosproject.net.driver.DriverHandler;
import org.onosproject.ovsdb.controller.OvsdbBridge;
import org.onosproject.ovsdb.controller.OvsdbClientService;
+import org.onosproject.ovsdb.controller.OvsdbConstant;
import org.onosproject.ovsdb.controller.OvsdbController;
import org.onosproject.ovsdb.controller.OvsdbNodeId;
@@ -83,7 +84,7 @@
if (nodeIds.size() == 0) {
//TODO decide what port?
ovsController.connect(IpAddress.valueOf(targetIp),
- targetPort == null ? TpPort.tpPort(6640) : targetPort);
+ targetPort == null ? TpPort.tpPort(OvsdbConstant.OVSDBPORT) : targetPort);
delay(1000); //FIXME... connect is async
}
List<OvsdbClientService> clientServices = ovsController.getNodeIds().stream()
diff --git a/drivers/ovsdb/src/main/java/org/onosproject/drivers/ovsdb/OvsdbMirroringConfig.java b/drivers/ovsdb/src/main/java/org/onosproject/drivers/ovsdb/OvsdbMirroringConfig.java
new file mode 100644
index 0000000..9a1896e
--- /dev/null
+++ b/drivers/ovsdb/src/main/java/org/onosproject/drivers/ovsdb/OvsdbMirroringConfig.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.drivers.ovsdb;
+
+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.BridgeName;
+import org.onosproject.net.behaviour.MirroringConfig;
+import org.onosproject.net.behaviour.MirroringDescription;
+import org.onosproject.net.behaviour.MirroringStatistics;
+import org.onosproject.net.behaviour.MirroringName;
+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.OvsdbConstant;
+import org.onosproject.ovsdb.controller.OvsdbController;
+import org.onosproject.ovsdb.controller.OvsdbMirror;
+import org.onosproject.ovsdb.controller.OvsdbNodeId;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkState;
+import static org.onlab.util.Tools.delay;
+
+/**
+ * Implementation of mirror config which allows to add, delete and get mirrorings statistics.
+ */
+public class OvsdbMirroringConfig extends AbstractHandlerBehaviour implements MirroringConfig {
+
+ private static Logger log = LoggerFactory.getLogger(OvsdbMirroringConfig.class);
+
+ /**
+ * Adds a mirroring with a given description.
+ *
+ * @param bridge the bridge name
+ * @param mirroringDescription mirroring description
+ * @return true if succeeds, or false
+ */
+ @Override
+ public boolean addMirroring(BridgeName bridge, MirroringDescription mirroringDescription) {
+ DriverHandler handler = handler();
+ OvsdbClientService ovsdbClient = getOvsdbClientService(handler);
+ OvsdbMirror mirror = OvsdbMirror.builder(mirroringDescription).build();
+ return ovsdbClient.createMirror(bridge.name(), mirror);
+ }
+
+ /**
+ * Removes a mirroring.
+ *
+ * @param mirroringName mirroring name
+ */
+ @Override
+ public void deleteMirroring(MirroringName mirroringName) {
+ DriverHandler handler = handler();
+ OvsdbClientService ovsdbClient = getOvsdbClientService(handler);
+ ovsdbClient.dropMirror(mirroringName);
+ }
+
+ /**
+ * Returns a collection of MirroringStatistics.
+ *
+ * @return statistics collection
+ */
+ @Override
+ public Collection<MirroringStatistics> getMirroringStatistics() {
+ DriverHandler handler = handler();
+ OvsdbClientService ovsdbClient = getOvsdbClientService(handler);
+ return ovsdbClient.getMirroringStatistics(handler.data().deviceId());
+ }
+
+ /**
+ * Helper method which is used for getting OvsdbClientService.
+ */
+ private OvsdbClientService getOvsdbClientService(DriverHandler handler) {
+
+ OvsdbController ovsController = handler.get(OvsdbController.class);
+ DeviceService deviceService = handler.get(DeviceService.class);
+ DeviceId deviceId = handler.data().deviceId();
+
+ String[] splits = deviceId.toString().split(":");
+ if (splits == null || splits.length < 1) {
+ log.warn("Wrong deviceId format");
+ return null;
+ }
+
+ /**
+ * Each type of device has to be managed in a different way.
+ */
+ switch (splits[0]) {
+ case "ovsdb":
+ OvsdbNodeId nodeId = changeDeviceIdToNodeId(deviceId);
+ return ovsController.getOvsdbClient(nodeId);
+ case "of":
+ String[] mgmtAddress = deviceService.getDevice(deviceId)
+ .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<OvsdbNodeId> 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(OvsdbConstant.OVSDBPORT) : targetPort);
+ delay(1000); //FIXME... connect is async
+ }
+ List<OvsdbClientService> clientServices = ovsController.getNodeIds().stream()
+ .filter(nodeID -> nodeID.getIpAddress().equals(targetIp))
+ .map(ovsController::getOvsdbClient)
+ .filter(cs -> cs.getBridges().stream().anyMatch(b -> dpidMatches(b, deviceId)))
+ .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;
+ default:
+ log.warn("Unmanaged device type");
+ }
+ return null;
+
+ }
+
+ private static boolean dpidMatches(OvsdbBridge bridge, DeviceId deviceId) {
+ checkArgument(bridge.datapathId().isPresent());
+
+ String bridgeDpid = "of:" + bridge.datapathId().get();
+ String ofDpid = deviceId.toString();
+ return bridgeDpid.equals(ofDpid);
+ }
+
+ /**
+ * OvsdbNodeId(IP) is used in the adaptor while DeviceId(ovsdb:IP)
+ * is used in the core. So DeviceId need be changed to OvsdbNodeId.
+ *
+ * @param deviceId the device id in ovsdb:ip format
+ * @return the ovsdb node id
+ */
+ 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);
+ }
+
+}
diff --git a/drivers/ovsdb/src/main/resources/ovsdb-drivers.xml b/drivers/ovsdb/src/main/resources/ovsdb-drivers.xml
index 9e88ba9..15d7d5f 100644
--- a/drivers/ovsdb/src/main/resources/ovsdb-drivers.xml
+++ b/drivers/ovsdb/src/main/resources/ovsdb-drivers.xml
@@ -28,6 +28,8 @@
manufacturer="Nicira, Inc\." hwVersion="Open vSwitch" swVersion="2\..*">
<behaviour api="org.onosproject.net.behaviour.ControllerConfig"
impl="org.onosproject.drivers.ovsdb.OvsdbControllerConfig"/>
+ <behaviour api="org.onosproject.net.behaviour.MirroringConfig"
+ impl="org.onosproject.drivers.ovsdb.OvsdbMirroringConfig"/>
</driver>
</drivers>
diff --git a/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbClientService.java b/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbClientService.java
index 5a0676b..a5ba5a3 100644
--- a/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbClientService.java
+++ b/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbClientService.java
@@ -19,6 +19,8 @@
import org.onlab.packet.IpAddress;
import org.onosproject.net.DeviceId;
import org.onosproject.net.behaviour.ControllerInfo;
+import org.onosproject.net.behaviour.MirroringStatistics;
+import org.onosproject.net.behaviour.MirroringName;
import org.onosproject.ovsdb.rfc.jsonrpc.OvsdbRpc;
import org.onosproject.ovsdb.rfc.message.TableUpdates;
import org.onosproject.ovsdb.rfc.notation.Row;
@@ -40,6 +42,41 @@
OvsdbNodeId nodeId();
/**
+ * Creates a mirror port. Mirrors the traffic
+ * that goes to selectDstPort or comes from
+ * selectSrcPort or packets containing selectVlan
+ * to mirrorPort or to all ports that trunk mirrorVlan.
+ *
+ * @param bridgeName the name of the bridge
+ * @param mirror the OVSDB mirror description
+ * @return true if mirror creation is successful, false otherwise
+ */
+ boolean createMirror(String bridgeName, OvsdbMirror mirror);
+
+ /**
+ * Gets the Mirror uuid.
+ *
+ * @param mirrorName mirror name
+ * @return mirror uuid, empty if no uuid is found
+ */
+ String getMirrorUuid(String mirrorName);
+
+ /**
+ * Gets mirroring statistics of the device.
+ *
+ * @param deviceId target device id
+ * @return set of mirroring statistics; empty if no mirror is found
+ */
+ Set<MirroringStatistics> getMirroringStatistics(DeviceId deviceId);
+
+ /**
+ * Drops the configuration for mirror.
+ *
+ * @param mirroringName
+ */
+ void dropMirror(MirroringName mirroringName);
+
+ /**
* Creates a tunnel port with given options.
*
* @deprecated version 1.7.0 - Hummingbird
diff --git a/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbConstant.java b/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbConstant.java
index 6562384..aea0845 100644
--- a/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbConstant.java
+++ b/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbConstant.java
@@ -41,6 +41,7 @@
/** Bridge table. */
public static final String BRIDGE = "Bridge";
public static final String PORTS = "ports";
+ public static final String MIRRORS = "mirrors";
// other configs
public static final String DATAPATH_ID = "datapath-id";
public static final String DISABLE_INBAND = "disable-in-band";
@@ -66,6 +67,9 @@
/** Controller table. */
public static final String CONTROLLER = "Controller";
+ /** Mirror table. */
+ public static final String MIRROR = "Mirror";
+
/** Ovsdb bridge name. */
// TODO remove this particular bridge name from OVSDB provider
public static final String INTEGRATION_BRIDGE = "br-int";
diff --git a/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbMirror.java b/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbMirror.java
new file mode 100644
index 0000000..1fbe5cb
--- /dev/null
+++ b/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/OvsdbMirror.java
@@ -0,0 +1,363 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.ovsdb.controller;
+
+import com.google.common.collect.Maps;
+import org.onosproject.net.DefaultAnnotations;
+import org.onosproject.net.behaviour.MirroringDescription;
+import org.onosproject.ovsdb.rfc.notation.Uuid;
+
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+/**
+ * The class representing an OVSDB mirror.
+ * This class is immutable.
+ */
+public final class OvsdbMirror {
+
+ private final String mirroringName;
+ private boolean selectAll;
+ private final Set<Uuid> monitorSrcPorts;
+ private final Set<Uuid> monitorDstPorts;
+ private final Set<Short> monitorVlans;
+ private final Optional<Uuid> mirrorPort;
+ private final Optional<Short> mirrorVlan;
+ private Map<String, String> externalIds;
+
+ /**
+ * Creates an OvsdbMirror using the given inputs.
+ *
+ * @param mirroringName the name of the mirroring
+ * @param selectAll mirrors all ports
+ * @param monitorSrcPorts the monitored src ports
+ * @param monitorDstPorts the monitored dst ports
+ * @param monitorVlans the monitored vlans
+ * @param mirrorPort the mirror port
+ * @param mirrorVlan the mirror vlan
+ * @param externalIds optional key/value options
+ */
+ private OvsdbMirror(String mirroringName, boolean selectAll, Set<Uuid> monitorSrcPorts, Set<Uuid> monitorDstPorts,
+ Set<Short> monitorVlans, Optional<Uuid> mirrorPort, Optional<Short> mirrorVlan,
+ Map<String, String> externalIds) {
+
+ this.mirroringName = mirroringName;
+ this.selectAll = selectAll;
+ this.monitorSrcPorts = monitorSrcPorts;
+ this.monitorDstPorts = monitorDstPorts;
+ this.monitorVlans = monitorVlans;
+ this.mirrorPort = mirrorPort;
+ this.mirrorVlan = mirrorVlan;
+ this.externalIds = externalIds;
+
+ }
+
+ /**
+ * Returns the name of the mirroring.
+ *
+ * @return the string representing the name
+ */
+ public String mirroringName() {
+ return mirroringName;
+ }
+
+ /**
+ * Returns selectAll value.
+ *
+ * @return mirrors all ports if true
+ */
+ public boolean selectAll() {
+ return selectAll;
+ }
+
+ /**
+ * Returns the monitored src ports.
+ *
+ * @return the uuids set of the ports
+ */
+ public Set<Uuid> monitorSrcPorts() {
+ return monitorSrcPorts;
+ }
+
+ /**
+ * Returns the monitored dst ports.
+ *
+ * @return the uuids set of the ports
+ */
+ public Set<Uuid> monitorDstPorts() {
+ return monitorDstPorts;
+ }
+
+ /**
+ * Returns the monitored vlans.
+ *
+ * @return the vlans set
+ */
+ public Set<Short> monitorVlans() {
+ return monitorVlans;
+ }
+
+ /**
+ * Returns the mirror port.
+ *
+ * @return the uuid port if present, otherwise null
+ */
+ public Uuid mirrorPort() {
+ return mirrorPort.orElse(null);
+ }
+
+ /**
+ * Returns the mirror vlan.
+ *
+ * @return the vlan id if present, otherwise null
+ */
+ public Short mirrorVlan() {
+ return mirrorVlan.orElse(null);
+ }
+
+ /**
+ * Returns the optional external ids.
+ *
+ * @return the external ids.
+ */
+ public Map<String, String> externalIds() {
+ return externalIds;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mirroringName, selectAll, monitorSrcPorts, monitorDstPorts,
+ monitorVlans, mirrorPort, mirrorVlan, externalIds);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof OvsdbMirror) {
+ final OvsdbMirror other = (OvsdbMirror) obj;
+ return Objects.equals(this.mirroringName, other.mirroringName) &&
+ Objects.equals(this.selectAll, other.selectAll) &&
+ Objects.equals(this.monitorSrcPorts, other.monitorSrcPorts) &&
+ Objects.equals(this.monitorDstPorts, other.monitorDstPorts) &&
+ Objects.equals(this.monitorVlans, other.monitorVlans) &&
+ Objects.equals(this.mirrorPort, other.mirrorPort) &&
+ Objects.equals(this.mirrorVlan, other.mirrorVlan) &&
+ Objects.equals(this.externalIds, other.externalIds);
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("mirroringName", mirroringName())
+ .add("selectAll", selectAll())
+ .add("monitorSrcPorts", monitorSrcPorts())
+ .add("monitorDstPorts", monitorDstPorts())
+ .add("monitorVlans", monitorVlans())
+ .add("mirrorPort", mirrorPort())
+ .add("mirrorVlan", mirrorVlan())
+ .add("externalIds", externalIds())
+ .toString();
+ }
+
+ /**
+ * Returns new OVSDB mirror builder.
+ *
+ * @return ovsdb mirror builder
+ */
+ public static OvsdbMirror.Builder builder() {
+ return new OvsdbMirror.Builder();
+ }
+
+ /**
+ * Returns new OVSDB mirror builder with mirror description.
+ *
+ * @param mirrorDesc mirror description
+ * @return ovsdb mirror builder
+ */
+ public static OvsdbMirror.Builder builder(MirroringDescription mirrorDesc) {
+ return new OvsdbMirror.Builder(mirrorDesc);
+ }
+
+ /**
+ * Builder of OVSDB mirror entities.
+ */
+ public static final class Builder {
+
+ private String mirroringName;
+ private boolean selectAll;
+ private Set<Uuid> monitorSrcPorts;
+ private Set<Uuid> monitorDstPorts;
+ private Set<Short> monitorVlans;
+ private Optional<Uuid> mirrorPort;
+ private Optional<Short> mirrorVlan;
+ private Map<String, String> externalIds = Maps.newHashMap();
+
+ /**
+ * Constructs an empty builder.
+ */
+ private Builder() {
+
+ }
+
+ /**
+ * Constructs a builder with a given mirror description.
+ *
+ * @param mirrorDesc mirror description
+ */
+ private Builder(MirroringDescription mirrorDesc) {
+
+ mirroringName = mirrorDesc.name().name();
+ selectAll = false;
+ monitorSrcPorts = mirrorDesc.monitorSrcPorts().parallelStream()
+ .map(monitorSrcPort -> Uuid.uuid(monitorSrcPort))
+ .collect(Collectors.toSet());
+ monitorDstPorts = mirrorDesc.monitorDstPorts().parallelStream()
+ .map(monitorDstPort -> Uuid.uuid(monitorDstPort))
+ .collect(Collectors.toSet());
+ monitorVlans = mirrorDesc.monitorVlans().parallelStream()
+ .map(monitorVlan -> monitorVlan.toShort())
+ .collect(Collectors.toSet());
+
+ if (mirrorDesc.mirrorPort().isPresent()) {
+ mirrorPort = Optional.of(Uuid.uuid(mirrorDesc.mirrorPort().get()));
+ } else {
+ mirrorPort = Optional.empty();
+ }
+
+ if (mirrorDesc.mirrorVlan().isPresent()) {
+ mirrorVlan = Optional.of(mirrorDesc.mirrorVlan().get().toShort());
+ } else {
+ mirrorVlan = Optional.empty();
+ }
+
+ externalIds.putAll(((DefaultAnnotations) mirrorDesc.annotations()).asMap());
+
+ }
+
+ /**
+ * Returns new OVSDB mirror.
+ *
+ * @return ovsdb mirror
+ */
+ public OvsdbMirror build() {
+ return new OvsdbMirror(mirroringName, selectAll, monitorSrcPorts, monitorDstPorts, monitorVlans,
+ mirrorPort, mirrorVlan, externalIds);
+ }
+
+ /**
+ * Returns OVSDB mirror builder with a given name.
+ *
+ * @param name name of the mirror
+ * @return ovsdb interface builder
+ */
+ public OvsdbMirror.Builder mirroringName(String name) {
+ this.mirroringName = name;
+ return this;
+ }
+
+ /**
+ * Returns OVSDB mirror builder with select all.
+ *
+ * @param all mirrors all ports
+ * @return ovsdb interface builder
+ */
+ public OvsdbMirror.Builder selectAll(boolean all) {
+ this.selectAll = all;
+ return this;
+ }
+
+ /**
+ * Returns OVSDB mirror builder with a given set
+ * of monitored src ports.
+ *
+ * @param monitorPorts ports to be monitored
+ * @return ovsdb mirror builder
+ */
+ public OvsdbMirror.Builder monitorSrcPorts(Set<Uuid> monitorPorts) {
+ this.monitorSrcPorts = monitorPorts;
+ return this;
+ }
+
+ /**
+ * Returns OVSDB mirror builder with a given set
+ * of monitored dst ports.
+ *
+ * @param monitorPorts ports to be monitored
+ * @return ovsdb mirror builder
+ */
+ public OvsdbMirror.Builder monitorDstPorts(Set<Uuid> monitorPorts) {
+ this.monitorDstPorts = monitorPorts;
+ return this;
+ }
+
+ /**
+ * Returns OVSDB mirror builder with a given set
+ * of monitored vlans.
+ *
+ * @param vlans vlans to be monitored
+ * @return ovsdb mirror builder
+ */
+ public OvsdbMirror.Builder monitorVlans(Set<Short> vlans) {
+ this.monitorVlans = vlans;
+ return this;
+ }
+
+ /**
+ * Returns OVSDB mirror builder with a given mirror port.
+ *
+ * @param port the mirror port
+ * @return ovsdb mirror builder
+ */
+ public OvsdbMirror.Builder mirrorPort(Uuid port) {
+ this.mirrorPort = Optional.ofNullable(port);
+ return this;
+ }
+
+ /**
+ * Returns OVSDB mirror builder with a given mirror vlan.
+ *
+ * @param vlan the mirror vlan
+ * @return ovsdb mirror builder
+ */
+ public OvsdbMirror.Builder mirrorVlan(Short vlan) {
+ this.mirrorVlan = Optional.ofNullable(vlan);
+ return this;
+ }
+
+ /**
+ * Returns OVSDB mirror builder with given external ids.
+ *
+ * @param ids the external ids
+ * @return ovsdb mirror builder
+ */
+ public OvsdbMirror.Builder externalIds(Map<String, String> ids) {
+ this.externalIds = ids;
+ return this;
+ }
+
+ }
+
+}
diff --git a/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java b/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java
index 26904d5..635f1a1 100644
--- a/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java
+++ b/protocols/ovsdb/api/src/main/java/org/onosproject/ovsdb/controller/driver/DefaultOvsdbClient.java
@@ -17,6 +17,8 @@
import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.base.Function;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
@@ -30,10 +32,13 @@
import org.onosproject.net.DeviceId;
import org.onosproject.net.behaviour.BridgeDescription;
import org.onosproject.net.behaviour.ControllerInfo;
+import org.onosproject.net.behaviour.MirroringStatistics;
+import org.onosproject.net.behaviour.MirroringName;
import org.onosproject.ovsdb.controller.OvsdbBridge;
import org.onosproject.ovsdb.controller.OvsdbClientService;
import org.onosproject.ovsdb.controller.OvsdbInterface;
import org.onosproject.ovsdb.controller.OvsdbInterface.Type;
+import org.onosproject.ovsdb.controller.OvsdbMirror;
import org.onosproject.ovsdb.controller.OvsdbNodeId;
import org.onosproject.ovsdb.controller.OvsdbPort;
import org.onosproject.ovsdb.controller.OvsdbPortName;
@@ -41,6 +46,7 @@
import org.onosproject.ovsdb.controller.OvsdbRowStore;
import org.onosproject.ovsdb.controller.OvsdbStore;
import org.onosproject.ovsdb.controller.OvsdbTableStore;
+
import org.onosproject.ovsdb.rfc.jsonrpc.Callback;
import org.onosproject.ovsdb.rfc.message.OperationResult;
import org.onosproject.ovsdb.rfc.message.TableUpdates;
@@ -61,6 +67,7 @@
import org.onosproject.ovsdb.rfc.table.Bridge;
import org.onosproject.ovsdb.rfc.table.Controller;
import org.onosproject.ovsdb.rfc.table.Interface;
+import org.onosproject.ovsdb.rfc.table.Mirror;
import org.onosproject.ovsdb.rfc.table.OvsdbTable;
import org.onosproject.ovsdb.rfc.table.Port;
import org.onosproject.ovsdb.rfc.table.TableGenerator;
@@ -73,10 +80,12 @@
import java.net.InetSocketAddress;
import java.util.ArrayList;
+
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
@@ -104,6 +113,7 @@
private final Map<String, SettableFuture<? extends Object>> requestResult = Maps.newHashMap();
private final Map<String, DatabaseSchema> schema = Maps.newHashMap();
+
/**
* Creates an OvsdbClient.
*
@@ -234,6 +244,107 @@
ovsdbStore.createOrUpdateOvsdbStore(dbName, tableStore);
}
+ /**
+ * Gets the Mirror uuid.
+ *
+ * @param mirrorName mirror name
+ * @return mirror uuid, empty if no uuid is found
+ */
+ @Override
+ public String getMirrorUuid(String mirrorName) {
+ DatabaseSchema dbSchema = schema.get(DATABASENAME);
+ OvsdbRowStore rowStore = getRowStore(DATABASENAME, MIRROR);
+ if (rowStore == null) {
+ log.warn("The mirror uuid is null");
+ return null;
+ }
+
+ ConcurrentMap<String, Row> mirrorTableRows = rowStore.getRowStore();
+ if (mirrorTableRows == null) {
+ log.warn("The mirror uuid is null");
+ return null;
+ }
+
+ for (String uuid : mirrorTableRows.keySet()) {
+ Mirror mirror = (Mirror) TableGenerator
+ .getTable(dbSchema, mirrorTableRows.get(uuid), OvsdbTable.MIRROR);
+ String name = mirror.getName();
+ if (name.contains(mirrorName)) {
+ return uuid;
+ }
+ }
+ log.warn("Mirroring not found");
+ return null;
+ }
+
+ /**
+ * Gets mirrors of the device.
+ *
+ * @param deviceId target device id
+ * @return set of mirroring; empty if no mirror is found
+ */
+ @Override
+ public Set<MirroringStatistics> getMirroringStatistics(DeviceId deviceId) {
+ Uuid bridgeUuid = getBridgeUuid(deviceId);
+ if (bridgeUuid == null) {
+ log.warn("Couldn't find bridge {} in {}", deviceId, nodeId.getIpAddress());
+ return null;
+ }
+
+ List<MirroringStatistics> mirrorings = getMirrorings(bridgeUuid);
+ if (mirrorings == null) {
+ log.warn("Couldn't find mirrors in {}", nodeId.getIpAddress());
+ return null;
+ }
+ return ImmutableSet.copyOf(mirrorings);
+ }
+
+ /**
+ * Helper method which retrieves mirrorings statistics using bridge uuid.
+ *
+ * @param bridgeUuid the uuid of the bridge
+ * @return the list of the mirrorings statistics.
+ */
+ private List<MirroringStatistics> getMirrorings(Uuid bridgeUuid) {
+ DatabaseSchema dbSchema = schema.get(DATABASENAME);
+ if (dbSchema == null) {
+ log.warn("Unable to retrieve dbSchema {}", DATABASENAME);
+ return null;
+ }
+ OvsdbRowStore rowStore = getRowStore(DATABASENAME, BRIDGE);
+ if (rowStore == null) {
+ log.warn("Unable to retrieve rowStore {} of {}", BRIDGE, DATABASENAME);
+ return null;
+ }
+
+ Row bridgeRow = rowStore.getRow(bridgeUuid.value());
+ Bridge bridge = (Bridge) TableGenerator.
+ getTable(dbSchema, bridgeRow, OvsdbTable.BRIDGE);
+
+ Set<Uuid> mirroringsUuids = (Set<Uuid>) ((OvsdbSet) bridge
+ .getMirrorsColumn().data()).set();
+
+ OvsdbRowStore mirrorRowStore = getRowStore(DATABASENAME, MIRROR);
+ if (mirrorRowStore == null) {
+ log.warn("Unable to retrieve rowStore {} of {}", MIRROR, DATABASENAME);
+ return null;
+ }
+
+ List<MirroringStatistics> mirroringStatistics = new ArrayList<>();
+ ConcurrentMap<String, Row> mirrorTableRows = mirrorRowStore.getRowStore();
+ mirrorTableRows.forEach((key, row) -> {
+ if (!mirroringsUuids.contains(Uuid.uuid(key))) {
+ return;
+ }
+ Mirror mirror = (Mirror) TableGenerator
+ .getTable(dbSchema, row, OvsdbTable.MIRROR);
+ mirroringStatistics.add(MirroringStatistics.mirroringStatistics(mirror.getName(),
+ (Map<String, Integer>) ((OvsdbMap) mirror
+ .getStatisticsColumn().data()).map()));
+ });
+ return ImmutableList.copyOf(mirroringStatistics);
+ }
+
@Override
public String getPortUuid(String portName, String bridgeUuid) {
DatabaseSchema dbSchema = schema.get(DATABASENAME);
@@ -502,6 +613,142 @@
deleteConfig(BRIDGE, UUID, bridgeUuid, DATABASENAME, BRIDGES);
}
+ /**
+ * Creates a mirror port. Mirrors the traffic
+ * that goes to selectDstPort or comes from
+ * selectSrcPort or packets containing selectVlan
+ * to mirrorPort or to all ports that trunk mirrorVlan.
+ *
+ * @param mirror the OVSDB mirror description
+ * @return true if mirror creation is successful, false otherwise
+ */
+ @Override
+ public boolean createMirror(String bridgeName, OvsdbMirror mirror) {
+
+ /**
+ * Retrieves bridge's uuid. It is necessary to update
+ * Bridge table.
+ */
+ String bridgeUuid = getBridgeUuid(bridgeName);
+ if (bridgeUuid == null) {
+ log.warn("Couldn't find bridge {} in {}", bridgeName, nodeId.getIpAddress());
+ return false;
+ }
+
+ OvsdbMirror.Builder mirrorBuilder = OvsdbMirror.builder();
+
+ mirrorBuilder.mirroringName(mirror.mirroringName());
+ mirrorBuilder.selectAll(mirror.selectAll());
+
+ /**
+ * Retrieves the uuid of the monitored dst ports.
+ */
+ mirrorBuilder.monitorDstPorts(mirror.monitorDstPorts().parallelStream()
+ .map(dstPort -> {
+ String dstPortUuid = getPortUuid(dstPort.value(), bridgeUuid);
+ if (dstPortUuid != null) {
+ return Uuid.uuid(dstPortUuid);
+ }
+ log.warn("Couldn't find port {} in {}",
+ dstPort.value(), nodeId.getIpAddress());
+ return null;
+ })
+ .filter(Objects::nonNull)
+ .collect(Collectors.toSet())
+ );
+
+ /**
+ * Retrieves the uuid of the monitored src ports.
+ */
+ mirrorBuilder.monitorSrcPorts(mirror.monitorSrcPorts().parallelStream()
+ .map(srcPort -> {
+ String srcPortUuid = getPortUuid(srcPort.value(), bridgeUuid);
+ if (srcPortUuid != null) {
+ return Uuid.uuid(srcPortUuid);
+ }
+ log.warn("Couldn't find port {} in {}",
+ srcPort.value(), nodeId.getIpAddress());
+ return null;
+ }).filter(Objects::nonNull)
+ .collect(Collectors.toSet())
+ );
+
+ mirrorBuilder.monitorVlans(mirror.monitorVlans());
+ mirrorBuilder.mirrorPort(mirror.mirrorPort());
+ mirrorBuilder.mirrorVlan(mirror.mirrorVlan());
+ mirrorBuilder.externalIds(mirror.externalIds());
+ mirror = mirrorBuilder.build();
+
+ if (mirror.monitorDstPorts().size() == 0 &&
+ mirror.monitorSrcPorts().size() == 0 &&
+ mirror.monitorVlans().size() == 0) {
+ log.warn("Invalid monitoring data");
+ return false;
+ }
+
+ DatabaseSchema dbSchema = schema.get(DATABASENAME);
+
+ Mirror mirrorEntry = (Mirror) TableGenerator.createTable(dbSchema, OvsdbTable.MIRROR);
+ mirrorEntry.setName(mirror.mirroringName());
+ mirrorEntry.setSelectDstPort(mirror.monitorDstPorts());
+ mirrorEntry.setSelectSrcPort(mirror.monitorSrcPorts());
+ mirrorEntry.setSelectVlan(mirror.monitorVlans());
+ mirrorEntry.setExternalIds(mirror.externalIds());
+
+ /**
+ * If mirror port, retrieves the uuid of the mirror port.
+ */
+ if (mirror.mirrorPort() != null) {
+
+ String outputPortUuid = getPortUuid(mirror.mirrorPort().value(), bridgeUuid);
+ if (outputPortUuid == null) {
+ log.warn("Couldn't find port {} in {}", mirror.mirrorPort().value(), nodeId.getIpAddress());
+ return false;
+ }
+
+ mirrorEntry.setOutputPort(Uuid.uuid(outputPortUuid));
+
+ } else if (mirror.mirrorVlan() != null) {
+
+ mirrorEntry.setOutputVlan(mirror.mirrorVlan());
+
+ } else {
+ log.warn("Invalid mirror, no mirror port and no mirror vlan");
+ return false;
+ }
+
+ ArrayList<Operation> operations = Lists.newArrayList();
+ Insert mirrorInsert = new Insert(dbSchema.getTableSchema("Mirror"), "Mirror", mirrorEntry.getRow());
+ operations.add(mirrorInsert);
+
+ // update the bridge table
+ Condition condition = ConditionUtil.isEqual(UUID, Uuid.uuid(bridgeUuid));
+ Mutation mutation = MutationUtil.insert(MIRRORS, Uuid.uuid("Mirror"));
+ List<Condition> conditions = Lists.newArrayList(condition);
+ List<Mutation> mutations = Lists.newArrayList(mutation);
+ operations.add(new Mutate(dbSchema.getTableSchema("Bridge"), conditions, mutations));
+
+ transactConfig(DATABASENAME, operations);
+ log.info("Created mirror {}", mirror.mirroringName());
+ return true;
+ }
+
+ /**
+ * Drops the configuration for mirror.
+ *
+ * @param mirroringName
+ */
+ @Override
+ public void dropMirror(MirroringName mirroringName) {
+ String mirrorUuid = getMirrorUuid(mirroringName.name());
+ if (mirrorUuid != null) {
+ log.info("Deleted mirror {}", mirroringName.name());
+ deleteConfig(MIRROR, UUID, mirrorUuid, BRIDGE, MIRRORS);
+ }
+ log.warn("Unable to delete {}", mirroringName.name());
+ return;
+ }
+
@Deprecated
@Override
public boolean createTunnel(String bridgeName, String ifaceName, String tunnelType,
diff --git a/protocols/ovsdb/api/src/test/java/org/onosproject/ovsdb/controller/driver/OvsdbClientServiceAdapter.java b/protocols/ovsdb/api/src/test/java/org/onosproject/ovsdb/controller/driver/OvsdbClientServiceAdapter.java
index 8601185..e4cad7d 100644
--- a/protocols/ovsdb/api/src/test/java/org/onosproject/ovsdb/controller/driver/OvsdbClientServiceAdapter.java
+++ b/protocols/ovsdb/api/src/test/java/org/onosproject/ovsdb/controller/driver/OvsdbClientServiceAdapter.java
@@ -22,9 +22,12 @@
import org.onlab.packet.IpAddress;
import org.onosproject.net.DeviceId;
import org.onosproject.net.behaviour.ControllerInfo;
+import org.onosproject.net.behaviour.MirroringStatistics;
+import org.onosproject.net.behaviour.MirroringName;
import org.onosproject.ovsdb.controller.OvsdbBridge;
import org.onosproject.ovsdb.controller.OvsdbClientService;
import org.onosproject.ovsdb.controller.OvsdbInterface;
+import org.onosproject.ovsdb.controller.OvsdbMirror;
import org.onosproject.ovsdb.controller.OvsdbNodeId;
import org.onosproject.ovsdb.controller.OvsdbPort;
import org.onosproject.ovsdb.rfc.message.TableUpdates;
@@ -46,6 +49,54 @@
return null;
}
+ /**
+ * Creates a mirror port. Mirrors the traffic
+ * that goes to selectDstPort or comes from
+ * selectSrcPort or packets containing selectVlan
+ * to mirrorPort or to all ports that trunk mirrorVlan.
+ *
+ * @param bridgeName the name of the bridge
+ * @param mirror the OVSDB mirror description
+ * @return true if mirror creation is successful, false otherwise
+ */
+ @Override
+ public boolean createMirror(String bridgeName, OvsdbMirror mirror) {
+ return true;
+ }
+
+ /**
+ * Gets the Mirror uuid.
+ *
+ * @param mirrorName mirror name
+ * @return mirror uuid, empty if no uuid is found
+ */
+ @Override
+ public String getMirrorUuid(String mirrorName) {
+ return null;
+ }
+
+ /**
+ * Gets mirroring statistics of the device.
+ *
+ * @param deviceId target device id
+ * @return set of mirroring statistics; empty if no mirror is found
+ */
+ @Override
+ public Set<MirroringStatistics> getMirroringStatistics(DeviceId deviceId) {
+ return null;
+ }
+
+
+ /**
+ * Drops the configuration for mirror.
+ *
+ * @param mirroringName
+ */
+ @Override
+ public void dropMirror(MirroringName mirroringName) {
+
+ }
+
@Override
public boolean createTunnel(String bridgeName, String portName, String tunnelType, Map<String, String> options) {
return true;
diff --git a/protocols/ovsdb/rfc/src/main/java/org/onosproject/ovsdb/rfc/table/Mirror.java b/protocols/ovsdb/rfc/src/main/java/org/onosproject/ovsdb/rfc/table/Mirror.java
index 23eef59..5740f84 100644
--- a/protocols/ovsdb/rfc/src/main/java/org/onosproject/ovsdb/rfc/table/Mirror.java
+++ b/protocols/ovsdb/rfc/src/main/java/org/onosproject/ovsdb/rfc/table/Mirror.java
@@ -203,7 +203,7 @@
* of attributes.
* @param outputVlan the column data which column name is "output_vlan"
*/
- public void setOutputVlan(Set<Short> outputVlan) {
+ public void setOutputVlan(Short outputVlan) {
ColumnDescription columndesc = new ColumnDescription(MirrorColumn.OUTPUTVLAN.columnName(),
"setOutputVlan", VersionNum.VERSION100);
super.setDataHandler(columndesc, outputVlan);