Pier Ventre
Committed by Gerrit Code Review

[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
1 +/*
2 + * Copyright 2016-present Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +package org.onosproject.net.behaviour;
18 +
19 +import com.google.common.annotations.Beta;
20 +import com.google.common.base.MoreObjects;
21 +import org.onlab.packet.VlanId;
22 +import org.onosproject.net.AbstractDescription;
23 +import org.onosproject.net.SparseAnnotations;
24 +
25 +import java.util.List;
26 +import java.util.Optional;
27 +
28 +/**
29 + * Default implementation of mirroring description entity.
30 + */
31 +@Beta
32 +public class DefaultMirroringDescription extends AbstractDescription
33 + implements MirroringDescription {
34 +
35 + private final MirroringName mirroringName;
36 + private final List<String> monitorSrcPorts;
37 + private final List<String> monitorDstPorts;
38 + private final List<VlanId> monitorVlans;
39 + private final Optional<String> mirrorPort;
40 + private final Optional<VlanId> mirrorVlan;
41 +
42 + /**
43 + * Creates a mirroring description using the supplied information.
44 + *
45 + * @param name the name of the mirroring
46 + * @param monitorsrcports the monitored src ports
47 + * @param monitordstports the monitored dst ports
48 + * @param monitorvlans the monitored vlans
49 + * @param mirrorport the mirror port
50 + * @param mirrorvlan the mirror vlan
51 + * @param annotations optional key/value annotations
52 + */
53 + public DefaultMirroringDescription(MirroringName name,
54 + List<String> monitorsrcports,
55 + List<String> monitordstports,
56 + List<VlanId> monitorvlans,
57 + Optional<String> mirrorport,
58 + Optional<VlanId> mirrorvlan,
59 + SparseAnnotations... annotations) {
60 + super(annotations);
61 + this.mirroringName = name;
62 + this.monitorSrcPorts = monitorsrcports;
63 + this.monitorDstPorts = monitordstports;
64 + this.monitorVlans = monitorvlans;
65 + this.mirrorPort = mirrorport;
66 + this.mirrorVlan = mirrorvlan;
67 + }
68 +
69 +
70 + /**
71 + * Returns mirroring name.
72 + *
73 + * @return mirroring name
74 + */
75 + @Override
76 + public MirroringName name() {
77 + return mirroringName;
78 + }
79 +
80 + /**
81 + * Returns src ports to monitor.
82 + * If it is empty, then no src port has
83 + * to be monitored.
84 + *
85 + * @return set of src ports to monitor
86 + */
87 + @Override
88 + public List<String> monitorSrcPorts() {
89 + return monitorSrcPorts;
90 + }
91 +
92 + /**
93 + * Returns dst ports to monitor.
94 + * If it is empty, then no dst port has
95 + * to be monitored.
96 + *
97 + * @return set of dst ports to monitor
98 + */
99 + @Override
100 + public List<String> monitorDstPorts() {
101 + return monitorDstPorts;
102 + }
103 +
104 + /**
105 + * Returns vlans to monitor.
106 + * If it is empty, then no vlan has
107 + * to be monitored.
108 + *
109 + * @return monitored vlan
110 + */
111 + @Override
112 + public List<VlanId> monitorVlans() {
113 + return monitorVlans;
114 + }
115 +
116 + /**
117 + * Returns mirror port.
118 + * If it is not set, then no destination
119 + * port for mirrored packets.
120 + *
121 + * @return mirror port
122 + */
123 + @Override
124 + public Optional<String> mirrorPort() {
125 + return mirrorPort;
126 + }
127 +
128 + /**
129 + * Returns mirror vlan.
130 + * If it is not set the no destination
131 + * vlan for mirrored packets.
132 + *
133 + * @return mirror vlan
134 + */
135 + @Override
136 + public Optional<VlanId> mirrorVlan() {
137 + return mirrorVlan;
138 + }
139 +
140 + @Override
141 + public String toString() {
142 + return MoreObjects.toStringHelper(this)
143 + .add("name", name())
144 + .add("monitorsrcports", monitorSrcPorts())
145 + .add("monitordstports", monitorDstPorts())
146 + .add("monitorvlans", monitorVlans())
147 + .add("mirrorport", mirrorPort())
148 + .add("mirrorvlan", mirrorVlan())
149 + .toString();
150 + }
151 +}
1 +/*
2 + * Copyright 2016-present Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +package org.onosproject.net.behaviour;
18 +
19 +import com.google.common.annotations.Beta;
20 +import org.onosproject.net.driver.HandlerBehaviour;
21 +
22 +import java.util.Collection;
23 +
24 +/**
25 + * Behaviour for handling various drivers for mirroring configurations.
26 + */
27 +@Beta
28 +public interface MirroringConfig extends HandlerBehaviour {
29 +
30 + /**
31 + * Adds a mirroring with a given description.
32 + *
33 + * @param bridge the bridge name
34 + * @param mirroringDescription mirroring description
35 + * @return true if succeeds, or false
36 + */
37 + boolean addMirroring(BridgeName bridge, MirroringDescription mirroringDescription);
38 +
39 + /**
40 + * Removes a mirroring.
41 + *
42 + * @param mirroringName mirroring name
43 + */
44 + void deleteMirroring(MirroringName mirroringName);
45 +
46 + /**
47 + * Returns a collection of MirroringStatistics.
48 + *
49 + * @return statistics collection
50 + */
51 + Collection<MirroringStatistics> getMirroringStatistics();
52 +
53 +}
1 +/*
2 + * Copyright 2016-present Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +package org.onosproject.net.behaviour;
18 +
19 +import com.google.common.annotations.Beta;
20 +import org.onlab.packet.VlanId;
21 +import org.onosproject.net.Annotated;
22 +import org.onosproject.net.Description;
23 +
24 +import java.util.List;
25 +import java.util.Optional;
26 +
27 +/**
28 + * The abstraction of a mirroring. Port mirroring is a method of monitoring
29 + * network traffic that forwards a copy of each incoming or outgoing packet from
30 + * one port (Monitor port) on a network switch to another port (Mirror port)
31 + * where the packet can be analyzed.
32 + */
33 +@Beta
34 +public interface MirroringDescription extends Description, Annotated {
35 +
36 + /**
37 + * Returns mirroring name.
38 + *
39 + * @return mirroring name
40 + */
41 + MirroringName name();
42 +
43 + /**
44 + * Returns src ports to monitor.
45 + * If it is empty, then no src port has
46 + * to be monitored.
47 + *
48 + * @return set of src ports to monitor
49 + */
50 + List<String> monitorSrcPorts();
51 +
52 + /**
53 + * Returns dst ports to monitor.
54 + * If it is empty, then no dst port has
55 + * to be monitored.
56 + *
57 + * @return set of dst ports to monitor
58 + */
59 + List<String> monitorDstPorts();
60 +
61 + /**
62 + * Returns vlans to monitor.
63 + * If it is empty, then no vlan has
64 + * to be monitored.
65 + *
66 + * @return monitored vlan
67 + */
68 + List<VlanId> monitorVlans();
69 +
70 + /**
71 + * Returns mirror port.
72 + * If it is not set, then no destination
73 + * port for mirrored packets.
74 + *
75 + * @return mirror port
76 + */
77 + Optional<String> mirrorPort();
78 +
79 + /**
80 + * Returns mirror vlan.
81 + * If it is not set then no destination
82 + * vlan for mirrored packets.
83 + *
84 + * @return mirror vlan
85 + */
86 + Optional<VlanId> mirrorVlan();
87 +
88 +}
1 +/*
2 + * Copyright 2016-present Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +package org.onosproject.net.behaviour;
18 +
19 +import com.google.common.base.MoreObjects;
20 +
21 +import java.util.Objects;
22 +
23 +/**
24 + * Represents for a mirroring name.
25 + */
26 +public final class MirroringName {
27 +
28 + private final String name;
29 +
30 + private MirroringName(String name) {
31 + this.name = name;
32 + }
33 +
34 + /**
35 + * Creates a mirroring name using the supplied string.
36 + *
37 + * @param name mirroring name
38 + * @return a port mirroring name
39 + */
40 + public static MirroringName mirroringName(String name) {
41 + return new MirroringName(name);
42 + }
43 +
44 + /**
45 + * Returns the mirroring name string.
46 + *
47 + * @return name string
48 + */
49 + public String name() {
50 + return name;
51 + }
52 +
53 + @Override
54 + public int hashCode() {
55 + return name.hashCode();
56 + }
57 +
58 + @Override
59 + public boolean equals(Object obj) {
60 + if (this == obj) {
61 + return true;
62 + }
63 + if (obj instanceof MirroringName) {
64 + final MirroringName that = (MirroringName) obj;
65 + return this.getClass() == that.getClass() &&
66 + Objects.equals(this.name, that.name);
67 + }
68 + return false;
69 + }
70 +
71 + @Override
72 + public String toString() {
73 + return MoreObjects.toStringHelper(getClass())
74 + .add("name", name)
75 + .toString();
76 + }
77 +
78 +}
1 +/*
2 + * Copyright 2016-present Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +package org.onosproject.net.behaviour;
18 +
19 +import com.google.common.base.MoreObjects;
20 +
21 +import java.util.Map;
22 +import java.util.Objects;
23 +
24 +/**
25 + * Represents statistics associated to a mirroring.
26 + */
27 +public final class MirroringStatistics {
28 +
29 + private MirroringName mirroringName;
30 + private int txBytes;
31 + private int txPackets;
32 +
33 + /**
34 + * Statistics associated to a named mirroring.
35 + *
36 + * @param name the name of the mirroring
37 + * @param bytes transmitted bytes
38 + * @param packets transmitted packets
39 + */
40 + private MirroringStatistics(String name, int bytes, int packets) {
41 + this.mirroringName = MirroringName.mirroringName(name);
42 + this.txBytes = bytes;
43 + this.txPackets = packets;
44 + }
45 +
46 + /**
47 + *
48 + * Creates a MirroringStatistics using the supplied information.
49 + *
50 + * @param name the name of the mirroring
51 + * @param statistics the associated statistics
52 + * @return the MirroringStatistics object
53 + */
54 + public static MirroringStatistics mirroringStatistics(String name, Map<String, Integer> statistics) {
55 + return new MirroringStatistics(name, statistics.get("tx_bytes"), statistics.get("tx_packets"));
56 + }
57 +
58 + /**
59 + * Returns the mirroring name string.
60 + *
61 + * @return name string
62 + */
63 + public MirroringName name() {
64 + return mirroringName;
65 + }
66 +
67 + /**
68 + * Returns the transmitted bytes.
69 + *
70 + * @return the bytes
71 + */
72 + public long bytes() {
73 + return txBytes;
74 + }
75 +
76 + /**
77 + * Returns the transmitted packtes.
78 + *
79 + * @return the packets
80 + */
81 + public long packtes() {
82 + return txPackets;
83 + }
84 +
85 + @Override
86 + public int hashCode() {
87 + return Objects.hash(name().name(), txBytes, txPackets);
88 + }
89 +
90 + @Override
91 + public boolean equals(Object obj) {
92 + if (this == obj) {
93 + return true;
94 + }
95 + if (obj instanceof MirroringStatistics) {
96 + final MirroringStatistics that = (MirroringStatistics) obj;
97 + return this.getClass() == that.getClass() &&
98 + Objects.equals(this.mirroringName, that.mirroringName) &&
99 + Objects.equals(this.txBytes, that.txBytes) &&
100 + Objects.equals(this.txPackets, that.txPackets);
101 + }
102 + return false;
103 + }
104 +
105 + @Override
106 + public String toString() {
107 + return MoreObjects.toStringHelper(getClass())
108 + .add("name", name())
109 + .add("tx_bytes", bytes())
110 + .add("tx_packets", packtes())
111 + .toString();
112 + }
113 +
114 +}
...@@ -28,6 +28,7 @@ import org.onosproject.net.driver.AbstractHandlerBehaviour; ...@@ -28,6 +28,7 @@ import org.onosproject.net.driver.AbstractHandlerBehaviour;
28 import org.onosproject.net.driver.DriverHandler; 28 import org.onosproject.net.driver.DriverHandler;
29 import org.onosproject.ovsdb.controller.OvsdbBridge; 29 import org.onosproject.ovsdb.controller.OvsdbBridge;
30 import org.onosproject.ovsdb.controller.OvsdbClientService; 30 import org.onosproject.ovsdb.controller.OvsdbClientService;
31 +import org.onosproject.ovsdb.controller.OvsdbConstant;
31 import org.onosproject.ovsdb.controller.OvsdbController; 32 import org.onosproject.ovsdb.controller.OvsdbController;
32 import org.onosproject.ovsdb.controller.OvsdbNodeId; 33 import org.onosproject.ovsdb.controller.OvsdbNodeId;
33 34
...@@ -83,7 +84,7 @@ public class OvsdbControllerConfig extends AbstractHandlerBehaviour implements C ...@@ -83,7 +84,7 @@ public class OvsdbControllerConfig extends AbstractHandlerBehaviour implements C
83 if (nodeIds.size() == 0) { 84 if (nodeIds.size() == 0) {
84 //TODO decide what port? 85 //TODO decide what port?
85 ovsController.connect(IpAddress.valueOf(targetIp), 86 ovsController.connect(IpAddress.valueOf(targetIp),
86 - targetPort == null ? TpPort.tpPort(6640) : targetPort); 87 + targetPort == null ? TpPort.tpPort(OvsdbConstant.OVSDBPORT) : targetPort);
87 delay(1000); //FIXME... connect is async 88 delay(1000); //FIXME... connect is async
88 } 89 }
89 List<OvsdbClientService> clientServices = ovsController.getNodeIds().stream() 90 List<OvsdbClientService> clientServices = ovsController.getNodeIds().stream()
......
1 +/*
2 + * Copyright 2016-present Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +package org.onosproject.drivers.ovsdb;
18 +
19 +import org.onlab.packet.IpAddress;
20 +import org.onlab.packet.TpPort;
21 +import org.onosproject.net.AnnotationKeys;
22 +import org.onosproject.net.DeviceId;
23 +import org.onosproject.net.behaviour.BridgeName;
24 +import org.onosproject.net.behaviour.MirroringConfig;
25 +import org.onosproject.net.behaviour.MirroringDescription;
26 +import org.onosproject.net.behaviour.MirroringStatistics;
27 +import org.onosproject.net.behaviour.MirroringName;
28 +import org.onosproject.net.device.DeviceService;
29 +import org.onosproject.net.driver.AbstractHandlerBehaviour;
30 +import org.onosproject.net.driver.DriverHandler;
31 +import org.onosproject.ovsdb.controller.OvsdbBridge;
32 +import org.onosproject.ovsdb.controller.OvsdbClientService;
33 +import org.onosproject.ovsdb.controller.OvsdbConstant;
34 +import org.onosproject.ovsdb.controller.OvsdbController;
35 +import org.onosproject.ovsdb.controller.OvsdbMirror;
36 +import org.onosproject.ovsdb.controller.OvsdbNodeId;
37 +import org.slf4j.Logger;
38 +import org.slf4j.LoggerFactory;
39 +
40 +import java.util.Collection;
41 +import java.util.List;
42 +import java.util.stream.Collectors;
43 +
44 +import static com.google.common.base.Preconditions.checkArgument;
45 +import static com.google.common.base.Preconditions.checkState;
46 +import static org.onlab.util.Tools.delay;
47 +
48 +/**
49 + * Implementation of mirror config which allows to add, delete and get mirrorings statistics.
50 + */
51 +public class OvsdbMirroringConfig extends AbstractHandlerBehaviour implements MirroringConfig {
52 +
53 + private static Logger log = LoggerFactory.getLogger(OvsdbMirroringConfig.class);
54 +
55 + /**
56 + * Adds a mirroring with a given description.
57 + *
58 + * @param bridge the bridge name
59 + * @param mirroringDescription mirroring description
60 + * @return true if succeeds, or false
61 + */
62 + @Override
63 + public boolean addMirroring(BridgeName bridge, MirroringDescription mirroringDescription) {
64 + DriverHandler handler = handler();
65 + OvsdbClientService ovsdbClient = getOvsdbClientService(handler);
66 + OvsdbMirror mirror = OvsdbMirror.builder(mirroringDescription).build();
67 + return ovsdbClient.createMirror(bridge.name(), mirror);
68 + }
69 +
70 + /**
71 + * Removes a mirroring.
72 + *
73 + * @param mirroringName mirroring name
74 + */
75 + @Override
76 + public void deleteMirroring(MirroringName mirroringName) {
77 + DriverHandler handler = handler();
78 + OvsdbClientService ovsdbClient = getOvsdbClientService(handler);
79 + ovsdbClient.dropMirror(mirroringName);
80 + }
81 +
82 + /**
83 + * Returns a collection of MirroringStatistics.
84 + *
85 + * @return statistics collection
86 + */
87 + @Override
88 + public Collection<MirroringStatistics> getMirroringStatistics() {
89 + DriverHandler handler = handler();
90 + OvsdbClientService ovsdbClient = getOvsdbClientService(handler);
91 + return ovsdbClient.getMirroringStatistics(handler.data().deviceId());
92 + }
93 +
94 + /**
95 + * Helper method which is used for getting OvsdbClientService.
96 + */
97 + private OvsdbClientService getOvsdbClientService(DriverHandler handler) {
98 +
99 + OvsdbController ovsController = handler.get(OvsdbController.class);
100 + DeviceService deviceService = handler.get(DeviceService.class);
101 + DeviceId deviceId = handler.data().deviceId();
102 +
103 + String[] splits = deviceId.toString().split(":");
104 + if (splits == null || splits.length < 1) {
105 + log.warn("Wrong deviceId format");
106 + return null;
107 + }
108 +
109 + /**
110 + * Each type of device has to be managed in a different way.
111 + */
112 + switch (splits[0]) {
113 + case "ovsdb":
114 + OvsdbNodeId nodeId = changeDeviceIdToNodeId(deviceId);
115 + return ovsController.getOvsdbClient(nodeId);
116 + case "of":
117 + String[] mgmtAddress = deviceService.getDevice(deviceId)
118 + .annotations().value(AnnotationKeys.MANAGEMENT_ADDRESS).split(":");
119 + String targetIp = mgmtAddress[0];
120 + TpPort targetPort = null;
121 + if (mgmtAddress.length > 1) {
122 + targetPort = TpPort.tpPort(Integer.parseInt(mgmtAddress[1]));
123 + }
124 + List<OvsdbNodeId> nodeIds = ovsController.getNodeIds().stream()
125 + .filter(nodeID -> nodeID.getIpAddress().equals(targetIp))
126 + .collect(Collectors.toList());
127 + if (nodeIds.size() == 0) {
128 + //TODO decide what port?
129 + ovsController.connect(IpAddress.valueOf(targetIp),
130 + targetPort == null ? TpPort.tpPort(OvsdbConstant.OVSDBPORT) : targetPort);
131 + delay(1000); //FIXME... connect is async
132 + }
133 + List<OvsdbClientService> clientServices = ovsController.getNodeIds().stream()
134 + .filter(nodeID -> nodeID.getIpAddress().equals(targetIp))
135 + .map(ovsController::getOvsdbClient)
136 + .filter(cs -> cs.getBridges().stream().anyMatch(b -> dpidMatches(b, deviceId)))
137 + .collect(Collectors.toList());
138 + checkState(clientServices.size() > 0, "No clientServices found");
139 + //FIXME add connection to management address if null --> done ?
140 + return clientServices.size() > 0 ? clientServices.get(0) : null;
141 + default:
142 + log.warn("Unmanaged device type");
143 + }
144 + return null;
145 +
146 + }
147 +
148 + private static boolean dpidMatches(OvsdbBridge bridge, DeviceId deviceId) {
149 + checkArgument(bridge.datapathId().isPresent());
150 +
151 + String bridgeDpid = "of:" + bridge.datapathId().get();
152 + String ofDpid = deviceId.toString();
153 + return bridgeDpid.equals(ofDpid);
154 + }
155 +
156 + /**
157 + * OvsdbNodeId(IP) is used in the adaptor while DeviceId(ovsdb:IP)
158 + * is used in the core. So DeviceId need be changed to OvsdbNodeId.
159 + *
160 + * @param deviceId the device id in ovsdb:ip format
161 + * @return the ovsdb node id
162 + */
163 + private OvsdbNodeId changeDeviceIdToNodeId(DeviceId deviceId) {
164 + String[] splits = deviceId.toString().split(":");
165 + if (splits == null || splits.length < 1) {
166 + return null;
167 + }
168 + IpAddress ipAddress = IpAddress.valueOf(splits[1]);
169 + return new OvsdbNodeId(ipAddress, 0);
170 + }
171 +
172 +}
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
28 manufacturer="Nicira, Inc\." hwVersion="Open vSwitch" swVersion="2\..*"> 28 manufacturer="Nicira, Inc\." hwVersion="Open vSwitch" swVersion="2\..*">
29 <behaviour api="org.onosproject.net.behaviour.ControllerConfig" 29 <behaviour api="org.onosproject.net.behaviour.ControllerConfig"
30 impl="org.onosproject.drivers.ovsdb.OvsdbControllerConfig"/> 30 impl="org.onosproject.drivers.ovsdb.OvsdbControllerConfig"/>
31 + <behaviour api="org.onosproject.net.behaviour.MirroringConfig"
32 + impl="org.onosproject.drivers.ovsdb.OvsdbMirroringConfig"/>
31 </driver> 33 </driver>
32 </drivers> 34 </drivers>
33 35
......
...@@ -19,6 +19,8 @@ import com.google.common.util.concurrent.ListenableFuture; ...@@ -19,6 +19,8 @@ import com.google.common.util.concurrent.ListenableFuture;
19 import org.onlab.packet.IpAddress; 19 import org.onlab.packet.IpAddress;
20 import org.onosproject.net.DeviceId; 20 import org.onosproject.net.DeviceId;
21 import org.onosproject.net.behaviour.ControllerInfo; 21 import org.onosproject.net.behaviour.ControllerInfo;
22 +import org.onosproject.net.behaviour.MirroringStatistics;
23 +import org.onosproject.net.behaviour.MirroringName;
22 import org.onosproject.ovsdb.rfc.jsonrpc.OvsdbRpc; 24 import org.onosproject.ovsdb.rfc.jsonrpc.OvsdbRpc;
23 import org.onosproject.ovsdb.rfc.message.TableUpdates; 25 import org.onosproject.ovsdb.rfc.message.TableUpdates;
24 import org.onosproject.ovsdb.rfc.notation.Row; 26 import org.onosproject.ovsdb.rfc.notation.Row;
...@@ -40,6 +42,41 @@ public interface OvsdbClientService extends OvsdbRpc { ...@@ -40,6 +42,41 @@ public interface OvsdbClientService extends OvsdbRpc {
40 OvsdbNodeId nodeId(); 42 OvsdbNodeId nodeId();
41 43
42 /** 44 /**
45 + * Creates a mirror port. Mirrors the traffic
46 + * that goes to selectDstPort or comes from
47 + * selectSrcPort or packets containing selectVlan
48 + * to mirrorPort or to all ports that trunk mirrorVlan.
49 + *
50 + * @param bridgeName the name of the bridge
51 + * @param mirror the OVSDB mirror description
52 + * @return true if mirror creation is successful, false otherwise
53 + */
54 + boolean createMirror(String bridgeName, OvsdbMirror mirror);
55 +
56 + /**
57 + * Gets the Mirror uuid.
58 + *
59 + * @param mirrorName mirror name
60 + * @return mirror uuid, empty if no uuid is found
61 + */
62 + String getMirrorUuid(String mirrorName);
63 +
64 + /**
65 + * Gets mirroring statistics of the device.
66 + *
67 + * @param deviceId target device id
68 + * @return set of mirroring statistics; empty if no mirror is found
69 + */
70 + Set<MirroringStatistics> getMirroringStatistics(DeviceId deviceId);
71 +
72 + /**
73 + * Drops the configuration for mirror.
74 + *
75 + * @param mirroringName
76 + */
77 + void dropMirror(MirroringName mirroringName);
78 +
79 + /**
43 * Creates a tunnel port with given options. 80 * Creates a tunnel port with given options.
44 * 81 *
45 * @deprecated version 1.7.0 - Hummingbird 82 * @deprecated version 1.7.0 - Hummingbird
......
...@@ -41,6 +41,7 @@ public final class OvsdbConstant { ...@@ -41,6 +41,7 @@ public final class OvsdbConstant {
41 /** Bridge table. */ 41 /** Bridge table. */
42 public static final String BRIDGE = "Bridge"; 42 public static final String BRIDGE = "Bridge";
43 public static final String PORTS = "ports"; 43 public static final String PORTS = "ports";
44 + public static final String MIRRORS = "mirrors";
44 // other configs 45 // other configs
45 public static final String DATAPATH_ID = "datapath-id"; 46 public static final String DATAPATH_ID = "datapath-id";
46 public static final String DISABLE_INBAND = "disable-in-band"; 47 public static final String DISABLE_INBAND = "disable-in-band";
...@@ -66,6 +67,9 @@ public final class OvsdbConstant { ...@@ -66,6 +67,9 @@ public final class OvsdbConstant {
66 /** Controller table. */ 67 /** Controller table. */
67 public static final String CONTROLLER = "Controller"; 68 public static final String CONTROLLER = "Controller";
68 69
70 + /** Mirror table. */
71 + public static final String MIRROR = "Mirror";
72 +
69 /** Ovsdb bridge name. */ 73 /** Ovsdb bridge name. */
70 // TODO remove this particular bridge name from OVSDB provider 74 // TODO remove this particular bridge name from OVSDB provider
71 public static final String INTEGRATION_BRIDGE = "br-int"; 75 public static final String INTEGRATION_BRIDGE = "br-int";
......
1 +/*
2 + * Copyright 2016-present Open Networking Laboratory
3 + *
4 + * Licensed under the Apache License, Version 2.0 (the "License");
5 + * you may not use this file except in compliance with the License.
6 + * You may obtain a copy of the License at
7 + *
8 + * http://www.apache.org/licenses/LICENSE-2.0
9 + *
10 + * Unless required by applicable law or agreed to in writing, software
11 + * distributed under the License is distributed on an "AS IS" BASIS,
12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 + * See the License for the specific language governing permissions and
14 + * limitations under the License.
15 + */
16 +
17 +package org.onosproject.ovsdb.controller;
18 +
19 +import com.google.common.collect.Maps;
20 +import org.onosproject.net.DefaultAnnotations;
21 +import org.onosproject.net.behaviour.MirroringDescription;
22 +import org.onosproject.ovsdb.rfc.notation.Uuid;
23 +
24 +import java.util.Map;
25 +import java.util.Objects;
26 +import java.util.Optional;
27 +import java.util.Set;
28 +import java.util.stream.Collectors;
29 +
30 +import static com.google.common.base.MoreObjects.toStringHelper;
31 +
32 +/**
33 + * The class representing an OVSDB mirror.
34 + * This class is immutable.
35 + */
36 +public final class OvsdbMirror {
37 +
38 + private final String mirroringName;
39 + private boolean selectAll;
40 + private final Set<Uuid> monitorSrcPorts;
41 + private final Set<Uuid> monitorDstPorts;
42 + private final Set<Short> monitorVlans;
43 + private final Optional<Uuid> mirrorPort;
44 + private final Optional<Short> mirrorVlan;
45 + private Map<String, String> externalIds;
46 +
47 + /**
48 + * Creates an OvsdbMirror using the given inputs.
49 + *
50 + * @param mirroringName the name of the mirroring
51 + * @param selectAll mirrors all ports
52 + * @param monitorSrcPorts the monitored src ports
53 + * @param monitorDstPorts the monitored dst ports
54 + * @param monitorVlans the monitored vlans
55 + * @param mirrorPort the mirror port
56 + * @param mirrorVlan the mirror vlan
57 + * @param externalIds optional key/value options
58 + */
59 + private OvsdbMirror(String mirroringName, boolean selectAll, Set<Uuid> monitorSrcPorts, Set<Uuid> monitorDstPorts,
60 + Set<Short> monitorVlans, Optional<Uuid> mirrorPort, Optional<Short> mirrorVlan,
61 + Map<String, String> externalIds) {
62 +
63 + this.mirroringName = mirroringName;
64 + this.selectAll = selectAll;
65 + this.monitorSrcPorts = monitorSrcPorts;
66 + this.monitorDstPorts = monitorDstPorts;
67 + this.monitorVlans = monitorVlans;
68 + this.mirrorPort = mirrorPort;
69 + this.mirrorVlan = mirrorVlan;
70 + this.externalIds = externalIds;
71 +
72 + }
73 +
74 + /**
75 + * Returns the name of the mirroring.
76 + *
77 + * @return the string representing the name
78 + */
79 + public String mirroringName() {
80 + return mirroringName;
81 + }
82 +
83 + /**
84 + * Returns selectAll value.
85 + *
86 + * @return mirrors all ports if true
87 + */
88 + public boolean selectAll() {
89 + return selectAll;
90 + }
91 +
92 + /**
93 + * Returns the monitored src ports.
94 + *
95 + * @return the uuids set of the ports
96 + */
97 + public Set<Uuid> monitorSrcPorts() {
98 + return monitorSrcPorts;
99 + }
100 +
101 + /**
102 + * Returns the monitored dst ports.
103 + *
104 + * @return the uuids set of the ports
105 + */
106 + public Set<Uuid> monitorDstPorts() {
107 + return monitorDstPorts;
108 + }
109 +
110 + /**
111 + * Returns the monitored vlans.
112 + *
113 + * @return the vlans set
114 + */
115 + public Set<Short> monitorVlans() {
116 + return monitorVlans;
117 + }
118 +
119 + /**
120 + * Returns the mirror port.
121 + *
122 + * @return the uuid port if present, otherwise null
123 + */
124 + public Uuid mirrorPort() {
125 + return mirrorPort.orElse(null);
126 + }
127 +
128 + /**
129 + * Returns the mirror vlan.
130 + *
131 + * @return the vlan id if present, otherwise null
132 + */
133 + public Short mirrorVlan() {
134 + return mirrorVlan.orElse(null);
135 + }
136 +
137 + /**
138 + * Returns the optional external ids.
139 + *
140 + * @return the external ids.
141 + */
142 + public Map<String, String> externalIds() {
143 + return externalIds;
144 + }
145 +
146 + @Override
147 + public int hashCode() {
148 + return Objects.hash(mirroringName, selectAll, monitorSrcPorts, monitorDstPorts,
149 + monitorVlans, mirrorPort, mirrorVlan, externalIds);
150 + }
151 +
152 + @Override
153 + public boolean equals(Object obj) {
154 + if (this == obj) {
155 + return true;
156 + }
157 + if (obj instanceof OvsdbMirror) {
158 + final OvsdbMirror other = (OvsdbMirror) obj;
159 + return Objects.equals(this.mirroringName, other.mirroringName) &&
160 + Objects.equals(this.selectAll, other.selectAll) &&
161 + Objects.equals(this.monitorSrcPorts, other.monitorSrcPorts) &&
162 + Objects.equals(this.monitorDstPorts, other.monitorDstPorts) &&
163 + Objects.equals(this.monitorVlans, other.monitorVlans) &&
164 + Objects.equals(this.mirrorPort, other.mirrorPort) &&
165 + Objects.equals(this.mirrorVlan, other.mirrorVlan) &&
166 + Objects.equals(this.externalIds, other.externalIds);
167 + }
168 + return false;
169 + }
170 +
171 + @Override
172 + public String toString() {
173 + return toStringHelper(this)
174 + .add("mirroringName", mirroringName())
175 + .add("selectAll", selectAll())
176 + .add("monitorSrcPorts", monitorSrcPorts())
177 + .add("monitorDstPorts", monitorDstPorts())
178 + .add("monitorVlans", monitorVlans())
179 + .add("mirrorPort", mirrorPort())
180 + .add("mirrorVlan", mirrorVlan())
181 + .add("externalIds", externalIds())
182 + .toString();
183 + }
184 +
185 + /**
186 + * Returns new OVSDB mirror builder.
187 + *
188 + * @return ovsdb mirror builder
189 + */
190 + public static OvsdbMirror.Builder builder() {
191 + return new OvsdbMirror.Builder();
192 + }
193 +
194 + /**
195 + * Returns new OVSDB mirror builder with mirror description.
196 + *
197 + * @param mirrorDesc mirror description
198 + * @return ovsdb mirror builder
199 + */
200 + public static OvsdbMirror.Builder builder(MirroringDescription mirrorDesc) {
201 + return new OvsdbMirror.Builder(mirrorDesc);
202 + }
203 +
204 + /**
205 + * Builder of OVSDB mirror entities.
206 + */
207 + public static final class Builder {
208 +
209 + private String mirroringName;
210 + private boolean selectAll;
211 + private Set<Uuid> monitorSrcPorts;
212 + private Set<Uuid> monitorDstPorts;
213 + private Set<Short> monitorVlans;
214 + private Optional<Uuid> mirrorPort;
215 + private Optional<Short> mirrorVlan;
216 + private Map<String, String> externalIds = Maps.newHashMap();
217 +
218 + /**
219 + * Constructs an empty builder.
220 + */
221 + private Builder() {
222 +
223 + }
224 +
225 + /**
226 + * Constructs a builder with a given mirror description.
227 + *
228 + * @param mirrorDesc mirror description
229 + */
230 + private Builder(MirroringDescription mirrorDesc) {
231 +
232 + mirroringName = mirrorDesc.name().name();
233 + selectAll = false;
234 + monitorSrcPorts = mirrorDesc.monitorSrcPorts().parallelStream()
235 + .map(monitorSrcPort -> Uuid.uuid(monitorSrcPort))
236 + .collect(Collectors.toSet());
237 + monitorDstPorts = mirrorDesc.monitorDstPorts().parallelStream()
238 + .map(monitorDstPort -> Uuid.uuid(monitorDstPort))
239 + .collect(Collectors.toSet());
240 + monitorVlans = mirrorDesc.monitorVlans().parallelStream()
241 + .map(monitorVlan -> monitorVlan.toShort())
242 + .collect(Collectors.toSet());
243 +
244 + if (mirrorDesc.mirrorPort().isPresent()) {
245 + mirrorPort = Optional.of(Uuid.uuid(mirrorDesc.mirrorPort().get()));
246 + } else {
247 + mirrorPort = Optional.empty();
248 + }
249 +
250 + if (mirrorDesc.mirrorVlan().isPresent()) {
251 + mirrorVlan = Optional.of(mirrorDesc.mirrorVlan().get().toShort());
252 + } else {
253 + mirrorVlan = Optional.empty();
254 + }
255 +
256 + externalIds.putAll(((DefaultAnnotations) mirrorDesc.annotations()).asMap());
257 +
258 + }
259 +
260 + /**
261 + * Returns new OVSDB mirror.
262 + *
263 + * @return ovsdb mirror
264 + */
265 + public OvsdbMirror build() {
266 + return new OvsdbMirror(mirroringName, selectAll, monitorSrcPorts, monitorDstPorts, monitorVlans,
267 + mirrorPort, mirrorVlan, externalIds);
268 + }
269 +
270 + /**
271 + * Returns OVSDB mirror builder with a given name.
272 + *
273 + * @param name name of the mirror
274 + * @return ovsdb interface builder
275 + */
276 + public OvsdbMirror.Builder mirroringName(String name) {
277 + this.mirroringName = name;
278 + return this;
279 + }
280 +
281 + /**
282 + * Returns OVSDB mirror builder with select all.
283 + *
284 + * @param all mirrors all ports
285 + * @return ovsdb interface builder
286 + */
287 + public OvsdbMirror.Builder selectAll(boolean all) {
288 + this.selectAll = all;
289 + return this;
290 + }
291 +
292 + /**
293 + * Returns OVSDB mirror builder with a given set
294 + * of monitored src ports.
295 + *
296 + * @param monitorPorts ports to be monitored
297 + * @return ovsdb mirror builder
298 + */
299 + public OvsdbMirror.Builder monitorSrcPorts(Set<Uuid> monitorPorts) {
300 + this.monitorSrcPorts = monitorPorts;
301 + return this;
302 + }
303 +
304 + /**
305 + * Returns OVSDB mirror builder with a given set
306 + * of monitored dst ports.
307 + *
308 + * @param monitorPorts ports to be monitored
309 + * @return ovsdb mirror builder
310 + */
311 + public OvsdbMirror.Builder monitorDstPorts(Set<Uuid> monitorPorts) {
312 + this.monitorDstPorts = monitorPorts;
313 + return this;
314 + }
315 +
316 + /**
317 + * Returns OVSDB mirror builder with a given set
318 + * of monitored vlans.
319 + *
320 + * @param vlans vlans to be monitored
321 + * @return ovsdb mirror builder
322 + */
323 + public OvsdbMirror.Builder monitorVlans(Set<Short> vlans) {
324 + this.monitorVlans = vlans;
325 + return this;
326 + }
327 +
328 + /**
329 + * Returns OVSDB mirror builder with a given mirror port.
330 + *
331 + * @param port the mirror port
332 + * @return ovsdb mirror builder
333 + */
334 + public OvsdbMirror.Builder mirrorPort(Uuid port) {
335 + this.mirrorPort = Optional.ofNullable(port);
336 + return this;
337 + }
338 +
339 + /**
340 + * Returns OVSDB mirror builder with a given mirror vlan.
341 + *
342 + * @param vlan the mirror vlan
343 + * @return ovsdb mirror builder
344 + */
345 + public OvsdbMirror.Builder mirrorVlan(Short vlan) {
346 + this.mirrorVlan = Optional.ofNullable(vlan);
347 + return this;
348 + }
349 +
350 + /**
351 + * Returns OVSDB mirror builder with given external ids.
352 + *
353 + * @param ids the external ids
354 + * @return ovsdb mirror builder
355 + */
356 + public OvsdbMirror.Builder externalIds(Map<String, String> ids) {
357 + this.externalIds = ids;
358 + return this;
359 + }
360 +
361 + }
362 +
363 +}
...@@ -17,6 +17,8 @@ package org.onosproject.ovsdb.controller.driver; ...@@ -17,6 +17,8 @@ package org.onosproject.ovsdb.controller.driver;
17 17
18 import com.fasterxml.jackson.databind.JsonNode; 18 import com.fasterxml.jackson.databind.JsonNode;
19 import com.google.common.base.Function; 19 import com.google.common.base.Function;
20 +import com.google.common.collect.ImmutableList;
21 +import com.google.common.collect.ImmutableSet;
20 import com.google.common.collect.Lists; 22 import com.google.common.collect.Lists;
21 import com.google.common.collect.Maps; 23 import com.google.common.collect.Maps;
22 import com.google.common.collect.Sets; 24 import com.google.common.collect.Sets;
...@@ -30,10 +32,13 @@ import org.onlab.packet.IpAddress; ...@@ -30,10 +32,13 @@ import org.onlab.packet.IpAddress;
30 import org.onosproject.net.DeviceId; 32 import org.onosproject.net.DeviceId;
31 import org.onosproject.net.behaviour.BridgeDescription; 33 import org.onosproject.net.behaviour.BridgeDescription;
32 import org.onosproject.net.behaviour.ControllerInfo; 34 import org.onosproject.net.behaviour.ControllerInfo;
35 +import org.onosproject.net.behaviour.MirroringStatistics;
36 +import org.onosproject.net.behaviour.MirroringName;
33 import org.onosproject.ovsdb.controller.OvsdbBridge; 37 import org.onosproject.ovsdb.controller.OvsdbBridge;
34 import org.onosproject.ovsdb.controller.OvsdbClientService; 38 import org.onosproject.ovsdb.controller.OvsdbClientService;
35 import org.onosproject.ovsdb.controller.OvsdbInterface; 39 import org.onosproject.ovsdb.controller.OvsdbInterface;
36 import org.onosproject.ovsdb.controller.OvsdbInterface.Type; 40 import org.onosproject.ovsdb.controller.OvsdbInterface.Type;
41 +import org.onosproject.ovsdb.controller.OvsdbMirror;
37 import org.onosproject.ovsdb.controller.OvsdbNodeId; 42 import org.onosproject.ovsdb.controller.OvsdbNodeId;
38 import org.onosproject.ovsdb.controller.OvsdbPort; 43 import org.onosproject.ovsdb.controller.OvsdbPort;
39 import org.onosproject.ovsdb.controller.OvsdbPortName; 44 import org.onosproject.ovsdb.controller.OvsdbPortName;
...@@ -41,6 +46,7 @@ import org.onosproject.ovsdb.controller.OvsdbPortNumber; ...@@ -41,6 +46,7 @@ import org.onosproject.ovsdb.controller.OvsdbPortNumber;
41 import org.onosproject.ovsdb.controller.OvsdbRowStore; 46 import org.onosproject.ovsdb.controller.OvsdbRowStore;
42 import org.onosproject.ovsdb.controller.OvsdbStore; 47 import org.onosproject.ovsdb.controller.OvsdbStore;
43 import org.onosproject.ovsdb.controller.OvsdbTableStore; 48 import org.onosproject.ovsdb.controller.OvsdbTableStore;
49 +
44 import org.onosproject.ovsdb.rfc.jsonrpc.Callback; 50 import org.onosproject.ovsdb.rfc.jsonrpc.Callback;
45 import org.onosproject.ovsdb.rfc.message.OperationResult; 51 import org.onosproject.ovsdb.rfc.message.OperationResult;
46 import org.onosproject.ovsdb.rfc.message.TableUpdates; 52 import org.onosproject.ovsdb.rfc.message.TableUpdates;
...@@ -61,6 +67,7 @@ import org.onosproject.ovsdb.rfc.schema.TableSchema; ...@@ -61,6 +67,7 @@ import org.onosproject.ovsdb.rfc.schema.TableSchema;
61 import org.onosproject.ovsdb.rfc.table.Bridge; 67 import org.onosproject.ovsdb.rfc.table.Bridge;
62 import org.onosproject.ovsdb.rfc.table.Controller; 68 import org.onosproject.ovsdb.rfc.table.Controller;
63 import org.onosproject.ovsdb.rfc.table.Interface; 69 import org.onosproject.ovsdb.rfc.table.Interface;
70 +import org.onosproject.ovsdb.rfc.table.Mirror;
64 import org.onosproject.ovsdb.rfc.table.OvsdbTable; 71 import org.onosproject.ovsdb.rfc.table.OvsdbTable;
65 import org.onosproject.ovsdb.rfc.table.Port; 72 import org.onosproject.ovsdb.rfc.table.Port;
66 import org.onosproject.ovsdb.rfc.table.TableGenerator; 73 import org.onosproject.ovsdb.rfc.table.TableGenerator;
...@@ -73,10 +80,12 @@ import org.slf4j.LoggerFactory; ...@@ -73,10 +80,12 @@ import org.slf4j.LoggerFactory;
73 80
74 import java.net.InetSocketAddress; 81 import java.net.InetSocketAddress;
75 import java.util.ArrayList; 82 import java.util.ArrayList;
83 +
76 import java.util.HashSet; 84 import java.util.HashSet;
77 import java.util.Iterator; 85 import java.util.Iterator;
78 import java.util.List; 86 import java.util.List;
79 import java.util.Map; 87 import java.util.Map;
88 +import java.util.Objects;
80 import java.util.Optional; 89 import java.util.Optional;
81 import java.util.Set; 90 import java.util.Set;
82 import java.util.concurrent.ConcurrentMap; 91 import java.util.concurrent.ConcurrentMap;
...@@ -104,6 +113,7 @@ public class DefaultOvsdbClient implements OvsdbProviderService, OvsdbClientServ ...@@ -104,6 +113,7 @@ public class DefaultOvsdbClient implements OvsdbProviderService, OvsdbClientServ
104 private final Map<String, SettableFuture<? extends Object>> requestResult = Maps.newHashMap(); 113 private final Map<String, SettableFuture<? extends Object>> requestResult = Maps.newHashMap();
105 private final Map<String, DatabaseSchema> schema = Maps.newHashMap(); 114 private final Map<String, DatabaseSchema> schema = Maps.newHashMap();
106 115
116 +
107 /** 117 /**
108 * Creates an OvsdbClient. 118 * Creates an OvsdbClient.
109 * 119 *
...@@ -234,6 +244,107 @@ public class DefaultOvsdbClient implements OvsdbProviderService, OvsdbClientServ ...@@ -234,6 +244,107 @@ public class DefaultOvsdbClient implements OvsdbProviderService, OvsdbClientServ
234 ovsdbStore.createOrUpdateOvsdbStore(dbName, tableStore); 244 ovsdbStore.createOrUpdateOvsdbStore(dbName, tableStore);
235 } 245 }
236 246
247 + /**
248 + * Gets the Mirror uuid.
249 + *
250 + * @param mirrorName mirror name
251 + * @return mirror uuid, empty if no uuid is found
252 + */
253 + @Override
254 + public String getMirrorUuid(String mirrorName) {
255 + DatabaseSchema dbSchema = schema.get(DATABASENAME);
256 + OvsdbRowStore rowStore = getRowStore(DATABASENAME, MIRROR);
257 + if (rowStore == null) {
258 + log.warn("The mirror uuid is null");
259 + return null;
260 + }
261 +
262 + ConcurrentMap<String, Row> mirrorTableRows = rowStore.getRowStore();
263 + if (mirrorTableRows == null) {
264 + log.warn("The mirror uuid is null");
265 + return null;
266 + }
267 +
268 + for (String uuid : mirrorTableRows.keySet()) {
269 + Mirror mirror = (Mirror) TableGenerator
270 + .getTable(dbSchema, mirrorTableRows.get(uuid), OvsdbTable.MIRROR);
271 + String name = mirror.getName();
272 + if (name.contains(mirrorName)) {
273 + return uuid;
274 + }
275 + }
276 + log.warn("Mirroring not found");
277 + return null;
278 + }
279 +
280 + /**
281 + * Gets mirrors of the device.
282 + *
283 + * @param deviceId target device id
284 + * @return set of mirroring; empty if no mirror is found
285 + */
286 + @Override
287 + public Set<MirroringStatistics> getMirroringStatistics(DeviceId deviceId) {
288 + Uuid bridgeUuid = getBridgeUuid(deviceId);
289 + if (bridgeUuid == null) {
290 + log.warn("Couldn't find bridge {} in {}", deviceId, nodeId.getIpAddress());
291 + return null;
292 + }
293 +
294 + List<MirroringStatistics> mirrorings = getMirrorings(bridgeUuid);
295 + if (mirrorings == null) {
296 + log.warn("Couldn't find mirrors in {}", nodeId.getIpAddress());
297 + return null;
298 + }
299 + return ImmutableSet.copyOf(mirrorings);
300 + }
301 +
302 + /**
303 + * Helper method which retrieves mirrorings statistics using bridge uuid.
304 + *
305 + * @param bridgeUuid the uuid of the bridge
306 + * @return the list of the mirrorings statistics.
307 + */
308 + private List<MirroringStatistics> getMirrorings(Uuid bridgeUuid) {
309 + DatabaseSchema dbSchema = schema.get(DATABASENAME);
310 + if (dbSchema == null) {
311 + log.warn("Unable to retrieve dbSchema {}", DATABASENAME);
312 + return null;
313 + }
314 + OvsdbRowStore rowStore = getRowStore(DATABASENAME, BRIDGE);
315 + if (rowStore == null) {
316 + log.warn("Unable to retrieve rowStore {} of {}", BRIDGE, DATABASENAME);
317 + return null;
318 + }
319 +
320 + Row bridgeRow = rowStore.getRow(bridgeUuid.value());
321 + Bridge bridge = (Bridge) TableGenerator.
322 + getTable(dbSchema, bridgeRow, OvsdbTable.BRIDGE);
323 +
324 + Set<Uuid> mirroringsUuids = (Set<Uuid>) ((OvsdbSet) bridge
325 + .getMirrorsColumn().data()).set();
326 +
327 + OvsdbRowStore mirrorRowStore = getRowStore(DATABASENAME, MIRROR);
328 + if (mirrorRowStore == null) {
329 + log.warn("Unable to retrieve rowStore {} of {}", MIRROR, DATABASENAME);
330 + return null;
331 + }
332 +
333 + List<MirroringStatistics> mirroringStatistics = new ArrayList<>();
334 + ConcurrentMap<String, Row> mirrorTableRows = mirrorRowStore.getRowStore();
335 + mirrorTableRows.forEach((key, row) -> {
336 + if (!mirroringsUuids.contains(Uuid.uuid(key))) {
337 + return;
338 + }
339 + Mirror mirror = (Mirror) TableGenerator
340 + .getTable(dbSchema, row, OvsdbTable.MIRROR);
341 + mirroringStatistics.add(MirroringStatistics.mirroringStatistics(mirror.getName(),
342 + (Map<String, Integer>) ((OvsdbMap) mirror
343 + .getStatisticsColumn().data()).map()));
344 + });
345 + return ImmutableList.copyOf(mirroringStatistics);
346 + }
347 +
237 @Override 348 @Override
238 public String getPortUuid(String portName, String bridgeUuid) { 349 public String getPortUuid(String portName, String bridgeUuid) {
239 DatabaseSchema dbSchema = schema.get(DATABASENAME); 350 DatabaseSchema dbSchema = schema.get(DATABASENAME);
...@@ -502,6 +613,142 @@ public class DefaultOvsdbClient implements OvsdbProviderService, OvsdbClientServ ...@@ -502,6 +613,142 @@ public class DefaultOvsdbClient implements OvsdbProviderService, OvsdbClientServ
502 deleteConfig(BRIDGE, UUID, bridgeUuid, DATABASENAME, BRIDGES); 613 deleteConfig(BRIDGE, UUID, bridgeUuid, DATABASENAME, BRIDGES);
503 } 614 }
504 615
616 + /**
617 + * Creates a mirror port. Mirrors the traffic
618 + * that goes to selectDstPort or comes from
619 + * selectSrcPort or packets containing selectVlan
620 + * to mirrorPort or to all ports that trunk mirrorVlan.
621 + *
622 + * @param mirror the OVSDB mirror description
623 + * @return true if mirror creation is successful, false otherwise
624 + */
625 + @Override
626 + public boolean createMirror(String bridgeName, OvsdbMirror mirror) {
627 +
628 + /**
629 + * Retrieves bridge's uuid. It is necessary to update
630 + * Bridge table.
631 + */
632 + String bridgeUuid = getBridgeUuid(bridgeName);
633 + if (bridgeUuid == null) {
634 + log.warn("Couldn't find bridge {} in {}", bridgeName, nodeId.getIpAddress());
635 + return false;
636 + }
637 +
638 + OvsdbMirror.Builder mirrorBuilder = OvsdbMirror.builder();
639 +
640 + mirrorBuilder.mirroringName(mirror.mirroringName());
641 + mirrorBuilder.selectAll(mirror.selectAll());
642 +
643 + /**
644 + * Retrieves the uuid of the monitored dst ports.
645 + */
646 + mirrorBuilder.monitorDstPorts(mirror.monitorDstPorts().parallelStream()
647 + .map(dstPort -> {
648 + String dstPortUuid = getPortUuid(dstPort.value(), bridgeUuid);
649 + if (dstPortUuid != null) {
650 + return Uuid.uuid(dstPortUuid);
651 + }
652 + log.warn("Couldn't find port {} in {}",
653 + dstPort.value(), nodeId.getIpAddress());
654 + return null;
655 + })
656 + .filter(Objects::nonNull)
657 + .collect(Collectors.toSet())
658 + );
659 +
660 + /**
661 + * Retrieves the uuid of the monitored src ports.
662 + */
663 + mirrorBuilder.monitorSrcPorts(mirror.monitorSrcPorts().parallelStream()
664 + .map(srcPort -> {
665 + String srcPortUuid = getPortUuid(srcPort.value(), bridgeUuid);
666 + if (srcPortUuid != null) {
667 + return Uuid.uuid(srcPortUuid);
668 + }
669 + log.warn("Couldn't find port {} in {}",
670 + srcPort.value(), nodeId.getIpAddress());
671 + return null;
672 + }).filter(Objects::nonNull)
673 + .collect(Collectors.toSet())
674 + );
675 +
676 + mirrorBuilder.monitorVlans(mirror.monitorVlans());
677 + mirrorBuilder.mirrorPort(mirror.mirrorPort());
678 + mirrorBuilder.mirrorVlan(mirror.mirrorVlan());
679 + mirrorBuilder.externalIds(mirror.externalIds());
680 + mirror = mirrorBuilder.build();
681 +
682 + if (mirror.monitorDstPorts().size() == 0 &&
683 + mirror.monitorSrcPorts().size() == 0 &&
684 + mirror.monitorVlans().size() == 0) {
685 + log.warn("Invalid monitoring data");
686 + return false;
687 + }
688 +
689 + DatabaseSchema dbSchema = schema.get(DATABASENAME);
690 +
691 + Mirror mirrorEntry = (Mirror) TableGenerator.createTable(dbSchema, OvsdbTable.MIRROR);
692 + mirrorEntry.setName(mirror.mirroringName());
693 + mirrorEntry.setSelectDstPort(mirror.monitorDstPorts());
694 + mirrorEntry.setSelectSrcPort(mirror.monitorSrcPorts());
695 + mirrorEntry.setSelectVlan(mirror.monitorVlans());
696 + mirrorEntry.setExternalIds(mirror.externalIds());
697 +
698 + /**
699 + * If mirror port, retrieves the uuid of the mirror port.
700 + */
701 + if (mirror.mirrorPort() != null) {
702 +
703 + String outputPortUuid = getPortUuid(mirror.mirrorPort().value(), bridgeUuid);
704 + if (outputPortUuid == null) {
705 + log.warn("Couldn't find port {} in {}", mirror.mirrorPort().value(), nodeId.getIpAddress());
706 + return false;
707 + }
708 +
709 + mirrorEntry.setOutputPort(Uuid.uuid(outputPortUuid));
710 +
711 + } else if (mirror.mirrorVlan() != null) {
712 +
713 + mirrorEntry.setOutputVlan(mirror.mirrorVlan());
714 +
715 + } else {
716 + log.warn("Invalid mirror, no mirror port and no mirror vlan");
717 + return false;
718 + }
719 +
720 + ArrayList<Operation> operations = Lists.newArrayList();
721 + Insert mirrorInsert = new Insert(dbSchema.getTableSchema("Mirror"), "Mirror", mirrorEntry.getRow());
722 + operations.add(mirrorInsert);
723 +
724 + // update the bridge table
725 + Condition condition = ConditionUtil.isEqual(UUID, Uuid.uuid(bridgeUuid));
726 + Mutation mutation = MutationUtil.insert(MIRRORS, Uuid.uuid("Mirror"));
727 + List<Condition> conditions = Lists.newArrayList(condition);
728 + List<Mutation> mutations = Lists.newArrayList(mutation);
729 + operations.add(new Mutate(dbSchema.getTableSchema("Bridge"), conditions, mutations));
730 +
731 + transactConfig(DATABASENAME, operations);
732 + log.info("Created mirror {}", mirror.mirroringName());
733 + return true;
734 + }
735 +
736 + /**
737 + * Drops the configuration for mirror.
738 + *
739 + * @param mirroringName
740 + */
741 + @Override
742 + public void dropMirror(MirroringName mirroringName) {
743 + String mirrorUuid = getMirrorUuid(mirroringName.name());
744 + if (mirrorUuid != null) {
745 + log.info("Deleted mirror {}", mirroringName.name());
746 + deleteConfig(MIRROR, UUID, mirrorUuid, BRIDGE, MIRRORS);
747 + }
748 + log.warn("Unable to delete {}", mirroringName.name());
749 + return;
750 + }
751 +
505 @Deprecated 752 @Deprecated
506 @Override 753 @Override
507 public boolean createTunnel(String bridgeName, String ifaceName, String tunnelType, 754 public boolean createTunnel(String bridgeName, String ifaceName, String tunnelType,
......
...@@ -22,9 +22,12 @@ import com.google.common.util.concurrent.ListenableFuture; ...@@ -22,9 +22,12 @@ import com.google.common.util.concurrent.ListenableFuture;
22 import org.onlab.packet.IpAddress; 22 import org.onlab.packet.IpAddress;
23 import org.onosproject.net.DeviceId; 23 import org.onosproject.net.DeviceId;
24 import org.onosproject.net.behaviour.ControllerInfo; 24 import org.onosproject.net.behaviour.ControllerInfo;
25 +import org.onosproject.net.behaviour.MirroringStatistics;
26 +import org.onosproject.net.behaviour.MirroringName;
25 import org.onosproject.ovsdb.controller.OvsdbBridge; 27 import org.onosproject.ovsdb.controller.OvsdbBridge;
26 import org.onosproject.ovsdb.controller.OvsdbClientService; 28 import org.onosproject.ovsdb.controller.OvsdbClientService;
27 import org.onosproject.ovsdb.controller.OvsdbInterface; 29 import org.onosproject.ovsdb.controller.OvsdbInterface;
30 +import org.onosproject.ovsdb.controller.OvsdbMirror;
28 import org.onosproject.ovsdb.controller.OvsdbNodeId; 31 import org.onosproject.ovsdb.controller.OvsdbNodeId;
29 import org.onosproject.ovsdb.controller.OvsdbPort; 32 import org.onosproject.ovsdb.controller.OvsdbPort;
30 import org.onosproject.ovsdb.rfc.message.TableUpdates; 33 import org.onosproject.ovsdb.rfc.message.TableUpdates;
...@@ -46,6 +49,54 @@ public class OvsdbClientServiceAdapter implements OvsdbClientService { ...@@ -46,6 +49,54 @@ public class OvsdbClientServiceAdapter implements OvsdbClientService {
46 return null; 49 return null;
47 } 50 }
48 51
52 + /**
53 + * Creates a mirror port. Mirrors the traffic
54 + * that goes to selectDstPort or comes from
55 + * selectSrcPort or packets containing selectVlan
56 + * to mirrorPort or to all ports that trunk mirrorVlan.
57 + *
58 + * @param bridgeName the name of the bridge
59 + * @param mirror the OVSDB mirror description
60 + * @return true if mirror creation is successful, false otherwise
61 + */
62 + @Override
63 + public boolean createMirror(String bridgeName, OvsdbMirror mirror) {
64 + return true;
65 + }
66 +
67 + /**
68 + * Gets the Mirror uuid.
69 + *
70 + * @param mirrorName mirror name
71 + * @return mirror uuid, empty if no uuid is found
72 + */
73 + @Override
74 + public String getMirrorUuid(String mirrorName) {
75 + return null;
76 + }
77 +
78 + /**
79 + * Gets mirroring statistics of the device.
80 + *
81 + * @param deviceId target device id
82 + * @return set of mirroring statistics; empty if no mirror is found
83 + */
84 + @Override
85 + public Set<MirroringStatistics> getMirroringStatistics(DeviceId deviceId) {
86 + return null;
87 + }
88 +
89 +
90 + /**
91 + * Drops the configuration for mirror.
92 + *
93 + * @param mirroringName
94 + */
95 + @Override
96 + public void dropMirror(MirroringName mirroringName) {
97 +
98 + }
99 +
49 @Override 100 @Override
50 public boolean createTunnel(String bridgeName, String portName, String tunnelType, Map<String, String> options) { 101 public boolean createTunnel(String bridgeName, String portName, String tunnelType, Map<String, String> options) {
51 return true; 102 return true;
......
...@@ -203,7 +203,7 @@ public class Mirror extends AbstractOvsdbTableService { ...@@ -203,7 +203,7 @@ public class Mirror extends AbstractOvsdbTableService {
203 * of attributes. 203 * of attributes.
204 * @param outputVlan the column data which column name is "output_vlan" 204 * @param outputVlan the column data which column name is "output_vlan"
205 */ 205 */
206 - public void setOutputVlan(Set<Short> outputVlan) { 206 + public void setOutputVlan(Short outputVlan) {
207 ColumnDescription columndesc = new ColumnDescription(MirrorColumn.OUTPUTVLAN.columnName(), 207 ColumnDescription columndesc = new ColumnDescription(MirrorColumn.OUTPUTVLAN.columnName(),
208 "setOutputVlan", VersionNum.VERSION100); 208 "setOutputVlan", VersionNum.VERSION100);
209 super.setDataHandler(columndesc, outputVlan); 209 super.setDataHandler(columndesc, outputVlan);
......