[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/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,