blob: 9a1896eb3cbeb604b6c44d8bdea14b1c7016711a [file] [log] [blame]
Pier Ventref5d72362016-07-17 12:02:14 +02001/*
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
17package org.onosproject.drivers.ovsdb;
18
19import org.onlab.packet.IpAddress;
20import org.onlab.packet.TpPort;
21import org.onosproject.net.AnnotationKeys;
22import org.onosproject.net.DeviceId;
23import org.onosproject.net.behaviour.BridgeName;
24import org.onosproject.net.behaviour.MirroringConfig;
25import org.onosproject.net.behaviour.MirroringDescription;
26import org.onosproject.net.behaviour.MirroringStatistics;
27import org.onosproject.net.behaviour.MirroringName;
28import org.onosproject.net.device.DeviceService;
29import org.onosproject.net.driver.AbstractHandlerBehaviour;
30import org.onosproject.net.driver.DriverHandler;
31import org.onosproject.ovsdb.controller.OvsdbBridge;
32import org.onosproject.ovsdb.controller.OvsdbClientService;
33import org.onosproject.ovsdb.controller.OvsdbConstant;
34import org.onosproject.ovsdb.controller.OvsdbController;
35import org.onosproject.ovsdb.controller.OvsdbMirror;
36import org.onosproject.ovsdb.controller.OvsdbNodeId;
37import org.slf4j.Logger;
38import org.slf4j.LoggerFactory;
39
40import java.util.Collection;
41import java.util.List;
42import java.util.stream.Collectors;
43
44import static com.google.common.base.Preconditions.checkArgument;
45import static com.google.common.base.Preconditions.checkState;
46import static org.onlab.util.Tools.delay;
47
48/**
49 * Implementation of mirror config which allows to add, delete and get mirrorings statistics.
50 */
51public 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}